]> git.proxmox.com Git - qemu.git/blame - target-sh4/op_helper.c
target-ppc: fix TCG type errors introduced in r5754
[qemu.git] / target-sh4 / op_helper.c
CommitLineData
fdf9b3e8
FB
1/*
2 * SH4 emulation
5fafdf24 3 *
fdf9b3e8
FB
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"
a7812ae4 22#include "helper.h"
fdf9b3e8 23
fdf9b3e8
FB
24#ifndef CONFIG_USER_ONLY
25
26#define MMUSUFFIX _mmu
fdf9b3e8
FB
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
6ebbf390 40void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
fdf9b3e8
FB
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;
6ebbf390 51 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
fdf9b3e8
FB
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 }
e6afc2f4 63 cpu_loop_exit();
fdf9b3e8
FB
64 }
65 env = saved_env;
66}
67
68#endif
69
ea2b542a
AJ
70void 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
e6afc2f4
AJ
80void helper_raise_illegal_instruction(void)
81{
82 env->exception_index = 0x180;
83 cpu_loop_exit();
84}
85
86void helper_raise_slot_illegal_instruction(void)
87{
88 env->exception_index = 0x1a0;
89 cpu_loop_exit();
90}
91
92void helper_debug(void)
93{
94 env->exception_index = EXCP_DEBUG;
95 cpu_loop_exit();
96}
97
f24f381b 98void helper_sleep(uint32_t next_pc)
e6afc2f4
AJ
99{
100 env->halted = 1;
101 env->exception_index = EXCP_HLT;
f24f381b 102 env->pc = next_pc;
e6afc2f4
AJ
103 cpu_loop_exit();
104}
105
106void helper_trapa(uint32_t tra)
107{
108 env->tra = tra << 2;
109 env->exception_index = 0x160;
110 cpu_loop_exit();
111}
112
6f06939b 113uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
114{
115 uint32_t tmp0, tmp1;
116
6f06939b
AJ
117 tmp1 = arg0 + arg1;
118 tmp0 = arg1;
119 arg1 = tmp1 + (env->sr & 1);
fdf9b3e8
FB
120 if (tmp0 > tmp1)
121 env->sr |= SR_T;
122 else
123 env->sr &= ~SR_T;
6f06939b 124 if (tmp1 > arg1)
fdf9b3e8 125 env->sr |= SR_T;
6f06939b 126 return arg1;
fdf9b3e8
FB
127}
128
6f06939b 129uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
130{
131 uint32_t dest, src, ans;
132
6f06939b 133 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
134 dest = 0;
135 else
136 dest = 1;
6f06939b 137 if ((int32_t) arg0 >= 0)
fdf9b3e8
FB
138 src = 0;
139 else
140 src = 1;
141 src += dest;
6f06939b
AJ
142 arg1 += arg0;
143 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
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;
6f06939b 155 return arg1;
fdf9b3e8
FB
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
69d6275b 168uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
169{
170 uint32_t tmp0, tmp2;
171 uint8_t old_q, tmp1 = 0xff;
172
69d6275b 173 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
fdf9b3e8 174 old_q = Q;
69d6275b 175 if ((0x80000000 & arg1) != 0)
fdf9b3e8
FB
176 SETQ;
177 else
178 CLRQ;
69d6275b
AJ
179 tmp2 = arg0;
180 arg1 <<= 1;
181 arg1 |= T;
fdf9b3e8
FB
182 switch (old_q) {
183 case 0:
184 switch (M) {
185 case 0:
69d6275b
AJ
186 tmp0 = arg1;
187 arg1 -= tmp2;
188 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
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:
69d6275b
AJ
205 tmp0 = arg1;
206 arg1 += tmp2;
207 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
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:
69d6275b
AJ
228 tmp0 = arg1;
229 arg1 += tmp2;
230 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
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:
69d6275b
AJ
247 tmp0 = arg1;
248 arg1 -= tmp2;
249 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
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;
69d6275b
AJ
272 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
273 return arg1;
fdf9b3e8
FB
274}
275
6f06939b 276void helper_macl(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
277{
278 int64_t res;
279
280 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 281 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
fdf9b3e8
FB
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
6f06939b 292void helper_macw(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
293{
294 int64_t res;
295
296 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 297 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
fdf9b3e8
FB
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
6f06939b 311uint32_t helper_negc(uint32_t arg)
fdf9b3e8
FB
312{
313 uint32_t temp;
314
6f06939b
AJ
315 temp = -arg;
316 arg = temp - (env->sr & SR_T);
fdf9b3e8
FB
317 if (0 < temp)
318 env->sr |= SR_T;
319 else
320 env->sr &= ~SR_T;
6f06939b 321 if (temp < arg)
fdf9b3e8 322 env->sr |= SR_T;
6f06939b 323 return arg;
fdf9b3e8
FB
324}
325
6f06939b 326uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
327{
328 uint32_t tmp0, tmp1;
329
6f06939b
AJ
330 tmp1 = arg1 - arg0;
331 tmp0 = arg1;
332 arg1 = tmp1 - (env->sr & SR_T);
fdf9b3e8
FB
333 if (tmp0 < tmp1)
334 env->sr |= SR_T;
335 else
336 env->sr &= ~SR_T;
6f06939b 337 if (tmp1 < arg1)
fdf9b3e8 338 env->sr |= SR_T;
6f06939b 339 return arg1;
fdf9b3e8
FB
340}
341
6f06939b 342uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
343{
344 int32_t dest, src, ans;
345
6f06939b 346 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
347 dest = 0;
348 else
349 dest = 1;
6f06939b 350 if ((int32_t) arg0 >= 0)
fdf9b3e8
FB
351 src = 0;
352 else
353 src = 1;
354 src += dest;
6f06939b
AJ
355 arg1 -= arg0;
356 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
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;
6f06939b 368 return arg1;
fdf9b3e8
FB
369}
370
cc4ba6a9
AJ
371static inline void set_t(void)
372{
373 env->sr |= SR_T;
374}
375
376static inline void clr_t(void)
377{
378 env->sr &= ~SR_T;
379}
380
390af821
AJ
381void 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}
cc4ba6a9
AJ
389
390uint32_t helper_fabs_FT(uint32_t t0)
391{
392 float32 ret = float32_abs(*(float32*)&t0);
393 return *(uint32_t*)(&ret);
394}
395
396uint64_t helper_fabs_DT(uint64_t t0)
397{
398 float64 ret = float64_abs(*(float64*)&t0);
399 return *(uint64_t*)(&ret);
400}
401
402uint32_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
408uint64_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
414void 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
422void 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
430void 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
438void 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
446uint64_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
452uint32_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
458uint32_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
464uint64_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
470uint32_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
476uint64_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
482uint32_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
488uint64_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
7fdf924f
AJ
494uint32_t helper_fneg_T(uint32_t t0)
495{
496 float32 ret = float32_chs(*(float32*)&t0);
497 return *(uint32_t*)(&ret);
498}
499
cc4ba6a9
AJ
500uint32_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
506uint64_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
512uint32_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
518uint64_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
524uint32_t helper_ftrc_FT(uint32_t t0)
525{
526 return float32_to_int32_round_to_zero(*(float32*)&t0, &env->fp_status);
527}
528
529uint32_t helper_ftrc_DT(uint64_t t0)
530{
531 return float64_to_int32_round_to_zero(*(float64*)&t0, &env->fp_status);
532}