Extended Disassembler
---------------------
version 0.29a, 21 May 1997
by Darren Salt <arcsalt@spuddy.mew.co.uk>


The module Disassembler provides a patch for all versions of the Debugger
module from RISC OS 3.10 onwards. However, at the time of writing it hasn't
(AFAIK) been tested with ARM8 and StrongARM.

It is aware of all ARMs up to ARM8 and StrongARM SA-110; it knows of all
instructions up to ARM7, and the sign-extend and half-word load/store
extensions. It also has a few extras thrown in (see below). It can also
auto-detect which cache type is in use (ie. whether you have an ARM2 or
ARM250 [uncached of course!], ARM3, ARM6 or later, or StrongARM).

To make the necessary changes to the Debugger module it must be located in
RAM. The Disassembler module will therefore attempt to RMFaster the Debugger
module which will require a small amount of memory in the RMA, in addition to
that required by the Disassembler module itself.

Loading Disassembler should be performed at the command line. It is safe to
do this from the ShellCLI, ie. whilst the desktop is active.

* If any breakpoints were set, these will be lost if the Debugger module was
  running from ROM.

It is possible to initialise the flags by appending them to the load command.
For example:
  *RMLoad System:Modules.Disassem -FDwithR13 Y -QuoteSWIs Y
(If a flag is not specified, it defaults to OFF.)


The module supports one command and two SWIs. It also tries to patch
*ShowRegs so that it uses the APCS-R register names if the APCS flag is set.


