############################ # # MIPS32 # Basic and FP (COP1) instructions # # (See bottom of file for MIPS64 instructions included with MIPS32) # ############################ @if defined(ISA_VARIANT) @define AMODE "ISA_MODE=0" # ISA_MODE must restrict MIPS instruction decoding and require ISA_MODE=0 @else @define AMODE "epsilon" # Mips16 instructions not supported - Mips32 only @endif # 0000 00ss ssst tttt dddd d000 0010 0000 :add RD32, RS32src, RT32src is $(AMODE) & prime=0 & sa=0 & fct=0x20 & RD32 & RS32src & RT32src & RD { RD32 = RS32src + RT32src; @ifdef MIPS64 RD = sext(RD32); @endif } # 0010 01ss ssst tttt iiii iiii iiii iiii :addiu RT32, RS32src, simmed is $(AMODE) & prime=9 & RT32 & RS32src & simmed & RT { RT32 = RS32src + simmed; @ifdef MIPS64 RT = sext(RT32); @endif } # 0000 00ss ssst tttt dddd d000 0010 0001 :addu RD32, RS32src, RT32src is $(AMODE) & prime=0 & fct=0x21 & RS32src & RT32src & RD32 & sa=0 & RD { RD32 = RS32src + RT32src; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0010 0100 :and RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x24 & RSsrc & RTsrc & RD & sa=0 { RD = RSsrc & RTsrc; } # 0011 00ss ssst tttt iiii iiii iiii iiii :andi RT, RSsrc, immed is $(AMODE) & prime=0xC & RSsrc & RT & immed { RT = RSsrc & immed; } # 0001 0000 0000 0000 iiii iiii iiii iiii :b Rel16 is $(AMODE) & prime=4 & rs=0 & rt=0 & Rel16 { delayslot(1); goto Rel16; } # 0001 00ss ssst tttt iiii iiii iiii iiii :beq RSsrc, RTsrc, Rel16 is $(AMODE) & prime=4 & RSsrc & RTsrc & Rel16 { delayflag:1 = ( RSsrc == RTsrc ); delayslot( 1 ); if delayflag goto Rel16; } # 0000 01ss sss0 0001 iiii iiii iiii iiii :bgez RSsrc, Rel16 is $(AMODE) & prime=1 & cond=1 & RSsrc & Rel16 { delayflag:1 = ( RSsrc s>= 0 ); delayslot( 1 ); if delayflag goto Rel16; } # 0001 11ss sss0 0000 iiii iiii iiii iiii :bgtz RSsrc, Rel16 is $(AMODE) & prime=7 & cond=0 & RSsrc & Rel16 { delayflag:1 = ( RSsrc s> 0 ); delayslot( 1 ); if delayflag goto Rel16; } # 0001 10ss sss0 0000 iiii iiii iiii iiii :blez RSsrc, Rel16 is $(AMODE) & prime=6 & cond=0 & RSsrc & Rel16 { delayflag:1 = ( RSsrc s<= 0 ); delayslot( 1 ); if delayflag goto Rel16; } # 0000 01ss sss0 0000 iiii iiii iiii iiii :bltz RSsrc, Rel16 is $(AMODE) & prime=1 & cond=0 & RSsrc & Rel16 { delayflag:1 = ( RSsrc s< 0 ); delayslot( 1 ); if delayflag goto Rel16; } # 0001 01ss ssst tttt iiii iiii iiii iiii :bne RSsrc, RTsrc, Rel16 is $(AMODE) & prime=5 & RSsrc & RTsrc & Rel16 { delayflag:1 = ( RSsrc != RTsrc ); delayslot( 1 ); if delayflag goto Rel16; } # 0000 00cc cccc cccc cccc cccc cc00 1101 :break breakcode is $(AMODE) & prime=0 & fct=0xD & breakcode { tmp:4=breakcode; trap(tmp); } # 1011 11bb bbbo oooo iiii iiii iiii iiii :cache op, OFF_BASER6 is $(AMODE) & ((prime=0x2F & REL6=0) | (prime=0x1F & REL6=1 & fct=0x25 & bit6=0)) & OFF_BASER6 & op { cacheOp(op:1, OFF_BASER6); } :cachee op, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x1B & bit6=0 & OFF_BASER6 & op { cacheOp(op:1, OFF_BASER6); } :cfc0 RT, RD0 is $(AMODE) & prime=0x10 & copop=2 & RT & RD0 & bigfunct=0 { RT = sext( RD0:$(SIZETO4) ); } # 0100 1000 010t tttt ssss s000 0000 0000 :cfc2 RT, immed is $(AMODE) & prime=0x12 & copop=2 & RT & immed { tmp:4 = getCopControlWord( 2:1, immed:4 ); RT = sext(tmp); } # Special case of ADDU # 0000 0000 0000 0000 dddd d000 0010 0001 :clear RD is $(AMODE) & prime=0 & fct=0x21 & rs=0 & rt=0 & RD & sa=0 { RD = 0; } define pcodeop special2; # 0111 00ss ssst tttt dddd daaa aaxx xyyy # valid values of x and y: # x: 0 y: 3,6,7 # x: 1 y: 0-7 # x: 2 y: 0-7 # x: 3 y: 0-7 # x: 4 y: 2,3,6,7 # x: 5 y: 0-7 # x: 6 y: 0-7 # x: 7 y: 0-6 :SPECIAL2 RD, RSsrc, RTsrc, sa, fct is $(AMODE) & prime=0x1C & sa & RD & RSsrc & RTsrc & fct { tmp:1 = fct; tmp2:1 = sa; RD = special2(RSsrc, RTsrc, tmp2, tmp); } # 0100 101c cccc cccc cccc cccc cccc cccc :cop2 cofun is $(AMODE) & prime=0x12 & bit25=1 & cofun { arg:4 = cofun; copFunction(2:1, arg); } :ctc0 RTsrc, RD0 is $(AMODE) & prime=0x10 & copop=6 & RTsrc & RD0 & bigfunct=0 { RD0 = RTsrc; } # 0100 1000 110t tttt iiii iiii iiii iiii :ctc2 RTsrc, immed is $(AMODE) & prime=0x12 & copop=6 & RTsrc & immed { setCopControlWord( 2:1, immed:4, RTsrc ); } # 0100 0010 0000 0000 0000 0000 0001 1111 :deret is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x0 & fct=0x1F { return[DEPC]; } # 0100 0001 011t tttt 0110 0000 0000 0000 :di is $(AMODE) & prime=0x10 & mfmc0=0x0B & rd=0x0C & fct2=0x0 & bit5=0x0 & zero3=0x0 & rt=0x0 { Status = Status & -2; # clearing last bit (ffff..fffe == -2 signed) } :di RT is $(AMODE) & prime=0x10 & mfmc0=0x0B & rd=0x0C & fct2=0x0 & bit5=0x0 & zero3=0x0 & RT { RT = Status; Status = Status & -2; # clearing last bit (ffff..fffe == -2 signed) } # 0000 0000 0000 0000 0000 0000 1100 0000 :ehb is $(AMODE) & prime=0x0 & rs=0x0 & rt=0x0 & rd=0x0 & fct2=0x3 & fct=0x0 { } # 0100 0001 011t tttt 0110 0000 0010 0000 :ei is $(AMODE) & prime=0x10 & mfmc0=0x0B & rd=0x0C & fct2=0x0 & bit5=0x01 & zero3=0x0 & rt=0x0 { Status = Status | 1; } :ei RT is $(AMODE) & prime=0x10 & mfmc0=0x0B & rd=0x0C & fct2=0x0 & bit5=0x01 & zero3=0x0 & RT { RT = Status; Status = Status | 1; } # MIPS R3000 and prior only, replaced with ERET in R4000 and later # 0100 0010 0000 0000 0000 0000 0001 0000 :rfe is $(AMODE) & prime=0x10 & fct=0x10 & bit25=1 & copfill=0 { local currentStatus = Status; Status = (currentStatus & 0xfffffff0) | ((currentStatus & 0x3c) >> 2); } # 0100 0010 0000 0000 0000 0000 0001 1000 :eret is $(AMODE) & prime=0x10 & fct=0x18 & bit25=1 & copfill=0 { return[EPC]; } :eretnc is $(AMODE) & prime=0x10 & fct=0x18 & bit25=1 & copfill=1 { return[EPC]; } # 0111 11ss ssst tttt mmmm mLLL LL00 0000 :ext RT, RSsrc, lsb, ExtSize is $(AMODE) & prime=0x1F & fct=0x0 & RT & RSsrc & lsb & msbd & ExtSize { # Extract Bit Field # RT = extractField(RSsrc, msbd:1, lsb:1); # Note that msbd = size - 1 rs_tmp:$(REGSIZE) = RSsrc << ($(REGSIZE) * 8 - (msbd + lsb + 1)); rs_tmp = rs_tmp >> ($(REGSIZE) * 8 - (msbd + 1)); RT = zext(rs_tmp); } # 0111 11ss ssst tttt mmmm mLLL LL00 0100 :ins RT, RSsrc, lsb, InsSize is $(AMODE) & prime=0x1F & fct=0x04 & RT & RTsrc & RSsrc & lsb & msbd & InsSize { tmpa:$(REGSIZE) = -1; tmpa = tmpa >> ($(REGSIZE) * 8 - InsSize); tmpb:$(REGSIZE) = RSsrc & tmpa; tmpa = tmpa << lsb; tmpa = ~tmpa; tmpb = tmpb << lsb; RT = (RT & tmpa) | tmpb; } # 0000 10aa aaaa aaaa aaaa aaaa aaaa aaaa :j Abs26 is $(AMODE) & prime=2 & Abs26 { delayslot( 1 ); goto Abs26; } # 0000 11aa aaaa aaaa aaaa aaaa aaaa aaaa :jal Abs26 is $(AMODE) & prime=3 & Abs26 { ra = inst_next; delayslot( 1 ); call Abs26; } @ifdef ISA_VARIANT # 0000 00ss sss0 0000 dddd dhhh hh00 1001 :jalr RD, RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & RD { build RD; build RSsrc; JXWritePC(RSsrc); RD = inst_next; delayslot( 1 ); call [pc]; } :jalr RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & rd=0x1F { build RSsrc; JXWritePC(RSsrc); ra = inst_next; delayslot( 1 ); call [pc]; } @else # 0000 00ss sss0 0000 dddd dhhh hh00 1001 :jalr RD, RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & RD { RD = inst_next; delayslot( 1 ); tmp:$(ADDRSIZE) = 0; ValCast(tmp,RSsrc); call [tmp]; } :jalr RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & rd=0x1F { ra = inst_next; delayslot( 1 ); tmp:$(ADDRSIZE) = 0; ValCast(tmp,RSsrc); call [tmp]; } @endif @ifdef ISA_VARIANT # 0000 00ss sss0 0000 dddd d1hh hh00 1001 :jalr.hb RD, RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & RD & bit10=1 { build RD; build RSsrc; JXWritePC(RSsrc); RD = inst_next; delayslot( 1 ); call [pc]; } :jalr.hb RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & rd=0x1F & bit10=1 { build RSsrc; JXWritePC(RSsrc); ra = inst_next; delayslot( 1 ); call [pc]; } @else # 0000 00ss sss0 0000 dddd d1hh hh00 1001 :jalr.hb RD, RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & RD & bit10=1 { RD = inst_next; delayslot( 1 ); tmp:$(ADDRSIZE) = 0; ValCast(tmp,RSsrc); call [tmp]; } :jalr.hb RSsrc is $(AMODE) & prime=0 & fct=9 & RSsrc & rt=0 & rd=0x1F & bit10=1 { ra = inst_next; delayslot( 1 ); tmp:$(ADDRSIZE) = 0; ValCast(tmp,RSsrc); call [tmp]; } @endif @ifdef ISA_VARIANT # 0000 00ss sss0 0000 0000 0hhh hh00 1000 :jr RSsrc is $(AMODE) & prime=0 & ((REL6=0 & fct=8) | (REL6=1 & fct=0x09)) & RSsrc & rt=0 & rd=0 { build RSsrc; JXWritePC(RSsrc); delayslot(1); goto [pc]; } @else # 0000 00ss sss0 0000 0000 0hhh hh00 1000 :jr RSsrc is $(AMODE) & prime=0 & ((REL6=0 & fct=8) | (REL6=1 & fct=0x09)) & RSsrc & rt=0 & rd=0 { delayslot(1); tmp:$(ADDRSIZE) = 0; ValCast(tmp,RSsrc); goto [tmp]; } @endif @ifdef ISA_VARIANT # 0000 00ss sss0 0000 0000 01hh hh00 1000 :jr.hb RSsrc is $(AMODE) & prime=0 & ((REL6=0 & fct=8) | (REL6=1 & fct=0x09)) & RSsrc & rt=0 & rd=0 & bit10=1 { build RSsrc; JXWritePC(RSsrc); delayslot(1); goto [pc]; } @else # 0000 00ss sss0 0000 0000 01hh hh00 1000 :jr.hb RSsrc is $(AMODE) & prime=0 & ((REL6=0 & fct=8) | (REL6=1 & fct=0x09)) & RSsrc & rt=0 & rd=0 & bit10=1 { delayslot(1); tmp:$(ADDRSIZE) = 0; ValCast(tmp,RSsrc); goto [tmp]; } @endif # Special case of JR # 0000 0011 1110 0000 0000 0hhh hh00 1000 @ifdef ISA_VARIANT :jr ra is $(AMODE) & prime=0 & ((REL6=0 & fct=8) | (REL6=1 & fct=0x09)) & rs=0x1F & ra & rt=0 & rd=0 & sa=0 { JXWritePC(ra); delayslot(1); return[pc]; } @else :jr ra is $(AMODE) & prime=0 & ((REL6=0 & fct=8) | (REL6=1 & fct=0x09)) & rs=0x1F & ra & rt=0 & rd=0 & sa=0 { delayslot(1); return[ra]; } @endif # 1000 00bb bbbt tttt iiii iiii iiii iiii :lb RT, OFF_BASE is $(AMODE) & prime=0x20 & OFF_BASE & RT { RT = sext(*[ram]:1 OFF_BASE); } :lbe RT, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x2C & bit6=0 & OFF_BASER6 & RT { RT = sext(*[ram]:1 OFF_BASER6); } # 1001 00bb bbbt tttt iiii iiii iiii iiii :lbu RT, OFF_BASE is $(AMODE) & prime=0x24 & OFF_BASE & RT { RT = zext( *[ram]:1 OFF_BASE ); } :lbue RT, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x28 & bit6=0 & OFF_BASER6 & RT { RT = zext( *[ram]:1 OFF_BASER6 ); } # 1000 01bb bbbt tttt iiii iiii iiii iiii :lh RT, OFF_BASE is $(AMODE) & prime=0x21 & OFF_BASE & RT { RT = sext( *[ram]:2 OFF_BASE ); } :lhe RT, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x2D & bit6=0 & OFF_BASER6 & RT { RT = sext( *[ram]:2 OFF_BASER6 ); } # 1001 01bb bbbt tttt iiii iiii iiii iiii :lhu RT, OFF_BASE is $(AMODE) & prime=0x25 & OFF_BASE & RT { RT = zext( *[ram]:2 OFF_BASE ); } :lhue RT, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x29 & bit6=0 & OFF_BASER6 & RT { RT = zext( *[ram]:2 OFF_BASER6 ); } :lle RT, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x2E & bit6=0 & OFF_BASER6 & RT { RT = sext(*[ram]:4 OFF_BASER6); } # 1000 11bb bbbt tttt iiii iiii iiii iiii :lw RT, OFF_BASE is $(AMODE) & prime=0x23 & OFF_BASE & RT { RT = sext( *[ram]:4 OFF_BASE ); } :lwe RT, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x2F & bit6=0 & OFF_BASER6 & RT { RT = sext( *[ram]:4 OFF_BASER6 ); } :lbx RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=22 & INDEX_BASE { RD = sext(*[ram]:1 INDEX_BASE); } :lhux RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=20 & INDEX_BASE { RD = zext(*[ram]:2 INDEX_BASE); } @ifdef MIPS64 :lwux RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=16 & INDEX_BASE { RD = zext(*[ram]:4 INDEX_BASE); } @endif # 0100 0000 000t tttt dddd d000 0000 0sss :mfc0 RT, RD0 is $(AMODE) & prime=0x10 & copop=0 & RT & RD0 & zero6=0 { RT = sext( RD0:$(SIZETO4) ); } # 0100 1000 000t tttt iiii iiii iiii iiii :mfc2 RT, immed is $(AMODE) & prime=0x12 & copop=0 & RT & immed { tmp:$(REGSIZE) = getCopReg(2:1, immed:4); RT = sext( tmp ); } # 0100 1000 011t tttt iiii iiii iiii iiii :mfhc2 RT, immed is $(AMODE) & prime=0x12 & copop=3 & RT & fs & immed { tmp:$(REGSIZE) = getCopReg(2:1, immed:4); RT = sext(tmp >> 32); } # Special case of ADDIU # 0010 0100 000t tttt iiii iiii iiii iiii :li RT, simmed is $(AMODE) & prime=9 & rs=0 & RT & simmed { RT = simmed; } # Special case of ADDU # 0000 0000 000t tttt dddd d000 0010 0001 :move RD, RTsrc is $(AMODE) & prime=0 & fct=0x21 & rs=0 & RD & RTsrc & sa=0 { RD = RTsrc; } # Special case of ADDU # 0000 00ss sss0 0000 dddd d000 0010 0001 :move RD, RSsrc is $(AMODE) & prime=0 & fct=0x21 & RSsrc & rt=0 & RD & sa=0 { RD = RSsrc; } # 0100 0000 100t tttt dddd d000 0000 0sss :mtc0 RTsrc, RD0, sel is $(AMODE) & prime=0x10 & copop=4 & RTsrc & RD0 & zero6=0 & sel { setCopReg(0:1, RD0, RTsrc, sel:1); } # 0100 1000 100t tttt iiii iiii iiii iiii :mtc2 RTsrc, immed is $(AMODE) & prime=0x12 & copop=4 & RTsrc & immed { setCopReg(2:1, immed:4, RTsrc); } :mthc0 RTsrc, RD0, sel is $(AMODE) & prime=0x10 & copop=6 & RTsrc & RD0 & zero6=0 & sel { setCopReg(0:1, RD0, RTsrc, sel:1); } # 0100 1000 111t tttt iiii iiii iiii iiii :mthc2 RTsrc, immed is $(AMODE) & prime=0x12 & copop=0x07 & RTsrc & immed { arg:4 = immed; tmp:4 = RTsrc:$(SIZETO4); low:4 = getCopReg(2:1, arg); val:8 = (zext(tmp) << 32) + zext(low); setCopReg(2:1, arg, val); } :nal is $(AMODE) & REL6=0 & prime=1 & cond=0x10 & zero21=0 { delayslot(1); ra = inst_next; } # 0000 0000 0000 0000 0000 0000 0000 0000 :nop is $(AMODE) & prime=0 & rs=0 & rt=0 & rd=0 & sa=0 & fct=0 { } # 0000 00ss ssst tttt dddd d000 0010 0111 :nor RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x27 & RSsrc & RTsrc & RD & sa=0 { RD = ~(RSsrc | RTsrc); } # 0000 00ss ssst tttt dddd d000 0010 0101 :or RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x25 & RSsrc & RTsrc & RD & sa=0 { RD = RSsrc | RTsrc; } # 0011 01ss ssst tttt iiii iiii iiii iiii :ori RT, RSsrc, immed is $(AMODE) & prime=0xD & RSsrc & RT & immed { RT = RSsrc | immed; } :pause is $(AMODE) & prime=0 & szero=0 & fct=0 & fct2=0x05 { wait(); } :pref hint, OFF_BASE is $(AMODE) & prime=0x33 & hint & OFF_BASE { prefetch(OFF_BASE, hint:1); } :prefe hint, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x23 & bit6=0 & OFF_BASER6 & hint { prefetch(OFF_BASER6, hint:1); } # 0111 1100 000t tttt dddd d000 0011 1011 :rdhwr RT, rd_hw is $(AMODE) & prime=0x1F & rs=0 & fct2=0 & fct=0x3B & RT & rd_hw & rd!=4 { RT = getHWRegister(rd_hw); } # 0111 1100 000t tttt dddd d000 0011 1011 :rdhwr RT, rd_hw, sel_0608 is $(AMODE) & REL6=1 & prime=0x1F & rs=0 & spec2=0 & fct=0x3B & RT & rd_hw & rd=4 & sel_0608 { RT = getHWRegister(rd_hw, sel_0608:1); } # 0100 0001 010t tttt dddd d000 0000 0000 :rdpgpr RD, RT is $(AMODE) & prime=0x10 & rs=10 & bigfunct=0 & RD & RT { RD = getShadow(RT); } # 0000 0000 001t tttt dddd daaa aa00 0010 :rotr RD32, RT32src, sa is $(AMODE) & prime=0 & zero1=0 & bit21=1 & fct=2 & RD32 & RT32src & sa & RD { tmp1:4 = RT32src >> sa; tmp2:4 = RT32src << (32 - sa); RD32 = tmp1 + tmp2; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0100 0110 :rotrv RD32, RT32src, RS32src is $(AMODE) & prime=0 & zero2=0 & bit6=1 & fct=6 & RD32 & RT32src & RS32src & RD { shift:4 = RS32src & 0x1f; tmp1:4 = RT32src >> shift; tmp2:4 = RT32src << (32 - shift); RD32 = tmp1 + tmp2; @ifdef MIPS64 RD = sext(RD32); @endif } # 1010 00bb bbbt tttt iiii iiii iiii iiii :sb RTsrc, OFF_BASE is $(AMODE) & prime=0x28 & OFF_BASE & RTsrc { *[ram]:1 OFF_BASE = RTsrc:1; } :sbe RTsrc, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x1C & bit6=0 & OFF_BASER6 & RTsrc { *[ram]:1 OFF_BASER6 = RTsrc:1; } :sce RTsrc, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x1E & bit6=0 & OFF_BASER6 & RTsrc { *[ram]:4 OFF_BASER6 = RTsrc:$(SIZETO4); RTsrc = 1; } # 0111 00cc cccc cccc cccc cccc cc11 1111 :sdbbp breakcode is $(AMODE) & prime=0x1C & fct=0x3F & breakcode { signalDebugBreakpointException(); } @ifndef COPR_C # 1111 10bb bbbt tttt iiii iiii iiii iiii :sdc2 RTsrc, OFF_BASE is $(AMODE) & prime=0x3E & OFF_BASE & RTsrc { *[ram]:8 OFF_BASE = getCopReg(2:1, RTsrc); } @endif # 0111 1100 000t tttt dddd d100 0010 0000 :seb RD, RTsrc is $(AMODE) & prime=0x1F & rs=0 & fct2=0x10 & fct=0x20 & RD & RTsrc { RD = sext( RTsrc:1 ); } # 0111 1100 000t tttt dddd d110 0010 0000 :seh RD, RTsrc is $(AMODE) & prime=0x1F & rs=0 & fct2=0x18 & fct=0x20 & RD & RTsrc { RD = sext( RTsrc:2 ); } # 1010 01bb bbbt tttt iiii iiii iiii iiii :sh RTsrc, OFF_BASE is $(AMODE) & prime=0x29 & OFF_BASE & RTsrc { *[ram]:2 OFF_BASE = RTsrc:2; } :she RTsrc, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x1D & bit6=0 & OFF_BASER6 & RTsrc { *[ram]:2 OFF_BASER6 = RTsrc:2; } # 0000 0000 000t tttt dddd daaa aa00 0000 :sll RD32, RT32src, sa is $(AMODE) & prime=0 & fct=0 & rs=0 & RD32 & RT32src & sa & RD { RD32 = RT32src << sa; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0000 0100 :sllv RD32, RT32src, RS32src is $(AMODE) & prime=0 & fct=4 & RS32src & RT32src & RD32 & sa=0 & RD { shift:4 = RS32src & 0x1f; RD32 = RT32src << shift; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0010 1010 :slt RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x2A & RSsrc & RTsrc & RD & sa=0 { RD = zext( RSsrc s< RTsrc ); } # 0010 10ss ssst tttt iiii iiii iiii iiii :slti RT, RSsrc, simmed is $(AMODE) & prime=10 & RSsrc & RT & simmed { RT = zext( RSsrc s< simmed ); } # 0010 11ss ssst tttt iiii iiii iiii iiii :sltiu RT, RSsrc, simmed is $(AMODE) & prime=0xB & RSsrc & RT & simmed { RT = zext( RSsrc < simmed ); } # 0000 00ss ssst tttt dddd d000 0010 1011 :sltu RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x2B & RSsrc & RTsrc & RD & sa=0 { RD = zext( RSsrc < RTsrc ); } # 0000 0000 000t tttt dddd daaa aa00 0011 :sra RD32, RT32src, sa is $(AMODE) & prime=0 & fct=3 & rs=0 & RT32src & RD32 & sa & RD { RD32 = RT32src s>> sa; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0000 0111 :srav RD32, RT32src, RS32src is $(AMODE) & prime=0 & fct=7 & RS32src & RT32src & RD32 & sa=0 & RD { shift:4 = RS32src & 0x1f; RD32 = RT32src s>> shift; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 0000 000t tttt dddd daaa aa00 0010 :srl RD32, RT32src, sa is $(AMODE) & prime=0 & fct=2 & rs=0 & RT32src & RD32 & sa & RD { RD32 = RT32src >> sa; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0000 0110 :srlv RD32, RT32src, RS32src is $(AMODE) & prime=0 & fct=6 & RS32src & RT32src & RD32 & sa=0 & RD { shift:4 = RS32src & 0x1f; RD32 = RT32src >> shift; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 0000 0000 0000 0000 0000 0100 0000 :ssnop is $(AMODE) & prime=0 & rs=0 & rt=0 & rd=0 & sa=1 & fct=0 { } # 0000 00ss ssst tttt dddd d000 0010 0010 :sub RD32, RS32src, RT32src is $(AMODE) & prime=0 & fct=0x22 & RS32src & RT32src & RD32 & sa=0 & RD { RD32 = RS32src - RT32src; @ifdef MIPS64 RD = sext(RD32); @endif } # 0000 00ss ssst tttt dddd d000 0010 0011 :subu RD32, RS32src, RT32src is $(AMODE) & prime=0 & fct=0x23 & RS32src & RT32src & RD32 & sa=0 & RD { RD32 = RS32src - RT32src; @ifdef MIPS64 RD = sext(RD32); @endif } # 1010 11bb bbbt tttt iiii iiii iiii iiii :sw RTsrc, OFF_BASE is $(AMODE) & prime=0x2B & OFF_BASE & RTsrc { *[ram]:4 OFF_BASE = RTsrc:$(SIZETO4); } @ifndef COPR_C # 1110 10bb bbbt tttt iiii iiii iiii iiii :swc2 hint, OFF_BASE is $(AMODE) & prime=0x3A & OFF_BASE & hint { tmp:4 = getCopReg(2:1, hint:4); *[ram]:4 OFF_BASE = tmp; } @endif :swe RTsrc, OFF_BASER6 is $(AMODE) & prime=0x1F & fct=0x1F & bit6=0 & OFF_BASER6 & RTsrc { *[ram]:4 OFF_BASER6 = RTsrc:$(SIZETO4); } define pcodeop SYNC; # 0000 0000 0000 0000 0000 0yyy yy00 1111 :sync scalar is $(AMODE) & prime=0 & fct=0xF & szero=0 & stype [ scalar = stype + 0; ] { SYNC(scalar:1); } # 0000 01bb bbb1 1111 iiii iiii iiii iiii :synci OFF_BASE is $(AMODE) & prime=1 & OFF_BASE & synci=0x1F { } # 0000 00cc cccc cccc cccc cccc cc00 1100 :syscall is $(AMODE) & prime=0 & fct=0xC & breakcode { tmp:4=breakcode; syscall(tmp); } # 0000 0000 0000 0000 cccc cccc cc11 0100 # trap always :teq RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x34 & RSsrc & RTsrc & code & rs=0 & rt=0 { tmp:2 = code; local dest:$(ADDRSIZE) = trap(tmp); goto [dest]; } # 0000 00ss ssst tttt cccc cccc cc11 0100 :teq RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x34 & RSsrc & RTsrc & code { if (RSsrc != RTsrc) goto ; tmp:2=code; trap(tmp); } # 0000 00ss ssst tttt cccc cccc cc11 0000 :tge RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x30 & RSsrc & RTsrc & code { if (RSsrc < RTsrc) goto ; tmp:2=code; trap(tmp); } # 0000 00ss ssst tttt cccc cccc cc11 0001 :tgeu RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x31 & RSsrc & RTsrc & code { if (RSsrc < RTsrc) goto ; tmp:2=code; trap(tmp); } :tlbinv is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x00 & fct=0x03 { TLB_invalidate(Index, EntryHi); } :tlbinvf is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x00 & fct=0x04 { TLB_invalidate_flush(Index); } :tlbp is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x00 & fct=0x08 { Index = TLB_probe_for_matching_entry(EntryHi); } :tlbr is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x00 & fct=0x01 { EntryHi = TLB_read_indexed_entryHi(Index); EntryLo0 = TLB_read_indexed_entryLo0(Index); EntryLo1 = TLB_read_indexed_entryLo1(Index); PageMask = TLB_read_indexed_entryPageMask(Index); } :tlbwi is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x00 & fct=0x02 { TLB_write_indexed_entry(Index, EntryHi, EntryLo0, EntryLo1, PageMask); } :tlbwr is $(AMODE) & prime=0x10 & bit25=1 & copfill=0x00 & fct=0x06 { TLB_write_random_entry(Random, EntryHi, EntryLo0, EntryLo1, PageMask); } # 0000 00ss ssst tttt cccc cccc cc11 0010 :tlt RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x32 & RSsrc & RTsrc & code { if (RSsrc s>= RTsrc) goto ; tmp:2=code; trap(tmp); } # 0000 00ss ssst tttt cccc cccc cc11 0011 :tltu RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x33 & RSsrc & RTsrc & code { if (RSsrc >= RTsrc) goto ; tmp:2=code; trap(tmp); } # 0000 00ss ssst tttt cccc cccc cc11 0110 :tne RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x36 & RSsrc & RTsrc & code { if (RSsrc == RTsrc) goto ; tmp:2=code; trap(tmp); } # 0100 001c cccc cccc cccc cccc cc10 0000 :wait is $(AMODE) & prime=0x10 & fct=0x20 & copfill & bit25=1 { tmp:4 = copfill; wait(tmp); } # 0100 0001 110t tttt dddd d000 0000 0000 :wrpgpr RD, RTsrc is $(AMODE) & prime=0x10 & format=0xE & RTsrc & RD & bigfunct=0 { setShadow(RD, RTsrc); } # 0111 1100 000t tttt dddd d000 1010 0000 :wsbh RD, RTsrc is $(AMODE) & prime=0x1F & format=0 & RTsrc & RD & wsbh=2 & bshfl=0x20 { tmp1:$(REGSIZE) = RTsrc & 0xff; tmp2:$(REGSIZE) = (RTsrc >> 8) & 0xff; tmp3:$(REGSIZE) = (RTsrc >> 16) & 0xff; tmp4:$(REGSIZE) = (RTsrc >> 24) & 0xff; RD = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | (tmp2); } # 0000 00ss ssst tttt dddd d000 0010 0110 :xor RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x26 & RSsrc & RTsrc & RD & sa=0 { RD = RSsrc ^ RTsrc; } # 0011 10ss ssst tttt iiii iiii iiii iiii :xori RT, RSsrc, immed is $(AMODE) & prime=0xE & RSsrc & RT & immed { RT = RSsrc ^ immed; } ############################ # # MIPS64 Instructions to be included with all MIPS32 processors # ############################ ## Allow MIPS 64 instructions below for compilers ## using a 64-bit chip, but really keeping things to 32-bits # Special case of daddu # 0000 00ss ssst tttt dddd d000 0010 1101 :clear RD is $(AMODE) & prime=0 & fct=0x2D & rs=0 & rt=0 & RD & sa=0 { RD = 0; } # 0000 00ss ssst tttt dddd d000 0010 1100 :dadd RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x2C & RSsrc & RTsrc & RD & sa=0 { RD = RSsrc + RTsrc; } # 0110 01ss ssst tttt iiii iiii iiii iiii :daddiu RT, RSsrc, simmed is $(AMODE) & prime=0x19 & RSsrc & RT & simmed { RT = RSsrc + simmed; } # 0000 00ss ssst tttt dddd d000 0010 1101 :daddu RD, RSsrc, RTsrc is $(AMODE) & prime=0 & fct=0x2D & RSsrc & RTsrc & RD & sa=0 { RD = RSsrc + RTsrc; } #### # # Pre-6 semantics # #### # 0010 00ss ssst tttt iiii iiii iiii iiii :addi RT32, RS32src, simmed is $(AMODE) & REL6=0 & prime=8 & RT32 & RS32src & simmed & RT { RT32 = RS32src + simmed; @ifdef MIPS64 RT = sext(RT32); @endif } # 0000 01ss sss1 0001 iiii iiii iiii iiii :bal Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=0x11 & rs=0 & Rel16 { ra = inst_next; delayslot( 1 ); call Rel16; } # Special case PIC :bal Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=0x11 & rs=0 & off16=1 & Rel16 { ra = inst_next; delayslot( 1 ); goto Rel16; } # 0100 1001 000c cc00 iiii iiii iiii iiii :bc2f Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc=0 & nd=0 & tf=0 & Rel16 { tmp:1 = getCopCondition(2:1, 0:1); delayslot(1); if (tmp != 0) goto inst_next; goto Rel16; } :bc2f cc,Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc & nd=0 & tf=0 & Rel16 { tmp:1 = getCopCondition(2:1, cc:1); delayslot(1); if (tmp != 0) goto inst_next; goto Rel16; } # 0100 1001 000c cc10 iiii iiii iiii iiii :bc2fl Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc=0 & nd=1 & tf=0 & Rel16 { tmp:1 = getCopCondition(2:1, 0:1); if (tmp != 0) goto inst_next; delayslot(1); goto Rel16; } :bc2fl cc,Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc & nd=1 & tf=0 & Rel16 { tmp:1 = getCopCondition(2:1, cc:1); if (tmp != 0) goto inst_next; delayslot(1); goto Rel16; } # 0100 1001 000c cc01 iiii iiii iiii iiii :bc2t Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc=0 & nd=0 & tf=1 & Rel16 { tmp:1 = getCopCondition(2:1, 0:1); delayslot(1); if (tmp == 0) goto inst_next; goto Rel16; } :bc2t cc,Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc & nd=0 & tf=1 & Rel16 { tmp:1 = getCopCondition(2:1, cc:1); delayslot(1); if (tmp == 0) goto inst_next; goto Rel16; } # 0100 1001 000c cc11 iiii iiii iiii iiii :bc2tl Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc=0 & nd=1 & tf=1 & Rel16 { tmp:1 = getCopCondition(2:1, 0:1); if (tmp == 0) goto inst_next; delayslot(1); goto Rel16; } :bc2tl cc,Rel16 is $(AMODE) & REL6=0 & prime=0x12 & copop=8 & cc & nd=1 & tf=1 & Rel16 { tmp:1 = getCopCondition(2:1, cc:1); if (tmp == 0) goto inst_next; delayslot(1); goto Rel16; } # 0101 00ss ssst tttt iiii iiii iiii iiii :beql RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=0 & prime=0x14 & RSsrc & RTsrc & Rel16 { if (!(RSsrc==RTsrc)) goto inst_next; delayslot(1); goto Rel16; } :bgezal RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=0x11 & RSsrc & Rel16 { ra = inst_next; delayflag:1 = ( RSsrc s>= 0 ); delayslot( 1 ); if (!delayflag) goto inst_next; call Rel16; } # 0000 01ss sss1 0011 iiii iiii iiii iiii :bgezall RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=0x13 & RSsrc & Rel16 { ra = inst_next; if (!(RSsrc s>= 0)) goto inst_next; delayslot( 1 ); call Rel16; } # 0000 01ss sss0 0011 iiii iiii iiii iiii :bgezl RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=3 & RSsrc & Rel16 { if (!(RSsrc s>= 0)) goto inst_next; delayslot(1); goto Rel16; } # 0101 11ss sss0 0000 iiii iiii iiii iiii :bgtzl RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=0x17 & cond=0 & RSsrc & Rel16 { if (!(RSsrc s> 0)) goto inst_next; delayslot(1); goto Rel16; } # 0101 10ss sss0 0000 iiii iiii iiii iiii :blezl RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=0x16 & cond=0 & RSsrc & Rel16 { if (!(RSsrc s<= 0)) goto inst_next; delayslot(1); goto Rel16; } # 0000 01ss sss1 0000 iiii iiii iiii iiii :bltzal RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=0x10 & RSsrc & Rel16 { ra = inst_next; delayflag:1 = ( RSsrc s< 0 ); delayslot( 1 ); if (!delayflag) goto inst_next; call Rel16; } # 0000 01ss sss1 0010 iiii iiii iiii iiii :bltzall RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=0x12 & RSsrc & Rel16 { ra = inst_next; if (!(RSsrc s< 0)) goto inst_next; delayslot(1); call Rel16; } # 0000 01ss sss0 0010 iiii iiii iiii iiii :bltzl RSsrc, Rel16 is $(AMODE) & REL6=0 & prime=1 & cond=2 & RSsrc & Rel16 { if (!(RSsrc s< 0)) goto inst_next; delayslot(1); goto Rel16; } # 0101 01ss ssst tttt iiii iiii iiii iiii :bnel RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=0 & prime=0x15 & RSsrc & RTsrc & Rel16 { if (!(RSsrc!=RTsrc)) goto inst_next; delayslot(1); goto Rel16; } # 0111 00ss ssst tttt dddd d000 0010 0001 :clo RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x21 & RD & RSsrc { # Count leading ones in a word RD = lzcount( ~RSsrc ); } # 0111 00ss ssst tttt dddd d000 0010 0000 :clz RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x20 & RD & RSsrc { # Count leading zeros in a word RD = lzcount( RSsrc ); } # 0000 00ss ssst tttt 0000 0000 0001 1010 :div RS32src, RT32src is $(AMODE) & REL6=0 & prime=0 & fct=0x1A & RS32src & RT32src & rd=0 & sa=0 { lo = sext(RS32src s/ RT32src); hi = sext(RS32src s% RT32src); } # 0000 00ss ssst tttt 0000 0000 0001 1011 :divu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0 & fct=0x1B & RS32src & RT32src & rd=0 & sa=0 { lo = sext(RS32src / RT32src); hi = sext(RS32src % RT32src); } @ifdef ISA_VARIANT # 0111 01aa aaaa aaaa aaaa aaaa aaaa aaaa :jalx Abs26 is $(AMODE) & REL6=0 & prime=0x1D & Abs26 [ ISA_MODE = 1; globalset(Abs26, ISA_MODE);] { ra = inst_next; delayslot( 1 ); ISAModeSwitch = 1; call Abs26; } @endif @ifndef COPR_C # 1101 10bb bbbt tttt iiii iiii iiii iiii :ldc2 rt, OFF_BASE is $(AMODE) & REL6=0 & prime=0x36 & OFF_BASE & rt { setCopReg(2:1, rt, *[ram]:8 OFF_BASE); } @endif # 1100 00bb bbbt tttt iiii iiii iiii iiii :ll RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x30 & OFF_BASE & RT { RT = sext(*[ram]:4 OFF_BASE); } # 0011 1100 000t tttt iiii iiii iiii iiii :lui RT, immed is $(AMODE) & REL6=0 & prime=0xF & rs=0 & RT & immed { tmp:4 = immed << 16; RT = sext(tmp); } @ifndef COPR_C # 1100 10bb bbbt tttt iiii iiii iiii iiii :lwc2 rt, OFF_BASE is $(AMODE) & REL6=0 & prime=0x32 & OFF_BASE & rt { setCopReg( 2:1, rt, *[ram]:4 OFF_BASE ); } @endif @if ENDIAN == "big" # 1000 10bb bbbt tttt iiii iiii iiii iiii :lwl RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x22 & OFF_BASE & RT & RTsrc { shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff >> ((4-shft) * 8)); valLoad:4 = *(addr) << (shft * 8); RT = sext( valLoad | valOrig ); } # 1001 10bb bbbt tttt iiii iiii iiii iiii :lwr RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x26 & OFF_BASE & RT & RTsrc { shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff << ((shft+1) * 8)); valLoad:4 = *(addr) >> ((3-shft) * 8); RT = sext( valOrig | valLoad ); } :lwle RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x19 & bit6=0 & OFF_BASER6 & RTsrc & RT { shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff >> ((4-shft) * 8)); valLoad:4 = *(addr) << (shft * 8); RT = sext( valLoad | valOrig ); } :lwre RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x1A & bit6=0 & OFF_BASER6 & RTsrc & RT { shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff << ((shft+1) * 8)); valLoad:4 = *(addr) >> ((3-shft) * 8); RT = sext( valOrig | valLoad ); } @else :lwl RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x22 & OFF_BASE & RT & RTsrc { shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff >> ((shft+1)* 8)); valLoad:4 = *(addr) << ((3-shft) * 8); RT = sext( valLoad | valOrig ); } # 1001 10bb bbbt tttt iiii iiii iiii iiii :lwr RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x26 & OFF_BASE & RT & RTsrc { shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff << ((4-shft)* 8)); valLoad:4 = *(addr) >> (shft * 8); RT = sext( valOrig | valLoad ); } :lwle RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x19 & bit6=0 & OFF_BASER6 & RTsrc & RT { shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff >> ((shft+1)* 8)); valLoad:4 = *(addr) << ((3-shft) * 8); RT = sext( valLoad | valOrig ); } :lwre RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x1A & bit6=0 & OFF_BASER6 & RTsrc & RT { shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = RTsrc:$(SIZETO4) & (0xffffffff << ((4-shft)* 8)); valLoad:4 = *(addr) >> (shft * 8); RT = sext( valOrig | valLoad ); } @endif # lwl and lwr almost always come in pairs. # When the analyzer does finds a matching lwl/lwr pair, the pcode is simplified so that # lwl does all the loading while lwr is a no-op @if ENDIAN == "big" :lwl RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x22 & OFF_BASE & RT & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 1; globalset(inst_next, PAIR_INSTRUCTION_FLAG);] { RT = sext( *[ram]:4 OFF_BASE ); } :lwr RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x26 & OFF_BASE & RT & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 0; ] { } @else :lwl RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x22 & OFF_BASE & RT & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 1; globalset(inst_next, PAIR_INSTRUCTION_FLAG);] { } :lwr RT, OFF_BASE is $(AMODE) & REL6=0 & prime=0x26 & OFF_BASE & RT & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 0; ] { RT = sext( *[ram]:4 OFF_BASE ); } @endif # 0111 00ss ssst tttt 000a a000 0000 0000 :madd RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & zero1315=0x0 & fct2=0x0 & fct=0x0 & RS32src & RT32src & ac=0 & achi & aclo { tmp1:8 = sext(RS32src); tmp2:8 = sext(RT32src); prod:8 = tmp1 * tmp2; aclo = aclo & 0xffffffff; # Make sure any upper bits of lo don't contribute to sum sum:8 = (zext(achi) << 32) + zext(aclo) + prod; aclo = sext(sum:4); sum = sum >> 32; achi = sext(sum:4); } # 0111 00ss ssst tttt 000a a000 0000 0001 :maddu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & zero1315=0x0 & fct2=0x0 & fct=0x01 & RS32src & RT32src & ac=0 & achi & aclo { tmp1:8 = zext(RS32src); tmp2:8 = zext(RT32src); prod:8 = tmp1 * tmp2; aclo = aclo & 0xffffffff; # Make sure any upper bits of lo don't contribute to sum sum:8 = (zext(achi) << 32) + zext(aclo) + prod; aclo = sext(sum:4); sum = sum >> 32; achi = sext(sum:4); } # 0000 0000 0aa0 0000 dddd d000 0001 0000 :mfhi RD is $(AMODE) & REL6=0 & prime=0 & fct=0x10 & RD & zero5=0 & zero1620=0 & zero2325=0 & acf=0 & acfhi { RD = acfhi; } # 0000 0000 0aa0 0000 dddd d000 0001 0010 :mflo RD is $(AMODE) & REL6=0 & prime=0 & fct=0x12 & RD & zero5=0 & zero1620=0 & zero2325=0 & acf=0 & acflo { RD = acflo; } # 0000 00ss ssst tttt dddd d000 0000 1011 :movn RD, RSsrc, RTsrc is $(AMODE) & REL6=0 & prime=0 & zero5=0 & fct=0xB & RD & RSsrc & RTsrc { if (RTsrc == 0) goto ; RD = RSsrc; } # 0000 00ss ssst tttt dddd d000 0000 1010 :movz RD, RSsrc, RTsrc is $(AMODE) & REL6=0 & prime=0 & zero5=0 & fct=10 & RD & RSsrc & RTsrc { if (RTsrc != 0) goto ; # We can't use goto inst_next because it fails if we are in a delay slot RD = RSsrc; } # 0111 00ss ssst tttt 000a a000 0000 0100 :msub RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & fct2=0 & fct=0x04 & RS32src & RT32src & zero1315=0 & aclo & achi { tmp1:8 = sext(RS32src); tmp2:8 = sext(RT32src); prod:8 = tmp1 * tmp2; aclo = aclo & 0xffffffff; # Make sure any upper bits of lo don't contribute to sum sum:8 = (zext(achi) << 32) + zext(aclo) - prod; aclo = sext(sum:4); sum = sum >> 32; achi = sext(sum:4); } # 0111 00ss ssst tttt 000a a000 0000 0101 :msubu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & fct2=0 & fct=0x05 & RS32src & RT32src & zero1315=0 & ac=0 & aclo & achi { tmp1:8 = zext(RS32src); tmp2:8 = zext(RT32src); prod:8 = tmp1 * tmp2; aclo = aclo & 0xffffffff; # Make sure any upper bits of lo don't contribute to sum sum:8 = (zext(achi) << 32) + zext(aclo) - prod; aclo = sext(sum:4); sum = sum >> 32; achi = sext(sum:4); } # 0000 00ss sss0 0000 000a a000 0001 0001 :mthi RSsrc is $(AMODE) & REL6=0 & prime=0 & fct=0x11 & RSsrc & zero5=0 & zero1320=0 & ac=0 & achi { achi = RSsrc; } # 0000 00ss sss0 0000 000a a000 0001 0011 :mtlo RSsrc is $(AMODE) & REL6=0 & prime=0 & fct=0x13 & RSsrc & zero5=0 & zero1320=0 & ac=0 & aclo { aclo = RSsrc; } # 0111 00ss ssst tttt dddd d000 0000 0010 :mul RD, RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x02 & RD & RS32src & RT32src { tmp1:8 = sext( RS32src ); tmp2:8 = sext( RT32src ); prod:8 = tmp1 * tmp2; RD = sext( prod:4 ); } # 0000 00ss ssst tttt 000a a000 0001 1000 :mult RS32src, RT32src is $(AMODE) & REL6=0 & prime=0 & fct=0x18 & RS32src & RT32src & zero5=0 & zero1315=0 & aclo & achi { tmp1:8 = sext( RS32src ); tmp2:8 = sext( RT32src ); prod:8 = tmp1 * tmp2; aclo = sext(prod:4); prod = prod >> 32; achi = sext(prod:4); } # 0000 00ss ssst tttt 000a a000 0001 1001 :multu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0 & fct=0x19 & RS32src & RT32src & zero5=0 & zero1315=0 & aclo & achi { tmp1:8 = zext( RS32src ); tmp2:8 = zext( RT32src ); prod:8 = tmp1 * tmp2; aclo = sext(prod:4); prod = prod >> 32; achi = sext(prod:4); } # 0100 0110 110t tttt ssss sddd dd10 1100 :pll.ps fd, fs, ft is $(AMODE) & REL6=0 & prime=0x11 & format=0x16 & fct=0x2C & ft & fs & fd unimpl # 0100 0110 110t tttt ssss sddd dd10 1101 :plu.ps fd, fs, ft is $(AMODE) & REL6=0 & prime=0x11 & format=0x16 & fct=0x2D & ft & fs & fd unimpl #:prefx # 0100 0110 110t tttt ssss sddd dd10 1110 :pul.ps fd, fs, ft is $(AMODE) & REL6=0 & prime=0x11 & format=0x16 & fct=0x2E & fd & fs & ft unimpl # 0100 0110 110t tttt ssss sddd dd10 1111 :puu.ps fd, fs, ft is $(AMODE) & REL6=0 & prime=0x11 & format=0x16 & fct=0x2F & fd & fs & ft unimpl # 1110 00bb bbbt tttt iiii iiii iiii iiii :sc RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x38 & OFF_BASE & RT & RTsrc { *[ram]:4 OFF_BASE = RTsrc:$(SIZETO4); RT = 1; } @if ENDIAN == "big" # 1010 10bb bbbt tttt iiii iiii iiii iiii :swl RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2A & OFF_BASE & RTsrc { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = *(addr) & (0xffffffff << ((4-shft) * 8)); valStore:4 = tmpRT >> (shft * 8); *(addr) = valOrig | valStore; } # 1011 10bb bbbt tttt iiii iiii iiii iiii :swr RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2E & OFF_BASE & RTsrc { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = *(addr) & (0xffffffff >> ((shft+1) * 8)); valStore:4 = tmpRT << ((3-shft)*8); *(addr) = valOrig | valStore; } :swle RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x21 & bit6=0 & OFF_BASER6 & RTsrc & RT { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = *(addr) & (0xffffffff << ((4-shft) * 8)); valStore:4 = tmpRT >> (shft * 8); *(addr) = valOrig | valStore; } :swre RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x22 & bit6=0 & OFF_BASER6 & RTsrc & RT { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = *(addr) & (0xffffffff >> ((shft+1) * 8)); valStore:4 = tmpRT << ((3-shft)*8); *(addr) = valOrig | valStore; } @else # 1010 10bb bbbt tttt iiii iiii iiii iiii :swl RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2A & OFF_BASE & RTsrc { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = *(addr) & (0xffffffff << ((shft+1) * 8)); valStore:4 = tmpRT >> ((3-shft) * 8); *(addr) = valOrig | valStore; } # 1011 10bb bbbt tttt iiii iiii iiii iiii :swr RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2E & OFF_BASE & RTsrc { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASE & 0x3; addr:$(ADDRSIZE) = OFF_BASE - shft; valOrig:4 = *(addr) & (0xffffffff >> ((4-shft) * 8)); valStore:4 = tmpRT << (shft*8); *(addr) = valOrig | valStore; } :swle RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x21 & bit6=0 & OFF_BASER6 & RTsrc & RT { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = *(addr) & (0xffffffff << ((shft+1) * 8)); valStore:4 = tmpRT >> ((3-shft) * 8); *(addr) = valOrig | valStore; } :swre RTsrc, OFF_BASER6 is $(AMODE) & REL6=0 & prime=0x1F & fct=0x22 & bit6=0 & OFF_BASER6 & RTsrc & RT { tmpRT:4 = RTsrc:$(SIZETO4); shft:$(ADDRSIZE) = OFF_BASER6 & 0x3; addr:$(ADDRSIZE) = OFF_BASER6 - shft; valOrig:4 = *(addr) & (0xffffffff >> ((4-shft) * 8)); valStore:4 = tmpRT << (shft*8); *(addr) = valOrig | valStore; } @endif # When the analyzer finds a matching swl/swr pair, the pcode is simplified so that # swl does all the storing while swr is a no-op @if ENDIAN == "big" :swl RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2A & OFF_BASE & RTsrc & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 1; globalset(inst_next, PAIR_INSTRUCTION_FLAG);] { *[ram]:4 OFF_BASE = RTsrc:$(SIZETO4); } :swr RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2E & OFF_BASE & RTsrc & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 0; ]{ } @else :swl RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2A & OFF_BASE & RTsrc & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 1; globalset(inst_next, PAIR_INSTRUCTION_FLAG);] { } :swr RTsrc, OFF_BASE is $(AMODE) & REL6=0 & prime=0x2E & OFF_BASE & RTsrc & PAIR_INSTRUCTION_FLAG=1 [ PAIR_INSTRUCTION_FLAG = 0; ]{ *[ram]:4 OFF_BASE = RTsrc:$(SIZETO4); } @endif # 0000 01ss sss0 1100 iiii iiii iiii iiii :teqi RSsrc, simmed is $(AMODE) & REL6=0 & prime=1 & cond=0xC & RSsrc & simmed { if (RSsrc != simmed) goto ; trap(); } # 0000 01ss sss0 1000 iiii iiii iiii iiii :tgei RSsrc, simmed is $(AMODE) & REL6=0 & prime=1 & cond=8 & RSsrc & simmed { if (RSsrc s< simmed) goto ; trap(); } # 0000 01ss sss0 1001 iiii iiii iiii iiii :tgeiu RSsrc, simmed is $(AMODE) & REL6=0 & prime=1 & cond=9 & RSsrc & simmed { if (RSsrc < simmed) goto ; trap(); } # 0000 01ss sss0 1010 iiii iiii iiii iiii :tlti RSsrc, simmed is $(AMODE) & REL6=0 & prime=1 & cond=10 & RSsrc & simmed { if (RSsrc s>= simmed) goto ; trap(); } # 0000 01ss sss0 1011 iiii iiii iiii iiii :tltiu RSsrc, simmed is $(AMODE) & REL6=0 & prime=1 & cond=0xB & RSsrc & simmed { if (RSsrc >= simmed) goto ; trap(); } # 0000 01ss sss0 1110 iiii iiii iiii iiii :tnei RSsrc, simmed is $(AMODE) & REL6=0 & prime=1 & cond=0xE & RSsrc & simmed { if (RSsrc == simmed) goto ; trap(); } ############################ # # MIPS64 Instructions to be included with all MIPS32 processors # ############################ ## Allow MIPS 64 instructions below for compilers ## using a 64-bit chip, but really keeping things to 32-bits # 0110 00ss ssst tttt iiii iiii iiii iiii :daddi RT, RSsrc, simmed is $(AMODE) & REL6=0 & prime=0x18 & RSsrc & RT & simmed { RT = RSsrc + simmed; } #### # # Release 6 semantics # #### :addiupc RSsrc, S19L2 is $(AMODE) & REL6=1 & prime=0x3B & bitz19=0 & RSsrc & S19L2 { RSsrc = inst_start + sext(S19L2); } :align RD, RS32src, RT32src, bp2 is $(AMODE) & REL6=1 & prime=0x1F & spec3=0x2 & fct=0x20 & bp2 & RS32src & RT32src & RD { tmp:4 = RT32src << (8 * bp2); tmp = tmp | (RS32src >> (32 - (8 * bp2))); RD = sext(tmp); } :aluipc RSsrc, S16L16 is $(AMODE) & REL6=1 & prime=0x3B & op=0x1F & RSsrc & S16L16 { RSsrc = inst_start + sext(S16L16); RSsrc = RSsrc & ~0xFFFF; } :aui RTsrc, RSsrc, S16L16 is $(AMODE) & REL6=1 & prime=0x0F & RSsrc & RTsrc & S16L16 { RTsrc = RSsrc + sext(S16L16); } :auipc RSsrc, S16L16 is $(AMODE) & REL6=1 & prime=0x3B & op=0x1E & RSsrc & S16L16 { RSsrc = inst_start + sext(S16L16); } # 0000 0100 0001 0001 iiii iiii iiii iiii :bal Rel16 is $(AMODE) & REL6=1 & prime=0x01 & cond=0x11 & rs=0 & Rel16 { ra = inst_next; delayslot(1); call Rel16; } :bal Rel16 is $(AMODE) & REL6=1 & prime=0x01 & cond=0x11 & rs=0 & off16=1 & Rel16 { ra = inst_next; delayslot(1); goto Rel16; } :balc Rel26 is $(AMODE) & REL6=1 & prime=0x3A & Rel26 { ra = inst_next; call Rel26; } :bc Rel26 is $(AMODE) & REL6=1 & prime=0x32 & Rel26 { goto Rel26; } :bc2eqz op, Rel16 is $(AMODE) & REL6=1 & prime=0x12 & copop=0x09 & op & Rel16 { tmp:1 = getCopCondition(2:1, op:1); if (tmp == 0) goto inst_next; goto Rel16; } :bc2nez op, Rel16 is $(AMODE) & REL6=1 & prime=0x12 & copop=0x0D & op & Rel16 { tmp:1 = getCopCondition(2:1, op:1); if (tmp != 0) goto inst_next; goto Rel16; } :bad1 is $(AMODE) & REL6=1 & prime=0x06 & rs=0 & rt=0 unimpl :blezalc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x06 & rs=0 & RTsrc & Rel16 { if (RTsrc s> 0) goto inst_next; ra = inst_next; call Rel16; } :bgezalc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x06 & rs=rt & rt!=0 & RTsrc & Rel16 { if (RTsrc s< 0) goto inst_next; ra = inst_next; call Rel16; } :bgeuc RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x06 & rt!=0 & rs!=rt & RSsrc & RTsrc & Rel16 { if (RSsrc >= RTsrc) goto Rel16; } :bad2 is $(AMODE) & REL6=1 & prime=0x07 & rs=0 & rt=0 unimpl :bgtzalc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x07 & rs=0 & RTsrc & Rel16 { if (RTsrc s<= 0) goto inst_next; ra = inst_next; call Rel16; } :bltzalc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x07 & rs=rt & rt!=0 & RTsrc & Rel16 { if (RTsrc s>= 0) goto inst_next; ra = inst_next; call Rel16; } :bltuc RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x07 & rt!=0 & rs!=rt & RSsrc & RTsrc & Rel16 { if (RSsrc < RTsrc) goto Rel16; } :beqzalc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x08 & rs=0 & rt!=0 & RTsrc & Rel16 { if (RTsrc s> 0) goto inst_next; ra = inst_next; call Rel16; } :beqc RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x08 & rs!=0 & rs 0x7FFFFFFF) || (tmpS s< -2147483648); @if REGSIZE == "8" tmpF = tmpF || (RTsrc s> 0x7FFFFFFF) || (RTsrc s< -2147483648) || (RSsrc s> 0x7FFFFFFF) || (RSsrc s< -2147483648); @endif if (tmpF == 1) goto Rel16; } :bnezalc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x18 & rs=0 & rt!=0 & RTsrc & Rel16 { if (RTsrc == 0) goto inst_next; ra = inst_next; call Rel16; } :bnec RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x18 & rs!=0 & rs 0x7FFFFFFF) || (tmpS s< -2147483648); @if REGSIZE == "8" tmpF = tmpF || (RTsrc s> 0x7FFFFFFF) || (RTsrc s< -2147483648) || (RSsrc s> 0x7FFFFFFF) || (RSsrc s< -2147483648); @endif if (tmpF == 0) goto Rel16; } :bad3 is $(AMODE) & REL6=1 & prime=0x16 & rs=0 & rt=0 unimpl :blezc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x16 & rs=0 & rt!=0 & RTsrc & Rel16 { if (RTsrc s<= 0) goto Rel16; } :bgezc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x16 & rs=rt & rt!=0 & RTsrc & Rel16 { if (RTsrc s>= 0) goto Rel16; } :bgec RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x16 & RSsrc & RTsrc & Rel16 { if (RSsrc s>= RTsrc) goto Rel16; } :bad4 is $(AMODE) & REL6=1 & prime=0x17 & rs=0 & rt=0 unimpl :bgtzc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x17 & rs=0 & rt!=0 & RTsrc & Rel16 { if (RTsrc s> 0) goto Rel16; } :bltzc RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x17 & rs=rt & rt!=0 & RTsrc & Rel16 { if (RTsrc s< 0) goto Rel16; } :bltc RSsrc, RTsrc, Rel16 is $(AMODE) & REL6=1 & prime=0x17 & RSsrc & RTsrc & Rel16 { if (RSsrc s< RTsrc) goto Rel16; } # The jic instruction takes care of the 'bad' case here :beqzc RSsrc, Rel21 is $(AMODE) & REL6=1 & prime=0x36 & RSsrc & Rel21 { if (RSsrc == 0) goto Rel21; } # The jialc instruction takes care of the 'bad' case here :bnezc RSsrc, Rel21 is $(AMODE) & REL6=1 & prime=0x3E & RSsrc & Rel21 { if (RSsrc != 0) goto Rel21; } :bitswap RD, RT32src is $(AMODE) & REL6=1 & prime=0x1F & zero21=0 & fct2=0 & bshfl=0x20 & RT32src & RD { tmp:4 = bitSwap(RT32src); RD = sext(tmp); } :clo RD, RSsrc is $(AMODE) & REL6=1 & prime=0x00 & op=0 & sa=0x1 & fct=0x11 & RD & RSsrc { RD = lzcount( ~RSsrc ); } :clz RD, RSsrc is $(AMODE) & REL6=1 & prime=0x00 & op=0 & sa=0x1 & fct=0x10 & RD & RSsrc { RD = lzcount( RSsrc ); } :div RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x1A & fct2=0x02 & RD & RS32src & RT32src { tmp:4 = RS32src s/ RT32src; RD = sext(tmp); } :mod RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x1A & fct2=0x03 & RD & RS32src & RT32src { tmp:4 = RS32src s% RT32src; RD = sext(tmp); } :divu RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x1B & fct2=0x02 & RD & RS32src & RT32src { tmp:4 = RS32src / RT32src; RD = sext(tmp); } :modu RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x1B & fct2=0x03 & RD & RS32src & RT32src { tmp:4 = RS32src % RT32src; RD = sext(tmp); } :dvp RT is $(AMODE) & REL6=1 & prime=0x10 & mfmc0=0x0B & fct=0x24 & RT & RD0 & zero5=0 & zero4=0 { disableProcessor(RT); } :evp RT is $(AMODE) & REL6=1 & prime=0x10 & mfmc0=0x0B & fct=0x04 & RT & RD0 & zero5=0 & zero4=0 { enableProcessor(RT); } # NOTE: Unlike almost every other branch/jump that has an immediate, the immediate is *IS NOT* shifted. This allows # this instruction to serve same function as jalx in pre-6. :jialc RTsrc, simmed is $(AMODE) & REL6=1 & prime=0x3E & jsub=0x00 & RTsrc & simmed { build RTsrc; tmp:$(REGSIZE) = sext(simmed:2) + RTsrc; JXWritePC(tmp); ra = inst_next; call [pc]; } :jic RTsrc, simmed is $(AMODE) & REL6=1 & prime=0x36 & jsub=0x00 & RTsrc & simmed { build RTsrc; tmp:$(REGSIZE) = sext(simmed:2) + RTsrc; JXWritePC(tmp); goto [pc]; } :jic RTsrc, simmed is $(AMODE) & REL6=1 & prime=0x36 & jsub=0x00 & RTsrc & simmed & immed=0x00 & rt=0x1f { build RTsrc; JXWritePC(ra); return [pc]; } @ifndef COPR_C :ldc2 RTsrc, simmed11(baser6) is $(AMODE) & REL6=1 & prime=0x12 & copop=0x0E & simmed11 & baser6 & RTsrc { tmp:$(REGSIZE) = simmed11; tmp = tmp + baser6; tmpa:$(ADDRSIZE) = 0; ValCast(tmpa,tmp); setCopReg(2:1, RTsrc, *[ram]:8 tmpa); } @endif :ll RT, OFF_BASER6 is $(AMODE) & REL6=1 & prime=0x1F & fct=0x36 & bit6=0 & OFF_BASER6 & RT { RT = sext(*[ram]:4 OFF_BASER6); } :llx RT, OFF_BASER6 is $(AMODE) & REL6=1 & prime=0x1F & fct=0x36 & bit6=1 & OFF_BASER6 & RT { RT = sext(*[ram]:4 OFF_BASER6); } :llxe RT, OFF_BASER6 is $(AMODE) & REL6=1 & prime=0x1F & fct=0x27 & bit6=1 & OFF_BASER6 & RT { RT = sext(*[ram]:4 OFF_BASER6); } :lsa RD, RS32src, RT32src, SAV is $(AMODE) & REL6=1 & prime=0x00 & fct=0x05 & spec3=0 & SAV & RD & RS32src & RT32src { tmp:4 = (RS32src << SAV) + RT32src; RD = sext(tmp); } @ifndef COPR_C :lwc2 RTsrc, simmed11(baser6) is $(AMODE) & REL6=1 & prime=0x12 & copop=0x0A & simmed11 & baser6 & RTsrc { tmp:$(REGSIZE) = simmed11; tmp = tmp + baser6; tmpa:$(ADDRSIZE) = 0; ValCast(tmpa,tmp); setCopReg( 2:1, RTsrc, *[ram]:4 tmpa); } @endif :lwpc RS, S19L2 is $(AMODE) & REL6=1 & prime=0x3B & pcrel=0x1 & RS & S19L2 { tmp:$(REGSIZE) = inst_start + sext(S19L2); tmpa:$(ADDRSIZE) = 0; ValCast(tmpa,tmp); RS = sext(*[ram]:4 tmpa); } :mul RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x18 & fct2=0x02 & RD & RS32src & RT32src { tmpS:8 = sext(RS32src); tmpT:8 = sext(RT32src); tmpS = tmpS * tmpT; tmp:4 = tmpS[0,32]; RD = sext(tmp); } :muh RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x18 & fct2=0x03 & RD & RS32src & RT32src { tmpS:8 = sext(RS32src); tmpT:8 = sext(RT32src); tmpS = tmpS * tmpT; tmp:4 = tmpS[32,32]; RD = sext(tmp); } :mulu RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x19 & fct2=0x02 & RD & RS32src & RT32src { tmpS:8 = zext(RS32src); tmpT:8 = zext(RT32src); tmpS = tmpS * tmpT; tmp:4 = tmpS[0,32]; RD = sext(tmp); } :muhu RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x19 & fct2=0x03 & RD & RS32src & RT32src { tmpS:8 = zext(RS32src); tmpT:8 = zext(RT32src); tmpS = tmpS * tmpT; tmp:4 = tmpS[32,32]; RD = sext(tmp); } :scx RTsrc, OFF_BASER6 is $(AMODE) & REL6=1 & prime=0x1F & fct=0x26 & bit6=1 & OFF_BASER6 & RTsrc { *[ram]:4 OFF_BASER6 = RTsrc:$(SIZETO4); } :scxe RTsrc, OFF_BASER6 is $(AMODE) & REL6=1 & prime=0x1F & fct=0x1E & bit6=1 & OFF_BASER6 & RTsrc { *[ram]:4 OFF_BASER6 = RTsrc:$(SIZETO4); RTsrc = 1; } :seleqz RD, RSsrc, RTsrc is $(AMODE) & REL6=1 & prime=0x00 & fct=0x35 & fct2=0x00 & RD & RSsrc & RTsrc { # We use tmp to cover case where rs and rd are the same reg tmps:$(REGSIZE) = RSsrc; tmpt:$(REGSIZE) = RTsrc; RD = 0; if (tmpt != 0) goto ; RD = tmps; } :selnez RD, RSsrc, RTsrc is $(AMODE) & REL6=1 & prime=0x00 & fct=0x37 & fct2=0x00 & RD & RSsrc & RTsrc { # We use tmp to cover case where rs and rd are the same reg tmps:$(REGSIZE) = RSsrc; tmpt:$(REGSIZE) = RTsrc; RD = 0; if (tmpt == 0) goto ; RD = tmps; } :sigrie immed is $(AMODE) & REL6=1 & prime=0x01 & zero21=0 & cond=0x17 & immed { signalReservedInstruction(immed:2); } @include "mipsfloat.sinc"