tcg/e2k: refactor

This commit is contained in:
Denis Drakhnia 2024-03-22 16:52:10 +02:00
parent a54831a5a1
commit efad21f957
1 changed files with 322 additions and 223 deletions

View File

@ -378,12 +378,12 @@ done:
}
}
static void tcg_out_start(Bundle *bundle)
static void e2k_out_start(Bundle *bundle)
{
memset(bundle, 0, sizeof(*bundle));
}
static void tcg_out_end(TCGContext *s, Bundle *bundle)
static void e2k_out_end(TCGContext *s, Bundle *bundle)
{
uint32_t buffer[32], syll = 0;
int cur, count, lts, pls, cds;
@ -578,7 +578,7 @@ static const struct AlcOpcode alc_opcodes[] = {
#undef DEF
};
static void e2k_insert_rlp(Bundle *bundle, int alc, bool mrgc, PredReg preg, bool inv)
static void e2k_out_rlp_(Bundle *bundle, int alc, bool mrgc, PredReg preg, bool inv)
{
bool cluster = alc > 2;
@ -606,15 +606,25 @@ static void e2k_insert_rlp(Bundle *bundle, int alc, bool mrgc, PredReg preg, boo
tcg_debug_assert(0 && "failed to insert RLP/MRGC");
}
static void e2k_insert_lit(Bundle *bundle, int alc, int64_t val)
static void e2k_out_rlp(Bundle *bundle, int alc, PredReg preg, bool inv)
{
e2k_out_rlp_(bundle, alc, false, preg, inv);
}
static void e2k_out_mrgc(Bundle *bundle, int alc, PredReg preg, bool inv)
{
e2k_out_rlp_(bundle, alc, true, preg, inv);
}
static void e2k_out_lit(Bundle *bundle, int alc, int64_t val)
{
tcg_debug_assert(!bundle->lit_present[alc]);
bundle->lit_present[alc] = true;
bundle->lit[alc] = val;
}
static void e2k_insert_alc(Bundle *bundle, int alc, AlcOpc opc, uint8_t dst,
uint8_t src1, uint8_t src2, uint8_t src3)
static void e2k_out_alf(Bundle *bundle, int alc, AlcOpc opc, uint8_t dst,
uint8_t src1, uint8_t src2, uint8_t src3)
{
const AlcOpcode *info = &alc_opcodes[opc];
@ -635,26 +645,70 @@ static void e2k_insert_alc(Bundle *bundle, int alc, AlcOpc opc, uint8_t dst,
}
}
static void e2k_insert_alc_lit(Bundle *bundle, int alc, AlcOpc opc, uint8_t dst,
uint8_t src1, int64_t src2, bool c_src2, uint8_t src3)
static void e2k_out_alf_lit(Bundle *bundle, int alc, AlcOpc opc, uint8_t dst,
uint8_t src1, int64_t src2, bool c_src2, uint8_t src3)
{
if (c_src2) {
e2k_insert_lit(bundle, alc, src2);
e2k_out_lit(bundle, alc, src2);
}
e2k_insert_alc(bundle, alc, opc, dst, src1, c_src2 ? 0 : GPR(src2), src3);
e2k_out_alf(bundle, alc, opc, dst, src1, c_src2 ? 0 : GPR(src2), src3);
}
/* ALF2 */
static void e2k_insert_alc_rr(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
TCGReg src2)
/* ALF1 dst:reg, src1:reg:uimm5, src2:reg:lit */
static void e2k_out_alf1_rrr(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
TCGReg src1, TCGReg src2)
{
e2k_insert_alc(bundle, alc, opc, GPR(dst), 0, GPR(src2), 0);
e2k_out_alf(bundle, alc, opc, GPR(dst), GPR(src1), GPR(src2), 0);
}
static void e2k_insert_alc_cr(Bundle *bundle, int alc, AlcOpc opc, CtprReg dst,
TCGReg src2)
static void e2k_out_alf1_rrc(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
TCGReg src1, TCGArg src2, bool c_src2)
{
e2k_insert_alc(bundle, alc, opc, CTPR(dst), 0, GPR(src2), 0);
e2k_out_alf_lit(bundle, alc, opc, GPR(dst), GPR(src1), src2, c_src2, 0);
}
static void e2k_out_alf1_rri(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
TCGReg src1, int64_t src2)
{
e2k_out_alf_lit(bundle, alc, opc, GPR(dst), GPR(src1), src2, true, 0);
}
/* ALF2 dst:reg, src2:reg:lit */
static void e2k_out_alf2_rr(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
TCGReg src2)
{
e2k_out_alf(bundle, alc, opc, GPR(dst), 0, GPR(src2), 0);
}
static void e2k_out_alf2_rc(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
TCGArg src2, bool c_src2)
{
e2k_out_alf_lit(bundle, alc, opc, GPR(dst), 0, src2, c_src2, 0);
}
static void e2k_out_alf2_ri(Bundle *bundle, int alc, AlcOpc opc, TCGReg dst,
int64_t src2)
{
e2k_out_alf_lit(bundle, alc, opc, GPR(dst), 0, src2, true, 0);
}
/* ALF7 dst:pred_reg, src1:reg:uimm5, src2:reg:lit */
static void e2k_out_alf7_prr(Bundle *bundle, int alc, AlcOpc opc, PredReg dst,
TCGReg src1, TCGReg src2)
{
e2k_out_alf(bundle, alc, opc, dst, GPR(src1), GPR(src2), 0);
}
static void e2k_out_alf7_prc(Bundle *bundle, int alc, AlcOpc opc, PredReg dst,
TCGReg src1, TCGArg src2, bool c_src2)
{
e2k_out_alf_lit(bundle, alc, opc, dst, GPR(src1), src2, c_src2, 0);
}
static void e2k_out_alf7_pri(Bundle *bundle, int alc, AlcOpc opc, PredReg dst,
TCGReg src1, int64_t src2)
{
e2k_out_alf_lit(bundle, alc, opc, dst, GPR(src1), src2, true, 0);
}
static uint32_t encode_cs0_imm28(int32_t offset)
@ -667,7 +721,7 @@ static uint32_t encode_cs0_prep(CtprReg ctpr, int32_t offset)
return ((uint32_t) ctpr << 30) | encode_cs0_imm28(offset);
}
static void e2k_insert_cs(Bundle *bundle, int n, uint32_t cs)
static void e2k_out_cs(Bundle *bundle, int n, uint32_t cs)
{
tcg_debug_assert(!bundle->cs_present[n]);
@ -675,36 +729,40 @@ static void e2k_insert_cs(Bundle *bundle, int n, uint32_t cs)
bundle->cs[n] = cs;
}
static void e2k_insert_prep(Bundle *bundle, CtprReg dst, int32_t offset)
static void e2k_out_prep_r(Bundle *bundle, int alc, CtprReg dst, TCGReg src2)
{
e2k_set_latency(bundle, E2K_LATENCY_PREP);
e2k_insert_cs(bundle, 0, (uint32_t) dst << 30 | encode_cs0_imm28(offset));
e2k_out_alf(bundle, alc, ALC_MOVTD_CTPR, CTPR(dst), 0, GPR(src2), 0);
}
static void e2k_insert_prep_return(Bundle *bundle)
static void e2k_out_prep(Bundle *bundle, CtprReg dst, int32_t offset)
{
e2k_set_latency(bundle, E2K_LATENCY_PREP);
e2k_out_cs(bundle, 0, (uint32_t) dst << 30 | encode_cs0_imm28(offset));
}
static void e2k_out_prep_return(Bundle *bundle)
{
e2k_set_latency(bundle, E2K_LATENCY_PREP_RETURN);
e2k_insert_cs(bundle, 0, 0xf0000000);
e2k_out_cs(bundle, 0, 0xf0000000);
}
typedef enum {
CT_NONE = 0,
CT_ALWAYS = 1,
CT_PREG = 2, /* pN */
CT_NOT_PREG = 3, /* ~pN */
CT_LOOP_END = 4, /* loop_end */
CT_NOT_LOOP_END = 5, /* ~loop_end */
CT_PREG_OR_LOOP_END = 6, /* pN || loop_end */
CT_NOT_PREG_AND_NOT_LOOP_END = 7, /* ~pN && ~loop_end */
CT_MLOCK_OR_ALC = 8, /* mlock || %dt_al0134 (SS[4:0] dt_al bitmask) */
CT_MLOCK_OR_CMP = 9, /* mlock || {~}alcN || {~}%alcN (SS[4:0] cmpN in ALC or clpN) */
CT_CMP_CLP = 11, /* {~}{alp,plu}N v7+ */
CT_NOT_PREG_OR_LOOP_END = 14, /* ~pN || loop_end */
CT_PREG_AND_NOT_LOOP_END = 15, /* pN && ~loop_end */
CT_PREG = 2, /* pN */
CT_NOT_PREG = 3, /* ~pN */
CT_LOOP_END = 4, /* loop_end */
CT_NOT_LOOP_END = 5, /* ~loop_end */
CT_PREG_OR_LOOP_END = 6, /* pN || loop_end */
CT_NOT_PREG_AND_NOT_LOOP_END = 7, /* ~pN && ~loop_end */
CT_MLOCK_OR_ALC = 8, /* mlock || %dt_al0134 (SS[4:0] dt_al bitmask) */
CT_MLOCK_OR_CMP = 9, /* mlock || {~}alcN || {~}%alcN (SS[4:0] cmpN in ALC or clpN) */
CT_CMP_CLP = 11, /* {~}{alp,plu}N v7+ */
CT_NOT_PREG_OR_LOOP_END = 14, /* ~pN || loop_end */
CT_PREG_AND_NOT_LOOP_END = 15, /* pN && ~loop_end */
} CtCond;
static void e2k_insert_ct(Bundle *bundle, CtprReg ctpr, CtCond cond,
uint8_t pred)
static void e2k_out_ct(Bundle *bundle, CtprReg ctpr, CtCond cond, uint8_t pred)
{
bundle->ss_present = true;
bundle->ss = deposit32(bundle->ss, 0, 5, pred);
@ -712,14 +770,13 @@ static void e2k_insert_ct(Bundle *bundle, CtprReg ctpr, CtCond cond,
bundle->ss = deposit32(bundle->ss, 10, 2, ctpr);
}
static void e2k_insert_call(Bundle *bundle, CtprReg ctpr, CtCond cond,
uint8_t pred)
static void e2k_out_call(Bundle *bundle, CtprReg ctpr, CtCond cond, uint8_t pred)
{
e2k_insert_ct(bundle, ctpr, cond, pred);
e2k_insert_cs(bundle, 1, 0x50000000 | WBS);
e2k_out_ct(bundle, ctpr, cond, pred);
e2k_out_cs(bundle, 1, 0x50000000 | WBS);
}
static void e2k_insert_mov(Bundle *bundle, int alc, TCGType type, TCGReg ret, TCGReg arg)
static void e2k_out_mov(Bundle *bundle, int alc, TCGType type, TCGReg ret, TCGReg arg)
{
if (ret == arg) {
return;
@ -727,20 +784,26 @@ static void e2k_insert_mov(Bundle *bundle, int alc, TCGType type, TCGReg ret, TC
switch (type) {
case TCG_TYPE_I32:
e2k_insert_alc_rr(bundle, alc, ALC_MOVW, ret, arg);
e2k_out_alf2_rr(bundle, alc, ALC_MOVW, ret, arg);
break;
case TCG_TYPE_I64:
e2k_insert_alc_rr(bundle, alc, ALC_MOVD, ret, arg);
e2k_out_alf2_rr(bundle, alc, ALC_MOVD, ret, arg);
break;
default:
g_assert_not_reached();
}
}
static void e2k_insert_movi(Bundle *bundle, int alc, TCGReg ret,
int64_t val)
static void e2k_out_sxt(Bundle *bundle, int alc, TCGType type, TCGReg ret, TCGReg arg)
{
e2k_insert_alc_lit(bundle, alc, ALC_MOVD, GPR(ret), 0, val, true, 0);
if (type == TCG_TYPE_I32) {
e2k_out_alf2_rr(bundle, alc, ALC_SXTW, ret, arg);
}
}
static void e2k_out_movi(Bundle *bundle, int alc, TCGReg ret, int64_t val)
{
e2k_out_alf2_ri(bundle, alc, ALC_MOVD, ret, val);
}
/*
@ -772,38 +835,44 @@ static void tcg_out_nop(TCGContext *s)
static void tcg_out_wait(TCGContext *s, uint32_t flags)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_cs(&bundle, 1, E2K_CS0_WAIT | flags);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_cs(&bundle, 1, E2K_CS0_WAIT | flags);
e2k_out_end(s, &bundle);
}
static void tcg_out_alf(TCGContext *s, int alc, AlcOpc opc,
uint8_t dst, uint8_t src1, uint8_t src2, uint8_t src3)
static void tcg_out_alf(TCGContext *s, int alc, AlcOpc opc, uint8_t dst,
uint8_t src1, uint8_t src2, uint8_t src3)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_alc(&bundle, alc, opc, dst, src1, src2, src3);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_alf(&bundle, alc, opc, dst, src1, src2, src3);
e2k_out_end(s, &bundle);
}
static void tcg_out_alf_lit(TCGContext *s, int alc, AlcOpc opc,
uint8_t dst, uint8_t src1, int64_t src2, bool c_src2,
uint8_t src3)
static void tcg_out_alf_lit(TCGContext *s, int alc, AlcOpc opc, uint8_t dst,
uint8_t src1, int64_t src2, bool c_src2, uint8_t src3)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_alc_lit(&bundle, alc, opc, dst, src1, src2, c_src2, src3);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_alf_lit(&bundle, alc, opc, dst, src1, src2, c_src2, src3);
e2k_out_end(s, &bundle);
}
/* ALF1 dst:reg, src1:reg:uimm5, src2:reg:lit */
static void tcg_out_alf1_rrr(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, TCGReg src1, TCGReg src2)
TCGReg dst, TCGReg src1, TCGReg src2)
{
tcg_out_alf(s, alc, opc, GPR(dst), GPR(src1), GPR(src2), 0);
}
static void tcg_out_alf1_rrc(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, TCGReg src1, TCGArg src2, bool c_src2)
{
tcg_out_alf_lit(s, alc, opc, GPR(dst), GPR(src1), src2, c_src2, 0);
}
static void tcg_out_alf1_rir(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, uint8_t src1, TCGReg src2)
TCGReg dst, uint8_t src1, TCGReg src2)
{
tcg_out_alf(s, alc, opc, GPR(dst), UIMM5(src1), GPR(src2), 0);
}
@ -820,48 +889,62 @@ static void tcg_out_alf1_rri(TCGContext *s, int alc, AlcOpc opc,
tcg_out_alf_lit(s, alc, opc, GPR(dst), GPR(src1), src2, true, 0);
}
static void tcg_out_alf1_rrc(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, TCGReg src1, TCGArg src2, bool c_src2)
{
tcg_out_alf_lit(s, alc, opc, GPR(dst), GPR(src1), src2, c_src2, 0);
}
/* ALF2 dst:reg, src2:reg:lit */
static void tcg_out_alf2_rr(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, TCGReg src2)
{
tcg_out_alf(s, alc, opc, GPR(dst), 0, GPR(src2), 0);
}
static void tcg_out_alf21_rrir(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, TCGReg src1, TCGArg src2, TCGReg src3)
static void tcg_out_alf2_ri(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, int64_t src2)
{
tcg_out_alf_lit(s, alc, opc, GPR(dst), 0, src2, true, 0);
}
static void tcg_out_alf2_rc(TCGContext *s, int alc, AlcOpc opc,
TCGReg dst, int64_t src2, bool c_src2)
{
tcg_out_alf_lit(s, alc, opc, GPR(dst), 0, src2, c_src2, 0);
}
/* ALF21 dst:reg, src1:reg:uimm5, src2:reg:lit, src2:reg */
static void tcg_out_alf21_rrrr(TCGContext *s, int alc, AlcOpc opc, TCGReg dst,
TCGReg src1, TCGArg src2, TCGReg src3)
{
tcg_out_alf(s, alc, opc, GPR(dst), GPR(src1), GPR(src2), GPR(src3));
}
static void tcg_out_alf21_rrir(TCGContext *s, int alc, AlcOpc opc, TCGReg dst,
TCGReg src1, TCGArg src2, TCGReg src3)
{
tcg_out_alf_lit(s, alc, opc, GPR(dst), GPR(src1), src2, true, GPR(src3));
}
static void tcg_out_prep_addr(TCGContext *s, CtprReg dst, int64_t src2)
static void tcg_out_prep_i(TCGContext *s, CtprReg dst, int64_t src2)
{
tcg_out_alf_lit(s, 0, ALC_MOVTD_CTPR, CTPR(dst), 0, src2, true, 0);
}
static void tcg_out_prep_gpr(TCGContext *s, CtprReg dst, TCGReg src2)
static void tcg_out_prep_r(TCGContext *s, CtprReg dst, TCGReg src2)
{
tcg_out_alf(s, 0, ALC_MOVTD_CTPR, CTPR(dst), 0, GPR(src2), 0);
}
static void tcg_out_prep_disp(TCGContext *s, CtprReg dst, int32_t offset)
static void tcg_out_prep(TCGContext *s, CtprReg dst, int32_t offset)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_prep(&bundle, dst, offset);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_prep(&bundle, dst, offset);
e2k_out_end(s, &bundle);
}
static void tcg_out_ct(TCGContext *s, CtprReg ctpr, CtCond cond, PredReg preg)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_ct(&bundle, ctpr, cond, preg);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_ct(&bundle, ctpr, cond, preg);
e2k_out_end(s, &bundle);
}
static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
@ -921,9 +1004,9 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
return true;
}
tcg_out_start(&bundle);
e2k_insert_mov(&bundle, 0, type, ret, arg);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_mov(&bundle, 0, type, ret, arg);
e2k_out_end(s, &bundle);
return true;
}
@ -932,10 +1015,9 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
tcg_target_long val)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_movi(&bundle, 0, rd, val);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_movi(&bundle, 0, rd, val);
e2k_out_end(s, &bundle);
}
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
@ -1027,8 +1109,8 @@ static const struct {
[TCG_COND_GTU] = { ALC_CMPBEDB, true },
};
static bool e2k_insert_setcond(Bundle *bundle, int alc, TCGType type, TCGCond cond, PredReg ret,
TCGReg src1, int64_t src2, bool c_src2)
static bool e2k_out_setcond(Bundle *bundle, int alc, TCGType type, TCGCond cond,
PredReg ret, TCGReg src1, int64_t src2, bool c_src2)
{
AlcOpc cmp;
bool invert;
@ -1043,7 +1125,7 @@ static bool e2k_insert_setcond(Bundle *bundle, int alc, TCGType type, TCGCond co
tcg_debug_assert(cmp);
e2k_insert_alc_lit(bundle, alc, cmp, ret, GPR(src1), src2, c_src2, 0);
e2k_out_alf7_prc(bundle, alc, cmp, ret, src1, src2, c_src2);
return invert;
}
@ -1054,10 +1136,10 @@ static void tcg_out_brcond(TCGContext *s, TCGType type, TCGCond cond, TCGReg src
Bundle bundle;
bool invert;
tcg_out_start(&bundle);
invert = e2k_insert_setcond(&bundle, 0, type, cond, PREG_TMP0, src1, src2, c_src2);
e2k_insert_prep(&bundle, CTPR1, 0);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
invert = e2k_out_setcond(&bundle, 0, type, cond, PREG_TMP0, src1, src2, c_src2);
e2k_out_prep(&bundle, CTPR1, 0);
e2k_out_end(s, &bundle);
tcg_out_reloc_prep(s, &bundle, l);
tcg_out_ct(s, CTPR1, invert ? CT_NOT_PREG : CT_PREG, PREG_TMP0);
@ -1069,14 +1151,14 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond, TCGReg re
Bundle bundle;
bool invert;
tcg_out_start(&bundle);
invert = e2k_insert_setcond(&bundle, 0, type, cond, PREG_TMP0, src1, src2, c_src2);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
invert = e2k_out_setcond(&bundle, 0, type, cond, PREG_TMP0, src1, src2, c_src2);
e2k_out_end(s, &bundle);
tcg_out_start(&bundle);
e2k_insert_alc(&bundle, 0, ALC_MERGED, GPR(ret), UIMM5(0), UIMM4(1), 0);
e2k_insert_rlp(&bundle, 0, true, PREG_TMP0, invert);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_alf(&bundle, 0, ALC_MERGED, GPR(ret), UIMM5(0), UIMM4(1), 0);
e2k_out_mrgc(&bundle, 0, PREG_TMP0, invert);
e2k_out_end(s, &bundle);
}
static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond, TCGReg ret,
@ -1086,18 +1168,18 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond, TCGReg re
{
Bundle bundle;
bool inv;
AlcOpc mov = type == TCG_TYPE_I64 ? ALC_MOVD : ALC_MOVW;
AlcOpc mov = type == TCG_TYPE_I32 ? ALC_MOVW : ALC_MOVD;
tcg_out_start(&bundle);
inv = e2k_insert_setcond(&bundle, 0, type, cond, PREG_TMP0, cmp1, cmp2, c_cmp2);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
inv = e2k_out_setcond(&bundle, 0, type, cond, PREG_TMP0, cmp1, cmp2, c_cmp2);
e2k_out_end(s, &bundle);
tcg_out_start(&bundle);
e2k_insert_alc_lit(&bundle, 0, mov, GPR(ret), 0, val1, c_val1, 0);
e2k_insert_rlp(&bundle, 0, false, PREG_TMP0, inv);
e2k_insert_alc_lit(&bundle, 1, mov, GPR(ret), 0, val2, c_val2, 0);
e2k_insert_rlp(&bundle, 1, false, PREG_TMP0, !inv);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_alf2_rc(&bundle, 0, mov, ret, val1, c_val1);
e2k_out_alf2_rc(&bundle, 1, mov, ret, val2, c_val2);
e2k_out_rlp(&bundle, 0, PREG_TMP0, inv);
e2k_out_rlp(&bundle, 1, PREG_TMP0, !inv);
e2k_out_end(s, &bundle);
}
static void tcg_out_clz_int(TCGContext *s, TCGType type, TCGReg ret,
@ -1118,20 +1200,20 @@ static void tcg_out_clz_int(TCGContext *s, TCGType type, TCGReg ret,
bitrev = ALC_BITREVW;
}
tcg_out_start(&bundle);
e2k_insert_alc(&bundle, 0, cmp, PREG_TMP0, UIMM5(0), GPR(a0), 0);
e2k_out_start(&bundle);
e2k_out_alf7_pri(&bundle, 0, cmp, PREG_TMP0, a0, 0);
if (do_bitrev) {
e2k_insert_alc(&bundle, 1, bitrev, GPR(TCG_REG_TMP0), 0, GPR(a0), 0);
e2k_out_alf2_rr(&bundle, 1, bitrev, TCG_REG_TMP0, a0);
a0 = TCG_REG_TMP0;
}
tcg_out_end(s, &bundle);
e2k_out_end(s, &bundle);
tcg_out_start(&bundle);
e2k_insert_alc_lit(&bundle, 0, mov, GPR(ret), 0, a1, c1, 0);
e2k_insert_rlp(&bundle, 0, false, PREG_TMP0, false);
e2k_insert_alc(&bundle, 1, clz, GPR(ret), 0, GPR(a0), 0);
e2k_insert_rlp(&bundle, 1, false, PREG_TMP0, true);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_alf2_rc(&bundle, 0, mov, ret, a1, c1);
e2k_out_alf(&bundle, 1, clz, GPR(ret), 0, GPR(a0), 0);
e2k_out_rlp(&bundle, 0, PREG_TMP0, false);
e2k_out_rlp(&bundle, 1, PREG_TMP0, true);
e2k_out_end(s, &bundle);
}
static uint16_t e2k_field_sel(int ofs, int len, bool sign)
@ -1165,42 +1247,41 @@ static void tcg_out_deposit_int(TCGContext *s, TCGType type, TCGReg ret,
tcg_out_alf1_rri(s, 0, opc2, ret, ret, ofs);
}
static void tcg_out_ldst(TCGContext *s, AlcOpc opc, TCGReg data,
TCGReg addr, intptr_t offset, bool sxt)
static void e2k_out_ld(Bundle *bundle, int alc, TCGType type, TCGReg ret,
TCGReg addr, intptr_t offset)
{
tcg_out_alf1_rri(s, 2, opc, data, addr, offset);
AlcOpc opc = type == TCG_TYPE_I32 ? ALC_LW : ALC_LD;
e2k_out_alf1_rri(bundle, alc, opc, ret, addr, offset);
}
if (sxt) {
switch (opc) {
case ALC_LB:
tcg_out_ext8s(s, TCG_TYPE_I64, data, data);
break;
case ALC_LH:
tcg_out_ext16s(s, TCG_TYPE_I64, data, data);
break;
case ALC_LW:
tcg_out_ext32s(s, data, data);
break;
case ALC_LD:
break;
default:
g_assert_not_reached();
}
static void e2k_out_st(Bundle *bundle, int alc, TCGType type, TCGReg data,
TCGReg addr, intptr_t offset)
{
AlcOpc opc = type == TCG_TYPE_I32 ? ALC_SW : ALC_SD;
e2k_out_alf1_rri(bundle, alc, opc, data, addr, offset);
}
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
TCGReg addr, intptr_t offset)
{
Bundle bundle;
e2k_out_start(&bundle);
e2k_out_ld(&bundle, 0, type, ret, addr, offset);
e2k_out_end(s, &bundle);
if (type == TCG_TYPE_I32) {
tcg_out_ext32s(s, ret, ret);
}
}
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
TCGReg arg1, intptr_t arg2)
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
TCGReg addr, intptr_t offset)
{
AlcOpc opc = type == TCG_TYPE_I32 ? ALC_LW : ALC_LD;
tcg_out_ldst(s, opc, arg, arg1, arg2, true);
}
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
TCGReg arg1, intptr_t arg2)
{
AlcOpc opc = type == TCG_TYPE_I32 ? ALC_SW : ALC_SD;
tcg_out_ldst(s, opc, arg, arg1, arg2, false);
Bundle bundle;
e2k_out_start(&bundle);
e2k_out_st(&bundle, 2, type, data, addr, offset);
e2k_out_end(s, &bundle);
}
static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
@ -1218,19 +1299,19 @@ static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
if (offset == (int32_t) offset) {
/* short jump +/-1GiB */
tcg_out_prep_disp(s, CTPR1, offset);
tcg_out_prep(s, CTPR1, offset);
} else {
/* far jump: 64-bit */
tcg_out_prep_addr(s, CTPR1, (int64_t) arg);
tcg_out_prep_i(s, CTPR1, (int64_t) arg);
}
tcg_out_start(&bundle);
e2k_out_start(&bundle);
if (tail) {
e2k_insert_ct(&bundle, CTPR1, CT_ALWAYS, 0);
e2k_out_ct(&bundle, CTPR1, CT_ALWAYS, 0);
} else {
e2k_insert_call(&bundle, CTPR1, CT_ALWAYS, 0);
e2k_out_call(&bundle, CTPR1, CT_ALWAYS, 0);
}
tcg_out_end(s, &bundle);
e2k_out_end(s, &bundle);
}
static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
@ -1276,9 +1357,9 @@ static void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
{
Bundle bundle;
tcg_out_start(&bundle);
e2k_insert_prep(&bundle, CTPR1, 0);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_prep(&bundle, CTPR1, 0);
e2k_out_end(s, &bundle);
bool ok = reloc_prep_ctpr(s->code_ptr - bundle.len + bundle.cs_offset[0],
target, bundle.cs_offset[0]);
tcg_debug_assert(ok);
@ -1370,14 +1451,26 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
ldst->oi = oi;
ldst->addrlo_reg = addr_reg;
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
e2k_out_start(&bundle);
e2k_out_ld(&bundle, 0, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
e2k_out_ld(&bundle, 2, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
if (addr_type == TCG_TYPE_I32) {
e2k_out_alf2_rr(&bundle, 1, ALC_SXTW, TCG_REG_TMP2, addr_reg);
bundle.latency -= 1;
} else {
e2k_out_alf1_rri(&bundle, 1, ALC_SHRD, TCG_REG_TMP2, addr_reg,
s->page_bits - CPU_TLB_ENTRY_BITS);
}
e2k_out_end(s, &bundle);
tcg_out_alf1_rri(s, 0, ALC_SHRD, TCG_REG_TMP2, addr_reg,
s->page_bits - CPU_TLB_ENTRY_BITS);
if (addr_type == TCG_TYPE_I32) {
tcg_out_alf1_rri(s, 0, ALC_SHRD, TCG_REG_TMP2, TCG_REG_TMP2,
s->page_bits - CPU_TLB_ENTRY_BITS);
}
tcg_out_alf1_rrr(s, 0, ALC_ANDD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
tcg_out_alf1_rrr(s, 0, ALC_ADDD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
e2k_out_start(&bundle);
e2k_out_alf1_rrr(&bundle, 0, ALC_ADDD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
/*
* For aligned accesses, we check the first byte and include the alignment
* bits within the address. For unaligned access, we check that we don't
@ -1386,40 +1479,43 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
addr_adj = addr_reg;
if (a_mask < s_mask) {
addr_adj = TCG_REG_TMP0;
tcg_out_alf1_rri(s, 0, addr_type == TCG_TYPE_I32 ? ALC_ADDW : ALC_ADDD,
e2k_out_alf1_rri(&bundle, 1, addr_type == TCG_TYPE_I32 ? ALC_ADDW : ALC_ADDD,
addr_adj, addr_reg, s_mask - a_mask);
}
e2k_out_end(s, &bundle);
e2k_out_start(&bundle);
compare_mask = s->page_mask | a_mask;
if (compare_mask == sextract64(compare_mask, 0, 12)) {
tcg_out_alf1_rri(s, 0, ALC_ANDD, TCG_REG_TMP1, addr_adj,
compare_mask);
} else {
tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
tcg_out_alf1_rrr(s, 0, ALC_ANDD, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
}
e2k_out_alf1_rri(&bundle, 1, ALC_ANDD, TCG_REG_TMP1, addr_adj, compare_mask);
/* Load the tlb comparator and the addend. */
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
e2k_out_ld(&bundle, 0, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
is_ld ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write));
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
e2k_out_ld(&bundle, 2, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
offsetof(CPUTLBEntry, addend));
e2k_out_end(s, &bundle);
/* Compare masked address with the TLB entry. */
tcg_out_start(&bundle);
e2k_insert_prep(&bundle, CTPR1, 0);
e2k_insert_alc(&bundle, 0, ALC_CMPEDB, PREG_TMP0, GPR(TCG_REG_TMP0), GPR(TCG_REG_TMP1), 0);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_prep(&bundle, CTPR1, 0);
e2k_out_alf(&bundle, 0, ALC_CMPEDB, PREG_TMP0, GPR(TCG_REG_TMP0), GPR(TCG_REG_TMP1), 0);
e2k_out_end(s, &bundle);
ldst->label_ptr[0] = s->code_ptr - bundle.len + bundle.cs_offset[0];
ldst->label_addend[0] = bundle.cs_offset[0];
tcg_out_ct(s, CTPR1, CT_NOT_PREG, PREG_TMP0);
/* TLB Hit - translate address using addend. */
if (addr_type != TCG_TYPE_I32) {
tcg_out_alf1_rrr(s, 0, ALC_ADDD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
e2k_out_start(&bundle);
e2k_out_alf1_rrr(&bundle, 0, ALC_ADDD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
e2k_out_ct(&bundle, CTPR1, CT_NOT_PREG, PREG_TMP0);
e2k_out_end(s, &bundle);
} else {
tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
e2k_out_start(&bundle);
e2k_out_ct(&bundle, CTPR1, CT_NOT_PREG, PREG_TMP0);
e2k_out_alf2_rr(&bundle, 0, ALC_ZXTW, TCG_REG_TMP0, addr_reg);
e2k_out_end(s, &bundle);
tcg_out_alf1_rrr(s, 0, ALC_ADDD, TCG_REG_TMP0, TCG_REG_TMP0, TCG_REG_TMP2);
}
*pbase = TCG_REG_TMP0;
@ -1432,10 +1528,10 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
ldst->oi = oi;
ldst->addrlo_reg = addr_reg;
tcg_out_start(&bundle);
e2k_insert_prep(&bundle, CTPR1, 0);
e2k_insert_alc_lit(&bundle, 0, ALC_CMPANDEDB, PREG_TMP0, GPR(addr_reg), a_mask, true, 0);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_prep(&bundle, CTPR1, 0);
e2k_out_alf_lit(&bundle, 0, ALC_CMPANDEDB, PREG_TMP0, GPR(addr_reg), a_mask, true, 0);
e2k_out_end(s, &bundle);
ldst->label_ptr[0] = s->code_ptr - bundle.len + bundle.cs_offset[0];
ldst->label_addend[0] = bundle.cs_offset[0];
@ -1569,13 +1665,13 @@ static void tcg_out_goto_tb(TCGContext *s, int which)
{
/* Direct branch will be patched by tb_target_set_jmp_target. */
set_jmp_insn_offset(s, which);
tcg_out_prep_disp(s, CTPR1, 0);
tcg_out_prep(s, CTPR1, 0);
tcg_out_ct(s, CTPR1, CT_ALWAYS, 0);
/* When branch is out of range, fall through to indirect. */
AlcOpc opc = TCG_TYPE_PTR == TCG_TYPE_I32 ? ALC_LW : ALC_LD;
tcg_out_alf1_rii(s, 0, opc, TCG_REG_TMP0, 0, get_jmp_target_addr(s, which));
tcg_out_prep_gpr(s, CTPR1, TCG_REG_TMP0);
tcg_out_prep_r(s, CTPR1, TCG_REG_TMP0);
tcg_out_ct(s, CTPR1, CT_ALWAYS, 0);
set_jmp_reset_offset(s, which);
}
@ -1611,14 +1707,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
switch (opc) {
case INDEX_op_goto_ptr:
tcg_out_prep_gpr(s, CTPR1, a0);
tcg_out_prep_r(s, CTPR1, a0);
tcg_out_ct(s, CTPR1, CT_ALWAYS, 0);
break;
case INDEX_op_br:
tcg_out_start(&bundle);
e2k_insert_prep(&bundle, CTPR1, 0);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_prep(&bundle, CTPR1, 0);
e2k_out_end(s, &bundle);
tcg_out_reloc_prep(s, &bundle, arg_label(a0));
tcg_out_ct(s, CTPR1, CT_ALWAYS, 0);
@ -1626,45 +1722,48 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_ld8u_i32:
case INDEX_op_ld8u_i64:
tcg_out_ldst(s, ALC_LB, a0, a1, a2, false);
break;
case INDEX_op_ld8s_i32:
case INDEX_op_ld8s_i64:
tcg_out_ldst(s, ALC_LB, a0, a1, a2, true);
tcg_out_alf1_rri(s, 0, ALC_LB, a0, a1, a2);
break;
case INDEX_op_ld16u_i32:
case INDEX_op_ld16u_i64:
tcg_out_ldst(s, ALC_LH, a0, a1, a2, false);
tcg_out_alf1_rri(s, 0, ALC_LH, a0, a1, a2);
break;
case INDEX_op_ld32u_i64:
tcg_out_alf1_rri(s, 0, ALC_LW, a0, a1, a2);
break;
case INDEX_op_ld_i64:
tcg_out_alf1_rri(s, 0, ALC_LD, a0, a1, a2);
break;
case INDEX_op_ld8s_i32:
case INDEX_op_ld8s_i64:
tcg_out_alf1_rri(s, 0, ALC_LB, a0, a1, a2);
tcg_out_alf2_rr(s, 0, ALC_SXTB, a0, a0);
break;
case INDEX_op_ld16s_i32:
case INDEX_op_ld16s_i64:
tcg_out_ldst(s, ALC_LH, a0, a1, a2, true);
break;
case INDEX_op_ld32u_i64:
tcg_out_ldst(s, ALC_LW, a0, a1, a2, false);
tcg_out_alf1_rri(s, 0, ALC_LH, a0, a1, a2);
tcg_out_alf2_rr(s, 0, ALC_SXTH, a0, a0);
break;
case INDEX_op_ld_i32:
case INDEX_op_ld32s_i64:
tcg_out_ldst(s, ALC_LW, a0, a1, a2, true);
break;
case INDEX_op_ld_i64:
tcg_out_ldst(s, ALC_LD, a0, a1, a2, false);
tcg_out_alf1_rri(s, 0, ALC_LW, a0, a1, a2);
tcg_out_alf2_rr(s, 0, ALC_SXTW, a0, a0);
break;
case INDEX_op_st8_i32:
case INDEX_op_st8_i64:
tcg_out_ldst(s, ALC_SB, a0, a1, a2, false);
tcg_out_alf1_rri(s, 2, ALC_SB, a0, a1, a2);
break;
case INDEX_op_st16_i32:
case INDEX_op_st16_i64:
tcg_out_ldst(s, ALC_SH, a0, a1, a2, false);
tcg_out_alf1_rri(s, 2, ALC_SH, a0, a1, a2);
break;
case INDEX_op_st_i32:
case INDEX_op_st32_i64:
tcg_out_ldst(s, ALC_SW, a0, a1, a2, false);
tcg_out_alf1_rri(s, 2, ALC_SW, a0, a1, a2);
break;
case INDEX_op_st_i64:
tcg_out_ldst(s, ALC_SD, a0, a1, a2, false);
tcg_out_alf1_rri(s, 2, ALC_SD, a0, a1, a2);
break;
case INDEX_op_and_i32:
@ -2097,7 +2196,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
/* TB prologue */
tcg_out_start(&bundle);
e2k_out_start(&bundle);
/*
* setwd 16
@ -2108,22 +2207,22 @@ static void tcg_target_qemu_prologue(TCGContext *s)
bundle.lts_present[0] = true;
bundle.lts[0] = 0x00000110;
e2k_insert_alc_cr(&bundle, 0, ALC_MOVTD_CTPR, CTPR1, TCG_REG_R1);
e2k_insert_mov(&bundle, 1, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_R0);
e2k_out_prep_r(&bundle, 0, CTPR1, TCG_REG_R1);
e2k_out_mov(&bundle, 1, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_R0);
#if !defined(CONFIG_SOFTMMU)
e2k_insert_movi(&bundle, 2, TCG_GUEST_BASE_REG, guest_base);
e2k_out_movi(&bundle, 2, TCG_GUEST_BASE_REG, guest_base);
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
#endif
tcg_out_end(s, &bundle);
e2k_out_end(s, &bundle);
tcg_out_start(&bundle);
e2k_out_start(&bundle);
/* user stack is freed automatically */
e2k_insert_lit(&bundle, 0, -FRAME_SIZE);
e2k_insert_alc(&bundle, 0, ALC_GETSP, GPR(TCG_REG_SP), 0, 0, 0);
e2k_out_lit(&bundle, 0, -FRAME_SIZE);
e2k_out_alf(&bundle, 0, ALC_GETSP, GPR(TCG_REG_SP), 0, 0, 0);
/* Call generated code */
e2k_insert_ct(&bundle, CTPR1, CT_ALWAYS, 0);
tcg_out_end(s, &bundle);
e2k_out_ct(&bundle, CTPR1, CT_ALWAYS, 0);
e2k_out_end(s, &bundle);
/* Return path for goto_ptr. Set return value to 0 */
tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
@ -2132,9 +2231,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* TB epilogue */
tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
tcg_out_start(&bundle);
e2k_insert_prep_return(&bundle);
tcg_out_end(s, &bundle);
e2k_out_start(&bundle);
e2k_out_prep_return(&bundle);
e2k_out_end(s, &bundle);
tcg_out_ct(s, CTPR3, CT_ALWAYS, 0);
}