qemu-e2k/target/e2k/translate.h

267 lines
6.2 KiB
C

#ifndef E2K_TRANSLATE_H
#define E2K_TRANSLATE_H
#include "tcg/tcg-op.h"
#include "exec/translator.h"
/* ibranch disp */
#define DISAS_JUMP_STATIC DISAS_TARGET_0
/* ibranch disp ? cond */
#define DISAS_BRANCH_STATIC DISAS_TARGET_1
/*
* ct %ctprN
* call %ctprN, wbs=M
* */
#define DISAS_JUMP DISAS_TARGET_2
/*
* ct %ctprN ? cond
* call %ctprN, wbs=M ? cond
*/
#define DISAS_BRANCH DISAS_TARGET_3
#define IS_BASED(i) (((i) & 0x80) == 0)
#define IS_REGULAR(i) (((i) & 0xc0) == 0x80)
#define IS_IMM5(i) (((i) & 0xe0) == 0xc0)
#define IS_IMM4(i) (((i) & 0xf0) == 0xc0)
#define IS_LIT(i) (((i) & 0xf0) == 0xd0)
#define IS_LIT16_LO(i) (((i) & 0x0e) == 0x00)
#define IS_LIT16_HI(i) (((i) & 0x0e) == 0x04)
#define IS_LIT32(i) (((i) & 0x0c) == 0x08)
#define IS_LIT64(i) (((i) & 0x0c) == 0x0c)
#define IS_GLOBAL(i) (((i) & 0xe0) == 0xe0)
#define GET_BASED(i) ((i) & 0x7f)
#define GET_REGULAR(i) ((i) & 0x3f)
#define GET_IMM5(i) ((i) & 0x1f)
#define GET_IMM4(i) ((i) & 0x0f)
#define GET_LIT(i) ((i) & 0x03)
#define GET_GLOBAL(i) ((i) & 0x1f)
typedef enum {
CTPR_TAG_RETURN = 0x2,
CTPR_TAG_DISP = 0x3,
CTPR_TAG_LDISP = 0x3,
CTPR_TAG_SDISP = 0x5,
} CtprTag;
typedef enum {
CTPR_OPC_LDISP = 0x1,
} CtprOpc;
typedef enum {
ALES_NONE = 0x00,
ALES_PRESENT = 0x01,
ALES_ALLOCATED = 0x02,
} AlesFlag;
typedef struct CPUE2KStateTCG {
TCGv pc;
TCGv npc;
TCGv ctprs[4];
TCGv cond;
TCGv_i64 lsr;
TCGv_i32 call_wbs;
TCGv_i64 wregs[WREGS_SIZE];
TCGv_i64 gregs[GREGS_SIZE];
TCGv_ptr wptr; /* pointer to wregs */
TCGv_i32 woff; /* holds wbs * 2 */
TCGv_i32 wsize; /* holds wsz * 2 */
TCGv_i32 boff; /* holds rbs * 2 */
TCGv_i32 bsize; /* holds rsz * 2 + 2 */
TCGv_i32 bcur; /* holds rcur * 2 */
TCGv_i64 pregs;
TCGv_i32 psize; /* holds psz */
TCGv_i32 pcur; /* holds pcur */
} CPUE2KStateTCG;
extern struct CPUE2KStateTCG e2k_cs;
typedef struct UnpackedBundle {
uint32_t hs;
uint32_t ss;
uint32_t als[6];
uint32_t cs0;
uint16_t ales[6];
uint32_t cs1;
uint16_t aas[6];
uint32_t lts[4];
uint32_t pls[3];
uint32_t cds[3];
bool ss_present;
bool als_present[6];
bool cs0_present;
AlesFlag ales_present[6];
bool cs1_present;
bool aas_present[6];
bool lts_present[4];
bool pls_present[3];
bool cds_present[3];
} UnpackedBundle;
enum ResultType {
RESULT_NONE,
RESULT_BASED_REG,
RESULT_REGULAR_REG,
RESULT_GLOBAL_REG,
RESULT_PREG,
};
typedef struct {
enum ResultType tag;
union {
struct {
unsigned int i;
TCGv_i64 v;
} reg;
} u;
} Result;
typedef struct DisasContext {
DisasContextBase base;
UnpackedBundle bundle;
target_ulong pc;
target_ulong npc;
int jump_ctpr;
int mmuidx;
int version;
// Temporary values.
TCGv_i32 t32[16];
TCGv_i64 t64[32];
TCGv ttl[8];
// Allocated temporary values count.
int t32_len;
int t64_len;
int ttl_len;
/* TODO: move to CPUE2KState */
Result alc[6];
/* TODO: move to CPUE2KState */
struct {
target_ulong dest; /* ibranch dst */
} jmp;
} DisasContext;
static inline TCGv_i32 e2k_get_temp_i32(DisasContext *dc)
{
assert(dc->t32_len < ARRAY_SIZE(dc->t32));
return dc->t32[dc->t32_len++] = tcg_temp_new_i32();
}
static inline TCGv_i64 e2k_get_temp_i64(DisasContext *dc)
{
assert(dc->t64_len < ARRAY_SIZE(dc->t64));
return dc->t64[dc->t64_len++] = tcg_temp_new_i64();
}
static inline TCGv e2k_get_temp(DisasContext *dc)
{
assert(dc->ttl_len < ARRAY_SIZE(dc->ttl));
return dc->ttl[dc->ttl_len++] = tcg_temp_new();
}
// FIXME: x must not be greater than y * 2
static inline void e2k_gen_wrap_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y)
{
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_sub_i32(t0, x, y);
tcg_gen_movcond_i32(TCG_COND_LTU, ret, x, y, x, t0);
tcg_temp_free_i32(t0);
}
// FIXME: x must not be greater than y * 2
static inline void e2k_gen_wrapi_i32(TCGv_i32 ret, TCGv_i32 x, uint32_t y)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_const_i32(y);
tcg_gen_sub_i32(t0, x, t1);
tcg_gen_movcond_i32(TCG_COND_LTU, ret, x, t1, x, t0);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
// FIXME: x must not be greater than y * 2
static inline void e2k_gen_wrap_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y)
{
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_sub_i64(t0, x, y);
tcg_gen_movcond_i64(TCG_COND_LTU, ret, x, y, x, t0);
tcg_temp_free_i64(t0);
}
static inline void e2k_gen_get_field_i64(TCGv_i64 ret, TCGv_i64 val,
unsigned int start, unsigned int end)
{
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_andi_i64(t0, val, GEN_MASK(start, end));
tcg_gen_shli_i64(ret, t0, start);
tcg_temp_free_i64(t0);
}
static inline void e2k_gen_set_field_i64(TCGv_i64 ret, TCGv_i64 val,
uint64_t field, unsigned int start, unsigned int end)
{
uint64_t mask = GEN_MASK(start, end);
TCGv_i64 t0 = tcg_const_i64(~mask);
TCGv_i64 t1 = tcg_const_i64((field << start) & mask);
TCGv_i64 t2 = tcg_temp_new_i64();
tcg_gen_and_i64(t2, val, t0);
tcg_gen_or_i64(ret, t2, t1);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
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);
TCGv_i64 e2k_get_wreg(DisasContext *dc, int reg);
void e2k_gen_store_wreg(int reg, TCGv_i64 val);
TCGv_i64 e2k_get_breg(DisasContext *dc, int reg);
void e2k_gen_store_breg(int reg, TCGv_i64 val);
TCGv_i64 e2k_get_greg(DisasContext *dc, int reg);
void e2k_gen_store_greg(int reg, TCGv_i64 val);
void e2k_gen_exception(DisasContext *dc, int which);
void e2k_control_gen(DisasContext *dc);
void e2k_alc_gen(DisasContext *dc);
void e2k_alc_commit(DisasContext *dc);
void e2k_win_commit(DisasContext *dc);
#endif