m_genesis.kv 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 2 ;; ;;
m_genesis.kv 3 ;; This file is part of 'M', a MIPS system emulator. ;;
m_genesis.kv 4 ;; ;;
m_genesis.kv 5 ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;;
m_genesis.kv 6 ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;;
m_genesis.kv 7 ;; ;;
m_genesis.kv 8 ;; You do not have, nor can you ever acquire the right to use, copy or ;;
m_genesis.kv 9 ;; distribute this software ; Should you use this software for any purpose, ;;
m_genesis.kv 10 ;; or copy and distribute it to anyone or in any manner, you are breaking ;;
m_genesis.kv 11 ;; the laws of whatever soi-disant jurisdiction, and you promise to ;;
m_genesis.kv 12 ;; continue doing so for the indefinite future. In any case, please ;;
m_genesis.kv 13 ;; always : read and understand any software ; verify any PGP signatures ;;
m_genesis.kv 14 ;; that you use - for any purpose. ;;
m_genesis.kv 15 ;; ;;
m_genesis.kv 16 ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;;
m_genesis.kv 17 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 18
m_genesis.kv 19 ;; TODO: 1) Traps in ADD and SUB (gcc 4.8.1 doesn't seem to use. but do exist)
m_genesis.kv 20 ;; 2) Tests!!!
m_genesis.kv 21
m_genesis.kv 22 ;----------------------------
m_genesis.kv 23 ; R-Type MIPS Instructions: |
m_genesis.kv 24 ;----------------------------
m_genesis.kv 25
m_genesis.kv 26 ;-----------------------------------------------------------------------------
m_genesis.kv 27 section .rodata
m_genesis.kv 28 align GRAIN, db 0x90
m_genesis.kv 29 _R_Table:
m_genesis.kv 30 A32 _r_sll ; 0x00 : sll (000000????????????????????000000)
m_genesis.kv 31 A32 _bad ; 0x01 : UNDEFINED
m_genesis.kv 32 A32 _r_srl ; 0x02 : srl (000000????????????????????000010)
m_genesis.kv 33 A32 _r_sra ; 0x03 : sra (000000????????????????????000011)
m_genesis.kv 34 A32 _r_sllv ; 0x04 : sllv (000000????????????????????000100)
m_genesis.kv 35 A32 _bad ; 0x05 : UNDEFINED
m_genesis.kv 36 A32 _r_srlv ; 0x06 : srlv (000000????????????????????000110)
m_genesis.kv 37 A32 _r_srav ; 0x07 : srav (000000????????????????????000111)
m_genesis.kv 38 A32 _r_jr ; 0x08 : jr (000000????????????????????001000)
m_genesis.kv 39 A32 _r_jalr ; 0x09 : jalr (000000????????????????????001001)
m_genesis.kv 40 A32 _r_movz ; 0x0a : movz (000000???????????????00000001010)
m_genesis.kv 41 A32 _r_movn ; 0x0b : movn (000000???????????????00000001011)
m_genesis.kv 42 A32 _r_syscall ; 0x0c : syscall (000000????????????????????001100)
m_genesis.kv 43 A32 _bad ; 0x0d : UNDEFINED
m_genesis.kv 44 A32 _bad ; 0x0e : UNDEFINED
m_genesis.kv 45 A32 _r_sync ; 0x0f : sync (000000????????????????????001111)
m_genesis.kv 46 A32 _r_mfhi ; 0x10 : mfhi (000000????????????????????010000)
m_genesis.kv 47 A32 _r_mthi ; 0x11 : mthi (000000????????????????????010001)
m_genesis.kv 48 A32 _r_mflo ; 0x12 : mflo (000000????????????????????010010)
m_genesis.kv 49 A32 _r_mtlo ; 0x13 : mtlo (000000????????????????????010011)
m_genesis.kv 50 A32 _bad ; 0x14 : UNDEFINED
m_genesis.kv 51 A32 _bad ; 0x15 : UNDEFINED
m_genesis.kv 52 A32 _bad ; 0x16 : UNDEFINED
m_genesis.kv 53 A32 _bad ; 0x17 : UNDEFINED
m_genesis.kv 54 A32 _r_mult ; 0x18 : mult (000000????????????????????011000)
m_genesis.kv 55 A32 _r_multu ; 0x19 : multu (000000????????????????????011001)
m_genesis.kv 56 A32 _r_div ; 0x1a : div (000000????????????????????011010)
m_genesis.kv 57 A32 _r_divu ; 0x1b : divu (000000????????????????????011011)
m_genesis.kv 58 A32 _bad ; 0x1c : UNDEFINED
m_genesis.kv 59 A32 _bad ; 0x1d : UNDEFINED
m_genesis.kv 60 A32 _bad ; 0x1e : UNDEFINED
m_genesis.kv 61 A32 _bad ; 0x1f : UNDEFINED
m_genesis.kv 62 A32 _r_add ; 0x20 : add (000000????????????????????100000)
m_genesis.kv 63 A32 _r_addu ; 0x21 : addu (000000????????????????????100001)
m_genesis.kv 64 A32 _r_sub ; 0x22 : sub (000000????????????????????100010)
m_genesis.kv 65 A32 _r_subu ; 0x23 : subu (000000????????????????????100011)
m_genesis.kv 66 A32 _r_and ; 0x24 : and (000000????????????????????100100)
m_genesis.kv 67 A32 _r_or ; 0x25 : or (000000????????????????????100101)
m_genesis.kv 68 A32 _r_xor ; 0x26 : xor (000000????????????????????100110)
m_genesis.kv 69 A32 _r_nor ; 0x27 : nor (000000????????????????????100111)
m_genesis.kv 70 A32 _bad ; 0x28 : UNDEFINED
m_genesis.kv 71 A32 _bad ; 0x29 : UNDEFINED
m_genesis.kv 72 A32 _r_slt ; 0x2a : slt (000000????????????????????101010)
m_genesis.kv 73 A32 _r_sltu ; 0x2b : sltu (000000????????????????????101011)
m_genesis.kv 74 A32 _bad ; 0x2c : UNDEFINED
m_genesis.kv 75 A32 _bad ; 0x2d : UNDEFINED
m_genesis.kv 76 A32 _bad ; 0x2e : UNDEFINED
m_genesis.kv 77 A32 _bad ; 0x2f : UNDEFINED
m_genesis.kv 78 A32 _bad ; 0x30 : UNDEFINED
m_genesis.kv 79 A32 _bad ; 0x31 : UNDEFINED
m_genesis.kv 80 A32 _bad ; 0x32 : UNDEFINED
m_genesis.kv 81 A32 _bad ; 0x33 : UNDEFINED
m_genesis.kv 82 A32 _r_teq ; 0x34 : teq (000000????????????????????110100)
m_genesis.kv 83 A32 _bad ; 0x35 : UNDEFINED
m_genesis.kv 84 A32 _r_tne ; 0x36 : tne (000000????????????????????110110)
m_genesis.kv 85 A32 _bad ; 0x37 : UNDEFINED
m_genesis.kv 86 A32 _bad ; 0x38 : UNDEFINED
m_genesis.kv 87 A32 _bad ; 0x39 : UNDEFINED
m_genesis.kv 88 A32 _bad ; 0x3a : UNDEFINED
m_genesis.kv 89 A32 _bad ; 0x3b : UNDEFINED
m_genesis.kv 90 A32 _bad ; 0x3c : UNDEFINED
m_genesis.kv 91 A32 _bad ; 0x3d : UNDEFINED
m_genesis.kv 92 A32 _bad ; 0x3e : UNDEFINED
m_genesis.kv 93 A32 _bad ; 0x3f : UNDEFINED
m_genesis.kv 94 ;-----------------------------------------------------------------------------
m_genesis.kv 95
m_genesis.kv 96 section .text
m_genesis.kv 97
m_genesis.kv 98 ;-----------------------------------------------------------------------------
m_genesis.kv 99 ; SLL -- Shift left logical.
m_genesis.kv 100 ; Shifts a register value left by the shift amount listed in the instruction
m_genesis.kv 101 ; and places the result in a third register. Zeroes are shifted in.
m_genesis.kv 102 ; Operation: $d = $t << h; advance_pc(4);
m_genesis.kv 103 ; Syntax: sll $d, $t, h
m_genesis.kv 104 ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0000
m_genesis.kv 105 ;-----------------------------------------------------------------------------
m_genesis.kv 106 align GRAIN, db 0x90
m_genesis.kv 107 _r_sll:
m_genesis.kv 108 RType_D_T_Shamt ; load rS, rT, Shamt Fields
m_genesis.kv 109 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 110 shl TMP, cl ; TMP := TMP << CL (Shamt is in ECX)
m_genesis.kv 111 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 112 jmp _end_cycle
m_genesis.kv 113 ;-----------------------------------------------------------------------------
m_genesis.kv 114
m_genesis.kv 115 ;-----------------------------------------------------------------------------
m_genesis.kv 116 ; SRL -- Shift right logical.
m_genesis.kv 117 ; Shifts a register value right by the shift amount (shamt) and places the
m_genesis.kv 118 ; value in the destination register. Zeroes are shifted in.
m_genesis.kv 119 ; Operation: $d = $t >> h; advance_pc(4);
m_genesis.kv 120 ; Syntax: srl $d, $t, h
m_genesis.kv 121 ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0010
m_genesis.kv 122 ;-----------------------------------------------------------------------------
m_genesis.kv 123 align GRAIN, db 0x90
m_genesis.kv 124 _r_srl:
m_genesis.kv 125 RType_D_T_Shamt ; load rS, rT, Shamt Fields
m_genesis.kv 126 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 127 shr TMP, cl ; TMP := TMP >> CL (Shamt is in ECX)
m_genesis.kv 128 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 129 jmp _end_cycle
m_genesis.kv 130 ;-----------------------------------------------------------------------------
m_genesis.kv 131
m_genesis.kv 132 ;-----------------------------------------------------------------------------
m_genesis.kv 133 ; SRA -- Shift right arithmetic.
m_genesis.kv 134 ; Shifts a register value right by the shift amount (shamt) and places the
m_genesis.kv 135 ; value in the destination register. The sign bit is shifted in.
m_genesis.kv 136 ; Operation: $d = $t >> h; advance_pc(4);
m_genesis.kv 137 ; Syntax: sra $d, $t, h
m_genesis.kv 138 ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0011
m_genesis.kv 139 ;-----------------------------------------------------------------------------
m_genesis.kv 140 align GRAIN, db 0x90
m_genesis.kv 141 _r_sra:
m_genesis.kv 142 RType_D_T_Shamt ; load rS, rT, Shamt Fields
m_genesis.kv 143 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 144 sar TMP, cl ; TMP := TMP >>(sgn) CL (Shamt is in ECX)
m_genesis.kv 145 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 146 jmp _end_cycle
m_genesis.kv 147 ;-----------------------------------------------------------------------------
m_genesis.kv 148
m_genesis.kv 149 ;-----------------------------------------------------------------------------
m_genesis.kv 150 ; SLLV -- Shift left logical variable.
m_genesis.kv 151 ; Shifts a register value left by the value in a second register and places
m_genesis.kv 152 ; the result in a third register. Zeroes are shifted in.
m_genesis.kv 153 ; Operation: $d = $t << $s; advance_pc(4);
m_genesis.kv 154 ; Syntax: sllv $d, $t, $s
m_genesis.kv 155 ; Encoding: 0000 00ss ssst tttt dddd d--- --00 0100
m_genesis.kv 156 ;-----------------------------------------------------------------------------
m_genesis.kv 157 align GRAIN, db 0x90
m_genesis.kv 158 _r_sllv:
m_genesis.kv 159 RType ; load rD, rS, rT Fields
m_genesis.kv 160 mov ecx, R(rS) ; Now CL is the shift amount
m_genesis.kv 161 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 162 shl TMP, cl ; TMP := TMP << CL
m_genesis.kv 163 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 164 jmp _end_cycle
m_genesis.kv 165 ;-----------------------------------------------------------------------------
m_genesis.kv 166
m_genesis.kv 167 ;-----------------------------------------------------------------------------
m_genesis.kv 168 ; SRLV -- Shift right logical variable.
m_genesis.kv 169 ; Shifts a register value right by the amount specified in $s and places the
m_genesis.kv 170 ; value in the destination register. Zeroes are shifted in.
m_genesis.kv 171 ; Operation: $d = $t >> $s; advance_pc(4);
m_genesis.kv 172 ; Syntax: srlv $d, $t, $s
m_genesis.kv 173 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 0110
m_genesis.kv 174 ;-----------------------------------------------------------------------------
m_genesis.kv 175 align GRAIN, db 0x90
m_genesis.kv 176 _r_srlv:
m_genesis.kv 177 RType ; load rD, rS, rT Fields
m_genesis.kv 178 mov ecx, R(rS) ; Now CL is the shift amount
m_genesis.kv 179 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 180 shr TMP, cl ; TMP := TMP >> CL
m_genesis.kv 181 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 182 jmp _end_cycle
m_genesis.kv 183 ;-----------------------------------------------------------------------------
m_genesis.kv 184
m_genesis.kv 185 ;-----------------------------------------------------------------------------
m_genesis.kv 186 ; SRAV - Shift Word Right Arithmetic Variable.
m_genesis.kv 187 ; Execute an arithmetic right-shift of a word by a variable number of bits.
m_genesis.kv 188 ; The contents of the low-order 32-bit word of rT are shifted right,
m_genesis.kv 189 ; duplicating the sign-bit (bit 31) in the emptied bits; the word result is
m_genesis.kv 190 ; placed in rD. The bit-shift amount is specified by the low-order 5 bits
m_genesis.kv 191 ; of rS.
m_genesis.kv 192 ; Operation: $d = $t >> $s; advance_pc(4);
m_genesis.kv 193 ; Syntax: srav $d, $t, $s
m_genesis.kv 194 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 0111
m_genesis.kv 195 ;-----------------------------------------------------------------------------
m_genesis.kv 196 align GRAIN, db 0x90
m_genesis.kv 197 _r_srav:
m_genesis.kv 198 RType ; load rD, rS, rT Fields
m_genesis.kv 199 mov ecx, R(rS) ; Now CL is the shift amount
m_genesis.kv 200 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 201 sar TMP, cl ; TMP := TMP >> CL (extends sign bit)
m_genesis.kv 202 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 203 jmp _end_cycle
m_genesis.kv 204 ;-----------------------------------------------------------------------------
m_genesis.kv 205
m_genesis.kv 206 ;-----------------------------------------------------------------------------
m_genesis.kv 207 ; JR -- Jump register.
m_genesis.kv 208 ; Jump to the address contained in register $s
m_genesis.kv 209 ; Operation: PC = nPC; nPC = $s;
m_genesis.kv 210 ; Syntax: jr $s
m_genesis.kv 211 ; Encoding: 0000 00ss sss0 0000 0000 0000 0000 1000
m_genesis.kv 212 ;-----------------------------------------------------------------------------
m_genesis.kv 213 align GRAIN, db 0x90
m_genesis.kv 214 _r_jr:
m_genesis.kv 215 RType_S_Only ; Load rS Field
m_genesis.kv 216 mov nPC, R(rS) ; nPC := Regs[rS]
m_genesis.kv 217 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 218 jmp _end_cycle
m_genesis.kv 219 ;-----------------------------------------------------------------------------
m_genesis.kv 220
m_genesis.kv 221 ;-----------------------------------------------------------------------------
m_genesis.kv 222 ; JALR - Jump and Link Register.
m_genesis.kv 223 ; Execute a procedure call to an instruction address in a register.
m_genesis.kv 224 ; Place the return address link in rD. The return link is the address of the
m_genesis.kv 225 ; second instruction following the branch, where execution continues after a
m_genesis.kv 226 ; procedure call. Jump to the effective target address in rS. Execute the
m_genesis.kv 227 ; instruction that follows the jump, in the branch delay slot, before
m_genesis.kv 228 ; executing the jump itself.
m_genesis.kv 229 ; Operation: $d = PC + 8; PC = nPC; nPC = $s
m_genesis.kv 230 ; Syntax: jalr $s
m_genesis.kv 231 ; Encoding: 0000 00ss sss0 0000 dddd 0000 0000 1001
m_genesis.kv 232 ;-----------------------------------------------------------------------------
m_genesis.kv 233 align GRAIN, db 0x90
m_genesis.kv 234 _r_jalr:
m_genesis.kv 235 RType_S_D_Only ; Load rD and rS Fields
m_genesis.kv 236 mov nPC, R(rS) ; nPC := Regs[rS]
m_genesis.kv 237 mov TMP, PC ; TMP := PC
m_genesis.kv 238 add TMP, 0x8 ; TMP := TMP + 8
m_genesis.kv 239 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 240 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 241 jmp _end_cycle
m_genesis.kv 242 ;-----------------------------------------------------------------------------
m_genesis.kv 243
m_genesis.kv 244 ;-----------------------------------------------------------------------------
m_genesis.kv 245 ; MOVZ - Move Conditional on Zero.
m_genesis.kv 246 ; Conditionally move a register after testing a register value.
m_genesis.kv 247 ; If the value in rT is equal to zero, then the contents of rS are placed
m_genesis.kv 248 ; into rD.
m_genesis.kv 249 ; Operation: if $t = 0 then $d = $s
m_genesis.kv 250 ; Syntax: movz $d, $s, $t
m_genesis.kv 251 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 1010
m_genesis.kv 252 ;-----------------------------------------------------------------------------
m_genesis.kv 253 ; TODO: measure if the cmov is actually faster than a branch here !
m_genesis.kv 254 ; TODO: untested
m_genesis.kv 255 align GRAIN, db 0x90
m_genesis.kv 256 _r_movz:
m_genesis.kv 257 ; UNDONE_INST
m_genesis.kv 258 RType ; load rD, rS, rT Fields
m_genesis.kv 259 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 260 test TMP, TMP ; Set Z flag if TMP = 0
m_genesis.kv 261 mov TMP, R(rD) ; First, move Regs[rD] to TMP
m_genesis.kv 262 cmovz TMP, R(rS) ; If Z flag set, overwrite with Regs[rS]
m_genesis.kv 263 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 264 jmp _end_cycle
m_genesis.kv 265 ;-----------------------------------------------------------------------------
m_genesis.kv 266
m_genesis.kv 267 ;-----------------------------------------------------------------------------
m_genesis.kv 268 ; MOVN - Move Conditional on Not Zero.
m_genesis.kv 269 ; Conditionally move a register after testing a register value.
m_genesis.kv 270 ; If the value in rT is NOT equal to zero, then the contents of rS are placed
m_genesis.kv 271 ; into rD.
m_genesis.kv 272 ; Operation: if $t != 0 then $d = $s
m_genesis.kv 273 ; Syntax: movn $d, $s, $t
m_genesis.kv 274 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 1011
m_genesis.kv 275 ;-----------------------------------------------------------------------------
m_genesis.kv 276 ; TODO: measure if the cmov is actually faster than a branch here !
m_genesis.kv 277 ; TODO: untested
m_genesis.kv 278 align GRAIN, db 0x90
m_genesis.kv 279 _r_movn:
m_genesis.kv 280 ; UNDONE_INST
m_genesis.kv 281 RType ; load rD, rS, rT Fields
m_genesis.kv 282 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 283 test TMP, TMP ; Set Z flag if TMP = 0
m_genesis.kv 284 mov TMP, R(rD) ; First, move Regs[rD] to TMP
m_genesis.kv 285 cmovnz TMP, R(rS) ; If Z not set, overwrite with Regs[rS]
m_genesis.kv 286 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 287 jmp _end_cycle
m_genesis.kv 288 ;-----------------------------------------------------------------------------
m_genesis.kv 289
m_genesis.kv 290 ;-----------------------------------------------------------------------------
m_genesis.kv 291 ; SYSCALL -- System call.
m_genesis.kv 292 ; Generates a software interrupt.
m_genesis.kv 293 ; Operation: advance_pc(4);
m_genesis.kv 294 ; Syntax: syscall
m_genesis.kv 295 ; Encoding: 0000 00-- ---- ---- ---- ---- --00 1100
m_genesis.kv 296 ;-----------------------------------------------------------------------------
m_genesis.kv 297 align GRAIN, db 0x90
m_genesis.kv 298 _r_syscall:
m_genesis.kv 299 ; no fields
m_genesis.kv 300 SetEXC EXC_SYS ; Set the EXC_SYS Exception
m_genesis.kv 301 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 302 ;-----------------------------------------------------------------------------
m_genesis.kv 303
m_genesis.kv 304 ;-----------------------------------------------------------------------------
m_genesis.kv 305 ; SYNC - Synchronize Shared Memory.
m_genesis.kv 306 ; Operation: This is a NOP in this emulator.
m_genesis.kv 307 ; Syntax: sync
m_genesis.kv 308 ; Encoding: 0000 0000 0000 0000 0000 0000 0000 1111
m_genesis.kv 309 ;-----------------------------------------------------------------------------
m_genesis.kv 310 align GRAIN, db 0x90
m_genesis.kv 311 _r_sync:
m_genesis.kv 312 jmp _end_cycle
m_genesis.kv 313 ;-----------------------------------------------------------------------------
m_genesis.kv 314
m_genesis.kv 315 ;-----------------------------------------------------------------------------
m_genesis.kv 316 ; MFHI -- Move from HI.
m_genesis.kv 317 ; The contents of special register HI are moved to the specified register.
m_genesis.kv 318 ; Operation: $d = $HI; advance_pc(4);
m_genesis.kv 319 ; Syntax: mfhi $d
m_genesis.kv 320 ; Encoding: 0000 0000 0000 0000 dddd d000 0001 0000
m_genesis.kv 321 ;-----------------------------------------------------------------------------
m_genesis.kv 322 align GRAIN, db 0x90
m_genesis.kv 323 _r_mfhi:
m_genesis.kv 324 RType_D_Only ; Load rD Field
m_genesis.kv 325 mov TMP, Sr(HI) ; TMP := Sr(HI)
m_genesis.kv 326 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 327 jmp _end_cycle
m_genesis.kv 328 ;-----------------------------------------------------------------------------
m_genesis.kv 329
m_genesis.kv 330 ;-----------------------------------------------------------------------------
m_genesis.kv 331 ; MTHI - Move to HI Register.
m_genesis.kv 332 ; The contents of rS are loaded to the special register HI.
m_genesis.kv 333 ; Operation: $HI = $s
m_genesis.kv 334 ; Syntax: mthi $s
m_genesis.kv 335 ; Encoding: 0000 00ss sss0 0000 0000 0000 0001 0001
m_genesis.kv 336 ;-----------------------------------------------------------------------------
m_genesis.kv 337 align GRAIN, db 0x90
m_genesis.kv 338 _r_mthi:
m_genesis.kv 339 RType_S_Only ; Load rS Field
m_genesis.kv 340 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 341 mov Sr(HI), TMP ; HI := TMP
m_genesis.kv 342 jmp _end_cycle
m_genesis.kv 343 ;-----------------------------------------------------------------------------
m_genesis.kv 344
m_genesis.kv 345 ;-----------------------------------------------------------------------------
m_genesis.kv 346 ; MFLO -- Move from LO.
m_genesis.kv 347 ; The contents of register LO are moved to the specified register.
m_genesis.kv 348 ; Operation: $d = $LO; advance_pc(4);
m_genesis.kv 349 ; Syntax: mflo $d
m_genesis.kv 350 ; Encoding: 0000 0000 0000 0000 dddd d000 0001 0010
m_genesis.kv 351 ;-----------------------------------------------------------------------------
m_genesis.kv 352 align GRAIN, db 0x90
m_genesis.kv 353 _r_mflo:
m_genesis.kv 354 RType_D_Only ; Load rD Field
m_genesis.kv 355 mov TMP, Sr(LO) ; TMP := Sr(LO)
m_genesis.kv 356 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 357 jmp _end_cycle
m_genesis.kv 358 ;-----------------------------------------------------------------------------
m_genesis.kv 359
m_genesis.kv 360 ;-----------------------------------------------------------------------------
m_genesis.kv 361 ; MTLO - Move to LO.
m_genesis.kv 362 ; The contents of rS are loaded to the special register LO.
m_genesis.kv 363 ; Operation: $LO = $s
m_genesis.kv 364 ; Syntax: mtlo $s
m_genesis.kv 365 ; Encoding: 0000 00ss sss0 0000 0000 0000 0001 0011
m_genesis.kv 366 ;-----------------------------------------------------------------------------
m_genesis.kv 367 align GRAIN, db 0x90
m_genesis.kv 368 _r_mtlo:
m_genesis.kv 369 RType_S_Only ; Load rS Field
m_genesis.kv 370 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 371 mov Sr(LO), TMP ; LO := TMP
m_genesis.kv 372 jmp _end_cycle
m_genesis.kv 373 ;-----------------------------------------------------------------------------
m_genesis.kv 374
m_genesis.kv 375 ;-----------------------------------------------------------------------------
m_genesis.kv 376 ; MULT -- Multiply signed.
m_genesis.kv 377 ; Multiplies $s by $t and stores the result in $HI:$LO.
m_genesis.kv 378 ; Operation: $HI:$LO = $s * $t; advance_pc(4);
m_genesis.kv 379 ; Syntax: mult $s, $t
m_genesis.kv 380 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1000
m_genesis.kv 381 ;-----------------------------------------------------------------------------
m_genesis.kv 382 align GRAIN, db 0x90
m_genesis.kv 383 _r_mult:
m_genesis.kv 384 RType_S_T_Only
m_genesis.kv 385 mov eax, R(rT) ; eax := Regs[rT]
m_genesis.kv 386 imul R(rS) ; edx:eax := Regs[rS] * eax (signed)
m_genesis.kv 387 mov Sr(LO), eax ; LO := Bottom 32 bits of product
m_genesis.kv 388 mov Sr(HI), edx ; HI := Top 32 bits of product
m_genesis.kv 389 jmp _end_cycle
m_genesis.kv 390 ;-----------------------------------------------------------------------------
m_genesis.kv 391
m_genesis.kv 392 ;-----------------------------------------------------------------------------
m_genesis.kv 393 ; MULTU -- Multiply unsigned.
m_genesis.kv 394 ; Multiplies $s by $t and stores the result in $HI:$LO.
m_genesis.kv 395 ; Operation: $HI:$LO = $s * $t; advance_pc(4);
m_genesis.kv 396 ; Syntax: multu $s, $t
m_genesis.kv 397 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1001
m_genesis.kv 398 ;-----------------------------------------------------------------------------
m_genesis.kv 399 align GRAIN, db 0x90
m_genesis.kv 400 _r_multu:
m_genesis.kv 401 RType_S_T_Only ; Load rS and rT Fields
m_genesis.kv 402 mov eax, R(rT) ; eax := Regs[rT]
m_genesis.kv 403 mul R(rS) ; edx:eax := Regs[rS] * eax (unsigned)
m_genesis.kv 404 mov Sr(LO), eax ; LO := Bottom 32 bits of product
m_genesis.kv 405 mov Sr(HI), edx ; HI := Top 32 bits of product
m_genesis.kv 406 jmp _end_cycle
m_genesis.kv 407 ;-----------------------------------------------------------------------------
m_genesis.kv 408
m_genesis.kv 409 ;-----------------------------------------------------------------------------
m_genesis.kv 410 ; DIV -- Divide signed.
m_genesis.kv 411 ; Divides $s by $t and stores the quotient in $LO and the remainder in $HI
m_genesis.kv 412 ; Operation: $LO = $s / $t; $HI = $s % $t; advance_pc(4);
m_genesis.kv 413 ; Syntax: div $s, $t
m_genesis.kv 414 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1010
m_genesis.kv 415 ;-----------------------------------------------------------------------------
m_genesis.kv 416 ; TODO: detect div0 and other special cases
m_genesis.kv 417 align GRAIN, db 0x90
m_genesis.kv 418 _r_div:
m_genesis.kv 419 RType_S_T_Only ; Load rS and rT Fields
m_genesis.kv 420 mov eax, R(rS) ; eax := Regs[rS]
m_genesis.kv 421 cdq ; extend sign of eax into edx
m_genesis.kv 422 cmp R(rT), 0 ; test for div0
m_genesis.kv 423 je _r_div_div0 ; div0 is undefined result
m_genesis.kv 424 idiv R(rT) ; edx:eax / Regs[rT]; edx := r, eax := q
m_genesis.kv 425 mov Sr(LO), eax ; LO := edx:eax /(signed) ecx (quotient)
m_genesis.kv 426 mov Sr(HI), edx ; HI := edx:eax %(signed) ecx (remainder)
m_genesis.kv 427 _r_div_div0:
m_genesis.kv 428 jmp _end_cycle
m_genesis.kv 429 ;-----------------------------------------------------------------------------
m_genesis.kv 430
m_genesis.kv 431 ;-----------------------------------------------------------------------------
m_genesis.kv 432 ; DIVU -- Divide unsigned.
m_genesis.kv 433 ; Divides $s by $t and stores the quotient in $LO and the remainder in $HI
m_genesis.kv 434 ; Operation: $LO = $s / $t; $HI = $s % $t; advance_pc(4);
m_genesis.kv 435 ; Syntax: divu $s, $t
m_genesis.kv 436 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1011
m_genesis.kv 437 ;-----------------------------------------------------------------------------
m_genesis.kv 438 ; TODO: detect div0 and other special cases
m_genesis.kv 439 align GRAIN, db 0x90
m_genesis.kv 440 _r_divu:
m_genesis.kv 441 RType_S_T_Only ; Load rS and rT Fields
m_genesis.kv 442 xor edx, edx ; edx := 0
m_genesis.kv 443 mov eax, R(rS) ; eax := Regs[rS]
m_genesis.kv 444 cmp R(rT), 0 ; test for div0
m_genesis.kv 445 je _r_divu_div0 ; div0 is undefined result
m_genesis.kv 446 div R(rT) ; edx:eax / Regs[rT]; edx := r, eax := q
m_genesis.kv 447 mov Sr(LO), eax ; LO := edx:eax / ecx (quotient)
m_genesis.kv 448 mov Sr(HI), edx ; HI := edx:eax % ecx (remainder)
m_genesis.kv 449 _r_divu_div0:
m_genesis.kv 450 jmp _end_cycle
m_genesis.kv 451 ;-----------------------------------------------------------------------------
m_genesis.kv 452
m_genesis.kv 453 ;-----------------------------------------------------------------------------
m_genesis.kv 454 ; ADD -- Add (with overflow).
m_genesis.kv 455 ; Adds two registers and stores the result in a register
m_genesis.kv 456 ; Operation: $d = $s + $t; advance_pc(4);
m_genesis.kv 457 ; Syntax: add $d, $s, $t
m_genesis.kv 458 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0000
m_genesis.kv 459 ;-----------------------------------------------------------------------------
m_genesis.kv 460 align GRAIN, db 0x90
m_genesis.kv 461 _r_add:
m_genesis.kv 462 RType ; load rD, rS, rT Fields
m_genesis.kv 463 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 464 add TMP, R(rT) ; TMP := Regs[rS] + Regs[rT]
m_genesis.kv 465 ; TODO: detect/trap overflow
m_genesis.kv 466 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 467 jmp _end_cycle
m_genesis.kv 468 ;-----------------------------------------------------------------------------
m_genesis.kv 469
m_genesis.kv 470 ;-----------------------------------------------------------------------------
m_genesis.kv 471 ; ADDU -- Add unsigned (no overflow).
m_genesis.kv 472 ; Adds two registers and stores the result in a register
m_genesis.kv 473 ; Operation: $d = $s + $t; advance_pc(4);
m_genesis.kv 474 ; Syntax: addu $d, $s, $t
m_genesis.kv 475 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0001
m_genesis.kv 476 ;-----------------------------------------------------------------------------
m_genesis.kv 477 align GRAIN, db 0x90
m_genesis.kv 478 _r_addu:
m_genesis.kv 479 RType ; load rD, rS, rT Fields
m_genesis.kv 480 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 481 add TMP, R(rT) ; TMP := Regs[rS] + Regs[rT]
m_genesis.kv 482 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 483 jmp _end_cycle
m_genesis.kv 484 ;-----------------------------------------------------------------------------
m_genesis.kv 485
m_genesis.kv 486 ;-----------------------------------------------------------------------------
m_genesis.kv 487 ; SUB -- Subtract.
m_genesis.kv 488 ; Subtracts two registers and stores the result in a register
m_genesis.kv 489 ; Operation: $d = $s - $t; advance_pc(4);
m_genesis.kv 490 ; Syntax: sub $d, $s, $t
m_genesis.kv 491 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0010
m_genesis.kv 492 ;-----------------------------------------------------------------------------
m_genesis.kv 493 align GRAIN, db 0x90
m_genesis.kv 494 _r_sub:
m_genesis.kv 495 RType ; load rD, rS, rT Fields
m_genesis.kv 496 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 497 sub TMP, R(rT) ; TMP := Regs[rS] - Regs[rT]
m_genesis.kv 498 ; TODO: detect and trap overflow
m_genesis.kv 499 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 500 jmp _end_cycle
m_genesis.kv 501 ;-----------------------------------------------------------------------------
m_genesis.kv 502
m_genesis.kv 503 ;-----------------------------------------------------------------------------
m_genesis.kv 504 ; SUBU -- Subtract unsigned.
m_genesis.kv 505 ; Subtracts two registers and stores the result in a register
m_genesis.kv 506 ; Operation: $d = $s - $t; advance_pc(4);
m_genesis.kv 507 ; Syntax: subu $d, $s, $t
m_genesis.kv 508 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0011
m_genesis.kv 509 ;-----------------------------------------------------------------------------
m_genesis.kv 510 align GRAIN, db 0x90
m_genesis.kv 511 _r_subu:
m_genesis.kv 512 RType ; load rD, rS, rT Fields
m_genesis.kv 513 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 514 sub TMP, R(rT) ; TMP := Regs[rS] - Regs[rT]
m_genesis.kv 515 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 516 jmp _end_cycle
m_genesis.kv 517 ;-----------------------------------------------------------------------------
m_genesis.kv 518
m_genesis.kv 519 ;-----------------------------------------------------------------------------
m_genesis.kv 520 ; AND -- Bitwise AND.
m_genesis.kv 521 ; Bitwise ANDs two registers and stores the result in a register
m_genesis.kv 522 ; Operation: $d = $s & $t; advance_pc(4);
m_genesis.kv 523 ; Syntax: and $d, $s, $t
m_genesis.kv 524 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0100
m_genesis.kv 525 ;-----------------------------------------------------------------------------
m_genesis.kv 526 align GRAIN, db 0x90
m_genesis.kv 527 _r_and:
m_genesis.kv 528 RType ; load rD, rS, rT Fields
m_genesis.kv 529 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 530 and TMP, R(rT) ; TMP := TMP & Regs[rT]
m_genesis.kv 531 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 532 jmp _end_cycle
m_genesis.kv 533 ;-----------------------------------------------------------------------------
m_genesis.kv 534
m_genesis.kv 535 ;-----------------------------------------------------------------------------
m_genesis.kv 536 ; OR -- Bitwise OR.
m_genesis.kv 537 ; Bitwise logical ORs two registers and stores the result in a register
m_genesis.kv 538 ; Operation: $d = $s | $t; advance_pc(4);
m_genesis.kv 539 ; Syntax: or $d, $s, $t
m_genesis.kv 540 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0101
m_genesis.kv 541 ;-----------------------------------------------------------------------------
m_genesis.kv 542 align GRAIN, db 0x90
m_genesis.kv 543 _r_or:
m_genesis.kv 544 RType ; load rD, rS, rT Fields
m_genesis.kv 545 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 546 or TMP, R(rT) ; TMP := TMP | Regs[rT]
m_genesis.kv 547 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 548 jmp _end_cycle
m_genesis.kv 549 ;-----------------------------------------------------------------------------
m_genesis.kv 550
m_genesis.kv 551 ;-----------------------------------------------------------------------------
m_genesis.kv 552 ; XOR -- Bitwise Exclusive OR.
m_genesis.kv 553 ; Exclusive ORs two registers and stores the result in a register
m_genesis.kv 554 ; Operation: $d = $s ^ $t; advance_pc(4);
m_genesis.kv 555 ; Syntax: xor $d, $s, $t
m_genesis.kv 556 ; Encoding: 0000 00ss ssst tttt dddd d--- --10 0110
m_genesis.kv 557 ;-----------------------------------------------------------------------------
m_genesis.kv 558 align GRAIN, db 0x90
m_genesis.kv 559 _r_xor:
m_genesis.kv 560 RType ; load rD, rS, rT Fields
m_genesis.kv 561 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 562 xor TMP, R(rT) ; TMP := TMP ^ Regs[rT]
m_genesis.kv 563 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 564 jmp _end_cycle
m_genesis.kv 565 ;-----------------------------------------------------------------------------
m_genesis.kv 566
m_genesis.kv 567 ;-----------------------------------------------------------------------------
m_genesis.kv 568 ; NOR - Not OR.
m_genesis.kv 569 ; Do a bitwise logical NOT OR.
m_genesis.kv 570 ; The contents of rS are combined with the contents of rT in a bitwise logical
m_genesis.kv 571 ; NOR operation. The result is placed into rD.
m_genesis.kv 572 ; Operation: $d = $s NOR $t
m_genesis.kv 573 ; Syntax: nor $d, $s, $t
m_genesis.kv 574 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0111
m_genesis.kv 575 ;-----------------------------------------------------------------------------
m_genesis.kv 576 align GRAIN, db 0x90
m_genesis.kv 577 _r_nor:
m_genesis.kv 578 RType ; load rD, rS, rT Fields
m_genesis.kv 579 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 580 or TMP, R(rT) ; TMP := TMP | Regs[rT]
m_genesis.kv 581 not TMP ; TMP := ~TMP
m_genesis.kv 582 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
m_genesis.kv 583 jmp _end_cycle
m_genesis.kv 584 ;-----------------------------------------------------------------------------
m_genesis.kv 585
m_genesis.kv 586 ;-----------------------------------------------------------------------------
m_genesis.kv 587 ; SLT -- Set on less than (signed).
m_genesis.kv 588 ; If $s is less than $t, $d is set to one. It gets zero otherwise.
m_genesis.kv 589 ; Operation: if $s < $t $d = 1; advance_pc(4); else $d = 0; advance_pc(4);
m_genesis.kv 590 ; Syntax: slt $d, $s, $t
m_genesis.kv 591 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 1010
m_genesis.kv 592 ;-----------------------------------------------------------------------------
m_genesis.kv 593 align GRAIN, db 0x90
m_genesis.kv 594 _r_slt:
m_genesis.kv 595 RType ; load rD, rS, rT Fields
m_genesis.kv 596 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 597 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 598 ; We do not need rS, so can reuse it here:
m_genesis.kv 599 setl rS_LowByte ; 1 if R(rS) <(signed) R(rT), else 0
m_genesis.kv 600 and rS, 0x1 ; Only want the bit that we have set
m_genesis.kv 601 Wr_Reg rD, rS ; Regs[rD] := result
m_genesis.kv 602 jmp _end_cycle
m_genesis.kv 603 ;-----------------------------------------------------------------------------
m_genesis.kv 604
m_genesis.kv 605 ;-----------------------------------------------------------------------------
m_genesis.kv 606 ; SLTU -- Set on less than unsigned.
m_genesis.kv 607 ; If $s is less than $t, $d is set to one. It gets zero otherwise.
m_genesis.kv 608 ; Operation: if $s < $t $d = 1; advance_pc(4); else $d = 0; advance_pc(4);
m_genesis.kv 609 ; Syntax: sltu $d, $s, $t
m_genesis.kv 610 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 1011
m_genesis.kv 611 ;-----------------------------------------------------------------------------
m_genesis.kv 612 align GRAIN, db 0x90
m_genesis.kv 613 _r_sltu:
m_genesis.kv 614 RType ; load rD, rS, rT Fields
m_genesis.kv 615 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 616 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 617 ; We do not need rS, so can reuse it here:
m_genesis.kv 618 setb rS_LowByte ; 1 if R(rS) <(signed) R(rT), else 0
m_genesis.kv 619 and rS, 0x1 ; Only want the bit that we have set
m_genesis.kv 620 Wr_Reg rD, rS ; Regs[rD] := result
m_genesis.kv 621 jmp _end_cycle
m_genesis.kv 622 ;-----------------------------------------------------------------------------
m_genesis.kv 623
m_genesis.kv 624 ;-----------------------------------------------------------------------------
m_genesis.kv 625 ; TEQ - Trap if Equal.
m_genesis.kv 626 ; TODO: document
m_genesis.kv 627 ;-----------------------------------------------------------------------------
m_genesis.kv 628 align GRAIN, db 0x90
m_genesis.kv 629 _r_teq:
m_genesis.kv 630 RType_S_T_Only ; Load rS and rT Fields
m_genesis.kv 631 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 632 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 633 jne _r_teq_neql
m_genesis.kv 634 SetEXC EXC_Tr ; Spring the Trap Exception.
m_genesis.kv 635 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 636 _r_teq_neql:
m_genesis.kv 637 jmp _end_cycle
m_genesis.kv 638 ;-----------------------------------------------------------------------------
m_genesis.kv 639
m_genesis.kv 640 ;-----------------------------------------------------------------------------
m_genesis.kv 641 ; TNE - Trap if Not Equal.
m_genesis.kv 642 ; Compare registers and do a conditional trap.
m_genesis.kv 643 ; Compare the contents of rS and rT as signed integers;
m_genesis.kv 644 ; if rS is not equal to rT, then take a Trap exception.
m_genesis.kv 645 ; The contents of the code field are ignored by hardware and may be used to
m_genesis.kv 646 ; encode information for system software. To retrieve the information,
m_genesis.kv 647 ; system software must load the instruction word from memory.
m_genesis.kv 648 ; Operation: if $s != $t then Trap
m_genesis.kv 649 ; Syntax: TNE $s, $t
m_genesis.kv 650 ; Encoding: 0000 00ss ssst tttt cccc cccc cc11 0110
m_genesis.kv 651 ;-----------------------------------------------------------------------------
m_genesis.kv 652 align GRAIN, db 0x90
m_genesis.kv 653 _r_tne:
m_genesis.kv 654 RType_S_T_Only ; Load rS and rT Fields
m_genesis.kv 655 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 656 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 657 je _r_tne_eql
m_genesis.kv 658 SetEXC EXC_Tr ; Spring the Trap Exception.
m_genesis.kv 659 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 660 _r_tne_eql:
m_genesis.kv 661 jmp _end_cycle
m_genesis.kv 662 ;-----------------------------------------------------------------------------