From patchwork Fri Jun 1 03:23:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peter A. G. Crosthwaite" X-Patchwork-Id: 162262 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6340BB7003 for ; Fri, 1 Jun 2012 13:24:01 +1000 (EST) Received: from localhost ([::1]:60630 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SaIT1-00016r-IB for incoming@patchwork.ozlabs.org; Thu, 31 May 2012 23:23:59 -0400 Received: from eggs.gnu.org ([208.118.235.92]:49123) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SaISt-00016T-EU for qemu-devel@nongnu.org; Thu, 31 May 2012 23:23:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SaISr-0002Iq-BR for qemu-devel@nongnu.org; Thu, 31 May 2012 23:23:51 -0400 Received: from mail-pz0-f45.google.com ([209.85.210.45]:60137) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SaISr-0002IJ-1z for qemu-devel@nongnu.org; Thu, 31 May 2012 23:23:49 -0400 Received: by dadv2 with SMTP id v2so2382149dad.4 for ; Thu, 31 May 2012 20:23:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=YRwBk9yaJ0A19PzT43hOCE97wCS7urVzdaUmcRT1Ovs=; b=UCkN8nip570cGT9BPshB4yKIF8gf5hEHQABGsgC1o2fVmI+1s0i0y8iW/KzYIaS7Tk EEewJt+A1HPfw6l7fkyPm4kkBqCPrqkXptvkIXA1Ggsk3PVBRpC0TN1AyJi1Cc8Nmlcs Mk/CM2gBxSzyxr2wFhiwz13JdAVzWV3uepZLY54kt9IQ6wKLLndIF1nIIM33jy873PP6 D7FeHBtaXFlp9o2mGCNR1cNyZci6aqigvG/AvfB5TYZo17kdQHHdYV6++dr+unJohqyR ncu5/goHATJ7mnaUhjDOfD0RwJrjm6KD3GlTbYZ6G5Xz7siBgHmm3HdPmhonjb0Log+p X3dg== Received: by 10.68.228.39 with SMTP id sf7mr5921545pbc.45.1338521026516; Thu, 31 May 2012 20:23:46 -0700 (PDT) Received: from localhost ([124.148.20.9]) by mx.google.com with ESMTPS id jv6sm1199819pbc.40.2012.05.31.20.23.42 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 31 May 2012 20:23:45 -0700 (PDT) From: "Peter A. G. Crosthwaite" To: edgar.iglesias@gmail.com, qemu-devel@nongnu.org Date: Fri, 1 Jun 2012 13:23:28 +1000 Message-Id: <1338521008-12740-1-git-send-email-peter.crosthwaite@petalogix.com> X-Mailer: git-send-email 1.7.3.2 X-Gm-Message-State: ALoCoQmrtNuJOP0fxxDh44JP4PnH5bx9/XracHKpNEt5psbDcGJgYw/sFXftkS1Q/EpMwpPOsfxJ X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.210.45 Cc: peter.crosthwaite@petalogix.com, david.holsgrove@petalogix.com, john.williams@petalogix.com Subject: [Qemu-devel] [PATCH v4] target-microblaze: lwx/swx: first implementation 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 Signed-off-by: Peter A. G. Crosthwaite --- changed from v3: simplified tcg local variable usage aqcross branch changed from v2: fixed tcg local variable usage across branch reworked carry logic (with new write_carryi() function) made LOG_DIS show lwx swx properly changed from v1: implemented reservation address checking created new cpu state variable specifically for reservation address/flag state target-microblaze/cpu.c | 1 + target-microblaze/cpu.h | 4 ++ target-microblaze/helper.c | 2 + target-microblaze/translate.c | 62 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c index 9c3b74e..34b3a9b 100644 --- a/target-microblaze/cpu.c +++ b/target-microblaze/cpu.c @@ -39,6 +39,7 @@ static void mb_cpu_reset(CPUState *s) mcc->parent_reset(s); memset(env, 0, offsetof(CPUMBState, breakpoints)); + env->res_addr = RES_ADDR_NONE; tlb_flush(env, 1); /* Disable stack protector. */ diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 718d5bb..b0ba9fe 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -243,6 +243,10 @@ struct CPUMBState { /* Stack protectors. Yes, it's a hw feature. */ uint32_t slr, shr; + /* lwx/swx reserved address */ +#define RES_ADDR_NONE 0xffffffff /* Use 0xffffffff to indicate no reservation */ + uint32_t res_addr; + /* Internal flags. */ #define IMM_FLAG 4 #define MSR_EE_FLAG (1 << 8) diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c index 2412a58..74fce26 100644 --- a/target-microblaze/helper.c +++ b/target-microblaze/helper.c @@ -29,6 +29,7 @@ void do_interrupt (CPUMBState *env) { env->exception_index = -1; + env->res_addr = RES_ADDR_NONE; env->regs[14] = env->sregs[SR_PC]; } @@ -116,6 +117,7 @@ void do_interrupt(CPUMBState *env) assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG))); assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); /* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */ + env->res_addr = RES_ADDR_NONE; switch (env->exception_index) { case EXCP_HW_EXCP: if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index a362938..f0ebd59 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -162,6 +162,14 @@ static void write_carry(DisasContext *dc, TCGv v) tcg_temp_free(t0); } +static void write_carryi(DisasContext *dc, int carry) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_movi_tl(t0, carry ? 1 : 0); + write_carry(dc, t0); + tcg_temp_free(t0); +} + /* True if ALU operand b is a small immediate that may deserve faster treatment. */ static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) @@ -948,12 +956,13 @@ static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size) static void dec_load(DisasContext *dc) { TCGv t, *addr; - unsigned int size, rev = 0; + unsigned int size, rev = 0, ex = 0; size = 1 << (dc->opcode & 3); if (!dc->type_b) { rev = (dc->ir >> 9) & 1; + ex = (dc->ir >> 10) & 1; } if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) @@ -963,7 +972,8 @@ static void dec_load(DisasContext *dc) return; } - LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : ""); + LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", + ex ? "x" : ""); t_sync_flags(dc); addr = compute_ldst_addr(dc, &t); @@ -1019,6 +1029,17 @@ static void dec_load(DisasContext *dc) } } + /* lwx does not throw unaligned access errors, so force alignment */ + if (ex) { + /* Force addr into the temp. */ + if (addr != &t) { + t = tcg_temp_new(); + tcg_gen_mov_tl(t, *addr); + addr = &t; + } + tcg_gen_andi_tl(t, t, ~3); + } + /* If we get a fault on a dslot, the jmpstate better be in sync. */ sync_jmpstate(dc); @@ -1057,6 +1078,12 @@ static void dec_load(DisasContext *dc) } } + if (ex) { /* lwx */ + /* no support for for AXI exclusive so always clear C */ + write_carryi(dc, 0); + tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr)); + } + if (addr == &t) tcg_temp_free(t); } @@ -1078,12 +1105,14 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val, static void dec_store(DisasContext *dc) { - TCGv t, *addr; - unsigned int size, rev = 0; + TCGv t, *addr, swx_addr, r_check = 0; + int swx_skip = 0; + unsigned int size, rev = 0, ex = 0; size = 1 << (dc->opcode & 3); if (!dc->type_b) { rev = (dc->ir >> 9) & 1; + ex = (dc->ir >> 10) & 1; } if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) @@ -1093,12 +1122,30 @@ static void dec_store(DisasContext *dc) return; } - LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : ""); + LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", + ex ? "x" : ""); t_sync_flags(dc); /* If we get a fault on a dslot, the jmpstate better be in sync. */ sync_jmpstate(dc); addr = compute_ldst_addr(dc, &t); + if (ex) { /* swx */ + r_check = tcg_temp_new(); + swx_addr = tcg_temp_local_new(); + + /* Force addr into the swx_addr. */ + tcg_gen_mov_tl(swx_addr, *addr); + addr = &swx_addr; + /* swx does not throw unaligned access errors, so force alignment */ + tcg_gen_andi_tl(swx_addr, swx_addr, ~3); + + tcg_gen_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr)); + write_carryi(dc, 1); + swx_skip = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip); + write_carryi(dc, 0); + } + if (rev && size != 4) { /* Endian reverse the address. t is addr. */ switch (size) { @@ -1174,6 +1221,11 @@ static void dec_store(DisasContext *dc) gen_helper_memalign(*addr, tcg_const_tl(dc->rd), tcg_const_tl(1), tcg_const_tl(size - 1)); } + if (ex) { + gen_set_label(swx_skip); + tcg_temp_free(r_check); + tcg_temp_free(swx_addr); + } if (addr == &t) tcg_temp_free(t);