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