]> git.proxmox.com Git - qemu.git/blame - target-sh4/op_helper.c
SH4: sleep instruction bug fix
[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
f24f381b 97void helper_sleep(uint32_t next_pc)
e6afc2f4
AJ
98{
99 env->halted = 1;
100 env->exception_index = EXCP_HLT;
f24f381b 101 env->pc = next_pc;
e6afc2f4
AJ
102 cpu_loop_exit();
103}
104
105void helper_trapa(uint32_t tra)
106{
107 env->tra = tra << 2;
108 env->exception_index = 0x160;
109 cpu_loop_exit();
110}
111
6f06939b 112uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
113{
114 uint32_t tmp0, tmp1;
115
6f06939b
AJ
116 tmp1 = arg0 + arg1;
117 tmp0 = arg1;
118 arg1 = tmp1 + (env->sr & 1);
fdf9b3e8
FB
119 if (tmp0 > tmp1)
120 env->sr |= SR_T;
121 else
122 env->sr &= ~SR_T;
6f06939b 123 if (tmp1 > arg1)
fdf9b3e8 124 env->sr |= SR_T;
6f06939b 125 return arg1;
fdf9b3e8
FB
126}
127
6f06939b 128uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
129{
130 uint32_t dest, src, ans;
131
6f06939b 132 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
133 dest = 0;
134 else
135 dest = 1;
6f06939b 136 if ((int32_t) arg0 >= 0)
fdf9b3e8
FB
137 src = 0;
138 else
139 src = 1;
140 src += dest;
6f06939b
AJ
141 arg1 += arg0;
142 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
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;
6f06939b 154 return arg1;
fdf9b3e8
FB
155}
156
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
166
69d6275b 167uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
168{
169 uint32_t tmp0, tmp2;
170 uint8_t old_q, tmp1 = 0xff;
171
69d6275b 172 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
fdf9b3e8 173 old_q = Q;
69d6275b 174 if ((0x80000000 & arg1) != 0)
fdf9b3e8
FB
175 SETQ;
176 else
177 CLRQ;
69d6275b
AJ
178 tmp2 = arg0;
179 arg1 <<= 1;
180 arg1 |= T;
fdf9b3e8
FB
181 switch (old_q) {
182 case 0:
183 switch (M) {
184 case 0:
69d6275b
AJ
185 tmp0 = arg1;
186 arg1 -= tmp2;
187 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
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;
201 }
202 break;
203 case 1:
69d6275b
AJ
204 tmp0 = arg1;
205 arg1 += tmp2;
206 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
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;
220 }
221 break;
222 }
223 break;
224 case 1:
225 switch (M) {
226 case 0:
69d6275b
AJ
227 tmp0 = arg1;
228 arg1 += tmp2;
229 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
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;
243 }
244 break;
245 case 1:
69d6275b
AJ
246 tmp0 = arg1;
247 arg1 -= tmp2;
248 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
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;
262 }
263 break;
264 }
265 break;
266 }
267 if (Q == M)
268 SETT;
269 else
270 CLRT;
69d6275b
AJ
271 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
272 return arg1;
fdf9b3e8
FB
273}
274
6f06939b 275void helper_macl(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
276{
277 int64_t res;
278
279 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 280 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
fdf9b3e8
FB
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;
288 }
289}
290
6f06939b 291void helper_macw(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
292{
293 int64_t res;
294
295 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 296 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
fdf9b3e8
FB
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;
306 }
307 }
308}
309
6f06939b 310uint32_t helper_negc(uint32_t arg)
fdf9b3e8
FB
311{
312 uint32_t temp;
313
6f06939b
AJ
314 temp = -arg;
315 arg = temp - (env->sr & SR_T);
fdf9b3e8
FB
316 if (0 < temp)
317 env->sr |= SR_T;
318 else
319 env->sr &= ~SR_T;
6f06939b 320 if (temp < arg)
fdf9b3e8 321 env->sr |= SR_T;
6f06939b 322 return arg;
fdf9b3e8
FB
323}
324
6f06939b 325uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
326{
327 uint32_t tmp0, tmp1;
328
6f06939b
AJ
329 tmp1 = arg1 - arg0;
330 tmp0 = arg1;
331 arg1 = tmp1 - (env->sr & SR_T);
fdf9b3e8
FB
332 if (tmp0 < tmp1)
333 env->sr |= SR_T;
334 else
335 env->sr &= ~SR_T;
6f06939b 336 if (tmp1 < arg1)
fdf9b3e8 337 env->sr |= SR_T;
6f06939b 338 return arg1;
fdf9b3e8
FB
339}
340
6f06939b 341uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
342{
343 int32_t dest, src, ans;
344
6f06939b 345 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
346 dest = 0;
347 else
348 dest = 1;
6f06939b 349 if ((int32_t) arg0 >= 0)
fdf9b3e8
FB
350 src = 0;
351 else
352 src = 1;
353 src += dest;
6f06939b
AJ
354 arg1 -= arg0;
355 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
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;
6f06939b 367 return arg1;
fdf9b3e8
FB
368}
369
cc4ba6a9
AJ
370static inline void set_t(void)
371{
372 env->sr |= SR_T;
373}
374
375static inline void clr_t(void)
376{
377 env->sr &= ~SR_T;
378}
379
390af821
AJ
380void helper_ld_fpscr(uint32_t val)
381{
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);
387}
cc4ba6a9
AJ
388
389uint32_t helper_fabs_FT(uint32_t t0)
390{
391 float32 ret = float32_abs(*(float32*)&t0);
392 return *(uint32_t*)(&ret);
393}
394
395uint64_t helper_fabs_DT(uint64_t t0)
396{
397 float64 ret = float64_abs(*(float64*)&t0);
398 return *(uint64_t*)(&ret);
399}
400
401uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
402{
403 float32 ret = float32_add(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
404 return *(uint32_t*)(&ret);
405}
406
407uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
408{
409 float64 ret = float64_add(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
410 return *(uint64_t*)(&ret);
411}
412
413void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
414{
415 if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 0)
416 set_t();
417 else
418 clr_t();
419}
420
421void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
422{
423 if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 0)
424 set_t();
425 else
426 clr_t();
427}
428
429void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
430{
431 if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 1)
432 set_t();
433 else
434 clr_t();
435}
436
437void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
438{
439 if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 1)
440 set_t();
441 else
442 clr_t();
443}
444
445uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
446{
447 float64 ret = float32_to_float64(*(float32*)&t0, &env->fp_status);
448 return *(uint64_t*)(&ret);
449}
450
451uint32_t helper_fcnvds_DT_FT(uint64_t t0)
452{
453 float32 ret = float64_to_float32(*(float64*)&t0, &env->fp_status);
454 return *(uint32_t*)(&ret);
455}
456
457uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
458{
459 float32 ret = float32_div(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
460 return *(uint32_t*)(&ret);
461}
462
463uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
464{
465 float64 ret = float64_div(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
466 return *(uint64_t*)(&ret);
467}
468
469uint32_t helper_float_FT(uint32_t t0)
470{
471 float32 ret = int32_to_float32(t0, &env->fp_status);
472 return *(uint32_t*)(&ret);
473}
474
475uint64_t helper_float_DT(uint32_t t0)
476{
477 float64 ret = int32_to_float64(t0, &env->fp_status);
478 return *(uint64_t*)(&ret);
479}
480
481uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
482{
483 float32 ret = float32_mul(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
484 return *(uint32_t*)(&ret);
485}
486
487uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
488{
489 float64 ret = float64_mul(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
490 return *(uint64_t*)(&ret);
491}
492
7fdf924f
AJ
493uint32_t helper_fneg_T(uint32_t t0)
494{
495 float32 ret = float32_chs(*(float32*)&t0);
496 return *(uint32_t*)(&ret);
497}
498
cc4ba6a9
AJ
499uint32_t helper_fsqrt_FT(uint32_t t0)
500{
501 float32 ret = float32_sqrt(*(float32*)&t0, &env->fp_status);
502 return *(uint32_t*)(&ret);
503}
504
505uint64_t helper_fsqrt_DT(uint64_t t0)
506{
507 float64 ret = float64_sqrt(*(float64*)&t0, &env->fp_status);
508 return *(uint64_t*)(&ret);
509}
510
511uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
512{
513 float32 ret = float32_sub(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
514 return *(uint32_t*)(&ret);
515}
516
517uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
518{
519 float64 ret = float64_sub(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
520 return *(uint64_t*)(&ret);
521}
522
523uint32_t helper_ftrc_FT(uint32_t t0)
524{
525 return float32_to_int32_round_to_zero(*(float32*)&t0, &env->fp_status);
526}
527
528uint32_t helper_ftrc_DT(uint64_t t0)
529{
530 return float64_to_int32_round_to_zero(*(float64*)&t0, &env->fp_status);
531}