Commit 26b46094 authored by Richard Henderson's avatar Richard Henderson Committed by Richard Henderson
Browse files

target-alpha: Add IPRs to be used by the emulation PALcode.



These aren't actually used yet, but we can at least access
them via the HW_MFPR and HW_MTPR instructions.

Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent bba9bdce
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -244,6 +244,9 @@ struct CPUAlphaState {
    uint8_t ps;
    uint8_t intr_flag;
    uint8_t pal_mode;
    uint8_t fen;

    uint32_t pcc_ofs;

    /* These pass data from the exception logic in the translator and
       helpers to the OS entry point.  This is used for both system
@@ -252,6 +255,18 @@ struct CPUAlphaState {
    uint64_t trap_arg1;
    uint64_t trap_arg2;

#if !defined(CONFIG_USER_ONLY)
    /* The internal data required by our emulation of the Unix PALcode.  */
    uint64_t exc_addr;
    uint64_t palbr;
    uint64_t ptbr;
    uint64_t vptptr;
    uint64_t sysval;
    uint64_t usp;
    uint64_t shadow[8];
    uint64_t scratch[24];
#endif

#if TARGET_LONG_BITS > HOST_LONG_BITS
    /* temporary fixed-point registers
     * used to emulate 64 bits target on 32 bits hosts
+13 −0
Original line number Diff line number Diff line
@@ -47,11 +47,24 @@ static VMStateField vmstate_cpu_fields[] = {
    VMSTATE_UINT8(ps, CPUState),
    VMSTATE_UINT8(intr_flag, CPUState),
    VMSTATE_UINT8(pal_mode, CPUState),
    VMSTATE_UINT8(fen, CPUState),

    VMSTATE_UINT32(pcc_ofs, CPUState),

    VMSTATE_UINTTL(trap_arg0, CPUState),
    VMSTATE_UINTTL(trap_arg1, CPUState),
    VMSTATE_UINTTL(trap_arg2, CPUState),

    VMSTATE_UINTTL(exc_addr, CPUState),
    VMSTATE_UINTTL(palbr, CPUState),
    VMSTATE_UINTTL(ptbr, CPUState),
    VMSTATE_UINTTL(vptptr, CPUState),
    VMSTATE_UINTTL(sysval, CPUState),
    VMSTATE_UINTTL(usp, CPUState),

    VMSTATE_UINTTL_ARRAY(shadow, CPUState, 8),
    VMSTATE_UINTTL_ARRAY(scratch, CPUState, 24),

    VMSTATE_END_OF_LIST()
};

+96 −0
Original line number Diff line number Diff line
@@ -1468,6 +1468,89 @@ static void gen_rx(int ra, int set)
    tcg_temp_free_i32(tmp);
}

#ifndef CONFIG_USER_ONLY

#define PR_BYTE         0x100000
#define PR_LONG         0x200000

static int cpu_pr_data(int pr)
{
    switch (pr) {
    case  0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
    case  1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
    case  2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
    case  3: return offsetof(CPUAlphaState, trap_arg0);
    case  4: return offsetof(CPUAlphaState, trap_arg1);
    case  5: return offsetof(CPUAlphaState, trap_arg2);
    case  6: return offsetof(CPUAlphaState, exc_addr);
    case  7: return offsetof(CPUAlphaState, palbr);
    case  8: return offsetof(CPUAlphaState, ptbr);
    case  9: return offsetof(CPUAlphaState, vptptr);
    case 10: return offsetof(CPUAlphaState, unique);
    case 11: return offsetof(CPUAlphaState, sysval);
    case 12: return offsetof(CPUAlphaState, usp);

    case 32 ... 39:
        return offsetof(CPUAlphaState, shadow[pr - 32]);
    case 40 ... 63:
        return offsetof(CPUAlphaState, scratch[pr - 40]);
    }
    return 0;
}

static void gen_mfpr(int ra, int regno)
{
    int data = cpu_pr_data(regno);

    /* In our emulated PALcode, these processor registers have no
       side effects from reading.  */
    if (ra == 31) {
        return;
    }

    /* The basic registers are data only, and unknown registers
       are read-zero, write-ignore.  */
    if (data == 0) {
        tcg_gen_movi_i64(cpu_ir[ra], 0);
    } else if (data & PR_BYTE) {
        tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, data & ~PR_BYTE);
    } else if (data & PR_LONG) {
        tcg_gen_ld32s_i64(cpu_ir[ra], cpu_env, data & ~PR_LONG);
    } else {
        tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
    }
}

static void gen_mtpr(int rb, int regno)
{
    TCGv tmp;
    int data;

    if (rb == 31) {
        tmp = tcg_const_i64(0);
    } else {
        tmp = cpu_ir[rb];
    }

    /* The basic registers are data only, and unknown registers
       are read-zero, write-ignore.  */
    data = cpu_pr_data(regno);
    if (data != 0) {
        if (data & PR_BYTE) {
            tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
        } else if (data & PR_LONG) {
            tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
        } else {
            tcg_gen_st_i64(tmp, cpu_env, data);
        }
    }

    if (rb == 31) {
        tcg_temp_free(tmp);
    }
}
#endif /* !USER_ONLY*/

static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
{
    uint32_t palcode;
@@ -2576,6 +2659,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
        break;
    case 0x19:
        /* HW_MFPR (PALcode) */
#ifndef CONFIG_USER_ONLY
        if (ctx->pal_mode) {
            gen_mfpr(ra, insn & 0xffff);
            break;
        }
#endif
        goto invalid_opc;
    case 0x1A:
        /* JMP, JSR, RET, JSR_COROUTINE.  These only differ by the branch
@@ -2845,6 +2934,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
        break;
    case 0x1D:
        /* HW_MTPR (PALcode) */
#ifndef CONFIG_USER_ONLY
        if (ctx->pal_mode) {
            gen_mtpr(ra, insn & 0xffff);
            break;
        }
#endif
        goto invalid_opc;
    case 0x1E:
        /* HW_RET (PALcode) */
@@ -3272,6 +3367,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
#endif
    env->lock_addr = -1;
    env->fen = 1;

    qemu_init_vcpu(env);
    return env;