Snakey's R4300i Assembler






Version History




Version 1.0
3/??/04

Just Getting Started. This ReadMe probably looks like shit.




Usage/Syntax Notes




General Notes

  • All values used in your routines must be Hexadecimal unless specified otherwise in this ReadMe!
  • Spacing between registers and such, though frowned upon, is generally supported.


Addressing

The default starting address is 80000000. This can be changed in two ways (both within the ASM textbox). Address must be aligned for ASM. This means the address needs to end in 0,4,8 or C. And yes, it has to be Hex!

Method 1: Just use the address on its own line, but it must begin with an '8'.


80142014
JAL    80000060
ADDIU  $V0,$V0,00FF
80000060
LUI    $K1,3F80
JR     $RA
MTC1   $K1,F2

Method 2: Use a colon.


80142014:
JAL    80000060
ADDIU  $V0,$V0,00FF
60:
LUI    $K1,3F80
JR     $RA
MTC1   $K1,F2




Immediates/Jump Targets

Jumps and other opcodes where you use a value are fairly forgiving on syntax of the value.

Some Examples:


JAL 80000060
J  60
JAL $60
J 0x60
ADDIU $V0,$V0,00FF
ADDIU $V0,$V0,FF
ADDIU $V0,$V0,$00FF
ADDIU $V0,$V0,$FF
ADDIU $V0,$V0,0x00FF




Branches

Branches can be done in 3 ways: by address, by immediate, and by label. Anything shorter than 5 characters will be considered an immediate. Anything long, an address.

Some Examples:


BEQ $V0,$A1,80000068
NOP
BNE $V1,$S1,3
ADDIU  $V0,$V0,00FF
LUI    $K1,3F80
MTC1   $K1,F2
BNE $V1,$S1,@bah
ADDIU  $V0,$V0,00FF
LUI    $K1,3F80
@bah
MTC1   $K1,F2




Registers

Registers are another thing I tried to make flexible. Some Examples:


ADDIU  $V0,$zero,00FF
ADDIU  $V0,zero,00FF
ADDIU  $V0,R00,00FF
ADDIU  $V0,R0,00FF
ADDIU  V0,R0,00FF
ADDIU  R3,R0,00FF
ADDIU  R03,R0,00FF
LUI    $K1,3F80
MTC1   $K1,F2
MTC1   $K1,F02
MTC1   $K1,$F2
MTC1   $K1,FPR2




Comments

The semi-colon can be used for commenting. Some Examples:


ADDIU  $V0,$zero,00FF ;V0 will now be 00FF
;Put 3F80 into F2
LUI    $K1,3F80
MTC1   $K1,F2





Unsupported Opcodes




 

The only OP that's not supported at all is CACHE. I couldn't figure out how the hell it's assembled. I was also unsure of some of the Trap OPs. Any of the ones with an Immediate are good, but the ones like TEQ will give you a little warning. I'm not sure if those are right or not.




Supported Pseudo Opcodes




Notes

I've added all the typical pseudo OPs that were listed in n64ops#a.txt of the reference docs, and a ton more of my own. Here's the full list...



Explanations

rs = 5-bit source register specifier
rt = 5-bit target (source/destination) register or branch condition
rd = 5-bit destination register specifier
fs = 5-bit floating point source register specifier
ft = 5-bit floating point target (source/destination) register or branch condition
fd = 5-bit floating point destination register specifier
base = 5-bit value
float = Float value (32bit)
imm = 16 bit immediate value
offset = 16 bit branch displacement or address displacement
target = 26 bit jump target address [] = Optional argument.



