target-tilegx: Support iret instruction and related special registers

EX_CONTEXT_0_0 is used for jumping address, and EX_CONTEXT_0_1 is for
INTERRUPT_CRITICAL_SECTION, which should only be 0 or 1 in user mode, or
it will cause target SIGILL (and the patch doesn't support system mode).

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Chen Gang 2015-10-04 17:41:14 +08:00 committed by Richard Henderson
parent 77b3adc001
commit fec7daab3d
4 changed files with 38 additions and 1 deletions

View File

@ -53,6 +53,8 @@ enum {
TILEGX_SPR_CMPEXCH = 0,
TILEGX_SPR_CRITICAL_SEC = 1,
TILEGX_SPR_SIM_CONTROL = 2,
TILEGX_SPR_EX_CONTEXT_0_0 = 3,
TILEGX_SPR_EX_CONTEXT_0_1 = 4,
TILEGX_SPR_COUNT
};

View File

@ -22,6 +22,7 @@
#include "qemu-common.h"
#include "exec/helper-proto.h"
#include <zlib.h> /* For crc32 */
#include "syscall_defs.h"
void helper_exception(CPUTLGState *env, uint32_t excp)
{
@ -31,6 +32,27 @@ void helper_exception(CPUTLGState *env, uint32_t excp)
cpu_loop_exit(cs);
}
void helper_ext01_ics(CPUTLGState *env)
{
uint64_t val = env->spregs[TILEGX_SPR_EX_CONTEXT_0_1];
switch (val) {
case 0:
case 1:
env->spregs[TILEGX_SPR_CRITICAL_SEC] = val;
break;
default:
#if defined(CONFIG_USER_ONLY)
env->signo = TARGET_SIGILL;
env->sigcode = TARGET_ILL_ILLOPC;
helper_exception(env, TILEGX_EXCP_SIGNAL);
#else
helper_exception(env, TILEGX_EXCP_OPCODE_UNIMPLEMENTED);
#endif
break;
}
}
uint64_t helper_cntlz(uint64_t arg)
{
return clz64(arg);

View File

@ -1,4 +1,5 @@
DEF_HELPER_2(exception, noreturn, env, i32)
DEF_HELPER_1(ext01_ics, void, env)
DEF_HELPER_FLAGS_1(cntlz, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(cnttz, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(pcnt, TCG_CALL_NO_RWG_SE, i64, i64)

View File

@ -529,6 +529,15 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
/* ??? This should yield, especially in system mode. */
mnemonic = "nap";
goto done0;
case OE_RR_X1(IRET):
gen_helper_ext01_ics(cpu_env);
dc->jmp.cond = TCG_COND_ALWAYS;
dc->jmp.dest = tcg_temp_new();
tcg_gen_ld_tl(dc->jmp.dest, cpu_env,
offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_0]));
tcg_gen_andi_tl(dc->jmp.dest, dc->jmp.dest, ~7);
mnemonic = "iret";
goto done0;
case OE_RR_X1(SWINT0):
case OE_RR_X1(SWINT2):
case OE_RR_X1(SWINT3):
@ -606,7 +615,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
break;
case OE_RR_X0(FSINGLE_PACK1):
case OE_RR_Y0(FSINGLE_PACK1):
case OE_RR_X1(IRET):
return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RR_X1(LD1S):
memop = MO_SB;
@ -1947,6 +1955,10 @@ static const TileSPR *find_spr(unsigned spr)
offsetof(CPUTLGState, spregs[TILEGX_SPR_CRITICAL_SEC]), 0, 0)
D(SIM_CONTROL,
offsetof(CPUTLGState, spregs[TILEGX_SPR_SIM_CONTROL]), 0, 0)
D(EX_CONTEXT_0_0,
offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_0]), 0, 0)
D(EX_CONTEXT_0_1,
offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_1]), 0, 0)
}
#undef D