[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa |
Date: |
Mon, 13 Jun 2016 16:58:17 -0700 |
Signed-off-by: Richard Henderson <address@hidden>
---
linux-user/main.c | 45 ++++++++++++++++++++++++
target-openrisc/cpu.c | 1 +
target-openrisc/cpu.h | 9 +++++
target-openrisc/interrupt.c | 1 +
target-openrisc/interrupt_helper.c | 1 +
target-openrisc/mmu.c | 1 +
target-openrisc/translate.c | 70 ++++++++++++++++++++++++++++++++++++++
7 files changed, 128 insertions(+)
diff --git a/linux-user/main.c b/linux-user/main.c
index f8a8764..51af5d1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2720,6 +2720,48 @@ error:
#endif
#ifdef TARGET_OPENRISC
+static void do_store_exclusive(CPUOpenRISCState *env)
+{
+ target_ulong addr, val, tmp;
+ target_siginfo_t info;
+ int ret = 0;
+
+ addr = env->lock_addr;
+ tmp = env->lock_st_addr;
+ env->lock_addr = -1;
+ env->lock_st_addr = 0;
+
+ start_exclusive();
+ mmap_lock();
+
+ if (addr == tmp) {
+ if (get_user_u32(val, addr)) {
+ goto do_sigsegv;
+ }
+ if (val == env->lock_value) {
+ if (put_user_u32(env->lock_st_value, addr)) {
+ goto do_sigsegv;
+ }
+ ret = 1;
+ }
+ }
+ env->sr_f = ret;
+ env->pc += 4;
+
+ mmap_unlock();
+ end_exclusive();
+ return;
+
+ do_sigsegv:
+ mmap_unlock();
+ end_exclusive();
+
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = addr;
+ queue_signal(env, TARGET_SIGSEGV, &info);
+}
void cpu_loop(CPUOpenRISCState *env)
{
@@ -2795,6 +2837,9 @@ void cpu_loop(CPUOpenRISCState *env)
case EXCP_NR:
qemu_log_mask(CPU_LOG_INT, "\nNR\n");
break;
+ case EXCP_SWA:
+ do_store_exclusive(env);
+ break;
default:
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
trapnr);
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 155913f..e6f6186 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -55,6 +55,7 @@ static void openrisc_cpu_reset(CPUState *s)
cpu->env.pc = 0x100;
cpu->env.sr = SR_FO | SR_SM;
+ cpu->env.lock_addr = -1;
s->exception_index = -1;
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8c130da..bb9540f 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -169,6 +169,8 @@ enum {
EXCP_FPE = 0xd,
EXCP_TRAP = 0xe,
EXCP_NR,
+ /* For usermode emulation. */
+ EXCP_SWA,
};
/* Supervisor register */
@@ -295,6 +297,13 @@ typedef struct CPUOpenRISCState {
uint32_t fpcsr; /* Float register */
float_status fp_status;
+ target_ulong lock_addr;
+ target_ulong lock_value;
+#ifdef CONFIG_USER_ONLY
+ target_ulong lock_st_addr;
+ target_ulong lock_st_value;
+#endif
+
uint32_t flags; /* cpu_flags, we only use it for exception
in solt so far. */
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 36ca131..77c2d00 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -55,6 +55,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
env->sr &= ~SR_TEE;
env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
+ env->lock_addr = -1;
if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
env->pc = (cs->exception_index << 8);
diff --git a/target-openrisc/interrupt_helper.c
b/target-openrisc/interrupt_helper.c
index 71e14ce..68d1598 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -34,6 +34,7 @@ void HELPER(rfe)(CPUOpenRISCState *env)
cpu->env.pc = cpu->env.epcr;
cpu->env.npc = cpu->env.epcr;
cpu_set_sr(&cpu->env, cpu->env.esr);
+ cpu->env.lock_addr = -1;
#ifndef CONFIG_USER_ONLY
if (cpu->env.sr & SR_DME) {
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 505dcdc..56b11d3 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -174,6 +174,7 @@ static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU
*cpu,
cs->exception_index = exception;
cpu->env.eear = address;
+ cpu->env.lock_addr = -1;
}
#ifndef CONFIG_USER_ONLY
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index e539693..0ad0c39 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -58,6 +58,8 @@ static TCGv cpu_ppc;
static TCGv cpu_sr_f; /* bf/bnf, F flag taken */
static TCGv cpu_sr_cy; /* carry (unsigned overflow) */
static TCGv cpu_sr_ov; /* signed overflow */
+static TCGv cpu_lock_addr;
+static TCGv cpu_lock_value;
static TCGv_i32 fpcsr;
static TCGv_i64 cpu_mac; /* MACHI:MACLO */
static TCGv_i32 env_flags;
@@ -93,6 +95,12 @@ void openrisc_translate_init(void)
offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
cpu_sr_ov = tcg_global_mem_new(cpu_env,
offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
+ cpu_lock_addr = tcg_global_mem_new(cpu_env,
+ offsetof(CPUOpenRISCState, lock_addr),
+ "lock_addr");
+ cpu_lock_value = tcg_global_mem_new(cpu_env,
+ offsetof(CPUOpenRISCState, lock_value),
+ "lock_value");
fpcsr = tcg_global_mem_new_i32(cpu_env,
offsetof(CPUOpenRISCState, fpcsr),
"fpcsr");
@@ -478,6 +486,58 @@ static void gen_msbu(DisasContext *dc, TCGv srca, TCGv
srcb)
gen_ove_cy(dc);
}
+static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
+{
+ TCGv ea = tcg_temp_new();
+
+ tcg_gen_addi_tl(ea, ra, ofs);
+ tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
+ tcg_gen_mov_tl(cpu_lock_addr, ea);
+ tcg_gen_mov_tl(cpu_lock_value, rd);
+ tcg_temp_free(ea);
+}
+
+static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs)
+{
+#ifdef CONFIG_USER_ONLY
+ TCGv ea = tcg_temp_new();
+ tcg_gen_addi_tl(ea, ra, ofs);
+ tcg_gen_st_tl(ea, cpu_env, offsetof(CPUOpenRISCState, lock_st_addr));
+ tcg_temp_free(ea);
+
+ tcg_gen_st32_tl(rb, cpu_env, offsetof(CPUOpenRISCState, lock_st_value));
+
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_SWA);
+ dc->is_jmp = DISAS_UPDATE;
+#else
+ TCGv ea, val;
+ TCGLabel *lab_fail, *lab_done;
+
+ ea = tcg_temp_new();
+ tcg_gen_addi_tl(ea, ra, ofs);
+
+ lab_fail = gen_new_label();
+ lab_done = gen_new_label();
+ tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
+ tcg_temp_free(ea);
+
+ val = tcg_temp_new();
+ tcg_gen_qemu_ld_tl(val, cpu_lock_addr, dc->mem_idx, MO_TEUL);
+ tcg_gen_brcond_tl(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+
+ tcg_gen_qemu_st_tl(rb, cpu_lock_addr, dc->mem_idx, MO_TEUL);
+ tcg_gen_movi_tl(cpu_sr_f, 1);
+ tcg_gen_br(lab_done);
+
+ gen_set_label(lab_fail);
+ tcg_gen_movi_tl(cpu_sr_f, 0);
+
+ gen_set_label(lab_done);
+ tcg_gen_movi_tl(cpu_lock_addr, -1);
+#endif
+}
+
static void dec_calc(DisasContext *dc, uint32_t insn)
{
uint32_t op0, op1, op2;
@@ -732,6 +792,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
}
break;
+ case 0x1b: /* l.lwa */
+ LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
+ gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
+ break;
+
case 0x1c: /* l.cust1 */
LOG_DIS("l.cust1\n");
break;
@@ -858,6 +923,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
}
break;
+ case 0x33: /* l.swa */
+ LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
+ gen_swa(dc, cpu_R[rb], cpu_R[ra], I5_11);
+ break;
+
case 0x34: /* l.sd */
LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
check_ob64s(dc);
--
2.5.5
- [Qemu-devel] [PATCH 13/25] target-openrisc: Enable trap, csync, msync, psync for user mode, (continued)
- [Qemu-devel] [PATCH 13/25] target-openrisc: Enable trap, csync, msync, psync for user mode, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 11/25] target-openrisc: Rationalize immediate extraction, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 14/25] target-openrisc: Implement muld, muldu, macu, msbu, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 19/25] target-openrisc: Tidy ppc/npc implementation, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 09/25] target-openrisc: Implement ff1 and fl1 for 64-bit, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 21/25] target-openrisc: Tidy insn dumping, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 16/25] target-openrisc: Write back result before FPE exception, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 18/25] target-openrisc: Implement l.adrp, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 20/25] target-openrisc: Optimize l.jal to next, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 10/25] target-openrisc: Represent MACHI:MACLO as a single unit, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 17/25] target-openrisc: Implement lwa, swa,
Richard Henderson <=
- [Qemu-devel] [PATCH 15/25] target-openrisc: Fix madd, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 24/25] target-openrisc: Generate goto_tb for direct branches, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 25/25] target-openrisc: Generate goto_tb for conditional branches, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 22/25] target-openrisc: Tidy handling of delayed branches, Richard Henderson, 2016/06/13
- [Qemu-devel] [PATCH 23/25] target-openrisc: Optimize for r0 being zero, Richard Henderson, 2016/06/13