/* This doesn't look like -*- C -*-, but it is!
 *
 * This file was written by Todd Austin, University of Wisconsin - Madison
 * Department of Computer Sciences
 *
 * Copyright (C) 1994, 1995 by Todd Austin
 *
 * This source file is distributed in the hope that it will be useful,
 * but without any warranty.  No author or distributor accepts
 * responsibility to anyone for the consequences of using it or for
 * whether it serves any particular purpose or works at all.
 *
 * Everyone is granted permission to copy, modify and redistribute
 * this source file under the following conditions:
 *
 *    Permission is granted to anyone to make or distribute copies
 *    of this source code, either as received or modified, in any
 *    medium, provided that all copyright notices, permission and
 *    nonwarranty notices are preserved, and that the distributor
 *    grants the recipient permission for further redistribution as
 *    permitted by this document.
 *
 *    Permission is granted to distribute this file in compiled
 *    or executable form under the same conditions applying for
 *    source code, provided that either
 *    A. it is accompanied by the corresponding machine-readable
 *       source code, or
 *    B. it is accompanied by a written offer, with no time limit,
 *       to give anyone a machine-readable copy of the corresponding
 *       source code in return for reimbursement of the cost of
 *       distribution.  This written offer must permit verbatim
 *       duplication by anyone.
 *    C. it is distributed by someone who received only the
 *       executable form, and is accompanied by a copy of the
 *       written offer of source code which s/he received along with it.
 *
 * In other words, you are welcome to use, share and improve this
 * source file.  You are forbidden to forbid anyone else to use, share
 * and improve what you give them.
 *
 * INTERNET: austin@cs.wisc.edu
 * US Mail: 1210 W. Dayton Street, Madison, WI 53706
 *
 * $Id: ss.def,v 1.7 1994/11/21 16:44:08 austin Exp austin $
 */


DEFFU(IntALU,		"fu-int-ALU")
DEFFU(IntMULT,		"fu-int-multiply")
DEFFU(IntDIV,		"fu-int-divide")
DEFFU(FloatADD,		"fu-FP-add/sub")
DEFFU(FloatCMP,		"fu-FP-comparison")
DEFFU(FloatCVT,		"fu-FP-conversion")
DEFFU(FloatMULT,	"fu-FP-multiply")
DEFFU(FloatDIV,		"fu-FP-divide")
DEFFU(FloatSQRT,	"fu-FP-sqrt")
DEFFU(RdPort,		"rd-port")
DEFFU(WrPort,		"wr-port")

DEFINST(NOP,		0x00,
	"nop",		"",
	IntALU,		F_ICOMP,
	LDST,
	SNA, LDST, SNA, LDST,
	SNA, LDST, SNA, LDST, SNA, LDST,
	NA, /* address field */
	/* do nothing */(0))

/*
 * control operations
 */

DEFINST(JUMP,		0x01,
	"j",		"J",
	NA, 		F_CTRL|F_UNCOND|F_UNCONDJMP,
	LDST,
	SNA, LDST, SNA, LDST, 	
        SNA, LDST, SNA, LDST, SNA, LDST,
	((CPC & 036000000000) | (TARG << 2)),
	SET_NPC((CPC & 036000000000) | (TARG << 2)))
DEFINST(JAL,		0x02,
	"jal",		"J",
	IntALU,		F_CTRL|F_UNCOND,
	LDST,
	SET_GPRSRC(31), LDST, SNA, LDST,       
        SNA, LDST, SNA, LDST, SNA, LDST,
        ((CPC & 036000000000) | (TARG << 2)),
	(SET_NPC((CPC & 036000000000) | (TARG << 2)), SET_GPR(31, CPC + 8)))
DEFINST(JR, 		0x03,
	"jr", 		"s", 
	NA, 		F_CTRL|F_UNCOND,
	LDST,
	SNA, LDST, SNA, LDST,
	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	GPR(RS),
	(TALIGN(GPR(RS)), SET_NPC(GPR(RS))))
DEFINST(JALR, 		0x04,
	"jalr", 	"d,s",
	IntALU,		F_CTRL|F_UNCOND,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST, 
	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	GPR(RS),
	(TALIGN(GPR(RS)), SET_GPR(RD, CPC + 8), SET_NPC(GPR(RS))))
