Module Name:    src
Committed By:   matt
Date:           Wed Dec 29 00:40:41 UTC 2010

Modified Files:
        src/sys/arch/mips/conf [matt-nb5-mips64]: files.mips
Added Files:
        src/sys/arch/mips/mips [matt-nb5-mips64]: bds_emul.S

Log Message:
Break out break slot instruction emualtion into its own .S file.
Redo that and simplify


To generate a diff of this commit:
cvs rdiff -u -r1.58.24.11 -r1.58.24.12 src/sys/arch/mips/conf/files.mips
cvs rdiff -u -r0 -r1.1.2.1 src/sys/arch/mips/mips/bds_emul.S

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/conf/files.mips
diff -u src/sys/arch/mips/conf/files.mips:1.58.24.11 src/sys/arch/mips/conf/files.mips:1.58.24.12
--- src/sys/arch/mips/conf/files.mips:1.58.24.11	Sun Feb 28 23:45:07 2010
+++ src/sys/arch/mips/conf/files.mips	Wed Dec 29 00:40:40 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files.mips,v 1.58.24.11 2010/02/28 23:45:07 matt Exp $
+#	$NetBSD: files.mips,v 1.58.24.12 2010/12/29 00:40:40 matt Exp $
 #
 
 defflag	opt_cputype.h		NOFPU FPEMUL
@@ -42,7 +42,7 @@
 file	arch/mips/mips/pmap_tlb.c
 file	arch/mips/mips/trap.c			# trap handlers
 file	arch/mips/mips/syscall.c		# syscall entries
-file	arch/mips/mips/mips_fixup.c		mips3 | mips4 | mips32 | mips64
+file	arch/mips/mips/mips_fixup.c
 file	arch/mips/mips/mips_fpu.c
 file	arch/mips/mips/mips_machdep.c
 file	arch/mips/mips/mips_softint.c
@@ -68,6 +68,7 @@
 file	arch/mips/mips/mips_fputrap.c		!nofpu | fpemul
 file	arch/mips/mips/mips_emul.c
 file	arch/mips/mips/fp.S			!nofpu | fpemul
+file	arch/mips/mips/bds_emul.S		fpemul
 
 file	arch/mips/mips/procfs_machdep.c		procfs
 

Added files:

