;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; This file is part of 'M', a MIPS system emulator. ;; ;; ;; ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;; ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;; ;; ;; ;; You do not have, nor can you ever acquire the right to use, copy or ;; ;; distribute this software ; Should you use this software for any purpose, ;; ;; or copy and distribute it to anyone or in any manner, you are breaking ;; ;; the laws of whatever soi-disant jurisdiction, and you promise to ;; ;; continue doing so for the indefinite future. In any case, please ;; ;; always : read and understand any software ; verify any PGP signatures ;; ;; that you use - for any purpose. ;; ;; ;; ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; TODO: 1) Traps in ADD and SUB (gcc 4.8.1 doesn't seem to use. but do exist) ;; 2) Tests!!! ;---------------------------- ; R-Type MIPS Instructions: | ;---------------------------- ;----------------------------------------------------------------------------- section .rodata align GRAIN, db 0x90 _R_Table: A32 _r_sll ; 0x00 : sll (000000????????????????????000000) A32 _bad ; 0x01 : UNDEFINED A32 _r_srl ; 0x02 : srl (000000????????????????????000010) A32 _r_sra ; 0x03 : sra (000000????????????????????000011) A32 _r_sllv ; 0x04 : sllv (000000????????????????????000100) A32 _bad ; 0x05 : UNDEFINED A32 _r_srlv ; 0x06 : srlv (000000????????????????????000110) A32 _r_srav ; 0x07 : srav (000000????????????????????000111) A32 _r_jr ; 0x08 : jr (000000????????????????????001000) A32 _r_jalr ; 0x09 : jalr (000000????????????????????001001) A32 _r_movz ; 0x0a : movz (000000???????????????00000001010) A32 _r_movn ; 0x0b : movn (000000???????????????00000001011) A32 _r_syscall ; 0x0c : syscall (000000????????????????????001100) A32 _bad ; 0x0d : UNDEFINED A32 _bad ; 0x0e : UNDEFINED A32 _r_sync ; 0x0f : sync (000000????????????????????001111) A32 _r_mfhi ; 0x10 : mfhi (000000????????????????????010000) A32 _r_mthi ; 0x11 : mthi (000000????????????????????010001) A32 _r_mflo ; 0x12 : mflo (000000????????????????????010010) A32 _r_mtlo ; 0x13 : mtlo (000000????????????????????010011) A32 _bad ; 0x14 : UNDEFINED A32 _bad ; 0x15 : UNDEFINED A32 _bad ; 0x16 : UNDEFINED A32 _bad ; 0x17 : UNDEFINED A32 _r_mult ; 0x18 : mult (000000????????????????????011000) A32 _r_multu ; 0x19 : multu (000000????????????????????011001) A32 _r_div ; 0x1a : div (000000????????????????????011010) A32 _r_divu ; 0x1b : divu (000000????????????????????011011) A32 _bad ; 0x1c : UNDEFINED A32 _bad ; 0x1d : UNDEFINED A32 _bad ; 0x1e : UNDEFINED A32 _bad ; 0x1f : UNDEFINED A32 _r_add ; 0x20 : add (000000????????????????????100000) A32 _r_addu ; 0x21 : addu (000000????????????????????100001) A32 _r_sub ; 0x22 : sub (000000????????????????????100010) A32 _r_subu ; 0x23 : subu (000000????????????????????100011) A32 _r_and ; 0x24 : and (000000????????????????????100100) A32 _r_or ; 0x25 : or (000000????????????????????100101) A32 _r_xor ; 0x26 : xor (000000????????????????????100110) A32 _r_nor ; 0x27 : nor (000000????????????????????100111) A32 _bad ; 0x28 : UNDEFINED A32 _bad ; 0x29 : UNDEFINED A32 _r_slt ; 0x2a : slt (000000????????????????????101010) A32 _r_sltu ; 0x2b : sltu (000000????????????????????101011) A32 _bad ; 0x2c : UNDEFINED A32 _bad ; 0x2d : UNDEFINED A32 _bad ; 0x2e : UNDEFINED A32 _bad ; 0x2f : UNDEFINED A32 _bad ; 0x30 : UNDEFINED A32 _bad ; 0x31 : UNDEFINED A32 _bad ; 0x32 : UNDEFINED A32 _bad ; 0x33 : UNDEFINED A32 _r_teq ; 0x34 : teq (000000????????????????????110100) A32 _bad ; 0x35 : UNDEFINED A32 _r_tne ; 0x36 : tne (000000????????????????????110110) A32 _bad ; 0x37 : UNDEFINED A32 _bad ; 0x38 : UNDEFINED A32 _bad ; 0x39 : UNDEFINED A32 _bad ; 0x3a : UNDEFINED A32 _bad ; 0x3b : UNDEFINED A32 _bad ; 0x3c : UNDEFINED A32 _bad ; 0x3d : UNDEFINED A32 _bad ; 0x3e : UNDEFINED A32 _bad ; 0x3f : UNDEFINED ;----------------------------------------------------------------------------- section .text ;----------------------------------------------------------------------------- ; SLL -- Shift left logical. ; Shifts a register value left by the shift amount listed in the instruction ; and places the result in a third register. Zeroes are shifted in. ; Operation: $d = $t << h; advance_pc(4); ; Syntax: sll $d, $t, h ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0000 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_sll: RType_D_T_Shamt ; load rS, rT, Shamt Fields mov TMP, R(rT) ; TMP := Regs[rT] shl TMP, cl ; TMP := TMP << CL (Shamt is in ECX) Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SRL -- Shift right logical. ; Shifts a register value right by the shift amount (shamt) and places the ; value in the destination register. Zeroes are shifted in. ; Operation: $d = $t >> h; advance_pc(4); ; Syntax: srl $d, $t, h ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0010 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_srl: RType_D_T_Shamt ; load rS, rT, Shamt Fields mov TMP, R(rT) ; TMP := Regs[rT] shr TMP, cl ; TMP := TMP >> CL (Shamt is in ECX) Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SRA -- Shift right arithmetic. ; Shifts a register value right by the shift amount (shamt) and places the ; value in the destination register. The sign bit is shifted in. ; Operation: $d = $t >> h; advance_pc(4); ; Syntax: sra $d, $t, h ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0011 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_sra: RType_D_T_Shamt ; load rS, rT, Shamt Fields mov TMP, R(rT) ; TMP := Regs[rT] sar TMP, cl ; TMP := TMP >>(sgn) CL (Shamt is in ECX) Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SLLV -- Shift left logical variable. ; Shifts a register value left by the value in a second register and places ; the result in a third register. Zeroes are shifted in. ; Operation: $d = $t << $s; advance_pc(4); ; Syntax: sllv $d, $t, $s ; Encoding: 0000 00ss ssst tttt dddd d--- --00 0100 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_sllv: RType ; load rD, rS, rT Fields mov ecx, R(rS) ; Now CL is the shift amount mov TMP, R(rT) ; TMP := Regs[rT] shl TMP, cl ; TMP := TMP << CL Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SRLV -- Shift right logical variable. ; Shifts a register value right by the amount specified in $s and places the ; value in the destination register. Zeroes are shifted in. ; Operation: $d = $t >> $s; advance_pc(4); ; Syntax: srlv $d, $t, $s ; Encoding: 0000 00ss ssst tttt dddd d000 0000 0110 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_srlv: RType ; load rD, rS, rT Fields mov ecx, R(rS) ; Now CL is the shift amount mov TMP, R(rT) ; TMP := Regs[rT] shr TMP, cl ; TMP := TMP >> CL Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SRAV - Shift Word Right Arithmetic Variable. ; Execute an arithmetic right-shift of a word by a variable number of bits. ; The contents of the low-order 32-bit word of rT are shifted right, ; duplicating the sign-bit (bit 31) in the emptied bits; the word result is ; placed in rD. The bit-shift amount is specified by the low-order 5 bits ; of rS. ; Operation: $d = $t >> $s; advance_pc(4); ; Syntax: srav $d, $t, $s ; Encoding: 0000 00ss ssst tttt dddd d000 0000 0111 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_srav: RType ; load rD, rS, rT Fields mov ecx, R(rS) ; Now CL is the shift amount mov TMP, R(rT) ; TMP := Regs[rT] sar TMP, cl ; TMP := TMP >> CL (extends sign bit) Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; JR -- Jump register. ; Jump to the address contained in register $s ; Operation: PC = nPC; nPC = $s; ; Syntax: jr $s ; Encoding: 0000 00ss sss0 0000 0000 0000 0000 1000 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_jr: RType_S_Only ; Load rS Field mov nPC, R(rS) ; nPC := Regs[rS] Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; JALR - Jump and Link Register. ; Execute a procedure call to an instruction address in a register. ; Place the return address link in rD. The return link is the address of the ; second instruction following the branch, where execution continues after a ; procedure call. Jump to the effective target address in rS. Execute the ; instruction that follows the jump, in the branch delay slot, before ; executing the jump itself. ; Operation: $d = PC + 8; PC = nPC; nPC = $s ; Syntax: jalr $s ; Encoding: 0000 00ss sss0 0000 dddd 0000 0000 1001 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_jalr: RType_S_D_Only ; Load rD and rS Fields mov nPC, R(rS) ; nPC := Regs[rS] mov TMP, PC ; TMP := PC add TMP, 0x8 ; TMP := TMP + 8 Wr_Reg rD, TMP ; Regs[rD] := TMP (result) Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MOVZ - Move Conditional on Zero. ; Conditionally move a register after testing a register value. ; If the value in rT is equal to zero, then the contents of rS are placed ; into rD. ; Operation: if $t = 0 then $d = $s ; Syntax: movz $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0000 1010 ;----------------------------------------------------------------------------- ; TODO: measure if the cmov is actually faster than a branch here ! ; TODO: untested align GRAIN, db 0x90 _r_movz: ; UNDONE_INST RType ; load rD, rS, rT Fields mov TMP, R(rT) ; TMP := Regs[rT] test TMP, TMP ; Set Z flag if TMP = 0 mov TMP, R(rD) ; First, move Regs[rD] to TMP cmovz TMP, R(rS) ; If Z flag set, overwrite with Regs[rS] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MOVN - Move Conditional on Not Zero. ; Conditionally move a register after testing a register value. ; If the value in rT is NOT equal to zero, then the contents of rS are placed ; into rD. ; Operation: if $t != 0 then $d = $s ; Syntax: movn $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0000 1011 ;----------------------------------------------------------------------------- ; TODO: measure if the cmov is actually faster than a branch here ! ; TODO: untested align GRAIN, db 0x90 _r_movn: ; UNDONE_INST RType ; load rD, rS, rT Fields mov TMP, R(rT) ; TMP := Regs[rT] test TMP, TMP ; Set Z flag if TMP = 0 mov TMP, R(rD) ; First, move Regs[rD] to TMP cmovnz TMP, R(rS) ; If Z not set, overwrite with Regs[rS] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SYSCALL -- System call. ; Generates a software interrupt. ; Operation: advance_pc(4); ; Syntax: syscall ; Encoding: 0000 00-- ---- ---- ---- ---- --00 1100 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_syscall: ; no fields SetEXC EXC_SYS ; Set the EXC_SYS Exception jmp _Handle_Exception ; Go straight to exception handler. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SYNC - Synchronize Shared Memory. ; Operation: This is a NOP in this emulator. ; Syntax: sync ; Encoding: 0000 0000 0000 0000 0000 0000 0000 1111 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_sync: jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MFHI -- Move from HI. ; The contents of special register HI are moved to the specified register. ; Operation: $d = $HI; advance_pc(4); ; Syntax: mfhi $d ; Encoding: 0000 0000 0000 0000 dddd d000 0001 0000 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_mfhi: RType_D_Only ; Load rD Field mov TMP, Sr(HI) ; TMP := Sr(HI) Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MTHI - Move to HI Register. ; The contents of rS are loaded to the special register HI. ; Operation: $HI = $s ; Syntax: mthi $s ; Encoding: 0000 00ss sss0 0000 0000 0000 0001 0001 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_mthi: RType_S_Only ; Load rS Field mov TMP, R(rS) ; TMP := Regs[rS] mov Sr(HI), TMP ; HI := TMP jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MFLO -- Move from LO. ; The contents of register LO are moved to the specified register. ; Operation: $d = $LO; advance_pc(4); ; Syntax: mflo $d ; Encoding: 0000 0000 0000 0000 dddd d000 0001 0010 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_mflo: RType_D_Only ; Load rD Field mov TMP, Sr(LO) ; TMP := Sr(LO) Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MTLO - Move to LO. ; The contents of rS are loaded to the special register LO. ; Operation: $LO = $s ; Syntax: mtlo $s ; Encoding: 0000 00ss sss0 0000 0000 0000 0001 0011 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_mtlo: RType_S_Only ; Load rS Field mov TMP, R(rS) ; TMP := Regs[rS] mov Sr(LO), TMP ; LO := TMP jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MULT -- Multiply signed. ; Multiplies $s by $t and stores the result in $HI:$LO. ; Operation: $HI:$LO = $s * $t; advance_pc(4); ; Syntax: mult $s, $t ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1000 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_mult: RType_S_T_Only mov eax, R(rT) ; eax := Regs[rT] imul R(rS) ; edx:eax := Regs[rS] * eax (signed) mov Sr(LO), eax ; LO := Bottom 32 bits of product mov Sr(HI), edx ; HI := Top 32 bits of product jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MULTU -- Multiply unsigned. ; Multiplies $s by $t and stores the result in $HI:$LO. ; Operation: $HI:$LO = $s * $t; advance_pc(4); ; Syntax: multu $s, $t ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1001 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_multu: RType_S_T_Only ; Load rS and rT Fields mov eax, R(rT) ; eax := Regs[rT] mul R(rS) ; edx:eax := Regs[rS] * eax (unsigned) mov Sr(LO), eax ; LO := Bottom 32 bits of product mov Sr(HI), edx ; HI := Top 32 bits of product jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; DIV -- Divide signed. ; Divides $s by $t and stores the quotient in $LO and the remainder in $HI ; Operation: $LO = $s / $t; $HI = $s % $t; advance_pc(4); ; Syntax: div $s, $t ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1010 ;----------------------------------------------------------------------------- ; TODO: detect div0 and other special cases align GRAIN, db 0x90 _r_div: RType_S_T_Only ; Load rS and rT Fields mov eax, R(rS) ; eax := Regs[rS] cdq ; extend sign of eax into edx cmp R(rT), 0 ; test for div0 je _r_div_div0 ; div0 is undefined result idiv R(rT) ; edx:eax / Regs[rT]; edx := r, eax := q mov Sr(LO), eax ; LO := edx:eax /(signed) ecx (quotient) mov Sr(HI), edx ; HI := edx:eax %(signed) ecx (remainder) _r_div_div0: jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; DIVU -- Divide unsigned. ; Divides $s by $t and stores the quotient in $LO and the remainder in $HI ; Operation: $LO = $s / $t; $HI = $s % $t; advance_pc(4); ; Syntax: divu $s, $t ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1011 ;----------------------------------------------------------------------------- ; TODO: detect div0 and other special cases align GRAIN, db 0x90 _r_divu: RType_S_T_Only ; Load rS and rT Fields xor edx, edx ; edx := 0 mov eax, R(rS) ; eax := Regs[rS] cmp R(rT), 0 ; test for div0 je _r_divu_div0 ; div0 is undefined result div R(rT) ; edx:eax / Regs[rT]; edx := r, eax := q mov Sr(LO), eax ; LO := edx:eax / ecx (quotient) mov Sr(HI), edx ; HI := edx:eax % ecx (remainder) _r_divu_div0: jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ADD -- Add (with overflow). ; Adds two registers and stores the result in a register ; Operation: $d = $s + $t; advance_pc(4); ; Syntax: add $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0000 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_add: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] add TMP, R(rT) ; TMP := Regs[rS] + Regs[rT] ; TODO: detect/trap overflow Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ADDU -- Add unsigned (no overflow). ; Adds two registers and stores the result in a register ; Operation: $d = $s + $t; advance_pc(4); ; Syntax: addu $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0001 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_addu: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] add TMP, R(rT) ; TMP := Regs[rS] + Regs[rT] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SUB -- Subtract. ; Subtracts two registers and stores the result in a register ; Operation: $d = $s - $t; advance_pc(4); ; Syntax: sub $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0010 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_sub: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] sub TMP, R(rT) ; TMP := Regs[rS] - Regs[rT] ; TODO: detect and trap overflow Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SUBU -- Subtract unsigned. ; Subtracts two registers and stores the result in a register ; Operation: $d = $s - $t; advance_pc(4); ; Syntax: subu $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0011 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_subu: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] sub TMP, R(rT) ; TMP := Regs[rS] - Regs[rT] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; AND -- Bitwise AND. ; Bitwise ANDs two registers and stores the result in a register ; Operation: $d = $s & $t; advance_pc(4); ; Syntax: and $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0100 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_and: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] and TMP, R(rT) ; TMP := TMP & Regs[rT] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; OR -- Bitwise OR. ; Bitwise logical ORs two registers and stores the result in a register ; Operation: $d = $s | $t; advance_pc(4); ; Syntax: or $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0101 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_or: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] or TMP, R(rT) ; TMP := TMP | Regs[rT] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; XOR -- Bitwise Exclusive OR. ; Exclusive ORs two registers and stores the result in a register ; Operation: $d = $s ^ $t; advance_pc(4); ; Syntax: xor $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d--- --10 0110 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_xor: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] xor TMP, R(rT) ; TMP := TMP ^ Regs[rT] Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; NOR - Not OR. ; Do a bitwise logical NOT OR. ; The contents of rS are combined with the contents of rT in a bitwise logical ; NOR operation. The result is placed into rD. ; Operation: $d = $s NOR $t ; Syntax: nor $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0111 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_nor: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] or TMP, R(rT) ; TMP := TMP | Regs[rT] not TMP ; TMP := ~TMP Wr_Reg rD, TMP ; Regs[rD] := TMP (result) jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SLT -- Set on less than (signed). ; If $s is less than $t, $d is set to one. It gets zero otherwise. ; Operation: if $s < $t $d = 1; advance_pc(4); else $d = 0; advance_pc(4); ; Syntax: slt $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 1010 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_slt: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] cmp TMP, R(rT) ; CMP(TMP, Regs[rT]) ; We do not need rS, so can reuse it here: setl rS_LowByte ; 1 if R(rS) <(signed) R(rT), else 0 and rS, 0x1 ; Only want the bit that we have set Wr_Reg rD, rS ; Regs[rD] := result jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; SLTU -- Set on less than unsigned. ; If $s is less than $t, $d is set to one. It gets zero otherwise. ; Operation: if $s < $t $d = 1; advance_pc(4); else $d = 0; advance_pc(4); ; Syntax: sltu $d, $s, $t ; Encoding: 0000 00ss ssst tttt dddd d000 0010 1011 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_sltu: RType ; load rD, rS, rT Fields mov TMP, R(rS) ; TMP := Regs[rS] cmp TMP, R(rT) ; CMP(TMP, Regs[rT]) ; We do not need rS, so can reuse it here: setb rS_LowByte ; 1 if R(rS) <(signed) R(rT), else 0 and rS, 0x1 ; Only want the bit that we have set Wr_Reg rD, rS ; Regs[rD] := result jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; TEQ - Trap if Equal. ; TODO: document ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_teq: RType_S_T_Only ; Load rS and rT Fields mov TMP, R(rS) ; TMP := Regs[rS] cmp TMP, R(rT) ; CMP(TMP, Regs[rT]) jne _r_teq_neql SetEXC EXC_Tr ; Spring the Trap Exception. jmp _Handle_Exception ; Go straight to exception handler. _r_teq_neql: jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; TNE - Trap if Not Equal. ; Compare registers and do a conditional trap. ; Compare the contents of rS and rT as signed integers; ; if rS is not equal to rT, then take a Trap exception. ; The contents of the code field are ignored by hardware and may be used to ; encode information for system software. To retrieve the information, ; system software must load the instruction word from memory. ; Operation: if $s != $t then Trap ; Syntax: TNE $s, $t ; Encoding: 0000 00ss ssst tttt cccc cccc cc11 0110 ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _r_tne: RType_S_T_Only ; Load rS and rT Fields mov TMP, R(rS) ; TMP := Regs[rS] cmp TMP, R(rT) ; CMP(TMP, Regs[rT]) je _r_tne_eql SetEXC EXC_Tr ; Spring the Trap Exception. jmp _Handle_Exception ; Go straight to exception handler. _r_tne_eql: jmp _end_cycle ;-----------------------------------------------------------------------------