target: e2k: Move %br parts to %br.

This commit is contained in:
Denis Drakhnia 2020-11-14 11:20:18 +02:00 committed by Denis Drakhnia
parent 54feb6fbe3
commit a5f7f32a8f
9 changed files with 236 additions and 161 deletions

View File

@ -73,6 +73,23 @@ static const struct e2k_def_t e2k_defs[] = {
} }
}; };
static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags)
{
uint32_t br = env->br;
int rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_LEN);
int rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_LEN);
int rcur = GET_FIELD(br, BR_RCUR_OFF, BR_RCUR_LEN);
int psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_LEN);
int pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_LEN);
qemu_fprintf(f, "br %#x\n", br);
qemu_fprintf(f, " rbs %#x\n", rbs);
qemu_fprintf(f, " rsz %#x\n", rsz);
qemu_fprintf(f, " rcur %#x\n", rcur);
qemu_fprintf(f, " psz %#x\n", psz);
qemu_fprintf(f, " pcur %#x\n", pcur);
}
void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{ {
E2KCPU *cpu = E2K_CPU(cs); E2KCPU *cpu = E2K_CPU(cs);
@ -84,9 +101,7 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n", qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n",
env->usd_hi, env->usd_lo); env->usd_hi, env->usd_lo);
qemu_fprintf(f, "wbs: %d, wsz: %d\n", (int) env->wbs, (int) env->wsz); qemu_fprintf(f, "wbs: %d, wsz: %d\n", (int) env->wbs, (int) env->wsz);
qemu_fprintf(f, "rbs: %d, rsz: %d, rcur: %d\n", cpu_dump_state_br(env, f, flags);
(int) env->rbs, (int) env->rsz, (int) env->rcur);
qemu_fprintf(f, "psz: %d, pcur: %d\n", (int) env->psz, (int) env->pcur);
qemu_fprintf(f, "lsr: %016lx\n", env->lsr); qemu_fprintf(f, "lsr: %016lx\n", env->lsr);
for (i = 0; i < 192; i += 4) { for (i = 0; i < 192; i += 4) {

View File

@ -7,6 +7,12 @@
void e2k_tcg_initialize(void); void e2k_tcg_initialize(void);
#define GEN_MASK(start, end) \
(((1UL << ((end) - (start) + 1)) - 1) << start)
#define GET_BIT(v, index) (((v) >> (index)) & 1)
#define GET_FIELD(v, start, end) \
(((v) >> (start)) & ((1UL << ((end) - (start) + 1)) - 1))
#define MMU_USER_IDX 1 #define MMU_USER_IDX 1
#define CPU_RESOLVING_TYPE TYPE_E2K_CPU #define CPU_RESOLVING_TYPE TYPE_E2K_CPU
#define WREGS_SIZE 192 #define WREGS_SIZE 192
@ -22,6 +28,28 @@ void e2k_tcg_initialize(void);
#define CTPR_IPD_OFF 59 #define CTPR_IPD_OFF 59
#define CTPR_IPD_END 60 #define CTPR_IPD_END 60
#define BR_RBS_OFF 0 /* based regs window offset */
#define BR_RBS_END 5
#define BR_RBS_LEN (BR_RBS_END - BR_RBS_OFF + 1)
#define BR_RSZ_OFF 6 /* based regs window size */
#define BR_RSZ_END 11
#define BR_RSZ_LEN (BR_RSZ_END - BR_RSZ_OFF + 1)
#define BR_RCUR_OFF 12 /* based regs current index */
#define BR_RCUR_END 17
#define BR_RCUR_LEN (BR_RCUR_END - BR_RCUR_OFF + 1)
#define BR_BN_OFF BR_RBS_OFF
#define BR_BN_END BR_RCUR_END
#define BR_BN_LEN (BR_BN_END - BR_BN_OFF + 1)
#define BR_PSZ_OFF 18 /* based pregs window size */
#define BR_PSZ_END 22
#define BR_PSZ_LEN (BR_PSZ_END - BR_PSZ_OFF + 1)
#define BR_PCUR_OFF 23 /* based pregs current index */
#define BR_PCUR_END 27
#define BR_PCUR_LEN (BR_PCUR_END - BR_PCUR_OFF + 1)
#define BR_BP_OFF BR_PSZ_OFF
#define BR_BP_END BR_PCUR_END
#define BR_BP_LEN (BR_BP_END - BR_BP_OFF + 1)
#define LSR_LCNT_OFF 0 /* loop counter */ #define LSR_LCNT_OFF 0 /* loop counter */
#define LSR_LCNT_END 31 #define LSR_LCNT_END 31
#define LSR_LCNT_LEN (LSR_LCNT_END - LSR_LCNT_OFF + 1) #define LSR_LCNT_LEN (LSR_LCNT_END - LSR_LCNT_OFF + 1)
@ -65,13 +93,7 @@ typedef struct CPUArchState {
uint32_t nfx; // TODO uint32_t nfx; // TODO
uint32_t dbl; // TODO uint32_t dbl; // TODO
/* TODO: move them to %br? */ uint32_t br; /* based regs and pregs window registers */
uint32_t rbs; // based regs offset
uint32_t rsz; // based regs size
uint32_t rcur; // based regs current offset
uint64_t psz; // pred regs window size
uint64_t pcur; // pred regs current offset
uint64_t lsr; /* loop status register */ uint64_t lsr; /* loop status register */
uint32_t syscall_wbs; uint32_t syscall_wbs;

View File

@ -14,7 +14,7 @@ void helper_raise_exception(CPUE2KState *env, int tt)
cpu_loop_exit(cs); cpu_loop_exit(cs);
} }
void helper_call(CPUE2KState *env, uint64_t ctpr, uint64_t cond) void helper_call(CPUE2KState *env, target_ulong ctpr, target_ulong cond)
{ {
int tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END); int tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END);
if (!cond) { if (!cond) {

View File

@ -1,5 +1,5 @@
DEF_HELPER_2(raise_exception, noreturn, env, int) DEF_HELPER_2(raise_exception, noreturn, env, int)
DEF_HELPER_3(call, void, env, i64, i64) DEF_HELPER_3(call, void, env, tl, tl)
DEF_HELPER_2(sxt, i64, i64, i64) DEF_HELPER_2(sxt, i64, i64, i64)
DEF_HELPER_1(debug_i32, void, i32) DEF_HELPER_1(debug_i32, void, i32)
DEF_HELPER_1(debug_i64, void, i64) DEF_HELPER_1(debug_i64, void, i64)

View File

@ -189,7 +189,7 @@ static target_ulong unpack_bundle(CPUE2KState *env, DisasContext *ctx)
static inline void save_state(DisasContext *dc) static inline void save_state(DisasContext *dc)
{ {
tcg_gen_movi_tl(e2k_cs.pc, dc->pc); tcg_gen_movi_tl(e2k_cs.pc, dc->pc);
tcg_gen_movi_tl(e2k_cs.pc, dc->npc); // tcg_gen_movi_tl(e2k_cs.pc, dc->npc);
} }
void e2k_gen_exception(DisasContext *dc, int which) void e2k_gen_exception(DisasContext *dc, int which)
@ -360,18 +360,18 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
break; break;
} }
case STATIC_JUMP: case STATIC_JUMP:
tcg_gen_mov_i64(e2k_cs.pc, dc->jmp.dest); tcg_gen_mov_tl(e2k_cs.pc, dc->jmp.dest);
tcg_gen_exit_tb(NULL, 0); tcg_gen_exit_tb(NULL, 0);
break; break;
case DYNAMIC_JUMP: { case DYNAMIC_JUMP: {
TCGv_i64 one = tcg_const_i64(1); TCGv_i64 one = tcg_const_tl(1);
TCGv_i64 npc = tcg_const_i64(dc->npc); TCGv_i64 npc = tcg_const_tl(dc->npc);
tcg_gen_movcond_i64(TCG_COND_EQ, e2k_cs.pc, tcg_gen_movcond_tl(TCG_COND_EQ, e2k_cs.pc,
dc->jmp.cond, one, dc->jmp.cond, one,
dc->jmp.dest, npc dc->jmp.dest, npc
); );
tcg_temp_free_i64(npc); tcg_temp_free(npc);
tcg_temp_free_i64(one); tcg_temp_free(one);
tcg_gen_exit_tb(NULL, 0); tcg_gen_exit_tb(NULL, 0);
break; break;
} }
@ -380,8 +380,8 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
break; break;
} }
tcg_temp_free_i64(dc->jmp.dest); tcg_temp_free(dc->jmp.dest);
tcg_temp_free_i64(dc->jmp.cond); tcg_temp_free(dc->jmp.cond);
} }
static void e2k_tr_disas_log(const DisasContextBase *db, static void e2k_tr_disas_log(const DisasContextBase *db,
@ -425,16 +425,12 @@ void e2k_tcg_initialize(void) {
{ &e2k_cs.wsz, offsetof(CPUE2KState, wsz), "wsz" }, { &e2k_cs.wsz, offsetof(CPUE2KState, wsz), "wsz" },
{ &e2k_cs.nfx, offsetof(CPUE2KState, nfx), "nfx" }, { &e2k_cs.nfx, offsetof(CPUE2KState, nfx), "nfx" },
{ &e2k_cs.dbl, offsetof(CPUE2KState, dbl), "dbl" }, { &e2k_cs.dbl, offsetof(CPUE2KState, dbl), "dbl" },
{ &e2k_cs.rbs, offsetof(CPUE2KState, rbs), "rbs" }, { &e2k_cs.br, offsetof(CPUE2KState, br), "br" },
{ &e2k_cs.rsz, offsetof(CPUE2KState, rsz), "rsz" },
{ &e2k_cs.rcur, offsetof(CPUE2KState, rcur), "rcur" },
{ &e2k_cs.syscall_wbs, offsetof(CPUE2KState, syscall_wbs), "syscall_wbs" }, { &e2k_cs.syscall_wbs, offsetof(CPUE2KState, syscall_wbs), "syscall_wbs" },
}; };
static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = { static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = {
{ &e2k_cs.pregs, offsetof(CPUE2KState, pregs), "pregs" }, { &e2k_cs.pregs, offsetof(CPUE2KState, pregs), "pregs" },
{ &e2k_cs.psz, offsetof(CPUE2KState, psz), "psz" },
{ &e2k_cs.pcur, offsetof(CPUE2KState, pcur), "pcur" },
{ &e2k_cs.usd_lo, offsetof(CPUE2KState, usd_lo), "usd.lo" }, { &e2k_cs.usd_lo, offsetof(CPUE2KState, usd_lo), "usd.lo" },
{ &e2k_cs.usd_hi, offsetof(CPUE2KState, usd_hi), "usd.hi" }, { &e2k_cs.usd_hi, offsetof(CPUE2KState, usd_hi), "usd.hi" },
{ &e2k_cs.lsr, offsetof(CPUE2KState, lsr), "lsr" }, { &e2k_cs.lsr, offsetof(CPUE2KState, lsr), "lsr" },

View File

@ -8,12 +8,6 @@
#define DYNAMIC_JUMP DISAS_TARGET_1 #define DYNAMIC_JUMP DISAS_TARGET_1
#define DISAS_CALL DISAS_TARGET_2 #define DISAS_CALL DISAS_TARGET_2
#define GEN_MASK(start, end) \
(((1UL << ((end) - (start) + 1)) - 1) << start)
#define GET_BIT(v, index) (((v) >> (index)) & 1)
#define GET_FIELD(v, start, end) \
(((v) >> (start)) & ((1 << ((end) - (start) + 1)) - 1))
#define IS_BASED(i) (((i) & 0x80) == 0) #define IS_BASED(i) (((i) & 0x80) == 0)
#define IS_REGULAR(i) (((i) & 0xc0) == 0x80) #define IS_REGULAR(i) (((i) & 0xc0) == 0x80)
#define IS_IMM5(i) (((i) & 0xe0) == 0xc0) #define IS_IMM5(i) (((i) & 0xe0) == 0xc0)
@ -56,11 +50,7 @@ typedef struct CPUE2KStateTCG {
TCGv_i32 wsz; TCGv_i32 wsz;
TCGv_i32 nfx; TCGv_i32 nfx;
TCGv_i32 dbl; TCGv_i32 dbl;
TCGv_i32 rbs; TCGv_i32 br;
TCGv_i32 rsz;
TCGv_i32 rcur;
TCGv_i64 psz;
TCGv_i64 pcur;
TCGv_i64 lsr; TCGv_i64 lsr;
TCGv_i32 syscall_wbs; TCGv_i32 syscall_wbs;
TCGv_ptr win_ptr; TCGv_ptr win_ptr;

View File

@ -506,7 +506,7 @@ static void gen_alopf_simple(DisasContext *dc, int chan)
case 0x1d: /* sard */ gen_alopf1_i64(dc, chan, tcg_gen_sar_i64); break; case 0x1d: /* sard */ gen_alopf1_i64(dc, chan, tcg_gen_sar_i64); break;
case 0x1e: /* TODO: getfs */ abort(); break; case 0x1e: /* TODO: getfs */ abort(); break;
case 0x1f: /* TODO: getfd */ abort(); break; case 0x1f: /* TODO: getfd */ abort(); break;
case 0x21: { // cmp{op}sd case 0x21: { // cmp{op}db
TCGv_i64 cpu_src1 = get_src1(dc, als); TCGv_i64 cpu_src1 = get_src1(dc, als);
TCGv_i64 cpu_src2 = get_src2(dc, als); TCGv_i64 cpu_src2 = get_src2(dc, als);
TCGv_i64 tmp_dst = e2k_get_temp_i64(dc); TCGv_i64 tmp_dst = e2k_get_temp_i64(dc);

View File

@ -3,7 +3,7 @@
#include "exec/log.h" #include "exec/log.h"
#include "translate.h" #include "translate.h"
static inline void gen_alc_dec(DisasContext *dc, TCGCond cond) static inline void gen_alc_dec(TCGCond cond, TCGv_i64 jmp_cond)
{ {
TCGv_i64 one = tcg_const_i64(1); TCGv_i64 one = tcg_const_i64(1);
TCGv_i32 zero = tcg_const_i32(0); TCGv_i32 zero = tcg_const_i32(0);
@ -24,9 +24,7 @@ static inline void gen_alc_dec(DisasContext *dc, TCGCond cond)
tcg_gen_extrh_i64_i32(t5, e2k_cs.lsr); tcg_gen_extrh_i64_i32(t5, e2k_cs.lsr);
tcg_gen_or_i32(t6, t5, t4); tcg_gen_or_i32(t6, t5, t4);
tcg_gen_concat_i32_i64(t7, t2, t6); tcg_gen_concat_i32_i64(t7, t2, t6);
tcg_gen_movcond_i64(cond, e2k_cs.lsr, tcg_gen_movcond_i64(cond, e2k_cs.lsr, jmp_cond, one, t7, e2k_cs.lsr);
dc->jmp.cond, one,
t7, e2k_cs.lsr);
tcg_temp_free_i64(t7); tcg_temp_free_i64(t7);
tcg_temp_free_i32(t6); tcg_temp_free_i32(t6);
@ -40,100 +38,144 @@ static inline void gen_alc_dec(DisasContext *dc, TCGCond cond)
tcg_temp_free_i64(one); tcg_temp_free_i64(one);
} }
static inline void gen_abp_inc(DisasContext *dc, TCGCond cond) static inline void gen_pcur_inc(TCGv_i32 ret, TCGv_i32 br)
{ {
TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i32 pcur = tcg_temp_new_i32();
TCGv_i64 t1 = tcg_temp_new_i64(); TCGv_i32 psz = tcg_temp_new_i32();
TCGv_i64 one = tcg_const_i64(1); TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_subi_i64(t0, e2k_cs.pcur, 1); tcg_gen_extract_i32(pcur, br, BR_PCUR_OFF, BR_PCUR_LEN);
tcg_gen_umin_i64(t1, t0, e2k_cs.psz); tcg_gen_extract_i32(psz, br, BR_PSZ_OFF, BR_PSZ_LEN);
tcg_gen_movcond_i64(cond, e2k_cs.pcur, dc->jmp.cond, one, t1, e2k_cs.pcur); tcg_gen_subi_i32(t0, pcur, 1);
tcg_gen_umin_i32(t1, t0, psz);
tcg_gen_deposit_i32(ret, br, t1, BR_PCUR_OFF, BR_PCUR_LEN);
tcg_temp_free_i64(one); tcg_temp_free_i32(t1);
tcg_temp_free_i64(t1); tcg_temp_free_i32(t0);
tcg_temp_free_i64(t0); tcg_temp_free_i32(psz);
tcg_temp_free_i32(pcur);
} }
static inline void gen_abn_inc(DisasContext *dc, TCGCond cond) static inline void gen_rcur_inc(TCGv_i32 ret, TCGv_i32 br)
{ {
TCGv_i32 rcur = tcg_temp_new_i32();
TCGv_i32 rsz = tcg_temp_new_i32();
TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32(); TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32(); TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_i32 t3 = tcg_temp_new_i32();
TCGv_i32 one = tcg_const_i32(1);
tcg_gen_subi_i32(t0, e2k_cs.rcur, 1); tcg_gen_extract_i32(rcur, br, BR_RCUR_OFF, BR_RCUR_LEN);
tcg_gen_umin_i32(t2, t0, e2k_cs.rsz); tcg_gen_extract_i32(rsz, br, BR_RSZ_OFF, BR_RSZ_LEN);
tcg_gen_extrl_i64_i32(t3, dc->jmp.cond); tcg_gen_subi_i32(t0, rcur, 1);
tcg_gen_movcond_i32(cond, e2k_cs.rcur, tcg_gen_umin_i32(t2, t0, rsz);
t3, one, tcg_gen_deposit_i32(ret, br, t2, BR_RCUR_OFF, BR_RCUR_LEN);
t2, e2k_cs.rcur);
tcg_temp_free_i32(one);
tcg_temp_free_i32(t3);
tcg_temp_free_i32(t2); tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
tcg_temp_free_i32(rsz);
tcg_temp_free_i32(rcur);
}
static inline void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond,
TCGv_i32 v1, TCGv_i32 v2)
{
TCGv_i32 one = tcg_const_i32(1);
TCGCond c;
switch (flag) {
case 0x00:
c = TCG_COND_NEVER;
break;
case 0x01:
c = TCG_COND_EQ;
break;
case 0x02:
c = TCG_COND_NE;
break;
case 0x03:
c = TCG_COND_ALWAYS;
break;
default:
g_assert_not_reached();
break;
}
tcg_gen_movcond_i32(c, ret, cond, one, v1, v2);
tcg_temp_free_i32(one);
} }
void e2k_win_commit(DisasContext *dc) void e2k_win_commit(DisasContext *dc)
{ {
TCGv_i32 cond = tcg_temp_new_i32();
// Change windowing registers after commit is done. // Change windowing registers after commit is done.
uint32_t ss = dc->bundle.ss; uint32_t ss = dc->bundle.ss;
// unsigned int vfdi = (ss & 0x04000000) >> 26; // unsigned int vfdi = (ss & 0x04000000) >> 26;
// unsigned int abg = (ss & 0x01800000) >> 23; // unsigned int abg = (ss & 0x01800000) >> 23;
unsigned int abp = GET_FIELD(ss, 18, 19);
unsigned int abn = GET_FIELD(ss, 21, 22);
tcg_gen_trunc_tl_i32(cond, dc->jmp.cond);
if (GET_BIT(ss, 16)) { if (GET_BIT(ss, 16)) {
gen_alc_dec(dc, TCG_COND_EQ); gen_alc_dec(TCG_COND_EQ, dc->jmp.cond);
} }
if (GET_BIT(ss, 17)) { if (GET_BIT(ss, 17)) {
gen_alc_dec(dc, TCG_COND_NE); gen_alc_dec(TCG_COND_NE, dc->jmp.cond);
} }
if (GET_BIT(ss, 18)) { if (abp) {
gen_abp_inc(dc, TCG_COND_EQ); TCGv_i32 t0 = tcg_temp_new_i32();
gen_pcur_inc(t0, e2k_cs.br);
gen_movcond_flag_i32(e2k_cs.br, abp, cond, t0, e2k_cs.br);
tcg_temp_free_i32(t0);
} }
if (GET_BIT(ss, 19)) {
gen_abp_inc(dc, TCG_COND_NE); if (abn) {
} TCGv_i32 t0 = tcg_temp_new_i32();
if (GET_BIT(ss, 21)) {
gen_abn_inc(dc, TCG_COND_EQ); gen_rcur_inc(t0, e2k_cs.br);
} gen_movcond_flag_i32(e2k_cs.br, abn, cond, t0, e2k_cs.br);
if (GET_BIT(ss, 22)) {
gen_abn_inc(dc, TCG_COND_NE); tcg_temp_free_i32(t0);
} }
tcg_temp_free_i32(cond);
} }
static inline void gen_is_last_iter(TCGv_i64 ret) static inline void gen_is_last_iter(TCGv ret)
{ {
TCGv_i64 t0 = tcg_temp_new_i64(); TCGv t0 = tcg_temp_new();
TCGv_i64 t1 = tcg_temp_new_i64(); TCGv t1 = tcg_temp_new();
TCGv_i64 t2 = tcg_temp_new_i64(); TCGv t2 = tcg_temp_new();
e2k_gen_lcnt(t0); e2k_gen_lcnt(t0);
tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t0, 2); tcg_gen_setcondi_tl(TCG_COND_LTU, t1, t0, 2);
tcg_gen_extract_i64(t2, e2k_cs.lsr, LSR_VLC_OFF, 1); tcg_gen_extract_tl(t2, e2k_cs.lsr, LSR_VLC_OFF, 1);
tcg_gen_and_i64(ret, t1, t2); tcg_gen_and_tl(ret, t1, t2);
tcg_temp_free(t2); tcg_temp_free(t2);
tcg_temp_free(t1); tcg_temp_free(t1);
tcg_temp_free(t0); tcg_temp_free(t0);
} }
static inline void gen_is_loop_end(TCGv_i64 ret) static inline void gen_is_loop_end(TCGv ret)
{ {
TCGv_i64 t0 = tcg_temp_new_i64(); TCGv t0 = tcg_temp_new();
TCGv_i64 t1 = tcg_temp_new_i64(); TCGv t1 = tcg_temp_new();
TCGv_i64 t2 = tcg_temp_new_i64(); TCGv t2 = tcg_temp_new();
e2k_gen_ecnt(t0); e2k_gen_ecnt(t0);
tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t0, 0); tcg_gen_setcondi_tl(TCG_COND_EQ, t1, t0, 0);
gen_is_last_iter(t2); gen_is_last_iter(t2);
tcg_gen_and_i64(ret, t1, t2); tcg_gen_and_tl(ret, t1, t2);
tcg_temp_free_i64(t2); tcg_temp_free(t2);
tcg_temp_free_i64(t1); tcg_temp_free(t1);
tcg_temp_free_i64(t0); tcg_temp_free(t0);
} }
static void gen_cs0(DisasContext *dc) static void gen_cs0(DisasContext *dc)
@ -324,6 +366,7 @@ static void gen_cs1(DisasContext *dc)
abort(); abort();
} else { } else {
uint32_t lts0 = bundle->lts[0]; uint32_t lts0 = bundle->lts[0];
tcg_gen_movi_i32(e2k_cs.wsz, GET_FIELD(lts0, 5, 11)); tcg_gen_movi_i32(e2k_cs.wsz, GET_FIELD(lts0, 5, 11));
tcg_gen_movi_i32(e2k_cs.nfx, GET_BIT(lts0, 4)); tcg_gen_movi_i32(e2k_cs.nfx, GET_BIT(lts0, 4));
@ -334,17 +377,15 @@ static void gen_cs1(DisasContext *dc)
} }
if (setbn) { if (setbn) {
unsigned int rcur = (cs1 & 0x0003f000) >> 12; TCGv_i32 bn = tcg_const_i32(GET_FIELD(cs1, BR_BN_OFF, BR_BN_END));
unsigned int rsz = (cs1 & 0x00000fc0) >> 6; tcg_gen_deposit_i32(e2k_cs.br, e2k_cs.br, bn, BR_BN_OFF, BR_BN_LEN);
unsigned int rbs = cs1 & 0x0000003f; tcg_temp_free_i32(bn);
tcg_gen_movi_i32(e2k_cs.rcur, rcur);
tcg_gen_movi_i32(e2k_cs.rsz, rsz);
tcg_gen_movi_i32(e2k_cs.rbs, rbs);
} }
if (setbp) { if (setbp) {
tcg_gen_movi_i64(e2k_cs.psz, GET_FIELD(cs1, 18, 23)); TCGv_i32 bp = tcg_const_i32(GET_FIELD(cs1, BR_PSZ_OFF, BR_PSZ_END));
tcg_gen_deposit_i32(e2k_cs.br, e2k_cs.br, bp, BR_BP_OFF, BR_BP_LEN);
tcg_temp_free_i32(bp);
} }
} else if (opc == SETEI) { } else if (opc == SETEI) {
/* Verify that CS1.param.sft = CS1.param[27] is equal to zero as required /* Verify that CS1.param.sft = CS1.param[27] is equal to zero as required
@ -458,58 +499,52 @@ static void gen_jmp(DisasContext *dc)
if (cond_type == 1) { if (cond_type == 1) {
dc->base.is_jmp = STATIC_JUMP; dc->base.is_jmp = STATIC_JUMP;
tcg_gen_movi_i64(dc->jmp.cond, 1); tcg_gen_movi_tl(dc->jmp.cond, 1);
} else { } else {
/* TODO: single assign */ /* TODO: single assign */
TCGv_i64 cond = tcg_temp_new_i64(); TCGv cond = tcg_temp_new();
TCGv preg = tcg_temp_new();
TCGv loop_end = tcg_temp_new();
TCGv not_loop_end = tcg_temp_new();
dc->base.is_jmp = DYNAMIC_JUMP; dc->base.is_jmp = DYNAMIC_JUMP;
if (cond_type == 2 || cond_type == 6 || cond_type == 0xf) { e2k_gen_preg(preg, psrc);
/* if pred is true */ gen_is_loop_end(loop_end);
tcg_gen_mov_i64(cond, e2k_get_preg(dc, psrc)); tcg_gen_setcondi_tl(TCG_COND_NE, not_loop_end, loop_end, 1);
} else if (cond_type == 3 || cond_type == 7 || cond_type == 0xe) {
/* if pred is false */ switch (cond_type) {
TCGv_i64 one = tcg_const_i64(1); case 0x2:
TCGv_i64 zero = tcg_const_i64(0); case 0x6:
tcg_gen_movcond_i64(TCG_COND_EQ, cond, case 0xf:
e2k_get_preg(dc, psrc), zero, tcg_gen_mov_tl(cond, preg);
one, zero); break;
tcg_temp_free_i64(zero); case 0x3:
tcg_temp_free_i64(one); case 0x7:
case 0xe:
tcg_gen_setcondi_tl(TCG_COND_NE, cond, preg, 1);
break;
default:
break;
} }
/* TODO: other kinds of conditions */ switch (cond_type) {
case 0x4:
if (cond_type == 4 || cond_type == 6 || cond_type == 0xe) { tcg_gen_mov_tl(cond, loop_end);
TCGv_i64 is_loop_end = tcg_temp_new_i64(); break;
case 0x5:
gen_is_loop_end(is_loop_end); tcg_gen_mov_tl(cond, not_loop_end);
break;
if (cond_type == 6 || cond_type == 0xe) { case 0x6:
tcg_gen_or_i64(cond, cond, is_loop_end); case 0xe:
} else { tcg_gen_or_tl(cond, cond, loop_end);
tcg_gen_mov_i64(cond, is_loop_end); break;
} case 0x7:
case 0xf:
tcg_temp_free_i64(is_loop_end); tcg_gen_and_tl(cond, cond, not_loop_end);
} break;
default:
if (cond_type == 5 || cond_type == 7 || cond_type == 0xf) { break;
TCGv_i64 is_loop_end = tcg_temp_new_i64();
TCGv_i64 t0 = tcg_temp_new_i64();
gen_is_loop_end(is_loop_end);
tcg_gen_setcondi_i64(TCG_COND_EQ, t0, is_loop_end, 0);
if(cond_type == 7 || cond_type == 0xf) {
tcg_gen_and_i64(cond, cond, t0);
} else {
tcg_gen_mov_i64(cond, t0);
}
tcg_temp_free_i64(t0);
tcg_temp_free_i64(is_loop_end);
} }
if (cond_type == 8) { if (cond_type == 8) {
@ -561,9 +596,12 @@ static void gen_jmp(DisasContext *dc)
abort(); abort();
} }
tcg_gen_mov_i64(dc->jmp.cond, cond); tcg_gen_mov_tl(dc->jmp.cond, cond);
tcg_temp_free_i64(cond); tcg_temp_free(not_loop_end);
tcg_temp_free(loop_end);
tcg_temp_free(preg);
tcg_temp_free(cond);
} }
/* TODO: check CPU behavior if present ibranch and ctpr is not zero */ /* TODO: check CPU behavior if present ibranch and ctpr is not zero */
@ -576,12 +614,8 @@ static void gen_jmp(DisasContext *dc)
dc->base.is_jmp = DISAS_CALL; dc->base.is_jmp = DISAS_CALL;
return; return;
} }
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_andi_i64(t0, e2k_cs.ctprs[ctpr], GEN_MASK(0, 47)); tcg_gen_andi_tl(dc->jmp.dest, e2k_cs.ctprs[ctpr], GEN_MASK(0, 47));
tcg_gen_mov_tl(dc->jmp.dest, t0);
tcg_temp_free_i64(t0);
} }
} }