DEFINST(BEQ,		0x05,
	"beq",		"s,t,j",
	IntALU,		F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	(CPC + 8 + (OFS << 2)),
	(GPR(RS) == GPR(RT)) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BNE,		0x06,
	"bne",		"s,t,j",
	IntALU,		F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(GPR(RS) != GPR(RT)) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BLEZ,		0x07,
	"blez",		"s,j",
	IntALU,		F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(GPR(RS) <= 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BGTZ,		0x08,
	"bgtz",		"s,j",
	IntALU,		F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(GPR(RS) > 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BLTZ, 		0x09,
	"bltz", 	"s,j", 
	IntALU, 	F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(GPR(RS) < 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BGEZ, 		0x0a,
	"bgez", 	"s,j", 
	IntALU, 	F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(GPR(RS) >= 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BC1F, 		0x0b,
	"bc1f", 	"j", 
	IntALU,		F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
	FCC_SRC, COMP, SNA, LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(!FCC) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)
DEFINST(BC1T, 		0x0c,
	"bc1t", 	"j", 
	IntALU,		F_CTRL|F_COND,
	LDST,
	SNA, LDST, SNA, LDST,
	FCC_SRC, COMP, SNA, LDST, SNA, LDST,
        (CPC + 8 + (OFS << 2)),
	(FCC) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0)

/*
 * load/store operations
 *
 * NOTE: the out-of-order issue simulator(s) require that the
 * address dependencies of loads and stores be contained in input
 * dependency slots 1 and 2, slot 0 is used for the input of
 * the load/store value. the address slot contains the effective address
 * in the case of loads and stores.
 */

DEFINST(LB,		0x20,
	"lb",		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
        (GPR(BS)+OFS),
	SET_GPR(RT, READ_SIGNED_BYTE(GPR(BS)+OFS)))

DEFINST(FLB,		0x21,
	"flb",		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP|F_FLOAD,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
        (GPR(BS)+OFS),
	SET_FPR_L(FT, READ_SIGNED_BYTE(GPR(BS)+OFS)))

DEFINST(LBU, 		0x22, 
	"lbu", 		"t,o(b)",
	RdPort, 	F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
        (GPR(BS)+OFS),
	SET_GPR(RT, READ_UNSIGNED_BYTE(GPR(BS)+OFS)))

DEFINST(FLBU, 		0x23, 
	"flbu",		"t,o(b)",
	RdPort, 	F_MEM|F_LOAD|F_DISP|F_FLOAD,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
        (GPR(BS)+OFS),
	SET_FPR_L(FT, READ_UNSIGNED_BYTE(GPR(BS)+OFS)))

DEFINST(LH, 		0x24,
	"lh",		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
        (GPR(BS)+OFS),
	SET_GPR(RT, READ_SIGNED_HALF(GPR(BS)+OFS)))

DEFINST(FLH, 		0x25,
	"flh",		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP|F_FLOAD,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
        (GPR(BS)+OFS),
	SET_FPR_L(FT, READ_SIGNED_HALF(GPR(BS)+OFS)))

DEFINST(LHU, 		0x26, 
	"lhu", 		"t,o(b)",
	RdPort, 	F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	SET_GPR(RT, READ_UNSIGNED_HALF(GPR(BS)+OFS)))

DEFINST(FLHU, 		0x27, 
	"flhu", 		"t,o(b)",
	RdPort, 	F_MEM|F_LOAD|F_DISP|F_FLOAD,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	SET_FPR_L(FT, READ_UNSIGNED_HALF(GPR(BS)+OFS)))

DEFINST(LW,		0x28,
	"lw", 		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	SET_GPR(RT, READ_WORD(GPR(BS)+OFS)))

DEFINST(LWD,		0x29,
	"lw.d",		"s,Z",
	RdPort,		F_MEM|F_LOAD|F_DIRECT,
	LDST,
	SET_GPRSRC(RT), LDST, SET_GPRSRC((RT)+1), LDST, 
	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	(SET_GPR(RT, READ_WORD(GPR(BS)+OFS)),
         SET_GPR(((RT)+1), READ_WORD(GPR(BS)+OFS+4))))

DEFINST(LWC1, 		0x2a,
	"lwc1", 	"T,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP|F_FLOAD,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	SET_FPR_L(FT, READ_WORD(GPR(BS)+OFS)))

DEFINST(LWC1D, 		0x2b,
	"lwc1.d", 	"S,Z",
	RdPort,		F_MEM|F_LOAD|F_DISP|F_FLOAD,
	LDST,
	SET_FPRLSRC(FT), COMP, SET_FPRLSRC((FT)+1), COMP,
	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	(SET_FPR_L(FT, READ_WORD(GPR(BS)+OFS)),
	 SET_FPR_L(((FT)+1), READ_WORD(GPR(BS)+OFS+4))))

DEFINST(LWL,		0x2c,
	"lwl",		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,	
	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	(temp_bs = GPR(BS),
	 ss_lr_temp = READ_WORD(WL_BASE(temp_bs + OFS)),
	 SET_GPR(RT, ((GPR(RT) & WL_PROT_MASK(temp_bs + OFS)) |
		      (ss_lr_temp & ~WL_PROT_MASK(temp_bs + OFS))))))
DEFINST(LWR,		0x2d,
	"lwr",		"t,o(b)",
	RdPort,		F_MEM|F_LOAD|F_DISP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
	SNA, LDST, GPR_SRC(BS), LDST, SNA, LDST,
	(GPR(BS)+OFS),
	(temp_bs = GPR(BS),
	 ss_lr_temp = READ_WORD(WR_BASE(temp_bs + OFS)),
	 SET_GPR(RT, ((GPR(RT) & WR_PROT_MASK(temp_bs + OFS)) |
		      (ss_lr_temp & ~WR_PROT_MASK(temp_bs + OFS))))))

DEFINST(SB, 		0x30, 
	"sb", 		"t,o(b)",
	WrPort, 	F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(BS), LDST, SNA, LDST, GPR_SRC(RT), LDST,
	(GPR(BS)+OFS),
	WRITE_BYTE(GPR(RT), GPR(BS) + OFS))

DEFINST(FSB, 		0x31, 
	"fsb", 		"t,o(b)",
	WrPort, 	F_MEM|F_STORE|F_DISP|F_FSTORE,
	LDST,
	SNA, LDST, SNA, LDST,
 	FPR_LSRC(FT), COMP, SNA, COMP, GPR_SRC(BS), LDST,
	(GPR(BS)+OFS),
	WRITE_BYTE(FPR_L(FT), GPR(BS) + OFS))

DEFINST(SH, 		0x32, 
	"sh", 		"t,o(b)",
	WrPort, 	F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(BS), LDST, SNA, LDST, GPR_SRC(RT), LDST,
	(GPR(BS)+OFS),
	WRITE_HALF(GPR(RT), GPR(BS) + OFS))

DEFINST(FSH, 		0x33, 
	"fsh", 		"t,o(b)",
	WrPort, 	F_MEM|F_STORE|F_DISP|F_FSTORE,
	LDST,
	SNA, LDST, SNA, LDST,
 	FPR_LSRC(FT), COMP, SNA, COMP, GPR_SRC(BS), LDST,
	(GPR(BS)+OFS),
	WRITE_HALF(FPR_L(FT), GPR(BS) + OFS))

DEFINST(SW, 		0x34, 
	"sw", 		"t,o(b)",
	WrPort, 	F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(BS), LDST, SNA, LDST, GPR_SRC(RT), LDST,
	(GPR(BS)+OFS),
	WRITE_WORD(GPR(RT), GPR(BS) + OFS))

DEFINST(SWD, 		0x35,
	"sw.d",		"s,Z", 
	WrPort,		F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST, 	
	GPR_SRC(BS), LDST, GPR_SRC((RT)+1), LDST, GPR_SRC(RT), LDST,
	(GPR(BS)+OFS),
	(WRITE_WORD(GPR(RT), GPR(BS)+OFS),
         WRITE_WORD(GPR((RT)+1), GPR(BS)+OFS+4)))

DEFINST(SWC1, 		0x36, 
	"swc1", 	"T,o(b)",
	WrPort, 	F_MEM|F_STORE|F_DISP|F_FSTORE,
	LDST,
	SNA, LDST, SNA, LDST,
	FPR_LSRC(FT), COMP, SNA, COMP, GPR_SRC(BS), LDST,
	(GPR(BS)+OFS),
	WRITE_WORD(FPR_L(FT), GPR(BS)+OFS))

DEFINST(SWC1D, 		0x37,
	"swc1.d", 	"S,Z",
	WrPort, 	F_MEM|F_STORE|F_DISP|F_FSTORE,
	LDST,
	SNA, LDST, SNA, LDST,
	FPR_LSRC(FT), COMP, FPR_LSRC((FT)+1), COMP, GPR_SRC(BS), LDST,
	(GPR(BS)+OFS),
	(WRITE_WORD(FPR_L(FT), GPR(BS)+OFS),
         WRITE_WORD(FPR_L((FT)+1), GPR(BS)+OFS+4)))

DEFINST(DSZ,		0x38,
	"dsz",		"o(b)",
	WrPort,		F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST,
        SNA, COMP, SNA, COMP, GPR_SRC(BS), LDST,
	(GPR(BS)+OFS),
	((WRITE_WORD(GPR(0), GPR(BS)+OFS)),
         (WRITE_WORD(GPR(0), GPR(BS)+OFS+4))))

DEFINST(SWL,		0x39,
	"swl",		"t,o(b)",
	WrPort,		F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST,
	GPR_SRC(BS), LDST, SNA, LDST, GPR_SRC(RT), LDST,
	(GPR(BS)+OFS),
	(temp_bs = GPR(BS),
	 ss_lr_temp = READ_WORD(WL_BASE(temp_bs + OFS)),
	 ss_lr_temp = ((GPR(RT) & ~WL_PROT_MASK(temp_bs + OFS)) |
		       (ss_lr_temp & WL_PROT_MASK(temp_bs + OFS))),
	 WRITE_WORD(ss_lr_temp, WL_BASE(temp_bs + OFS))))
DEFINST(SWR,		0x3a,
	"swr",		"t,o(b)",
	WrPort,		F_MEM|F_STORE|F_DISP,
	LDST,
	SNA, LDST, SNA, LDST,
	GPR_SRC(BS), LDST, SNA, LDST, GPR_SRC(RT), LDST,
	(GPR(BS)+OFS),
	(ss_lr_temp = READ_WORD(WR_BASE(GPR(BS)+OFS)),
	 ss_lr_temp = ((GPR(RT) & ~WR_PROT_MASK(GPR(BS)+OFS)) |
		       (ss_lr_temp & WR_PROT_MASK(GPR(BS)+OFS))),
	 WRITE_WORD(ss_lr_temp, WR_BASE(GPR(BS)+OFS))))


/* reg+reg loads and stores */


DEFINST(LB_RR,		0xc0,
	"lb",		"t,(b+d)",
	RdPort,		F_MEM|F_LOAD|F_RR,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(LBU_RR,		0xc1, 
	"lbu", 		"t,(b+d)",
	RdPort, 	F_MEM|F_LOAD|F_RR,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(LH_RR, 		0xc2,
	"lh",		"t,(b+d)",
	RdPort,		F_MEM|F_LOAD|F_RR,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(LHU_RR,		0xc3, 
	"lhu", 		"t,(b+d)",
	RdPort, 	F_MEM|F_LOAD|F_RR,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(LW_RR,		0xc4,
	"lw", 		"t,(b+d)",
	RdPort,		F_MEM|F_LOAD|F_RR,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(LWC1_RR,	0xc5,
	"lwc1", 	"T,(b+d)",
	RdPort,		F_MEM|F_LOAD|F_RR,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))

DEFINST(SB_RR, 		0xc6, 
	"sb", 		"t,(b+d)", 
	WrPort, 	F_MEM|F_STORE|F_RR,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RT), LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(SH_RR, 		0xc7, 
	"sh", 		"t,(b+d)", 
	WrPort, 	F_MEM|F_STORE|F_RR,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RT), LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(SW_RR, 		0xc8, 
	"sw", 		"t,(b+d)", 
	WrPort, 	F_MEM|F_STORE|F_RR,
	LDST,
	SNA, LDST, SNA, LDST,
 	GPR_SRC(RT), LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(SWC1_RR,	0xc9, 
	"swc1", 	"T,(b+d)", 
	WrPort, 	F_MEM|F_STORE|F_RR,
	LDST,
	SNA, LDST, SNA, LDST,		
	FPR_LSRC(FT), COMP, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))


/* reg + reg + 4 addressing mode, used to synthesize `l.d r,(s+t)^++' */

DEFINST(LWC1_RR_R2,	0xca,
	"lwc1.r2", 	"T,(b+d)",
	RdPort,		F_MEM|F_LOAD|F_RR,
	LDST,
	SET_FPRLSRC(FT), COMP, SNA, COMP,
	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(SWC1_RR_R2,	0xcb,
	"swc1.r2", 	"T,(b+d)", 
	WrPort, 	F_MEM|F_STORE|F_RR,
	LDST,
	SNA, LDST, SNA, LDST,
	FPR_LSRC(FT), COMP, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))

DEFINST(LW_RR_R2,	0xcc,
	"lw.r2",	"t,(b+d)",
	RdPort,		F_MEM|F_LOAD|F_RR,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))
DEFINST(SW_RR_R2,	0xcd, 
	"sw.r2", 	"t,(b+d)",
	WrPort, 	F_MEM|F_STORE|F_RR,
	LDST,
	SNA, LDST, SNA, LDST, 	
	GPR_SRC(RT), LDST, GPR_SRC(BS), LDST, GPR_SRC(RD), LDST,
	NA,
	fatal("bad instruction at 0x%08x",regs_PC))

/*
 * Integer ALU operations
 */

DEFINST(ADD, 		0x40,
	"add", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	(OVER(GPR(RS),GPR(RT)), SET_GPR(RD, GPR(RS) + GPR(RT))))
DEFINST(ADDI,		0x41,
	"addi",		"t,s,i",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	(OVER(GPR(RS),IMM), SET_GPR(RT, GPR(RS) + IMM)))
DEFINST(ADDU, 		0x42,
	"addu", 	"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RS) + GPR(RT)))
DEFINST(ADDIU,		0x43,
	"addiu",	"t,s,i",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, GPR(RS) + IMM))

DEFINST(SUB, 		0x44,
	"sub", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	(UNDER(GPR(RS),GPR(RT)), SET_GPR(RD, GPR(RS) - GPR(RT))))
DEFINST(SUBU, 		0x45,
	"subu", 	"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RS) - GPR(RT)))

DEFINST(MULT, 		0x46,
	"mult", 	"s,t", 
	IntMULT, 	F_ICOMP|F_LONGLAT,
	LDST,
	SET_HISRC, LDST, SET_LOSRC, LDST,
    	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	InstMULT(inst))
DEFINST(MULTU, 		0x47,
	"multu", 	"s,t", 
	IntMULT, 	F_ICOMP|F_LONGLAT,
	LDST,
	SET_HISRC, LDST, SET_LOSRC, LDST,
	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	InstMULTU(inst))
DEFINST(DIV, 		0x48,
	"div", 		"s,t", 
	IntDIV, 	F_ICOMP|F_LONGLAT,
	LDST,
	SET_HISRC, LDST, SET_LOSRC, LDST,
	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	(DIV0(GPR(RT)), SET_LO(GPR(RS) / GPR(RT)), SET_HI(GPR(RS) % GPR(RT))))
DEFINST(DIVU, 		0x49,
	"divu", 	"s,t", 
	IntDIV, 	F_ICOMP|F_LONGLAT,
	LDST,
	SET_HISRC, LDST, SET_LOSRC, LDST,
	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	(DIV0(GPR(RT)), SET_LO(((unsigned)GPR(RS)) / ((unsigned)GPR(RT))),
	 SET_HI(((unsigned)GPR(RS)) % ((unsigned)GPR(RT)))))

DEFINST(MFHI, 		0x4a,
	"mfhi", 	"d",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,	
	HI_SRC, LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RD, HI))
DEFINST(MTHI, 		0x4b,
	"mthi", 	"s",
	IntALU, 	F_ICOMP,
	LDST,
	SET_HISRC, LDST, SNA, LDST,
	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_HI(GPR(RS)))
DEFINST(MFLO, 		0x4c,
	"mflo", 	"d", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	LO_SRC, LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RD, LO))
DEFINST(MTLO, 		0x4d,
	"mtlo", 	"s", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_LOSRC, LDST, SNA, LDST,
	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_LO(GPR(RS)))

/* AND conflicts with GNU defs */
DEFINST(AND_, 		0x4e,
	"and", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RS) & GPR(RT)))
DEFINST(ANDI,		0x4f,
	"andi",		"t,s,u",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, GPR(RS) & UIMM))
DEFINST(OR, 		0x50,
	"or", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RS) | GPR(RT)))
DEFINST(ORI, 		0x51,
	"ori",		"t,s,u",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, GPR(RS) | UIMM))
DEFINST(XOR, 		0x52,
	"xor", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,	
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RS) ^ GPR(RT)))
DEFINST(XORI, 		0x53,
	"xori",		"t,s,u",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, GPR(RS) ^ UIMM))
