-
+ 40EF74622647A11AC973984A9F831AD39BBEC47EAC267E3F62FB30E36058AC4B01074B97585E9B36E0B32DEB7344EC4C5AA6585E9571BAA2E0432E8D78DEB254
m/mipsinst/r_instrs.asm
(0 . 0)(1 . 662)
4043 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4044 ;; ;;
4045 ;; This file is part of 'M', a MIPS system emulator. ;;
4046 ;; ;;
4047 ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;;
4048 ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;;
4049 ;; ;;
4050 ;; You do not have, nor can you ever acquire the right to use, copy or ;;
4051 ;; distribute this software ; Should you use this software for any purpose, ;;
4052 ;; or copy and distribute it to anyone or in any manner, you are breaking ;;
4053 ;; the laws of whatever soi-disant jurisdiction, and you promise to ;;
4054 ;; continue doing so for the indefinite future. In any case, please ;;
4055 ;; always : read and understand any software ; verify any PGP signatures ;;
4056 ;; that you use - for any purpose. ;;
4057 ;; ;;
4058 ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;;
4059 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4060
4061 ;; TODO: 1) Traps in ADD and SUB (gcc 4.8.1 doesn't seem to use. but do exist)
4062 ;; 2) Tests!!!
4063
4064 ;----------------------------
4065 ; R-Type MIPS Instructions: |
4066 ;----------------------------
4067
4068 ;-----------------------------------------------------------------------------
4069 section .rodata
4070 align GRAIN, db 0x90
4071 _R_Table:
4072 A32 _r_sll ; 0x00 : sll (000000????????????????????000000)
4073 A32 _bad ; 0x01 : UNDEFINED
4074 A32 _r_srl ; 0x02 : srl (000000????????????????????000010)
4075 A32 _r_sra ; 0x03 : sra (000000????????????????????000011)
4076 A32 _r_sllv ; 0x04 : sllv (000000????????????????????000100)
4077 A32 _bad ; 0x05 : UNDEFINED
4078 A32 _r_srlv ; 0x06 : srlv (000000????????????????????000110)
4079 A32 _r_srav ; 0x07 : srav (000000????????????????????000111)
4080 A32 _r_jr ; 0x08 : jr (000000????????????????????001000)
4081 A32 _r_jalr ; 0x09 : jalr (000000????????????????????001001)
4082 A32 _r_movz ; 0x0a : movz (000000???????????????00000001010)
4083 A32 _r_movn ; 0x0b : movn (000000???????????????00000001011)
4084 A32 _r_syscall ; 0x0c : syscall (000000????????????????????001100)
4085 A32 _bad ; 0x0d : UNDEFINED
4086 A32 _bad ; 0x0e : UNDEFINED
4087 A32 _r_sync ; 0x0f : sync (000000????????????????????001111)
4088 A32 _r_mfhi ; 0x10 : mfhi (000000????????????????????010000)
4089 A32 _r_mthi ; 0x11 : mthi (000000????????????????????010001)
4090 A32 _r_mflo ; 0x12 : mflo (000000????????????????????010010)
4091 A32 _r_mtlo ; 0x13 : mtlo (000000????????????????????010011)
4092 A32 _bad ; 0x14 : UNDEFINED
4093 A32 _bad ; 0x15 : UNDEFINED
4094 A32 _bad ; 0x16 : UNDEFINED
4095 A32 _bad ; 0x17 : UNDEFINED
4096 A32 _r_mult ; 0x18 : mult (000000????????????????????011000)
4097 A32 _r_multu ; 0x19 : multu (000000????????????????????011001)
4098 A32 _r_div ; 0x1a : div (000000????????????????????011010)
4099 A32 _r_divu ; 0x1b : divu (000000????????????????????011011)
4100 A32 _bad ; 0x1c : UNDEFINED
4101 A32 _bad ; 0x1d : UNDEFINED
4102 A32 _bad ; 0x1e : UNDEFINED
4103 A32 _bad ; 0x1f : UNDEFINED
4104 A32 _r_add ; 0x20 : add (000000????????????????????100000)
4105 A32 _r_addu ; 0x21 : addu (000000????????????????????100001)
4106 A32 _r_sub ; 0x22 : sub (000000????????????????????100010)
4107 A32 _r_subu ; 0x23 : subu (000000????????????????????100011)
4108 A32 _r_and ; 0x24 : and (000000????????????????????100100)
4109 A32 _r_or ; 0x25 : or (000000????????????????????100101)
4110 A32 _r_xor ; 0x26 : xor (000000????????????????????100110)
4111 A32 _r_nor ; 0x27 : nor (000000????????????????????100111)
4112 A32 _bad ; 0x28 : UNDEFINED
4113 A32 _bad ; 0x29 : UNDEFINED
4114 A32 _r_slt ; 0x2a : slt (000000????????????????????101010)
4115 A32 _r_sltu ; 0x2b : sltu (000000????????????????????101011)
4116 A32 _bad ; 0x2c : UNDEFINED
4117 A32 _bad ; 0x2d : UNDEFINED
4118 A32 _bad ; 0x2e : UNDEFINED
4119 A32 _bad ; 0x2f : UNDEFINED
4120 A32 _bad ; 0x30 : UNDEFINED
4121 A32 _bad ; 0x31 : UNDEFINED
4122 A32 _bad ; 0x32 : UNDEFINED
4123 A32 _bad ; 0x33 : UNDEFINED
4124 A32 _r_teq ; 0x34 : teq (000000????????????????????110100)
4125 A32 _bad ; 0x35 : UNDEFINED
4126 A32 _r_tne ; 0x36 : tne (000000????????????????????110110)
4127 A32 _bad ; 0x37 : UNDEFINED
4128 A32 _bad ; 0x38 : UNDEFINED
4129 A32 _bad ; 0x39 : UNDEFINED
4130 A32 _bad ; 0x3a : UNDEFINED
4131 A32 _bad ; 0x3b : UNDEFINED
4132 A32 _bad ; 0x3c : UNDEFINED
4133 A32 _bad ; 0x3d : UNDEFINED
4134 A32 _bad ; 0x3e : UNDEFINED
4135 A32 _bad ; 0x3f : UNDEFINED
4136 ;-----------------------------------------------------------------------------
4137
4138 section .text
4139
4140 ;-----------------------------------------------------------------------------
4141 ; SLL -- Shift left logical.
4142 ; Shifts a register value left by the shift amount listed in the instruction
4143 ; and places the result in a third register. Zeroes are shifted in.
4144 ; Operation: $d = $t << h; advance_pc(4);
4145 ; Syntax: sll $d, $t, h
4146 ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0000
4147 ;-----------------------------------------------------------------------------
4148 align GRAIN, db 0x90
4149 _r_sll:
4150 RType_D_T_Shamt ; load rS, rT, Shamt Fields
4151 mov TMP, R(rT) ; TMP := Regs[rT]
4152 shl TMP, cl ; TMP := TMP << CL (Shamt is in ECX)
4153 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4154 jmp _end_cycle
4155 ;-----------------------------------------------------------------------------
4156
4157 ;-----------------------------------------------------------------------------
4158 ; SRL -- Shift right logical.
4159 ; Shifts a register value right by the shift amount (shamt) and places the
4160 ; value in the destination register. Zeroes are shifted in.
4161 ; Operation: $d = $t >> h; advance_pc(4);
4162 ; Syntax: srl $d, $t, h
4163 ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0010
4164 ;-----------------------------------------------------------------------------
4165 align GRAIN, db 0x90
4166 _r_srl:
4167 RType_D_T_Shamt ; load rS, rT, Shamt Fields
4168 mov TMP, R(rT) ; TMP := Regs[rT]
4169 shr TMP, cl ; TMP := TMP >> CL (Shamt is in ECX)
4170 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4171 jmp _end_cycle
4172 ;-----------------------------------------------------------------------------
4173
4174 ;-----------------------------------------------------------------------------
4175 ; SRA -- Shift right arithmetic.
4176 ; Shifts a register value right by the shift amount (shamt) and places the
4177 ; value in the destination register. The sign bit is shifted in.
4178 ; Operation: $d = $t >> h; advance_pc(4);
4179 ; Syntax: sra $d, $t, h
4180 ; Encoding: 0000 00-- ---t tttt dddd dhhh hh00 0011
4181 ;-----------------------------------------------------------------------------
4182 align GRAIN, db 0x90
4183 _r_sra:
4184 RType_D_T_Shamt ; load rS, rT, Shamt Fields
4185 mov TMP, R(rT) ; TMP := Regs[rT]
4186 sar TMP, cl ; TMP := TMP >>(sgn) CL (Shamt is in ECX)
4187 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4188 jmp _end_cycle
4189 ;-----------------------------------------------------------------------------
4190
4191 ;-----------------------------------------------------------------------------
4192 ; SLLV -- Shift left logical variable.
4193 ; Shifts a register value left by the value in a second register and places
4194 ; the result in a third register. Zeroes are shifted in.
4195 ; Operation: $d = $t << $s; advance_pc(4);
4196 ; Syntax: sllv $d, $t, $s
4197 ; Encoding: 0000 00ss ssst tttt dddd d--- --00 0100
4198 ;-----------------------------------------------------------------------------
4199 align GRAIN, db 0x90
4200 _r_sllv:
4201 RType ; load rD, rS, rT Fields
4202 mov ecx, R(rS) ; Now CL is the shift amount
4203 mov TMP, R(rT) ; TMP := Regs[rT]
4204 shl TMP, cl ; TMP := TMP << CL
4205 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4206 jmp _end_cycle
4207 ;-----------------------------------------------------------------------------
4208
4209 ;-----------------------------------------------------------------------------
4210 ; SRLV -- Shift right logical variable.
4211 ; Shifts a register value right by the amount specified in $s and places the
4212 ; value in the destination register. Zeroes are shifted in.
4213 ; Operation: $d = $t >> $s; advance_pc(4);
4214 ; Syntax: srlv $d, $t, $s
4215 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 0110
4216 ;-----------------------------------------------------------------------------
4217 align GRAIN, db 0x90
4218 _r_srlv:
4219 RType ; load rD, rS, rT Fields
4220 mov ecx, R(rS) ; Now CL is the shift amount
4221 mov TMP, R(rT) ; TMP := Regs[rT]
4222 shr TMP, cl ; TMP := TMP >> CL
4223 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4224 jmp _end_cycle
4225 ;-----------------------------------------------------------------------------
4226
4227 ;-----------------------------------------------------------------------------
4228 ; SRAV - Shift Word Right Arithmetic Variable.
4229 ; Execute an arithmetic right-shift of a word by a variable number of bits.
4230 ; The contents of the low-order 32-bit word of rT are shifted right,
4231 ; duplicating the sign-bit (bit 31) in the emptied bits; the word result is
4232 ; placed in rD. The bit-shift amount is specified by the low-order 5 bits
4233 ; of rS.
4234 ; Operation: $d = $t >> $s; advance_pc(4);
4235 ; Syntax: srav $d, $t, $s
4236 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 0111
4237 ;-----------------------------------------------------------------------------
4238 align GRAIN, db 0x90
4239 _r_srav:
4240 RType ; load rD, rS, rT Fields
4241 mov ecx, R(rS) ; Now CL is the shift amount
4242 mov TMP, R(rT) ; TMP := Regs[rT]
4243 sar TMP, cl ; TMP := TMP >> CL (extends sign bit)
4244 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4245 jmp _end_cycle
4246 ;-----------------------------------------------------------------------------
4247
4248 ;-----------------------------------------------------------------------------
4249 ; JR -- Jump register.
4250 ; Jump to the address contained in register $s
4251 ; Operation: PC = nPC; nPC = $s;
4252 ; Syntax: jr $s
4253 ; Encoding: 0000 00ss sss0 0000 0000 0000 0000 1000
4254 ;-----------------------------------------------------------------------------
4255 align GRAIN, db 0x90
4256 _r_jr:
4257 RType_S_Only ; Load rS Field
4258 mov nPC, R(rS) ; nPC := Regs[rS]
4259 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
4260 jmp _end_cycle
4261 ;-----------------------------------------------------------------------------
4262
4263 ;-----------------------------------------------------------------------------
4264 ; JALR - Jump and Link Register.
4265 ; Execute a procedure call to an instruction address in a register.
4266 ; Place the return address link in rD. The return link is the address of the
4267 ; second instruction following the branch, where execution continues after a
4268 ; procedure call. Jump to the effective target address in rS. Execute the
4269 ; instruction that follows the jump, in the branch delay slot, before
4270 ; executing the jump itself.
4271 ; Operation: $d = PC + 8; PC = nPC; nPC = $s
4272 ; Syntax: jalr $s
4273 ; Encoding: 0000 00ss sss0 0000 dddd 0000 0000 1001
4274 ;-----------------------------------------------------------------------------
4275 align GRAIN, db 0x90
4276 _r_jalr:
4277 RType_S_D_Only ; Load rD and rS Fields
4278 mov nPC, R(rS) ; nPC := Regs[rS]
4279 mov TMP, PC ; TMP := PC
4280 add TMP, 0x8 ; TMP := TMP + 8
4281 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4282 Flg_On InDelaySlot ; Set 'Delay Slot' Flag.
4283 jmp _end_cycle
4284 ;-----------------------------------------------------------------------------
4285
4286 ;-----------------------------------------------------------------------------
4287 ; MOVZ - Move Conditional on Zero.
4288 ; Conditionally move a register after testing a register value.
4289 ; If the value in rT is equal to zero, then the contents of rS are placed
4290 ; into rD.
4291 ; Operation: if $t = 0 then $d = $s
4292 ; Syntax: movz $d, $s, $t
4293 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 1010
4294 ;-----------------------------------------------------------------------------
4295 ; TODO: measure if the cmov is actually faster than a branch here !
4296 ; TODO: untested
4297 align GRAIN, db 0x90
4298 _r_movz:
4299 ; UNDONE_INST
4300 RType ; load rD, rS, rT Fields
4301 mov TMP, R(rT) ; TMP := Regs[rT]
4302 test TMP, TMP ; Set Z flag if TMP = 0
4303 mov TMP, R(rD) ; First, move Regs[rD] to TMP
4304 cmovz TMP, R(rS) ; If Z flag set, overwrite with Regs[rS]
4305 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4306 jmp _end_cycle
4307 ;-----------------------------------------------------------------------------
4308
4309 ;-----------------------------------------------------------------------------
4310 ; MOVN - Move Conditional on Not Zero.
4311 ; Conditionally move a register after testing a register value.
4312 ; If the value in rT is NOT equal to zero, then the contents of rS are placed
4313 ; into rD.
4314 ; Operation: if $t != 0 then $d = $s
4315 ; Syntax: movn $d, $s, $t
4316 ; Encoding: 0000 00ss ssst tttt dddd d000 0000 1011
4317 ;-----------------------------------------------------------------------------
4318 ; TODO: measure if the cmov is actually faster than a branch here !
4319 ; TODO: untested
4320 align GRAIN, db 0x90
4321 _r_movn:
4322 ; UNDONE_INST
4323 RType ; load rD, rS, rT Fields
4324 mov TMP, R(rT) ; TMP := Regs[rT]
4325 test TMP, TMP ; Set Z flag if TMP = 0
4326 mov TMP, R(rD) ; First, move Regs[rD] to TMP
4327 cmovnz TMP, R(rS) ; If Z not set, overwrite with Regs[rS]
4328 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4329 jmp _end_cycle
4330 ;-----------------------------------------------------------------------------
4331
4332 ;-----------------------------------------------------------------------------
4333 ; SYSCALL -- System call.
4334 ; Generates a software interrupt.
4335 ; Operation: advance_pc(4);
4336 ; Syntax: syscall
4337 ; Encoding: 0000 00-- ---- ---- ---- ---- --00 1100
4338 ;-----------------------------------------------------------------------------
4339 align GRAIN, db 0x90
4340 _r_syscall:
4341 ; no fields
4342 SetEXC EXC_SYS ; Set the EXC_SYS Exception
4343 jmp _Handle_Exception ; Go straight to exception handler.
4344 ;-----------------------------------------------------------------------------
4345
4346 ;-----------------------------------------------------------------------------
4347 ; SYNC - Synchronize Shared Memory.
4348 ; Operation: This is a NOP in this emulator.
4349 ; Syntax: sync
4350 ; Encoding: 0000 0000 0000 0000 0000 0000 0000 1111
4351 ;-----------------------------------------------------------------------------
4352 align GRAIN, db 0x90
4353 _r_sync:
4354 jmp _end_cycle
4355 ;-----------------------------------------------------------------------------
4356
4357 ;-----------------------------------------------------------------------------
4358 ; MFHI -- Move from HI.
4359 ; The contents of special register HI are moved to the specified register.
4360 ; Operation: $d = $HI; advance_pc(4);
4361 ; Syntax: mfhi $d
4362 ; Encoding: 0000 0000 0000 0000 dddd d000 0001 0000
4363 ;-----------------------------------------------------------------------------
4364 align GRAIN, db 0x90
4365 _r_mfhi:
4366 RType_D_Only ; Load rD Field
4367 mov TMP, Sr(HI) ; TMP := Sr(HI)
4368 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4369 jmp _end_cycle
4370 ;-----------------------------------------------------------------------------
4371
4372 ;-----------------------------------------------------------------------------
4373 ; MTHI - Move to HI Register.
4374 ; The contents of rS are loaded to the special register HI.
4375 ; Operation: $HI = $s
4376 ; Syntax: mthi $s
4377 ; Encoding: 0000 00ss sss0 0000 0000 0000 0001 0001
4378 ;-----------------------------------------------------------------------------
4379 align GRAIN, db 0x90
4380 _r_mthi:
4381 RType_S_Only ; Load rS Field
4382 mov TMP, R(rS) ; TMP := Regs[rS]
4383 mov Sr(HI), TMP ; HI := TMP
4384 jmp _end_cycle
4385 ;-----------------------------------------------------------------------------
4386
4387 ;-----------------------------------------------------------------------------
4388 ; MFLO -- Move from LO.
4389 ; The contents of register LO are moved to the specified register.
4390 ; Operation: $d = $LO; advance_pc(4);
4391 ; Syntax: mflo $d
4392 ; Encoding: 0000 0000 0000 0000 dddd d000 0001 0010
4393 ;-----------------------------------------------------------------------------
4394 align GRAIN, db 0x90
4395 _r_mflo:
4396 RType_D_Only ; Load rD Field
4397 mov TMP, Sr(LO) ; TMP := Sr(LO)
4398 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4399 jmp _end_cycle
4400 ;-----------------------------------------------------------------------------
4401
4402 ;-----------------------------------------------------------------------------
4403 ; MTLO - Move to LO.
4404 ; The contents of rS are loaded to the special register LO.
4405 ; Operation: $LO = $s
4406 ; Syntax: mtlo $s
4407 ; Encoding: 0000 00ss sss0 0000 0000 0000 0001 0011
4408 ;-----------------------------------------------------------------------------
4409 align GRAIN, db 0x90
4410 _r_mtlo:
4411 RType_S_Only ; Load rS Field
4412 mov TMP, R(rS) ; TMP := Regs[rS]
4413 mov Sr(LO), TMP ; LO := TMP
4414 jmp _end_cycle
4415 ;-----------------------------------------------------------------------------
4416
4417 ;-----------------------------------------------------------------------------
4418 ; MULT -- Multiply signed.
4419 ; Multiplies $s by $t and stores the result in $HI:$LO.
4420 ; Operation: $HI:$LO = $s * $t; advance_pc(4);
4421 ; Syntax: mult $s, $t
4422 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1000
4423 ;-----------------------------------------------------------------------------
4424 align GRAIN, db 0x90
4425 _r_mult:
4426 RType_S_T_Only
4427 mov eax, R(rT) ; eax := Regs[rT]
4428 imul R(rS) ; edx:eax := Regs[rS] * eax (signed)
4429 mov Sr(LO), eax ; LO := Bottom 32 bits of product
4430 mov Sr(HI), edx ; HI := Top 32 bits of product
4431 jmp _end_cycle
4432 ;-----------------------------------------------------------------------------
4433
4434 ;-----------------------------------------------------------------------------
4435 ; MULTU -- Multiply unsigned.
4436 ; Multiplies $s by $t and stores the result in $HI:$LO.
4437 ; Operation: $HI:$LO = $s * $t; advance_pc(4);
4438 ; Syntax: multu $s, $t
4439 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1001
4440 ;-----------------------------------------------------------------------------
4441 align GRAIN, db 0x90
4442 _r_multu:
4443 RType_S_T_Only ; Load rS and rT Fields
4444 mov eax, R(rT) ; eax := Regs[rT]
4445 mul R(rS) ; edx:eax := Regs[rS] * eax (unsigned)
4446 mov Sr(LO), eax ; LO := Bottom 32 bits of product
4447 mov Sr(HI), edx ; HI := Top 32 bits of product
4448 jmp _end_cycle
4449 ;-----------------------------------------------------------------------------
4450
4451 ;-----------------------------------------------------------------------------
4452 ; DIV -- Divide signed.
4453 ; Divides $s by $t and stores the quotient in $LO and the remainder in $HI
4454 ; Operation: $LO = $s / $t; $HI = $s % $t; advance_pc(4);
4455 ; Syntax: div $s, $t
4456 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1010
4457 ;-----------------------------------------------------------------------------
4458 ; TODO: detect div0 and other special cases
4459 align GRAIN, db 0x90
4460 _r_div:
4461 RType_S_T_Only ; Load rS and rT Fields
4462 mov eax, R(rS) ; eax := Regs[rS]
4463 cdq ; extend sign of eax into edx
4464 cmp R(rT), 0 ; test for div0
4465 je _r_div_div0 ; div0 is undefined result
4466 idiv R(rT) ; edx:eax / Regs[rT]; edx := r, eax := q
4467 mov Sr(LO), eax ; LO := edx:eax /(signed) ecx (quotient)
4468 mov Sr(HI), edx ; HI := edx:eax %(signed) ecx (remainder)
4469 _r_div_div0:
4470 jmp _end_cycle
4471 ;-----------------------------------------------------------------------------
4472
4473 ;-----------------------------------------------------------------------------
4474 ; DIVU -- Divide unsigned.
4475 ; Divides $s by $t and stores the quotient in $LO and the remainder in $HI
4476 ; Operation: $LO = $s / $t; $HI = $s % $t; advance_pc(4);
4477 ; Syntax: divu $s, $t
4478 ; Encoding: 0000 00ss ssst tttt 0000 0000 0001 1011
4479 ;-----------------------------------------------------------------------------
4480 ; TODO: detect div0 and other special cases
4481 align GRAIN, db 0x90
4482 _r_divu:
4483 RType_S_T_Only ; Load rS and rT Fields
4484 xor edx, edx ; edx := 0
4485 mov eax, R(rS) ; eax := Regs[rS]
4486 cmp R(rT), 0 ; test for div0
4487 je _r_divu_div0 ; div0 is undefined result
4488 div R(rT) ; edx:eax / Regs[rT]; edx := r, eax := q
4489 mov Sr(LO), eax ; LO := edx:eax / ecx (quotient)
4490 mov Sr(HI), edx ; HI := edx:eax % ecx (remainder)
4491 _r_divu_div0:
4492 jmp _end_cycle
4493 ;-----------------------------------------------------------------------------
4494
4495 ;-----------------------------------------------------------------------------
4496 ; ADD -- Add (with overflow).
4497 ; Adds two registers and stores the result in a register
4498 ; Operation: $d = $s + $t; advance_pc(4);
4499 ; Syntax: add $d, $s, $t
4500 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0000
4501 ;-----------------------------------------------------------------------------
4502 align GRAIN, db 0x90
4503 _r_add:
4504 RType ; load rD, rS, rT Fields
4505 mov TMP, R(rS) ; TMP := Regs[rS]
4506 add TMP, R(rT) ; TMP := Regs[rS] + Regs[rT]
4507 ; TODO: detect/trap overflow
4508 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4509 jmp _end_cycle
4510 ;-----------------------------------------------------------------------------
4511
4512 ;-----------------------------------------------------------------------------
4513 ; ADDU -- Add unsigned (no overflow).
4514 ; Adds two registers and stores the result in a register
4515 ; Operation: $d = $s + $t; advance_pc(4);
4516 ; Syntax: addu $d, $s, $t
4517 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0001
4518 ;-----------------------------------------------------------------------------
4519 align GRAIN, db 0x90
4520 _r_addu:
4521 RType ; load rD, rS, rT Fields
4522 mov TMP, R(rS) ; TMP := Regs[rS]
4523 add TMP, R(rT) ; TMP := Regs[rS] + Regs[rT]
4524 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4525 jmp _end_cycle
4526 ;-----------------------------------------------------------------------------
4527
4528 ;-----------------------------------------------------------------------------
4529 ; SUB -- Subtract.
4530 ; Subtracts two registers and stores the result in a register
4531 ; Operation: $d = $s - $t; advance_pc(4);
4532 ; Syntax: sub $d, $s, $t
4533 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0010
4534 ;-----------------------------------------------------------------------------
4535 align GRAIN, db 0x90
4536 _r_sub:
4537 RType ; load rD, rS, rT Fields
4538 mov TMP, R(rS) ; TMP := Regs[rS]
4539 sub TMP, R(rT) ; TMP := Regs[rS] - Regs[rT]
4540 ; TODO: detect and trap overflow
4541 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4542 jmp _end_cycle
4543 ;-----------------------------------------------------------------------------
4544
4545 ;-----------------------------------------------------------------------------
4546 ; SUBU -- Subtract unsigned.
4547 ; Subtracts two registers and stores the result in a register
4548 ; Operation: $d = $s - $t; advance_pc(4);
4549 ; Syntax: subu $d, $s, $t
4550 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0011
4551 ;-----------------------------------------------------------------------------
4552 align GRAIN, db 0x90
4553 _r_subu:
4554 RType ; load rD, rS, rT Fields
4555 mov TMP, R(rS) ; TMP := Regs[rS]
4556 sub TMP, R(rT) ; TMP := Regs[rS] - Regs[rT]
4557 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4558 jmp _end_cycle
4559 ;-----------------------------------------------------------------------------
4560
4561 ;-----------------------------------------------------------------------------
4562 ; AND -- Bitwise AND.
4563 ; Bitwise ANDs two registers and stores the result in a register
4564 ; Operation: $d = $s & $t; advance_pc(4);
4565 ; Syntax: and $d, $s, $t
4566 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0100
4567 ;-----------------------------------------------------------------------------
4568 align GRAIN, db 0x90
4569 _r_and:
4570 RType ; load rD, rS, rT Fields
4571 mov TMP, R(rS) ; TMP := Regs[rS]
4572 and TMP, R(rT) ; TMP := TMP & Regs[rT]
4573 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4574 jmp _end_cycle
4575 ;-----------------------------------------------------------------------------
4576
4577 ;-----------------------------------------------------------------------------
4578 ; OR -- Bitwise OR.
4579 ; Bitwise logical ORs two registers and stores the result in a register
4580 ; Operation: $d = $s | $t; advance_pc(4);
4581 ; Syntax: or $d, $s, $t
4582 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0101
4583 ;-----------------------------------------------------------------------------
4584 align GRAIN, db 0x90
4585 _r_or:
4586 RType ; load rD, rS, rT Fields
4587 mov TMP, R(rS) ; TMP := Regs[rS]
4588 or TMP, R(rT) ; TMP := TMP | Regs[rT]
4589 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4590 jmp _end_cycle
4591 ;-----------------------------------------------------------------------------
4592
4593 ;-----------------------------------------------------------------------------
4594 ; XOR -- Bitwise Exclusive OR.
4595 ; Exclusive ORs two registers and stores the result in a register
4596 ; Operation: $d = $s ^ $t; advance_pc(4);
4597 ; Syntax: xor $d, $s, $t
4598 ; Encoding: 0000 00ss ssst tttt dddd d--- --10 0110
4599 ;-----------------------------------------------------------------------------
4600 align GRAIN, db 0x90
4601 _r_xor:
4602 RType ; load rD, rS, rT Fields
4603 mov TMP, R(rS) ; TMP := Regs[rS]
4604 xor TMP, R(rT) ; TMP := TMP ^ Regs[rT]
4605 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4606 jmp _end_cycle
4607 ;-----------------------------------------------------------------------------
4608
4609 ;-----------------------------------------------------------------------------
4610 ; NOR - Not OR.
4611 ; Do a bitwise logical NOT OR.
4612 ; The contents of rS are combined with the contents of rT in a bitwise logical
4613 ; NOR operation. The result is placed into rD.
4614 ; Operation: $d = $s NOR $t
4615 ; Syntax: nor $d, $s, $t
4616 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 0111
4617 ;-----------------------------------------------------------------------------
4618 align GRAIN, db 0x90
4619 _r_nor:
4620 RType ; load rD, rS, rT Fields
4621 mov TMP, R(rS) ; TMP := Regs[rS]
4622 or TMP, R(rT) ; TMP := TMP | Regs[rT]
4623 not TMP ; TMP := ~TMP
4624 Wr_Reg rD, TMP ; Regs[rD] := TMP (result)
4625 jmp _end_cycle
4626 ;-----------------------------------------------------------------------------
4627
4628 ;-----------------------------------------------------------------------------
4629 ; SLT -- Set on less than (signed).
4630 ; If $s is less than $t, $d is set to one. It gets zero otherwise.
4631 ; Operation: if $s < $t $d = 1; advance_pc(4); else $d = 0; advance_pc(4);
4632 ; Syntax: slt $d, $s, $t
4633 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 1010
4634 ;-----------------------------------------------------------------------------
4635 align GRAIN, db 0x90
4636 _r_slt:
4637 RType ; load rD, rS, rT Fields
4638 mov TMP, R(rS) ; TMP := Regs[rS]
4639 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
4640 ; We do not need rS, so can reuse it here:
4641 setl rS_LowByte ; 1 if R(rS) <(signed) R(rT), else 0
4642 and rS, 0x1 ; Only want the bit that we have set
4643 Wr_Reg rD, rS ; Regs[rD] := result
4644 jmp _end_cycle
4645 ;-----------------------------------------------------------------------------
4646
4647 ;-----------------------------------------------------------------------------
4648 ; SLTU -- Set on less than unsigned.
4649 ; If $s is less than $t, $d is set to one. It gets zero otherwise.
4650 ; Operation: if $s < $t $d = 1; advance_pc(4); else $d = 0; advance_pc(4);
4651 ; Syntax: sltu $d, $s, $t
4652 ; Encoding: 0000 00ss ssst tttt dddd d000 0010 1011
4653 ;-----------------------------------------------------------------------------
4654 align GRAIN, db 0x90
4655 _r_sltu:
4656 RType ; load rD, rS, rT Fields
4657 mov TMP, R(rS) ; TMP := Regs[rS]
4658 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
4659 ; We do not need rS, so can reuse it here:
4660 setb rS_LowByte ; 1 if R(rS) <(signed) R(rT), else 0
4661 and rS, 0x1 ; Only want the bit that we have set
4662 Wr_Reg rD, rS ; Regs[rD] := result
4663 jmp _end_cycle
4664 ;-----------------------------------------------------------------------------
4665
4666 ;-----------------------------------------------------------------------------
4667 ; TEQ - Trap if Equal.
4668 ; TODO: document
4669 ;-----------------------------------------------------------------------------
4670 align GRAIN, db 0x90
4671 _r_teq:
4672 RType_S_T_Only ; Load rS and rT Fields
4673 mov TMP, R(rS) ; TMP := Regs[rS]
4674 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
4675 jne _r_teq_neql
4676 SetEXC EXC_Tr ; Spring the Trap Exception.
4677 jmp _Handle_Exception ; Go straight to exception handler.
4678 _r_teq_neql:
4679 jmp _end_cycle
4680 ;-----------------------------------------------------------------------------
4681
4682 ;-----------------------------------------------------------------------------
4683 ; TNE - Trap if Not Equal.
4684 ; Compare registers and do a conditional trap.
4685 ; Compare the contents of rS and rT as signed integers;
4686 ; if rS is not equal to rT, then take a Trap exception.
4687 ; The contents of the code field are ignored by hardware and may be used to
4688 ; encode information for system software. To retrieve the information,
4689 ; system software must load the instruction word from memory.
4690 ; Operation: if $s != $t then Trap
4691 ; Syntax: TNE $s, $t
4692 ; Encoding: 0000 00ss ssst tttt cccc cccc cc11 0110
4693 ;-----------------------------------------------------------------------------
4694 align GRAIN, db 0x90
4695 _r_tne:
4696 RType_S_T_Only ; Load rS and rT Fields
4697 mov TMP, R(rS) ; TMP := Regs[rS]
4698 cmp TMP, R(rT) ; CMP(TMP, Regs[rT])
4699 je _r_tne_eql
4700 SetEXC EXC_Tr ; Spring the Trap Exception.
4701 jmp _Handle_Exception ; Go straight to exception handler.
4702 _r_tne_eql:
4703 jmp _end_cycle
4704 ;-----------------------------------------------------------------------------