home *** CD-ROM | disk | FTP | other *** search
RISC OS BBC BASIC V Source | 1996-10-26 | 12.0 KB | 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%
-