DEFINST(NOR, 		0x54,
	"nor", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, ~(GPR(RS) | GPR(RT))))

DEFINST(SLL, 		0x55,
	"sll", 		"d,t,H", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RT), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RT) << SHAMT))
DEFINST(SLLV, 		0x56,
	"sllv", 	"d,t,s", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,	
	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, GPR(RT) << (GPR(RS) & 037)))
DEFINST(SRL, 		0x57,
	"srl", 		"d,t,H", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RT), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RD, ((unsigned)GPR(RT)) >> SHAMT))
DEFINST(SRLV, 		0x58,
	"srlv", 	"d,t,s", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, ((unsigned)GPR(RT)) >> (GPR(RS) & 037)))
DEFINST(SRA, 		0x59,
	"sra", 		"d,t,H", 
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RT), LDST, SNA, LDST, SNA, LDST,
	NA,
	InstSRA(inst))
DEFINST(SRAV, 		0x5a,
	"srav", 	"d,t,s",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RT), LDST, GPR_SRC(RS), LDST, SNA, LDST,
	NA,
	InstSRAV(inst))

DEFINST(SLT,		0x5b,
	"slt", 		"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, (GPR(RS) < GPR(RT)) ? 1 : 0))
DEFINST(SLTI, 		0x5c,
	"slti",		"t,s,i",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, (GPR(RS) < IMM) ? 1 : 0))
