target: e2k: Add loop_end/not_loop_end condition.
This commit is contained in:
parent
37acf287ad
commit
24b5d5c7fb
|
@ -84,6 +84,7 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
|||
qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n",
|
||||
env->usd_hi, env->usd_lo);
|
||||
qemu_fprintf(f, "psz: %d, pcur: %d\n", (int) env->psz, (int) env->pcur);
|
||||
qemu_fprintf(f, "lsr: %016lx\n", env->lsr);
|
||||
|
||||
for (i = 0; i < 192; i += 4) {
|
||||
const char *s1 = i < 10 ? " " : (i < 100 ? " " : "");
|
||||
|
|
|
@ -13,6 +13,35 @@ void e2k_tcg_initialize(void);
|
|||
// size of regular reg in bytes
|
||||
#define REG_SIZE (sizeof(target_ulong))
|
||||
|
||||
#define CTPR_BASE_OFF 0
|
||||
#define CTPR_BASE_END 47
|
||||
#define CTPR_TAG_OFF 54
|
||||
#define CTPR_TAG_END 56
|
||||
#define CTPR_OPC_OFF 57
|
||||
#define CTPR_OPC_END 58
|
||||
#define CTPR_IPD_OFF 59
|
||||
#define CTPR_IPD_END 60
|
||||
|
||||
#define LSR_LCNT_OFF 0 /* loop counter */
|
||||
#define LSR_LCNT_END 31
|
||||
#define LSR_LCNT_LEN (LSR_LCNT_END - LSR_LCNT_OFF + 1)
|
||||
#define LSR_ECNT_OFF 32 /* epilogue counter */
|
||||
#define LSR_ECNT_END 36
|
||||
#define LSR_ECNT_LEN (LSR_ECNT_END - LSR_ECNT_OFF + 1)
|
||||
#define LSR_VLC_OFF 37 /* loop count valid bit */
|
||||
#define LSR_OVER_OFF 38 /* loop count overflow */
|
||||
#define LSR_LDMC_OFF 39 /* loads manual control */
|
||||
#define LSR_LDOVL_OFF 40 /* load overlap */
|
||||
#define LSR_LDOVL_END 47
|
||||
#define LSR_LDOVL_SIZE (LSR_LDOVL_END - LSR_LDOVL_OFF + 1)
|
||||
#define LSR_PCNT_OFF 48 /* prologue counter */
|
||||
#define LSR_PCNT_END 52
|
||||
#define LSR_PCNT_LEN (LSR_PCNT_END - LSR_PCNT_OFF + 1)
|
||||
#define LSR_STRMD_OFF 53 /* store remainder counter */
|
||||
#define LSR_STRMD_END 59
|
||||
#define LSR_STRMD_LEN (LSR_STRMD_END - LSR_STRMD_OFF + 1)
|
||||
#define LSR_SEMC_OFF /* side effects manual control */
|
||||
|
||||
typedef enum {
|
||||
E2K_EXCP_UNIMPL = 0x01,
|
||||
E2K_EXCP_SYSCALL = 0x02,
|
||||
|
@ -43,6 +72,8 @@ typedef struct CPUArchState {
|
|||
uint64_t psz; // pred regs window size
|
||||
uint64_t pcur; // pred regs current offset
|
||||
|
||||
uint64_t lsr; /* loop status register */
|
||||
|
||||
uint32_t syscall_wbs;
|
||||
|
||||
uint64_t usd_lo;
|
||||
|
|
|
@ -5,7 +5,6 @@ e2k_ss.add(files(
|
|||
'helper_int.c',
|
||||
'translate.c',
|
||||
'translate/state.c',
|
||||
'translate/win.c',
|
||||
'translate/control.c',
|
||||
'translate/alc.c',
|
||||
))
|
||||
|
|
|
@ -435,8 +435,9 @@ void e2k_tcg_initialize(void) {
|
|||
{ &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_hi, offsetof(CPUE2KState, usd_hi), "%usd.hi" },
|
||||
{ &e2k_cs.usd_lo, offsetof(CPUE2KState, usd_lo), "usd.lo" },
|
||||
{ &e2k_cs.usd_hi, offsetof(CPUE2KState, usd_hi), "usd.hi" },
|
||||
{ &e2k_cs.lsr, offsetof(CPUE2KState, lsr), "lsr" },
|
||||
};
|
||||
|
||||
static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
|
||||
|
|
|
@ -32,15 +32,6 @@
|
|||
#define GET_LIT(i) ((i) & 0x03)
|
||||
#define GET_GLOBAL(i) ((i) & 0x1f)
|
||||
|
||||
#define CTPR_BASE_OFF 0
|
||||
#define CTPR_BASE_END 47
|
||||
#define CTPR_TAG_OFF 54
|
||||
#define CTPR_TAG_END 56
|
||||
#define CTPR_OPC_OFF 57
|
||||
#define CTPR_OPC_END 58
|
||||
#define CTPR_IPD_OFF 59
|
||||
#define CTPR_IPD_END 60
|
||||
|
||||
typedef enum {
|
||||
CTPR_TAG_RETURN = 0x2,
|
||||
CTPR_TAG_DISP = 0x3,
|
||||
|
@ -70,6 +61,7 @@ typedef struct CPUE2KStateTCG {
|
|||
TCGv_i32 rcur;
|
||||
TCGv_i64 psz;
|
||||
TCGv_i64 pcur;
|
||||
TCGv_i64 lsr;
|
||||
TCGv_i32 syscall_wbs;
|
||||
TCGv_ptr win_ptr;
|
||||
TCGv_i64 wregs[WREGS_SIZE];
|
||||
|
@ -142,7 +134,9 @@ typedef struct DisasContext {
|
|||
int t64_len;
|
||||
int ttl_len;
|
||||
|
||||
/* TODO: move to CPUE2KState */
|
||||
Result alc[6];
|
||||
/* TODO: move to CPUE2KState */
|
||||
struct {
|
||||
TCGv dest;
|
||||
TCGv_i64 cond;
|
||||
|
@ -216,6 +210,26 @@ static inline void e2k_gen_set_field_i64(TCGv_i64 ret, TCGv_i64 val,
|
|||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void e2k_gen_lcnt(TCGv_i64 ret)
|
||||
{
|
||||
tcg_gen_andi_i64(ret, e2k_cs.lsr, (1UL << 32) - 1);
|
||||
}
|
||||
|
||||
static inline void e2k_gen_ecnt(TCGv_i64 ret)
|
||||
{
|
||||
tcg_gen_extract_i64(ret, e2k_cs.lsr, LSR_ECNT_OFF, LSR_ECNT_LEN);
|
||||
}
|
||||
|
||||
static inline void e2k_gen_pcnt(TCGv_i32 ret)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_extract_i64(t0, e2k_cs.lsr, LSR_PCNT_OFF, LSR_PCNT_LEN);
|
||||
tcg_gen_extrl_i64_i32(ret, t0);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
void e2k_gen_preg(TCGv_i64 ret, int reg);
|
||||
TCGv_i64 e2k_get_preg(DisasContext *dc, int reg);
|
||||
void e2k_gen_store_preg(int reg, TCGv_i64 val);
|
||||
|
|
|
@ -266,6 +266,9 @@ static inline void gen_rr_i64(TCGv_i64 ret, uint8_t state_reg)
|
|||
case 0x2d: /* %usd.lo */
|
||||
tcg_gen_mov_i64(ret, e2k_cs.usd_lo);
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
tcg_gen_mov_i64(ret, e2k_cs.lsr);
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
|
@ -308,6 +311,9 @@ static inline void gen_rw_i64(uint8_t state_reg, TCGv_i64 val)
|
|||
/* FIXME: user cannot write */
|
||||
tcg_gen_mov_i64(e2k_cs.usd_lo, val);
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
tcg_gen_mov_i64(e2k_cs.lsr, val);
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
|
|
|
@ -3,6 +3,137 @@
|
|||
#include "exec/log.h"
|
||||
#include "translate.h"
|
||||
|
||||
static inline void gen_alc_dec(DisasContext *dc, TCGCond cond)
|
||||
{
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
TCGv_i32 zero = tcg_const_i32(0);
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
TCGv_i32 t3 = tcg_temp_new_i32();
|
||||
TCGv_i32 t4 = tcg_temp_new_i32();
|
||||
TCGv_i32 t5 = tcg_temp_new_i32();
|
||||
TCGv_i32 t6 = tcg_temp_new_i32();
|
||||
TCGv_i64 t7 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_extrl_i64_i32(t0, e2k_cs.lsr);
|
||||
tcg_gen_subi_i32(t1, t0, 1);
|
||||
tcg_gen_movcond_i32(TCG_COND_LTU, t2, t1, t0, t1, t0);
|
||||
tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
|
||||
tcg_gen_shli_i32(t4, t3, LSR_OVER_OFF - 32);
|
||||
tcg_gen_extrh_i64_i32(t5, e2k_cs.lsr);
|
||||
tcg_gen_or_i32(t6, t5, t4);
|
||||
tcg_gen_concat_i32_i64(t7, t2, t6);
|
||||
tcg_gen_movcond_i64(cond, e2k_cs.lsr,
|
||||
dc->jmp.cond, one,
|
||||
t7, e2k_cs.lsr);
|
||||
|
||||
tcg_temp_free_i64(t7);
|
||||
tcg_temp_free_i32(t6);
|
||||
tcg_temp_free_i32(t5);
|
||||
tcg_temp_free_i32(t4);
|
||||
tcg_temp_free_i32(t3);
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(zero);
|
||||
tcg_temp_free_i64(one);
|
||||
}
|
||||
|
||||
static inline void gen_abp_inc(DisasContext *dc, TCGCond cond)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
|
||||
tcg_gen_subi_i64(t0, e2k_cs.pcur, 1);
|
||||
tcg_gen_umin_i64(t1, t0, e2k_cs.psz);
|
||||
tcg_gen_movcond_i64(cond, e2k_cs.pcur, dc->jmp.cond, one, t1, e2k_cs.pcur);
|
||||
|
||||
tcg_temp_free_i64(one);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void gen_abn_inc(DisasContext *dc, TCGCond cond)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 one = tcg_const_i32(1);
|
||||
TCGv_i32 jmp_cond = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_addi_i32(t0, e2k_cs.rcur, 2);
|
||||
e2k_gen_wrap_i32(t1, t0, e2k_cs.rsz);
|
||||
tcg_gen_extrl_i64_i32(jmp_cond, dc->jmp.cond);
|
||||
tcg_gen_movcond_i32(cond, e2k_cs.rcur,
|
||||
jmp_cond, one,
|
||||
t1, e2k_cs.rcur);
|
||||
|
||||
tcg_temp_free_i32(jmp_cond);
|
||||
tcg_temp_free_i32(one);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
void e2k_win_commit(DisasContext *dc)
|
||||
{
|
||||
// Change windowing registers after commit is done.
|
||||
uint32_t ss = dc->bundle.ss;
|
||||
// unsigned int vfdi = (ss & 0x04000000) >> 26;
|
||||
// unsigned int abg = (ss & 0x01800000) >> 23;
|
||||
|
||||
if (GET_BIT(ss, 16)) {
|
||||
gen_alc_dec(dc, TCG_COND_EQ);
|
||||
}
|
||||
if (GET_BIT(ss, 17)) {
|
||||
gen_alc_dec(dc, TCG_COND_NE);
|
||||
}
|
||||
if (GET_BIT(ss, 18)) {
|
||||
gen_abp_inc(dc, TCG_COND_EQ);
|
||||
}
|
||||
if (GET_BIT(ss, 19)) {
|
||||
gen_abp_inc(dc, TCG_COND_NE);
|
||||
}
|
||||
if (GET_BIT(ss, 21)) {
|
||||
gen_abn_inc(dc, TCG_COND_EQ);
|
||||
}
|
||||
if (GET_BIT(ss, 22)) {
|
||||
gen_abn_inc(dc, TCG_COND_NE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_is_last_iter(TCGv_i64 ret)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
|
||||
e2k_gen_lcnt(t0);
|
||||
tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t0, 2);
|
||||
tcg_gen_extract_i64(t2, e2k_cs.lsr, LSR_VLC_OFF, 1);
|
||||
tcg_gen_and_i64(ret, t1, t2);
|
||||
|
||||
tcg_temp_free(t2);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
|
||||
static inline void gen_is_loop_end(TCGv_i64 ret)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
|
||||
e2k_gen_ecnt(t0);
|
||||
tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t0, 0);
|
||||
gen_is_last_iter(t2);
|
||||
tcg_gen_and_i64(ret, t1, t2);
|
||||
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static void gen_cs0(DisasContext *dc)
|
||||
{
|
||||
typedef enum {
|
||||
|
@ -327,16 +458,19 @@ static void gen_jmp(DisasContext *dc)
|
|||
dc->base.is_jmp = STATIC_JUMP;
|
||||
tcg_gen_movi_i64(dc->jmp.cond, 1);
|
||||
} else {
|
||||
/* TODO: single assign */
|
||||
TCGv_i64 cond = tcg_temp_new_i64();
|
||||
|
||||
dc->base.is_jmp = DYNAMIC_JUMP;
|
||||
|
||||
if (cond_type == 2 || cond_type == 6 || cond_type == 0xf) {
|
||||
/* if pred is true */
|
||||
tcg_gen_mov_i64(dc->jmp.cond, e2k_get_preg(dc, psrc));
|
||||
tcg_gen_mov_i64(cond, e2k_get_preg(dc, psrc));
|
||||
} else if (cond_type == 3 || cond_type == 7 || cond_type == 0xe) {
|
||||
/* if pred is false */
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
TCGv_i64 zero = tcg_const_i64(0);
|
||||
tcg_gen_movcond_i64(TCG_COND_EQ, dc->jmp.cond,
|
||||
tcg_gen_movcond_i64(TCG_COND_EQ, cond,
|
||||
e2k_get_preg(dc, psrc), zero,
|
||||
one, zero);
|
||||
tcg_temp_free_i64(zero);
|
||||
|
@ -345,27 +479,35 @@ static void gen_jmp(DisasContext *dc)
|
|||
|
||||
/* TODO: other kinds of conditions */
|
||||
|
||||
if (cond_type == 4
|
||||
|| cond_type == 6
|
||||
|| cond_type == 0xe)
|
||||
{
|
||||
if (cond_type == 4 || cond_type == 6 || cond_type == 0xe) {
|
||||
TCGv_i64 is_loop_end = tcg_temp_new_i64();
|
||||
|
||||
gen_is_loop_end(is_loop_end);
|
||||
|
||||
if (cond_type == 6 || cond_type == 0xe) {
|
||||
// or
|
||||
tcg_gen_or_i64(cond, cond, is_loop_end);
|
||||
} else {
|
||||
tcg_gen_mov_i64(cond, is_loop_end);
|
||||
}
|
||||
|
||||
// %LOOP_END
|
||||
tcg_temp_free_i64(is_loop_end);
|
||||
}
|
||||
|
||||
if (cond_type == 5
|
||||
|| cond_type == 7
|
||||
|| cond_type == 0xf)
|
||||
{
|
||||
if(cond_type == 7
|
||||
|| cond_type == 0xf)
|
||||
{
|
||||
// AND
|
||||
if (cond_type == 5 || cond_type == 7 || cond_type == 0xf) {
|
||||
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);
|
||||
}
|
||||
// %NOT_LOOP_END
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(is_loop_end);
|
||||
}
|
||||
|
||||
if (cond_type == 8) {
|
||||
|
@ -416,6 +558,10 @@ static void gen_jmp(DisasContext *dc)
|
|||
qemu_log_mask(LOG_UNIMP, "Undefined control transfer type %#x\n", cond_type);
|
||||
abort();
|
||||
}
|
||||
|
||||
tcg_gen_mov_i64(dc->jmp.cond, cond);
|
||||
|
||||
tcg_temp_free_i64(cond);
|
||||
}
|
||||
|
||||
/* TODO: check CPU behavior if present ibranch and ctpr is not zero */
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "exec/log.h"
|
||||
#include "translate.h"
|
||||
|
||||
static inline void gen_abp_inc(DisasContext *dc, TCGCond cond)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
|
||||
tcg_gen_subi_i64(t0, e2k_cs.pcur, 1);
|
||||
tcg_gen_umin_i64(t1, t0, e2k_cs.psz);
|
||||
tcg_gen_movcond_i64(cond, e2k_cs.pcur, dc->jmp.cond, one, t1, e2k_cs.pcur);
|
||||
|
||||
tcg_temp_free_i64(one);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void gen_abn_inc(DisasContext *dc, TCGCond cond)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 one = tcg_const_i32(1);
|
||||
TCGv_i32 jmp_cond = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_addi_i32(t0, e2k_cs.rcur, 2);
|
||||
e2k_gen_wrap_i32(t1, t0, e2k_cs.rsz);
|
||||
tcg_gen_extrl_i64_i32(jmp_cond, dc->jmp.cond);
|
||||
tcg_gen_movcond_i32(cond, e2k_cs.rcur,
|
||||
jmp_cond, one,
|
||||
t1, e2k_cs.rcur);
|
||||
|
||||
tcg_temp_free_i32(jmp_cond);
|
||||
tcg_temp_free_i32(one);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
void e2k_win_commit(DisasContext *dc)
|
||||
{
|
||||
// Change windowing registers after commit is done.
|
||||
uint32_t ss = dc->bundle.ss;
|
||||
// unsigned int vfdi = (ss & 0x04000000) >> 26;
|
||||
// unsigned int abg = (ss & 0x01800000) >> 23;
|
||||
// unsigned int alc = (ss & 0x00030000) >> 16;
|
||||
|
||||
if (GET_BIT(ss, 21)) {
|
||||
gen_abn_inc(dc, TCG_COND_EQ);
|
||||
}
|
||||
if (GET_BIT(ss, 22)) {
|
||||
gen_abn_inc(dc, TCG_COND_NE);
|
||||
}
|
||||
if (GET_BIT(ss, 18)) {
|
||||
gen_abp_inc(dc, TCG_COND_EQ);
|
||||
}
|
||||
if (GET_BIT(ss, 19)) {
|
||||
gen_abp_inc(dc, TCG_COND_NE);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue