Commit fec7daab authored by Chen Gang's avatar Chen Gang Committed by Richard Henderson
Browse files

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: default avatarChen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent 77b3adc0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
};

+22 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
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)
+13 −1
Original line number Diff line number Diff line
@@ -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