DEFINST(SLTU, 		0x5d,
	"sltu", 	"d,s,t",
	IntALU, 	F_ICOMP,
	LDST,
	SET_GPRSRC(RD), LDST, SNA, LDST,
	GPR_SRC(RS), LDST, GPR_SRC(RT), LDST, SNA, LDST,
	NA,
	SET_GPR(RD, (((unsigned)GPR(RS)) < ((unsigned)GPR(RT))) ? 1 : 0))
DEFINST(SLTIU,		0x5e,
	"sltiu",	"t,s,i",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	GPR_SRC(RS), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, ((unsigned)GPR(RS) < (unsigned)IMM) ? 1 : 0))


/*
 * Floating Point ALU operations
 */

DEFINST(FADD_S,		0x70,
	"add.s",	"D,S,T",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP, SNA, COMP,
	NA,
	/* FIXME: check precedences here */
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 SET_FPR_F(FD, FPR_F(FS) + FPR_F(FT))))
DEFINST(FADD_D,		0x71,
	"add.d",	"D,S,T",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	/* FIXME: check precedences here */
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 SET_FPR_D(FD, FPR_D(FS) + FPR_D(FT))))
DEFINST(FSUB_S,		0x72,
	"sub.s",	"D,S,T",
	FloatADD, 	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 SET_FPR_F(FD, FPR_F(FS) - FPR_F(FT))))
