jmp cond ads
cond = EQ, NEQ, LT, LE, GT, GE, ALWAYS
There are four flags in the processor: Sign, Zero, Carry, Overflow (S,Z,C,O). Each flag is one bit. They are like global variables. Flags are set by ALU intructions such as, add, sub, mul, div, and, xor etc. The ld/st instructions do not change flags. The condition is decided by flags. Flags are set by the previous ALU instruction. To compare two variables, subtract instruction is used and flags S,Z will be affected. Let two variables be in r1 and r2, "sub r0 r1 r2" will compare these variables and set the Sign and Zero flags without altering any register (because r0 is always zero). For example, EQ is true when Z = 1. LT is true when S = 1. LE is true when S = 1 or Z = 1. Subsequently, jump instruction can test the condition to affect the control flow.
Example of using jump to do if...then...else
if a > b then1
if b < c then2 e1 else2 e2
else1
e3
let r1 = a, r2 = b, r3 = c
ld r1 a
ld r2 b
ld r3 c
sub r0 r1 r2 ;; compare a b
jmp GT then1 ;; if a > b then1
e3 ;; else1
jmp always exit
:then1
sub r0 r2 r3 ;; compare b c
jmp LT then2
e2 ;; else2
jmp always exit
:then2
e1
:exit
jal rx ads
jump and link save PC to rx and jump to ads. rx = PC; PC = ads.
jr rx
restore PC from rx. PC = rx.
rx is called a link register. It stores PC which is called "the return address" for the function call. It is complicate when the function is recursive because rx must then be save/restore properly. We will concern here only the non-recursive call.
What is not mentioned here is the passing of parameters of a function call. It involves a data structure called "activation record". This data structure is the topic related to compiler contruction. For simplicity, the parameters can be passed through registers, assuming that the programmer takes responsibility to allocate registers appropriately.
Example of function call.
main(){
a = 2
b = sq(a)
}
sq(x){
return x * x
}
let r1 = a, r2 = b, r3 = x, r4 = retads, r5 = retvalue.
:main
ld r1 #2
st a r1 ;; a = 2
add r3 r1 r0 ;; x = a
jal r4 sq ;; call sq()
add r2 r5 r0 ;; b = sq(a)
st b r2
trap print r2
trap stop r0
:sq
mul r5 r3 r3
jr r4 ;; return
Note we use "add rx ry r0" to do rx = ry (moving a value between
two registers)
r4 is used as a link register to store the return address. The passing of a parameter is done by assigning x = a ("add r3 r1 r0"). The return value is stored in r5.
12 June 2003