Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- tcg/tci.c | 54 ++++++++++++++++++++++++++++ tcg/tci/tcg-target-opc.h.inc | 1 + tcg/tci/tcg-target.c.inc | 69 +++++++++++++++++++++++++++++++----- 3 files changed, 116 insertions(+), 8 deletions(-)
diff --git a/tcg/tci.c b/tcg/tci.c index dc916eb112..d65ff2b8f1 100644 --- a/tcg/tci.c +++ b/tcg/tci.c @@ -361,6 +361,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tcg_target_ulong regs[TCG_TARGET_NB_REGS]; uint64_t stack[(TCG_STATIC_CALL_ARGS_SIZE + TCG_STATIC_FRAME_SIZE) / sizeof(uint64_t)]; + bool carry = false; regs[TCG_AREG0] = (tcg_target_ulong)env; regs[TCG_REG_CALL_STACK] = (uintptr_t)stack; @@ -471,6 +472,9 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tci_args_rl(insn, tb_ptr, &r0, &ptr); regs[r0] = *(tcg_target_ulong *)ptr; break; + case INDEX_op_tci_setcarry: + carry = true; + break; /* Load/store operations (32 bit). */ @@ -575,6 +579,46 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, tci_args_rr(insn, &r0, &r1); regs[r0] = ctpop_tr(regs[r1]); break; + case INDEX_op_addco: + tci_args_rrr(insn, &r0, &r1, &r2); + t1 = regs[r1] + regs[r2]; + carry = t1 < regs[r1]; + regs[r0] = t1; + break; + case INDEX_op_addci: + tci_args_rrr(insn, &r0, &r1, &r2); + regs[r0] = regs[r1] + regs[r2] + carry; + break; + case INDEX_op_addcio: + tci_args_rrr(insn, &r0, &r1, &r2); + if (carry) { + t1 = regs[r1] + regs[r2] + 1; + carry = t1 <= regs[r1]; + } else { + t1 = regs[r1] + regs[r2]; + carry = t1 < regs[r1]; + } + regs[r0] = t1; + break; + case INDEX_op_subbo: + tci_args_rrr(insn, &r0, &r1, &r2); + carry = regs[r1] < regs[r2]; + regs[r0] = regs[r1] - regs[r2]; + break; + case INDEX_op_subbi: + tci_args_rrr(insn, &r0, &r1, &r2); + regs[r0] = regs[r1] - regs[r2] - carry; + break; + case INDEX_op_subbio: + tci_args_rrr(insn, &r0, &r1, &r2); + if (carry) { + carry = regs[r1] <= regs[r2]; + regs[r0] = regs[r1] - regs[r2] - 1; + } else { + carry = regs[r1] < regs[r2]; + regs[r0] = regs[r1] - regs[r2]; + } + break; case INDEX_op_muls2: tci_args_rrrr(insn, &r0, &r1, &r2, &r3); #if TCG_TARGET_REG_BITS == 32 @@ -968,6 +1012,10 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info) op_name, str_r(r0), ptr); break; + case INDEX_op_tci_setcarry: + info->fprintf_func(info->stream, "%-12s", op_name); + break; + case INDEX_op_ld8u_i32: case INDEX_op_ld8u_i64: case INDEX_op_ld8s_i32: @@ -1007,6 +1055,9 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info) break; case INDEX_op_add: + case INDEX_op_addci: + case INDEX_op_addcio: + case INDEX_op_addco: case INDEX_op_and: case INDEX_op_andc: case INDEX_op_clz: @@ -1027,6 +1078,9 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info) case INDEX_op_shl: case INDEX_op_shr: case INDEX_op_sub: + case INDEX_op_subbi: + case INDEX_op_subbio: + case INDEX_op_subbo: case INDEX_op_xor: case INDEX_op_tci_ctz32: case INDEX_op_tci_clz32: diff --git a/tcg/tci/tcg-target-opc.h.inc b/tcg/tci/tcg-target-opc.h.inc index 672d9b7323..4eb32ed736 100644 --- a/tcg/tci/tcg-target-opc.h.inc +++ b/tcg/tci/tcg-target-opc.h.inc @@ -2,6 +2,7 @@ /* These opcodes for use between the tci generator and interpreter. */ DEF(tci_movi, 1, 0, 1, TCG_OPF_NOT_PRESENT) DEF(tci_movl, 1, 0, 1, TCG_OPF_NOT_PRESENT) +DEF(tci_setcarry, 0, 0, 0, TCG_OPF_NOT_PRESENT) DEF(tci_clz32, 1, 2, 0, TCG_OPF_NOT_PRESENT) DEF(tci_ctz32, 1, 2, 0, TCG_OPF_NOT_PRESENT) DEF(tci_divs32, 1, 2, 0, TCG_OPF_NOT_PRESENT) diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc index bba96d7a19..947aa1aada 100644 --- a/tcg/tci/tcg-target.c.inc +++ b/tcg/tci/tcg-target.c.inc @@ -573,21 +573,50 @@ static const TCGOutOpBinary outop_add = { .out_rrr = tgen_add, }; +static TCGConstraintSetIndex cset_addsubcarry(TCGType type, unsigned flags) +{ + return type == TCG_TYPE_REG ? C_O1_I2(r, r, r) : C_NotImplemented; +} + +static void tgen_addco(TCGContext *s, TCGType type, + TCGReg a0, TCGReg a1, TCGReg a2) +{ + tcg_out_op_rrr(s, INDEX_op_addco, a0, a1, a2); +} + static const TCGOutOpBinary outop_addco = { - .base.static_constraint = C_NotImplemented, + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_addsubcarry, + .out_rrr = tgen_addco, }; +static void tgen_addci(TCGContext *s, TCGType type, + TCGReg a0, TCGReg a1, TCGReg a2) +{ + tcg_out_op_rrr(s, INDEX_op_addci, a0, a1, a2); +} + static const TCGOutOpAddSubCarry outop_addci = { - .base.static_constraint = C_NotImplemented, + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_addsubcarry, + .out_rrr = tgen_addci, }; +static void tgen_addcio(TCGContext *s, TCGType type, + TCGReg a0, TCGReg a1, TCGReg a2) +{ + tcg_out_op_rrr(s, INDEX_op_addcio, a0, a1, a2); +} + static const TCGOutOpBinary outop_addcio = { - .base.static_constraint = C_NotImplemented, + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_addsubcarry, + .out_rrr = tgen_addcio, }; static void tcg_out_set_carry(TCGContext *s) { - g_assert_not_reached(); + tcg_out_op_v(s, INDEX_op_tci_setcarry); } static void tgen_and(TCGContext *s, TCGType type, @@ -910,21 +939,45 @@ static const TCGOutOpSubtract outop_sub = { .out_rrr = tgen_sub, }; +static void tgen_subbo(TCGContext *s, TCGType type, + TCGReg a0, TCGReg a1, TCGReg a2) +{ + tcg_out_op_rrr(s, INDEX_op_subbo, a0, a1, a2); +} + static const TCGOutOpAddSubCarry outop_subbo = { - .base.static_constraint = C_NotImplemented, + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_addsubcarry, + .out_rrr = tgen_subbo, }; +static void tgen_subbi(TCGContext *s, TCGType type, + TCGReg a0, TCGReg a1, TCGReg a2) +{ + tcg_out_op_rrr(s, INDEX_op_subbi, a0, a1, a2); +} + static const TCGOutOpAddSubCarry outop_subbi = { - .base.static_constraint = C_NotImplemented, + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_addsubcarry, + .out_rrr = tgen_subbi, }; +static void tgen_subbio(TCGContext *s, TCGType type, + TCGReg a0, TCGReg a1, TCGReg a2) +{ + tcg_out_op_rrr(s, INDEX_op_subbio, a0, a1, a2); +} + static const TCGOutOpAddSubCarry outop_subbio = { - .base.static_constraint = C_NotImplemented, + .base.static_constraint = C_Dynamic, + .base.dynamic_constraint = cset_addsubcarry, + .out_rrr = tgen_subbio, }; static void tcg_out_set_borrow(TCGContext *s) { - g_assert_not_reached(); + tcg_out_op_v(s, INDEX_op_tci_setcarry); /* borrow == carry */ } static void tgen_xor(TCGContext *s, TCGType type, -- 2.43.0