DEFINST(FSUB_D,		0x73,
	"sub.d",	"D,S,T",
	FloatADD, 	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 SET_FPR_D(FD, FPR_D(FS) - FPR_D(FT))))
DEFINST(FMUL_S,		0x74,
	"mul.s",	"D,S,T",
	FloatMULT, 	F_FCOMP|F_LONGLAT,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 SET_FPR_F(FD, FPR_F(FS) * FPR_F(FT))))
DEFINST(FMUL_D, 	0x75,
	"mul.d",	"D,S,T",
	FloatMULT, 	F_FCOMP|F_LONGLAT,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 SET_FPR_D(FD, FPR_D(FS) * FPR_D(FT))))
DEFINST(FDIV_S,		0x76,
	"div.s",	"D,S,T",
	FloatDIV,	F_FCOMP|F_LONGLAT,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 (DIV0(FPR_F(FT)), SET_FPR_F(FD, FPR_F(FS) / FPR_F(FT)))))
DEFINST(FDIV_D,		0x77,
	"div.d",	"D,S,T",
	FloatDIV,	F_FCOMP|F_LONGLAT,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
	 (DIV0(FPR_D(FT)), SET_FPR_D(FD, FPR_D(FS) / FPR_D(FT)))))
DEFINST(FABS_S,		0x78,
	"abs.s",	"D,S",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, fabs((double)FPR_F(FS)))))
