target: e2k: Try to impl syscall.

This commit is contained in:
Denis Drakhnia 2020-11-12 15:52:51 +02:00 committed by Alibek Omarov
parent 42cd4b2c56
commit 779fc80db4
10 changed files with 150 additions and 96 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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)

View File

@ -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) {

View File

@ -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)

View File

@ -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)