Pseudo OPs List
OPcodeArgumentsAssembles To
NOPADDIU R0,R0,0000
or
SLL r0, r0, 0
(Short/Long)
MOVErd, rsADD rd, r0, rs
NEGrd, rtSUB rd, r0, rt
NEGUrd, rsSUBU rd, r0, rs
BNEZrs, offsetBNE rs, r0, offset
BNEZLrs, offsetBNEL rs, r0, offset
BEQZrs, offsetBEQ rs, r0, offset
BEQZLrs, offsetBEQL rs, r0, offset
BoffsetBEQ r0, r0, offset
BALoffsetBGEZAL r0, offset
LIrt, immORI rt, r0, imm (if imm is 16 bit)
or
LUI rt, high_16
ORI rt, rt, low_16 (if imm is 32 bit)
S.Sft, offset(base)SWC1 ft, offset(base)
L.Sft, offset(base)LWC1 ft, offset(base)
LBI / LBArt,offset[(base)]Note 1
LBUI / LBUArt,offset[(base)]Note 1
LDI / LDArt,offset[(base)]Note 1
LDLI / LDLArt,offset[(base)]Note 1
LDRI / LDRArt,offset[(base)]Note 1
LHI / LHArt,offset[(base)]Note 1
LHUI / LHUArt,offset[(base)]Note 1
LLI / LLArt,offset[(base)]Note 1
LLDI / LLDArt,offset[(base)]Note 1
LWI / LWArt,offset[(base)]Note 1
LWLI / LWLArt,offset[(base)]Note 1
LWRI / LWRArt,offset[(base)]Note 1
LWUI / LWUArt,offset[(base)]Note 1
DDIVHIrd,rs,rtDDIV rs,rt
MFHI rd
DDIVLOrd,rs,rtDDIV rs,rt
MFLO rd
DDIVUHIrd,rs,rtDDIVU rs,rt
MFHI rd
DDIVULOrd,rs,rtDDIVU rs,rt
MFLO rd
DMULTHIrd,rs,rtDMULT rs,rt
MFHI rd
DMULTLOrd,rs,rtDMULT rs,rt
MFLO rd
DMULTUHIrd,rs,rtDMULTU rs,rt
MFHI rd
DMULTULOrd,rs,rtDMULTU rs,rt
MFLO rd
MULTHIrd,rs,rtMULT rs,rt
MFHI rd
MULTLOrd,rs,rtMULT rs,rt
MFLO rd
MULTUHIrd,rs,rtMULTU rs,rt
MFHI rd
MULTULOrd,rs,rtMULTU rs,rt
MFLO rd
LTC1 / LIC1
(See Note 1)
fd,[rs,],imm
If no rs, $K1 is used
(if imm is 16 bit or lower 16 bits are 0)
LUI rs, imm
MTC1 rs,fd
(if imm is 32 bit)
LUI rs, high_16
ORI rs, rs, low_16
MTC1 rs,fd
LAC1fd,offset[(base)]
If no base, $K1 is used
LUI base, high_16
LWC1 fd,low_16(base)
LFC1 / LFTC1, LFPfd,[rs,],float
If no rs, $K1 is used.
Converts the float to hex and assembles the same as LTC1/LIC1.
Note 1

  • If no base is specified, rt is used.
  • The Load byte/word/etc Immediate/Address OPs assemble to:

    LUI base, high_16 Lx rt, low_16(base)

    example:

    LBI $V0,80000060($AT)

    Assembles to:

    LUI $AT,8000
    LB $V0,0060($AT)

  • The offset need not be the full address. LBI $V0,60($K1) will assemble the same as above. The '8' is implied. LAC1 works this way too.
  • The offset is auto-fixed. WTF does that mean? All Load OPs are signed. 80YYxxxx. If xxxx is greater than 7FFF then 1 must be added to the upper 16 bits for the load to work. i.e.

    LBI $V0,8014C6D0 would become:
    LUI $V0,8015
    LB $V0,C6D0($V0)



Credits/Contact




Author

Viper187 of GSCentral and The Snake Pit



Special Thanks

Parasyte - His 1337 programming/hacking skills are unmatched. I'm always asking him shit.
HyperHacker - GS hacker and VB6 programmer. :)
Icy Guy - GS hacker and up and coming VB6 programmer. He should really learn a good language instead....and learn ASM!! :P
SubDrag - Another cool GS hacker that's still at it after a lot of others have quit.
Kenobi - Still kind of the new guy on the block at GSC, but he's getting rather Parasyte-like with programming and Cube/GBA hacking :)