Module Name: src
Committed By: matt
Date: Fri Aug 21 17:50:00 UTC 2009
Modified Files:
src/sys/arch/mips/mips [matt-nb5-mips64]: mips_emul.c
Log Message:
Add sd/sdl/sdr ld/ldr/ldl emulation.
Use intptr_t for addresses.
To generate a diff of this commit:
cvs rdiff -u -r1.14.78.1 -r1.14.78.2 src/sys/arch/mips/mips/mips_emul.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/mips/mips/mips_emul.c
diff -u src/sys/arch/mips/mips/mips_emul.c:1.14.78.1 src/sys/arch/mips/mips/mips_emul.c:1.14.78.2
--- src/sys/arch/mips/mips/mips_emul.c:1.14.78.1 Thu Aug 20 04:36:05 2009
+++ src/sys/arch/mips/mips/mips_emul.c Fri Aug 21 17:50:00 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: mips_emul.c,v 1.14.78.1 2009/08/20 04:36:05 uebayasi Exp $ */
+/* $NetBSD: mips_emul.c,v 1.14.78.2 2009/08/21 17:50:00 matt Exp $ */
/*
* Copyright (c) 1999 Shuichiro URATA. All rights reserved.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.14.78.1 2009/08/20 04:36:05 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.14.78.2 2009/08/21 17:50:00 matt Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -43,35 +43,45 @@
#include <mips/vmparam.h> /* for VM_MAX_ADDRESS */
#include <mips/trap.h>
-void MachEmulateFP(u_int32_t, struct frame *, u_int32_t);
+void MachEmulateFP(uint32_t, struct frame *, uint32_t);
-static inline void send_sigsegv(vaddr_t, u_int32_t, struct frame *,
- u_int32_t);
-static inline void update_pc(struct frame *, u_int32_t);
+static inline void send_sigsegv(intptr_t, uint32_t, struct frame *,
+ uint32_t);
+static inline void update_pc(struct frame *, uint32_t);
vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned, int);
-void MachEmulateInst(u_int32_t, u_int32_t, vaddr_t, struct frame *);
+void MachEmulateInst(uint32_t, uint32_t, vaddr_t, struct frame *);
-void MachEmulateLWC0(u_int32_t inst, struct frame *, u_int32_t);
-void MachEmulateSWC0(u_int32_t inst, struct frame *, u_int32_t);
-void MachEmulateSpecial(u_int32_t inst, struct frame *, u_int32_t);
-void MachEmulateLWC1(u_int32_t inst, struct frame *, u_int32_t);
-void MachEmulateLDC1(u_int32_t inst, struct frame *, u_int32_t);
-void MachEmulateSWC1(u_int32_t inst, struct frame *, u_int32_t);
-void MachEmulateSDC1(u_int32_t inst, struct frame *, u_int32_t);
-
-void bcemul_lb(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_lbu(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_lh(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_lhu(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_lw(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_lwl(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_lwr(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_sb(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_sh(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_sw(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_swl(u_int32_t inst, struct frame *, u_int32_t);
-void bcemul_swr(u_int32_t inst, struct frame *f, u_int32_t);
+void MachEmulateLWC0(uint32_t inst, struct frame *, uint32_t);
+void MachEmulateSWC0(uint32_t inst, struct frame *, uint32_t);
+void MachEmulateSpecial(uint32_t inst, struct frame *, uint32_t);
+void MachEmulateLWC1(uint32_t inst, struct frame *, uint32_t);
+void MachEmulateLDC1(uint32_t inst, struct frame *, uint32_t);
+void MachEmulateSWC1(uint32_t inst, struct frame *, uint32_t);
+void MachEmulateSDC1(uint32_t inst, struct frame *, uint32_t);
+
+void bcemul_lb(uint32_t inst, struct frame *, uint32_t);
+void bcemul_lbu(uint32_t inst, struct frame *, uint32_t);
+void bcemul_lh(uint32_t inst, struct frame *, uint32_t);
+void bcemul_lhu(uint32_t inst, struct frame *, uint32_t);
+void bcemul_lw(uint32_t inst, struct frame *, uint32_t);
+void bcemul_lwl(uint32_t inst, struct frame *, uint32_t);
+void bcemul_lwr(uint32_t inst, struct frame *, uint32_t);
+#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64)
+void bcemul_ld(uint32_t inst, struct frame *, uint32_t);
+void bcemul_ldl(uint32_t inst, struct frame *, uint32_t);
+void bcemul_ldr(uint32_t inst, struct frame *, uint32_t);
+#endif
+void bcemul_sb(uint32_t inst, struct frame *, uint32_t);
+void bcemul_sh(uint32_t inst, struct frame *, uint32_t);
+void bcemul_sw(uint32_t inst, struct frame *, uint32_t);
+void bcemul_swl(uint32_t inst, struct frame *, uint32_t);
+void bcemul_swr(uint32_t inst, struct frame *f, uint32_t);
+#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64)
+void bcemul_sd(uint32_t inst, struct frame *, uint32_t);
+void bcemul_sdl(uint32_t inst, struct frame *, uint32_t);
+void bcemul_sdr(uint32_t inst, struct frame *f, uint32_t);
+#endif
/*
* MIPS2 LL instruction emulation state
@@ -79,7 +89,7 @@
struct {
struct lwp *lwp;
vaddr_t addr;
- u_int32_t value;
+ uint32_t value;
} llstate;
/*
@@ -207,22 +217,19 @@
* Emulate instructions (including floating-point instructions)
*/
void
-MachEmulateInst(status, cause, opc, frame)
- u_int32_t status;
- u_int32_t cause;
- vaddr_t opc;
- struct frame *frame;
+MachEmulateInst(uint32_t status, uint32_t cause, vaddr_t opc,
+ struct frame *frame)
{
- u_int32_t inst;
+ uint32_t inst;
ksiginfo_t ksi;
/*
* Fetch the instruction.
*/
if (cause & MIPS_CR_BR_DELAY)
- inst = fuword((u_int32_t *)opc+1);
+ inst = fuword((uint32_t *)opc+1);
else
- inst = fuword((u_int32_t *)opc);
+ inst = fuword((uint32_t *)opc);
switch (((InstFmt)inst).FRType.op) {
case OP_LWC0:
@@ -265,8 +272,8 @@
}
static inline void
-send_sigsegv(vaddr_t vaddr, u_int32_t exccode, struct frame *frame,
- u_int32_t cause)
+send_sigsegv(intptr_t vaddr, uint32_t exccode, struct frame *frame,
+ uint32_t cause)
{
ksiginfo_t ksi;
cause = (cause & 0xFFFFFF00) | (exccode << MIPS_CR_EXC_CODE_SHIFT);
@@ -281,7 +288,7 @@
}
static inline void
-update_pc(struct frame *frame, u_int32_t cause)
+update_pc(struct frame *frame, uint32_t cause)
{
if (cause & MIPS_CR_BR_DELAY)
@@ -296,9 +303,9 @@
* MIPS2 LL instruction
*/
void
-MachEmulateLWC0(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateLWC0(uint32_t inst, struct frame *frame, uint32_t cause)
{
- vaddr_t vaddr;
+ intptr_t vaddr;
int16_t offset;
void *t;
@@ -306,16 +313,8 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
- ksiginfo_t ksi;
- frame->f_regs[_R_CAUSE] = cause;
- frame->f_regs[_R_BADVADDR] = vaddr;
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_trap = cause;
- ksi.ksi_code = (vaddr & 3) ? BUS_ADRALN : BUS_ADRERR;
- ksi.ksi_addr = (void *)vaddr;
- (*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
+ if (vaddr < 0 || (vaddr & 3)) {
+ send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -328,7 +327,7 @@
llstate.lwp = curlwp;
llstate.addr = vaddr;
- llstate.value = *((u_int32_t *)t);
+ llstate.value = *((uint32_t *)t);
update_pc(frame, cause);
}
@@ -337,9 +336,9 @@
* MIPS2 SC instruction
*/
void
-MachEmulateSWC0(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateSWC0(uint32_t inst, struct frame *frame, uint32_t cause)
{
- vaddr_t vaddr;
+ intptr_t vaddr;
uint32_t value;
int16_t offset;
mips_reg_t *t;
@@ -348,16 +347,8 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
- ksiginfo_t ksi;
- frame->f_regs[_R_CAUSE] = cause;
- frame->f_regs[_R_BADVADDR] = vaddr;
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_trap = cause;
- ksi.ksi_code = (vaddr & 3) ? BUS_ADRALN : BUS_ADRERR;
- ksi.ksi_addr = (void *)vaddr;
- (*curproc->p_emul->e_trapsignal)(curlwp, &ksi);
+ if (vaddr < 0 || (vaddr & 3)) {
+ send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -396,7 +387,7 @@
}
void
-MachEmulateSpecial(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateSpecial(uint32_t inst, struct frame *frame, uint32_t cause)
{
ksiginfo_t ksi;
switch (((InstFmt)inst).RType.func) {
@@ -423,9 +414,9 @@
#define LWSWC1_MAXLOOP 12
void
-MachEmulateLWC1(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateLWC1(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
void *t;
mips_reg_t pc;
@@ -435,11 +426,12 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
+ if (vaddr < 0 || (vaddr & 3)) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
+ /* NewABI FIXME */
t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
if (copyin((void *)vaddr, t, 4) != 0) {
@@ -458,7 +450,7 @@
return;
vaddr = frame->f_regs[_R_PC]; /* XXX truncates to 32 bits */
- inst = fuiword((u_int32_t *)vaddr);
+ inst = fuiword((uint32_t *)vaddr);
if (((InstFmt)inst).FRType.op != OP_LWC1)
return;
@@ -466,11 +458,12 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
+ if (vaddr < 0 || (vaddr & 3)) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
+ /* NewABI FIXME */
t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
if (copyin((void *)vaddr, t, 4) != 0) {
@@ -484,9 +477,9 @@
}
void
-MachEmulateLDC1(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateLDC1(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
void *t;
@@ -494,11 +487,12 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr & 0x80000007) {
+ if (vaddr < 0 || (vaddr & 7)) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
+ /* NewABI FIXME */
t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]);
if (copyin((void *)vaddr, t, 8) != 0) {
@@ -510,9 +504,9 @@
}
void
-MachEmulateSWC1(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateSWC1(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
void *t;
mips_reg_t pc;
@@ -522,11 +516,12 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
+ if (vaddr < 0 || (vaddr & 3)) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
+ /* NewABI FIXME */
t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
if (copyout(t, (void *)vaddr, 4) != 0) {
@@ -545,7 +540,7 @@
return;
vaddr = frame->f_regs[_R_PC]; /* XXX truncates to 32 bits */
- inst = fuiword((u_int32_t *)vaddr);
+ inst = fuiword((uint32_t *)vaddr);
if (((InstFmt)inst).FRType.op != OP_SWC1)
return;
@@ -553,11 +548,12 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
+ if (vaddr < 0 || (vaddr & 3)) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
+ /* NewABI FIXME */
t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1F]);
if (copyout(t, (void *)vaddr, 4) != 0) {
@@ -571,9 +567,9 @@
}
void
-MachEmulateSDC1(u_int32_t inst, struct frame *frame, u_int32_t cause)
+MachEmulateSDC1(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
void *t;
@@ -581,11 +577,12 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr & 0x80000007) {
+ if (vaddr < 0 || (vaddr & 7)) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
+ /* NewABI FIXME */
t = &(curpcb->pcb_fpregs.r_regs[(inst>>16)&0x1E]);
if (copyout(t, (void *)vaddr, 8) != 0) {
@@ -597,9 +594,9 @@
}
void
-bcemul_lb(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lb(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
int8_t x;
@@ -607,7 +604,7 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment check */
- if (vaddr & 0x80000000) {
+ if (vaddr < 0) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -623,17 +620,17 @@
}
void
-bcemul_lbu(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lbu(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
- u_int8_t x;
+ uint8_t x;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment check */
- if (vaddr & 0x80000000) {
+ if (vaddr < 0) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -643,15 +640,15 @@
return;
}
- frame->f_regs[(inst>>16)&0x1F] = (u_int32_t)x;
+ frame->f_regs[(inst>>16)&0x1F] = (mips_ureg_t)x;
update_pc(frame, cause);
}
void
-bcemul_lh(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lh(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
int16_t x;
@@ -659,7 +656,7 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr & 0x80000001) {
+ if (vaddr < 0 || (vaddr & 1)) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -669,15 +666,15 @@
return;
}
- frame->f_regs[(inst>>16)&0x1F] = (int32_t)x;
+ frame->f_regs[(inst>>16)&0x1F] = x;
update_pc(frame, cause);
}
void
-bcemul_lhu(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lhu(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
u_int16_t x;
@@ -685,7 +682,7 @@
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr & 0x80000001) {
+ if (vaddr < 0 || (vaddr & 1)) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -695,22 +692,22 @@
return;
}
- frame->f_regs[(inst>>16)&0x1F] = (u_int32_t)x;
+ frame->f_regs[(inst>>16)&0x1F] = (mips_ureg_t)x;
update_pc(frame, cause);
}
void
-bcemul_lw(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lw(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
+ if (vaddr < 0 || (vaddr & 3)) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
@@ -724,21 +721,22 @@
}
void
-bcemul_lwl(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lwl(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr, a, x, shift;
+ intptr_t vaddr;
+ uint32_t a, x, shift;
int16_t offset;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment check */
- if (vaddr & 0x80000000) {
+ if (vaddr < 0) {
send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
return;
}
- if (copyin((void *)(vaddr & ~0x3), &a, 4) != 0) {
+ if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
return;
}
@@ -756,9 +754,10 @@
}
void
-bcemul_lwr(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_lwr(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr, a, x, shift;
+ intptr_t vaddr;
+ uint32_t a, x, shift;
int16_t offset;
offset = inst & 0xFFFF;
@@ -770,7 +769,7 @@
return;
}
- if (copyin((void *)(vaddr & ~0x3), &a, 4) != 0) {
+ if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
return;
}
@@ -787,10 +786,36 @@
update_pc(frame, cause);
}
+#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64)
+void
+bcemul_ld(uint32_t inst, struct frame *frame, uint32_t cause)
+{
+ intptr_t vaddr;
+ int16_t offset;
+
+ offset = inst & 0xFFFF;
+ vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
+
+ /* segment and alignment check */
+ if (vaddr > VM_MAX_ADDRESS || vaddr & 0x7) {
+ send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
+ return;
+ }
+
+ if (copyin((void *)vaddr, &(frame->f_regs[(inst>>16)&0x1F]), 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
+ return;
+ }
+
+ update_pc(frame, cause);
+}
+
void
-bcemul_sb(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_ldl(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
+ uint64_t a, x;
+ uint32_t shift;
int16_t offset;
offset = inst & 0xFFFF;
@@ -798,6 +823,73 @@
/* segment check */
if (vaddr & 0x80000000) {
+ send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
+ return;
+ }
+
+ if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
+ return;
+ }
+
+ x = frame->f_regs[(inst>>16)&0x1F];
+
+ shift = (7 - (vaddr & 0x7)) * 8;
+ a <<= shift;
+ x &= ~(~(uint64_t)0UL << shift);
+ x |= a;
+
+ frame->f_regs[(inst>>16)&0x1F] = x;
+
+ update_pc(frame, cause);
+}
+
+void
+bcemul_ldr(uint32_t inst, struct frame *frame, uint32_t cause)
+{
+ intptr_t vaddr;
+ uint64_t a, x;
+ uint32_t shift;
+ int16_t offset;
+
+ offset = inst & 0xFFFF;
+ vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
+
+ /* segment check */
+ if (vaddr < 0) {
+ send_sigsegv(vaddr, T_ADDR_ERR_LD, frame, cause);
+ return;
+ }
+
+ if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_LD_MISS, frame, cause);
+ return;
+ }
+
+ x = frame->f_regs[(inst>>16)&0x1F];
+
+ shift = (vaddr & 0x7) * 8;
+ a >>= shift;
+ x &= ~(~(uint64_t)0UL >> shift);
+ x |= a;
+
+ frame->f_regs[(inst>>16)&0x1F] = x;
+
+ update_pc(frame, cause);
+}
+#endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */
+
+void
+bcemul_sb(uint32_t inst, struct frame *frame, uint32_t cause)
+{
+ intptr_t vaddr;
+ int16_t offset;
+
+ offset = inst & 0xFFFF;
+ vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
+
+ /* segment check */
+ if (vaddr < 0) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
@@ -811,16 +903,16 @@
}
void
-bcemul_sh(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_sh(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr & 0x80000001) {
+ if (vaddr < 0 || vaddr & 1) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
@@ -834,16 +926,16 @@
}
void
-bcemul_sw(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_sw(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr;
+ intptr_t vaddr;
int16_t offset;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment and alignment check */
- if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) {
+ if (vaddr < 0 || (vaddr & 3)) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
@@ -857,28 +949,29 @@
}
void
-bcemul_swl(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_swl(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr, a, x, shift;
+ intptr_t vaddr;
+ uint32_t a, x, shift;
int16_t offset;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment check */
- if (vaddr & 0x80000000) {
+ if (vaddr < 0) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
- if (copyin((void *)(vaddr & ~0x3), &a, 4) != 0) {
+ if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
return;
}
x = frame->f_regs[(inst>>16)&0x1F];
- shift = (3 - (vaddr & 0x00000003)) * 8;
+ shift = (3 - (vaddr & 3)) * 8;
x >>= shift;
a &= ~(0xFFFFFFFFUL >> shift);
a |= x;
@@ -892,28 +985,29 @@
}
void
-bcemul_swr(u_int32_t inst, struct frame *frame, u_int32_t cause)
+bcemul_swr(uint32_t inst, struct frame *frame, uint32_t cause)
{
- u_int32_t vaddr, a, x, shift;
+ intptr_t vaddr;
+ uint32_t a, x, shift;
int16_t offset;
offset = inst & 0xFFFF;
vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
/* segment check */
- if (vaddr & 0x80000000) {
+ if (vaddr < 0) {
send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
return;
}
- if (copyin((void *)(vaddr & ~0x3), &a, 4) != 0) {
+ if (copyin((void *)(vaddr & ~3), &a, 4) != 0) {
send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
return;
}
x = frame->f_regs[(inst>>16)&0x1F];
- shift = (vaddr & 0x00000003) * 8;
+ shift = (vaddr & 3) * 8;
x <<= shift;
a &= ~(0xFFFFFFFFUL << shift);
a |= x;
@@ -925,4 +1019,103 @@
update_pc(frame, cause);
}
+
+#if defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64)
+void
+bcemul_sd(uint32_t inst, struct frame *frame, uint32_t cause)
+{
+ intptr_t vaddr;
+ int16_t offset;
+
+ offset = inst & 0xFFFF;
+ vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
+
+ /* segment and alignment check */
+ if (vaddr < 0 || vaddr & 0x7) {
+ send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
+ return;
+ }
+
+ if (copyout((void *)vaddr, &frame->f_regs[(inst>>16)&0x1F], 8) < 0) {
+ send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ return;
+ }
+
+ update_pc(frame, cause);
+}
+
+void
+bcemul_sdl(uint32_t inst, struct frame *frame, uint32_t cause)
+{
+ intptr_t vaddr;
+ uint64_t a, x;
+ uint32_t shift;
+ int16_t offset;
+
+ offset = inst & 0xFFFF;
+ vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
+
+ /* segment check */
+ if (vaddr < 0) {
+ send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
+ return;
+ }
+
+ if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ return;
+ }
+
+ x = frame->f_regs[(inst>>16)&0x1F];
+
+ shift = (7 - (vaddr & 7)) * 8;
+ x >>= shift;
+ a &= ~(~(uint64_t)0U >> shift);
+ a |= x;
+
+ if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ return;
+ }
+
+ update_pc(frame, cause);
+}
+
+void
+bcemul_sdr(uint32_t inst, struct frame *frame, uint32_t cause)
+{
+ intptr_t vaddr;
+ uint64_t a, x;
+ uint32_t shift;
+ int16_t offset;
+
+ offset = inst & 0xFFFF;
+ vaddr = frame->f_regs[(inst>>21)&0x1F] + offset;
+
+ /* segment check */
+ if (vaddr < 0) {
+ send_sigsegv(vaddr, T_ADDR_ERR_ST, frame, cause);
+ return;
+ }
+
+ if (copyin((void *)(vaddr & ~0x7), &a, 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ return;
+ }
+
+ x = frame->f_regs[(inst>>16)&0x1F];
+
+ shift = (vaddr & 7) * 8;
+ x <<= shift;
+ a &= ~(~(uint64_t)0U << shift);
+ a |= x;
+
+ if (copyout((void *)(vaddr & ~0x7), &a, 8) != 0) {
+ send_sigsegv(vaddr, T_TLB_ST_MISS, frame, cause);
+ return;
+ }
+
+ update_pc(frame, cause);
+}
+#endif /* defined(__mips_n32) || defined(__mips_n64) || defined(__mips_o64) */
#endif /* defined(SOFTFLOAT) */