Revision 4373f3ce target-arm/op.c
b/target-arm/op.c | ||
---|---|---|
252 | 252 |
FORCE_RET(); |
253 | 253 |
} |
254 | 254 |
|
255 |
/* VFP support. We follow the convention used for VFP instrunctions: |
|
256 |
Single precition routines have a "s" suffix, double precision a |
|
257 |
"d" suffix. */ |
|
258 |
|
|
259 |
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void) |
|
260 |
|
|
261 |
#define VFP_BINOP(name) \ |
|
262 |
VFP_OP(name, s) \ |
|
263 |
{ \ |
|
264 |
FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status); \ |
|
265 |
} \ |
|
266 |
VFP_OP(name, d) \ |
|
267 |
{ \ |
|
268 |
FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status); \ |
|
269 |
} |
|
270 |
VFP_BINOP(add) |
|
271 |
VFP_BINOP(sub) |
|
272 |
VFP_BINOP(mul) |
|
273 |
VFP_BINOP(div) |
|
274 |
#undef VFP_BINOP |
|
275 |
|
|
276 |
#define VFP_HELPER(name) \ |
|
277 |
VFP_OP(name, s) \ |
|
278 |
{ \ |
|
279 |
do_vfp_##name##s(); \ |
|
280 |
} \ |
|
281 |
VFP_OP(name, d) \ |
|
282 |
{ \ |
|
283 |
do_vfp_##name##d(); \ |
|
284 |
} |
|
285 |
VFP_HELPER(abs) |
|
286 |
VFP_HELPER(sqrt) |
|
287 |
VFP_HELPER(cmp) |
|
288 |
VFP_HELPER(cmpe) |
|
289 |
#undef VFP_HELPER |
|
290 |
|
|
291 |
/* XXX: Will this do the right thing for NANs. Should invert the signbit |
|
292 |
without looking at the rest of the value. */ |
|
293 |
VFP_OP(neg, s) |
|
294 |
{ |
|
295 |
FT0s = float32_chs(FT0s); |
|
296 |
} |
|
297 |
|
|
298 |
VFP_OP(neg, d) |
|
299 |
{ |
|
300 |
FT0d = float64_chs(FT0d); |
|
301 |
} |
|
302 |
|
|
303 |
VFP_OP(F1_ld0, s) |
|
304 |
{ |
|
305 |
union { |
|
306 |
uint32_t i; |
|
307 |
float32 s; |
|
308 |
} v; |
|
309 |
v.i = 0; |
|
310 |
FT1s = v.s; |
|
311 |
} |
|
312 |
|
|
313 |
VFP_OP(F1_ld0, d) |
|
314 |
{ |
|
315 |
union { |
|
316 |
uint64_t i; |
|
317 |
float64 d; |
|
318 |
} v; |
|
319 |
v.i = 0; |
|
320 |
FT1d = v.d; |
|
321 |
} |
|
322 |
|
|
323 |
/* Helper routines to perform bitwise copies between float and int. */ |
|
324 |
static inline float32 vfp_itos(uint32_t i) |
|
325 |
{ |
|
326 |
union { |
|
327 |
uint32_t i; |
|
328 |
float32 s; |
|
329 |
} v; |
|
330 |
|
|
331 |
v.i = i; |
|
332 |
return v.s; |
|
333 |
} |
|
334 |
|
|
335 |
static inline uint32_t vfp_stoi(float32 s) |
|
336 |
{ |
|
337 |
union { |
|
338 |
uint32_t i; |
|
339 |
float32 s; |
|
340 |
} v; |
|
341 |
|
|
342 |
v.s = s; |
|
343 |
return v.i; |
|
344 |
} |
|
345 |
|
|
346 |
static inline float64 vfp_itod(uint64_t i) |
|
347 |
{ |
|
348 |
union { |
|
349 |
uint64_t i; |
|
350 |
float64 d; |
|
351 |
} v; |
|
352 |
|
|
353 |
v.i = i; |
|
354 |
return v.d; |
|
355 |
} |
|
356 |
|
|
357 |
static inline uint64_t vfp_dtoi(float64 d) |
|
358 |
{ |
|
359 |
union { |
|
360 |
uint64_t i; |
|
361 |
float64 d; |
|
362 |
} v; |
|
363 |
|
|
364 |
v.d = d; |
|
365 |
return v.i; |
|
366 |
} |
|
367 |
|
|
368 |
/* Integer to float conversion. */ |
|
369 |
VFP_OP(uito, s) |
|
370 |
{ |
|
371 |
FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); |
|
372 |
} |
|
373 |
|
|
374 |
VFP_OP(uito, d) |
|
375 |
{ |
|
376 |
FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); |
|
377 |
} |
|
378 |
|
|
379 |
VFP_OP(sito, s) |
|
380 |
{ |
|
381 |
FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); |
|
382 |
} |
|
383 |
|
|
384 |
VFP_OP(sito, d) |
|
385 |
{ |
|
386 |
FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); |
|
387 |
} |
|
388 |
|
|
389 |
/* Float to integer conversion. */ |
|
390 |
VFP_OP(toui, s) |
|
391 |
{ |
|
392 |
FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status)); |
|
393 |
} |
|
394 |
|
|
395 |
VFP_OP(toui, d) |
|
396 |
{ |
|
397 |
FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status)); |
|
398 |
} |
|
399 |
|
|
400 |
VFP_OP(tosi, s) |
|
401 |
{ |
|
402 |
FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status)); |
|
403 |
} |
|
404 |
|
|
405 |
VFP_OP(tosi, d) |
|
406 |
{ |
|
407 |
FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status)); |
|
408 |
} |
|
409 |
|
|
410 |
/* TODO: Set rounding mode properly. */ |
|
411 |
VFP_OP(touiz, s) |
|
412 |
{ |
|
413 |
FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status)); |
|
414 |
} |
|
415 |
|
|
416 |
VFP_OP(touiz, d) |
|
417 |
{ |
|
418 |
FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status)); |
|
419 |
} |
|
420 |
|
|
421 |
VFP_OP(tosiz, s) |
|
422 |
{ |
|
423 |
FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status)); |
|
424 |
} |
|
425 |
|
|
426 |
VFP_OP(tosiz, d) |
|
427 |
{ |
|
428 |
FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status)); |
|
429 |
} |
|
430 |
|
|
431 |
/* floating point conversion */ |
|
432 |
VFP_OP(fcvtd, s) |
|
433 |
{ |
|
434 |
FT0d = float32_to_float64(FT0s, &env->vfp.fp_status); |
|
435 |
} |
|
436 |
|
|
437 |
VFP_OP(fcvts, d) |
|
438 |
{ |
|
439 |
FT0s = float64_to_float32(FT0d, &env->vfp.fp_status); |
|
440 |
} |
|
441 |
|
|
442 |
/* VFP3 fixed point conversion. */ |
|
443 |
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \ |
|
444 |
VFP_OP(name##to, p) \ |
|
445 |
{ \ |
|
446 |
ftype tmp; \ |
|
447 |
tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(FT0##p), \ |
|
448 |
&env->vfp.fp_status); \ |
|
449 |
FT0##p = ftype##_scalbn(tmp, PARAM1, &env->vfp.fp_status); \ |
|
450 |
} \ |
|
451 |
VFP_OP(to##name, p) \ |
|
452 |
{ \ |
|
453 |
ftype tmp; \ |
|
454 |
tmp = ftype##_scalbn(FT0##p, PARAM1, &env->vfp.fp_status); \ |
|
455 |
FT0##p = vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \ |
|
456 |
&env->vfp.fp_status)); \ |
|
457 |
} |
|
458 |
|
|
459 |
VFP_CONV_FIX(sh, d, float64, int16, ) |
|
460 |
VFP_CONV_FIX(sl, d, float64, int32, ) |
|
461 |
VFP_CONV_FIX(uh, d, float64, uint16, u) |
|
462 |
VFP_CONV_FIX(ul, d, float64, uint32, u) |
|
463 |
VFP_CONV_FIX(sh, s, float32, int16, ) |
|
464 |
VFP_CONV_FIX(sl, s, float32, int32, ) |
|
465 |
VFP_CONV_FIX(uh, s, float32, uint16, u) |
|
466 |
VFP_CONV_FIX(ul, s, float32, uint32, u) |
|
467 |
|
|
468 |
/* Get and Put values from registers. */ |
|
469 |
VFP_OP(getreg_F0, d) |
|
470 |
{ |
|
471 |
FT0d = *(float64 *)((char *) env + PARAM1); |
|
472 |
} |
|
473 |
|
|
474 |
VFP_OP(getreg_F0, s) |
|
475 |
{ |
|
476 |
FT0s = *(float32 *)((char *) env + PARAM1); |
|
477 |
} |
|
478 |
|
|
479 |
VFP_OP(getreg_F1, d) |
|
480 |
{ |
|
481 |
FT1d = *(float64 *)((char *) env + PARAM1); |
|
482 |
} |
|
483 |
|
|
484 |
VFP_OP(getreg_F1, s) |
|
485 |
{ |
|
486 |
FT1s = *(float32 *)((char *) env + PARAM1); |
|
487 |
} |
|
488 |
|
|
489 |
VFP_OP(setreg_F0, d) |
|
490 |
{ |
|
491 |
*(float64 *)((char *) env + PARAM1) = FT0d; |
|
492 |
} |
|
493 |
|
|
494 |
VFP_OP(setreg_F0, s) |
|
495 |
{ |
|
496 |
*(float32 *)((char *) env + PARAM1) = FT0s; |
|
497 |
} |
|
498 |
|
|
499 |
void OPPROTO op_vfp_movl_T0_fpscr(void) |
|
500 |
{ |
|
501 |
do_vfp_get_fpscr (); |
|
502 |
} |
|
503 |
|
|
504 |
void OPPROTO op_vfp_movl_T0_fpscr_flags(void) |
|
505 |
{ |
|
506 |
T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28); |
|
507 |
} |
|
508 |
|
|
509 |
void OPPROTO op_vfp_movl_fpscr_T0(void) |
|
510 |
{ |
|
511 |
do_vfp_set_fpscr(); |
|
512 |
} |
|
513 |
|
|
514 |
void OPPROTO op_vfp_movl_T0_xreg(void) |
|
515 |
{ |
|
516 |
T0 = env->vfp.xregs[PARAM1]; |
|
517 |
} |
|
518 |
|
|
519 |
void OPPROTO op_vfp_movl_xreg_T0(void) |
|
520 |
{ |
|
521 |
env->vfp.xregs[PARAM1] = T0; |
|
522 |
} |
|
523 |
|
|
524 |
/* Move between FT0s to T0 */ |
|
525 |
void OPPROTO op_vfp_mrs(void) |
|
526 |
{ |
|
527 |
T0 = vfp_stoi(FT0s); |
|
528 |
} |
|
529 |
|
|
530 |
void OPPROTO op_vfp_msr(void) |
|
531 |
{ |
|
532 |
FT0s = vfp_itos(T0); |
|
533 |
} |
|
534 |
|
|
535 |
/* Move between FT0d and {T0,T1} */ |
|
536 |
void OPPROTO op_vfp_mrrd(void) |
|
537 |
{ |
|
538 |
CPU_DoubleU u; |
|
539 |
|
|
540 |
u.d = FT0d; |
|
541 |
T0 = u.l.lower; |
|
542 |
T1 = u.l.upper; |
|
543 |
} |
|
544 |
|
|
545 |
void OPPROTO op_vfp_mdrr(void) |
|
546 |
{ |
|
547 |
CPU_DoubleU u; |
|
548 |
|
|
549 |
u.l.lower = T0; |
|
550 |
u.l.upper = T1; |
|
551 |
FT0d = u.d; |
|
552 |
} |
|
553 |
|
|
554 |
/* Load immediate. PARAM1 is the 32 most significant bits of the value. */ |
|
555 |
void OPPROTO op_vfp_fconstd(void) |
|
556 |
{ |
|
557 |
CPU_DoubleU u; |
|
558 |
u.l.upper = PARAM1; |
|
559 |
u.l.lower = 0; |
|
560 |
FT0d = u.d; |
|
561 |
} |
|
562 |
|
|
563 |
void OPPROTO op_vfp_fconsts(void) |
|
564 |
{ |
|
565 |
FT0s = vfp_itos(PARAM1); |
|
566 |
} |
|
567 |
|
|
568 | 255 |
void OPPROTO op_movl_cp_T0(void) |
569 | 256 |
{ |
570 | 257 |
helper_set_cp(env, PARAM1, T0); |
Also available in: Unified diff