target: e2k: Try to impl syscall.
This commit is contained in:
parent
42cd4b2c56
commit
779fc80db4
|
@ -37,6 +37,19 @@ void cpu_loop(CPUE2KState *env)
|
|||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case E2K_EXCP_SYSCALL: {
|
||||
/* TODO: wrap register indices */
|
||||
uint64_t *regs = &env->wregs[env->wbs * 2];
|
||||
abi_ulong ret = do_syscall(env, regs[0],
|
||||
regs[1], regs[2], regs[3], regs[4],
|
||||
regs[5], regs[6], regs[7], regs[8]);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
/* TODO: restart syscall */
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
regs[0] = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
|
||||
cpu_dump_state(cs, stderr, 0);
|
||||
|
|
|
@ -13,6 +13,10 @@ void e2k_tcg_initialize(void);
|
|||
// size of regular reg in bytes
|
||||
#define REG_SIZE (sizeof(target_ulong))
|
||||
|
||||
typedef enum {
|
||||
E2K_EXCP_SYSCALL = 0x01,
|
||||
} Exception;
|
||||
|
||||
struct e2k_def_t {
|
||||
const char *name;
|
||||
uint32_t isa_version;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "translate.h"
|
||||
|
||||
void helper_raise_exception(CPUE2KState *env, int tt)
|
||||
{
|
||||
|
@ -11,3 +12,14 @@ void helper_raise_exception(CPUE2KState *env, int tt)
|
|||
cs->exception_index = tt;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
void helper_check_syscall_ctpr(CPUE2KState *env, uint64_t ctpr)
|
||||
{
|
||||
int tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END);
|
||||
if (tag == CTPR_TAG_SDISP) {
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
cs->exception_index = E2K_EXCP_SYSCALL;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// include/exec/helper-proto.h needs this file
|
||||
|
||||
DEF_HELPER_2(raise_exception, noreturn, env, int)
|
||||
DEF_HELPER_2(check_syscall_ctpr, void, env, i64)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/log.h"
|
||||
#include "disas/disas.h"
|
||||
#include "translate.h"
|
||||
|
@ -202,76 +200,6 @@ void e2k_gen_exception(DisasContext *dc, int which)
|
|||
dc->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static target_ulong disas_e2k_insn(DisasContext *dc, CPUState *cs)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
UnpackedBundle *bundle = &dc->bundle;
|
||||
unsigned int bundle_len = unpack_bundle(env, dc->pc, bundle);
|
||||
/* TODO: exception, check bundle_len */
|
||||
target_ulong pc_next = dc->pc + bundle_len;
|
||||
|
||||
dc->jmp.dest = tcg_const_i64(0);
|
||||
dc->jmp.cond = tcg_const_i64(0);
|
||||
|
||||
e2k_alc_gen(dc);
|
||||
e2k_control_gen(dc);
|
||||
|
||||
e2k_alc_commit(dc);
|
||||
e2k_win_commit(dc);
|
||||
|
||||
/* Control transfer */
|
||||
switch(dc->base.is_jmp) {
|
||||
case DISAS_NEXT:
|
||||
case DISAS_TOO_MANY:
|
||||
dc->base.pc_next = pc_next;
|
||||
break;
|
||||
case DISAS_NORETURN:
|
||||
/* exception */
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->pc);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case STATIC_JUMP:
|
||||
tcg_gen_mov_i64(e2k_cs.pc, dc->jmp.dest);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case DYNAMIC_JUMP: {
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
TCGv_i64 next = tcg_const_i64(pc_next);
|
||||
tcg_gen_movcond_i64(TCG_COND_EQ, e2k_cs.pc,
|
||||
dc->jmp.cond, one,
|
||||
dc->jmp.dest, next
|
||||
);
|
||||
tcg_temp_free_i64(next);
|
||||
tcg_temp_free_i64(one);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* TODO: unreachable */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free_i64(dc->jmp.dest);
|
||||
tcg_temp_free_i64(dc->jmp.cond);
|
||||
|
||||
/* Free temporary values */
|
||||
while(dc->t32_len) {
|
||||
tcg_temp_free_i32(dc->t32[--dc->t32_len]);
|
||||
}
|
||||
|
||||
while(dc->t64_len) {
|
||||
tcg_temp_free_i64(dc->t64[--dc->t64_len]);
|
||||
}
|
||||
|
||||
while(dc->ttl_len) {
|
||||
tcg_temp_free(dc->ttl[--dc->ttl_len]);
|
||||
}
|
||||
|
||||
return pc_next;
|
||||
}
|
||||
|
||||
static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(db, DisasContext, base);
|
||||
|
@ -299,19 +227,80 @@ static bool e2k_tr_breakpoint_check(DisasContextBase *db, CPUState *cs,
|
|||
static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(db, DisasContext, base);
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
UnpackedBundle *bundle = &dc->bundle;
|
||||
dc->pc = dc->base.pc_next;
|
||||
disas_e2k_insn(dc, cs);
|
||||
unsigned int bundle_len = unpack_bundle(env, dc->pc, bundle);
|
||||
/* TODO: exception, check bundle_len */
|
||||
dc->base.pc_next = dc->pc + bundle_len;
|
||||
|
||||
e2k_alc_gen(dc);
|
||||
e2k_control_gen(dc);
|
||||
|
||||
e2k_alc_commit(dc);
|
||||
e2k_win_commit(dc);
|
||||
|
||||
/* Free temporary values */
|
||||
while(dc->t32_len) {
|
||||
tcg_temp_free_i32(dc->t32[--dc->t32_len]);
|
||||
}
|
||||
|
||||
while(dc->t64_len) {
|
||||
tcg_temp_free_i64(dc->t64[--dc->t64_len]);
|
||||
}
|
||||
|
||||
while(dc->ttl_len) {
|
||||
tcg_temp_free(dc->ttl[--dc->ttl_len]);
|
||||
}
|
||||
}
|
||||
|
||||
static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(db, DisasContext, base);
|
||||
|
||||
dc->jmp.dest = tcg_const_i64(0);
|
||||
dc->jmp.cond = tcg_const_i64(0);
|
||||
}
|
||||
|
||||
static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
|
||||
{
|
||||
// DisasContext *dc = container_of(db, DisasContext, base);
|
||||
// E2KCPU *cpu = E2K_CPU(cs);
|
||||
DisasContext *dc = container_of(db, DisasContext, base);
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
// CPUE2KState *env = &cpu->env;
|
||||
|
||||
/* Control transfer */
|
||||
switch(dc->base.is_jmp) {
|
||||
case DISAS_NEXT:
|
||||
case DISAS_TOO_MANY:
|
||||
break;
|
||||
case DISAS_NORETURN:
|
||||
/* exception */
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->pc);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case STATIC_JUMP:
|
||||
tcg_gen_mov_i64(e2k_cs.pc, dc->jmp.dest);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case DYNAMIC_JUMP: {
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
tcg_gen_movcond_i64(TCG_COND_EQ, e2k_cs.pc,
|
||||
dc->jmp.cond, one,
|
||||
dc->jmp.dest, e2k_cs.pc
|
||||
);
|
||||
tcg_temp_free_i64(one);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* TODO: unreachable */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free_i64(dc->jmp.dest);
|
||||
tcg_temp_free_i64(dc->jmp.cond);
|
||||
}
|
||||
|
||||
static void e2k_tr_disas_log(const DisasContextBase *db, CPUState *cpu)
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
#ifndef E2K_TRANSLATE_H
|
||||
#define E2K_TRANSLATE_H
|
||||
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/translator.h"
|
||||
|
||||
#define STATIC_JUMP DISAS_TARGET_0
|
||||
#define DYNAMIC_JUMP DISAS_TARGET_1
|
||||
|
||||
#define GEN_MASK(start, end) (((1 << ((end) - (start) + 1)) - 1) << start)
|
||||
#define GEN_MASK(type, start, end) \
|
||||
((((type) 1 << ((end) - (start) + 1)) - 1) << start)
|
||||
#define GET_BIT(v, index) (((v) >> (index)) & 1)
|
||||
#define GET_FIELD(v, start, end) \
|
||||
(((v) & GEN_MASK(start, end)) >> (start))
|
||||
(((v) >> (start)) & ((1 << ((end) - (start) + 1)) - 1))
|
||||
|
||||
#define IS_BASED(i) (((i) & 0x80) == 0)
|
||||
#define IS_REGULAR(i) (((i) & 0xc0) == 0x80)
|
||||
|
@ -29,7 +31,27 @@
|
|||
#define GET_LIT(i) ((i) & 0x03)
|
||||
#define GET_GLOBAL(i) ((i) & 0x1f)
|
||||
|
||||
typedef enum AlesFlag {
|
||||
#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,
|
||||
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,
|
||||
|
@ -38,7 +60,6 @@ typedef enum AlesFlag {
|
|||
typedef struct CPUE2KStateTCG {
|
||||
TCGv pc;
|
||||
TCGv ctprs[3];
|
||||
TCGv_i32 is_jmp;
|
||||
TCGv_i32 wbs;
|
||||
TCGv_i32 wsz;
|
||||
TCGv_i32 nfx;
|
||||
|
@ -153,7 +174,7 @@ static inline void e2k_gen_get_field_i64(TCGv_i64 ret, TCGv_i64 val,
|
|||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_and_i64(t0, val, GEN_MASK(start, end));
|
||||
tcg_gen_andi_i64(t0, val, GEN_MASK(uint64_t, start, end));
|
||||
tcg_gen_shli_i64(ret, t0, start);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
|
@ -162,7 +183,7 @@ static inline void e2k_gen_get_field_i64(TCGv_i64 ret, TCGv_i64 val,
|
|||
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);
|
||||
uint64_t mask = GEN_MASK(uint64_t, 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();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/translator.h"
|
||||
#include "translate.h"
|
||||
|
||||
static TCGv_i64 get_src1(DisasContext *dc, unsigned int als)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/translator.h"
|
||||
#include "translate.h"
|
||||
|
||||
static void gen_cs0(DisasContext *dc)
|
||||
|
@ -82,14 +80,26 @@ static void gen_cs0(DisasContext *dc)
|
|||
// invalid
|
||||
abort();
|
||||
}
|
||||
|
||||
if (type == DISP || type == SDISP || type == LDISP) {
|
||||
/* TODO: SDISP tag */
|
||||
int ipd = GET_FIELD(bundle->ss, 30, 31);
|
||||
if (type == DISP || type == LDISP) {
|
||||
unsigned int disp = GET_FIELD(cs0, 0, 27);
|
||||
/* Calculate a signed displacement in bytes. */
|
||||
int sdisp = ((int) (disp << 4)) >> 1;
|
||||
target_ulong tgt = dc->pc + sdisp;
|
||||
tcg_gen_movi_tl(e2k_cs.ctprs[ctpr], tgt);
|
||||
uint64_t reg = (dc->pc + sdisp) |
|
||||
((uint64_t) CTPR_TAG_DISP << CTPR_TAG_OFF) |
|
||||
((uint64_t) ipd << CTPR_IPD_OFF);
|
||||
if (type == LDISP) {
|
||||
reg |= (uint64_t) CTPR_OPC_LDISP << CTPR_OPC_OFF;
|
||||
}
|
||||
tcg_gen_movi_tl(e2k_cs.ctprs[ctpr], reg);
|
||||
} else if (type == SDISP) {
|
||||
unsigned int disp = GET_FIELD(cs0, 0, 27) << 11;
|
||||
/* FIXME: trap address */
|
||||
target_ulong base = ((uint64_t) 0xe2 << 40) | disp;
|
||||
uint64_t reg = (dc->pc + base) |
|
||||
((uint64_t) CTPR_TAG_SDISP << CTPR_TAG_OFF) |
|
||||
((uint64_t) ipd << CTPR_IPD_OFF);
|
||||
tcg_gen_movi_tl(e2k_cs.ctprs[ctpr], reg);
|
||||
}
|
||||
|
||||
if (/* Note that RETURN is said to be COPF1. I can't understand what its
|
||||
|
@ -250,9 +260,10 @@ static void gen_cs1(DisasContext *dc)
|
|||
unsigned int ctop = (bundle->ss & 0x00000c00) >> 10;
|
||||
/* In C.17.4 it's said that other bits in CS1.param except for the
|
||||
seven lowermost ones are ignored. */
|
||||
// unsigned int wbs = cs1 & 0x7f;
|
||||
unsigned int wbs = cs1 & 0x7f;
|
||||
|
||||
if (ctop) {
|
||||
tcg_gen_movi_i32(e2k_cs.wbs, wbs);
|
||||
// my_printf ("call %%ctpr%d, wbs = 0x%x", ctop, wbs);
|
||||
// print_ctcond (info, instr->ss & 0x1ff);
|
||||
} else {
|
||||
|
@ -315,8 +326,17 @@ static void gen_jmp(DisasContext *dc)
|
|||
|
||||
/* TODO: check CPU behavior if present ibranch and ctpr is not zero */
|
||||
|
||||
/* TODO: different kinds of ct */
|
||||
if (ctpr != 0) {
|
||||
tcg_gen_mov_tl(dc->jmp.dest, e2k_cs.ctprs[ctpr]);
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
|
||||
/* TODO: use save_state */
|
||||
tcg_gen_movi_i64(e2k_cs.pc, dc->pc);
|
||||
gen_helper_check_syscall_ctpr(cpu_env, e2k_cs.ctprs[ctpr]);
|
||||
tcg_gen_andi_i64(t0, e2k_cs.ctprs[ctpr], GEN_MASK(uint64_t, 0, 47));
|
||||
tcg_gen_mov_tl(dc->jmp.dest, t0);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
if (cond_type == 1) {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/translator.h"
|
||||
#include "translate.h"
|
||||
|
||||
TCGv_i64 e2k_get_preg(DisasContext *dc, int reg)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/translator.h"
|
||||
#include "translate.h"
|
||||
|
||||
static inline void gen_abn_inc(DisasContext *dc, TCGCond cond)
|
||||
|
|
Loading…
Reference in New Issue