;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; 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 . ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;----------------------------------------------------------------------------- section .rodata align GRAIN, db 0x90 _B_Table: A32 _b_bltz ; 0x00 : bltz (000001?????00000????????????????) A32 _b_bgez ; 0x01 : bgez (000001?????00001????????????????) A32 _b_bltzl ; 0x02 : bltzl (000001?????00010????????????????) A32 _b_bgezl ; 0x03 : bgezl (000001?????00011????????????????) A32 _bad ; 0x04 : UNDEFINED A32 _bad ; 0x05 : UNDEFINED A32 _bad ; 0x06 : UNDEFINED A32 _bad ; 0x07 : UNDEFINED A32 _bad ; 0x08 : UNDEFINED A32 _bad ; 0x09 : UNDEFINED A32 _bad ; 0x0a : UNDEFINED A32 _bad ; 0x0b : UNDEFINED A32 _bad ; 0x0c : UNDEFINED A32 _bad ; 0x0d : UNDEFINED A32 _bad ; 0x0e : UNDEFINED A32 _bad ; 0x0f : UNDEFINED A32 _b_bltzal ; 0x10 : bltzal (000001????x10000????????????????) A32 _b_bgezal ; 0x11 : bgezal (000001????x10001????????????????) A32 _bad ; 0x12 : UNDEFINED A32 _bad ; 0x13 : UNDEFINED A32 _bad ; 0x14 : UNDEFINED A32 _bad ; 0x15 : UNDEFINED A32 _bad ; 0x16 : UNDEFINED A32 _bad ; 0x17 : UNDEFINED A32 _bad ; 0x18 : UNDEFINED A32 _bad ; 0x19 : UNDEFINED A32 _bad ; 0x1a : UNDEFINED A32 _bad ; 0x1b : UNDEFINED A32 _bad ; 0x1c : UNDEFINED A32 _bad ; 0x1d : UNDEFINED A32 _bad ; 0x1e : UNDEFINED A32 _bad ; 0x1f : UNDEFINED ;----------------------------------------------------------------------------- section .text ;----------------------------------------------------------------------------- ; B-Type Instructions : ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; BLTZ -- Branch on less than zero. ; Branches if the register is less than zero ; Operation: if $s < 0 advance_pc(offset << 2)); else advance_pc(4); ; Syntax: bltz $s, offset ; Encoding: 0000 01ss sss0 0000 iiii iiii iiii iiii ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _b_bltz: IType_I_S_Only ; load rS and Imm Fields mov nPC, PC ; nPC := PC add nPC, 0x4 ; nPC := nPC + 4 SX18_4N Imm ; Sign Extend Imm * 4 mov TMP, 0x4 ; TMP := 4 cmp R(rS), 0 ; If Regs[rS] < 0: cmovl TMP, Imm ; ... then TMP := Imm add nPC, TMP ; nPC := nPC + TMP Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; BGEZ -- Branch on greater than or equal to zero. ; Branches if the register is greater than or equal to zero ; Operation: if $s >= 0 advance_pc(offset << 2)); else advance_pc(4); ; Syntax: bgez $s, offset ; Encoding: 0000 01ss sss0 0001 iiii iiii iiii iiii ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _b_bgez: IType_I_S_Only ; load rS and Imm Fields mov nPC, PC ; nPC := PC add nPC, 0x4 ; nPC := nPC + 4 SX18_4N Imm ; Sign Extend Imm * 4 mov TMP, 0x4 ; TMP := 4 cmp R(rS), 0 ; If Regs[rS] >= 0: cmovge TMP, Imm ; ... then TMP := Imm add nPC, TMP ; nPC := nPC + TMP Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; BLTZL - Branch on Less Than Zero Likely. ; Test a register, then do a PC-relative conditional branch; ; execute the delay slot only if the branch is taken. ; An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is ; added to the address of the instruction following the branch (not the branch ; itself), in the branch delay slot, to form a PC-relative effective target ; address. If the contents of rS are less than zero (sign bit is 1), branch to ; the effective target address after the instruction in the delay slot is ; executed. If the branch is not taken, the instruction in the delay slot is ; not executed. ; Operation: if rS < 0 then PC = PC + sign_extend(offset) ; else: nullify_current_instruction ; Syntax: bltzl $s, offset ; Encoding: 0000 01ss sss0 0010 iiii iiii iiii iiii ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _b_bltzl: IType_S_Only ; load only rS Field just now cmp R(rS), 0 ; CMP(Regs[rS], 0) jnl _i_bltzl_not_taken ; If !(Regs[rS] < 0) then NotTaken ; Taken: IType_I_Only ; load only Imm Field just now SX18_4N Imm ; Sign Extend Imm * 4 mov nPC, PC ; nPC := PC add nPC, 0x4 ; nPC := nPC + 4 add nPC, Imm ; nPC := nPC + Offset Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ; Not Taken: _i_bltzl_not_taken: add PC, 0x4 ; PC := PC + 4 jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; BGEZL - Branch on Greater Than or Equal to Zero Likely. ; Test a register, then do a PC-relative conditional branch; ; execute the delay slot only if the branch is taken. ; An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is ; added to the address of the instruction following the branch (not the branch ; itself), in the branch delay slot, to form a PC-relative effective target ; address. If the contents of rS are greater than or equal to zero ; (sign bit is 0), branch to the effective target address after the ; instruction in the delay slot is executed. If the branch is not taken, the ; instruction in the delay slot is not executed. ; Operation: if rS >= 0 then PC = PC + sign_extend(offset) ; else: nullify_current_instruction ; Syntax: bgezl $s, offset ; Encoding: 0000 01ss sss0 0011 iiii iiii iiii iiii ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _b_bgezl: IType_S_Only ; Load only rS Field just now cmp R(rS), 0 ; CMP(Regs[rS], 0) jnge _i_bgezl_not_taken ; If !(Regs[rS] >= 0) then NotTaken ; Taken: IType_I_Only ; Load only Imm Field just now SX18_4N Imm ; Sign Extend Imm * 4 mov nPC, PC ; nPC := PC add nPC, 0x4 ; nPC := nPC + 4 add nPC, Imm ; nPC := nPC + Offset Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ; Not Taken: _i_bgezl_not_taken: add PC, 0x4 ; PC := PC + 4 jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; BLTZAL -- Branch on less than zero and link. ; Branches if the register is less than zero and saves the return address ; in $31 ; Operation: if $s < 0 $31 = PC + 8 (or nPC + 4); advance_pc(offset << 2)); ; else advance_pc(4); ; Syntax: bltzal $s, offset ; Encoding: 0000 01ss sss1 0000 iiii iiii iiii iiii ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _b_bltzal: IType_I_S_Only ; Load rS and Imm Fields mov nPC, PC ; nPC := PC add nPC, 0x4 ; nPC := nPC + 4 mov TMP, nPC ; TMP := nPC add TMP, 0x4 ; TMP := TMP + 4 mov R(31), TMP ; Regs[31] := TMP SX18_4N Imm ; Sign Extend Imm * 4 mov TMP, 0x4 ; TMP := 4 cmp R(rS), 0 ; If Regs[rS] < 0: cmovl TMP, Imm ; ... then TMP := Imm add nPC, TMP ; nPC := nPC + TMP Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; BGEZAL -- Branch on greater than or equal to zero and link. ; Branches if the register is greater than or equal to zero and saves the ; return address in $31 ; Operation: if $s >= 0 $31 = PC + 8 (or nPC + 4); advance_pc(offset << 2)); ; else advance_pc(4); ; Syntax: bgezal $s, offset ; Encoding: 0000 01ss sss1 0001 iiii iiii iiii iiii ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _b_bgezal: IType_I_S_Only ; Load rS and Imm Fields mov nPC, PC ; nPC := PC add nPC, 0x4 ; nPC := nPC + 4 mov TMP, nPC ; TMP := nPC add TMP, 0x4 ; TMP := TMP + 4 mov R(31), TMP ; Regs[31] := TMP SX18_4N Imm ; Sign Extend Imm * 4 mov TMP, 0x4 ; TMP := 4 cmp R(rS), 0 ; If Regs[rS] < 0: cmovnl TMP, Imm ; ... then TMP := Imm add nPC, TMP ; nPC := nPC + TMP Flg_On InDelaySlot ; Set 'Delay Slot' Flag. jmp _end_cycle ;-----------------------------------------------------------------------------