From: Chen Gang <gang.chen.5...@gmail.com> At present, tilegx qemu will abort for "setup_frame: not implemented", when meet raise instruction.
Signed-off-by: Chen Gang <gang.chen.5...@gmail.com> --- linux-user/main.c | 14 ++++++++ target-tilegx/cpu.h | 3 ++ target-tilegx/translate.c | 89 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 782037d..7e49931 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3436,6 +3436,17 @@ static void gen_sigill_reg(CPUTLGState *env) queue_signal(env, info.si_signo, &info); } +static void gen_sigill(CPUTLGState *env) +{ + target_siginfo_t info; + + info.si_signo = env->signo; + info.si_errno = 0; + info.si_code = env->sigcode; + info._sifields._sigfault._addr = env->pc; + queue_signal(env, info.si_signo, &info); +} + static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val) { if (unlikely(reg >= TILEGX_R_COUNT)) { @@ -3622,6 +3633,9 @@ void cpu_loop(CPUTLGState *env) case TILEGX_EXCP_OPCODE_FETCHOR4: do_fetch(env, trapnr, false); break; + case TILEGX_EXCP_OPCODE_ILL: + gen_sigill(env); + break; case TILEGX_EXCP_REG_IDN_ACCESS: case TILEGX_EXCP_REG_UDN_ACCESS: gen_sigill_reg(env); diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h index b9f5082..72a1878 100644 --- a/target-tilegx/cpu.h +++ b/target-tilegx/cpu.h @@ -75,6 +75,7 @@ typedef enum { TILEGX_EXCP_OPCODE_FETCHAND4 = 0x10c, TILEGX_EXCP_OPCODE_FETCHOR = 0x10d, TILEGX_EXCP_OPCODE_FETCHOR4 = 0x10e, + TILEGX_EXCP_OPCODE_ILL = 0x10f, TILEGX_EXCP_REG_IDN_ACCESS = 0x181, TILEGX_EXCP_REG_UDN_ACCESS = 0x182, TILEGX_EXCP_UNALIGNMENT = 0x201, @@ -86,6 +87,8 @@ typedef struct CPUTLGState { uint64_t spregs[TILEGX_SPR_COUNT]; /* Special used registers by outside */ uint64_t pc; /* Current pc */ + uint64_t signo; /* Signal number */ + uint64_t sigcode; /* Signal code */ #if defined(CONFIG_USER_ONLY) uint64_t atomic_srca; /* Arguments to atomic "exceptions" */ uint64_t atomic_srcb; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 6622aeb..969c66e 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -23,6 +23,8 @@ #include "disas/disas.h" #include "tcg-op.h" #include "exec/cpu_ldst.h" +#include "linux-user/syscall_defs.h" + #include "opcode_tilegx.h" #include "spr_def_64.h" @@ -378,8 +380,74 @@ static void gen_v4op(TCGv d64, TCGv a64, TCGv b64, tcg_temp_free_i32(bh); } +static TileExcp gen_ill(DisasContext *dc, int signo, int sigcode, + const char *mnemonic) +{ + TCGv t0 = tcg_const_tl(signo); + TCGv t1 = tcg_const_tl(sigcode); + + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUTLGState, signo)); + tcg_gen_st_tl(t1, cpu_env, offsetof(CPUTLGState, sigcode)); + + tcg_temp_free(t1); + tcg_temp_free(t0); + + qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic); + return TILEGX_EXCP_OPCODE_ILL; +} + +static int parse_from_addli(uint64_t bundle, int *signo, int *sigcode) +{ + if ((get_Opcode_X0(bundle) != ADDLI_OPCODE_X0) + || (get_Dest_X0(bundle) != TILEGX_R_ZERO) + || (get_SrcA_X0(bundle) != TILEGX_R_ZERO)) { + return 0; + } + + *signo = get_Imm16_X0(bundle) & 0x3f; + *sigcode = (get_Imm16_X0(bundle) >> 6) & 0xf; + + switch (*signo) { + case TARGET_SIGILL: + return *sigcode <= TARGET_NSIGILL; + case TARGET_SIGFPE: + return *sigcode <= TARGET_NSIGFPE; + case TARGET_SIGSEGV: + return *sigcode <= TARGET_NSIGSEGV; + case TARGET_SIGBUS: + return *sigcode <= TARGET_NSIGBUS; + case TARGET_SIGTRAP: + return *sigcode <= TARGET_NSIGTRAP; + default: + return 0; + } +} + +static TileExcp gen_specill(DisasContext *dc, unsigned dest, unsigned srca, + uint64_t bundle) +{ + const char *mnemonic; + int signo; + int sigcode; + + if (dest == 0x1c && srca == 0x25) { + signo = TARGET_SIGTRAP; + sigcode = TARGET_TRAP_BRKPT; + mnemonic = "bpt"; + } else if (dest == 0x1d && srca == 0x25 + && parse_from_addli(bundle, &signo, &sigcode)) { + mnemonic = "raise"; + } else { + signo = TARGET_SIGILL; + sigcode = TARGET_ILL_ILLOPC; + mnemonic = "ill"; + } + + return gen_ill(dc, signo, sigcode, mnemonic); +} + static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, - unsigned dest, unsigned srca) + unsigned dest, unsigned srca, uint64_t bundle) { TCGv tdest, tsrca; const char *mnemonic; @@ -407,16 +475,9 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext, mnemonic = "flushwb"; goto done0; case OE_RR_X1(ILL): - if (dest == 0x1c && srca == 0x25) { - mnemonic = "bpt"; - goto done2; - } - /* Fall through */ + return gen_specill(dc, dest, srca, bundle); case OE_RR_Y1(ILL): - mnemonic = "ill"; - done2: - qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic); - return TILEGX_EXCP_OPCODE_UNKNOWN; + return gen_ill(dc, TARGET_SIGILL, TARGET_ILL_ILLOPC, "ill"); case OE_RR_X1(MF): mnemonic = "mf"; goto done0; @@ -1806,7 +1867,7 @@ static TileExcp decode_y0(DisasContext *dc, tilegx_bundle_bits bundle) case RRR_1_OPCODE_Y0: if (ext == UNARY_RRR_1_OPCODE_Y0) { ext = get_UnaryOpcodeExtension_Y0(bundle); - return gen_rr_opcode(dc, OE(opc, ext, Y0), dest, srca); + return gen_rr_opcode(dc, OE(opc, ext, Y0), dest, srca, bundle); } /* fallthru */ case RRR_0_OPCODE_Y0: @@ -1852,7 +1913,7 @@ static TileExcp decode_y1(DisasContext *dc, tilegx_bundle_bits bundle) case RRR_1_OPCODE_Y1: if (ext == UNARY_RRR_1_OPCODE_Y0) { ext = get_UnaryOpcodeExtension_Y1(bundle); - return gen_rr_opcode(dc, OE(opc, ext, Y1), dest, srca); + return gen_rr_opcode(dc, OE(opc, ext, Y1), dest, srca, bundle); } /* fallthru */ case RRR_0_OPCODE_Y1: @@ -1954,7 +2015,7 @@ static TileExcp decode_x0(DisasContext *dc, tilegx_bundle_bits bundle) ext = get_RRROpcodeExtension_X0(bundle); if (ext == UNARY_RRR_0_OPCODE_X0) { ext = get_UnaryOpcodeExtension_X0(bundle); - return gen_rr_opcode(dc, OE(opc, ext, X0), dest, srca); + return gen_rr_opcode(dc, OE(opc, ext, X0), dest, srca, bundle); } srcb = get_SrcB_X0(bundle); return gen_rrr_opcode(dc, OE(opc, ext, X0), dest, srca, srcb); @@ -2001,7 +2062,7 @@ static TileExcp decode_x1(DisasContext *dc, tilegx_bundle_bits bundle) switch (ext) { case UNARY_RRR_0_OPCODE_X1: ext = get_UnaryOpcodeExtension_X1(bundle); - return gen_rr_opcode(dc, OE(opc, ext, X1), dest, srca); + return gen_rr_opcode(dc, OE(opc, ext, X1), dest, srca, bundle); case ST1_RRR_0_OPCODE_X1: return gen_st_opcode(dc, dest, srca, srcb, MO_UB, "st1"); case ST2_RRR_0_OPCODE_X1: -- 1.9.3