[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode in
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode instructions. |
Date: |
Mon, 9 May 2011 14:34:24 -0700 |
All of the "raw" memory accesses should be "phys" instead. Fix
some confusion about argument ordering of the store routines.
Fix the implementation of store-conditional.
Delete the "alt-mode" helpers. Because we only implement two
mmu modes, let /a imply user-mode unconditionally.
For the moment, stub out HW_MTPR and HW_MFPR.
Merge hw_rei with hw_ret.
Signed-off-by: Richard Henderson <address@hidden>
---
target-alpha/cpu.h | 4 +
target-alpha/helper.h | 27 +++-----
target-alpha/op_helper.c | 159 ++++++++++------------------------------------
target-alpha/translate.c | 130 ++++++++++----------------------------
4 files changed, 82 insertions(+), 238 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index bdd396c..60b753f 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -192,6 +192,8 @@ enum {
#define SWCR_MASK (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK)
+#define CPU_SAVE_VERSION 1
+
/* MMU modes definitions */
/* Alpha has 5 MMU modes: PALcode, kernel, executive, supervisor, and user.
@@ -243,6 +245,8 @@ struct CPUAlphaState {
exist for use in user-mode. */
uint8_t ps;
uint8_t intr_flag;
+ uint8_t fen;
+ uint8_t pal_mode;
/* These pass data from the exception logic in the translator and
helpers to the OS entry point. This is used for both system
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 7435c61..9ffc372 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -100,25 +100,16 @@ DEF_HELPER_1(ieee_input_cmp, i64, i64)
DEF_HELPER_1(ieee_input_s, i64, i64)
#if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_0(hw_rei, void)
DEF_HELPER_1(hw_ret, void, i64)
-DEF_HELPER_0(set_alt_mode, void)
-DEF_HELPER_0(restore_mode, void)
-
-DEF_HELPER_1(ld_virt_to_phys, i64, i64)
-DEF_HELPER_1(st_virt_to_phys, i64, i64)
-DEF_HELPER_2(ldl_raw, void, i64, i64)
-DEF_HELPER_2(ldq_raw, void, i64, i64)
-DEF_HELPER_2(ldl_l_raw, void, i64, i64)
-DEF_HELPER_2(ldq_l_raw, void, i64, i64)
-DEF_HELPER_2(ldl_kernel, void, i64, i64)
-DEF_HELPER_2(ldq_kernel, void, i64, i64)
-DEF_HELPER_2(ldl_data, void, i64, i64)
-DEF_HELPER_2(ldq_data, void, i64, i64)
-DEF_HELPER_2(stl_raw, void, i64, i64)
-DEF_HELPER_2(stq_raw, void, i64, i64)
-DEF_HELPER_2(stl_c_raw, i64, i64, i64)
-DEF_HELPER_2(stq_c_raw, i64, i64, i64)
+
+DEF_HELPER_1(ldl_phys, i64, i64)
+DEF_HELPER_1(ldq_phys, i64, i64)
+DEF_HELPER_1(ldl_l_phys, i64, i64)
+DEF_HELPER_1(ldq_l_phys, i64, i64)
+DEF_HELPER_2(stl_phys, void, i64, i64)
+DEF_HELPER_2(stq_phys, void, i64, i64)
+DEF_HELPER_2(stl_c_phys, i64, i64, i64)
+DEF_HELPER_2(stq_c_phys, i64, i64, i64)
#endif
#include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index fde14c4..73e5805 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1156,167 +1156,78 @@ uint64_t helper_cvtqg (uint64_t a)
/* PALcode support special instructions */
#if !defined (CONFIG_USER_ONLY)
-void helper_hw_rei (void)
-{
- env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
- env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
- env->intr_flag = 0;
- env->lock_addr = -1;
- /* XXX: re-enable interrupts and memory mapping */
-}
-
void helper_hw_ret (uint64_t a)
{
env->pc = a & ~3;
- env->ipr[IPR_EXC_ADDR] = a & 1;
+ env->pal_mode = a & 1;
env->intr_flag = 0;
env->lock_addr = -1;
- /* XXX: re-enable interrupts and memory mapping */
-}
-
-void helper_set_alt_mode (void)
-{
- env->saved_mode = env->ps & 0xC;
- env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
-}
-
-void helper_restore_mode (void)
-{
- env->ps = (env->ps & ~0xC) | env->saved_mode;
}
-
#endif
/*****************************************************************************/
/* Softmmu support */
#if !defined (CONFIG_USER_ONLY)
-
-/* XXX: the two following helpers are pure hacks.
- * Hopefully, we emulate the PALcode, then we should never see
- * HW_LD / HW_ST instructions.
- */
-uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
-{
- uint64_t tlb_addr, physaddr;
- int index, mmu_idx;
- void *retaddr;
-
- mmu_idx = cpu_mmu_index(env);
- index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
- if ((virtaddr & TARGET_PAGE_MASK) ==
- (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
- } else {
- /* the page is not in the TLB : fill it */
- retaddr = GETPC();
- tlb_fill(virtaddr, 0, mmu_idx, retaddr);
- goto redo;
- }
- return physaddr;
-}
-
-uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
-{
- uint64_t tlb_addr, physaddr;
- int index, mmu_idx;
- void *retaddr;
-
- mmu_idx = cpu_mmu_index(env);
- index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
- if ((virtaddr & TARGET_PAGE_MASK) ==
- (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
- } else {
- /* the page is not in the TLB : fill it */
- retaddr = GETPC();
- tlb_fill(virtaddr, 1, mmu_idx, retaddr);
- goto redo;
- }
- return physaddr;
-}
-
-void helper_ldl_raw(uint64_t t0, uint64_t t1)
-{
- ldl_raw(t1, t0);
-}
-
-void helper_ldq_raw(uint64_t t0, uint64_t t1)
-{
- ldq_raw(t1, t0);
-}
-
-void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
-{
- env->lock = t1;
- ldl_raw(t1, t0);
-}
-
-void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_phys(uint64_t p)
{
- env->lock = t1;
- ldl_raw(t1, t0);
+ return (int32_t)ldl_phys(p);
}
-void helper_ldl_kernel(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_phys(uint64_t p)
{
- ldl_kernel(t1, t0);
+ return ldq_phys(p);
}
-void helper_ldq_kernel(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_l_phys(uint64_t p)
{
- ldq_kernel(t1, t0);
+ env->lock_addr = p;
+ return env->lock_value = (int32_t)ldl_phys(p);
}
-void helper_ldl_data(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_l_phys(uint64_t p)
{
- ldl_data(t1, t0);
+ env->lock_addr = p;
+ return env->lock_value = ldl_phys(p);
}
-void helper_ldq_data(uint64_t t0, uint64_t t1)
+void helper_stl_phys(uint64_t p, uint64_t v)
{
- ldq_data(t1, t0);
+ stl_phys(p, v);
}
-void helper_stl_raw(uint64_t t0, uint64_t t1)
+void helper_stq_phys(uint64_t p, uint64_t v)
{
- stl_raw(t1, t0);
+ stq_phys(p, v);
}
-void helper_stq_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
{
- stq_raw(t1, t0);
-}
-
-uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
-{
- uint64_t ret;
+ uint64_t ret = 0;
- if (t1 == env->lock) {
- stl_raw(t1, t0);
- ret = 0;
- } else
- ret = 1;
-
- env->lock = 1;
+ if (p == env->lock_addr) {
+ int32_t old = ldl_phys(p);
+ if (old == (int32_t)env->lock_value) {
+ stl_phys(p, v);
+ ret = 1;
+ }
+ }
+ env->lock_addr = -1;
return ret;
}
-uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
{
- uint64_t ret;
-
- if (t1 == env->lock) {
- stq_raw(t1, t0);
- ret = 0;
- } else
- ret = 1;
+ uint64_t ret = 0;
- env->lock = 1;
+ if (p == env->lock_addr) {
+ uint64_t old = ldq_phys(p);
+ if (old == env->lock_value) {
+ stq_phys(p, v);
+ ret = 1;
+ }
+ }
+ env->lock_addr = -1;
return ret;
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index d81e617..b14b8fc 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -326,7 +326,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx,
int ra, int rb,
#if defined(CONFIG_USER_ONLY)
addr = cpu_lock_st_addr;
#else
- addr = tcg_local_new();
+ addr = tcg_temp_local_new();
#endif
if (rb != 31) {
@@ -349,7 +349,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx,
int ra, int rb,
lab_fail = gen_new_label();
lab_done = gen_new_label();
- tcg_gen_brcond(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+ tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
val = tcg_temp_new();
if (quad) {
@@ -357,7 +357,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx,
int ra, int rb,
} else {
tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
}
- tcg_gen_brcond(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+ tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
if (quad) {
tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
@@ -2580,11 +2580,7 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- if (ra != 31) {
- TCGv tmp = tcg_const_i32(insn & 0xFF);
- gen_helper_mfpr(cpu_ir[ra], tmp, cpu_ir[ra]);
- tcg_temp_free(tmp);
- }
+ tcg_abort();
break;
#endif
case 0x1A:
@@ -2616,27 +2612,26 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
switch ((insn >> 12) & 0xF) {
case 0x0:
/* Longword physical access (hw_ldl/p) */
- gen_helper_ldl_raw(cpu_ir[ra], addr);
+ gen_helper_ldl_phys(cpu_ir[ra], addr);
break;
case 0x1:
/* Quadword physical access (hw_ldq/p) */
- gen_helper_ldq_raw(cpu_ir[ra], addr);
+ gen_helper_ldq_phys(cpu_ir[ra], addr);
break;
case 0x2:
/* Longword physical access with lock (hw_ldl_l/p) */
- gen_helper_ldl_l_raw(cpu_ir[ra], addr);
+ gen_helper_ldl_l_phys(cpu_ir[ra], addr);
break;
case 0x3:
/* Quadword physical access with lock (hw_ldq_l/p) */
- gen_helper_ldq_l_raw(cpu_ir[ra], addr);
+ gen_helper_ldq_l_phys(cpu_ir[ra], addr);
break;
case 0x4:
/* Longword virtual PTE fetch (hw_ldl/v) */
- tcg_gen_qemu_ld32s(cpu_ir[ra], addr, 0);
- break;
+ goto invalid_opc;
case 0x5:
/* Quadword virtual PTE fetch (hw_ldq/v) */
- tcg_gen_qemu_ld64(cpu_ir[ra], addr, 0);
+ goto invalid_opc;
break;
case 0x6:
/* Incpu_ir[ra]id */
@@ -2646,51 +2641,33 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
goto invalid_opc;
case 0x8:
/* Longword virtual access (hw_ldl) */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_ldl_raw(cpu_ir[ra], addr);
- break;
+ goto invalid_opc;
case 0x9:
/* Quadword virtual access (hw_ldq) */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_ldq_raw(cpu_ir[ra], addr);
- break;
+ goto invalid_opc;
case 0xA:
/* Longword virtual access with protection check (hw_ldl/w) */
- tcg_gen_qemu_ld32s(cpu_ir[ra], addr, 0);
+ tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
break;
case 0xB:
/* Quadword virtual access with protection check (hw_ldq/w) */
- tcg_gen_qemu_ld64(cpu_ir[ra], addr, 0);
+ tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
break;
case 0xC:
/* Longword virtual access with alt access mode (hw_ldl/a)*/
- gen_helper_set_alt_mode();
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_ldl_raw(cpu_ir[ra], addr);
- gen_helper_restore_mode();
- break;
+ goto invalid_opc;
case 0xD:
/* Quadword virtual access with alt access mode (hw_ldq/a) */
- gen_helper_set_alt_mode();
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_ldq_raw(cpu_ir[ra], addr);
- gen_helper_restore_mode();
- break;
+ goto invalid_opc;
case 0xE:
/* Longword virtual access with alternate access mode and
- * protection checks (hw_ldl/wa)
- */
- gen_helper_set_alt_mode();
- gen_helper_ldl_data(cpu_ir[ra], addr);
- gen_helper_restore_mode();
+ protection checks (hw_ldl/wa) */
+ tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
break;
case 0xF:
/* Quadword virtual access with alternate access mode and
- * protection checks (hw_ldq/wa)
- */
- gen_helper_set_alt_mode();
- gen_helper_ldq_data(cpu_ir[ra], addr);
- gen_helper_restore_mode();
+ protection checks (hw_ldq/wa) */
+ tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
break;
}
tcg_temp_free(addr);
@@ -2879,18 +2856,7 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- else {
- TCGv tmp1 = tcg_const_i32(insn & 0xFF);
- if (ra != 31)
- gen_helper_mtpr(tmp1, cpu_ir[ra]);
- else {
- TCGv tmp2 = tcg_const_i64(0);
- gen_helper_mtpr(tmp1, tmp2);
- tcg_temp_free(tmp2);
- }
- tcg_temp_free(tmp1);
- ret = EXIT_PC_STALE;
- }
+ abort();
break;
#endif
case 0x1E:
@@ -2900,21 +2866,7 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- if (rb == 31) {
- /* "Old" alpha */
- gen_helper_hw_rei();
- } else {
- TCGv tmp;
-
- if (ra != 31) {
- tmp = tcg_temp_new();
- tcg_gen_addi_i64(tmp, cpu_ir[rb], (((int64_t)insn << 51) >>
51));
- } else
- tmp = tcg_const_i64(((int64_t)insn << 51) >> 51);
- gen_helper_hw_ret(tmp);
- tcg_temp_free(tmp);
- }
- ret = EXIT_PC_UPDATED;
+ gen_helper_hw_ret(cpu_ir[rb]);
break;
#endif
case 0x1F:
@@ -2940,30 +2892,26 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
switch ((insn >> 12) & 0xF) {
case 0x0:
/* Longword physical access */
- gen_helper_stl_raw(val, addr);
+ gen_helper_stl_phys(addr, val);
break;
case 0x1:
/* Quadword physical access */
- gen_helper_stq_raw(val, addr);
+ gen_helper_stq_phys(addr, val);
break;
case 0x2:
/* Longword physical access with lock */
- gen_helper_stl_c_raw(val, val, addr);
+ gen_helper_stl_c_phys(val, addr, val);
break;
case 0x3:
/* Quadword physical access with lock */
- gen_helper_stq_c_raw(val, val, addr);
+ gen_helper_stq_c_phys(val, addr, val);
break;
case 0x4:
/* Longword virtual access */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_stl_raw(val, addr);
- break;
+ goto invalid_opc;
case 0x5:
/* Quadword virtual access */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_stq_raw(val, addr);
- break;
+ goto invalid_opc;
case 0x6:
/* Invalid */
goto invalid_opc;
@@ -2984,18 +2932,10 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
goto invalid_opc;
case 0xC:
/* Longword virtual access with alternate access mode */
- gen_helper_set_alt_mode();
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_stl_raw(val, addr);
- gen_helper_restore_mode();
- break;
+ goto invalid_opc;
case 0xD:
/* Quadword virtual access with alternate access mode */
- gen_helper_set_alt_mode();
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_stl_raw(val, addr);
- gen_helper_restore_mode();
- break;
+ goto invalid_opc;
case 0xE:
/* Invalid */
goto invalid_opc;
@@ -3160,12 +3100,7 @@ static inline void
gen_intermediate_code_internal(CPUState *env,
ctx.env = env;
ctx.pc = pc_start;
ctx.amask = env->amask;
-#if defined (CONFIG_USER_ONLY)
- ctx.mem_idx = 0;
-#else
- ctx.mem_idx = ((env->ps >> 3) & 3);
- ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
-#endif
+ ctx.mem_idx = cpu_mmu_index(env);
/* ??? Every TB begins with unset rounding mode, to be initialized on
the first fp insn of the TB. Alternately we could define a proper
@@ -3334,8 +3269,11 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
env->ps = 1 << 3;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
| FPCR_UNFD | FPCR_INED | FPCR_DNOD));
+#else
+ env->pal_mode = 1;
#endif
env->lock_addr = -1;
+ env->fen = 1;
qemu_init_vcpu(env);
return env;
--
1.7.4.4
- [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4, Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 01/35] Export the unassigned_mem read/write functions., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 02/35] target-alpha: Disassemble EV6 PALcode instructions., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 03/35] pci: Export pci_to_cpu_addr., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 04/35] target-alpha: Single-step properly across branches., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 06/35] target-alpha: Enable the alpha-softmmu target., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 07/35] target-alpha: Tidy exception constants., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 09/35] target-alpha: Cleanup MMU modes., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 11/35] target-alpha: Add IPRs to be used by the emulation PALcode., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode instructions.,
Richard Henderson <=
- [Qemu-devel] [PATCH 12/35] target-alpha: Tidy up arithmetic exceptions., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 13/35] target-alpha: Use do_restore_state for arithmetic exceptions., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 05/35] target-alpha: Remove partial support for palcode emulation., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 14/35] target-alpha: Merge HW_REI and HW_RET implementations., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 08/35] target-alpha: Rationalize internal processor registers., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 15/35] target-alpha: Implement do_interrupt for system mode., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 16/35] target-alpha: Swap shadow registers moving to/from PALmode., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 17/35] target-alpha: Add various symbolic constants., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 18/35] target-alpha: Use kernel mmu_idx for pal_mode., Richard Henderson, 2011/05/09
- [Qemu-devel] [PATCH 20/35] target-alpha: Disable interrupts properly., Richard Henderson, 2011/05/09