DEFINST(FABS_D,		0x79,
	"abs.d",	"D,S",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, fabs(FPR_D(FS)))))
DEFINST(FMOV_S,		0x7a,
	"mov.s",	"D,S",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, FPR_F(FS))))
DEFINST(FMOV_D,		0x7b,
	"mov.d",	"D,S",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, FPR_D(FS))))
DEFINST(FNEG_S,		0x7c,
	"neg.s",	"D,S",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, -FPR_F(FS))))
DEFINST(FNEG_D,		0x7d,
	"neg.d",	"D,S",
	FloatADD,	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, -FPR_D(FS))))

DEFINST(CVT_S_D,	0x80, 
	"cvt.s.d", 	"D,S",
	FloatCVT,	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, (float)FPR_D(FS))))
DEFINST(CVT_S_W,	0x81,
	"cvt.s.w", 	"D,S",
	FloatCVT,	F_FCOMP,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_LSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, (float)FPR_L(FS))))
DEFINST(CVT_D_S,	0x82,
	"cvt.d.s",	"D,S",
	FloatCVT,	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, (double)FPR_F(FS))))
DEFINST(CVT_D_W,	0x83,
	"cvt.d.w",	"D,S",
	FloatCVT,	F_FCOMP,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_LSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, (double)FPR_L(FS))))
DEFINST(CVT_W_S,	0x84,
	"cvt.w.s", 	"D,S",
	FloatCVT,	F_FCOMP,
	COMP,
	SET_FPRLSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_L(FD, (long)FPR_F(FS))))
