Commit 8f09da69 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/xtensa/tags/20181001-xtensa' into staging



target/xtensa: preparation for FLIX support

Separate generation of per-instruction code (such as raising exceptions
and terminating TB) from per-opcode code.

# gpg: Signature made Mon 01 Oct 2018 19:14:34 BST
# gpg:                using RSA key 51F9CC91F83FA044
# gpg: Good signature from "Max Filippov <filippov@cadence.com>"
# gpg:                 aka "Max Filippov <max.filippov@cogentembedded.com>"
# gpg:                 aka "Max Filippov <jcmvbkbc@gmail.com>"
# Primary key fingerprint: 2B67 854B 98E5 327D CDEB  17D8 51F9 CC91 F83F A044

* remotes/xtensa/tags/20181001-xtensa:
  target/xtensa: extract gen_check_interrupts call
  target/xtensa: make rsr/wsr helpers return void
  target/xtensa: extract unconditional TB termination via slot 0
  target/xtensa: always end TB on CCOUNT access/CCOMPARE write
  target/xtensa: change SR number checks to assertions
  target/xtensa: extract unconditional TB termination
  target/xtensa: extract test for division by zero
  target/xtensa: extract test for cpdisabled exception
  target/xtensa: extract test for alloca exception
  target/xtensa: extract test for window underflow exception
  target/xtensa: extract test for window overflow exception
  target/xtensa: extract test for debug exception
  target/xtensa: extract test for syscall instruction
  target/xtensa: extract test for privileged instruction
  target/xtensa: extract test for an illegal instruction

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e32e62f2 d74624e5
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ enum {
#define MEMCTL_IL0EN 0x1

#define MAX_INSN_LENGTH 64
#define MAX_INSN_SLOTS 32
#define MAX_OPCODE_ARGS 16
#define MAX_NAREG 64
#define MAX_NINTERRUPT 32
@@ -347,11 +348,40 @@ typedef struct XtensaMemory {
typedef struct DisasContext DisasContext;
typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
                               const uint32_t par[]);
typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
                                     const uint32_t arg[],
                                     const uint32_t par[]);
typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
                                         const uint32_t arg[],
                                         const uint32_t par[]);

enum {
    XTENSA_OP_ILL = 0x1,
    XTENSA_OP_PRIVILEGED = 0x2,
    XTENSA_OP_SYSCALL = 0x4,
    XTENSA_OP_DEBUG_BREAK = 0x8,

    XTENSA_OP_OVERFLOW = 0x10,
    XTENSA_OP_UNDERFLOW = 0x20,
    XTENSA_OP_ALLOCA = 0x40,
    XTENSA_OP_COPROCESSOR = 0x80,

    XTENSA_OP_DIVIDE_BY_ZERO = 0x100,

    XTENSA_OP_CHECK_INTERRUPTS = 0x200,
    XTENSA_OP_EXIT_TB_M1 = 0x400,
    XTENSA_OP_EXIT_TB_0 = 0x800,
};

typedef struct XtensaOpcodeOps {
    const char *name;
    XtensaOpcodeOp translate;
    XtensaOpcodeBoolTest test_ill;
    XtensaOpcodeUintTest test_overflow;
    const uint32_t *par;
    uint32_t op_flags;
    uint32_t windowed_register_op;
    uint32_t coprocessor;
} XtensaOpcodeOps;

typedef struct XtensaOpcodeTranslators {
@@ -661,6 +691,9 @@ static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch)
#define XTENSA_TBFLAG_WINDOW_MASK 0x18000
#define XTENSA_TBFLAG_WINDOW_SHIFT 15
#define XTENSA_TBFLAG_YIELD 0x20000
#define XTENSA_TBFLAG_CWOE 0x40000
#define XTENSA_TBFLAG_CALLINC_MASK 0x180000
#define XTENSA_TBFLAG_CALLINC_SHIFT 19

static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
        target_ulong *cs_base, uint32_t *flags)
