home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 4
/
DATAFILE_PDCD4.iso
/
utilities
/
utilsd
/
extbasdis
/
ExtBasDoc
< prev
Wrap
Text File
|
1996-03-03
|
11KB
|
365 lines
Extended BASIC Assembler
————————————————————————
Version 1.67, 3 March 1996
by Darren Salt
Contains code from v1.00 and v1.30 by Adrian Lees
The module ExtBASICasm provides a patch for versions 1.05, 1.06 and 1.14 of
BASIC V, as supplied with RISC OS 3.1, 3.5 and 3.6 respectively, to allow the
direct use of the extra instructions provided by the ARM3, ARM6 and ARM7
processors. The missing floating-point and general coprocessor instructions,
and some assembler directives more familiar to Acorn Assembler users have
been added; also the APCS-R register names may be used.
To make the necessary changes to the BASIC module it must be located in RAM.
The ExtBASICasm module will therefore attempt to RMFaster the BASIC module
which will require a small amount of memory in the RMA, in addition to that
required by the ExtBASICasm module itself. More importantly, BASIC must not
be active, ie. running, at the time because then the module cannot be removed
to allow it to be moved. Loading ExtBASICasm should therefore be performed at
the command line. It is safe to do this from the ShellCLI, ie. whilst the
desktop is active, even with BASIC programs running because BASIC holds all
its information within the application workspace.
The instructions added by the module are as follows:
Extensions
——————————
OPT <value>
Bit 4: ASSERT control (1 = enabled on 'second pass')
Bit 5: LDC/STC T flag control (1 = automatically set)
Bit 6: UMUL/UMULL control (0 = short forms, 1 = long forms)
MUL{cond}{S} Rd,Rm,<#const>
variable length; Rd=Rm if <2 ADD/RSB
May cause 'duplicate register' if Rd=Rm and const is not simple - ie.
not 0, (2^x)-1, 2^x, (2^x+2^y)
MLA{cond}{S} Rd,Rm,<#const>,Ra
variable length; Rd=Rm if <2 ADD/RSB
Rd=Ra causes 'duplicate register' error if const is not simple, as
for MUL; Rd=Rm=Ra is special in that MLA Rd,Rd,#c,Rd = MUL Rd,Rd,#c+1
If Rd=Ra and const=0, no code is generated (none necessary).
DIV Rq,Rr,Rn,Rd,Rt [SGN Rs]
Integer division by register
Rq = quotient Rn = numerator Rt = temporary store
Rr = remainder Rd = denominator Rs = sign store
If Rs omitted then division is unsigned.
Rr may be same register as Rn *or* Rn may be same as Rs.
All other registers must be different.
Rt and Rs (if specified) are corrupted.
DIV Rq,Rr,Rn,#d[,[Rt]] [SGN Rs]
Integer division by constant
Registers as above
If Rs omitted then division is unsigned.
If Rt omitted and is required for this division then error given.
All registers must be different.
If specified, Rt and Rs are corrupted.
(Uses generator to build code - fast but may be long)
Notes: Uses Fourier method. For unsigned values, this is fixed to
handle unsigned top-bit-set properly, *except* for div by 3
which works for values up to &C0000000. Ideas and code
gratefully received...
*** Note no conditional!
ADR{cond}L Rd,<const>
Fixed length (two words)
ADR{cond}X Rd,<const>
Fixed length (three words)
ADR{cond}W Rd,<const>
Addressing relative to R12, one to three words
<const> MUST be defined before it is used
Adds/subtracts const to/from R12, storing result in Rd
Up to you to ensure that R12 correctly set up...
LDR, STR:
XXX{cond}{B}W Rd,<offset>
Load/store word/byte at [R12,#<offset>]
Also supported are the new ARM7M forms:
LDRxxH, LDRxxSH, LDRxxSB and equivalent STRs
The standard forms are used, with the following exceptions:
- no shifts
- constant offsets in range 0 to 255, +ve and -ve
The W forms are also supported.
SWAP{cond} Rd,Rn
Swaps Rd and Rn without using temporary store
Uses EOR method, is therefore three words long
VDU{cond}{X} <const>
= SWI "OS_WriteI"+<const>
With X present, XOS_WriteI is used instead.
NOP{cond}
= MOV{cond} R0,R0
EQUx, DCx, =
XXX <value>[,<value>]^
Extended form of EQUD, EQUW, DCB, etc.
Instead of, eg. DCD 0 : DCD 12 : DCD branch
you can now use DCD 0, 12, branch
ARM3 and later (including ARM250)
—————————————————————————————————
SWP{cond}{B} Rd,Rm,[Rn]
ARM6 and later
——————————————
MRS{cond} Rd,<psr>
MSR{cond} <psr{f}>,Rm
ARM7 and later
——————————————
UMUL, SMUL, UMLA, SMLA:
xxx{cond}{S} Rl,Rh,Rm,Rn
The 'official' forms UMULL, SMULL, UMLAL, SMLAL are used *instead of*
the 'short' forms if OPT bit 6 is set.
Unfortunately it's not possible to allow both forms at once: how
would you interpret "UMULLS" - UMUL condition LS or UMULL with S bit?
Floating-point instructions
———————————————————————————
Floating point coprocessor data transfer
LDF, STF:
xxx{cond}prec Fd,[Rn]{,#offset}
xxx{cond}prec Fd,[Rn,#offset]{!}
xxx{cond}prec Fd,<label | const>
LFM, SFM:
xxx{cond} Fd,m,[Rn]{,#offset}
xxx{cond} Fd,m,[Rn,#offset]{!}
xxx{cond} Fd,m,<label | const>
LFM{cond}{stack} Fd,m,[Rn]{!}
SFM{cond}{stack} Fd,m,[Rn]{!}
LFS{cond}{stack} Rn{!},<fp register list>
LFS{cond}{stack} Rn{!},<fp register list>
LFM, SFM, LFS and SFS use extended precision. The <fp register list>
is much as for LDM and STM, with restrictions: you must specify a
register or a sequence of registers, and the list must be compatible
with LFM and SFM - eg.
LFSFD R13!,{F3} LFMFD F3,1,[R13]! LFM F3,1,[R13],#12
SFSFD R13!,{F5-F0} SFMFD F5,4,[R13]! SFM F5,4,[R13,#-36]!
LFSDB R13,{F1,F0} LFMDB F0,2,[R13] LFM R0,2,[R13,#-24]
- for each row, all the instructions have the same effect.
Available stack types are DB, IA, EA, FD.
Note that example 2 wraps around - F5, F6, F7, F0 _in that order_.
* Floating point coprocessor register transfer
FLT{cond}prec{round} Fn,Rd
FIX{cond}{round} Rd,Fn
WFS, RFS, WFC, RFC:
xxx{cond} Rd
* Floating point coprocessor data operations
ADF, MUF, SUF, RSF, DVF, RDF, POW, RPW, RMF, FML, FDV, FRD, POL:
xxx{cond}prec{round} Fd,Fn,<Fm | #value>
MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
SIN, COS, TAN, ASN, ACN, ATN, URD, NRM:
xxx{cond}prec{round} Fd,<Fm | #value>
* Floating point coprocessor status transfer
CMF, CNF, CMFE, CNFE:
xxx{cond} Fm,Fn
General co-processor instructions
—————————————————————————————————
* Coprocessor data operations
CDO, CDP:
xxx{cond} CP#,copro_opcode,Cd,Cn,Cm{,const}
The values of copro_opcode and the optional constant must lie within
the range 0..15.
* Coprocessor data transfer
MCR, MCR:
xxx{cond} CP#,<const1>,Rd,Cn,Cm{,<const2>}
LDC, STC:
xxx{cond}{L}{T} CP#,Cd,[Rn]{,#offset}
xxx{cond}{L} CP#,Cd,[Rn{,#offset}]{!}
L and T may be specified in either order. So if you want an
unconditional LDC with both flags set, use LDCTL or LDCALLT since
LDCLT will be assembled as "LDC with T and L clear, if less than".
Also, setting bit 5 of the OPT value causes the W flag to be set
automatically (in the pre-indexed form).
Assembler directives
————————————————————
* Conditional - will STOP if expression is FALSE:
ASSERT <expression>
Bit 4 of the OPT value controls ASSERT. When it and bit 1 are zero,
ASSERTs are ignored.
* Constants
= <const|string>[,<const|string>]*
The bug causing an error when used in the form
.label = "something"
has been fixed.
EQUFS, EQUFD, EQUFE, EQUFP, EQUF
xxx <const>
and the DC.. and |.. equivalents.
These directives accept an expression that evaluates to either an
integer or a real number. The result is then converted into the
required precision and stored in the object code at P%, or O% if
indirect assembly is being used. EQUF is a synonym for EQUFD.
directive EQUFS EQUFD EQUFE EQUFP
bytes used 4 8 12 12
EQUP, DCP, P
xxx <string>,<const>
xxx <const>,<string>
Fixed-length string allocation. If the string is too short, then the
remaining space is padded with nulls; if it is too long, it is
truncated to the specified length.
EQUZ, DCZ, Z
xxx <string>
EQUS with automatic zero termination
Note: *ALL* the EQU... directives (and their equivalents) may have
their arguments repeated as described in the Extensions section.
FILL, %
xxx <const>{,<byte>}
Allocates <const> bytes of memory, initialised to <byte> (or 0).
If comma is present but no fill byte, then no initialisation is done.
FILE <filename>
Loads the specified file, allocating just enough space for it.
^ <offset>
Initialises the workspace address pointer to the given value.
This is used and updated by #.
Typical use:
^ 0