home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 55
/
Amiga_Dream_55.iso
/
RISCOS
/
MAGAZINE
/
NEWS
/
PCE021.ZIP
/
Pce021
/
Src
/
cpu
/
hdr
/
TempRegs
< prev
next >
Wrap
Text File
|
1998-05-27
|
4KB
|
153 lines
; TempRegs.h
; ----------
;
; Temporary registers are set up using the TEMPORARY macro, eg to set aside r0 and
; r3 as temporary registers, the following would be used:
; TEMPORARY r0
; TEMPORARY r3
; They can then be allocated and freed using the NEW and DELETE macros. Both
; require a string parameter, eg:
; GBLS reg
; MACRO
; example $val
; NEW reg
; mov $reg, #5
; mul $val, $reg, $val
; DELETE reg
; MEND
; If a routine is called that may corrupt the contents of the temporary registers,
; the current contents can be saved on the stack using PUSH, and restored using
; POP. If no temporary registers are currently allocated then the macros will
; produce no code. The IGNORE macro can be used to stop an allocated register from
; being stored if needed. Both PUSH and POP can be supplied with an optional
; condition code, eg:
; PUSH "eq"
; POP "lt"
GBLA tempregs_list
GBLA tempregs_used
GBLA tempregs_store
MACRO
TEMPORARY $tr_arg
tempregs_list SETA tempregs_list :OR: (1 << $tr_arg)
MEND
MACRO
ENSURE_UNUSED $tr_arg
ASSERT (tempregs_used :AND: (1 << $tr_arg)) = 0
MEND
MACRO
NEW $tr_arg
LCLA tr_counter
LCLA tr_chosen
tr_chosen SETA 255
WHILE (tr_counter < 32) :LAND: (tr_chosen = 255)
IF ((tempregs_list :AND: (1 << tr_counter)) /= 0) :LAND: ((tempregs_used :AND: (1 << tr_counter)) = 0)
tr_chosen SETA tr_counter
ENDIF
tr_counter SETA tr_counter + 1
WEND
ASSERT tr_chosen /= 255
tempregs_used SETA tempregs_used :OR: (1 << tr_chosen)
tempregs_store SETA tempregs_store :OR: (1 << tr_chosen)
IF tr_chosen < 10
$tr_arg SETS "r":CC:("$tr_chosen":RIGHT:1)
ELSE
tr_chosen SETA tr_chosen - 10
$tr_arg SETS "r1":CC:("$tr_chosen":RIGHT:1)
ENDIF
MEND
MACRO
NEW2 $tr_arg1, $tr_arg2
ASSERT ((tempregs_list :AND: (1 << $tr_arg2)) /= 0) :LAND: ((tempregs_used :AND: (1 << $tr_arg2)) = 0)
tempregs_used SETA tempregs_used :OR: (1 << $tr_arg2)
tempregs_store SETA tempregs_store :OR: (1 << $tr_arg2)
IF $tr_arg2 < 10
$tr_arg1 SETS "r":CC:(:STR:($tr_arg2):RIGHT:1)
ELSE
$tr_arg1 SETS "r":CC:(:STR:(0x$tr_arg2 - 10):RIGHT:1)
ENDIF
MEND
MACRO
DELETE $tr_arg
tempregs_used SETA tempregs_used :AND: :NOT: (1 << $$$tr_arg)
tempregs_store SETA tempregs_store :AND: :NOT: (1 << $$$tr_arg)
$tr_arg SETS "r999"
MEND
MACRO
IGNORE $tr_arg
tempregs_store SETA tempregs_store :AND: :NOT: (1 << $$$tr_arg)
MEND
MACRO
PUSH $cc
LCLS push_list
LCLA tr_counter
WHILE (tr_counter < 32)
IF (tempregs_store :AND: (1 << tr_counter)) /= 0
IF "$push_list" /= ""
push_list SETS "$push_list,"
ENDIF
IF tr_counter < 10
push_list SETS "$push_list r":CC:(:STR:($tr_counter):RIGHT:1)
ELSE
push_list SETS "$push_list r1":CC:(:STR:(0x$tr_counter - 10):RIGHT:1)
ENDIF
ENDIF
tr_counter SETA tr_counter + 1
WEND
IF "$push_list" /= ""
stm$cc.fd r13!, {$push_list}
ENDIF
MEND
MACRO
PUSH_EXCEPT $tr_arg, $cc
LCLA tr_store
tr_store SETA tempregs_store
tempregs_store SETA tempregs_store :AND: :NOT: (1 << $tr_arg)
PUSH $cc
tempregs_store SETA tr_store
MEND
MACRO
POP $cc
LCLS pop_list
LCLA tr_counter
WHILE (tr_counter < 32)
IF (tempregs_store :AND: (1 << tr_counter)) /= 0
IF "$pop_list" /= ""
pop_list SETS "$pop_list,"
ENDIF
IF tr_counter < 10
pop_list SETS "$pop_list r":CC:(:STR:($tr_counter):RIGHT:1)
ELSE
pop_list SETS "$pop_list r1":CC:(:STR:(0x$tr_counter - 10):RIGHT:1)
ENDIF
ENDIF
tr_counter SETA tr_counter + 1
WEND
IF "$pop_list" /= ""
ldm$cc.fd r13!, {$pop_list}
ENDIF
MEND
MACRO
POP_EXCEPT $tr_arg, $cc
LCLA tr_store
tr_store SETA tempregs_store
tempregs_store SETA tempregs_store :AND: :NOT: (1 << $tr_arg)
POP $cc
tempregs_store SETA tr_store
MEND
END