@@ -698,7 +731,9 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
            (env->sregs[WINDOW_BASE] + 1);
        uint32_t w = ctz32(windowstart | 0x8);

        *flags |= w << XTENSA_TBFLAG_WINDOW_SHIFT;
        *flags |= (w << XTENSA_TBFLAG_WINDOW_SHIFT) | XTENSA_TBFLAG_CWOE;
        *flags |= extract32(env->sregs[PS], PS_CALLINC_SHIFT,
                            PS_CALLINC_LEN) << XTENSA_TBFLAG_CALLINC_SHIFT;
    } else {
        *flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT;
    }
+6 −0
Original line number Diff line number Diff line
@@ -57,12 +57,18 @@ static void init_libisa(XtensaConfig *config)
{
    unsigned i, j;
    unsigned opcodes;
    unsigned formats;

    config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL);
    assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH);
    opcodes = xtensa_isa_num_opcodes(config->isa);
    formats = xtensa_isa_num_formats(config->isa);
    config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);

    for (i = 0; i < formats; ++i) {
        assert(xtensa_format_num_slots(config->isa, i) <= MAX_INSN_SLOTS);
    }

    for (i = 0; i < opcodes; ++i) {
        const char *opc_name = xtensa_opcode_name(config->isa, i);
        XtensaOpcodeOps *ops = NULL;
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)

DEF_HELPER_2(wsr_windowbase, void, env, i32)
DEF_HELPER_4(entry, void, env, i32, i32, i32)
DEF_HELPER_2(test_ill_retw, void, env, i32)
DEF_HELPER_2(test_underflow_retw, void, env, i32)
DEF_HELPER_2(retw, i32, env, i32)
DEF_HELPER_2(rotw, void, env, i32)
DEF_HELPER_3(window_check, noreturn, env, i32, i32)
+36 −37
Original line number Diff line number Diff line
@@ -253,23 +253,12 @@ void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
{
    int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
    if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
        qemu_log_mask(LOG_GUEST_ERROR, "Illegal entry instruction(pc = %08x), PS = %08x\n",
                      pc, env->sregs[PS]);
        HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
    } else {
        uint32_t windowstart = xtensa_replicate_windowstart(env) >>
            (env->sregs[WINDOW_BASE] + 1);

        if (windowstart & ((1 << callinc) - 1)) {
            HELPER(window_check)(env, pc, callinc);
        }
    env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
    xtensa_rotate_window(env, callinc);
    env->sregs[WINDOW_START] |=
        windowstart_bit(env->sregs[WINDOW_BASE], env);
}
}

void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
{
@@ -298,13 +287,12 @@ void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
    }
}

uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
void HELPER(test_ill_retw)(CPUXtensaState *env, uint32_t pc)
{
    int n = (env->regs[0] >> 30) & 0x3;
    int m = 0;
    uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
    uint32_t windowstart = env->sregs[WINDOW_START];
    uint32_t ret_pc = 0;

    if (windowstart & windowstart_bit(windowbase - 1, env)) {
        m = 1;
@@ -314,21 +302,23 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
        m = 3;
    }

    if (n == 0 || (m != 0 && m != n) ||
            ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) {
    if (n == 0 || (m != 0 && m != n)) {
        qemu_log_mask(LOG_GUEST_ERROR, "Illegal retw instruction(pc = %08x), "
                      "PS = %08x, m = %d, n = %d\n",
                      pc, env->sregs[PS], m, n);
        HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE);
    } else {
        int owb = windowbase;
    }
}

void HELPER(test_underflow_retw)(CPUXtensaState *env, uint32_t pc)
{
    int n = (env->regs[0] >> 30) & 0x3;

        ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
    if (!(env->sregs[WINDOW_START] &
          windowstart_bit(env->sregs[WINDOW_BASE] - n, env))) {
        uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);

        xtensa_rotate_window(env, -n);
        if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) {
            env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env);
        } else {
        /* window underflow */
        env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
            (windowbase << PS_OWB_SHIFT) | PS_EXCM;
@@ -343,6 +333,15 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
        }
    }
}

uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
{
    int n = (env->regs[0] >> 30) & 0x3;
    uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
    uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);

    xtensa_rotate_window(env, -n);
    env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
    return ret_pc;
}

+1737 −936

File changed.

Preview size limit exceeded, changes collapsed.