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) Trap for ADDI (gcc 4.8.1 doesn't appear to use, but it exists...)
m_genesis.kv 20 ;; 2) Tests!!!
m_genesis.kv 21
m_genesis.kv 22 ;------------------------
m_genesis.kv 23 ; I-Type 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 _I_Table:
m_genesis.kv 30 A32 _i_000000 ; 0x00 : All R-Type Instructions
m_genesis.kv 31 A32 _i_000001 ; 0x01 : bltz, bgez, bltzl, bgezl, bltzal, bgezal
m_genesis.kv 32 A32 _i_j ; 0x02 : j (000010??????????????????????????)
m_genesis.kv 33 A32 _i_jal ; 0x03 : jal (000011??????????????????????????)
m_genesis.kv 34 A32 _i_beq ; 0x04 : beq (000100??????????????????????????)
m_genesis.kv 35 A32 _i_bne ; 0x05 : bne (000101??????????????????????????)
m_genesis.kv 36 A32 _i_blez ; 0x06 : blez (000110??????????????????????????)
m_genesis.kv 37 A32 _i_bgtz ; 0x07 : bgtz (000111??????????????????????????)
m_genesis.kv 38 A32 _i_addi ; 0x08 : addi (001000??????????????????????????)
m_genesis.kv 39 A32 _i_addiu ; 0x09 : addiu (001001??????????????????????????)
m_genesis.kv 40 A32 _i_slti ; 0x0a : slti (001010??????????????????????????)
m_genesis.kv 41 A32 _i_sltiu ; 0x0b : sltiu (001011??????????????????????????)
m_genesis.kv 42 A32 _i_andi ; 0x0c : andi (001100??????????????????????????)
m_genesis.kv 43 A32 _i_ori ; 0x0d : ori (001101??????????????????????????)
m_genesis.kv 44 A32 _i_xori ; 0x0e : xori (001110??????????????????????????)
m_genesis.kv 45 A32 _i_lui ; 0x0f : lui (001111??????????????????????????)
m_genesis.kv 46 A32 _i_010000 ; 0x10 : mfc0, mtc0, tlbwi, tlbwr, tlbp, eret, wait
m_genesis.kv 47 A32 _bad ; 0x11 : UNDEFINED
m_genesis.kv 48 A32 _bad ; 0x12 : UNDEFINED
m_genesis.kv 49 A32 _bad ; 0x13 : UNDEFINED
m_genesis.kv 50 A32 _i_beql ; 0x14 : beql (010100??????????????????????????)
m_genesis.kv 51 A32 _i_bnel ; 0x15 : bnel (010101??????????????????????????)
m_genesis.kv 52 A32 _i_blezl ; 0x16 : blezl (010110??????????????????????????)
m_genesis.kv 53 A32 _i_bgtzl ; 0x17 : bgtzl (010111?????00000????????????????)
m_genesis.kv 54 A32 _bad ; 0x18 : UNDEFINED
m_genesis.kv 55 A32 _bad ; 0x19 : UNDEFINED
m_genesis.kv 56 A32 _bad ; 0x1a : UNDEFINED
m_genesis.kv 57 A32 _bad ; 0x1b : UNDEFINED
m_genesis.kv 58 A32 _i_mul ; 0x1c : mul (011100???????????????00000000010)
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 _i_lb ; 0x20 : lb (100000??????????????????????????)
m_genesis.kv 63 A32 _i_lh ; 0x21 : lh (100001??????????????????????????)
m_genesis.kv 64 A32 _i_lwl ; 0x22 : lwl (100010??????????????????????????)
m_genesis.kv 65 A32 _i_lw ; 0x23 : lw (100011??????????????????????????)
m_genesis.kv 66 A32 _i_lbu ; 0x24 : lbu (100100??????????????????????????)
m_genesis.kv 67 A32 _i_lhu ; 0x25 : lhu (100101??????????????????????????)
m_genesis.kv 68 A32 _i_lwr ; 0x26 : lwr (100110??????????????????????????)
m_genesis.kv 69 A32 _bad ; 0x27 : UNDEFINED
m_genesis.kv 70 A32 _i_sb ; 0x28 : sb (101000??????????????????????????)
m_genesis.kv 71 A32 _i_sh ; 0x29 : sh (101001??????????????????????????)
m_genesis.kv 72 A32 _i_swl ; 0x2a : swl (101010??????????????????????????)
m_genesis.kv 73 A32 _i_sw ; 0x2b : sw (101011??????????????????????????)
m_genesis.kv 74 A32 _bad ; 0x2c : UNDEFINED
m_genesis.kv 75 A32 _bad ; 0x2d : UNDEFINED
m_genesis.kv 76 A32 _i_swr ; 0x2e : swr (101110??????????????????????????)
m_genesis.kv 77 A32 _i_cache ; 0x2f : cache (101111??????????????????????????)
m_genesis.kv 78 A32 _i_ll ; 0x30 : ll (110000??????????????????????????)
m_genesis.kv 79 A32 _bad ; 0x31 : UNDEFINED
m_genesis.kv 80 A32 _bad ; 0x32 : UNDEFINED
m_genesis.kv 81 A32 _i_pref ; 0x33 : pref (110011??????????????????????????)
m_genesis.kv 82 A32 _bad ; 0x34 : UNDEFINED
m_genesis.kv 83 A32 _bad ; 0x35 : UNDEFINED
m_genesis.kv 84 A32 _bad ; 0x36 : UNDEFINED
m_genesis.kv 85 A32 _bad ; 0x37 : UNDEFINED
m_genesis.kv 86 A32 _i_sc ; 0x38 : sc (111000??????????????????????????)
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 align GRAIN, db 0x90
m_genesis.kv 96 _MFC0_Table:
m_genesis.kv 97 A32 _mfc0_r00 ; 0x00
m_genesis.kv 98 A32 _mfc0_r01 ; 0x01
m_genesis.kv 99 A32 _mfc0_r02 ; 0x02
m_genesis.kv 100 A32 _mfc0_r03 ; 0x03
m_genesis.kv 101 A32 _mfc0_r04 ; 0x04
m_genesis.kv 102 A32 _mfc0_r05 ; 0x05
m_genesis.kv 103 A32 _mfc0_r06 ; 0x06
m_genesis.kv 104 A32 _mfc0_r07 ; 0x07
m_genesis.kv 105 A32 _mfc0_r08 ; 0x08
m_genesis.kv 106 A32 _mfc0_r09 ; 0x09
m_genesis.kv 107 A32 _mfc0_r10 ; 0x0a
m_genesis.kv 108 A32 _mfc0_r11 ; 0x0b
m_genesis.kv 109 A32 _mfc0_r12 ; 0x0c
m_genesis.kv 110 A32 _mfc0_r13 ; 0x0d
m_genesis.kv 111 A32 _mfc0_r14 ; 0x0e
m_genesis.kv 112 A32 _mfc0_r15 ; 0x0f
m_genesis.kv 113 A32 _mfc0_r16 ; 0x10
m_genesis.kv 114 A32 _mfc0_r17 ; 0x11
m_genesis.kv 115 A32 _mfc0_r18 ; 0x12
m_genesis.kv 116 A32 _mfc0_r19 ; 0x13
m_genesis.kv 117 A32 _mfc0_r20 ; 0x14
m_genesis.kv 118 A32 _mfc0_r21 ; 0x15
m_genesis.kv 119 A32 _mfc0_r22 ; 0x16
m_genesis.kv 120 A32 _mfc0_r23 ; 0x17
m_genesis.kv 121 A32 _mfc0_r24 ; 0x18
m_genesis.kv 122 A32 _mfc0_r25 ; 0x19
m_genesis.kv 123 A32 _mfc0_r26 ; 0x1a
m_genesis.kv 124 A32 _mfc0_r27 ; 0x1b
m_genesis.kv 125 A32 _mfc0_r28 ; 0x1c
m_genesis.kv 126 A32 _mfc0_r29 ; 0x1d
m_genesis.kv 127 A32 _mfc0_r30 ; 0x1e
m_genesis.kv 128 A32 _mfc0_r31 ; 0x1f
m_genesis.kv 129 ;-----------------------------------------------------------------------------
m_genesis.kv 130 align GRAIN, db 0x90
m_genesis.kv 131 _MTC0_Table:
m_genesis.kv 132 A32 _mtc0_r00 ; 0x00
m_genesis.kv 133 A32 _mtc0_r01 ; 0x01
m_genesis.kv 134 A32 _mtc0_r02 ; 0x02
m_genesis.kv 135 A32 _mtc0_r03 ; 0x03
m_genesis.kv 136 A32 _mtc0_r04 ; 0x04
m_genesis.kv 137 A32 _mtc0_r05 ; 0x05
m_genesis.kv 138 A32 _mtc0_r06 ; 0x06
m_genesis.kv 139 A32 _mtc0_r07 ; 0x07
m_genesis.kv 140 A32 _mtc0_r08 ; 0x08
m_genesis.kv 141 A32 _mtc0_r09 ; 0x09
m_genesis.kv 142 A32 _mtc0_r10 ; 0x0a
m_genesis.kv 143 A32 _mtc0_r11 ; 0x0b
m_genesis.kv 144 A32 _mtc0_r12 ; 0x0c
m_genesis.kv 145 A32 _mtc0_r13 ; 0x0d
m_genesis.kv 146 A32 _mtc0_r14 ; 0x0e
m_genesis.kv 147 A32 _mtc0_r15 ; 0x0f
m_genesis.kv 148 A32 _mtc0_r16 ; 0x10
m_genesis.kv 149 A32 _mtc0_r17 ; 0x11
m_genesis.kv 150 A32 _mtc0_r18 ; 0x12
m_genesis.kv 151 A32 _mtc0_r19 ; 0x13
m_genesis.kv 152 A32 _mtc0_r20 ; 0x14
m_genesis.kv 153 A32 _mtc0_r21 ; 0x15
m_genesis.kv 154 A32 _mtc0_r22 ; 0x16
m_genesis.kv 155 A32 _mtc0_r23 ; 0x17
m_genesis.kv 156 A32 _mtc0_r24 ; 0x18
m_genesis.kv 157 A32 _mtc0_r25 ; 0x19
m_genesis.kv 158 A32 _mtc0_r26 ; 0x1a
m_genesis.kv 159 A32 _mtc0_r27 ; 0x1b
m_genesis.kv 160 A32 _mtc0_r28 ; 0x1c
m_genesis.kv 161 A32 _mtc0_r29 ; 0x1d
m_genesis.kv 162 A32 _mtc0_r30 ; 0x1e
m_genesis.kv 163 A32 _mtc0_r31 ; 0x1f
m_genesis.kv 164 ;-----------------------------------------------------------------------------
m_genesis.kv 165
m_genesis.kv 166 section .text
m_genesis.kv 167
m_genesis.kv 168 ;------------------------
m_genesis.kv 169 ; Invalid Instruction : |
m_genesis.kv 170 ;------------------------
m_genesis.kv 171 align GRAIN, db 0x90
m_genesis.kv 172 _bad:
m_genesis.kv 173 SetEXC EXC_RI ; Set the EXC_RI Exception
m_genesis.kv 174 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 175 ;-----------------------------------------------------------------------------
m_genesis.kv 176
m_genesis.kv 177 ;-----------------------------------------------------------------------------
m_genesis.kv 178 ; Eat 000000?????????????????????????? (R-Type) Instructions:
m_genesis.kv 179 ;-----------------------------------------------------------------------------
m_genesis.kv 180 align GRAIN, db 0x90
m_genesis.kv 181 _i_000000:
m_genesis.kv 182 mov eax, r_I ; Get the original instruction :
m_genesis.kv 183 and eax, 0x3F ; Get funct field, (lower 6 bits) ;
m_genesis.kv 184 JTABLE eax, _R_Table ; Dispatch on funct-field via R-Table.
m_genesis.kv 185 ;-----------------------------------------------------------------------------
m_genesis.kv 186
m_genesis.kv 187 ;-----------------------------------------------------------------------------
m_genesis.kv 188 ; Eat 000001?????QQQQQ???????????????? Branch Instructions :
m_genesis.kv 189 ; i.e. bltz, bgez, bltzl, bgezl, bltzal, bgezal
m_genesis.kv 190 ;-----------------------------------------------------------------------------
m_genesis.kv 191 align GRAIN, db 0x90
m_genesis.kv 192 _i_000001:
m_genesis.kv 193 mov eax, r_I ; Get the original instruction :
m_genesis.kv 194 shr eax, 16 ; Get the 5-bit field QQQQQ
m_genesis.kv 195 and eax, 0x1F ; which distinguishes these;
m_genesis.kv 196 JTABLE eax, _B_Table ; Dispatch via B-Table.
m_genesis.kv 197 ;-----------------------------------------------------------------------------
m_genesis.kv 198
m_genesis.kv 199 ;-----------------------------------------------------------------------------
m_genesis.kv 200 ; Eat 010000?????????????????????????? Misc. Instructions :
m_genesis.kv 201 ; mfc0, mtc0, tlbwi, tlbwr, tlbp, eret, wait
m_genesis.kv 202 ; PRIVILEGED (permitted in Kernel Mode only.)
m_genesis.kv 203 ;-----------------------------------------------------------------------------
m_genesis.kv 204 align GRAIN, db 0x90
m_genesis.kv 205 _i_010000:
m_genesis.kv 206 PRIVILEGED ; Permitted in Kernel Mode only.
m_genesis.kv 207 mov eax, r_I ; Get the original instruction :
m_genesis.kv 208 shr eax, 5 ; Get the top 27 bits
m_genesis.kv 209 cmp eax, 0x2100000 ; Equal 010000100000000000000000000..?
m_genesis.kv 210 je _tlbwi_tlbwr_tlbp_eret ; 010000100000000000000000000QQQQQ
m_genesis.kv 211 ;; At this point, we have either mfc0, mtc0, wait, or a bad instr:
m_genesis.kv 212 shr eax, 16 ; We already shifted by 5, so now 21:
m_genesis.kv 213 cmp eax, 0x200 ; ... are they equal to 0b01000000000 ?
m_genesis.kv 214 je _m_mfc0 ; mfc0 (01000000000?????????????????????)
m_genesis.kv 215 cmp eax, 0x204 ; ... are they equal to 0b01000000100 ?
m_genesis.kv 216 je _m_mtc0 ; mtc0 (01000000100?????????????????????)
m_genesis.kv 217 ;; Now determine if it is 'wait' (0100001???????????????????100000) :
m_genesis.kv 218 mov eax, r_I ; Get the original instruction :
m_genesis.kv 219 and eax, 0xFE00003F ; Get top 7 bits and bottom 6 bits only
m_genesis.kv 220 cmp eax, 0x42000020 ; Top must be 0b0100001, bottom 0b100000
m_genesis.kv 221 je _m_wait ; wait (0100001???????????????????100000)
m_genesis.kv 222 ;; Now, if it wasn't the 'wait' instruction, we must then have a turd:
m_genesis.kv 223 jmp _bad ; If we're here : undefined inst.
m_genesis.kv 224 ;-----------------------------------------------------------------------------
m_genesis.kv 225
m_genesis.kv 226 ;-----------------------------------------------------------------------------
m_genesis.kv 227 ; Eat 010000100000000000000000000QQQQQ Instructions (via _i_010000) :
m_genesis.kv 228 ; tlbwi, tlbwr, tlbp, eret
m_genesis.kv 229 ;-----------------------------------------------------------------------------
m_genesis.kv 230 align GRAIN, db 0x90
m_genesis.kv 231 _tlbwi_tlbwr_tlbp_eret:
m_genesis.kv 232 mov eax, r_I ; Get the original instruction :
m_genesis.kv 233 and eax, 0x1F ; Get the the 5-bit field QQQQQ from it
m_genesis.kv 234 JTABLE eax, _M_Table ; Dispatch via M-Table.
m_genesis.kv 235 ;-----------------------------------------------------------------------------
m_genesis.kv 236
m_genesis.kv 237 ;-----------------------------------------------------------------------------
m_genesis.kv 238 ; J -- Jump.
m_genesis.kv 239 ; Jumps to the calculated address.
m_genesis.kv 240 ; Operation: PC = nPC; nPC = (PC & 0xF0000000) | (target << 2);
m_genesis.kv 241 ; Syntax: j target
m_genesis.kv 242 ; Encoding: 0000 10ii iiii iiii iiii iiii iiii iiii
m_genesis.kv 243 ;-----------------------------------------------------------------------------
m_genesis.kv 244 align GRAIN, db 0x90
m_genesis.kv 245 _i_j:
m_genesis.kv 246 JType ; load J Field (ii..iii << 2)
m_genesis.kv 247 mov nPC, PC ; nPC := PC
m_genesis.kv 248 and nPC, 0xF0000000 ; keep only top 4 bits of nPC, zero rest
m_genesis.kv 249 or nPC, JTarg ; nPC := nPC | ( target << 2 )
m_genesis.kv 250 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 251 jmp _end_cycle
m_genesis.kv 252 ;-----------------------------------------------------------------------------
m_genesis.kv 253
m_genesis.kv 254 ;-----------------------------------------------------------------------------
m_genesis.kv 255 ; JAL -- Jump and link.
m_genesis.kv 256 ; Jumps to the calculated address and stores the return address in $31.
m_genesis.kv 257 ; Operation: $31 = PC + 8 (or nPC + 4);
m_genesis.kv 258 ; PC = nPC;
m_genesis.kv 259 ; nPC = (PC & 0xF0000000) | (target << 2);
m_genesis.kv 260 ; Syntax: jal target
m_genesis.kv 261 ; Encoding: 0000 11ii iiii iiii iiii iiii iiii iiii
m_genesis.kv 262 ;-----------------------------------------------------------------------------
m_genesis.kv 263 align GRAIN, db 0x90
m_genesis.kv 264 _i_jal:
m_genesis.kv 265 JType ; load J Field (ii..iii << 2)
m_genesis.kv 266 mov TMP, PC ; TMP := PC
m_genesis.kv 267 add TMP, 0x8 ; TMP := TMP + 8
m_genesis.kv 268 mov R(31), TMP ; Regs[31] := TMP
m_genesis.kv 269 sub TMP, 0x8 ; TMP := TMP - 8
m_genesis.kv 270 and TMP, 0xF0000000 ; keep only top 4 bits of TMP, zero rest
m_genesis.kv 271 or TMP, JTarg ; TMP := TMP | ( target << 2 )
m_genesis.kv 272 mov nPC, TMP ; nPC := TMP
m_genesis.kv 273 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 274 jmp _end_cycle
m_genesis.kv 275 ;-----------------------------------------------------------------------------
m_genesis.kv 276
m_genesis.kv 277 ;-----------------------------------------------------------------------------
m_genesis.kv 278 ; BEQ -- Branch on equal.
m_genesis.kv 279 ; Branches if the two registers are equal.
m_genesis.kv 280 ; Operation: if $s == $t advance_pc(offset << 2));
m_genesis.kv 281 ; else advance_pc(4);
m_genesis.kv 282 ; Syntax: beq $s, $t, offset
m_genesis.kv 283 ; Encoding: 0001 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 284 ;-----------------------------------------------------------------------------
m_genesis.kv 285 align GRAIN, db 0x90
m_genesis.kv 286 _i_beq:
m_genesis.kv 287 IType ; Load Imm, rS, rT Fields
m_genesis.kv 288 mov nPC, PC ; nPC := PC
m_genesis.kv 289 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 290 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 291 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 292 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 293 mov TMP, 0x4 ; TMP := 4
m_genesis.kv 294 cmove TMP, Imm ; If Regs[rS] = Regs[rT], TMP := Imm
m_genesis.kv 295 add nPC, TMP ; nPC := nPC + TMP
m_genesis.kv 296 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 297 jmp _end_cycle
m_genesis.kv 298 ;-----------------------------------------------------------------------------
m_genesis.kv 299
m_genesis.kv 300 ;-----------------------------------------------------------------------------
m_genesis.kv 301 ; BNE -- Branch on not equal.
m_genesis.kv 302 ; Branches if the two registers are not equal.
m_genesis.kv 303 ; Operation: if $s != $t advance_pc(offset << 2));
m_genesis.kv 304 ; else advance_pc(4);
m_genesis.kv 305 ; Syntax: bne $s, $t, offset
m_genesis.kv 306 ; Encoding: 0001 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 307 ;-----------------------------------------------------------------------------
m_genesis.kv 308 align GRAIN, db 0x90
m_genesis.kv 309 _i_bne:
m_genesis.kv 310 IType ; Load Imm, rS, rT Fields
m_genesis.kv 311 mov nPC, PC ; nPC := PC
m_genesis.kv 312 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 313 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 314 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 315 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 316 mov TMP, 0x4 ; TMP := 4
m_genesis.kv 317 cmovne TMP, Imm ; If Regs[rS] != Regs[rT], TMP := Imm
m_genesis.kv 318 add nPC, TMP ; nPC := nPC + TMP
m_genesis.kv 319 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 320 jmp _end_cycle
m_genesis.kv 321 ;-----------------------------------------------------------------------------
m_genesis.kv 322
m_genesis.kv 323 ;-----------------------------------------------------------------------------
m_genesis.kv 324 ; BLEZ -- Branch on less than or equal to zero.
m_genesis.kv 325 ; Branches if the register is less than or equal to zero
m_genesis.kv 326 ; Operation: if $s <= 0 advance_pc(offset << 2));
m_genesis.kv 327 ; else advance_pc(4);
m_genesis.kv 328 ; Syntax: blez $s, offset
m_genesis.kv 329 ; Encoding: 0001 10ss sss0 0000 iiii iiii iiii iiii
m_genesis.kv 330 ;-----------------------------------------------------------------------------
m_genesis.kv 331 align GRAIN, db 0x90
m_genesis.kv 332 _i_blez:
m_genesis.kv 333 IType_I_S_Only ; load rS and Imm Fields
m_genesis.kv 334 mov nPC, PC ; nPC := PC
m_genesis.kv 335 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 336 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 337 mov TMP, 0x4 ; TMP := 4
m_genesis.kv 338 cmp R(rS), 0 ; If Regs[rS] <= 0:
m_genesis.kv 339 cmovle TMP, Imm ; ... then TMP := Imm
m_genesis.kv 340 add nPC, TMP ; nPC := nPC + TMP
m_genesis.kv 341 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 342 jmp _end_cycle
m_genesis.kv 343 ;-----------------------------------------------------------------------------
m_genesis.kv 344
m_genesis.kv 345 ;-----------------------------------------------------------------------------
m_genesis.kv 346 ; BGTZ -- Branch on greater than zero.
m_genesis.kv 347 ; Branches if the register is greater than zero
m_genesis.kv 348 ; Operation: if $s > 0 advance_pc(offset << 2));
m_genesis.kv 349 ; else advance_pc(4);
m_genesis.kv 350 ; Syntax: bgtz $s, offset
m_genesis.kv 351 ; Encoding: 0001 11ss sss0 0000 iiii iiii iiii iiii
m_genesis.kv 352 ;-----------------------------------------------------------------------------
m_genesis.kv 353 align GRAIN, db 0x90
m_genesis.kv 354 _i_bgtz:
m_genesis.kv 355 IType_I_S_Only ; load rS and Imm Fields
m_genesis.kv 356 mov nPC, PC ; nPC := PC
m_genesis.kv 357 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 358 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 359 mov TMP, 0x4 ; TMP := 4
m_genesis.kv 360 cmp R(rS), 0 ; If Regs[rS] > 0:
m_genesis.kv 361 cmovg TMP, Imm ; ... then TMP := Imm
m_genesis.kv 362 add nPC, TMP ; nPC := nPC + TMP
m_genesis.kv 363 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 364 jmp _end_cycle
m_genesis.kv 365 ;-----------------------------------------------------------------------------
m_genesis.kv 366
m_genesis.kv 367 ;-----------------------------------------------------------------------------
m_genesis.kv 368 ; ADDI -- Add immediate (with overflow).
m_genesis.kv 369 ; Adds a register and a sign-extended immediate value and stores the
m_genesis.kv 370 ; result in a register
m_genesis.kv 371 ; Operation: $t = $s + imm; advance_pc(4);
m_genesis.kv 372 ; Syntax: addi $t, $s, imm
m_genesis.kv 373 ; Encoding: 0010 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 374 ;-----------------------------------------------------------------------------
m_genesis.kv 375 ; TODO: untested
m_genesis.kv 376 align GRAIN, db 0x90
m_genesis.kv 377 _i_addi:
m_genesis.kv 378 ; UNDONE_INST
m_genesis.kv 379 IType ; Load Imm, rS, rT Fields
m_genesis.kv 380 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 381 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 382 add TMP, Imm ; TMP := TMP + Imm
m_genesis.kv 383 ; TODO: detect and trap overflow
m_genesis.kv 384 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 385 jmp _end_cycle
m_genesis.kv 386 ;-----------------------------------------------------------------------------
m_genesis.kv 387
m_genesis.kv 388 ;-----------------------------------------------------------------------------
m_genesis.kv 389 ; ADDIU -- Add immediate unsigned (no overflow).
m_genesis.kv 390 ; Adds a register and a sign-extended immediate value and stores the
m_genesis.kv 391 ; result in a register
m_genesis.kv 392 ; Operation: $t = $s + imm; advance_pc(4);
m_genesis.kv 393 ; Syntax: addiu $t, $s, imm
m_genesis.kv 394 ; Encoding: 0010 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 395 ;-----------------------------------------------------------------------------
m_genesis.kv 396 align GRAIN, db 0x90
m_genesis.kv 397 _i_addiu:
m_genesis.kv 398 IType ; Load Imm, rS, rT Fields
m_genesis.kv 399 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 400 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 401 add TMP, Imm ; TMP := TMP + Imm
m_genesis.kv 402 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 403 jmp _end_cycle
m_genesis.kv 404 ;-----------------------------------------------------------------------------
m_genesis.kv 405
m_genesis.kv 406 ;-----------------------------------------------------------------------------
m_genesis.kv 407 ; SLTI -- Set on less than immediate (signed).
m_genesis.kv 408 ; If $s is less than immediate, $t is set to one. It gets zero otherwise.
m_genesis.kv 409 ; Operation: if $s < imm $t = 1; advance_pc(4);
m_genesis.kv 410 ; else $t = 0; advance_pc(4);
m_genesis.kv 411 ; Syntax: slti $t, $s, imm
m_genesis.kv 412 ; Encoding: 0010 10ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 413 ;-----------------------------------------------------------------------------
m_genesis.kv 414 align GRAIN, db 0x90
m_genesis.kv 415 _i_slti:
m_genesis.kv 416 IType ; Load Imm, rS, rT Fields
m_genesis.kv 417 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 418 xor TMP, TMP ; Clear TMP
m_genesis.kv 419 cmp R(rS), Imm ; CMP(R(rS), Imm)
m_genesis.kv 420 setl TMP_LowByte ; if $s <(sgn) imm then TMP := 1; else 0
m_genesis.kv 421 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 422 jmp _end_cycle
m_genesis.kv 423 ;-----------------------------------------------------------------------------
m_genesis.kv 424
m_genesis.kv 425 ;-----------------------------------------------------------------------------
m_genesis.kv 426 ; SLTIU -- Set on less than immediate unsigned.
m_genesis.kv 427 ; If $s is less than the unsigned immediate, $t is set to one.
m_genesis.kv 428 ; It gets zero otherwise.
m_genesis.kv 429 ; Operation: if $s < imm $t = 1; advance_pc(4);
m_genesis.kv 430 ; else $t = 0; advance_pc(4);
m_genesis.kv 431 ; Syntax: sltiu $t, $s, imm
m_genesis.kv 432 ; Encoding: 0010 11ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 433 ;-----------------------------------------------------------------------------
m_genesis.kv 434 ; Apparently even here we sign-extend the immediate.
m_genesis.kv 435 align GRAIN, db 0x90
m_genesis.kv 436 _i_sltiu:
m_genesis.kv 437 IType ; Load Imm, rS, rT Fields
m_genesis.kv 438 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 439 xor TMP, TMP ; Clear TMP
m_genesis.kv 440 cmp R(rS), Imm ; CMP(R(rS), Imm)
m_genesis.kv 441 setb TMP_LowByte ; if $s < imm then TMP := 1; else 0
m_genesis.kv 442 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 443 jmp _end_cycle
m_genesis.kv 444 ;-----------------------------------------------------------------------------
m_genesis.kv 445
m_genesis.kv 446 ;-----------------------------------------------------------------------------
m_genesis.kv 447 ; ANDI -- Bitwise AND immediate.
m_genesis.kv 448 ; Bitwise ANDs a register and an immediate value and stores the result
m_genesis.kv 449 ; in a register
m_genesis.kv 450 ; Operation: $t = $s & imm; advance_pc(4);
m_genesis.kv 451 ; Syntax: andi $t, $s, imm
m_genesis.kv 452 ; Encoding: 0011 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 453 ;-----------------------------------------------------------------------------
m_genesis.kv 454 align GRAIN, db 0x90
m_genesis.kv 455 _i_andi:
m_genesis.kv 456 IType ; Load Imm, rS, rT Fields
m_genesis.kv 457 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 458 and TMP, Imm ; TMP := TMP & Imm
m_genesis.kv 459 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 460 jmp _end_cycle
m_genesis.kv 461 ;-----------------------------------------------------------------------------
m_genesis.kv 462
m_genesis.kv 463 ;-----------------------------------------------------------------------------
m_genesis.kv 464 ; ORI -- Bitwise OR immediate.
m_genesis.kv 465 ; Bitwise OrS a register and an immediate value and stores the result
m_genesis.kv 466 ; in a register
m_genesis.kv 467 ; Operation: $t = $s | imm; advance_pc(4);
m_genesis.kv 468 ; Syntax: ori $t, $s, imm
m_genesis.kv 469 ; Encoding: 0011 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 470 ;-----------------------------------------------------------------------------
m_genesis.kv 471 align GRAIN, db 0x90
m_genesis.kv 472 _i_ori:
m_genesis.kv 473 IType ; Load Imm, rS, rT Fields
m_genesis.kv 474 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 475 or TMP, Imm ; TMP := TMP | Imm
m_genesis.kv 476 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 477 jmp _end_cycle
m_genesis.kv 478 ;-----------------------------------------------------------------------------
m_genesis.kv 479
m_genesis.kv 480 ;-----------------------------------------------------------------------------
m_genesis.kv 481 ; XORI -- Bitwise Exclusive Or immediate.
m_genesis.kv 482 ; Bitwise XOrS a register and an immediate value and stores the
m_genesis.kv 483 ; result in a register
m_genesis.kv 484 ; Operation: $t = $s ^ imm; advance_pc(4);
m_genesis.kv 485 ; Syntax: xori $t, $s, imm
m_genesis.kv 486 ; Encoding: 0011 10ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 487 ;-----------------------------------------------------------------------------
m_genesis.kv 488 align GRAIN, db 0x90
m_genesis.kv 489 _i_xori:
m_genesis.kv 490 IType ; Load Imm, rS, rT Fields
m_genesis.kv 491 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 492 xor TMP, Imm ; TMP := TMP ^ Imm
m_genesis.kv 493 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 494 jmp _end_cycle
m_genesis.kv 495 ;-----------------------------------------------------------------------------
m_genesis.kv 496
m_genesis.kv 497 ;-----------------------------------------------------------------------------
m_genesis.kv 498 ; LUI -- Load upper immediate.
m_genesis.kv 499 ; The immediate value is shifted left 16 bits and stored in the register.
m_genesis.kv 500 ; The lower 16 bits are zeroes.
m_genesis.kv 501 ; Operation: $t = (imm << 16); advance_pc(4);
m_genesis.kv 502 ; Syntax: lui $t, imm
m_genesis.kv 503 ; Encoding: 0011 11-- ---t tttt iiii iiii iiii iiii
m_genesis.kv 504 ;-----------------------------------------------------------------------------
m_genesis.kv 505 align GRAIN, db 0x90
m_genesis.kv 506 _i_lui:
m_genesis.kv 507 IType_I_T_Only ; Load Imm and rT Fields
m_genesis.kv 508 mov TMP, Imm ; TMP := Imm
m_genesis.kv 509 shl TMP, 16 ; TMP := TMP << 16
m_genesis.kv 510 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
m_genesis.kv 511 jmp _end_cycle
m_genesis.kv 512 ;-----------------------------------------------------------------------------
m_genesis.kv 513
m_genesis.kv 514 ;-----------------------------------------------------------------------------
m_genesis.kv 515 ; BEQL - Branch on Equal Likely.
m_genesis.kv 516 ; Compare registers, then do a PC-relative conditional branch;
m_genesis.kv 517 ; execute the delay slot only if the branch is taken.
m_genesis.kv 518 ; An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is
m_genesis.kv 519 ; added to the address of the instruction following the branch (not the
m_genesis.kv 520 ; branch itself), in the branch delay slot, to form a PC-relative effective
m_genesis.kv 521 ; target address. If the contents of rS and rT are equal, branch to the target
m_genesis.kv 522 ; address after the instruction in the delay slot is executed. If the branch
m_genesis.kv 523 ; is not taken, the instruction in the delay slot is not executed.
m_genesis.kv 524 ; Operation: if rS = rT then branch_likely
m_genesis.kv 525 ; Syntax: beql $s, $t, offset
m_genesis.kv 526 ; Encoding: 0101 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 527 ;-----------------------------------------------------------------------------
m_genesis.kv 528 align GRAIN, db 0x90
m_genesis.kv 529 _i_beql:
m_genesis.kv 530 IType ; Load Imm, rS, rT Fields
m_genesis.kv 531 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 532 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 533 jne _i_beql_not_taken ; If !(TMP = Regs[rT]) then NotTaken
m_genesis.kv 534 ; Taken:
m_genesis.kv 535 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 536 mov nPC, PC ; nPC := PC
m_genesis.kv 537 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 538 add nPC, Imm ; nPC := nPC + Offset
m_genesis.kv 539 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 540 jmp _end_cycle
m_genesis.kv 541 ; Not Taken:
m_genesis.kv 542 _i_beql_not_taken:
m_genesis.kv 543 add PC, 0x4 ; PC := PC + 4
m_genesis.kv 544 jmp _end_cycle
m_genesis.kv 545 ;-----------------------------------------------------------------------------
m_genesis.kv 546
m_genesis.kv 547 ;-----------------------------------------------------------------------------
m_genesis.kv 548 ; BNEL - Branch on Not Equal Likely.
m_genesis.kv 549 ; Compare registers, then do a PC-relative conditional branch;
m_genesis.kv 550 ; execute the delay slot only if the branch is taken.
m_genesis.kv 551 ; An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is
m_genesis.kv 552 ; added to the address of the instruction following the branch (not the
m_genesis.kv 553 ; branch itself), in the branch delay slot, to form a PC-relative effective
m_genesis.kv 554 ; target address. If the contents of rS and rT are NOT equal, branch to the
m_genesis.kv 555 ; target address after the instruction in the delay slot is executed. If the
m_genesis.kv 556 ; branch is not taken, the instruction in the delay slot is not executed.
m_genesis.kv 557 ; Operation: if rS != rT then branch_likely
m_genesis.kv 558 ; Syntax: bnel $s, $t, offset
m_genesis.kv 559 ; Encoding: 0101 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 560 ;-----------------------------------------------------------------------------
m_genesis.kv 561 align GRAIN, db 0x90
m_genesis.kv 562 _i_bnel:
m_genesis.kv 563 IType ; Load Imm, rS, rT Fields
m_genesis.kv 564 mov TMP, R(rS) ; TMP := Regs[rS]
m_genesis.kv 565 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
m_genesis.kv 566 je _i_bnel_not_taken ; If !(TMP != Regs[rT]) then NotTaken
m_genesis.kv 567 ; Taken:
m_genesis.kv 568 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 569 mov nPC, PC ; nPC := PC
m_genesis.kv 570 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 571 add nPC, Imm ; nPC := nPC + Offset
m_genesis.kv 572 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 573 jmp _end_cycle
m_genesis.kv 574 ; Not Taken:
m_genesis.kv 575 _i_bnel_not_taken:
m_genesis.kv 576 add PC, 0x4 ; PC := PC + 4
m_genesis.kv 577 jmp _end_cycle
m_genesis.kv 578 ;-----------------------------------------------------------------------------
m_genesis.kv 579
m_genesis.kv 580 ;-----------------------------------------------------------------------------
m_genesis.kv 581 ; BLEZL - Branch on Less Than or Equal to Zero Likely.
m_genesis.kv 582 ; Test a register, then do a PC-relative conditional branch;
m_genesis.kv 583 ; execute the delay slot only if the branch is taken.
m_genesis.kv 584 ; An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is
m_genesis.kv 585 ; added to the address of the instruction following the branch (not the branch
m_genesis.kv 586 ; itself), in the branch delay slot, to form a PC-relative effective target
m_genesis.kv 587 ; address. If the contents of rS are less than or equal to zero (sign bit is
m_genesis.kv 588 ; 1 or value is zero), branch to the effective target address after the
m_genesis.kv 589 ; instruction in the delay slot is executed. If the branch is not taken, the
m_genesis.kv 590 ; instruction in the delay slot is not executed.
m_genesis.kv 591 ; Operation: If rS <= 0 then branch_likely
m_genesis.kv 592 ; Syntax: bltzl $s, offset
m_genesis.kv 593 ; Encoding: 0101 10ss sss0 0000 iiii iiii iiii iiii
m_genesis.kv 594 ;-----------------------------------------------------------------------------
m_genesis.kv 595 align GRAIN, db 0x90
m_genesis.kv 596 _i_blezl:
m_genesis.kv 597 IType_S_Only ; load only rS Field just now
m_genesis.kv 598 cmp R(rS), 0 ; CMP(Regs[rS], 0)
m_genesis.kv 599 jnle _i_blezl_not_taken ; If !(Regs[rS] <= 0) then NotTaken
m_genesis.kv 600 ; Taken:
m_genesis.kv 601 IType_I_Only ; load only Imm Field just now
m_genesis.kv 602 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 603 mov nPC, PC ; nPC := PC
m_genesis.kv 604 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 605 add nPC, Imm ; nPC := nPC + Offset
m_genesis.kv 606 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 607 jmp _end_cycle
m_genesis.kv 608 ; Not Taken:
m_genesis.kv 609 _i_blezl_not_taken:
m_genesis.kv 610 add PC, 0x4 ; PC := PC + 4
m_genesis.kv 611 jmp _end_cycle
m_genesis.kv 612 ;-----------------------------------------------------------------------------
m_genesis.kv 613
m_genesis.kv 614 ;-----------------------------------------------------------------------------
m_genesis.kv 615 ; BGTZL - Branch on Greater Than Zero Likely.
m_genesis.kv 616 ; Test a register, then do a PC-relative conditional branch;
m_genesis.kv 617 ; execute the delay slot only if the branch is taken.
m_genesis.kv 618 ; An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is
m_genesis.kv 619 ; added to the address of the instruction following the branch (not the branch
m_genesis.kv 620 ; itself), in the branch delay slot, to form a PC-relative effective target
m_genesis.kv 621 ; address. If the contents of rS are greater than zero (sign bit is 0 but
m_genesis.kv 622 ; value not zero), branch to the effective target address after the
m_genesis.kv 623 ; instruction in the delay slot is executed. If the branch is not taken, the
m_genesis.kv 624 ; instruction in the delay slot is not executed.
m_genesis.kv 625 ; Operation: If rS > 0 then branch_likely
m_genesis.kv 626 ; Syntax: bgtzl $s, offset
m_genesis.kv 627 ; Encoding: 0101 11ss sss0 0000 iiii iiii iiii iiii
m_genesis.kv 628 ;-----------------------------------------------------------------------------
m_genesis.kv 629 align GRAIN, db 0x90
m_genesis.kv 630 _i_bgtzl:
m_genesis.kv 631 IType_S_Only ; load only rS Field just now
m_genesis.kv 632 cmp R(rS), 0 ; CMP(Regs[rS], 0)
m_genesis.kv 633 jng _i_bgtzl_not_taken ; If !(Regs[rS] > 0) then NotTaken
m_genesis.kv 634 ; Taken:
m_genesis.kv 635 IType_I_Only ; load only Imm Field just now
m_genesis.kv 636 SX18_4N Imm ; Sign Extend Imm * 4
m_genesis.kv 637 mov nPC, PC ; nPC := PC
m_genesis.kv 638 add nPC, 0x4 ; nPC := nPC + 4
m_genesis.kv 639 add nPC, Imm ; nPC := nPC + Offset
m_genesis.kv 640 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
m_genesis.kv 641 jmp _end_cycle
m_genesis.kv 642 ; Not Taken:
m_genesis.kv 643 _i_bgtzl_not_taken:
m_genesis.kv 644 add PC, 0x4 ; PC := PC + 4
m_genesis.kv 645 jmp _end_cycle
m_genesis.kv 646 ;-----------------------------------------------------------------------------
m_genesis.kv 647
m_genesis.kv 648 ;-----------------------------------------------------------------------------
m_genesis.kv 649 ; MUL - Multiply Word to Register.
m_genesis.kv 650 ; The 32-bit word value in rS is multiplied by the 32-bit value in rT,
m_genesis.kv 651 ; treating both operands as signed values, to produce a 64-bit result.
m_genesis.kv 652 ; The least significant 32 bits of the product are written to rD.
m_genesis.kv 653 ; The contents of HI and LO are UNPREDICTABLE after the operation.
m_genesis.kv 654 ; No arithmetic exception occurs under any circumstances.
m_genesis.kv 655 ; Syntax: mul $d, $s, $t
m_genesis.kv 656 ; Encoding: 0111 00ss ssst tttt dddd d000 0000 0010
m_genesis.kv 657 ;-----------------------------------------------------------------------------
m_genesis.kv 658 ; TODO: untested
m_genesis.kv 659 align GRAIN, db 0x90
m_genesis.kv 660 _i_mul:
m_genesis.kv 661 RType ; load rD, rS, rT Fields
m_genesis.kv 662 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 663 imul TMP, R(rS) ; TMP := TMP * Regs[rS] (Bottom 32 bits)
m_genesis.kv 664 Wr_Reg rD, TMP ; Regs[rD] := Bottom 32 bits of prod
m_genesis.kv 665 jmp _end_cycle
m_genesis.kv 666 ;-----------------------------------------------------------------------------
m_genesis.kv 667
m_genesis.kv 668 ;-----------------------------------------------------------------------------
m_genesis.kv 669 ; LB -- Load Byte.
m_genesis.kv 670 ; A byte is loaded into a register from the specified address.
m_genesis.kv 671 ; Operation: $t = MEM[$s + offset]; advance_pc(4);
m_genesis.kv 672 ; Syntax: lb $t, offset($s)
m_genesis.kv 673 ; Encoding: 1000 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 674 ;-----------------------------------------------------------------------------
m_genesis.kv 675 align GRAIN, db 0x90
m_genesis.kv 676 _i_lb:
m_genesis.kv 677 IType ; Load Imm, rS, rT Fields
m_genesis.kv 678 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 679 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 680 call _Virt_Read_Byte ; AL := Virt_Read_Byte(EAX)
m_genesis.kv 681 shl eax, 24 ; Shift left for sign-extension:
m_genesis.kv 682 sar eax, 24 ; Shift back right, dragging sign bit:
m_genesis.kv 683 Wr_Reg rT, EAX ; Regs[rT] := EAX
m_genesis.kv 684 jmp _end_cycle
m_genesis.kv 685 ;-----------------------------------------------------------------------------
m_genesis.kv 686
m_genesis.kv 687 ;-----------------------------------------------------------------------------
m_genesis.kv 688 ; LH - Load Halfword.
m_genesis.kv 689 ; Load a halfword from memory as a signed value.
m_genesis.kv 690 ; The contents of the 16-bit halfword at the memory location specified by the
m_genesis.kv 691 ; aligned effective address are fetched, sign-extended, and placed in rT.
m_genesis.kv 692 ; The 16-bit signed offset is added to the contents of rS to form the
m_genesis.kv 693 ; effective address. The effective address must be naturally-aligned.
m_genesis.kv 694 ; If the least-significant bit of the address is non-zero, an Address
m_genesis.kv 695 ; Error exception occurs
m_genesis.kv 696 ; Operation: $t = MEM[$s + offset]; advance_pc(4);
m_genesis.kv 697 ; Syntax: lh $t, offset($s)
m_genesis.kv 698 ; Encoding: 1000 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 699 ;-----------------------------------------------------------------------------
m_genesis.kv 700 ; NOTE: LHU is exactly same thing as LH, but without sign-extend.
m_genesis.kv 701 align GRAIN, db 0x90
m_genesis.kv 702 _i_lh:
m_genesis.kv 703 IType ; Load Imm, rS, rT Fields
m_genesis.kv 704 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 705 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 706 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 707 bt Imm, 0 ; Get low bit of vAddr
m_genesis.kv 708 jnc _i_lh_aligned_ok ; If zero, vAddr was properly aligned;
m_genesis.kv 709 SetEXC EXC_AdEL ; If vAddr was NOT properly aligned:
m_genesis.kv 710 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 711 _i_lh_aligned_ok: ; Load is to proceed normally:
m_genesis.kv 712 mov ecx, Imm ; Save vAddr to ECX
m_genesis.kv 713 xor TMP, TMP ; Clear TMP, where we will put the HW
m_genesis.kv 714 %ifdef LITTLE_ENDIAN
m_genesis.kv 715 ;; Read the low byte of the HW first:
m_genesis.kv 716 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr)
m_genesis.kv 717 mov TMP, eax ; TMP := eax (save the low byte)
m_genesis.kv 718 ;; Now read the high byte:
m_genesis.kv 719 mov eax, ecx ; Restore the original saved vAddr
m_genesis.kv 720 or eax, 1 ; Will read vAddr + 1
m_genesis.kv 721 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr + 1)
m_genesis.kv 722 %else
m_genesis.kv 723 or Imm, 1 ; First, read vAddr + 1 :
m_genesis.kv 724 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr + 1)
m_genesis.kv 725 mov TMP, eax ; TMP := eax (save low byte)
m_genesis.kv 726 mov eax, ecx ; Restore the original saved vAddr
m_genesis.kv 727 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr)
m_genesis.kv 728 %endif
m_genesis.kv 729 shl eax, 8 ; eax := eax << 8
m_genesis.kv 730 or eax, TMP ; eax := eax | TMP (high | low)
m_genesis.kv 731 shl eax, 16 ; left shift eax to put the HW on top
m_genesis.kv 732 sar eax, 16 ; right shift it back, to sign-extend.
m_genesis.kv 733 Wr_Reg rT, eax ; Regs[rT] := EAX (write back result)
m_genesis.kv 734 jmp _end_cycle
m_genesis.kv 735 ;-----------------------------------------------------------------------------
m_genesis.kv 736
m_genesis.kv 737 ;-----------------------------------------------------------------------------
m_genesis.kv 738 ; LWL - Load Word Left.
m_genesis.kv 739 ; Load the most-significant part of a word as a signed value from an unaligned
m_genesis.kv 740 ; memory address.
m_genesis.kv 741 ; Operation: $t = $t MERGE MEM[$s + offset]; advance_pc(4);
m_genesis.kv 742 ; Syntax: lwl $t, offset($s)
m_genesis.kv 743 ; Encoding: 1000 10ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 744 ;-----------------------------------------------------------------------------
m_genesis.kv 745 align GRAIN, db 0x90
m_genesis.kv 746 _i_lwl:
m_genesis.kv 747 IType ; Load Imm, rS, rT Fields
m_genesis.kv 748 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 749 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 750 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 751 mov TMP, R(rT) ; TMP := Regs[rT] (old reg value)
m_genesis.kv 752 mov AUX, Imm ; Save the original unaligned address
m_genesis.kv 753 and Imm, ~(0x3) ; Clear bottom two bits of address
m_genesis.kv 754 call _Virt_Read_Word ; EAX := Virt_Read_Word(EAX (aligned))
m_genesis.kv 755 ;; Proceed with write. EAX : old word, TMP : new word, ebx : still rT
m_genesis.kv 756 mov ecx, AUX ; ecx := original unaligned address
m_genesis.kv 757 and ecx, 0x3 ; keep only bottom two bits of it
m_genesis.kv 758 shl ecx, 3 ; ecx := ecx (8 * (addr[0..2]))
m_genesis.kv 759 shl eax, cl ; left shift eax (orig word) by above
m_genesis.kv 760 xor ecx, 24 ; ecx := 24 - ecx
m_genesis.kv 761 mov AUX, 0xFFFFFF ; AUX := 0xFFFFFF
m_genesis.kv 762 shr AUX, cl ; AUX := AUX >> cl
m_genesis.kv 763 and TMP, AUX ; TMP := TMP & AUX
m_genesis.kv 764 or TMP, eax ; TMP := TMP | eax (the writeback value)
m_genesis.kv 765 Wr_Reg rT, TMP ; Regs[rT] := TMP (the writeback value)
m_genesis.kv 766 jmp _end_cycle
m_genesis.kv 767 ;-----------------------------------------------------------------------------
m_genesis.kv 768
m_genesis.kv 769 ;-----------------------------------------------------------------------------
m_genesis.kv 770 ; LW -- Load Word.
m_genesis.kv 771 ; The contents of the 32-bit word at the memory location specified by the
m_genesis.kv 772 ; aligned effective address are fetched, signextended to the register length
m_genesis.kv 773 ; if necessary, and placed in register rT. The 16-bit signed offset is added
m_genesis.kv 774 ; to the contents of the base to form the effective address.
m_genesis.kv 775 ; Operation: $t = MEM[$s + offset]; advance_pc(4);
m_genesis.kv 776 ; Syntax: lw $t, offset($s)
m_genesis.kv 777 ; Encoding: 1000 11ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 778 ;-----------------------------------------------------------------------------
m_genesis.kv 779 align GRAIN, db 0x90
m_genesis.kv 780 _i_lw:
m_genesis.kv 781 IType ; Load Imm, rS, rT Fields
m_genesis.kv 782 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 783 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 784 call _Virt_Read_Word ; EAX := Virt_Read_Word(EAX)
m_genesis.kv 785 Wr_Reg rT, EAX ; Regs[rT] := EAX
m_genesis.kv 786 jmp _end_cycle
m_genesis.kv 787 ;-----------------------------------------------------------------------------
m_genesis.kv 788
m_genesis.kv 789 ;-----------------------------------------------------------------------------
m_genesis.kv 790 ; LBU - Load Byte Unsigned.
m_genesis.kv 791 ; Load a byte from memory as an unsigned value.
m_genesis.kv 792 ; The contents of the 8-bit byte at the memory location specified by the
m_genesis.kv 793 ; effective address are fetched, zero-extended, and placed in rT.
m_genesis.kv 794 ; The 16-bit signed offset is added to the contents of rS to form the
m_genesis.kv 795 ; effective address.
m_genesis.kv 796 ; Operation: $t = MEM[$s + offset]; advance_pc(4);
m_genesis.kv 797 ; Syntax: lbu $t, offset($s)
m_genesis.kv 798 ; Encoding: 1001 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 799 ;-----------------------------------------------------------------------------
m_genesis.kv 800 align GRAIN, db 0x90
m_genesis.kv 801 _i_lbu:
m_genesis.kv 802 IType ; Load Imm, rS, rT Fields
m_genesis.kv 803 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 804 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 805 call _Virt_Read_Byte ; AL := Virt_Read_Byte(EAX)
m_genesis.kv 806 Wr_Reg rT, EAX ; Regs[rT] := EAX
m_genesis.kv 807 jmp _end_cycle
m_genesis.kv 808 ;-----------------------------------------------------------------------------
m_genesis.kv 809
m_genesis.kv 810 ;-----------------------------------------------------------------------------
m_genesis.kv 811 ; LHU - Load Halfword Unsigned.
m_genesis.kv 812 ; Load a halfword from memory as an unsigned value.
m_genesis.kv 813 ; The contents of the 16-bit halfword at the memory location specified by the
m_genesis.kv 814 ; aligned effective address are fetched, zero-extended, and placed in reg rT.
m_genesis.kv 815 ; The 16-bit signed offset is added to the contents of register rS to form the
m_genesis.kv 816 ; effective address. The effective address must be naturally-aligned.
m_genesis.kv 817 ; If the least-significant bit of the address is non-zero,
m_genesis.kv 818 ; an Address Error exception occurs.
m_genesis.kv 819 ; Operation: $t = MEM[$s + offset]; advance_pc(4);
m_genesis.kv 820 ; Syntax: lhu $t, offset($s)
m_genesis.kv 821 ; Encoding: 1001 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 822 ;-----------------------------------------------------------------------------
m_genesis.kv 823 ; NOTE: exactly same thing as LH, but WITHOUT sign-extend.
m_genesis.kv 824 align GRAIN, db 0x90
m_genesis.kv 825 _i_lhu:
m_genesis.kv 826 IType ; Load Imm, rS, rT Fields
m_genesis.kv 827 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 828 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 829 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 830 bt Imm, 0 ; Get low bit of vAddr
m_genesis.kv 831 jnc _i_lhu_aligned_ok ; If zero, vAddr was properly aligned;
m_genesis.kv 832 SetEXC EXC_AdEL ; If vAddr was NOT properly aligned:
m_genesis.kv 833 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 834 _i_lhu_aligned_ok: ; Load is to proceed normally:
m_genesis.kv 835 mov ecx, Imm ; Save vAddr to ECX
m_genesis.kv 836 xor TMP, TMP ; Clear TMP, where we will put the HW
m_genesis.kv 837 %ifdef LITTLE_ENDIAN
m_genesis.kv 838 ;; Read the low byte of the HW first:
m_genesis.kv 839 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr + 1)
m_genesis.kv 840 mov TMP, eax ; TMP := eax (save the low byte)
m_genesis.kv 841 ;; Now read the high byte:
m_genesis.kv 842 mov eax, ecx ; Restore the original saved vAddr
m_genesis.kv 843 or eax, 1 ; Will read vAddr + 1
m_genesis.kv 844 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr + 1)
m_genesis.kv 845 %else
m_genesis.kv 846 or Imm, 1 ; First, read vAddr + 1 :
m_genesis.kv 847 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr + 1)
m_genesis.kv 848 mov TMP, eax ; TMP := eax (save low byte)
m_genesis.kv 849 mov eax, ecx ; Restore the original saved vAddr
m_genesis.kv 850 call _Virt_Read_Byte ; EAX := Virt_Read_Byte(vAddr)
m_genesis.kv 851 %endif
m_genesis.kv 852 shl eax, 8 ; eax := eax << 8
m_genesis.kv 853 or eax, TMP ; eax := eax | TMP (high | low)
m_genesis.kv 854 Wr_Reg rT, eax ; Regs[rT] := EAX (write back result)
m_genesis.kv 855 jmp _end_cycle
m_genesis.kv 856 ;-----------------------------------------------------------------------------
m_genesis.kv 857
m_genesis.kv 858 ;-----------------------------------------------------------------------------
m_genesis.kv 859 ; LWL - Load Word Right.
m_genesis.kv 860 ; Load the least-significant part of a word from an unaligned memory address
m_genesis.kv 861 ; as a signed value. The 16-bit signed offset is added to the contents of rS
m_genesis.kv 862 ; to form an effective address (EffAddr). EffAddr is the address of the
m_genesis.kv 863 ; least-significant of 4 consecutive bytes forming a word (W) in memory
m_genesis.kv 864 ; starting at an arbitrary byte boundary. A part of W, the least-significant
m_genesis.kv 865 ; 1 to 4 bytes, is in the aligned word containing EffAddr. This part of W is
m_genesis.kv 866 ; loaded into the least-significant (right) part of the word in register rT.
m_genesis.kv 867 ; The remaining most-significant part of the word in register rT is unchanged.
m_genesis.kv 868 ; Executing both LWR and LWL, in either order, delivers a sign-extended word
m_genesis.kv 869 ; value in the destination register.
m_genesis.kv 870 ; Operation: $t = $t MERGE MEM[$s + offset]; advance_pc(4);
m_genesis.kv 871 ; Syntax: lwr $t, offset($s)
m_genesis.kv 872 ; Encoding: 1001 10ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 873 ;-----------------------------------------------------------------------------
m_genesis.kv 874 align GRAIN, db 0x90
m_genesis.kv 875 _i_lwr:
m_genesis.kv 876 IType ; Load Imm, rS, rT Fields
m_genesis.kv 877 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 878 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 879 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 880 mov TMP, R(rT) ; TMP := Regs[rT] (value to write)
m_genesis.kv 881 mov AUX, Imm ; Save the original unaligned address
m_genesis.kv 882 and Imm, ~(0x3) ; Clear bottom two bits of address
m_genesis.kv 883 call _Virt_Read_Word ; EAX := Virt_Read_Word(EAX (aligned))
m_genesis.kv 884 ;; Proceed with write. EAX : old word, TMP : new word, ebx : still rT
m_genesis.kv 885 mov ecx, AUX ; ecx := original unaligned address
m_genesis.kv 886 and ecx, 0x3 ; keep only bottom two bits of it
m_genesis.kv 887 shl ecx, 3 ; ecx := ecx (8 * (addr[0..2]))
m_genesis.kv 888 mov AUX, 0xFFFFFF00 ; AUX := 0xFFFFFF00
m_genesis.kv 889 shl AUX, cl ; AUX := AUX << cl
m_genesis.kv 890 and TMP, AUX ; TMP := TMP & AUX
m_genesis.kv 891 xor ecx, 24 ; ecx := 24 - ecx
m_genesis.kv 892 shr eax, cl ; right shift eax (orig word) by above
m_genesis.kv 893 or TMP, eax ; TMP := TMP | eax (the writeback value)
m_genesis.kv 894 Wr_Reg rT, TMP ; Regs[rT] := TMP (the writeback value)
m_genesis.kv 895 jmp _end_cycle
m_genesis.kv 896 ;-----------------------------------------------------------------------------
m_genesis.kv 897
m_genesis.kv 898 ;-----------------------------------------------------------------------------
m_genesis.kv 899 ; SB -- Store Byte.
m_genesis.kv 900 ; The least significant byte of $t is stored at the specified address.
m_genesis.kv 901 ; Operation: MEM[$s + offset] = (0xff & $t); advance_pc(4);
m_genesis.kv 902 ; Syntax: sb $t, offset($s)
m_genesis.kv 903 ; Encoding: 1010 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 904 ;-----------------------------------------------------------------------------
m_genesis.kv 905 align GRAIN, db 0x90
m_genesis.kv 906 _i_sb:
m_genesis.kv 907 IType ; Load Imm, rS, rT Fields
m_genesis.kv 908 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 909 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 910 mov TMP, R(rT) ; TMP (EDX) := Regs[rT]
m_genesis.kv 911 and TMP, 0xFF ; Keep only low byte of TMP
m_genesis.kv 912 call _Virt_Write_Byte ; Virt_Write_Byte(EAX, DL)
m_genesis.kv 913 jmp _end_cycle
m_genesis.kv 914 ;-----------------------------------------------------------------------------
m_genesis.kv 915
m_genesis.kv 916 ;-----------------------------------------------------------------------------
m_genesis.kv 917 ; SH - Store Halfword.
m_genesis.kv 918 ; Store a halfword to memory. The least-significant 16-bit halfword of
m_genesis.kv 919 ; register rT is stored in memory at the location specified by the aligned
m_genesis.kv 920 ; effective address. The 16-bit signed offset is added to the contents of rS
m_genesis.kv 921 ; to form the effective address.
m_genesis.kv 922 ; The effective address must be naturally-aligned. If the least-significant
m_genesis.kv 923 ; bit of the address is non-zero, an Address Error exception occurs.
m_genesis.kv 924 ; Operation: MEM[$s + offset] = $t; advance_pc(4);
m_genesis.kv 925 ; Syntax: sh $t, offset($s)
m_genesis.kv 926 ; Encoding: 1010 01ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 927 ;-----------------------------------------------------------------------------
m_genesis.kv 928 align GRAIN, db 0x90
m_genesis.kv 929 _i_sh:
m_genesis.kv 930 IType ; Load Imm, rS, rT Fields
m_genesis.kv 931 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 932 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 933 bt Imm, 0 ; Get low bit of vAddr
m_genesis.kv 934 jnc _i_sh_aligned_ok ; If zero, vAddr was properly aligned;
m_genesis.kv 935 SetEXC EXC_AdES ; If vAddr was NOT properly aligned:
m_genesis.kv 936 jmp _Handle_Exception ; Go straight to exception handler.
m_genesis.kv 937 _i_sh_aligned_ok:
m_genesis.kv 938 mov AUX, Imm ; Save Imm (vAddr) to AUX
m_genesis.kv 939 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 940 mov ecx, R(rT) ; ecx := Regs[rT] (HW to be written)
m_genesis.kv 941 mov TMP, ecx ; TMP := ecx
m_genesis.kv 942 %ifdef LITTLE_ENDIAN
m_genesis.kv 943 and TMP, 0xFF ; isolate low byte
m_genesis.kv 944 call _Virt_Write_Byte ; Virt_Write_Byte(vAddr, DL)
m_genesis.kv 945 mov TMP, ecx ; TMP := the whole HW again
m_genesis.kv 946 and TMP, 0xFF00 ; isolate high byte
m_genesis.kv 947 shr TMP, 8 ; TMP := TMP >> 8 (get high byte)
m_genesis.kv 948 %else ;; Big-Endian
m_genesis.kv 949 shr TMP, 8 ; TMP := TMP >> 8 (get high byte)
m_genesis.kv 950 call _Virt_Write_Byte ; Virt_Write_Byte(vAddr, DL)
m_genesis.kv 951 mov TMP, ecx ; TMP := ecx again, now for low byte
m_genesis.kv 952 and TMP, 0xFF ; isolate low byte
m_genesis.kv 953 %endif
m_genesis.kv 954 mov eax, AUX ; restore vAddr from AUX
m_genesis.kv 955 or eax, 1 ; set bottom bit, for vAddr + 1
m_genesis.kv 956 call _Virt_Write_Byte ; Virt_Write_Byte(vAddr + 1, DL)
m_genesis.kv 957 jmp _end_cycle
m_genesis.kv 958 ;-----------------------------------------------------------------------------
m_genesis.kv 959
m_genesis.kv 960 ;-----------------------------------------------------------------------------
m_genesis.kv 961 ; SWL - Store Word Left.
m_genesis.kv 962 ; Store the most-significant part of a word to an unaligned memory address.
m_genesis.kv 963 ; Operation: MEM[$s + offset] = $t; advance_pc(4);
m_genesis.kv 964 ; Syntax: swl $t, offset($s)
m_genesis.kv 965 ; Encoding: 1010 10ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 966 ;-----------------------------------------------------------------------------
m_genesis.kv 967 align GRAIN, db 0x90
m_genesis.kv 968 _i_swl:
m_genesis.kv 969 IType ; Load Imm, rS, rT Fields
m_genesis.kv 970 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 971 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 972 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 973 mov TMP, R(rT) ; TMP := Regs[rT] (old reg value)
m_genesis.kv 974 ;; rT (ebx) is not needed any more, can be reused
m_genesis.kv 975 mov AUX, Imm ; Save the original unaligned address
m_genesis.kv 976 and Imm, ~(0x3) ; Clear bottom two bits of address
m_genesis.kv 977 mov ebx, Imm ; Save the aligned address for writeback
m_genesis.kv 978 call _Virt_Read_Word ; EAX := Virt_Read_Word(EAX (aligned))
m_genesis.kv 979 ;; Proceed with write. EAX : old word, TMP : new word, ebx : WB addr.
m_genesis.kv 980 mov ecx, AUX ; ecx := original unaligned address
m_genesis.kv 981 and ecx, 0x3 ; keep only bottom two bits
m_genesis.kv 982 shl ecx, 3 ; ecx := ecx (8 * (addr[0..2]))
m_genesis.kv 983 shr TMP, cl ; right shift TMP by above
m_genesis.kv 984 xor ecx, 24 ; ecx := 24 - ecx
m_genesis.kv 985 mov AUX, 0xFFFFFF00 ; AUX := 0xFFFFFF00
m_genesis.kv 986 shl AUX, cl ; AUX := AUX << cl
m_genesis.kv 987 and eax, AUX ; eax := eax & AUX
m_genesis.kv 988 or TMP, eax ; TMP := TMP | eax (the writeback value)
m_genesis.kv 989 mov eax, ebx ; restore aligned address for writeback
m_genesis.kv 990 call _Virt_Write_Word ; Virt_Write_Word(EAX, TMP)
m_genesis.kv 991 jmp _end_cycle
m_genesis.kv 992 ;-----------------------------------------------------------------------------
m_genesis.kv 993
m_genesis.kv 994 ;-----------------------------------------------------------------------------
m_genesis.kv 995 ; SW -- Store Word.
m_genesis.kv 996 ; The contents of $t is stored at the specified address.
m_genesis.kv 997 ; The effective address must be naturally-aligned.
m_genesis.kv 998 ; If either of the 2 least-significant bits of the address is non-zero,
m_genesis.kv 999 ; an Address Error exception occurs.
m_genesis.kv 1000 ; Operation: MEM[$s + offset] = $t; advance_pc(4);
m_genesis.kv 1001 ; Syntax: sw $t, offset($s)
m_genesis.kv 1002 ; Encoding: 1010 11ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 1003 ;-----------------------------------------------------------------------------
m_genesis.kv 1004 align GRAIN, db 0x90
m_genesis.kv 1005 _i_sw:
m_genesis.kv 1006 IType ; Load Imm, rS, rT Fields
m_genesis.kv 1007 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 1008 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 1009 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 1010 call _Virt_Write_Word ; Virt_Write_Word(EAX, TMP)
m_genesis.kv 1011 jmp _end_cycle
m_genesis.kv 1012 ;-----------------------------------------------------------------------------
m_genesis.kv 1013
m_genesis.kv 1014 ;-----------------------------------------------------------------------------
m_genesis.kv 1015 ; SWR - Store Word Right.
m_genesis.kv 1016 ; Store the least-significant part of a word to an unaligned memory address.
m_genesis.kv 1017 ; Operation: MEM[$s + offset] = $t; advance_pc(4);
m_genesis.kv 1018 ; Syntax: swr $t, offset($s)
m_genesis.kv 1019 ; Encoding: 1011 10ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 1020 ;-----------------------------------------------------------------------------
m_genesis.kv 1021 align GRAIN, db 0x90
m_genesis.kv 1022 _i_swr:
m_genesis.kv 1023 IType ; Load Imm, rS, rT Fields
m_genesis.kv 1024 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 1025 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 1026 ;; rS (ecx) is not needed any more, can be reused
m_genesis.kv 1027 mov TMP, R(rT) ; TMP := Regs[rT] (value to write)
m_genesis.kv 1028 ;; rT (ebx) is not needed any more, can be reused
m_genesis.kv 1029 mov AUX, Imm ; Save the original unaligned address
m_genesis.kv 1030 and Imm, ~(0x3) ; Clear bottom two bits of address
m_genesis.kv 1031 mov ebx, Imm ; Save the aligned address for writeback
m_genesis.kv 1032 call _Virt_Read_Word ; EAX := Virt_Read_Word(EAX (aligned))
m_genesis.kv 1033 ;; Proceed with write. EAX : old word, TMP : new word, ebx : WB addr.
m_genesis.kv 1034 mov ecx, AUX ; ecx := original unaligned address
m_genesis.kv 1035 and ecx, 0x3 ; keep only bottom two bits
m_genesis.kv 1036 shl ecx, 3 ; ecx := ecx * 8
m_genesis.kv 1037 mov AUX, 0xFFFFFF ; AUX := 0xFFFFFF
m_genesis.kv 1038 shr AUX, cl ; AUX := AUX >> cl
m_genesis.kv 1039 and eax, AUX ; eax := eax & AUX
m_genesis.kv 1040 xor ecx, 24 ; ecx := 24 - ecx (24 - 8 * (addr[0..2]))
m_genesis.kv 1041 shl TMP, cl ; left shift TMP (value to write) by above
m_genesis.kv 1042 or TMP, eax ; TMP := TMP | eax (the writeback value)
m_genesis.kv 1043 mov eax, ebx ; restore aligned address for writeback
m_genesis.kv 1044 call _Virt_Write_Word ; Virt_Write_Word(EAX, TMP)
m_genesis.kv 1045 jmp _end_cycle
m_genesis.kv 1046 ;-----------------------------------------------------------------------------
m_genesis.kv 1047
m_genesis.kv 1048 ;-----------------------------------------------------------------------------
m_genesis.kv 1049 ; CACHE.
m_genesis.kv 1050 ; Operation: This is a NOP in this emulator.
m_genesis.kv 1051 ; Syntax: cache $t, offset($s)
m_genesis.kv 1052 ; Encoding: 1011 11ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 1053 ; PRIVILEGED (permitted in Kernel Mode only.)
m_genesis.kv 1054 ;-----------------------------------------------------------------------------
m_genesis.kv 1055 align GRAIN, db 0x90
m_genesis.kv 1056 _i_cache:
m_genesis.kv 1057 ; no fields
m_genesis.kv 1058 PRIVILEGED ; Permitted in Kernel Mode only.
m_genesis.kv 1059 jmp _end_cycle
m_genesis.kv 1060 ;-----------------------------------------------------------------------------
m_genesis.kv 1061
m_genesis.kv 1062 ;-----------------------------------------------------------------------------
m_genesis.kv 1063 ; LL - Load Linked Word.
m_genesis.kv 1064 ; Load a word from memory for an atomic read-modify-write.
m_genesis.kv 1065 ; The contents of the 32-bit word at the memory location specified by the
m_genesis.kv 1066 ; aligned effective address are fetched and written into register rT.
m_genesis.kv 1067 ; The 16-bit signed offset is added to the contents of rS to form
m_genesis.kv 1068 ; an effective address.
m_genesis.kv 1069 ; Operation: $t = MEM[$s + offset]; llbit = 1; advance_pc(4);
m_genesis.kv 1070 ; Syntax: ll $t, offset($s)
m_genesis.kv 1071 ; Encoding: 1100 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 1072 ;-----------------------------------------------------------------------------
m_genesis.kv 1073 align GRAIN, db 0x90
m_genesis.kv 1074 _i_ll:
m_genesis.kv 1075 IType ; Load Imm, rS, rT Fields
m_genesis.kv 1076 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 1077 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 1078 call _Virt_Read_Word ; EAX := Virt_Read_Word(EAX)
m_genesis.kv 1079 Wr_Reg rT, EAX ; Regs[rT] := EAX
m_genesis.kv 1080 Flg_On LL_Bit ; Set the LL_Bit Flag
m_genesis.kv 1081 jmp _end_cycle
m_genesis.kv 1082 ;-----------------------------------------------------------------------------
m_genesis.kv 1083
m_genesis.kv 1084 ;-----------------------------------------------------------------------------
m_genesis.kv 1085 ; PREF - Prefetch.
m_genesis.kv 1086 ; Operation: This is a NOP in this emulator.
m_genesis.kv 1087 ; Syntax: pref $t, offset($s)
m_genesis.kv 1088 ; Encoding: 1100 11ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 1089 ;-----------------------------------------------------------------------------
m_genesis.kv 1090 align GRAIN, db 0x90
m_genesis.kv 1091 _i_pref:
m_genesis.kv 1092 ; no fields
m_genesis.kv 1093 jmp _end_cycle
m_genesis.kv 1094 ;-----------------------------------------------------------------------------
m_genesis.kv 1095
m_genesis.kv 1096 ;-----------------------------------------------------------------------------
m_genesis.kv 1097 ; SC - Store Conditional Word.
m_genesis.kv 1098 ; Store a word to memory to complete an atomic read-modify-write.
m_genesis.kv 1099 ; The 32-bit word in rT is conditionally stored in memory at the location
m_genesis.kv 1100 ; specified by the aligned effective address.
m_genesis.kv 1101 ; The 16-bit signed offset is added to the contents of rS to form an
m_genesis.kv 1102 ; effective address
m_genesis.kv 1103 ; Operation: if llbit == 1 then: MEM[$s + offset] = $t; rt = 1; advance_pc(4);
m_genesis.kv 1104 ; else: rt = 0; advance_pc(4);
m_genesis.kv 1105 ; Syntax: sc $t, offset($s)
m_genesis.kv 1106 ; Encoding: 1110 00ss ssst tttt iiii iiii iiii iiii
m_genesis.kv 1107 ;-----------------------------------------------------------------------------
m_genesis.kv 1108 align GRAIN, db 0x90
m_genesis.kv 1109 _i_sc:
m_genesis.kv 1110 IType ; Load Imm, rS, rT Fields
m_genesis.kv 1111 Flg_Get LL_Bit ; CF := LL_Bit
m_genesis.kv 1112 jnc _i_sc_not_taken ; If LL_Bit = 0, then do not store; else:
m_genesis.kv 1113 SX16 Imm ; Sign-extend the Imm offset
m_genesis.kv 1114 add Imm, R(rS) ; Imm (EAX) := Imm + Regs[rS] (vAddr)
m_genesis.kv 1115 mov TMP, R(rT) ; TMP := Regs[rT]
m_genesis.kv 1116 call _Virt_Write_Word ; Virt_Write_Word(EAX, TMP)
m_genesis.kv 1117 mov R(rT), 1 ; Regs[rT] := 1 ('yes, stored word')
m_genesis.kv 1118 jmp _i_sc_done ; Done.
m_genesis.kv 1119 _i_sc_not_taken:
m_genesis.kv 1120 mov R(rT), 0 ; Regs[rT] := 0 ('no, did not store')
m_genesis.kv 1121 _i_sc_done:
m_genesis.kv 1122 jmp _end_cycle
m_genesis.kv 1123 ;-----------------------------------------------------------------------------