home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
diskmanager
/
csdvar_2
/
BasAsmLib
(
.txt
)
< prev
next >
Wrap
RISC OS BBC BASIC V Source
|
1996-10-26
|
12KB
|
352 lines
>BasAsmLib 1.00
Musus Umbra, 1996
*******************************************************************
** Some (if not all) of these routines require that your code is **
** assembled using 'pass%' as the OPT parameter, and 'code%' as **
** the base address (initial O%/P%). **
*******************************************************************
==================================================================
Assemble a routine to display all the register contents (except
R14) without altering any of them! Very handy debugging function,
this one.
NB: You only need to assemble this once and should BL to it when
you need it (or use one of the debugging macros below)
==================================================================
showregs
[OPT pass%
B __showregs
.__super_stack equd 0
.__debug_link equd 0
;.__debug_stack equs
96,"!") :.__enddebug_stack
,.__debug_buffer equs "000000000000"
.__showregs
str r13,__super_stack
str r14,__debug_link
adr r13,__enddebug_stack
mov r14,r0
ldr r0,__debug_link
stmdb r13!,{r0}
ldr r0,__super_stack
stmdb r13!,{r0}
mov r0,r14
stmdb r13!,{r0-r12}
mov r6,#0
str r13,__debug_stack
ldr r13,__super_stack
.__regloop
swi 256+
cmp r6,#10
addlt r0,r6,#48
swilt "XOS_WriteC"
movlt r0,#32
swige 256+
addge r0,r6,#38
swi "XOS_WriteC"
swi 256+
str r13,__super_stack
ldr r13,__debug_stack
ldmia r13!,{r0}
str r13,__debug_stack
ldr r13,__super_stack
adr r1,__debug_buffer
mov r2,#32
swi "XOS_ConvertHex8"
swi "XOS_Write0"
swi "XOS_WriteS"
equd &00202020
add r6,r6,#1
cmp r6,#14
moveq r6,#15
ands r0,r6,#3
swieq "XOS_NewLine"
cmp r6,#15
ble __regloop
str r13,__super_stack
C"adr r13,__enddebug_stack-8
ldmdb r13!,{r0-r12}
ldr r13,__super_stack
ldr r14,__debug_link
movs pc,r14
==================================================================
A nice debugging thang (requires that you include FNshowregs
somewhere, see later)
Displays the text 'a$' and a register dump.
Sets SHOWREGS_USED to some non-zero value; it's suggested that you
have 'SHOWREGS_USED=0' at the start of your program (outside the
FOR pass% loop) and at some convenient point use something like:
... your code ...
]:IF SHOWREGS_USED:[OPT pass%:FNshowregs:]
[OPT pass%
... your code ...
==================================================================
debug(a$)
[OPT pass%
.SHOWREGS_USED
stmfd r13!,{r14}
\'SWI "XOS_NewLine":SWI "XOS_NewLine"
])SWI "XOS_WriteS":EQUS a$:EQUB 0:ALIGN
SWI "XOS_NewLine"
bl __showregs
ldmfd r13!,{r14}
==================================================================
Display the (null terminated) string pointed to by register 'r%'
(if register 'r%' isn't 0)
==================================================================
debps(r%)
[OPT pass%
stmfd r13!,{r0,r14}
mov r0,r%
cmp r0,#0
swine "XOS_Write0"
swi "XOS_NewLine"
ldmfd r13!,{r0,r14}
==================================================================
Print the message 'a$' followed by the (null terminated) string
pointed to by register 'r%' (if register 'r%' isn't 0)
==================================================================
debpp(a$,r%)
[OPT pass%
stmfd r13!,{r0,r14}
swi "XOS_WriteS"
equs a$:equb 0:align
mov r0,r%
cmp r0,#0
swine "XOS_Write0"
swi "XOS_NewLine"
ldmfd r13!,{r0,r14}
==================================================================
Assemble two instructions that place the address 'dest%' in
register 'reg%' (ie. a long ADR directive). 'dest%' must be
within 64K of P% (some limit, huh?)
FNadr is the equivalent of ADR
Use FNadrc when you want the ADR to be conditionally executed
==================================================================
adr(reg%,dest%)=
adrc("AL",reg%,dest%)
adrc(condition$,reg%,dest%)
(dest%-P%)>65536
1,"ADR destination out of range at &"+
(~P%)
A c$=
__toupper(
condition$,1,1))+
__toupper(
condition$,2,1))
0 cc%=
"EQNECSCCMIPLVSVCHILSGELTGTLEALNV",c$)
cc%=0
1, "Bad condition code in ADR at &"+
(~P%)
6 cc%=(cc%-1)
2:diff%=dest%-(P%+8):op1%=(cc%<<28)
: op1%+=&024F0000:op1%+=(reg%<<12):op1%+=
(diff%)
E op2%=(cc%<<28):op2%+=&02400C00:op2%+=(reg%<<16):op2%+=(reg%<<12)
A op2%+=
(diff%)>>8
&FF:
diff%>=0
op1%+=4<<20:op2%+=4<<20
% [OPT pass%:EQUD op1%:EQUD op2%:]
==================================================================
Extract the SWI number of a swi name in the module being compiled.
Requires that the module header is at 'code%'.
eg. to use the SWI "SomeModule_Example", you would use the macro:
swi FNmy_swi("Example")
This is handy as it means that when assembling a module that uses
its own SWIs, you don't have to fiddle or use absolute numbers,
or have a copy of the module loaded.
==================================================================
my_swi(leaf$)
switable%,swichunk%,swinumber%,i%,a$
(pass%
3) <= 1
= &20000
H switable%=code%+code%!&24:swichunk%=(code%!&1C)+&20000:swinumber%=0
switable%=0
swichunk%=0
1,"No swi table/chunk"
3 i%=0:
?switable%:switable%+=1:
:switable%+=1
?switable%
a$=""
C
?switable%:a$+=
?switable%:switable%+=1:
:switable%+=1
.
a$=leaf$
swinumber%=i%+swichunk%
i%+=1
&
swinumber%<>0
?switable%=0
-
1,"Module doesn't provide any SWIs"
swinumber%=0
1,"Can't find local swi '"+leaf$+"'"
=swinumber%
==================================================================
Another module one this:
returns a string that is padded with tab characters so that when
prettyprinted it is (at least) 16 characters wide.
Good for module 'help strings', eg.
.help_string equs FNtabpad(title$)+version$):equb 0
==================================================================
tabpad(a$)
(a$)<8
a$+=
(a$)<16
a$+=
==================================================================
Easy way of including 'w' 'hard' spaces (CHR$31) into an equs
(eg. in a help string for a module)
.command_help equs FNw(10)+"This is indented 10 spaces!"
==================================================================
h(w):=
==================================================================
Convert a string into a (shorter) equivalent to be PrettyPrinted
using the RISC OS dictionary. Useful for module help text, syntax
messages, etc
==================================================================
init_os_dict_tokenise
__tok_buffer% 512
, __tokenise% =
assemble_longest_match
( __dictionary% =
build_dictionary
os_dict_tokenise(a$)
A%,R%,E%,T%,O%
$__tok_buffer% = a$
6 A%=__tok_buffer%:
start at beginning of string
B%=__dictionary%
O%=A%:E%=A%+
1 ?E%=0 :
terminate with the good ol' null
R%=
(__tokenise%)
E
!R%
?O%=27:O%?1=!R%:O%+=2:A%=R%!4
?O%=?A%:A%+=1:O%+=1
A%>=E%
?O%=13
=$__tok_buffer%
INTERNAL USE ROUTINES
__toupper(a$)
a$>="a"
a$<="z"
(a$)-32)
build_dictionary
buffer%,tokenv$,token%,token$,B%
&02," the ",&03,"director",&04,"filing system",&05,"current"
&06," to a variable. Other types of value can be assigned with *"
&07,"file",&08,"default ",&09,"tion",&0A,"*Configure ",&0B,"name"
&0C," server",&0D,"number"
&0F," one or more files that match the given wildcard",&10," and "
&11,"relocatable module",&13,"sets the "
&18," is used to print a hard copy of the screen on EPSON-"
&1A,"printe",&1C," select",&1D,"xpression",&1F,"sprite"
&20," displays",&21,"free space",&22," {off}",&23,"library"
&24,"parameter",&25,"object",&26," all ",&27,"disc",&28," to "
&29," is "
&00,""
buffer% 1024 :
allocate 1K for the dictionary thang
B%=0
,
tokenv$,token$:token%=
(tokenv$)
! B%?buffer%=token%:B%+=1
I
(B%+
(token$)+1)>=1024
1,"Buffer to small for dictionary"
$(B%+buffer%)=token$
B%+=
(token$)
B%?buffer%=0
B%+=1
token%=0
=buffer%
assemble_longest_match
code%,pass%,P%
code% 4096
pass%=0
P%=code%
[OPT pass%
.__longest_match
\ On entry:
:\ r0->string to try to match dictionary against
\ r1->Dictionary
\ On exit:
\ r0->result block
\ Format of a dictionary is:
5\ {<token_number><null-terminated token>}+
2\ dictionary is terminated by token &00
! \ Format of result block is:
"&\ Offset Size Description
#D\ 0 4 Token number of best match (or 0 if none)
$8\ 4 4 byte after the matched string
&"str r13,__lm_system_stack
'1adr r13,__lm_stack \ local stack
()stmfd r13!,{r14} \ stack LR
)"bl __lm_swi_dict_match
*!adr r9,__lm_result_block
+:str r0,[r9,#4] \ byte after matched string
,-str r1,[r9] \ token number
-Qmov r0,r9 \ so
will yield a pointer to __lm__result_block
ldmfd r13!,{r14}
/"ldr r13,__lm_system_stack
movs pc,r14
2!.__lm_system_stack equd 0
3(.__lm_result_block equd 0:equd 0
4(.__lm_stack_top equs
.__lm_stack
7 ALIGN
.__lm_swi_dict_match
\ On entry:
;:\ r0->string to try to match dictionary against
\ r1->Dictionary
\ On exit:
?*\ r0->byte after matched string
@M\ r1=matching token (or 0 if no match, in which case r0 preserved)
B \ Format of a dictionary is:
C5\ {<token_number><null-terminated token>}+
D2\ dictionary is terminated by token &00
E6mov r5,#0 \ longest match to date
F5mov r4,#0 \ and its token number
.__lm_get_next_token
I*ldrb r2,[r1],#1 \ get token
J8cmp r2,#0 \ is it the 0 terminator?
K@beq __lm_finished \ if so, then we're finished
\ Get match length in r3
N3mov r3,#0 \ start at 0 matches
O,mov r6,r0 \ string1 ptr
P,mov r7,r1 \ string2 ptr
.__lm_matchloop
R6ldrb r8,[r6],#1 \ get next from string1
S6ldrb r9,[r7],#1 \ get next from string2
T3cmp r8,r9 \ are they the same?
U:addeq r3,r3,#1 \ if matched, matchlength++
V<beq __lm_matchloop \ loop until match fails
X?cmp r9,#0 \ did we match all of the token?
YKmovne r3,#0 \ if not, then we've matched nothing at all!
ZGcmp r3,r5 \ is it longer than the last best match?
[Bmovgt r5,r3 \ if so, record the new best length
\Bmovgt r4,r2 \ ... and the new best token number
.__lm_find_next_token
_<ldrb r8,[r1],#1 \ get next char in dictionary
`:cmp r8,#0 \ is it the NULL terminator
a!bne __lm_find_next_token
c b __lm_get_next_token
.__lm_finished
fFadd r0,r0,r5 \ ->character *after* the longest match
g;mov r1,r4 \ token number of best match
h%movs pc,r14 \ exit
=code%