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 ---