Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/mips/mips Implement true LL/SC emulation. Mostly f...
details: https://anonhg.NetBSD.org/src/rev/564e922283e4
branches: trunk
changeset: 534304:564e922283e4
user: gmcgarry <gmcgarry%NetBSD.org@localhost>
date: Sun Jul 21 05:47:51 2002 +0000
description:
Implement true LL/SC emulation. Mostly from Jason Thorpe in PR17548.
diffstat:
sys/arch/mips/mips/mips_emul.c | 141 ++++++++++++++--------------------------
1 files changed, 50 insertions(+), 91 deletions(-)
diffs (228 lines):
diff -r cde93eb37dcf -r 564e922283e4 sys/arch/mips/mips/mips_emul.c
--- a/sys/arch/mips/mips/mips_emul.c Sun Jul 21 02:56:35 2002 +0000
+++ b/sys/arch/mips/mips/mips_emul.c Sun Jul 21 05:47:51 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mips_emul.c,v 1.1 2002/07/06 23:59:21 gmcgarry Exp $ */
+/* $NetBSD: mips_emul.c,v 1.2 2002/07/21 05:47:51 gmcgarry Exp $ */
/*
* Copyright (c) 1999 Shuichiro URATA. All rights reserved.
@@ -71,6 +71,15 @@
void bcemul_swr(u_int32_t inst, struct frame *f, u_int32_t);
/*
+ * MIPS2 LL instruction emulation state
+ */
+struct {
+ struct proc *proc;
+ vaddr_t addr;
+ u_int32_t value;
+} llstate;
+
+/*
* Analyse 'next' PC address taking account of branch/jump instructions
*/
vaddr_t
@@ -210,7 +219,6 @@
inst = fuword((u_int32_t *)opc);
switch (((InstFmt)inst).FRType.op) {
-#if defined(MIPS1)
case OP_LWC0:
MachEmulateLWC0(inst, frame, cause);
break;
@@ -220,7 +228,6 @@
case OP_SPECIAL:
MachEmulateSpecial(inst, frame, cause);
break;
-#endif
case OP_COP1:
MachEmulateFP(inst, frame, cause);
break;
@@ -268,12 +275,8 @@
frame->f_regs[PC] += 4;
}
-#if defined(MIPS1)
-
-#define LWLWC0_MAXLOOP 12
-
/*
- * XXX only on uniprocessor machines
+ * MIPS2 LL instruction
*/
void
MachEmulateLWC0(u_int32_t inst, struct frame *frame, u_int32_t cause)
@@ -281,15 +284,15 @@
u_int32_t vaddr;
int16_t offset;
void *t;
- mips_reg_t pc;
- int i;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
- send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
+ frame->f_regs[CAUSE] = cause;
+ frame->f_regs[BADVADDR] = vaddr;
+ trapsignal(curproc, SIGBUS, vaddr);
return;
}
@@ -300,107 +303,66 @@
return;
}
- pc = frame->f_regs[PC];
- update_pc(frame, cause);
-
- if (cause & MIPS_CR_BR_DELAY)
- return;
-
- for (i = 1; i < LWLWC0_MAXLOOP; i++) {
- if (mips_btop(frame->f_regs[PC]) != mips_btop(pc))
- return;
-
- vaddr = frame->f_regs[PC]; /* XXX truncates to 32 bits */
- inst = fuiword((u_int32_t *)vaddr);
- if (((InstFmt)inst).FRType.op != OP_LWC0)
- return;
+ llstate.proc = curproc;
+ llstate.addr = vaddr;
+ llstate.value = *((u_int32_t *)t);
- offset = inst & 0xFFFF;
- vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
-
- /* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
- send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
- return;
- }
-
- t = &(frame->f_regs[(inst>>16)&0x1F]);
-
- if (copyin((void *)vaddr, t, 4) != 0) {
- send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
- return;
- }
-
- pc = frame->f_regs[PC];
- update_pc(frame, cause);
- }
+ update_pc(frame, cause);
}
-#define LWSWC0_MAXLOOP 12
-
/*
- * XXX only on uniprocessor machines
+ * MIPS2 SC instruction
*/
void
MachEmulateSWC0(u_int32_t inst, struct frame *frame, u_int32_t cause)
{
-
- u_int32_t vaddr;
+ u_int32_t vaddr, value;
int16_t offset;
- void *t;
- mips_reg_t pc;
- int i;
+ mips_reg_t *t;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
- send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
- return;
- }
-
- t = &(frame->f_regs[(inst>>16)&0x1F]);
-
- if (copyout(t, (void *)vaddr, 4) != 0) {
- send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ frame->f_regs[CAUSE] = cause;
+ frame->f_regs[BADVADDR] = vaddr;
+ trapsignal(curproc, SIGBUS, vaddr);
return;
}
- pc = frame->f_regs[PC];
- update_pc(frame, cause);
-
- if (cause & MIPS_CR_BR_DELAY)
- return;
-
- for (i = 1; i < LWSWC0_MAXLOOP; i++) {
- if (mips_btop(frame->f_regs[PC]) != mips_btop(pc))
- return;
+ t = (mips_reg_t *)&(frame->f_regs[(inst>>16)&0x1F]);
- vaddr = frame->f_regs[PC]; /* XXX truncates to 32 bits */
- inst = fuiword((u_int32_t *)vaddr);
- if (((InstFmt)inst).FRType.op != OP_SWC0)
- return;
-
- offset = inst & 0xFFFF;
- vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
-
- /* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
- send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
+ /*
+ * Check that the process and address match the last
+ * LL instruction.
+ */
+ if (curproc == llstate.proc && vaddr == llstate.addr) {
+ llstate.proc = NULL;
+ /*
+ * Check that the data at the address hasn't changed
+ * since the LL instruction.
+ */
+ if (copyin((void *)vaddr, &value, 4) != 0) {
+ send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
return;
}
-
- t = &(frame->f_regs[(inst>>16)&0x1F]);
-
- if (copyout(t, (void *)vaddr, 4) != 0) {
- send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ if (value == llstate.value) {
+ /* SC successful */
+ if (copyout(t, (void *)vaddr, 4) != 0) {
+ send_sigsegv(vaddr, T_TLB_ST_MISS,
+ frame, cause);
+ return;
+ }
+ *t = 1;
+ update_pc(frame, cause);
return;
}
+ }
- pc = frame->f_regs[PC];
- update_pc(frame, cause);
- }
+ /* SC failed */
+ *t = 0;
+ update_pc(frame, cause);
}
void
@@ -419,9 +381,6 @@
update_pc(frame, cause);
}
-#endif /* defined(MIPS1) */
-
-
#if defined(SOFTFLOAT)
#define LWSWC1_MAXLOOP 12
Home |
Main Index |
Thread Index |
Old Index