*DisassemblerFlags
 -----------------
 Allows you to set various MemoryI and Debugger_Disassemble features.
 Available switches:
	-FDwithR13 <f>	use FD with R13, eg. STMDB R13 -> STMFD R13
	-APCS <f>	use APCS-R register set
	-LFMstack <f>	use stack notation with LFM & SFM where possible
	-LFS <f>	use LFS and SFS in preference to LFM & SFM
	-QuoteSWIs <f>	put quotes around SWI names
	-UseDCD <f>	use DCD instead of 'Undefined instruction'
	-UseVDU <f>	use VDU x instead of SWI OS_WriteI+x
	-ANDEQasDCD <f>	use DCD instead of ANDEQ, MOV Rn,Rn (same register)
			etc.
	-UseADRL <f>	use ADRL/ADRX instead of ADR then ADD/SUB on same reg
	-UseADRW <f>	use ADRW instead of ADD/SUB Rn,R12,#m and LDRW, STRW,
			LDRBW, STRBW instead of xxxx Rn,[R12,#m]
	-LongMul <f>	append L to UMUL, UMLA, SMUL, SMLA (thus using the
			'official' forms)
	-UseLDRL <f>	use LDRL instead of ADD/SUB Rn,Rm,#o + LDR Rn,[Rn,#p]
			and ADD/SUB Rm,Ra,#o + LDR Rn,[Ra,#p]! and STR
			instead of equivalent STRs.
			(The LDRWL form is enabled by this *and* UseADRW)
	-UseNOP <f>	use NOP instead of MOV R0,R0
 where <f> is "0" or "N" (off), or "1" or "Y" (on).

 Use *DisassemblerFlags on its own to display the current state.

 These switches are three-way: "off", "on", and "unchanged". To leave it
unchanged, just don't specify it :-)


SWI Debugger_Disassemble
    --------------------
 Replaces the 'standard' version. Use it in exactly the same way.


SWI Debugger_63
    -----------
 (Note no proper name!)
 Used to alter the Debugger_Disassemble flags (listed above).
 Input  : R0 = BIC mask, R1 = EOR mask
 Process: new_flags = (old_flags AND NOT R0) EOR R1
 Output : R0 = old_flags, R1 = new_flags

 Bits in R0 and R1 are:
 0 = FDwithR13	2 = LFMstack	4 = QuoteSWIs	6 = ADNEQasDCD	8 = UseADRW
 1 = APCS	3 = LFS		5 = UseDCD	7 = UseADRL	9 = UseLDRL
 10 = UseNOP	11..31 = reserved, leave unchanged



Disassembly extensions and changes
----------------------------------

 MOV R0,R0	Optionally disassembled as NOP

 MOV PC,PC	Always disassembled as MOV PC,PC
		Sometimes used instead of a branch instruction:
			LDR	R0,data
			MOV	PC,PC
		.data	DCD	&123456		; this is ignored
			LDR	R1,[R0]

 SWP		Now listed as 'ARM250 and later'

 STM		Warning if base register second or later in register list and
		writeback enabled: 'Base not first in list'

 ADRL		ADR followed by ADD/SUB with same condition on same register.
		For example,
			00010000	ADRLS	R0,&00010100
			00010004	ADDLS	R0,R0,#&A000
		becomes
			00010000	ADRLS	R0,&00010100
			00010004	ADRLSL	R0,&0001A100

 ADRX		ADR followed by two ADD/SUBs with same condition on same
		register.

 ADRW		R12 relative: ADD/SUB Rn,R12,#m

 LDRW, LDRBW,	R12 relative: LDR/LDRB/STRB/STRB Rn,[R12,#m]
 STRW, STRBW

 LDRL, LDRBL	Without writeback:
		    Normal:
			ADD/SUB		Rn,Rm,#o
			LDR/LDRB	Rn,[Rn,#p]
		    ->	ADD/SUB		Rn,Rm,#o
			LDRL/LDRBL	Rn,[Rm,#o+p]
		    PC relative:
			ADR		Rn,a
			LDR/LDRB	Rn,[Rn,#p]
		    ->	ADR		Rn,a
			LDRL/LDRBL	Rn,a+p
		With writeback:
			ADD/SUB		Rm,Rm,#o
			LDR/LDRB	Rn,[Rm,#p]!
		    ->	ADD/SUB		Rm,Rm,#o
			LDRL/LDRBL	Rn,[Rm,#o+p]!
		Store address in third register:
		    Normal:
			ADD/SUB		Ra,Rm,#o
			LDR/LDRB	Rn,[Ra,#p]!
		    ->	ADD/SUB		Ra,Rm,#o
			LDRL/LDRBL	Rn,{Ra},[Rm,#o+p]
		    PC relative:
			ADR		Ra,a
			LDR/LDRB	Rn,[Ra,#p]
		    ->	ADR		Ra,a
			LDRL/LDRBL	Rn,{Ra},a+p

 STRL, STRBL	Without writeback:
		    Normal:
			ADD/SUB		Rm,Rm,#o
			STR/STRB	Rn,[Rm,#p]
		    ->	ADD/SUB		Rn,Rm,#o
			STRL/STRBL	Rn,[Rm,#o+p]
			(followed by a cancelling SUB/ADD)
		    PC relative:
			Is not practical
		With writeback:
			ADD/SUB		Rm,Rm,#o
			STR/STRB	Rn,[Rm,#p]!
		    ->	ADD/SUB		Rm,Rm,#o
			STRL/STRBL	Rn,[Rm,#o+p]!
		Store address in third register:
		    similar to LDRL/LDRBL

 LDRWL,		R12 relative:
 LDRBWL,		ADD/SUB		Rn,R12,#o
 STRWL,			LDR/LDRB	Rn,[R12,#p]
 STRBWL		->	ADD/SUB		Rn,R12,#o
			LDRWL/LDRBWL	Rn,o+p
		& similar for 3rd register variants (see LDRL)

 MCR, MRC	Constant (following first comma) now displayed correctly

 MRS, MSR	Added for ARM6 and later

 UMUL, SMUL,	Added for ARM7 and later
 UMLA, SMLA	(Long 'official' forms supported)

 LDFxW, STFxW	R12 relative LDF/STF ('x' = precision code)

 LFM, SFM	Extended format - for example,
			LFM	F1,3,[R13],#&024	; =36
		may be shown 'as is' or as any of
			LFMIA	F1,3,[R13]!
			LFMFD	F1,3,[R13]!
			LFSIA	R13!,{F1-F3}
			LFSFD	R13!,{F1-F3}

 FLT		Registers shown correct way round - Fx,Ry instead of Ry,Fx

 LDC, STC	L and T flags shown in order TL to avoid confusion with the
		LT condition. The T flag is not supported in current versions
		of FPEmulator; it is always used as the writeback bit, and
		must therefore be set for the post-indexed forms.
		(This also affects LDF, STF, LFM and SFM.)

 VDU, VDUX	Equivalent to SWI OS_WriteI and XOS_WriteI respectively

 LDR, STR	H, SH, SB forms added for ARM7M and later
		W (R12-relative) forms supported, eg. LDRSBW R0,&40

Instructions which rely on PC plus implied offset, because of the possibly
different values of this offset for different ARM implementations, are
flagged as "*** Offset not guaranteed".
(comp.sys.arm <47kr75$hpc@doc.armltd.co.uk>, David Seal, "Re: Storing PC")

LDRs and STRs which are PC-relative always appear in the standard form. For
an instruction pair in which the first is of the form "[Rm],#d" and the
second is an ADD or SUB modifying (and storing in) Rm, a comment "Rm+=x" will
be shown.

Comments of the form '="x"' now contain the character code: '="x" (120)".

As with all good software, there may be undocumented features... let me know
and I'll try to fix them :-)
