translate.c (0d89cb7c29d9030d96c32ea4cdde7b4ee6f3dcf4) | translate.c (4c42fd0d4e543aaf8981c737f971d27e7c9d4df0) |
---|---|
1/* 2 * HPPA emulation cpu translation for qemu. 3 * 4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> 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 --- 331 unchanged lines hidden (view full) --- 340{ 341 return (DisasCond){ 342 .c = TCG_COND_NE, 343 .a0 = cpu_psw_n, 344 .a1 = tcg_constant_i64(0) 345 }; 346} 347 | 1/* 2 * HPPA emulation cpu translation for qemu. 3 * 4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> 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 --- 331 unchanged lines hidden (view full) --- 340{ 341 return (DisasCond){ 342 .c = TCG_COND_NE, 343 .a0 = cpu_psw_n, 344 .a1 = tcg_constant_i64(0) 345 }; 346} 347 |
348static DisasCond cond_make_tmp(TCGCond c, TCGv_i64 a0, TCGv_i64 a1) | 348static DisasCond cond_make_tt(TCGCond c, TCGv_i64 a0, TCGv_i64 a1) |
349{ 350 assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); 351 return (DisasCond){ .c = c, .a0 = a0, .a1 = a1 }; 352} 353 | 349{ 350 assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); 351 return (DisasCond){ .c = c, .a0 = a0, .a1 = a1 }; 352} 353 |
354static DisasCond cond_make_0_tmp(TCGCond c, TCGv_i64 a0) | 354static DisasCond cond_make_ti(TCGCond c, TCGv_i64 a0, uint64_t imm) |
355{ | 355{ |
356 return cond_make_tmp(c, a0, tcg_constant_i64(0)); | 356 return cond_make_tt(c, a0, tcg_constant_i64(imm)); |
357} 358 | 357} 358 |
359static DisasCond cond_make_0(TCGCond c, TCGv_i64 a0) | 359static DisasCond cond_make_vi(TCGCond c, TCGv_i64 a0, uint64_t imm) |
360{ 361 TCGv_i64 tmp = tcg_temp_new_i64(); 362 tcg_gen_mov_i64(tmp, a0); | 360{ 361 TCGv_i64 tmp = tcg_temp_new_i64(); 362 tcg_gen_mov_i64(tmp, a0); |
363 return cond_make_0_tmp(c, tmp); | 363 return cond_make_ti(c, tmp, imm); |
364} 365 | 364} 365 |
366static DisasCond cond_make(TCGCond c, TCGv_i64 a0, TCGv_i64 a1) | 366static DisasCond cond_make_vv(TCGCond c, TCGv_i64 a0, TCGv_i64 a1) |
367{ 368 TCGv_i64 t0 = tcg_temp_new_i64(); 369 TCGv_i64 t1 = tcg_temp_new_i64(); 370 371 tcg_gen_mov_i64(t0, a0); 372 tcg_gen_mov_i64(t1, a1); | 367{ 368 TCGv_i64 t0 = tcg_temp_new_i64(); 369 TCGv_i64 t1 = tcg_temp_new_i64(); 370 371 tcg_gen_mov_i64(t0, a0); 372 tcg_gen_mov_i64(t1, a1); |
373 return cond_make_tmp(c, t0, t1); | 373 return cond_make_tt(c, t0, t1); |
374} 375 376static void cond_free(DisasCond *cond) 377{ 378 switch (cond->c) { 379 default: 380 cond->a0 = NULL; 381 cond->a1 = NULL; --- 402 unchanged lines hidden (view full) --- 784 cond = cond_make_f(); 785 break; 786 case 1: /* = / <> (Z / !Z) */ 787 if (!d) { 788 tmp = tcg_temp_new_i64(); 789 tcg_gen_ext32u_i64(tmp, res); 790 res = tmp; 791 } | 374} 375 376static void cond_free(DisasCond *cond) 377{ 378 switch (cond->c) { 379 default: 380 cond->a0 = NULL; 381 cond->a1 = NULL; --- 402 unchanged lines hidden (view full) --- 784 cond = cond_make_f(); 785 break; 786 case 1: /* = / <> (Z / !Z) */ 787 if (!d) { 788 tmp = tcg_temp_new_i64(); 789 tcg_gen_ext32u_i64(tmp, res); 790 res = tmp; 791 } |
792 cond = cond_make_0(TCG_COND_EQ, res); | 792 cond = cond_make_vi(TCG_COND_EQ, res, 0); |
793 break; 794 case 2: /* < / >= (N ^ V / !(N ^ V) */ 795 tmp = tcg_temp_new_i64(); 796 tcg_gen_xor_i64(tmp, res, sv); 797 if (!d) { 798 tcg_gen_ext32s_i64(tmp, tmp); 799 } | 793 break; 794 case 2: /* < / >= (N ^ V / !(N ^ V) */ 795 tmp = tcg_temp_new_i64(); 796 tcg_gen_xor_i64(tmp, res, sv); 797 if (!d) { 798 tcg_gen_ext32s_i64(tmp, tmp); 799 } |
800 cond = cond_make_0_tmp(TCG_COND_LT, tmp); | 800 cond = cond_make_ti(TCG_COND_LT, tmp, 0); |
801 break; 802 case 3: /* <= / > (N ^ V) | Z / !((N ^ V) | Z) */ 803 /* 804 * Simplify: 805 * (N ^ V) | Z 806 * ((res < 0) ^ (sv < 0)) | !res 807 * ((res ^ sv) < 0) | !res 808 * (~(res ^ sv) >= 0) | !res --- 5 unchanged lines hidden (view full) --- 814 if (!d) { 815 tcg_gen_sextract_i64(tmp, tmp, 31, 1); 816 tcg_gen_and_i64(tmp, tmp, res); 817 tcg_gen_ext32u_i64(tmp, tmp); 818 } else { 819 tcg_gen_sari_i64(tmp, tmp, 63); 820 tcg_gen_and_i64(tmp, tmp, res); 821 } | 801 break; 802 case 3: /* <= / > (N ^ V) | Z / !((N ^ V) | Z) */ 803 /* 804 * Simplify: 805 * (N ^ V) | Z 806 * ((res < 0) ^ (sv < 0)) | !res 807 * ((res ^ sv) < 0) | !res 808 * (~(res ^ sv) >= 0) | !res --- 5 unchanged lines hidden (view full) --- 814 if (!d) { 815 tcg_gen_sextract_i64(tmp, tmp, 31, 1); 816 tcg_gen_and_i64(tmp, tmp, res); 817 tcg_gen_ext32u_i64(tmp, tmp); 818 } else { 819 tcg_gen_sari_i64(tmp, tmp, 63); 820 tcg_gen_and_i64(tmp, tmp, res); 821 } |
822 cond = cond_make_0_tmp(TCG_COND_EQ, tmp); | 822 cond = cond_make_ti(TCG_COND_EQ, tmp, 0); |
823 break; 824 case 4: /* NUV / UV (!UV / UV) */ | 823 break; 824 case 4: /* NUV / UV (!UV / UV) */ |
825 cond = cond_make_0(TCG_COND_EQ, uv); | 825 cond = cond_make_vi(TCG_COND_EQ, uv, 0); |
826 break; 827 case 5: /* ZNV / VNZ (!UV | Z / UV & !Z) */ 828 tmp = tcg_temp_new_i64(); 829 tcg_gen_movcond_i64(TCG_COND_EQ, tmp, uv, ctx->zero, ctx->zero, res); 830 if (!d) { 831 tcg_gen_ext32u_i64(tmp, tmp); 832 } | 826 break; 827 case 5: /* ZNV / VNZ (!UV | Z / UV & !Z) */ 828 tmp = tcg_temp_new_i64(); 829 tcg_gen_movcond_i64(TCG_COND_EQ, tmp, uv, ctx->zero, ctx->zero, res); 830 if (!d) { 831 tcg_gen_ext32u_i64(tmp, tmp); 832 } |
833 cond = cond_make_0_tmp(TCG_COND_EQ, tmp); | 833 cond = cond_make_ti(TCG_COND_EQ, tmp, 0); |
834 break; 835 case 6: /* SV / NSV (V / !V) */ 836 if (!d) { 837 tmp = tcg_temp_new_i64(); 838 tcg_gen_ext32s_i64(tmp, sv); 839 sv = tmp; 840 } | 834 break; 835 case 6: /* SV / NSV (V / !V) */ 836 if (!d) { 837 tmp = tcg_temp_new_i64(); 838 tcg_gen_ext32s_i64(tmp, sv); 839 sv = tmp; 840 } |
841 cond = cond_make_0(TCG_COND_LT, sv); | 841 cond = cond_make_ti(TCG_COND_LT, sv, 0); |
842 break; 843 case 7: /* OD / EV */ 844 tmp = tcg_temp_new_i64(); 845 tcg_gen_andi_i64(tmp, res, 1); | 842 break; 843 case 7: /* OD / EV */ 844 tmp = tcg_temp_new_i64(); 845 tcg_gen_andi_i64(tmp, res, 1); |
846 cond = cond_make_0_tmp(TCG_COND_NE, tmp); | 846 cond = cond_make_ti(TCG_COND_NE, tmp, 0); |
847 break; 848 default: 849 g_assert_not_reached(); 850 } 851 if (cf & 1) { 852 cond.c = tcg_invert_cond(cond.c); 853 } 854 --- 45 unchanged lines hidden (view full) --- 900 901 if (ext_uns) { 902 tcg_gen_ext32u_i64(t1, in1); 903 tcg_gen_ext32u_i64(t2, in2); 904 } else { 905 tcg_gen_ext32s_i64(t1, in1); 906 tcg_gen_ext32s_i64(t2, in2); 907 } | 847 break; 848 default: 849 g_assert_not_reached(); 850 } 851 if (cf & 1) { 852 cond.c = tcg_invert_cond(cond.c); 853 } 854 --- 45 unchanged lines hidden (view full) --- 900 901 if (ext_uns) { 902 tcg_gen_ext32u_i64(t1, in1); 903 tcg_gen_ext32u_i64(t2, in2); 904 } else { 905 tcg_gen_ext32s_i64(t1, in1); 906 tcg_gen_ext32s_i64(t2, in2); 907 } |
908 return cond_make_tmp(tc, t1, t2); | 908 return cond_make_tt(tc, t1, t2); |
909 } | 909 } |
910 return cond_make(tc, in1, in2); | 910 return cond_make_vv(tc, in1, in2); |
911} 912 913/* 914 * Similar, but for logicals, where the carry and overflow bits are not 915 * computed, and use of them is undefined. 916 * 917 * Undefined or not, hardware does not trap. It seems reasonable to 918 * assume hardware treats cases c={4,5,6} as if C=0 & V=0, since that's --- 55 unchanged lines hidden (view full) --- 974 if (!d) { 975 TCGv_i64 tmp = tcg_temp_new_i64(); 976 977 if (ext_uns) { 978 tcg_gen_ext32u_i64(tmp, res); 979 } else { 980 tcg_gen_ext32s_i64(tmp, res); 981 } | 911} 912 913/* 914 * Similar, but for logicals, where the carry and overflow bits are not 915 * computed, and use of them is undefined. 916 * 917 * Undefined or not, hardware does not trap. It seems reasonable to 918 * assume hardware treats cases c={4,5,6} as if C=0 & V=0, since that's --- 55 unchanged lines hidden (view full) --- 974 if (!d) { 975 TCGv_i64 tmp = tcg_temp_new_i64(); 976 977 if (ext_uns) { 978 tcg_gen_ext32u_i64(tmp, res); 979 } else { 980 tcg_gen_ext32s_i64(tmp, res); 981 } |
982 return cond_make_0_tmp(tc, tmp); | 982 return cond_make_ti(tc, tmp, 0); |
983 } | 983 } |
984 return cond_make_0(tc, res); | 984 return cond_make_vi(tc, res, 0); |
985} 986 987/* Similar, but for shift/extract/deposit conditions. */ 988 989static DisasCond do_sed_cond(DisasContext *ctx, unsigned orig, bool d, 990 TCGv_i64 res) 991{ 992 unsigned c, f; --- 42 unchanged lines hidden (view full) --- 1035 * See hasless(v,1) from 1036 * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord 1037 */ 1038 tmp = tcg_temp_new_i64(); 1039 tcg_gen_subi_i64(tmp, res, ones); 1040 tcg_gen_andc_i64(tmp, tmp, res); 1041 tcg_gen_andi_i64(tmp, tmp, sgns); 1042 | 985} 986 987/* Similar, but for shift/extract/deposit conditions. */ 988 989static DisasCond do_sed_cond(DisasContext *ctx, unsigned orig, bool d, 990 TCGv_i64 res) 991{ 992 unsigned c, f; --- 42 unchanged lines hidden (view full) --- 1035 * See hasless(v,1) from 1036 * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord 1037 */ 1038 tmp = tcg_temp_new_i64(); 1039 tcg_gen_subi_i64(tmp, res, ones); 1040 tcg_gen_andc_i64(tmp, tmp, res); 1041 tcg_gen_andi_i64(tmp, tmp, sgns); 1042 |
1043 return cond_make_0_tmp(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp); | 1043 return cond_make_ti(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp, 0); |
1044} 1045 1046static TCGv_i64 get_carry(DisasContext *ctx, bool d, 1047 TCGv_i64 cb, TCGv_i64 cb_msb) 1048{ 1049 if (!d) { 1050 TCGv_i64 t = tcg_temp_new_i64(); 1051 tcg_gen_extract_i64(t, cb, 32, 1); --- 397 unchanged lines hidden (view full) --- 1449 tcg_gen_sub_i64(dest, in1, in2); 1450 tcg_gen_eqv_i64(cb, in1, in2); 1451 } 1452 tcg_gen_xor_i64(cb, cb, dest); 1453 tcg_gen_shri_i64(cb, cb, 1); 1454 } 1455 1456 tcg_gen_andi_i64(cb, cb, test_cb); | 1044} 1045 1046static TCGv_i64 get_carry(DisasContext *ctx, bool d, 1047 TCGv_i64 cb, TCGv_i64 cb_msb) 1048{ 1049 if (!d) { 1050 TCGv_i64 t = tcg_temp_new_i64(); 1051 tcg_gen_extract_i64(t, cb, 32, 1); --- 397 unchanged lines hidden (view full) --- 1449 tcg_gen_sub_i64(dest, in1, in2); 1450 tcg_gen_eqv_i64(cb, in1, in2); 1451 } 1452 tcg_gen_xor_i64(cb, cb, dest); 1453 tcg_gen_shri_i64(cb, cb, 1); 1454 } 1455 1456 tcg_gen_andi_i64(cb, cb, test_cb); |
1457 cond = cond_make_0_tmp(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, cb); | 1457 cond = cond_make_ti(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, cb, 0); |
1458 } 1459 1460 if (is_tc) { 1461 TCGv_i64 tmp = tcg_temp_new_i64(); 1462 tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1); 1463 gen_helper_tcond(tcg_env, tmp); 1464 } 1465 save_gpr(ctx, rt, dest); --- 2072 unchanged lines hidden (view full) --- 3538 if (a->d) { 3539 tcg_gen_shl_i64(tmp, tcg_r, cpu_sar); 3540 } else { 3541 /* Force shift into [32,63] */ 3542 tcg_gen_ori_i64(tmp, cpu_sar, 32); 3543 tcg_gen_shl_i64(tmp, tcg_r, tmp); 3544 } 3545 | 1458 } 1459 1460 if (is_tc) { 1461 TCGv_i64 tmp = tcg_temp_new_i64(); 1462 tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1); 1463 gen_helper_tcond(tcg_env, tmp); 1464 } 1465 save_gpr(ctx, rt, dest); --- 2072 unchanged lines hidden (view full) --- 3538 if (a->d) { 3539 tcg_gen_shl_i64(tmp, tcg_r, cpu_sar); 3540 } else { 3541 /* Force shift into [32,63] */ 3542 tcg_gen_ori_i64(tmp, cpu_sar, 32); 3543 tcg_gen_shl_i64(tmp, tcg_r, tmp); 3544 } 3545 |
3546 cond = cond_make_0_tmp(a->c ? TCG_COND_GE : TCG_COND_LT, tmp); | 3546 cond = cond_make_ti(a->c ? TCG_COND_GE : TCG_COND_LT, tmp, 0); |
3547 return do_cbranch(ctx, a->disp, a->n, &cond); 3548} 3549 3550static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a) 3551{ 3552 TCGv_i64 tmp, tcg_r; 3553 DisasCond cond; 3554 int p; 3555 3556 nullify_over(ctx); 3557 3558 tmp = tcg_temp_new_i64(); 3559 tcg_r = load_gpr(ctx, a->r); 3560 p = a->p | (a->d ? 0 : 32); 3561 tcg_gen_shli_i64(tmp, tcg_r, p); 3562 | 3547 return do_cbranch(ctx, a->disp, a->n, &cond); 3548} 3549 3550static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a) 3551{ 3552 TCGv_i64 tmp, tcg_r; 3553 DisasCond cond; 3554 int p; 3555 3556 nullify_over(ctx); 3557 3558 tmp = tcg_temp_new_i64(); 3559 tcg_r = load_gpr(ctx, a->r); 3560 p = a->p | (a->d ? 0 : 32); 3561 tcg_gen_shli_i64(tmp, tcg_r, p); 3562 |
3563 cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp); | 3563 cond = cond_make_ti(a->c ? TCG_COND_GE : TCG_COND_LT, tmp, 0); |
3564 return do_cbranch(ctx, a->disp, a->n, &cond); 3565} 3566 3567static bool trans_movb(DisasContext *ctx, arg_movb *a) 3568{ 3569 TCGv_i64 dest; 3570 DisasCond cond; 3571 --- 787 unchanged lines hidden (view full) --- 4359 4360 if (a->y == 1) { 4361 int mask; 4362 bool inv = false; 4363 4364 switch (a->c) { 4365 case 0: /* simple */ 4366 tcg_gen_andi_i64(t, t, 0x4000000); | 3564 return do_cbranch(ctx, a->disp, a->n, &cond); 3565} 3566 3567static bool trans_movb(DisasContext *ctx, arg_movb *a) 3568{ 3569 TCGv_i64 dest; 3570 DisasCond cond; 3571 --- 787 unchanged lines hidden (view full) --- 4359 4360 if (a->y == 1) { 4361 int mask; 4362 bool inv = false; 4363 4364 switch (a->c) { 4365 case 0: /* simple */ 4366 tcg_gen_andi_i64(t, t, 0x4000000); |
4367 ctx->null_cond = cond_make_0(TCG_COND_NE, t); | 4367 ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0); |
4368 goto done; 4369 case 2: /* rej */ 4370 inv = true; 4371 /* fallthru */ 4372 case 1: /* acc */ 4373 mask = 0x43ff800; 4374 break; 4375 case 6: /* rej8 */ --- 13 unchanged lines hidden (view full) --- 4389 break; 4390 default: 4391 gen_illegal(ctx); 4392 return true; 4393 } 4394 if (inv) { 4395 TCGv_i64 c = tcg_constant_i64(mask); 4396 tcg_gen_or_i64(t, t, c); | 4368 goto done; 4369 case 2: /* rej */ 4370 inv = true; 4371 /* fallthru */ 4372 case 1: /* acc */ 4373 mask = 0x43ff800; 4374 break; 4375 case 6: /* rej8 */ --- 13 unchanged lines hidden (view full) --- 4389 break; 4390 default: 4391 gen_illegal(ctx); 4392 return true; 4393 } 4394 if (inv) { 4395 TCGv_i64 c = tcg_constant_i64(mask); 4396 tcg_gen_or_i64(t, t, c); |
4397 ctx->null_cond = cond_make(TCG_COND_EQ, t, c); | 4397 ctx->null_cond = cond_make_tt(TCG_COND_EQ, t, c); |
4398 } else { 4399 tcg_gen_andi_i64(t, t, mask); | 4398 } else { 4399 tcg_gen_andi_i64(t, t, mask); |
4400 ctx->null_cond = cond_make_0(TCG_COND_EQ, t); | 4400 ctx->null_cond = cond_make_ti(TCG_COND_EQ, t, 0); |
4401 } 4402 } else { 4403 unsigned cbit = (a->y ^ 1) - 1; 4404 4405 tcg_gen_extract_i64(t, t, 21 - cbit, 1); | 4401 } 4402 } else { 4403 unsigned cbit = (a->y ^ 1) - 1; 4404 4405 tcg_gen_extract_i64(t, t, 21 - cbit, 1); |
4406 ctx->null_cond = cond_make_0(TCG_COND_NE, t); | 4406 ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0); |
4407 } 4408 4409 done: 4410 return nullify_end(ctx); 4411} 4412 4413/* 4414 * Float class 2 --- 427 unchanged lines hidden --- | 4407 } 4408 4409 done: 4410 return nullify_end(ctx); 4411} 4412 4413/* 4414 * Float class 2 --- 427 unchanged lines hidden --- |