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