sim-card
/
qemu
Archived
10
0
Fork 0

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: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2011-05-23 12:12:29 -07:00 committed by Richard Henderson
parent bba9bdcee8
commit 26b4609447
3 changed files with 124 additions and 0 deletions

View File

@ -244,6 +244,9 @@ struct CPUAlphaState {
uint8_t ps; uint8_t ps;
uint8_t intr_flag; uint8_t intr_flag;
uint8_t pal_mode; uint8_t pal_mode;
uint8_t fen;
uint32_t pcc_ofs;
/* These pass data from the exception logic in the translator and /* These pass data from the exception logic in the translator and
helpers to the OS entry point. This is used for both system 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_arg1;
uint64_t trap_arg2; 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 #if TARGET_LONG_BITS > HOST_LONG_BITS
/* temporary fixed-point registers /* temporary fixed-point registers
* used to emulate 64 bits target on 32 bits hosts * used to emulate 64 bits target on 32 bits hosts

View File

@ -47,11 +47,24 @@ static VMStateField vmstate_cpu_fields[] = {
VMSTATE_UINT8(ps, CPUState), VMSTATE_UINT8(ps, CPUState),
VMSTATE_UINT8(intr_flag, CPUState), VMSTATE_UINT8(intr_flag, CPUState),
VMSTATE_UINT8(pal_mode, CPUState), VMSTATE_UINT8(pal_mode, CPUState),
VMSTATE_UINT8(fen, CPUState),
VMSTATE_UINT32(pcc_ofs, CPUState),
VMSTATE_UINTTL(trap_arg0, CPUState), VMSTATE_UINTTL(trap_arg0, CPUState),
VMSTATE_UINTTL(trap_arg1, CPUState), VMSTATE_UINTTL(trap_arg1, CPUState),
VMSTATE_UINTTL(trap_arg2, 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() VMSTATE_END_OF_LIST()
}; };

View File

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