]> git.proxmox.com Git - qemu.git/blob - target-sh4/op.c
687bded9593b3667cf63bed64cbbb7d327d3e3b9
[qemu.git] / target-sh4 / op.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 "exec.h"
21
22 static inline void set_t(void)
23 {
24 env->sr |= SR_T;
25 }
26
27 static inline void clr_t(void)
28 {
29 env->sr &= ~SR_T;
30 }
31
32 static inline void cond_t(int cond)
33 {
34 if (cond)
35 set_t();
36 else
37 clr_t();
38 }
39
40 void OPPROTO op_ldtlb(void)
41 {
42 helper_ldtlb();
43 RETURN();
44 }
45
46 void OPPROTO op_frchg(void)
47 {
48 env->fpscr ^= FPSCR_FR;
49 RETURN();
50 }
51
52 void OPPROTO op_fschg(void)
53 {
54 env->fpscr ^= FPSCR_SZ;
55 RETURN();
56 }
57
58 void OPPROTO op_addc_T0_T1(void)
59 {
60 helper_addc_T0_T1();
61 RETURN();
62 }
63
64 void OPPROTO op_addv_T0_T1(void)
65 {
66 helper_addv_T0_T1();
67 RETURN();
68 }
69
70 void OPPROTO op_cmp_str_T0_T1(void)
71 {
72 cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
73 (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
74 (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
75 (T0 & 0xff000000) == (T1 & 0xff000000));
76 RETURN();
77 }
78
79 void OPPROTO op_div0s_T0_T1(void)
80 {
81 if (T1 & 0x80000000)
82 env->sr |= SR_Q;
83 else
84 env->sr &= ~SR_Q;
85 if (T0 & 0x80000000)
86 env->sr |= SR_M;
87 else
88 env->sr &= ~SR_M;
89 cond_t((T1 ^ T0) & 0x80000000);
90 RETURN();
91 }
92
93 void OPPROTO op_div1_T0_T1(void)
94 {
95 helper_div1_T0_T1();
96 RETURN();
97 }
98
99 void OPPROTO op_dmulsl_T0_T1(void)
100 {
101 helper_dmulsl_T0_T1();
102 RETURN();
103 }
104
105 void OPPROTO op_dmulul_T0_T1(void)
106 {
107 helper_dmulul_T0_T1();
108 RETURN();
109 }
110
111 void OPPROTO op_macl_T0_T1(void)
112 {
113 helper_macl_T0_T1();
114 RETURN();
115 }
116
117 void OPPROTO op_macw_T0_T1(void)
118 {
119 helper_macw_T0_T1();
120 RETURN();
121 }
122
123 void OPPROTO op_mull_T0_T1(void)
124 {
125 env->macl = (T0 * T1) & 0xffffffff;
126 RETURN();
127 }
128
129 void OPPROTO op_mulsw_T0_T1(void)
130 {
131 env->macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1;
132 RETURN();
133 }
134
135 void OPPROTO op_muluw_T0_T1(void)
136 {
137 env->macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1;
138 RETURN();
139 }
140
141 void OPPROTO op_negc_T0(void)
142 {
143 helper_negc_T0();
144 RETURN();
145 }
146
147 void OPPROTO op_shad_T0_T1(void)
148 {
149 if ((T0 & 0x80000000) == 0)
150 T1 <<= (T0 & 0x1f);
151 else if ((T0 & 0x1f) == 0)
152 T1 = (T1 & 0x80000000)? 0xffffffff : 0;
153 else
154 T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
155 RETURN();
156 }
157
158 void OPPROTO op_shld_T0_T1(void)
159 {
160 if ((T0 & 0x80000000) == 0)
161 T1 <<= (T0 & 0x1f);
162 else if ((T0 & 0x1f) == 0)
163 T1 = 0;
164 else
165 T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
166 RETURN();
167 }
168
169 void OPPROTO op_subc_T0_T1(void)
170 {
171 helper_subc_T0_T1();
172 RETURN();
173 }
174
175 void OPPROTO op_subv_T0_T1(void)
176 {
177 helper_subv_T0_T1();
178 RETURN();
179 }
180
181 void OPPROTO op_trapa(void)
182 {
183 env->tra = PARAM1 << 2;
184 env->exception_index = 0x160;
185 do_raise_exception();
186 RETURN();
187 }
188
189 void OPPROTO op_ldcl_rMplus_rN_bank(void)
190 {
191 env->gregs[PARAM2] = env->gregs[PARAM1];
192 env->gregs[PARAM1] += 4;
193 RETURN();
194 }
195
196 void OPPROTO op_ldc_T0_sr(void)
197 {
198 env->sr = T0 & 0x700083f3;
199 RETURN();
200 }
201
202 void OPPROTO op_stc_sr_T0(void)
203 {
204 T0 = env->sr;
205 RETURN();
206 }
207
208 #define LDSTOPS(target,load,store) \
209 void OPPROTO op_##load##_T0_##target (void) \
210 { env ->target = T0; RETURN(); \
211 } \
212 void OPPROTO op_##store##_##target##_T0 (void) \
213 { T0 = env->target; RETURN(); \
214 } \
215
216 LDSTOPS(gbr, ldc, stc)
217 LDSTOPS(vbr, ldc, stc)
218 LDSTOPS(ssr, ldc, stc)
219 LDSTOPS(spc, ldc, stc)
220 LDSTOPS(sgr, ldc, stc)
221 LDSTOPS(dbr, ldc, stc)
222 LDSTOPS(mach, lds, sts)
223 LDSTOPS(macl, lds, sts)
224 LDSTOPS(pr, lds, sts)
225 LDSTOPS(fpul, lds, sts)
226
227 void OPPROTO op_lds_T0_fpscr(void)
228 {
229 env->fpscr = T0 & 0x003fffff;
230 env->fp_status.float_rounding_mode = T0 & 0x01 ?
231 float_round_to_zero : float_round_nearest_even;
232
233 RETURN();
234 }
235
236 void OPPROTO op_sts_fpscr_T0(void)
237 {
238 T0 = env->fpscr & 0x003fffff;
239 RETURN();
240 }
241
242 void OPPROTO op_rotcl_Rn(void)
243 {
244 helper_rotcl(&env->gregs[PARAM1]);
245 RETURN();
246 }
247
248 void OPPROTO op_rotcr_Rn(void)
249 {
250 helper_rotcr(&env->gregs[PARAM1]);
251 RETURN();
252 }
253
254 void OPPROTO op_rotl_Rn(void)
255 {
256 cond_t(env->gregs[PARAM1] & 0x80000000);
257 env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
258 RETURN();
259 }
260
261 void OPPROTO op_rotr_Rn(void)
262 {
263 cond_t(env->gregs[PARAM1] & 1);
264 env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
265 ((env->sr & SR_T) ? 0x80000000 : 0);
266 RETURN();
267 }
268
269 void OPPROTO op_shal_Rn(void)
270 {
271 cond_t(env->gregs[PARAM1] & 0x80000000);
272 env->gregs[PARAM1] <<= 1;
273 RETURN();
274 }
275
276 void OPPROTO op_shar_Rn(void)
277 {
278 cond_t(env->gregs[PARAM1] & 1);
279 *(int32_t *)&env->gregs[PARAM1] >>= 1;
280 RETURN();
281 }
282
283 void OPPROTO op_shlr_Rn(void)
284 {
285 cond_t(env->gregs[PARAM1] & 1);
286 env->gregs[PARAM1] >>= 1;
287 RETURN();
288 }
289
290 void OPPROTO op_fmov_frN_FT0(void)
291 {
292 FT0 = env->fregs[PARAM1];
293 RETURN();
294 }
295
296 void OPPROTO op_fmov_drN_DT0(void)
297 {
298 CPU_DoubleU d;
299
300 d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
301 d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
302 DT0 = d.d;
303 RETURN();
304 }
305
306 void OPPROTO op_fmov_frN_FT1(void)
307 {
308 FT1 = env->fregs[PARAM1];
309 RETURN();
310 }
311
312 void OPPROTO op_fmov_drN_DT1(void)
313 {
314 CPU_DoubleU d;
315
316 d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
317 d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
318 DT1 = d.d;
319 RETURN();
320 }
321
322 void OPPROTO op_fmov_FT0_frN(void)
323 {
324 env->fregs[PARAM1] = FT0;
325 RETURN();
326 }
327
328 void OPPROTO op_fmov_DT0_drN(void)
329 {
330 CPU_DoubleU d;
331
332 d.d = DT0;
333 *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
334 *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
335 RETURN();
336 }
337
338 void OPPROTO op_fadd_FT(void)
339 {
340 FT0 = float32_add(FT0, FT1, &env->fp_status);
341 RETURN();
342 }
343
344 void OPPROTO op_fadd_DT(void)
345 {
346 DT0 = float64_add(DT0, DT1, &env->fp_status);
347 RETURN();
348 }
349
350 void OPPROTO op_fsub_FT(void)
351 {
352 FT0 = float32_sub(FT0, FT1, &env->fp_status);
353 RETURN();
354 }
355
356 void OPPROTO op_fsub_DT(void)
357 {
358 DT0 = float64_sub(DT0, DT1, &env->fp_status);
359 RETURN();
360 }
361
362 void OPPROTO op_fmul_FT(void)
363 {
364 FT0 = float32_mul(FT0, FT1, &env->fp_status);
365 RETURN();
366 }
367
368 void OPPROTO op_fmul_DT(void)
369 {
370 DT0 = float64_mul(DT0, DT1, &env->fp_status);
371 RETURN();
372 }
373
374 void OPPROTO op_fdiv_FT(void)
375 {
376 FT0 = float32_div(FT0, FT1, &env->fp_status);
377 RETURN();
378 }
379
380 void OPPROTO op_fdiv_DT(void)
381 {
382 DT0 = float64_div(DT0, DT1, &env->fp_status);
383 RETURN();
384 }
385
386 void OPPROTO op_fcmp_eq_FT(void)
387 {
388 cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
389 RETURN();
390 }
391
392 void OPPROTO op_fcmp_eq_DT(void)
393 {
394 cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
395 RETURN();
396 }
397
398 void OPPROTO op_fcmp_gt_FT(void)
399 {
400 cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
401 RETURN();
402 }
403
404 void OPPROTO op_fcmp_gt_DT(void)
405 {
406 cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
407 RETURN();
408 }
409
410 void OPPROTO op_float_FT(void)
411 {
412 FT0 = int32_to_float32(env->fpul, &env->fp_status);
413 RETURN();
414 }
415
416 void OPPROTO op_float_DT(void)
417 {
418 DT0 = int32_to_float64(env->fpul, &env->fp_status);
419 RETURN();
420 }
421
422 void OPPROTO op_ftrc_FT(void)
423 {
424 env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
425 RETURN();
426 }
427
428 void OPPROTO op_ftrc_DT(void)
429 {
430 env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
431 RETURN();
432 }
433
434 void OPPROTO op_fneg_frN(void)
435 {
436 env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
437 RETURN();
438 }
439
440 void OPPROTO op_fabs_FT(void)
441 {
442 FT0 = float32_abs(FT0);
443 RETURN();
444 }
445
446 void OPPROTO op_fabs_DT(void)
447 {
448 DT0 = float64_abs(DT0);
449 RETURN();
450 }
451
452 void OPPROTO op_fcnvsd_FT_DT(void)
453 {
454 DT0 = float32_to_float64(FT0, &env->fp_status);
455 RETURN();
456 }
457
458 void OPPROTO op_fcnvds_DT_FT(void)
459 {
460 FT0 = float64_to_float32(DT0, &env->fp_status);
461 RETURN();
462 }
463
464 void OPPROTO op_fsqrt_FT(void)
465 {
466 FT0 = float32_sqrt(FT0, &env->fp_status);
467 RETURN();
468 }
469
470 void OPPROTO op_fsqrt_DT(void)
471 {
472 DT0 = float64_sqrt(DT0, &env->fp_status);
473 RETURN();
474 }
475
476 void OPPROTO op_fmov_T0_frN(void)
477 {
478 *(uint32_t *)&env->fregs[PARAM1] = T0;
479 RETURN();
480 }
481
482 void OPPROTO op_movl_fpul_FT0(void)
483 {
484 FT0 = *(float32 *)&env->fpul;
485 RETURN();
486 }
487
488 void OPPROTO op_movl_FT0_fpul(void)
489 {
490 *(float32 *)&env->fpul = FT0;
491 RETURN();
492 }
493
494 void OPPROTO op_raise_illegal_instruction(void)
495 {
496 env->exception_index = 0x180;
497 do_raise_exception();
498 RETURN();
499 }
500
501 void OPPROTO op_raise_slot_illegal_instruction(void)
502 {
503 env->exception_index = 0x1a0;
504 do_raise_exception();
505 RETURN();
506 }
507
508 void OPPROTO op_debug(void)
509 {
510 env->exception_index = EXCP_DEBUG;
511 cpu_loop_exit();
512 }
513
514 void OPPROTO op_sleep(void)
515 {
516 env->halted = 1;
517 env->exception_index = EXCP_HLT;
518 cpu_loop_exit();
519 }
520
521 /* Load and store */
522 #define MEMSUFFIX _raw
523 #include "op_mem.c"
524 #undef MEMSUFFIX
525 #if !defined(CONFIG_USER_ONLY)
526 #define MEMSUFFIX _user
527 #include "op_mem.c"
528 #undef MEMSUFFIX
529
530 #define MEMSUFFIX _kernel
531 #include "op_mem.c"
532 #undef MEMSUFFIX
533 #endif