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