TCG README fixes (Stuart Brady)
[qemu/malc.git] / target-sh4 / op_helper.c
blobc1bc4e8942d0071b162549c20d8104f7b459af7b
1 /*
2 * SH4 emulation
4 * Copyright (c) 2005 Samuel Tardieu
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <assert.h>
21 #include "exec.h"
23 void do_raise_exception(void)
25 cpu_loop_exit();
28 #ifndef CONFIG_USER_ONLY
30 #define MMUSUFFIX _mmu
31 #ifdef __s390__
32 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
33 #else
34 # define GETPC() (__builtin_return_address(0))
35 #endif
37 #define SHIFT 0
38 #include "softmmu_template.h"
40 #define SHIFT 1
41 #include "softmmu_template.h"
43 #define SHIFT 2
44 #include "softmmu_template.h"
46 #define SHIFT 3
47 #include "softmmu_template.h"
49 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
51 TranslationBlock *tb;
52 CPUState *saved_env;
53 unsigned long pc;
54 int ret;
56 /* XXX: hack to restore env in all cases, even if not called from
57 generated code */
58 saved_env = env;
59 env = cpu_single_env;
60 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
61 if (ret) {
62 if (retaddr) {
63 /* now we have a real cpu fault */
64 pc = (unsigned long) retaddr;
65 tb = tb_find_pc(pc);
66 if (tb) {
67 /* the PC is inside the translated code. It means that we have
68 a virtual CPU fault */
69 cpu_restore_state(tb, env, pc, NULL);
72 do_raise_exception();
74 env = saved_env;
77 #endif
79 void helper_addc_T0_T1(void)
81 uint32_t tmp0, tmp1;
83 tmp1 = T0 + T1;
84 tmp0 = T1;
85 T1 = tmp1 + (env->sr & 1);
86 if (tmp0 > tmp1)
87 env->sr |= SR_T;
88 else
89 env->sr &= ~SR_T;
90 if (tmp1 > T1)
91 env->sr |= SR_T;
94 void helper_addv_T0_T1(void)
96 uint32_t dest, src, ans;
98 if ((int32_t) T1 >= 0)
99 dest = 0;
100 else
101 dest = 1;
102 if ((int32_t) T0 >= 0)
103 src = 0;
104 else
105 src = 1;
106 src += dest;
107 T1 += T0;
108 if ((int32_t) T1 >= 0)
109 ans = 0;
110 else
111 ans = 1;
112 ans += dest;
113 if (src == 0 || src == 2) {
114 if (ans == 1)
115 env->sr |= SR_T;
116 else
117 env->sr &= ~SR_T;
118 } else
119 env->sr &= ~SR_T;
122 #define T (env->sr & SR_T)
123 #define Q (env->sr & SR_Q ? 1 : 0)
124 #define M (env->sr & SR_M ? 1 : 0)
125 #define SETT env->sr |= SR_T
126 #define CLRT env->sr &= ~SR_T
127 #define SETQ env->sr |= SR_Q
128 #define CLRQ env->sr &= ~SR_Q
129 #define SETM env->sr |= SR_M
130 #define CLRM env->sr &= ~SR_M
132 void helper_div1_T0_T1(void)
134 uint32_t tmp0, tmp2;
135 uint8_t old_q, tmp1 = 0xff;
137 //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
138 old_q = Q;
139 if ((0x80000000 & T1) != 0)
140 SETQ;
141 else
142 CLRQ;
143 tmp2 = T0;
144 T1 <<= 1;
145 T1 |= T;
146 switch (old_q) {
147 case 0:
148 switch (M) {
149 case 0:
150 tmp0 = T1;
151 T1 -= tmp2;
152 tmp1 = T1 > tmp0;
153 switch (Q) {
154 case 0:
155 if (tmp1)
156 SETQ;
157 else
158 CLRQ;
159 break;
160 case 1:
161 if (tmp1 == 0)
162 SETQ;
163 else
164 CLRQ;
165 break;
167 break;
168 case 1:
169 tmp0 = T1;
170 T1 += tmp2;
171 tmp1 = T1 < tmp0;
172 switch (Q) {
173 case 0:
174 if (tmp1 == 0)
175 SETQ;
176 else
177 CLRQ;
178 break;
179 case 1:
180 if (tmp1)
181 SETQ;
182 else
183 CLRQ;
184 break;
186 break;
188 break;
189 case 1:
190 switch (M) {
191 case 0:
192 tmp0 = T1;
193 T1 += tmp2;
194 tmp1 = T1 < tmp0;
195 switch (Q) {
196 case 0:
197 if (tmp1)
198 SETQ;
199 else
200 CLRQ;
201 break;
202 case 1:
203 if (tmp1 == 0)
204 SETQ;
205 else
206 CLRQ;
207 break;
209 break;
210 case 1:
211 tmp0 = T1;
212 T1 -= tmp2;
213 tmp1 = T1 > tmp0;
214 switch (Q) {
215 case 0:
216 if (tmp1 == 0)
217 SETQ;
218 else
219 CLRQ;
220 break;
221 case 1:
222 if (tmp1)
223 SETQ;
224 else
225 CLRQ;
226 break;
228 break;
230 break;
232 if (Q == M)
233 SETT;
234 else
235 CLRT;
236 //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
239 void helper_dmulsl_T0_T1()
241 int64_t res;
243 res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
244 env->mach = (res >> 32) & 0xffffffff;
245 env->macl = res & 0xffffffff;
248 void helper_dmulul_T0_T1()
250 uint64_t res;
252 res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
253 env->mach = (res >> 32) & 0xffffffff;
254 env->macl = res & 0xffffffff;
257 void helper_macl_T0_T1()
259 int64_t res;
261 res = ((uint64_t) env->mach << 32) | env->macl;
262 res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
263 env->mach = (res >> 32) & 0xffffffff;
264 env->macl = res & 0xffffffff;
265 if (env->sr & SR_S) {
266 if (res < 0)
267 env->mach |= 0xffff0000;
268 else
269 env->mach &= 0x00007fff;
273 void helper_macw_T0_T1()
275 int64_t res;
277 res = ((uint64_t) env->mach << 32) | env->macl;
278 res += (int64_t) (int16_t) T0 *(int64_t) (int16_t) T1;
279 env->mach = (res >> 32) & 0xffffffff;
280 env->macl = res & 0xffffffff;
281 if (env->sr & SR_S) {
282 if (res < -0x80000000) {
283 env->mach = 1;
284 env->macl = 0x80000000;
285 } else if (res > 0x000000007fffffff) {
286 env->mach = 1;
287 env->macl = 0x7fffffff;
292 void helper_negc_T0()
294 uint32_t temp;
296 temp = -T0;
297 T0 = temp - (env->sr & SR_T);
298 if (0 < temp)
299 env->sr |= SR_T;
300 else
301 env->sr &= ~SR_T;
302 if (temp < T0)
303 env->sr |= SR_T;
306 void helper_subc_T0_T1()
308 uint32_t tmp0, tmp1;
310 tmp1 = T1 - T0;
311 tmp0 = T1;
312 T1 = tmp1 - (env->sr & SR_T);
313 if (tmp0 < tmp1)
314 env->sr |= SR_T;
315 else
316 env->sr &= ~SR_T;
317 if (tmp1 < T1)
318 env->sr |= SR_T;
321 void helper_subv_T0_T1()
323 int32_t dest, src, ans;
325 if ((int32_t) T1 >= 0)
326 dest = 0;
327 else
328 dest = 1;
329 if ((int32_t) T0 >= 0)
330 src = 0;
331 else
332 src = 1;
333 src += dest;
334 T1 -= T0;
335 if ((int32_t) T1 >= 0)
336 ans = 0;
337 else
338 ans = 1;
339 ans += dest;
340 if (src == 1) {
341 if (ans == 1)
342 env->sr |= SR_T;
343 else
344 env->sr &= ~SR_T;
345 } else
346 env->sr &= ~SR_T;
349 void helper_rotcl(uint32_t * addr)
351 uint32_t new;
353 new = (*addr << 1) | (env->sr & SR_T);
354 if (*addr & 0x80000000)
355 env->sr |= SR_T;
356 else
357 env->sr &= ~SR_T;
358 *addr = new;
361 void helper_rotcr(uint32_t * addr)
363 uint32_t new;
365 new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
366 if (*addr & 1)
367 env->sr |= SR_T;
368 else
369 env->sr &= ~SR_T;
370 *addr = new;