DEFINST(CVT_W_D,	0x85,
	"cvt.w.d", 	"D,S",
	FloatCVT,	F_FCOMP,
	COMP,
	SET_FPRLSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_L(FD, (long)FPR_D(FS))))

DEFINST(C_EQ_S,		0x90,
	"c.eq.s", 	"S,T",
	FloatCMP,	F_FCOMP,
	COMP,
	SET_FCCSRC, COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_F(FS) == FPR_F(FT))))
DEFINST(C_EQ_D,		0x91,
	"c.eq.d", 	"S,T",
	FloatCMP,	F_FCOMP,
	COMP,
	SET_FCCSRC, COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_D(FS) == FPR_D(FT))))
DEFINST(C_LT_S,		0x92,
	"c.lt.s", 	"S,T",
	FloatCMP,	F_FCOMP,
	COMP,
	SET_FCCSRC, COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP,SNA, COMP,
	NA,
	(FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_F(FS) < FPR_F(FT))))
DEFINST(C_LT_D,		0x93,
	"c.lt.d", 	"S,T",
	FloatCMP,	F_FCOMP,
	COMP,
	SET_FCCSRC, COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_D(FS) < FPR_D(FT))))
DEFINST(C_LE_S,		0x94,
	"c.le.s", 	"S,T",
	FloatCMP,	F_FCOMP,
	COMP,
	SET_FCCSRC, COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, FPR_FSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_F(FS) <= FPR_F(FT))))
DEFINST(C_LE_D,		0x95,
	"c.le.d", 	"S,T",
	FloatCMP,	F_FCOMP,
	COMP,
	SET_FCCSRC, COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, FPR_DSRC(FT), COMP, SNA, COMP,
	NA,
	(FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_D(FS) <= FPR_D(FT))))

DEFINST(FSQRT_S,	0x96,
	"sqrt.s",	"D,S",
	FloatSQRT,	F_FCOMP|F_LONGLAT,
	COMP,
	SET_FPRFSRC(FD), COMP, SNA, COMP,
	FPR_FSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, sqrt((double)FPR_F(FS)))))
DEFINST(FSQRT_D,	0x97,
	"sqrt.d",	"D,S",
	FloatSQRT,	F_FCOMP|F_LONGLAT,
	COMP,
	SET_FPRDSRC(FD), COMP, SNA, COMP,
	FPR_DSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	(FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, sqrt(FPR_D(FS)))))


/*
 * miscellaneous
 */

DEFINST(SYSCALL, 	0xa0,
	"syscall", 	"",
	NA, 		F_TRAP,
	LDST,
	SNA, LDST, SNA, LDST,
	SNA, LDST, SNA, LDST, SNA, LDST,
	NA,
	SYSCALL(inst))
DEFINST(BREAK,		0xa1,
	"break",	"B",
	NA,		F_TRAP,
	LDST,
	SNA, LDST, SNA, LDST,
	SNA, LDST, SNA, LDST, SNA, LDST,
	NA,
	/* NOTE: these are decoded speculatively, as they occur in integer
	   divide sequences, however, they should NEVER be executed under
	   non-exception conditions */
	/* abort() */0)
DEFINST(LUI, 		0xa2,
	"lui",		"t,U",
	IntALU,		F_ICOMP,
	LDST,
	SET_GPRSRC(RT), LDST, SNA, LDST,
 	SNA, LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_GPR(RT, UIMM << 16))

DEFINST(MFC1, 		0xa3,
	"mfc1", 	"t,S",
	IntALU, 	F_ICOMP,
	COMP,
	SET_GPRSRC(RT), LDST, SNA, LDST,
	FPR_LSRC(FS), COMP, SNA, COMP, SNA, COMP,
	NA,
	SET_GPR(RT, FPR_L(FS)))
DEFINST(CFC1, 		0xa4,
	"cfc1", 	"t,S",
	IntALU, 	F_ICOMP,
	COMP,
	SNA, COMP, SNA, COMP,		
	SNA, COMP, SNA, COMP, SNA, COMP,
	NA,
	fatal("bad instruction"))
DEFINST(MTC1, 		0xa5,
	"mtc1", 	"t,S",
	IntALU, 	F_ICOMP,
	LDST,
	SET_FPRLSRC(FS), COMP, SNA, COMP,
	GPR_SRC(RT), LDST, SNA, LDST, SNA, LDST,
	NA,
	SET_FPR_L(FS, GPR(RT)))
DEFINST(CTC1, 		0xa6,
	"ctc1", 	"t,S",
	IntALU, 	F_ICOMP,
	LDST,
	SNA, COMP, SNA, COMP,
	SNA, LDST, SNA, LDST, SNA, LDST,
	NA,
	fatal("bad instruction at 0x%08x", regs_PC))