Index: src/sys/arch/mips/mips/bds_emul.S
diff -u /dev/null src/sys/arch/mips/mips/bds_emul.S:1.1.2.1
--- /dev/null	Wed Dec 29 00:40:41 2010
+++ src/sys/arch/mips/mips/bds_emul.S	Wed Dec 29 00:40:41 2010
@@ -0,0 +1,629 @@
+/*	$NetBSD: bds_emul.S,v 1.1.2.1 2010/12/29 00:40:41 matt Exp $	*/
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)fp.s	8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/cdefs.h>
+
+#include <mips/asm.h>
+#include <mips/cpu.h>			/* for MIPS_CURLWP */
+#include <mips/trap.h>			/* for T_RES_INST */
+
+#include "assym.h"
+
+/* insns are reordered in the way as MIPS architecture imposes */
+	.set	reorder
+
+#define	REG_REGMASK	(0x1f << REG_SCALESHIFT)
+
+/*
+ * Emulate CPU instruction in branch delay slot.
+ * These instructions are not implemented and causes SIGILL.
+ *  jump/branch
+ *  COP0
+ *  trap/syscall/break
+ *
+ * Args are same as mips_emul_fp, eg.
+ * void mips_emul_delayslot(uint32_t insn, struct trapframe *tf, uint32_t cause);
+ * It should be used to emulate an instruction in a branch delay slot.
+ */
+LEAF(mips_emul_branchdelayslot)
+	REG_PROLOGUE
+	REG_S	zero, TF_REG_ZERO(a1)		# ensure zero has value 0
+	REG_EPILOGUE
+	move	t3, ra				# need to save this locally
+
+	srl	t0, a0, 26-PTR_SCALESHIFT
+	andi	t0, 0x3F << PTR_SCALESHIFT
+	PTR_L	t0, bcemul_optbl(t0)
+	j	t0
+
+	.rdata
+bcemul_optbl:
+	PTR_WORD bcemul_special			# 000 SPECIAL
+	PTR_WORD bcemul_sigill			# 001 REGIMM
+	PTR_WORD bcemul_sigill			# 002 J
+	PTR_WORD bcemul_sigill			# 003 JAL
+	PTR_WORD bcemul_sigill			# 004 BEQ
+	PTR_WORD bcemul_sigill			# 005 BNE
+	PTR_WORD bcemul_sigill			# 006 BLEZ
+	PTR_WORD bcemul_sigill			# 007 BGTZ
+	PTR_WORD bcemul_addi			# 010 ADDI
+	PTR_WORD bcemul_addiu			# 011 ADDIU
+	PTR_WORD bcemul_slti			# 012 SLTI
+	PTR_WORD bcemul_sltiu			# 013 SLTIU
+	PTR_WORD bcemul_andi			# 014 ANDI
+	PTR_WORD bcemul_ori			# 015 ORI
+	PTR_WORD bcemul_xori			# 016 XORI
+	PTR_WORD bcemul_lui			# 017 LUI
+	PTR_WORD bcemul_sigill			# 020 COP0
+	PTR_WORD _C_LABEL(mips_emul_fp)		# 021 COP1
+	PTR_WORD bcemul_sigill			# 022 COP2
+	PTR_WORD bcemul_sigill			# 023 COP1X
+	PTR_WORD bcemul_sigill			# 024 BEQL
+	PTR_WORD bcemul_sigill			# 025 BNEL
+	PTR_WORD bcemul_sigill			# 026 BNEZL
+	PTR_WORD bcemul_sigill			# 027 BGTZL
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 030 DADDI (*)
+	PTR_WORD bcemul_sigill			# 031 DADDIU (*)
+	PTR_WORD bcemul_sigill			# 030 LDL (*)
+	PTR_WORD bcemul_sigill			# 031 LDR (*)
+#else
+	PTR_WORD _C_LABEL(mips_emul_daddi)	# 030 DADDI (*)
+	PTR_WORD _C_LABEL(mips_emul_daddiu)	# 031 DADDIU (*)
+	PTR_WORD _C_LABEL(mips_emul_ldl)	# 032 LDL (*)
+	PTR_WORD _C_LABEL(mips_emul_ldr)	# 033 LDR (*)
+#endif
+	PTR_WORD bcemul_sigill			# 034 SPECIAL2
+	PTR_WORD bcemul_sigill			# 035 JALX
+	PTR_WORD bcemul_sigill			# 036 MDMX
+	PTR_WORD bcemul_sigill			# 037 SPECIAL3
+	PTR_WORD _C_LABEL(mips_emul_lb)		# 040 LB
+	PTR_WORD _C_LABEL(mips_emul_lh)		# 041 LH
+	PTR_WORD _C_LABEL(mips_emul_lwl)	# 042 LWL
+	PTR_WORD _C_LABEL(mips_emul_lw)		# 043 LW
+	PTR_WORD _C_LABEL(mips_emul_lbu)	# 044 LBU
+	PTR_WORD _C_LABEL(mips_emul_lhu)	# 045 LHU
+	PTR_WORD _C_LABEL(mips_emul_lwr)	# 046 LWR
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 047 LWU (*)
+#else
+	PTR_WORD _C_LABEL(mips_emul_lwu)	# 047 LWU (*)
+#endif
+	PTR_WORD _C_LABEL(mips_emul_sb)		# 050 SB
+	PTR_WORD _C_LABEL(mips_emul_sh)		# 051 SH
+	PTR_WORD _C_LABEL(mips_emul_swl)	# 052 SWL
+	PTR_WORD _C_LABEL(mips_emul_sw)		# 053 SW
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 054 SDL (*)
+	PTR_WORD bcemul_sigill			# 055 SDR (*)
+#else
+	PTR_WORD _C_LABEL(mips_emul_sdl)	# 054 SDL (*)
+	PTR_WORD _C_LABEL(mips_emul_sdr)	# 055 SDR (*)
+#endif
+	PTR_WORD _C_LABEL(mips_emul_swr)	# 056 SWR
+	PTR_WORD bcemul_sigill			# 057 CACHE
+	PTR_WORD bcemul_sigill			# 060 LL
+	PTR_WORD _C_LABEL(mips_emul_lwc1)	# 061 LWC1
+	PTR_WORD bcemul_sigill			# 062 LWC2
+	PTR_WORD bcemul_sigill			# 063 PREF
+	PTR_WORD bcemul_sigill			# 064 LLD (*)
+	PTR_WORD _C_LABEL(mips_emul_ldc1)	# 065 LDC
+	PTR_WORD bcemul_sigill			# 066 LDC2
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 067 LD (*)
+#else
+	PTR_WORD _C_LABEL(mips_emul_ld)		# 067 LD (*)
+#endif
+	PTR_WORD bcemul_sigill			# 070 SC
+	PTR_WORD _C_LABEL(mips_emul_swc1)	# 071 SWC1
+	PTR_WORD bcemul_sigill			# 072 SWC2
+	PTR_WORD bcemul_sigill			# 073
+	PTR_WORD bcemul_sigill			# 074 SCD (*)
+	PTR_WORD _C_LABEL(mips_emul_sdc1)	# 075 SDC1
+	PTR_WORD bcemul_sigill			# 076 SDC2
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 077 SD (*)
+#else
+	PTR_WORD _C_LABEL(mips_emul_sd)		# 077 SD (*)
+#endif
+
+	.text
+bcemul_immed_prologue:
+	srl	t1, a0, 21-REG_SCALESHIFT	# rs (source)
+	srl	t2, a0, 16-REG_SCALESHIFT	# rt (dest)
+	andi	t1, REG_REGMASK
+	andi	t2, REG_REGMASK
+	PTR_ADDU t1, a1
+	PTR_ADDU t2, a1
+	sll	v1, a0, 16
+	sra	v1, v1, 16			# signed immed
+	REG_PROLOGUE
+	REG_L	v0, TF_REG_ZERO(t1)		# load source
+	REG_EPILOGUE
+	j	ra				# execute the instruction
+
+bcemul_uimmed_prologue:
+	srl	t1, a0, 21-REG_SCALESHIFT	# rs (source)
+	srl	t2, a0, 16-REG_SCALESHIFT	# rt (dest)
+	andi	t1, REG_REGMASK
+	andi	t2, REG_REGMASK
+	PTR_ADDU t1, a1
+	PTR_ADDU t2, a1
+	andi	v1, a0, 0xffff			# unsigned immed
+	REG_PROLOGUE
+	REG_L	v0, TF_REG_ZERO(t1)		# load source
+	REG_EPILOGUE
+	j	ra
+
+#ifndef __mips_o32
+bcemul_daddi:
+	bal	bcemul_immed_prologue
+	daddiu	t0, v0, v1
+	b	bcemul_check_add_overflow
+#endif
+
+bcemul_addi:
+	bal	bcemul_immed_prologue
+	addu	t0, v0, v1
+
+bcemul_check_add_overflow:
+	move	ta0, t0		# result
+	move	ta1, v0		# addend 1
+	move	ta2, v1		# addend 2
+
+bcemul_check_overflow:
+	/* Overflow check */
+	xor	ta2, ta1	/* negative + positive can't overflow */
+	bltz	ta2, bcemul_store_and_done
+
+	/* must have added two positive or two negative numbers */
+	xor	ta1, ta0	/* result have same signedness as source? */
+	bgez	ta1, bcemul_store_and_done /* yes, then we didn't overflow */
+
+	b	bcemul_sigill
+
+bcemul_addiu:
+	bal	bcemul_immed_prologue
+	addu	t0, v0, v1
+	b	bcemul_store_and_done
+
+#ifndef __mips_o32
+bcemul_daddiu:
+	bal	bcemul_immed_prologue
+	daddu	t0, v0, v1
+	b	bcemul_store_and_done
+#endif
+
+bcemul_slti:
+	bal	bcemul_immed_prologue
+	slt	t0, v0, v1
+	b	bcemul_store_and_done
+
+bcemul_sltiu:
+	bal	bcemul_immed_prologue
+	sltu	t0, v0, v1
+	b	bcemul_store_and_done
+
+bcemul_andi:
+	bal	bcemul_uimmed_prologue
+	and	t0, v0, v1
+	b	bcemul_store_and_done
+
+bcemul_ori:
+	bal	bcemul_uimmed_prologue
+	or	t0, v0, v1
+	b	bcemul_store_and_done
+
+bcemul_xori:
+	bal	bcemul_uimmed_prologue
+	xor	t0, v0, v1
+	b	bcemul_store_and_done
+
+bcemul_lui:
+	srl	t2, a0, 16-REG_SCALESHIFT	# rt
+	andi	t2, REG_REGMASK
+	PTR_ADDU t2, a1
+	sll	t0, a0, 16
+	b	bcemul_store_and_done
+
+	.rdata
+bcemul_specialtbl:
+	PTR_WORD bcemul_special_genshift	# 000 SLL
+	PTR_WORD bcemul_sigill			# 001 MOVC1
+	PTR_WORD bcemul_special_genshift	# 002 SRL
+	PTR_WORD bcemul_special_genshift	# 003 SRA
+	PTR_WORD bcemul_special_genshiftv	# 004 SLLV
+	PTR_WORD bcemul_sigill			# 005
+	PTR_WORD bcemul_special_genshiftv	# 006 SRLV
+	PTR_WORD bcemul_special_genshiftv	# 007 SRAV
+	PTR_WORD bcemul_sigill			# 010 JR
+	PTR_WORD bcemul_sigill			# 011 JALR
+	PTR_WORD bcemul_sigill			# 012 MOVZ
+	PTR_WORD bcemul_sigill			# 013 MOVN
+	PTR_WORD bcemul_sigill			# 014 SYSCALL
+	PTR_WORD bcemul_sigill			# 015 BREAK
+	PTR_WORD bcemul_sigill			# 016
+	PTR_WORD bcemul_special_sync		# 017 SYNC
+	PTR_WORD bcemul_special_mfhilo		# 020 MFHI
+	PTR_WORD bcemul_special_mthilo		# 021 MTHI
+	PTR_WORD bcemul_special_mfhilo		# 022 MFLO
+	PTR_WORD bcemul_special_mthilo		# 023 MTLO
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 024 DSLLV (*)
+	PTR_WORD bcemul_sigill			# 025
+	PTR_WORD bcemul_sigill			# 026 DSRLV (*)
+	PTR_WORD bcemul_sigill			# 027 DSRAV (*)
+#else
+	PTR_WORD bcemul_special_genshiftv	# 024 DSLLV (*)
+	PTR_WORD bcemul_sigill			# 025
+	PTR_WORD bcemul_special_genshiftv	# 026 DSRLV (*)
+	PTR_WORD bcemul_special_genshiftv	# 027 DSRAV (*)
+#endif
+	PTR_WORD bcemul_special_genmultdiv	# 030 MULT
+	PTR_WORD bcemul_special_genmultdiv	# 031 MULTU
+	PTR_WORD bcemul_special_genmultdiv	# 032 DIV
+	PTR_WORD bcemul_special_genmultdiv	# 033 DIVU
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 034 DMULT (*)
+	PTR_WORD bcemul_sigill			# 035 DMULTU (*)
+	PTR_WORD bcemul_sigill			# 036 DDIV (*)
+	PTR_WORD bcemul_sigill			# 037 DDIVU (*)
+#else
+	PTR_WORD bcemul_special_genmultdiv	# 034 DMULT (*)
+	PTR_WORD bcemul_special_genmultdiv	# 035 DMULTU (*)
+	PTR_WORD bcemul_special_genmultdiv	# 036 DDIV (*)
+	PTR_WORD bcemul_special_genmultdiv	# 037 DDIVU (*)
+#endif
+	PTR_WORD bcemul_special_genadd		# 040 ADD
+	PTR_WORD bcemul_special_gen3op		# 041 ADDU
+	PTR_WORD bcemul_special_gensub		# 042 SUB
+	PTR_WORD bcemul_special_gen3op		# 043 SUBU
+	PTR_WORD bcemul_special_gen3op		# 044 AND
+	PTR_WORD bcemul_special_gen3op		# 045 OR
+	PTR_WORD bcemul_special_gen3op		# 046 XOR
+	PTR_WORD bcemul_special_gen3op		# 047 NOR
+	PTR_WORD bcemul_sigill			# 050
+	PTR_WORD bcemul_sigill			# 051
+	PTR_WORD bcemul_special_gen3op		# 052 SLT
+	PTR_WORD bcemul_special_gen3op		# 053 SLTU
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 054 DADD (*)
+	PTR_WORD bcemul_sigill			# 055 DADDU (*)
+	PTR_WORD bcemul_sigill			# 056 DSUB (*)
+	PTR_WORD bcemul_sigill			# 057 DSUBU (*)
+#else
+	PTR_WORD bcemul_special_genadd		# 054 DADD (*)
+	PTR_WORD bcemul_special_gen3op		# 055 DADDU (*)
+	PTR_WORD bcemul_special_gensub		# 056 DSUB (*)
+	PTR_WORD bcemul_special_gen3op		# 057 DSUBU (*)
+#endif
+	PTR_WORD bcemul_sigill			# 060 TGE
+	PTR_WORD bcemul_sigill			# 061 TGEU
+	PTR_WORD bcemul_sigill			# 062 TLT
+	PTR_WORD bcemul_sigill			# 063 TLTU
+	PTR_WORD bcemul_sigill			# 064 TEQ
+	PTR_WORD bcemul_sigill			# 065
+	PTR_WORD bcemul_sigill			# 066 TNE
+	PTR_WORD bcemul_sigill			# 067
+#ifdef __mips_o32
+	PTR_WORD bcemul_sigill			# 070 DSLL (*)
+	PTR_WORD bcemul_sigill			# 071
+	PTR_WORD bcemul_sigill			# 072 DSRL (*)
+	PTR_WORD bcemul_sigill			# 073 DSRA (*)
+	PTR_WORD bcemul_sigill			# 074 DSLL32 (*)
+	PTR_WORD bcemul_sigill			# 075
+	PTR_WORD bcemul_sigill			# 076 DSRL32 (*)
+	PTR_WORD bcemul_sigill			# 077 DSRA32 (*)
+#else
+	PTR_WORD bcemul_special_genshift	# 070 DSLL (*)
+	PTR_WORD bcemul_sigill			# 071
+	PTR_WORD bcemul_special_genshift	# 072 DSRL (*)
+	PTR_WORD bcemul_special_genshift	# 073 DSRA (*)
+	PTR_WORD bcemul_special_genshift	# 074 DSLL32 (*)
+	PTR_WORD bcemul_sigill			# 075
+	PTR_WORD bcemul_special_genshift	# 076 DSRL32 (*)
+	PTR_WORD bcemul_special_genshift	# 077 DSRA32 (*)
+#endif
+
+	.text
+	.set push
+	.set noreorder
+	.set nomacro
+	.set mips64
+bcemul_special_op:
+	jr	ra;	sllv	t0, v0, v1	# 000 SLL
+	jr	ra;	nop			# 001 MOVC1
+	jr	ra;	srlv	t0, v0, v1	# 002 SRL
+	jr	ra;	srav	t0, v0, v1	# 003 SRA
+	jr	ra;	sllv	t0, v0, v1	# 004 SLLV
+	jr	ra;	nop			# 005 *
+	jr	ra;	srlv	t0, v0, v1	# 006 SRLV
+	jr	ra;	srav	t0, v0, v1	# 007 SRAV
+ 
+	jr	ra;	nop			# 010 JR
+	jr	ra;	nop			# 011 JALR
+	jr	ra;	movz	t0, v0, v1	# 012 MOVZ
+	jr	ra;	movn	t0, v0, v1	# 013 MOVN
+	jr	ra;	nop			# 014 SYSCALL
+	jr	ra;	nop			# 015 BREAK
+	jr	ra;	nop			# 016 *
+	jr	ra;	nop			# 017 SYNC
+
+	jr	ra;	mfhi	t0		# 020 MFHI
+	jr	ra;	mthi	v0		# 021 MTHI
+	jr	ra;	mflo	t0		# 022 MFLO
+	jr	ra;	mtlo	v0		# 023 MTLO
+	jr	ra;	dsllv	t0, v0, v1	# 024 DSLLV
+	jr	ra;	nop			# 025 *
+	jr	ra;	dsrlv	t0, v0, v1	# 026 DSRLV
+	jr	ra;	dsrav	t0, v0, v1	# 027 DSRAV
+
+	jr	ra;	mult	v0, v1		# 030 MULT
+	jr	ra;	multu	v0, v1		# 031 MULTU
+	jr	ra;	div	$0, v0, v1	# 032 DIV
+	jr	ra;	divu	$0, v0, v1	# 033 DIVU
+	jr	ra;	dmult	v0, v1		# 034 DMULT
+	jr	ra;	dmultu	v0, v1		# 035 DMULTU
+	jr	ra;	ddiv	$0, v0, v1	# 036 DDIV
+	jr	ra;	ddivu	$0, v0, v1	# 037 DDIVU
+
+	jr	ra;	add	t0, v0, v1	# 040 ADD
+	jr	ra;	addu	t0, v0, v1	# 041 ADDU
+	jr	ra;	sub	t0, v0, v1	# 042 SUB
+	jr	ra;	subu	t0, v0, v1	# 043 SUBU
+	jr	ra;	and	t0, v0, v1	# 044 AND
+	jr	ra;	or	t0, v0, v1	# 045 OR
+	jr	ra;	xor	t0, v0, v1	# 046 XOR
+	jr	ra;	nor	t0, v0, v1	# 047 NOR
+
+	jr	ra;	nop			# 050 *
+	jr	ra;	nop			# 051 *
+	jr	ra;	slt	t0, v0, v1	# 052 SLT
+	jr	ra;	sltu	t0, v0, v1	# 053 SLTU
+	jr	ra;	dadd	t0, v0, v1	# 054 DADD
+	jr	ra;	daddu	t0, v0, v1	# 055 DADDU
+	jr	ra;	dsub	t0, v0, v1	# 056 DSUB
+	jr	ra;	dsubu	t0, v0, v1	# 057 DSUBU
+
+	jr	ra;	tge	v0, v1		# 060 TGE
+	jr	ra;	tgeu	v0, v1		# 061 TGEU
+	jr	ra;	tlt	v0, v1		# 062 TLT
+	jr	ra;	tltu	v0, v1		# 063 TLTU
+	jr	ra;	teq	v0, v1		# 064 TEQ
+	jr	ra;	nop			# 065 *
+	jr	ra;	tne	v0, v1		# 066 TNE
+	jr	ra;	nop			# 067 *
+
+	jr	ra;	dsllv	t0, v0, v1	# 070 DSLL
+	jr	ra;	nop			# 071 *
+	jr	ra;	dsrlv	t0, v0, v1	# 072 DSRL
+	jr	ra;	dsrav	t0, v0, v1	# 073 DSRA
+	jr	ra;	dsllv	t0, v0, v1	# 074 DSLL32
+	jr	ra;	nop			# 075 *
+	jr	ra;	dsrlv	t0, v0, v1	# 076 DSRL32
+	jr	ra;	dsrav	t0, v0, v1	# 077 DSRA32
+	.set pop	
+
+bcemul_special:
+	andi	t0, a0, 0x3f			# get special code
+	sll	t1, t0, 3			# calculate index in specialop
+	sll	t0, PTR_SCALESHIFT
+	PTR_LA	t9, bcemul_special_op(t1)
+	PTR_L	t0, bcemul_specialtbl(t0)
+	j	t0
+
+bcemul_special_3op_prologue:
+	srl	t0, a0, 21-REG_SCALESHIFT	# rs (source1)
+	srl	t1, a0, 16-REG_SCALESHIFT	# rt (source2)
+	srl	t2, a0, 11-REG_SCALESHIFT	# rd (dest)
+	andi	t0, REG_REGMASK
+	andi	t1, REG_REGMASK
+	andi	t2, REG_REGMASK
+	PTR_ADDU t0, a1
+	PTR_ADDU t1, a1
+	PTR_ADDU t2, a1
+	REG_PROLOGUE
+	REG_L	v0, TF_REG_ZERO(t0)		# load source1
+	REG_L	v1, TF_REG_ZERO(t1)		# load source2
+	REG_EPILOGUE
+	j	t9
+
+bcemul_special_2src_prologue:
+	srl	t0, a0, 21-REG_SCALESHIFT	# rs (source1)
+	srl	t1, a0, 16-REG_SCALESHIFT	# rt (source2)
+	andi	t0, REG_REGMASK
+	andi	t1, REG_REGMASK
+	PTR_ADDU t0, a1
+	PTR_ADDU t1, a1
+	REG_PROLOGUE
+	REG_L	v0, TF_REG_ZERO(t0)		# load source1
+	REG_L	v1, TF_REG_ZERO(t1)		# load source2
+	REG_EPILOGUE
+	j	t9
+
+bcemul_special_genshift:
+	srl	t1, a0, 16-REG_SCALESHIFT	# rt (source)
+	srl	t2, a0, 11-REG_SCALESHIFT	# rd (dest)
+	srl	v1, a0, 6			# sa
+	andi	t1, REG_REGMASK
+	andi	t2, REG_REGMASK
+	beqz	t2, bcemul_done			# fast escape for nop variants
+	andi	v1, 0x001F
+#ifndef __mips_o32
+	/*
+	 * Deal with DSLL32, DSRA32, DSRL32 who need 32 added to their
+	 * shift count.
+	 */
+	andi	v0, a0, 077			# focus on special op
+	sltiu	v0, v0, 074			# less than DSLL32?
+	xori	v0, 1				# invert result
+	sll	v0, 5				# shift by 5 (now 0 or 32)
+	addu	v1, v0				# add to shift count
+#endif
+	PTR_ADDU t1, a1
+	PTR_ADDU t2, a1
+	REG_PROLOGUE
+	REG_L	v0, TF_REG_ZERO(t1)		# load source
+	REG_EPILOGUE
+	jal	t9
+	j	bcemul_store_and_done
+
+bcemul_special_sync:
+	b	bcemul_done
+
+bcemul_special_mfhilo:
+	srl	t2, a0, 11-REG_SCALESHIFT	# rd (dest)
+	andi	t2, REG_REGMASK
+	PTR_ADDU t1, a1, TF_REG_MULHI
+	PTR_ADDU t2, a1
+	and	v0, a0, 2			# bit 1: 0=HI 1=LO
+	sll	v0, REG_SCALESHIFT - 1
+#if TF_REG_MULLO < TF_REG_MULHI
+	PTR_SUBU t1, v0
+#else
+	PTR_ADDU t1, v0
+#endif
+	REG_PROLOGUE
+	REG_L	t0, TF_REG_ZERO(t1)		# load source (mullo or mulhi)
+	REG_EPILOGUE
+	b	bcemul_store_and_done
+
+bcemul_special_mthilo:
+	srl	t1, a0, 21-REG_SCALESHIFT	# rs (source)
+	andi	t1, REG_REGMASK
+	PTR_ADDU t1, a1
+	PTR_ADDU t2, a1, TF_REG_MULHI
+	and	v0, a0, 2			# bit 1: 0=HI l=LO
+	sll	v0, REG_SCALESHIFT - 1
+#if TF_REG_MULLO < TF_REG_MULHI
+	PTR_SUBU t2, v0	
+#else
+	PTR_ADDU t2, v0
+#endif
+	REG_PROLOGUE
+	REG_L	t0, TF_REG_ZERO(t1)
+	REG_EPILOGUE
+	b	bcemul_store_and_done
+
+bcemul_special_genmultdiv:
+	bal	bcemul_special_2src_prologue	# grab operands and do it.
+	mflo	v0
+	mfhi	v1
+	REG_PROLOGUE
+	REG_S	v0, TF_REG_MULLO(a1)
+	REG_S	v1, TF_REG_MULHI(a1)
+	REG_EPILOGUE
+	b	bcemul_done
+
+bcemul_special_genadd:
+	bal	bcemul_special_3op_prologue
+	b	bcemul_check_add_overflow
+
+bcemul_special_gensub:
+	bal	bcemul_special_3op_prologue
+
+	/*
+	 * t0 = v0 - v1 which means v0 = t0 + v1
+	 * Now we can the same logic for overflow from addition.
+	 */
+	move	ta0, v0
+	move	ta1, t0
+	move	ta2, v1
+
+	b	bcemul_check_overflow
+
+bcemul_special_genshiftv:
+bcemul_special_gen3op:
+	bal	bcemul_special_3op_prologue
+	#b	bcemul_store_and_done	# fallthrough to bcemul_store_and_done
+
+bcemul_store_and_done:
+	beq	a1, t2, bcemul_done	# don't store to zero
+	REG_PROLOGUE
+	REG_S	t0, TF_REG_ZERO(t2)
+	REG_EPILOGUE
+	#b	bcemul_done		# fallthrough to bcemul_done
+
+bcemul_done:
+/*
+ * Succeeded to emulate instruction with no error
+ * so compute the next PC.
+ */
+	PTR_SUBU sp, CALLFRAME_SIZ
+	REG_S	t3, CALLFRAME_RA(sp)
+	REG_S	s0, CALLFRAME_S0(sp)
+	move	s0, a1			# save trapfame
+
+	/* Fetch previous branch instruction */
+	REG_PROLOGUE
+	REG_L	a0, TF_REG_EPC(s0)
+	REG_EPILOGUE
+	jal	_C_LABEL(ufetch_uint32)
+
+	/* Calculate branch destination */
+	sll	t0, v0, 16
+	sra	t0, t0, 16-2
+	REG_PROLOGUE
+	REG_L	t1, TF_REG_EPC(s0)
+	PTR_ADDU t0, 4
+	PTR_ADDU t1, t0
+	REG_S	t1, TF_REG_EPC(s0)
+	REG_EPILOGUE
+
+	REG_L	ra, CALLFRAME_RA(sp)
+	REG_L	s0, CALLFRAME_S0(sp)
+	PTR_ADDU sp, CALLFRAME_SIZ
+	j	ra
+
+/*
+ * Send SIGILL, SIGFPE.
+ * Args are same as mips_emul_fp.
+ */
+bcemul_sigill:
+	li	t0, 0xFFFFFF00
+	and	a2, a2, t0
+	ori	a2, a2, T_RES_INST << MIPS_CR_EXC_CODE_SHIFT
+	REG_PROLOGUE
+	REG_S	a2, TF_REG_CAUSE(a1)
+	REG_EPILOGUE
+
+	move	ra, t3				# restore ra
+	move	a2, a0				# code = instruction
+	move	a0, MIPS_CURLWP			# get current process
+	li	a1, SIGILL
+	j	_C_LABEL(fpemul_trapsignal)
+
+END(mips_emul_branchdelayslot)

Reply via email to