Reference: C to Assembly Patterns
This will be a quick reference page to clearly associate high level code constructs to assembly language. These are only one example of how to achieve the result, there are usually many others.
Bit Shift
Bit shifting in assembly language is commonly used instead of multiplication and division. The downside is it's only powers of 2 but that is also a common scenario when twiddling bits.
Assembly
slr t0, t1, 2
C
t0 = t1 / 4;
Assembly
sll t0, t1, 2
C
t0 = t1 * 4
Bit Manipulation
Bit manipulation is useful for testing if a specific bit is either a zero or one. Also can be used on groups or patterns of bits. Standard 'Truth Tables' apply.
Common usages
AND - Using a mask to check the state of a single or group of bits
OR -
NOR
XOR
Conditions
Think of the 'b' or branch instructions as the '(test == true) -> else'. It took me a while to think like this.
Test ex. beq t1, r0, label
if true go to label
if false continue to the instruction after the delay slot.
beq t1, r0, label
nop
add t1, t1, 1
label:
nop
add t1, t1, 2
C equivalent:
if (t1 != r0) // <= Inverted
{
t1 = t1 + 1;
}
else
{
t1 = t1 + 2
}
This is inverted logic for most programmers, hopefully the '(test == true) -> else' idea helps.
There are a few things to note about Branches. Trying to perform a branch condition in a single instruction is actually a bit limited. From the table below it's clear there are a lot of instruction options 16 in fact, what takes a second look is that there are no "immediate" comparison options, and if the condition isn't 'equal' or 'not equal' then it compares to zero. The best advice is find a way to compare against zero, there are many cases it can be difficult, but it's worth a little effort.
Psuedo Instructions
Always: Always executes the Delay Slot
Conditional: Only executes the Delay Slot if Branch is taken
Uses $ra: Sets the $ra Register so the Branch can return to that location
Conditional and uses $ra: combines both of the above options
Notes:
BEQ* and BNE are 2 register instructions
BL* and BG* instructions use a signed value in a single register
The BLE* instructions use the sign bit = 1 and <> zero.
The BLT* instructions use the sign bit = 1.
The BGE* instructions use the sign bit = 0.
The BGT* instructions use the sign bit = 0 and <> zero
In order of branching performance choice:
Compare Equal or not equal
bne or beq
Compare against zero
all of the other instructions
if you need a > or < combination
use a setl instruction to perform the comparison with a result of zero
If you want an 'immediate' type of compare
16bit or smaller use 'addi t0, r0, value'
Greater than 16bit use the li or la psuedo instruction
Load Register comparison value from RAM
Function Calls
j, jr - is a jump that is not coming back to the source location
Jump from initialization code to loop code
jal, jalr - saves it's source location in $ra and can return easily
Used for Function Calls
References
http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/index.html