-
+ 40EF74622647A11AC973984A9F831AD39BBEC47EAC267E3F62FB30E36058AC4B01074B97585E9B36E0B32DEB7344EC4C5AA6585E9571BAA2E0432E8D78DEB254m/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 ;-----------------------------------------------------------------------------