Fix typo in comment, by Andreas Faerber.
[qemu/dscho.git] / target-sh4 / op_helper.c
blobbf39921b4d9160d2045e55d909e874381eedf851
1 /*
2 * SH4 emulation
3 *
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 #define GETPC() (__builtin_return_address(0))
33 #define SHIFT 0
34 #include "softmmu_template.h"
36 #define SHIFT 1
37 #include "softmmu_template.h"
39 #define SHIFT 2
40 #include "softmmu_template.h"
42 #define SHIFT 3
43 #include "softmmu_template.h"
45 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
47 TranslationBlock *tb;
48 CPUState *saved_env;
49 unsigned long pc;
50 int ret;
52 /* XXX: hack to restore env in all cases, even if not called from
53 generated code */
54 saved_env = env;
55 env = cpu_single_env;
56 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, is_user, 1);
57 if (ret) {
58 if (retaddr) {
59 /* now we have a real cpu fault */
60 pc = (unsigned long) retaddr;
61 tb = tb_find_pc(pc);
62 if (tb) {
63 /* the PC is inside the translated code. It means that we have
64 a virtual CPU fault */
65 cpu_restore_state(tb, env, pc, NULL);
68 do_raise_exception();
70 env = saved_env;
73 #endif
75 void helper_addc_T0_T1(void)
77 uint32_t tmp0, tmp1;
79 tmp1 = T0 + T1;
80 tmp0 = T1;
81 T1 = tmp1 + (env->sr & 1);
82 if (tmp0 > tmp1)
83 env->sr |= SR_T;
84 else
85 env->sr &= ~SR_T;
86 if (tmp1 > T1)
87 env->sr |= SR_T;
90 void helper_addv_T0_T1(void)
92 uint32_t dest, src, ans;
94 if ((int32_t) T1 >= 0)
95 dest = 0;
96 else
97 dest = 1;
98 if ((int32_t) T0 >= 0)
99 src = 0;
100 else
101 src = 1;
102 src += dest;
103 T1 += T0;
104 if ((int32_t) T1 >= 0)
105 ans = 0;
106 else
107 ans = 1;
108 ans += dest;
109 if (src == 0 || src == 2) {
110 if (ans == 1)
111 env->sr |= SR_T;
112 else
113 env->sr &= ~SR_T;
114 } else
115 env->sr &= ~SR_T;
118 #define T (env->sr & SR_T)
119 #define Q (env->sr & SR_Q ? 1 : 0)
120 #define M (env->sr & SR_M ? 1 : 0)
121 #define SETT env->sr |= SR_T
122 #define CLRT env->sr &= ~SR_T
123 #define SETQ env->sr |= SR_Q
124 #define CLRQ env->sr &= ~SR_Q
125 #define SETM env->sr |= SR_M
126 #define CLRM env->sr &= ~SR_M
128 void helper_div1_T0_T1(void)
130 uint32_t tmp0, tmp2;
131 uint8_t old_q, tmp1 = 0xff;
133 //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
134 old_q = Q;
135 if ((0x80000000 & T1) != 0)
136 SETQ;
137 else
138 CLRQ;
139 tmp2 = T0;
140 T1 <<= 1;
141 T1 |= T;
142 switch (old_q) {
143 case 0:
144 switch (M) {
145 case 0:
146 tmp0 = T1;
147 T1 -= tmp2;
148 tmp1 = T1 > tmp0;
149 switch (Q) {
150 case 0:
151 if (tmp1)
152 SETQ;
153 else
154 CLRQ;
155 break;
156 case 1:
157 if (tmp1 == 0)
158 SETQ;
159 else
160 CLRQ;
161 break;
163 break;
164 case 1:
165 tmp0 = T1;
166 T1 += tmp2;
167 tmp1 = T1 < tmp0;
168 switch (Q) {
169 case 0:
170 if (tmp1 == 0)
171 SETQ;
172 else
173 CLRQ;
174 break;
175 case 1:
176 if (tmp1)
177 SETQ;
178 else
179 CLRQ;
180 break;
182 break;
184 break;
185 case 1:
186 switch (M) {
187 case 0:
188 tmp0 = T1;
189 T1 += tmp2;
190 tmp1 = T1 < tmp0;
191 switch (Q) {
192 case 0:
193 if (tmp1)
194 SETQ;
195 else
196 CLRQ;
197 break;
198 case 1:
199 if (tmp1 == 0)
200 SETQ;
201 else
202 CLRQ;
203 break;
205 break;
206 case 1:
207 tmp0 = T1;
208 T1 -= tmp2;
209 tmp1 = T1 > tmp0;
210 switch (Q) {
211 case 0:
212 if (tmp1 == 0)
213 SETQ;
214 else
215 CLRQ;
216 break;
217 case 1:
218 if (tmp1)
219 SETQ;
220 else
221 CLRQ;
222 break;
224 break;
226 break;
228 if (Q == M)
229 SETT;
230 else
231 CLRT;
232 //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
235 void helper_dmulsl_T0_T1()
237 int64_t res;
239 res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
240 env->mach = (res >> 32) & 0xffffffff;
241 env->macl = res & 0xffffffff;
244 void helper_dmulul_T0_T1()
246 uint64_t res;
248 res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
249 env->mach = (res >> 32) & 0xffffffff;
250 env->macl = res & 0xffffffff;
253 void helper_macl_T0_T1()
255 int64_t res;
257 res = ((uint64_t) env->mach << 32) | env->macl;
258 res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
259 env->mach = (res >> 32) & 0xffffffff;
260 env->macl = res & 0xffffffff;
261 if (env->sr & SR_S) {
262 if (res < 0)
263 env->mach |= 0xffff0000;
264 else
265 env->mach &= 0x00007fff;
269 void helper_macw_T0_T1()
271 int64_t res;
273 res = ((uint64_t) env->mach << 32) | env->macl;
274 res += (int64_t) (int16_t) T0 *(int64_t) (int16_t) T1;
275 env->mach = (res >> 32) & 0xffffffff;
276 env->macl = res & 0xffffffff;
277 if (env->sr & SR_S) {
278 if (res < -0x80000000) {
279 env->mach = 1;
280 env->macl = 0x80000000;
281 } else if (res > 0x000000007fffffff) {
282 env->mach = 1;
283 env->macl = 0x7fffffff;
288 void helper_negc_T0()
290 uint32_t temp;
292 temp = -T0;
293 T0 = temp - (env->sr & SR_T);
294 if (0 < temp)
295 env->sr |= SR_T;
296 else
297 env->sr &= ~SR_T;
298 if (temp < T0)
299 env->sr |= SR_T;
302 void helper_subc_T0_T1()
304 uint32_t tmp0, tmp1;
306 tmp1 = T1 - T0;
307 tmp0 = T1;
308 T1 = tmp1 - (env->sr & SR_T);
309 if (tmp0 < tmp1)
310 env->sr |= SR_T;
311 else
312 env->sr &= ~SR_T;
313 if (tmp1 < T1)
314 env->sr |= SR_T;
317 void helper_subv_T0_T1()
319 int32_t dest, src, ans;
321 if ((int32_t) T1 >= 0)
322 dest = 0;
323 else
324 dest = 1;
325 if ((int32_t) T0 >= 0)
326 src = 0;
327 else
328 src = 1;
329 src += dest;
330 T1 -= T0;
331 if ((int32_t) T1 >= 0)
332 ans = 0;
333 else
334 ans = 1;
335 ans += dest;
336 if (src == 1) {
337 if (ans == 1)
338 env->sr |= SR_T;
339 else
340 env->sr &= ~SR_T;
341 } else
342 env->sr &= ~SR_T;
345 void helper_rotcl(uint32_t * addr)
347 uint32_t new;
349 new = (*addr << 1) | (env->sr & SR_T);
350 if (*addr & 0x80000000)
351 env->sr |= SR_T;
352 else
353 env->sr &= ~SR_T;
354 *addr = new;
357 void helper_rotcr(uint32_t * addr)
359 uint32_t new;
361 new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
362 if (*addr & 1)
363 env->sr |= SR_T;
364 else
365 env->sr &= ~SR_T;
366 *addr = new;