From patchwork Thu Apr 28 20:50:53 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 93312 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B573B1007DB for ; Fri, 29 Apr 2011 06:56:43 +1000 (EST) Received: from localhost ([::1]:42759 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QFYGP-0006Di-71 for incoming@patchwork.ozlabs.org; Thu, 28 Apr 2011 16:56:41 -0400 Received: from eggs.gnu.org ([140.186.70.92]:47821) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QFYBX-0005FD-Sp for qemu-devel@nongnu.org; Thu, 28 Apr 2011 16:51:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QFYBV-0005bP-QW for qemu-devel@nongnu.org; Thu, 28 Apr 2011 16:51:39 -0400 Received: from mail-pv0-f173.google.com ([74.125.83.173]:64385) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QFYBV-0005Zh-CU for qemu-devel@nongnu.org; Thu, 28 Apr 2011 16:51:37 -0400 Received: by mail-pv0-f173.google.com with SMTP id 3so2495040pvg.4 for ; Thu, 28 Apr 2011 13:51:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:from:to:subject:date:message-id:x-mailer :in-reply-to:references; bh=auEC2JlJa+38pNSEu7KAM88qmg6lhn89YTg4PMpH+0Q=; b=Onug5X8IVc9YY7cNEPZtyELZaH8HoQNNLud6msf17DBEcJ+658L8QVivDSLXnrjEY8 oqxehXpb2FQWkp1U1+4a0gsX4QolLQbhvXysl0Ugb4FEbKJrlMs5fuq1Ywldv20V5ySn JtTvjVc1D9v3w11og+JbVWleg2obgxMFrfZU8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; b=YH8Wrc8HK2BThTrCwvZDV5o5HvV+nEGzg/jEQ5aNTHf5UEwzkeOX5PeNwm2iHmqEay adglT6DZJL0POKigBGuKuTjdTc1ONmyHRlsLbOC/AtjCSwkSxF7btgyk1IFetdaBmwhG jnB1jit5N4rP8ruBMScdZPy9VvtSfsYMhhg9Q= Received: by 10.142.62.9 with SMTP id k9mr1402235wfa.162.1304023896853; Thu, 28 Apr 2011 13:51:36 -0700 (PDT) Received: from localhost.localdomain (are.twiddle.net [75.101.38.216]) by mx.google.com with ESMTPS id z10sm2266797wfj.12.2011.04.28.13.51.35 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 28 Apr 2011 13:51:36 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 28 Apr 2011 13:50:53 -0700 Message-Id: <1304023875-25040-12-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.4.4 In-Reply-To: <1304023875-25040-1-git-send-email-rth@twiddle.net> References: <1304023875-25040-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 74.125.83.173 Subject: [Qemu-devel] [PATCH 11/33] target-alpha: Fixup translation of PALmode instructions. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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;