Fix interrupt exclusion via SSTEP_NOIRQ
[qemu/mini2440.git] / target-sh4 / op_helper.c
blobe5b3c98ab4d61bfca220abce5bbe35c789dd12bd
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 #ifndef CONFIG_USER_ONLY
25 #define MMUSUFFIX _mmu
27 #define SHIFT 0
28 #include "softmmu_template.h"
30 #define SHIFT 1
31 #include "softmmu_template.h"
33 #define SHIFT 2
34 #include "softmmu_template.h"
36 #define SHIFT 3
37 #include "softmmu_template.h"
39 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
41 TranslationBlock *tb;
42 CPUState *saved_env;
43 unsigned long pc;
44 int ret;
46 /* XXX: hack to restore env in all cases, even if not called from
47 generated code */
48 saved_env = env;
49 env = cpu_single_env;
50 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
51 if (ret) {
52 if (retaddr) {
53 /* now we have a real cpu fault */
54 pc = (unsigned long) retaddr;
55 tb = tb_find_pc(pc);
56 if (tb) {
57 /* the PC is inside the translated code. It means that we have
58 a virtual CPU fault */
59 cpu_restore_state(tb, env, pc, NULL);
62 cpu_loop_exit();
64 env = saved_env;
67 #endif
69 void helper_ldtlb(void)
71 #ifdef CONFIG_USER_ONLY
72 /* XXXXX */
73 assert(0);
74 #else
75 cpu_load_tlb(env);
76 #endif
79 void helper_raise_illegal_instruction(void)
81 env->exception_index = 0x180;
82 cpu_loop_exit();
85 void helper_raise_slot_illegal_instruction(void)
87 env->exception_index = 0x1a0;
88 cpu_loop_exit();
91 void helper_debug(void)
93 env->exception_index = EXCP_DEBUG;
94 cpu_loop_exit();
97 void helper_sleep(uint32_t next_pc)
99 env->halted = 1;
100 env->exception_index = EXCP_HLT;
101 env->pc = next_pc;
102 cpu_loop_exit();
105 void helper_trapa(uint32_t tra)
107 env->tra = tra << 2;
108 env->exception_index = 0x160;
109 cpu_loop_exit();
112 uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
114 uint32_t tmp0, tmp1;
116 tmp1 = arg0 + arg1;
117 tmp0 = arg1;
118 arg1 = tmp1 + (env->sr & 1);
119 if (tmp0 > tmp1)
120 env->sr |= SR_T;
121 else
122 env->sr &= ~SR_T;
123 if (tmp1 > arg1)
124 env->sr |= SR_T;
125 return arg1;
128 uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
130 uint32_t dest, src, ans;
132 if ((int32_t) arg1 >= 0)
133 dest = 0;
134 else
135 dest = 1;
136 if ((int32_t) arg0 >= 0)
137 src = 0;
138 else
139 src = 1;
140 src += dest;
141 arg1 += arg0;
142 if ((int32_t) arg1 >= 0)
143 ans = 0;
144 else
145 ans = 1;
146 ans += dest;
147 if (src == 0 || src == 2) {
148 if (ans == 1)
149 env->sr |= SR_T;
150 else
151 env->sr &= ~SR_T;
152 } else
153 env->sr &= ~SR_T;
154 return arg1;
157 #define T (env->sr & SR_T)
158 #define Q (env->sr & SR_Q ? 1 : 0)
159 #define M (env->sr & SR_M ? 1 : 0)
160 #define SETT env->sr |= SR_T
161 #define CLRT env->sr &= ~SR_T
162 #define SETQ env->sr |= SR_Q
163 #define CLRQ env->sr &= ~SR_Q
164 #define SETM env->sr |= SR_M
165 #define CLRM env->sr &= ~SR_M
167 uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
169 uint32_t tmp0, tmp2;
170 uint8_t old_q, tmp1 = 0xff;
172 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
173 old_q = Q;
174 if ((0x80000000 & arg1) != 0)
175 SETQ;
176 else
177 CLRQ;
178 tmp2 = arg0;
179 arg1 <<= 1;
180 arg1 |= T;
181 switch (old_q) {
182 case 0:
183 switch (M) {
184 case 0:
185 tmp0 = arg1;
186 arg1 -= tmp2;
187 tmp1 = arg1 > tmp0;
188 switch (Q) {
189 case 0:
190 if (tmp1)
191 SETQ;
192 else
193 CLRQ;
194 break;
195 case 1:
196 if (tmp1 == 0)
197 SETQ;
198 else
199 CLRQ;
200 break;
202 break;
203 case 1:
204 tmp0 = arg1;
205 arg1 += tmp2;
206 tmp1 = arg1 < tmp0;
207 switch (Q) {
208 case 0:
209 if (tmp1 == 0)
210 SETQ;
211 else
212 CLRQ;
213 break;
214 case 1:
215 if (tmp1)
216 SETQ;
217 else
218 CLRQ;
219 break;
221 break;
223 break;
224 case 1:
225 switch (M) {
226 case 0:
227 tmp0 = arg1;
228 arg1 += tmp2;
229 tmp1 = arg1 < tmp0;
230 switch (Q) {
231 case 0:
232 if (tmp1)
233 SETQ;
234 else
235 CLRQ;
236 break;
237 case 1:
238 if (tmp1 == 0)
239 SETQ;
240 else
241 CLRQ;
242 break;
244 break;
245 case 1:
246 tmp0 = arg1;
247 arg1 -= tmp2;
248 tmp1 = arg1 > tmp0;
249 switch (Q) {
250 case 0:
251 if (tmp1 == 0)
252 SETQ;
253 else
254 CLRQ;
255 break;
256 case 1:
257 if (tmp1)
258 SETQ;
259 else
260 CLRQ;
261 break;
263 break;
265 break;
267 if (Q == M)
268 SETT;
269 else
270 CLRT;
271 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
272 return arg1;
275 void helper_macl(uint32_t arg0, uint32_t arg1)
277 int64_t res;
279 res = ((uint64_t) env->mach << 32) | env->macl;
280 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
281 env->mach = (res >> 32) & 0xffffffff;
282 env->macl = res & 0xffffffff;
283 if (env->sr & SR_S) {
284 if (res < 0)
285 env->mach |= 0xffff0000;
286 else
287 env->mach &= 0x00007fff;
291 void helper_macw(uint32_t arg0, uint32_t arg1)
293 int64_t res;
295 res = ((uint64_t) env->mach << 32) | env->macl;
296 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
297 env->mach = (res >> 32) & 0xffffffff;
298 env->macl = res & 0xffffffff;
299 if (env->sr & SR_S) {
300 if (res < -0x80000000) {
301 env->mach = 1;
302 env->macl = 0x80000000;
303 } else if (res > 0x000000007fffffff) {
304 env->mach = 1;
305 env->macl = 0x7fffffff;
310 uint32_t helper_negc(uint32_t arg)
312 uint32_t temp;
314 temp = -arg;
315 arg = temp - (env->sr & SR_T);
316 if (0 < temp)
317 env->sr |= SR_T;
318 else
319 env->sr &= ~SR_T;
320 if (temp < arg)
321 env->sr |= SR_T;
322 return arg;
325 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
327 uint32_t tmp0, tmp1;
329 tmp1 = arg1 - arg0;
330 tmp0 = arg1;
331 arg1 = tmp1 - (env->sr & SR_T);
332 if (tmp0 < tmp1)
333 env->sr |= SR_T;
334 else
335 env->sr &= ~SR_T;
336 if (tmp1 < arg1)
337 env->sr |= SR_T;
338 return arg1;
341 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
343 int32_t dest, src, ans;
345 if ((int32_t) arg1 >= 0)
346 dest = 0;
347 else
348 dest = 1;
349 if ((int32_t) arg0 >= 0)
350 src = 0;
351 else
352 src = 1;
353 src += dest;
354 arg1 -= arg0;
355 if ((int32_t) arg1 >= 0)
356 ans = 0;
357 else
358 ans = 1;
359 ans += dest;
360 if (src == 1) {
361 if (ans == 1)
362 env->sr |= SR_T;
363 else
364 env->sr &= ~SR_T;
365 } else
366 env->sr &= ~SR_T;
367 return arg1;
370 static inline void set_t(void)
372 env->sr |= SR_T;
375 static inline void clr_t(void)
377 env->sr &= ~SR_T;
380 void helper_ld_fpscr(uint32_t val)
382 env->fpscr = val & 0x003fffff;
383 if (val & 0x01)
384 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
385 else
386 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
389 uint32_t helper_fabs_FT(uint32_t t0)
391 float32 ret = float32_abs(*(float32*)&t0);
392 return *(uint32_t*)(&ret);
395 uint64_t helper_fabs_DT(uint64_t t0)
397 float64 ret = float64_abs(*(float64*)&t0);
398 return *(uint64_t*)(&ret);
401 uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
403 float32 ret = float32_add(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
404 return *(uint32_t*)(&ret);
407 uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
409 float64 ret = float64_add(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
410 return *(uint64_t*)(&ret);
413 void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
415 if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 0)
416 set_t();
417 else
418 clr_t();
421 void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
423 if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 0)
424 set_t();
425 else
426 clr_t();
429 void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
431 if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 1)
432 set_t();
433 else
434 clr_t();
437 void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
439 if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 1)
440 set_t();
441 else
442 clr_t();
445 uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
447 float64 ret = float32_to_float64(*(float32*)&t0, &env->fp_status);
448 return *(uint64_t*)(&ret);
451 uint32_t helper_fcnvds_DT_FT(uint64_t t0)
453 float32 ret = float64_to_float32(*(float64*)&t0, &env->fp_status);
454 return *(uint32_t*)(&ret);
457 uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
459 float32 ret = float32_div(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
460 return *(uint32_t*)(&ret);
463 uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
465 float64 ret = float64_div(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
466 return *(uint64_t*)(&ret);
469 uint32_t helper_float_FT(uint32_t t0)
471 float32 ret = int32_to_float32(t0, &env->fp_status);
472 return *(uint32_t*)(&ret);
475 uint64_t helper_float_DT(uint32_t t0)
477 float64 ret = int32_to_float64(t0, &env->fp_status);
478 return *(uint64_t*)(&ret);
481 uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
483 float32 ret = float32_mul(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
484 return *(uint32_t*)(&ret);
487 uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
489 float64 ret = float64_mul(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
490 return *(uint64_t*)(&ret);
493 uint32_t helper_fneg_T(uint32_t t0)
495 float32 ret = float32_chs(*(float32*)&t0);
496 return *(uint32_t*)(&ret);
499 uint32_t helper_fsqrt_FT(uint32_t t0)
501 float32 ret = float32_sqrt(*(float32*)&t0, &env->fp_status);
502 return *(uint32_t*)(&ret);
505 uint64_t helper_fsqrt_DT(uint64_t t0)
507 float64 ret = float64_sqrt(*(float64*)&t0, &env->fp_status);
508 return *(uint64_t*)(&ret);
511 uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
513 float32 ret = float32_sub(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
514 return *(uint32_t*)(&ret);
517 uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
519 float64 ret = float64_sub(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
520 return *(uint64_t*)(&ret);
523 uint32_t helper_ftrc_FT(uint32_t t0)
525 return float32_to_int32_round_to_zero(*(float32*)&t0, &env->fp_status);
528 uint32_t helper_ftrc_DT(uint64_t t0)
530 return float64_to_int32_round_to_zero(*(float64*)&t0, &env->fp_status);