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) */

Reply via email to