- Convert each of the following to a string of calls to the RPN macros:
a = b - (c << 2);
pushaddr a
pushvar b
pushvar c
pushimm 2
ls
sub
put
b = a[ i ]; -- assume i is an array of integers
pushaddr b
pushaddr a
pushvar i
pushimm 2
ls
add
get
put
a[ i ] = i + 5; -- assume i is an array of integers
pushaddr a
pushvar i
pushimm 2
ls
add
pushvar i
pushimm 5
add
put
- The ars macro turns out to be a real challenge. The built in ARS
instruction in the Hawk machine requires a constant shift count,
between 1 and 16, but we need a variable. Here's a solution:
MACRO ars
qSPq = qSPq - 1
LIS R1,31
AND qSPq,R1 ; make sure we don't shift more than 31 places
LS qSPq,1 ; multiply shift count by 2
LEA R1,.+8+62
SUB R1,R1,qSPq
JUMPS R1 ; jump to the correct shift instruction
; .+8 gets here
ARS qSPq-1,1
ARS qSPq-1,1
ARS qSPq-1,1
.
. ; 31 shift instructions in a row
.
ARS qSPq-1,1
ARS qSPq-1,1
ARS qSPq-1,1
; .+8+62 gets here
ENDMAC
Other workable solutions involve a loop or a full-blown select/case structure
- Here is code for the if, else and endif macros:
MACRO if
qBLOCKNUMq = qBLOCKNUMq + 1
PUSH qBLOCKNUMq
qSPq = qSPq - 1
MOVECC R0,qSPq
LABGEN (BZS E),qQBLOCKNUMq,()
ENDMAC
MACRO else
TOP qTEMPq
LABGEN (JUMP Q),qTEMPq,()
LABGEN (E),qTEMPq,(:)
ENDMAC
MACRO endif
POP qTEMPq
LABGEN (Q),qTEMPq,(:)
ENDMAC
- Show the Hawk machine code resulting from the macro expansion:
pushvar i
LOAD R3,R2,i ; assume i is local
select
CMPI R3,1
BGT TO1
CMPI R3,0
BLT TO1
LEA R1,T1
ADDSL R3,R1,2
LOADS R1,R3
JUMPS R1
TO1:
JUMP O1
case 0
qTEMPq = .
. = T1 + (0 << 2)
W qTEMPq ; make a table entry
. = qTEMPq
xxxx
break
JUMP Q1
case 1
qTEMPq = .
. = T1 + (1 << 2)
W qTEMPq ; make a table entry
. = qTEMPq
yyyy
break
JUMP Q1
otherwise
O1:
zzzz
break
JUMP Q1
endselect
ALIGN 4
T1: ; this is where the table entries end up
. = . + (((1 - 0) + 1) << 2)
O1:
Q1:
- The select/case macros defined here require a break before the end select!
Falling into the end select from above will likely cause some kind of
trap because you'll end up trying to execute the jump table!