View File

@ -7,15 +7,24 @@ static void gen_preg_offset(TCGv_i64 ret, int reg)
{ {
assert(reg < 32); assert(reg < 32);
TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i32 pcur = tcg_temp_new_i32();
TCGv_i64 t1 = tcg_temp_new_i64(); TCGv_i32 psz = tcg_temp_new_i32();
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
tcg_gen_addi_i64(t0, e2k_cs.pcur, reg); tcg_gen_extract_i32(pcur, e2k_cs.br, BR_PCUR_OFF, BR_PCUR_LEN);
e2k_gen_wrap_i64(t1, t0, e2k_cs.psz); tcg_gen_extract_i32(psz, e2k_cs.br, BR_PSZ_OFF, BR_PSZ_LEN);
tcg_gen_shli_i64(ret, t1, 1); tcg_gen_addi_i32(t0, pcur, reg);
e2k_gen_wrap_i32(t1, t0, psz);
tcg_gen_shli_i32(t2, t1, 1);
tcg_gen_extu_i32_i64(ret, t2);
tcg_temp_free_i64(t1); tcg_temp_free_i32(t2);
tcg_temp_free_i64(t0); tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(psz);
tcg_temp_free_i32(pcur);
} }
static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset) static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset)
@ -123,16 +132,21 @@ void e2k_gen_store_wreg(int reg, TCGv_i64 val)
static inline void gen_breg_start(TCGv_i32 ret) static inline void gen_breg_start(TCGv_i32 ret)
{ {
TCGv_i32 rbs = tcg_temp_new_i32();
TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_add_i32(t0, e2k_cs.wbs, e2k_cs.rbs); tcg_gen_extract_i32(rbs, e2k_cs.br, BR_RBS_OFF, BR_RBS_LEN);
tcg_gen_add_i32(t0, e2k_cs.wbs, rbs);
tcg_gen_shli_i32(ret, t0, 1); tcg_gen_shli_i32(ret, t0, 1);
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
tcg_temp_free_i32(rbs);
} }
static inline void gen_breg_offset(TCGv_i32 ret, int reg) static inline void gen_breg_offset(TCGv_i32 ret, int reg)
{ {
TCGv_i32 rcur = tcg_temp_new_i32();
TCGv_i32 rsz = tcg_temp_new_i32();
TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32(); TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32(); TCGv_i32 t2 = tcg_temp_new_i32();
@ -144,9 +158,11 @@ static inline void gen_breg_offset(TCGv_i32 ret, int reg)
/* TODO: exception: reg > (rsz * 2 + 2) */ /* TODO: exception: reg > (rsz * 2 + 2) */
/* t = (reg + rcur * 2) % (rsz * 2 + 2) */ /* t = (reg + rcur * 2) % (rsz * 2 + 2) */
tcg_gen_shli_i32(t0, e2k_cs.rcur, 1); tcg_gen_extract_i32(rcur, e2k_cs.br, BR_RCUR_OFF, BR_RCUR_LEN);
tcg_gen_extract_i32(rsz, e2k_cs.br, BR_RSZ_OFF, BR_RSZ_LEN);
tcg_gen_shli_i32(t0, rcur, 1);
tcg_gen_addi_i32(t1, t0, reg); tcg_gen_addi_i32(t1, t0, reg);
tcg_gen_addi_i32(t2, e2k_cs.rsz, 1); tcg_gen_addi_i32(t2, rsz, 1);
tcg_gen_shli_i32(t3, t2, 1); tcg_gen_shli_i32(t3, t2, 1);
e2k_gen_wrap_i32(t4, t1, t3); e2k_gen_wrap_i32(t4, t1, t3);
@ -167,6 +183,8 @@ static inline void gen_breg_offset(TCGv_i32 ret, int reg)
tcg_temp_free_i32(t2); tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
tcg_temp_free_i32(rsz);
tcg_temp_free_i32(rcur);
} }
static inline void gen_breg_ptr(TCGv_ptr ret, int reg) static inline void gen_breg_ptr(TCGv_ptr ret, int reg)