]> git.proxmox.com Git - qemu.git/blob - target-sh4/op_helper.c
TCG variable type checking.
[qemu.git] / target-sh4 / op_helper.c
1 /*
2 * SH4 emulation
3 *
4 * Copyright (c) 2005 Samuel Tardieu
5 *
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.
10 *
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.
15 *
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
19 */
20 #include <assert.h>
21 #include "exec.h"
22 #include "helper.h"
23
24 #ifndef CONFIG_USER_ONLY
25
26 #define MMUSUFFIX _mmu
27
28 #define SHIFT 0
29 #include "softmmu_template.h"
30
31 #define SHIFT 1
32 #include "softmmu_template.h"
33
34 #define SHIFT 2
35 #include "softmmu_template.h"
36
37 #define SHIFT 3
38 #include "softmmu_template.h"
39
40 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
41 {
42 TranslationBlock *tb;
43 CPUState *saved_env;
44 unsigned long pc;
45 int ret;
46
47 /* XXX: hack to restore env in all cases, even if not called from
48 generated code */
49 saved_env = env;
50 env = cpu_single_env;
51 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
52 if (ret) {
53 if (retaddr) {
54 /* now we have a real cpu fault */
55 pc = (unsigned long) retaddr;
56 tb = tb_find_pc(pc);
57 if (tb) {
58 /* the PC is inside the translated code. It means that we have
59 a virtual CPU fault */
60 cpu_restore_state(tb, env, pc, NULL);
61 }
62 }
63 cpu_loop_exit();
64 }
65 env = saved_env;
66 }
67
68 #endif
69
70 void helper_ldtlb(void)
71 {
72 #ifdef CONFIG_USER_ONLY
73 /* XXXXX */
74 assert(0);
75 #else
76 cpu_load_tlb(env);
77 #endif
78 }
79
80 void helper_raise_illegal_instruction(void)
81 {
82 env->exception_index = 0x180;
83 cpu_loop_exit();
84 }
85
86 void helper_raise_slot_illegal_instruction(void)
87 {
88 env->exception_index = 0x1a0;
89 cpu_loop_exit();
90 }
91
92 void helper_debug(void)
93 {
94 env->exception_index = EXCP_DEBUG;
95 cpu_loop_exit();
96 }
97
98 void helper_sleep(uint32_t next_pc)
99 {
100 env->halted = 1;
101 env->exception_index = EXCP_HLT;
102 env->pc = next_pc;
103 cpu_loop_exit();
104 }
105
106 void helper_trapa(uint32_t tra)
107 {
108 env->tra = tra << 2;
109 env->exception_index = 0x160;
110 cpu_loop_exit();
111 }
112
113 uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
114 {
115 uint32_t tmp0, tmp1;
116
117 tmp1 = arg0 + arg1;
118 tmp0 = arg1;
119 arg1 = tmp1 + (env->sr & 1);
120 if (tmp0 > tmp1)
121 env->sr |= SR_T;
122 else
123 env->sr &= ~SR_T;
124 if (tmp1 > arg1)
125 env->sr |= SR_T;
126 return arg1;
127 }
128
129 uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
130 {
131 uint32_t dest, src, ans;
132
133 if ((int32_t) arg1 >= 0)
134 dest = 0;
135 else
136 dest = 1;
137 if ((int32_t) arg0 >= 0)
138 src = 0;
139 else
140 src = 1;
141 src += dest;
142 arg1 += arg0;
143 if ((int32_t) arg1 >= 0)
144 ans = 0;
145 else
146 ans = 1;
147 ans += dest;
148 if (src == 0 || src == 2) {
149 if (ans == 1)
150 env->sr |= SR_T;
151 else
152 env->sr &= ~SR_T;
153 } else
154 env->sr &= ~SR_T;
155 return arg1;
156 }
157
158 #define T (env->sr & SR_T)
159 #define Q (env->sr & SR_Q ? 1 : 0)
160 #define M (env->sr & SR_M ? 1 : 0)
161 #define SETT env->sr |= SR_T
162 #define CLRT env->sr &= ~SR_T
163 #define SETQ env->sr |= SR_Q
164 #define CLRQ env->sr &= ~SR_Q
165 #define SETM env->sr |= SR_M
166 #define CLRM env->sr &= ~SR_M
167
168 uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
169 {
170 uint32_t tmp0, tmp2;
171 uint8_t old_q, tmp1 = 0xff;
172
173 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
174 old_q = Q;
175 if ((0x80000000 & arg1) != 0)
176 SETQ;
177 else
178 CLRQ;
179 tmp2 = arg0;
180 arg1 <<= 1;
181 arg1 |= T;
182 switch (old_q) {
183 case 0:
184 switch (M) {
185 case 0:
186 tmp0 = arg1;
187 arg1 -= tmp2;
188 tmp1 = arg1 > tmp0;
189 switch (Q) {
190 case 0:
191 if (tmp1)
192 SETQ;
193 else
194 CLRQ;
195 break;
196 case 1:
197 if (tmp1 == 0)
198 SETQ;
199 else
200 CLRQ;
201 break;
202 }
203 break;
204 case 1:
205 tmp0 = arg1;
206 arg1 += tmp2;
207 tmp1 = arg1 < tmp0;
208 switch (Q) {
209 case 0:
210 if (tmp1 == 0)
211 SETQ;
212 else
213 CLRQ;
214 break;
215 case 1:
216 if (tmp1)
217 SETQ;
218 else
219 CLRQ;
220 break;
221 }
222 break;
223 }
224 break;
225 case 1:
226 switch (M) {
227 case 0:
228 tmp0 = arg1;
229 arg1 += tmp2;
230 tmp1 = arg1 < tmp0;
231 switch (Q) {
232 case 0:
233 if (tmp1)
234 SETQ;
235 else
236 CLRQ;
237 break;
238 case 1:
239 if (tmp1 == 0)
240 SETQ;
241 else
242 CLRQ;
243 break;
244 }
245 break;
246 case 1:
247 tmp0 = arg1;
248 arg1 -= tmp2;
249 tmp1 = arg1 > tmp0;
250 switch (Q) {
251 case 0:
252 if (tmp1 == 0)
253 SETQ;
254 else
255 CLRQ;
256 break;
257 case 1:
258 if (tmp1)
259 SETQ;
260 else
261 CLRQ;
262 break;
263 }
264 break;
265 }
266 break;
267 }
268 if (Q == M)
269 SETT;
270 else
271 CLRT;
272 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
273 return arg1;
274 }
275
276 void helper_macl(uint32_t arg0, uint32_t arg1)
277 {
278 int64_t res;
279
280 res = ((uint64_t) env->mach << 32) | env->macl;
281 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
282 env->mach = (res >> 32) & 0xffffffff;
283 env->macl = res & 0xffffffff;
284 if (env->sr & SR_S) {
285 if (res < 0)
286 env->mach |= 0xffff0000;
287 else
288 env->mach &= 0x00007fff;
289 }
290 }
291
292 void helper_macw(uint32_t arg0, uint32_t arg1)
293 {
294 int64_t res;
295
296 res = ((uint64_t) env->mach << 32) | env->macl;
297 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
298 env->mach = (res >> 32) & 0xffffffff;
299 env->macl = res & 0xffffffff;
300 if (env->sr & SR_S) {
301 if (res < -0x80000000) {
302 env->mach = 1;
303 env->macl = 0x80000000;
304 } else if (res > 0x000000007fffffff) {
305 env->mach = 1;
306 env->macl = 0x7fffffff;
307 }
308 }
309 }
310
311 uint32_t helper_negc(uint32_t arg)
312 {
313 uint32_t temp;
314
315 temp = -arg;
316 arg = temp - (env->sr & SR_T);
317 if (0 < temp)
318 env->sr |= SR_T;
319 else
320 env->sr &= ~SR_T;
321 if (temp < arg)
322 env->sr |= SR_T;
323 return arg;
324 }
325
326 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
327 {
328 uint32_t tmp0, tmp1;
329
330 tmp1 = arg1 - arg0;
331 tmp0 = arg1;
332 arg1 = tmp1 - (env->sr & SR_T);
333 if (tmp0 < tmp1)
334 env->sr |= SR_T;
335 else
336 env->sr &= ~SR_T;
337 if (tmp1 < arg1)
338 env->sr |= SR_T;
339 return arg1;
340 }
341
342 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
343 {
344 int32_t dest, src, ans;
345
346 if ((int32_t) arg1 >= 0)
347 dest = 0;
348 else
349 dest = 1;
350 if ((int32_t) arg0 >= 0)
351 src = 0;
352 else
353 src = 1;
354 src += dest;
355 arg1 -= arg0;
356 if ((int32_t) arg1 >= 0)
357 ans = 0;
358 else
359 ans = 1;
360 ans += dest;
361 if (src == 1) {
362 if (ans == 1)
363 env->sr |= SR_T;
364 else
365 env->sr &= ~SR_T;
366 } else
367 env->sr &= ~SR_T;
368 return arg1;
369 }
370
371 static inline void set_t(void)
372 {
373 env->sr |= SR_T;
374 }
375
376 static inline void clr_t(void)
377 {
378 env->sr &= ~SR_T;
379 }
380
381 void helper_ld_fpscr(uint32_t val)
382 {
383 env->fpscr = val & 0x003fffff;
384 if (val & 0x01)
385 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
386 else
387 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
388 }
389
390 uint32_t helper_fabs_FT(uint32_t t0)
391 {
392 float32 ret = float32_abs(*(float32*)&t0);
393 return *(uint32_t*)(&ret);
394 }
395
396 uint64_t helper_fabs_DT(uint64_t t0)
397 {
398 float64 ret = float64_abs(*(float64*)&t0);
399 return *(uint64_t*)(&ret);
400 }
401
402 uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
403 {
404 float32 ret = float32_add(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
405 return *(uint32_t*)(&ret);
406 }
407
408 uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
409 {
410 float64 ret = float64_add(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
411 return *(uint64_t*)(&ret);
412 }
413
414 void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
415 {
416 if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 0)
417 set_t();
418 else
419 clr_t();
420 }
421
422 void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
423 {
424 if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 0)
425 set_t();
426 else
427 clr_t();
428 }
429
430 void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
431 {
432 if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 1)
433 set_t();
434 else
435 clr_t();
436 }
437
438 void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
439 {
440 if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 1)
441 set_t();
442 else
443 clr_t();
444 }
445
446 uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
447 {
448 float64 ret = float32_to_float64(*(float32*)&t0, &env->fp_status);
449 return *(uint64_t*)(&ret);
450 }
451
452 uint32_t helper_fcnvds_DT_FT(uint64_t t0)
453 {
454 float32 ret = float64_to_float32(*(float64*)&t0, &env->fp_status);
455 return *(uint32_t*)(&ret);
456 }
457
458 uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
459 {
460 float32 ret = float32_div(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
461 return *(uint32_t*)(&ret);
462 }
463
464 uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
465 {
466 float64 ret = float64_div(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
467 return *(uint64_t*)(&ret);
468 }
469
470 uint32_t helper_float_FT(uint32_t t0)
471 {
472 float32 ret = int32_to_float32(t0, &env->fp_status);
473 return *(uint32_t*)(&ret);
474 }
475
476 uint64_t helper_float_DT(uint32_t t0)
477 {
478 float64 ret = int32_to_float64(t0, &env->fp_status);
479 return *(uint64_t*)(&ret);
480 }
481
482 uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
483 {
484 float32 ret = float32_mul(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
485 return *(uint32_t*)(&ret);
486 }
487
488 uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
489 {
490 float64 ret = float64_mul(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
491 return *(uint64_t*)(&ret);
492 }
493
494 uint32_t helper_fneg_T(uint32_t t0)
495 {
496 float32 ret = float32_chs(*(float32*)&t0);
497 return *(uint32_t*)(&ret);
498 }
499
500 uint32_t helper_fsqrt_FT(uint32_t t0)
501 {
502 float32 ret = float32_sqrt(*(float32*)&t0, &env->fp_status);
503 return *(uint32_t*)(&ret);
504 }
505
506 uint64_t helper_fsqrt_DT(uint64_t t0)
507 {
508 float64 ret = float64_sqrt(*(float64*)&t0, &env->fp_status);
509 return *(uint64_t*)(&ret);
510 }
511
512 uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
513 {
514 float32 ret = float32_sub(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
515 return *(uint32_t*)(&ret);
516 }
517
518 uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
519 {
520 float64 ret = float64_sub(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
521 return *(uint64_t*)(&ret);
522 }
523
524 uint32_t helper_ftrc_FT(uint32_t t0)
525 {
526 return float32_to_int32_round_to_zero(*(float32*)&t0, &env->fp_status);
527 }
528
529 uint32_t helper_ftrc_DT(uint64_t t0)
530 {
531 return float64_to_int32_round_to_zero(*(float64*)&t0, &env->fp_status);
532 }