DEFINST(DMFC1,          0xa7,
        "dmfc1",        "t,S",
        IntALU,         F_ICOMP,
	COMP,
        SET_GPRSRC(RT), LDST, SET_GPRSRC((RT)+1), LDST, 
	FPR_LSRC(FS), COMP, FPR_LSRC((FT)+1), COMP, SNA, COMP,
	NA,
	(SET_GPR(RT, FPR_L(FS)), SET_GPR((RT)+1,FPR_L((FS)+1))))

DEFINST(DMTC1,          0xa8,
        "dmtc1",        "t,S",
        IntALU,         F_ICOMP,
	LDST,
        SET_FPRLSRC(FS), COMP, SET_FPRLSRC((FS)+1), COMP, 
	GPR_SRC(RT), LDST, GPR_SRC((RT)+1), LDST, SNA, LDST,
	NA,
	(SET_FPR_L(FS, GPR(RT)), SET_FPR_L((FS)+1, GPR((RT)+1))))

#ifdef IMPL

/* non-expression instruction implementations */
/*
 * rd <- [rt] >> shamt)
 */
static void
InstSRA(SS_INST_TYPE inst)
{
  int i;

  /* Although SRA could be implemented with the >> operator in the
     MIPS machine, there are other machines that perform a logical
     right shift with the >> operator. */
  if (GPR(RT) & 020000000000) {
    SET_GPR(RD, GPR(RT));
    for (i = 0; i < SHAMT; i++) {
      SET_GPR(RD, (GPR(RD) >> 1) | 020000000000);
    }
  }
  else {
    SET_GPR(RD, GPR(RT) >> SHAMT);
  }
}

/*
 * rd <- [rt] >> [5 LSBs of rs])
 */
static void
InstSRAV(SS_INST_TYPE inst)
{
  int i;
  unsigned long shamt = GPR(RS) & 037;

  if (GPR(RT) & 020000000000) {
    SET_GPR(RD, GPR(RT));
    for (i = 0; i < shamt; i++) {
      SET_GPR(RD, (GPR(RD) >> 1) | 020000000000);
    }
  }
  else {
    SET_GPR(RD, GPR(RT) >> shamt);
  }
}

/*
 * HI,LO <- [rs] * [rt]    Integer product of [rs] & [rt] to HI/LO
 */
static void
InstMULT(SS_INST_TYPE inst)
{
  int sign1, sign2;
  long i, op1, op2;

  sign1 = sign2 = 0;
  SET_HI(0);
  SET_LO(0);
  op1 = GPR(RS);
  op2 = GPR(RT);

  /* For multiplication, treat -ve numbers as +ve numbers by
     converting 2's complement -ve numbers to ordinary notation */
  if (op1 & 020000000000) {
    sign1 = 1;
    op1 = (~op1) + 1;
  }
  if (op2 & 020000000000) {
    sign2 = 1;
    op2 = (~op2) + 1;
  }
  if (op1 & 020000000000)
    SET_LO(op2);
  for (i = 0; i < 31; i++) {
    SET_HI(HI << 1);
    SET_HI(HI + extractl(LO, 31, 1));
    SET_LO(LO << 1);
    if ((extractl(op1, 30-i, 1)) == 1) {
      if (((unsigned)037777777777 - (unsigned)LO) < (unsigned)op2) {
	SET_HI(HI + 1);
      }
      SET_LO(LO + op2);
    }
  }

  /* Take 2's complement of the result if the result is negative */
  if (sign1 ^ sign2) {
    SET_LO(~LO);
    SET_HI(~HI);
    if ((unsigned)LO == 037777777777) {
      SET_HI(HI + 1);
    }
    SET_LO(LO + 1);
  }
}

/*
 * HI,LO <- [rs] * [rt]    Integer product of [rs] & [rt] to HI/LO
 */
static void
InstMULTU(SS_INST_TYPE inst)
{
  long i;

  SET_HI(0);
  SET_LO(0);
  if (GPR(RS) & 020000000000)
    SET_LO(GPR(RT));
  for (i = 0; i < 31; i++) {
    SET_HI(HI << 1);
    SET_HI(HI + extractl(LO, 31, 1));
    SET_LO(LO << 1);
    if ((extractl(GPR(RS), 30-i, 1)) == 1) {
      if (((unsigned)037777777777 - (unsigned)LO) < (unsigned)GPR(RT)) {
	SET_HI(HI + 1);
      }
      SET_LO(LO + GPR(RT));
    }
  }
}

#endif IMPL
