home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / disassem / s / Disassem
Encoding:
Text File  |  1995-06-16  |  32.7 KB  |  1,487 lines

  1. ;+ -to IDEFS::Main.$.Proto.Disassem -module -quit
  2.  
  3. R0    RN    0
  4. R1    RN    1
  5. R2    RN    2
  6. R3    RN    3
  7. R4    RN    4
  8. R5    RN    5
  9. R6    RN    6
  10. R7    RN    7
  11. R8    RN    8
  12. R9    RN    9
  13. R10    RN    10
  14. R11    RN    11
  15. R12    RN    12
  16. R13    RN    13
  17. R14    RN    14
  18. PC    RN    15
  19.  
  20. CP15    CP    15
  21. C0    CN    0
  22.  
  23. XOS_WriteS        * &20001
  24. XOS_Write0        * &20002
  25. XOS_NewLine        * &20003
  26. XOS_CLI            * &20005
  27. XOS_Module        * &2001E
  28. XOS_BinaryToDecimal    * &20028
  29. XOS_SWINumberToString    * &20038
  30. XOS_ReadArgs        * &20049
  31. XOS_ConvertHex2        * &200D1
  32. XOS_ConvertHex4        * &200D2
  33. XOS_ConvertHex6        * &200D3
  34. XOS_ConvertHex8        * &200D4
  35. XOS_ConvertInteger4    * &200DC
  36.  
  37.  
  38. ;    Token    mask, test, token string
  39. ;    For instruction templates
  40.     MACRO
  41. $l    Token    $m,$v,$t
  42. $l    & &$m, &$v
  43.     = (:LEN:"$t"+13) :AND: -4
  44.     = "$t", 0
  45.     ALIGN
  46.     MEND
  47.  
  48.     GBLA    flag__b
  49.  
  50.     MACRO
  51. $l    FlagBit    $bit
  52.  [ "$bit" > ""
  53. flag__b    SETA    $bit
  54.  ]
  55. $l    *    1:SHL:flag__b
  56. flag__b    SETA    flag__b + 1
  57.     MEND
  58.  
  59.     ^    0,R12    ; Workspace
  60. prev    #    8
  61. flags    #    4
  62. adrlx    #    4
  63. adrlx_f    #    4
  64. buffer    #    0
  65.     #    256-:INDEX:buffer
  66. size    #    0
  67.  
  68. buffptr    *    :INDEX:buffer
  69.  
  70.  
  71. flag_stack    FlagBit    0
  72. flag_apcs    FlagBit
  73. flag_lfmstack    FlagBit
  74. flag_lfs    FlagBit
  75. flag_quoteswis    FlagBit
  76. flag_usedcd    FlagBit
  77. flag_usevdu    FlagBit
  78. flag_andeqasdcd    FlagBit
  79. flag_useadrl    FlagBit
  80. flag_useadrw    FlagBit
  81.  
  82. flag_arm6    * 1:SHL:31
  83.  
  84. ; Now some actual code...
  85.  
  86. start    & 0
  87.     & :INDEX:init
  88.     & :INDEX:exit
  89.     & 0
  90.     & :INDEX:title
  91.     & :INDEX:help
  92.     & :INDEX:commands
  93.     & 0
  94.  
  95. title    = "Disassembler",0
  96.  
  97. help    = "Disassembler",9,"0.18 (16 Jun 1995)",0
  98.  
  99. memoryflags_help
  100.  = "*",27,0," allows you",27,"(set various MemoryI",27,16
  101.  = "Debugger_Disassemble features. Available switches:",13
  102.  = 9,"-FDwithR13 <f>",9,"use FD with R13, eg. STMDB R13 -> STMFD R13",13
  103.  = 9,"-APCS <f>",9,"use APCS-R register set",13
  104.  = 9,"-LFMstack <f>",9,"use stack nota",27,9," with LFM & SFM where possible"
  105.  = 13
  106.  = 9,"-LFS <f>",9,"use LFS",27,16,"SFS in preference",27,"(LFM & SFM",13
  107.  = 9,"-QuoteSWIs <f>",9,"put quotes around SWI ",27,11,"s",13
  108.  = 9,"-UseDCD <f>",9,"use DCD instead of 'Undefined instruc",27,9,"'",13
  109.  = 9,"-UseVDU <f>",9,"use VDU x instead of SWI OS_WriteI+x",13
  110.  = 9,"-ANDEQasDCD <f>",9,"use DCD instead of 'ANDEQ'",27,16,"similar",13
  111.  = 9,"-UseADRL <f>",9,"use ADRL (ADRX) instead of ADR + ADD/SUB (+ ADD/SUB)"
  112.  = 13
  113.  = 9,"-UseADRW <f>",9,"use ADRW, LDRW, STRW for R12±m & [R12,#m]",13
  114.  = "where <f>",27,")""0"" or ""N"" (off), or ""1"" or ""Y"" (on).",13
  115.  = "Use *",27,0," on its own",27,"(display",27,2,27,5," state.",13
  116. memoryflags_syn
  117.  = 27,1," [<switches>]",0
  118.  
  119. dism_help
  120.  = "The ",27,0," module provides a new, fully compatible, version of "
  121.  = "Debugger_Disassemble by patching into",27,2,"Debugger module. This "
  122.  = "affects *MemoryI",27,16,"applica",27,9,"s such as !Zap.",13,13
  123.  = "The ARM7 instruc",27,9," set",27,")recognised,",27,16,"flagged where "
  124.  = "appropriate with ""ARMx or later"".",13,13
  125.  = "Differences: unrecognised SWIs are given by ",27,13,";",27,2,"L",27,16
  126.  = "T flags for LDC",27,16,"STC are reversed",27,"(avoid confusion with",27
  127.  = 2,"LT condi",27,9,"; and UMULL",27,16,"SMULL become UMUL",27,16,"SMUL "
  128.  = "respectively (to keep them",27,"(less than 8 characters with condi",27,9
  129.  = 27,16,"S flag).",13,0
  130.  
  131. rmfaster = "RMFaster "
  132. debug    = "Debugger",0
  133.  
  134. commands
  135.     = "DisassemblerFlags",0
  136.     ALIGN
  137.     & :INDEX:memoryflags
  138.     & &FF0000
  139.     & :INDEX:memoryflags_syn
  140.     & :INDEX:memoryflags_help
  141.     = "Disassembler",0
  142.     ALIGN
  143.     & 0,0,0,:INDEX:dism_help
  144.     & 0
  145.  
  146. init    STMFD    R13!,{R14}    ; Init module
  147.     ADR    R0,rmfaster
  148.     SWI    XOS_CLI        ; RMFaster Debugger (ignoring any error)
  149.     MOV    R0,#18
  150.     ADR    R1,debug
  151.     SWI    XOS_Module    ; Find Debugger module, exit if failed
  152.     ADRVS    R0,initfailed
  153.     LDMVSFD    R13!,{PC}
  154.     MOV    R8,R3        ; Claim workspace
  155.     MOV    R0,#6
  156.     MOV    R3,#:INDEX:size
  157.     SWI    XOS_Module
  158.     LDMVSFD    R13!,{PC}
  159.     STR    R2,[R12]
  160.     STR    R2,workspace
  161.     MOV    R0,#0        ; Initialise workspace
  162. wipe    SUBS    R3,R3,#4
  163.     STRPL    R0,[R2,R3]
  164.     BPL    wipe
  165.     LDR    R0,[R8,#32]    ; Patch into SWI code...
  166.     LDR    R1,[R0,R8]!    ; find address
  167.     ADD    R0,R0,#4
  168.     ADR    R4,swijump
  169.     STMIA    R4,{R0,R8}    ; store data for when this module RMKilled
  170.     STR    R1,firstinstr
  171.     ADR    R1,swihandler    ; calculate branch offset
  172.     SUB    R1,R1,R0
  173.     SUB    R1,R1,#4
  174.     MOV    R1,R1,LSL #6    ; make branch instruction
  175.     MOV    R1,R1,LSR #8
  176.     ORR    R1,R1,#&EA000000
  177.     STR    R1,[R0,#-4]    ; store it
  178.     LDR    R0,[R8,#-4]    ; Module length
  179.     SUB    R0,R0,#4
  180.     MOV    R1,R8
  181.     LDR    R3,searchfor
  182.     BIC    R4,R3,#255
  183. search    SUBS    R0,R0,#4    ; Search for 'print Rn'
  184.     MOVEQ    R1,#0        ; Set address to 0 if not found
  185.     BEQ    nomatch
  186.     LDR    R2,[R1],#4
  187.     TEQ    R2,R3
  188.     LDREQ    R2,[R1,#8]
  189.     TEQEQ    R2,R4
  190.     BNE    search
  191. nomatch    STR    R1,rnameaddr    ; Store address
  192.     TEQ    R1,#0        ; Found?
  193.     ADRNE    R0,renamecode    ; If so, replace SWI with BL to my code
  194.     SUBNE    R0,R0,R1
  195.     SUBNE    R0,R0,#4
  196.     MOVNE    R0,R0,LSL #6
  197.     MOVNE    R0,R0,LSR #8
  198.     ORRNE    R0,R0,#&EB000000
  199.     STRNE    R0,[R1,#-4]
  200. params    MOV    R0,R10        ; Decode parameters passed in by OS_Module
  201.     MOV    R1,#0
  202.     BL    memoryflags1    ; ignoring errors
  203.     MOV    R0,#4        ; Which ARM?
  204.     ADR    R2,undefid    ; Need to trap undefined instruction
  205.     SUB    R2,R2,#12    ; in case ARM2 or ARM250
  206.     MOV    R2,R2,LSR #2
  207.     ORR    R2,R2,#&EA000000
  208.     LDR    R1,[R0]
  209.     STR    R2,[R0]        ; = SWP R1,R2,[R0]
  210.     MOV    R2,#&200    ; ID = ARM2 if next instruction 'undefined'
  211.     MRC    CP15,0,R2,C0,C0    ; ARM ID
  212. undefid    STR    R1,[R0]        ; Restore trap
  213.     AND    R2,R2,#&FF00    ; Get part type [top 8 bits of if >=ARM6]
  214.     CMP    R2,#&600
  215.     LDRHS    R2,flags
  216.     ORRHS    R2,R2,#flag_arm6 ; Set 'ARM6' flag if ARM6 or later
  217.     STRHS    R2,flags
  218.     LDMFD    R13!,{PC}^
  219. searchfor            ; Code to search for in the Debugger module
  220.     SWI    XOS_BinaryToDecimal
  221. initfailed
  222.     & 0
  223.     = "Failed to install new Debugger_Disassemble",0
  224.     ALIGN
  225.  
  226.  
  227. exit    STMFD    R13!,{R14}    ; When RMKilled
  228.     MOV    R1,#0
  229.     STR    R1,workspace    ; Reset...
  230.     MOV    R0,#18
  231.     ADRL    R1,debug
  232.     SWI    XOS_Module    ; Find Debugger
  233.     BVS    released    ; Killed?
  234.     ADR    R4,swijump
  235.     LDMIA    R4,{R0,R2}
  236.     TEQ    R2,R3        ; Or moved?
  237.     BNE    released
  238.     TEQ    R1,#0        ; If not...
  239.     LDRNE    R1,firstinstr    ; Restore SWI code
  240.     STRNE    R1,[R0,#-4]
  241.     LDR    R1,rnameaddr    ; Restore 'print Rn' code
  242.     TEQ    R1,#0
  243.     LDRNE    R0,searchfor
  244.     STRNE    R0,[R1,#-4]
  245. released
  246.     MOV    R0,#7
  247.     LDR    R2,[R12]
  248.     SWI    XOS_Module
  249.     MOV    R0,#0
  250.     STR    R0,[R12]
  251.     LDMFD    R13!,{PC}^
  252.  
  253. swijump      & 0,0
  254. workspace & 0
  255. rnameaddr & 0
  256.  
  257.  
  258. swi_flags
  259.     STMFD    R13!,{R14}    ; Debugger_63
  260.     LDR    R12,workspace
  261.     LDR    R14,flags    ; flags = (flags BIC R0) EOR R1
  262.     BIC    R0,R14,R0
  263.     EOR    R1,R0,R1    ; Returns R0 = old flags, R1 = new flags
  264.     STR    R1,flags
  265.     MOV    R0,R14
  266.     LDMFD    R13!,{PC}^
  267.  
  268.  
  269. renamecode
  270.     STMFD    R13!,{R12,R14}
  271.     LDR    R12,workspace
  272.     LDR    R14,flags
  273.     TST    R14,#flag_apcs
  274.     BNE    dorename
  275.     SWI    XOS_BinaryToDecimal
  276.     LDMFD    R13!,{R12,PC}
  277. dorename
  278.     MOV    R14,#8
  279.     STRB    R14,[R1]
  280.     ADR    R14,apcs_names
  281.     LDR    R2,[R14,R0,LSL #1]!
  282.     STRB    R2,[R1,#1]
  283.     MOV    R2,R2,LSR #8
  284.     STRB    R2,[R1,#2]
  285.     MOV    R2,#0
  286.     CMP    R0,#9
  287.     STRGTB    R2,[R1,#4]
  288.     MOVGT    R2,#" "
  289.     STRB    R2,[R1,#3]
  290.     MOVGT    R2,#4
  291.     MOVLE    R2,#3
  292.     LDMFD    R13!,{R12,PC}^
  293.  
  294.  
  295. tab    SUB    R0,R8,R12
  296.     CMP    R0,#buffptr+8    ; Tabulate
  297.     MOVLT    R1,#buffptr+8    ; Tab stops set at columns 8 and 27
  298.     MOVGE    R1,#buffptr+27
  299.     CMP    R0,#buffptr+27
  300.     ADDGE    R1,R0,#1
  301.     ADD    R1,R1,R12
  302.     MOV    R0,#" "
  303. tabloop    STRB    R0,[R8],#1
  304.     TEQ    R8,R1
  305.     BNE    tabloop
  306.     MOVS    PC,R14
  307.  
  308. copy    STMFD    R13!,{R2,R14}    ; Copy string, leaving R8 -> null
  309. copy_lp    LDRB    R2,[R0],#1
  310.     STRB    R2,[R8],#1
  311.     TEQ    R2,#0
  312.     BNE    copy_lp
  313.     SUB    R8,R8,#1
  314.     LDMFD    R13!,{R2,PC}^
  315.  
  316. regno    LDRB    R1,[R8,#-1]    ; Register number or constant (0 to 15)
  317.     TEQ    R1,#"R"        ; Is it an ARM register?
  318.     BNE    regnotr
  319.     LDR    R1,flags
  320.     TEQ    R0,#15        ; Is it R15 (and not APCS-R names)?
  321.     TSTEQ    R1,#2
  322.     BEQ    is_pc
  323.     CMP    R0,#8        ; Is it in range R8..R14?
  324.     MOVGE    R5,R0        ; If so, flag it for later
  325.     TST    R1,#2        ; Are we using APCS-R names?
  326.     BEQ    regnotr
  327.     ADR    R1,apcs_names    ; If so, write register name
  328.     LDR    R0,[R1,R0,LSL #1]!
  329.     STRB    R0,[R8,#-1]    ; overwriting the "R" already there
  330.     MOV    R0,R0,LSR #8
  331.     STRB    R0,[R8],#1
  332.     MOVS    PC,R14
  333. apcs_names = "a1a2a3a4v1v2v3v4v5v6slfpipsplrpc"
  334. regnotr    ADD    R0,R0,#"0"    ; Store number
  335.     CMP    R0,#"9"
  336.     MOVGT    R1,#"1"
  337.     STRGTB    R1,[R8],#1
  338.     SUBGT    R0,R0,#10
  339.     STRB    R0,[R8],#1
  340.     MOVS    PC,R14
  341. is_pc    MOV    R0,#"P"        ; Store R15 as PC
  342.     STRB    R0,[R8,#-1]    ; overwriting "R" with "P"
  343.     MOV    R0,#"C"
  344.     STRB    R0,[R8],#1
  345.     MOVS    PC,R14
  346.  
  347. undefined
  348.     LDR    R1,flags    ; Undefined instruction
  349.     TST    R1,#flag_usedcd    ; Use "Undefined" or "DCD"?
  350.     ADREQ    R1,undef    ; "Undefined"
  351.     MOVEQ    R2,#useofnv-undef
  352.     LDMEQFD    R13!,{R0,R3-R12,PC}^
  353. usedcd    ADR    R0,dcd        ; "DCD"
  354.     ADR    R8,buffer
  355.     BL    copy
  356.     MOV    R0,R10
  357.     MOV    R1,R8
  358.     MOV    R2,#9
  359.     SWI    XOS_ConvertHex8
  360.     ADR    R1,buffer
  361.     SUB    R2,R8,R12
  362.     SUB    R2,R2,#buffptr
  363.     LDMFD    R13!,{R0,R3-R12,PC}^
  364.  
  365. undef    = "Undefined instruction",0
  366. dcd    = "DCD     &",0
  367. useofnv    = "; *** Use of NV",0
  368. not8_14 = "; *** Not R8-R14",0
  369. cdp_swi    = "; *** SWI after CDP",0
  370.     ALIGN
  371.  
  372. ; "append" always means to disassembled string
  373.  
  374. testnv    ADR    R0,prev        ; NV test, and tests based on previous instr.
  375.     LDMIA    R0,{R2,R3}
  376.     STMIA    R0,{R10,R11}
  377.     MOV    R0,R10,LSR #28
  378.     CMP    R0,#15        ; Is NV used?
  379.     BLEQ    tab
  380.     ADREQ    R0,useofnv
  381.     BLEQ    copy        ; If so, append warning and exit
  382.     BEQ    nomasks
  383.     ADD    R3,R3,#4    ; Was last instruction disassembled
  384.     TEQ    R3,R11        ; immediately before this one?
  385.     BNE    nomasks        ; If not, exit
  386.     CMP    R5,#0
  387.     BEQ    trycdp
  388.     ADR    R9,maskp    ; R8..R14 used after TSTP/TEQP/CMPP/CMNP ?
  389.     LDMIA    R9!,{R0,R1}
  390.     AND    R0,R2,R0
  391.     TEQ    R0,R1
  392.     BLEQ    tab
  393.     ADREQ    R0,not8_14    ; If so, append warning
  394.     BLEQ    copy
  395. trycdp    ADR    R9,maskcdp    ; SWI after CDP ?
  396.     LDMIA    R9!,{R0,R1}
  397.     AND    R0,R2,R0
  398.     TEQ    R0,R1
  399.     ANDEQ    R0,R10,#&F000000
  400.     TEQEQ    R0,#&F000000
  401.     BLEQ    tab
  402.     ADREQ    R0,cdp_swi    ; If so, append warning
  403.     BLEQ    copy
  404. nomasks    ADR    R1,buffer
  405.     SUB    R2,R8,R12
  406.     SUB    R2,R2,#buffptr
  407.     LDMFD    R13!,{R0,R3-R12,PC}^
  408. maskp    & &D90F000, &110F000    ; R8..R14 test
  409. maskcdp    & &F000010, &E000000    ; CDP/SWI test
  410.  
  411. swihandler
  412.     TEQ    R11,#0        ; Replacement for Debugger_Disassemble
  413.     BEQ    disasm
  414.     TEQ    R11,#63        ; Extra SWI (Debugger_63) for flag toggling
  415.     BEQ    swi_flags
  416. firstinstr &    0
  417.     LDR    PC,swijump    ; (passing on others to the Debugger module)
  418. disasm    STMFD    R13!,{R0,R3-R12,R14}
  419.     MOV    R10,R0        ; word
  420.     MOV    R11,R1        ; address
  421.     LDR    R12,workspace
  422.     LDMIA    R12,{R0,R1}    ; Special case for ADRL/ADRX
  423.     ADD    R1,R1,#4
  424.     TEQ    R1,R11
  425.     BLEQ    adrlchk
  426.     MOV    R0,#0
  427.     STR    R0,adrlx_f
  428.     MOV    R1,R10,LSL #20    ; Special case for ANDEQ & similar
  429.     MOV    R1,R1,LSR #20
  430.     ANDS    R0,R10,#&FF00000
  431.     TEQNE    R0,#&200000    ; trapping AND, EOR, ORR, BIC
  432.     TEQNE    R0,#&1800000    ; with same register for both sources
  433.     TEQNE    R0,#&1C00000    ; and no shift
  434.     ANDEQ    R9,R10,#&F0000
  435.     TEQEQ    R1,R9,LSR #16
  436.     BEQ    andeq
  437.     TEQ    R0,#&1A00000    ; and MOV and MVN with same register
  438.     TEQNE    R0,#&1E00000    ; for both source and destination, no shift
  439.     ANDEQ    R9,R10,#&F000
  440.     TEQEQ    R1,R9,LSR #12
  441.     BEQ    moveq
  442. gofind    LDR    R9,flags
  443.     TST    R9,#flag_usevdu    ; 'VDU' flag set?
  444.     ADREQL    R9,instructions    ; Point to instruction templates list
  445.     ADRNEL    R9,withvdu    ; including VDU if selected
  446. find    LDMIA    R9,{R0-R2}    ; Search list
  447.     ANDS    R2,R2,#255
  448.     BEQ    undefined    ; Undefined instruction if not in list
  449.     AND    R0,R0,R10
  450.     TEQ    R0,R1        ; Use mask to see if this is it
  451.     ADDNE    R9,R9,R2
  452.     BNE    find        ; If not, try next template
  453.     LDRB    R0,[R9,#9]!    ; Is template string = ""?
  454.     TEQ    R0,#0
  455.     BEQ    undefined    ; If so, is undefined instruction
  456. godecode
  457.     MOV    R5,#0        ; Set R8..R14 flag to FALSE
  458.     MOV    R6,#0        ; Set offset flag to 0
  459.     ADR    R8,buffer    ; Start of buffer
  460. decode    LDRB    R0,[R9],#1    ; Get next char from template string
  461.     STRB    R0,[R8]        ; Append
  462.     TEQ    R0,#0
  463.     BEQ    testnv        ; End of string? If so, check NV and flags
  464.     TEQ    R0,#32
  465.     BLEQ    tab        ; Space = tab
  466.     BEQ    decode
  467.     SUBS    R1,R0,#"¡"
  468.     ADDMI    R8,R8,#1
  469.     ADDPL    PC,PC,R1,LSL #2
  470.     B    decode
  471.     B    mul_check    ; ¡    MUL - Rd=Rm or Rd=PC ?
  472.     B    minus        ; ¢    sign for load/store instructions
  473.     B    ld_st        ; £    LD or ST
  474.     B    psr_user    ; ¤    "^" flag
  475.     B    f_0to2        ; ¥    FP reg
  476.     B    b_21to23    ; ¦    Constant
  477.     B    r_8to11        ; §    R reg
  478.     B    byte        ; ¨    "B" flag
  479.     B    condition    ; ©
  480.     B    r_12to15    ; ª
  481.     B    precision    ; «    FP precision, S/D/E/P
  482.     B    f_12to14    ; ¬
  483.     B    f_16to18    ; ­    (note: code 173)
  484.     B    f_0to2orconst    ; ®    FP reg or constant
  485.     B    const        ; ¯    ARM constant for MOV etc.
  486.     B    branch        ; °    Address
  487.     B    stack        ; ±    Stack type
  488.     B    reglist        ; ²    Register list for stack instructions
  489.     B    r_16to19    ; ³
  490.     B    offset12    ; ´    Offset for LDR/STR
  491.     B    pflag        ; µ    "P" flag
  492.     B    swi        ; ¶    SWI name or number
  493.     B    psr        ; ·    CPSR/SPSR
  494.     B    sflag        ; ¸    "S" flag
  495.     B    tflag        ; ¹    "T" flag
  496.     B    r_0to3        ; º
  497.     B    round        ; »    FP rounding, <blank>/P/M/Z
  498.     B    writeback    ; ¼    "!" flag
  499.     B    psr_part    ; ½    Which part of CPSR/SPSR to update
  500.     B    offset8        ; ¾    Offset for LDF/STF/LDC/STC
  501.     B    shift        ; ¿    LSL/LSR/ASR/ROR/RRX
  502.     B    numregs        ; À    Number of registers for LFM/SFM
  503.     B    c_5to7        ; Á    Constant for CDP/MCR/MRC
  504.     B    pc_offset12    ; Â    [PC,#offset] -> address for LDR/STR
  505.     B    pc_offset8    ; Ã    [PC,#offset] -> address for LDF etc.
  506.     B    offsetis    ; Ä    ; =offset
  507.     B    b_20to23    ; Å    Constant for CDP
  508.     B    lflag        ; Æ    "L" flag
  509.     B    cache        ; Ç    Cache registers
  510.     B    adr        ; È    ADR address
  511.     B    adrl        ; É    ADRL/ADRX address
  512.     B    lfm_sfm        ; Ê    LFM/SFM - which format (token string)
  513.     B    lfs_sfs        ; Ë    LFS/SFS reg list
  514.     B    arith        ; Ì    AND/EOR/.../SBC/RSC
  515.     B    test        ; Í    Compare, move, ORR, BIC
  516.     B    fparith        ; Î    FP binary (ADF etc)
  517.     B    fparithunary    ; Ï    FP unary (MVF etc)
  518.     B    fptrans        ; Ð    FP/ARM transfer (WFS etc)
  519.     B    fpcompare    ; Ñ    FP compare
  520.     B    mull        ; Ò    ARM7 long multiply
  521.     B    arm250orlater    ; Ó    ARM250
  522.     B    arm6orlater    ; Ô    ARM6
  523.     B    arm7orlater    ; Õ    ARM7
  524.     B    char        ; Ö    VDU (OS_WriteI substitute)
  525.     B    r12offset    ; ×    'W' option validation (1st char only)
  526.     B    adrwoff        ; Ø    ADRW constant
  527.     B    ldrwoff        ; Ù    LDRW/STRW constant
  528.  
  529. adrl_template    = "ADR©L Rª,&É",0
  530. adrx_template    = "ADR©X Rª,&É",0
  531.     ALIGN
  532.  
  533. adrlchk    LDR    R9,adrlx_f
  534.     SUB    R9,R9,#1
  535.     CMP    R9,#1
  536.     MOVHIS    PC,R14
  537.     AND    R9,R10,#&0FF00000
  538.     TEQ    R9,#&02400000
  539.     TEQNE    R9,#&02800000
  540.     ANDEQ    R1,R10,#&F000
  541.     ANDEQ    R2,R10,#&F0000
  542.     ANDEQ    R9,R0,#&F000
  543.     TEQEQ    R1,R2,LSR #4
  544.     TEQEQ    R1,R9
  545.     MOVEQ    R9,R10,LSR #28
  546.     MOVEQ    R1,R0,LSR #28
  547.     TEQEQ    R1,R9
  548.     MOVNES    PC,R14
  549.     LDR    R9,adrlx_f
  550.     TEQ    R9,#1
  551.     ADREQ    R9,adrl_template
  552.     ADRNE    R9,adrx_template
  553.     B    godecode
  554.  
  555. moveq    TEQ    R1,#0
  556.     ADREQ    R9,nop_template
  557.     BEQ    godecode
  558. andeq    LDR    R9,flags
  559.     TST    R9,#flag_andeqasdcd
  560.     BEQ    gofind
  561.     LDR    R9,movpcpc
  562.     TEQ    R9,R10,LSL #4
  563.     BNE    usedcd
  564.     B    gofind
  565. movpcpc    &    &1A0F00F0    ; (MOV PC,PC) :SHL: 4
  566. nop_template
  567.     = "NOP©",0
  568.     ALIGN
  569.  
  570. psr_user
  571.     TST    R10,#1:SHL:22    ; "^" flag
  572.     BEQ    decode
  573.     MOV    R0,#"^"
  574.     STRB    R0,[R8],#1
  575.     AND    R0,R10,#3:SHL:21
  576.     TEQ    R0,#3:SHL:21
  577.     TSTEQ    R10,#1:SHL:15
  578.     BLEQ    tab
  579.     ADREQ    R0,wrbk_user    ; Append comment if ! and ^ and no R15
  580.     BLEQ    copy
  581.     B    decode
  582.  
  583. wrbk_user = "; *** ! and ^",0
  584. is_st    = "ST",0
  585. is_ld    = "LD",0
  586.     ALIGN
  587.  
  588. ld_st    TST    R10,#1:SHL:20    ; LD or ST
  589.     ADREQ    R0,is_st
  590.     ADRNE    R0,is_ld
  591. copy_x    BL    copy
  592.     B    decode
  593.  
  594. f_0to2    AND    R0,R10,#7    ; FP register
  595. regno_x    BL    regno
  596.     B    decode
  597.  
  598. b_21to23
  599.     MOV    R0,R10,LSR #21    ; Constant
  600.     AND    R0,R0,#7
  601.     B    regno_x
  602.  
  603. r_8to11    MOV    R0,R10,LSR #8    ; ARM register
  604.     AND    R0,R0,#15
  605.     B    regno_x
  606.  
  607. byte    TST    R10,#1:SHL:22    ; "B" flag
  608.     MOVNE    R0,#"B"
  609.     STRNEB    R0,[R8],#1
  610.     B    decode
  611.  
  612. condition
  613.     MOV    R0,R10,LSR #28    ; Condition code
  614.     TEQ    R0,#&E
  615.     ADRNE    R1,conds
  616.     LDRNEB    R0,[R1,R0,LSL #1]!
  617.     STRNEB    R0,[R8],#1
  618.     LDRNEB    R0,[R1,#1]
  619.     STRNEB    R0,[R8],#1
  620.     B    decode
  621. conds    = "EQNECSCCMIPLVSVCHILSGELTGTLEALNV"
  622.  
  623. r_12to15
  624.     MOV    R0,R10,LSR #12    ; ARM register
  625.     AND    R0,R0,#15
  626.     B    regno_x
  627.  
  628. precision
  629.     AND    R0,R10,#&F000000
  630.     TEQ    R0,#&E000000    ; FP precision
  631.     MOVEQ    R0,R10,LSR #7
  632.     BICEQ    R0,R0,#&FE
  633.     BICEQ    R0,R0,#&F00
  634.     ORREQ    R0,R0,R0,LSR #11
  635.     MOVNE    R0,R10,LSR #15
  636.     BICNE    R0,R0,#&7E
  637.     ORRNE    R0,R0,R0,LSR #6
  638.     AND    R0,R0,#3
  639.     ADR    R1,precs
  640.     LDRB    R0,[R1,R0]
  641.     STRB    R0,[R8],#1
  642.     B    decode
  643. precs    = "SDEP"
  644.  
  645. f_12to14
  646.     MOV    R0,R10,LSR #12    ; FP register
  647.     AND    R0,R0,#7
  648.     B    regno_x
  649.  
  650. f_16to18
  651.     MOV    R0,R10,LSR #16    ; FP register
  652.     AND    R0,R0,#7
  653.     B    regno_x
  654.  
  655. f_0to2orconst
  656.     AND    R0,R10,#7    ; FP register or constant
  657.     TST    R10,#8
  658.     MOVEQ    R1,#"F"
  659.     MOVNE    R1,#"#"
  660.     STRB    R1,[R8],#1
  661.     BEQ    regno_x
  662.     ADR    R1,fpconsts
  663.     ADD    R0,R1,R0,LSL #2
  664.     B    copy_x
  665. fpconsts
  666.     = "0.0",0, "1.0",0, "2.0",0, "3.0",0
  667.     = "4.0",0, "5.0",0, "0.5",0, "10.0",0
  668.     ALIGN
  669.  
  670. const    AND    R0,R10,#255    ; ARM constant for MOV etc.
  671.     MOV    R1,R10,LSR #7
  672.     AND    R1,R1,#30
  673.     MOV    R0,R0,ROR R1
  674. vdu_com    CMP    R0,#9        ; 0 to 9 : just append digit
  675.     ADDLS    R1,R0,#"0"
  676.     MOVHI    R1,#"&"        ; or "&" if > 9
  677.     STRB    R1,[R8],#1
  678.     BLS    decode
  679.     MOV    R7,R0
  680.     MOV    R1,R8
  681.     MOV    R2,#9
  682.     CMP    R0,#&10000    ; >= 65536 - 8 digit hex
  683.     BHS    hex8
  684.     TST    R0,#&FF00    ; >= 256 - 4 digit hex
  685.     BNE    hex4
  686.     SWI    XOS_ConvertHex2 ; else     - 2 digit hex
  687.     MOV    R8,R1
  688. equals    CMP    R7,#8192    ; Is const < 8192 ?
  689.     BHS    decode
  690.     BL    tab        ; If so, append comment...
  691.     ADR    R0,comment
  692.     BL    copy
  693.     CMP    R7,#127
  694.     CMPNE    R7,#31
  695.     RSBHIS    R0,R7,#256    ; If <256 and is printable, use ; ="<chr>"
  696.     BLS    notchar
  697.     MOV    R0,#34
  698.     STRB    R0,[R8],#1
  699.     STRB    R7,[R8],#1
  700.     STRB    R0,[R8],#1
  701.     B    decode
  702. notchar    MOV    R0,R7        ; Otherwise use ; =<decimal>
  703.     MOV    R1,R8
  704.     MOV    R2,#9
  705.     SWI    XOS_ConvertInteger4
  706.     MOV    R8,R1
  707.     B    decode
  708. comment    = "; =",0
  709. hex4    SWI    XOS_ConvertHex4
  710.     MOV    R8,R1
  711.     B    equals
  712. hex8    SWI    XOS_ConvertHex8
  713.     MOV    R8,R1
  714.     B    equals
  715.  
  716. branch    BIC    R0,R10,#&FF000000
  717.     MOV    R0,R0,LSL #8    ; Convert branch offset into address
  718.     ADD    R1,R11,#8
  719.     ADD    R0,R1,R0,ASR #6
  720.     BIC    R0,R0,#&FC000003
  721. address    MOV    R1,R8
  722.     MOV    R2,#9
  723.     SWI    XOS_ConvertHex8
  724.     MOV    R8,R1
  725.     B    decode
  726.  
  727. stack    MOV    R0,R10,LSR #23    ; Decode stack type
  728.     AND    R0,R0,#3
  729.     LDR    R1,flags
  730.     TST    R1,#1        ; Is the R13 flag set?
  731.     BEQ    noR13
  732.     MOV    R1,R10,LSR #16
  733.     AND    R1,R1,#15
  734.     TEQ    R1,#13        ; Is R13 the base register?
  735.     BNE    noR13
  736.     TST    R10,#1:SHL:20
  737.     ADD    R0,R0,#4    ; if STM, point to STM stack types
  738.     ADDNE    R0,R0,#4    ; similarly for LDM
  739. noR13    ADR    R1,stacks    ; Any of R13 conditions false
  740.     LDRB    R0,[R1,R0,LSL #1]!
  741.     STRB    R0,[R8],#1    ; Append stack type name
  742.     LDRB    R0,[R1,#1]
  743.     STRB    R0,[R8],#1
  744.     B    decode
  745. stacks    = "DAIADBIB"    ; normal
  746.     = "EDEAFDFA"    ; STM
  747.     = "FAFDEAED"    ; LDM
  748.  
  749. reglist MOV    R2,R10,LSL #16    ; Register list for LDM/STM
  750.     MOVS    R2,R2,LSR #16    ; Output is of the form "R0,R1,R3-R5,PC"
  751.     BEQ    decode
  752.     MOV    R3,#0
  753. regloop    MOVS    R2,R2,LSR #1
  754.     BCC    nextreg
  755.     MOV    R0,#"R"
  756.     STRB    R0,[R8],#1
  757.     MOV    R0,R3
  758.     BL    regno
  759.     BEQ    decode
  760.     AND    R0,R2,#3
  761.     TEQ    R0,#3
  762.     MOVEQ    R0,#"-"
  763.     MOVNE    R0,#","
  764.     STRB    R0,[R8],#1
  765.     BNE    nextreg
  766. range    MOVS    R2,R2,LSR #1
  767.     ADDCS    R3,R3,#1
  768.     BCS    range
  769.     MOV    R2,R2,LSL #1
  770.     MOV    R0,#"R"
  771.     STRB    R0,[R8],#1
  772.     MOV    R0,R3
  773.     BL    regno
  774.     MOVNE    R0,#","
  775.     STRNEB    R0,[R8],#1
  776. nextreg    ADD    R3,R3,#1
  777.     CMP    R3,#16
  778.     BLT    regloop
  779.     B    decode
  780.  
  781. r_16to19
  782.     MOV    R0,R10,LSR #16    ; ARM register
  783.     AND    R0,R0,#15
  784.     B    regno_x
  785.  
  786. offset12
  787.     MOV    R0,R10,LSL #20    ; Offset for LDR/STR
  788.     MOV    R0,R0,LSR #20
  789. offset    CMP    R0,#10        ; Common offset code
  790.     ADDLT    R0,R0,#"0"
  791.     STRLTB    R0,[R8],#1    ; 0 to 9? Append digit
  792.     BLT    decode
  793.     MOV    R6,R0        ; Copy offset to offset flag
  794.     MOV    R1,R8
  795.     MOV    R2,#9        ; Else append as hex
  796.     SWI    XOS_ConvertHex4
  797.     MOV    R2,#"&"        ; Overwrite first "0" with "&"
  798.     STRB    R2,[R0]        ; (we end up with something like &123)
  799.     MOV    R8,R1
  800.     B    decode
  801.  
  802. pflag    AND    R0,R10,#&F000    ; "P" flag
  803.     TEQ    R0,#&F000
  804.     MOVEQ    R0,#"P"
  805.     STREQB    R0,[R8],#1
  806.     B    decode
  807.  
  808. swi    BIC    R0,R10,#&FF000000
  809.     MOV    R1,R8        ; SWI name
  810.     LDR    R2,flags
  811.     TST    R2,#flag_quoteswis
  812.     MOVNE    R2,#34        ; Put quote if required
  813.     STRNEB    R2,[R1],#1
  814.     MOV    R2,#224
  815.     MOV    R7,R1
  816.     SWI    XOS_SWINumberToString
  817.     MOV    R1,R7
  818.     LDRB    R0,[R1]
  819.     TEQ    R0,#"X"
  820.     ADDEQ    R1,R1,#1
  821.     ADR    R0,swi_user    ; If "User", "OS_Undefined" or their X forms
  822.     BL    compare        ; we use the SWI number instead
  823.     ADRNE    R0,swi_undef
  824.     BLNE    compare
  825.     BEQ    swinum
  826.     ADD    R8,R8,R2
  827.     LDR    R2,flags
  828.     TST    R2,#flag_quoteswis
  829.     SUBEQ    R8,R8,#1
  830.     MOVNE    R2,#34
  831.     STRNEB    R2,[R8],#1
  832.     B    decode
  833. swinum    MOV    R0,#"&"        ; Use the SWI number instead
  834.     STRB    R0,[R8],#1
  835.     BIC    R0,R10,#&FF000000
  836.     MOV    R1,R8
  837.     MOV    R2,#9
  838.     SWI    XOS_ConvertHex6
  839.     MOV    R8,R1
  840.     B    decode
  841. compare    STMFD    R13!,{R0-R3,R14}    ; String comparison (R0, R1)
  842. cploop    LDRB    R2,[R0],#1        ; Returns NE or EQ
  843.     LDRB    R3,[R1],#1
  844.     TEQ    R2,R3
  845.     LDMNEFD    R13!,{R0-R3,PC}
  846.     TEQ    R2,#0
  847.     BNE    cploop
  848.     LDMFD    R13!,{R0-R3,PC}
  849.  
  850. swi_user    = "User",0
  851. swi_undef    = "OS_Undefined",0
  852. cpsr    = "CPSR",0
  853. spsr    = "SPSR",0
  854.     ALIGN
  855.  
  856. psr    TST    R10,#1:SHL:22    ; Which PSR to use for MSR/MRS
  857.     ADREQ    R0,cpsr
  858.     ADRNE    R0,spsr
  859.     B    copy_x
  860.  
  861. sflag    TST    R10,#1:SHL:20    ; "S" flag
  862.     MOVNE    R0,#"S"
  863.     STRNEB    R0,[R8],#1
  864.     B    decode
  865.  
  866. tflag    TST    R10,#1:SHL:21    ; "T" flag
  867.     MOVNE    R0,#"T"
  868.     STRNEB    R0,[R8],#1
  869.     B    decode
  870.  
  871. r_0to3    AND    R0,R10,#15    ; ARM register
  872.     B    regno_x
  873.  
  874. round    MOV    R0,R10,LSR #5    ; FP rounding type
  875.     ANDS    R0,R0,#3
  876.     ADRNE    R1,rndchr
  877.     LDRNEB    R0,[R1,R0]
  878.     STRNEB    R0,[R8],#1
  879.     B    decode
  880. rndchr    = 0,"PMZ"
  881.  
  882. writeback
  883.     TST    R10,#1:SHL:21    ; "!" flag
  884.     MOVNE    R0,#"!"
  885.     STRNEB    R0,[R8],#1
  886.     B    decode
  887.  
  888. psr_part
  889.     MOV    R0,R10,LSR #16    ; PSR part to use for MSR/MRS
  890.     AND    R0,R0,#15
  891.     ADR    R1,psr_pnames
  892.     ADD    R1,R1,R0,LSL #1
  893.     ADD    R0,R1,R0,LSL #2
  894.     B    copy_x
  895. psr_pnames
  896.     = "_0000",0,  "_ctl",0,0, "_0010",0, "_0011",0
  897.     = "_0100",0,  "_0101",0,  "_0110",0, "_0111",0
  898.     = "_flg",0,0, "_all",0,0, "_1010",0, "_1011",0
  899.     = "_1100",0,  "_1101",0,  "_1110",0, "_1111",0
  900.  
  901. offset8    AND    R0,R10,#255    ; Offset for LDF/STF/LDC/STC
  902.     MOV    R0,R0,LSL #2
  903.     B    offset        ; Uses common offset code
  904.  
  905. shift    TST    R10,#16        ; Shifts and rotates
  906.     MOVNE    R2,#"R"        ; Register or immediate?
  907.     MOVNE    R3,R10,LSR #8
  908.     ANDNE    R3,R3,#15
  909.     MOVEQ    R2,#"#"
  910.     MOVEQ    R3,R10,LSR #7
  911.     ANDEQS    R3,R3,#31
  912.     MOVEQ    R3,#32        ; If immediate and shift by 0, set to 32
  913.     MOV    R1,R10,LSR #5    ; Get shift type
  914.     ANDS    R1,R1,#3
  915.     TEQEQ    R2,#"#"
  916.     TEQEQ    R3,#32
  917.     BEQ    decode        ; If LSL #0 [LSL #32], ignore it
  918.     TEQ    R1,#3
  919.     TEQEQ    R2,#"#"
  920.     TEQEQ    R3,#32
  921.     MOVEQ    R1,#4        ; If ROR #0 [ROR #32], set to RRX
  922.     ADR    R0,shname
  923.     ADD    R0,R0,R1,LSL #2
  924.     ADD    R0,R0,R1,LSL #1
  925.     BL    copy        ; Append shift name
  926.     TEQ    R1,#4
  927.     BEQ    decode        ; If RRX, don't append register or constant
  928.     STRB    R2,[R8],#1
  929.     MOV    R0,R3
  930.     TEQ    R2,#"R"
  931.     BEQ    regno_x        ; If register, append register number
  932.     MOV    R1,R8        ; else append constant
  933.     MOV    R2,#9
  934.     SWI    XOS_ConvertInteger4
  935.     MOV    R8,R1
  936.     B    decode
  937. shname    = ",LSL ",0, ",LSR ",0, ",ASR ",0, ",ROR ",0, ",RRX",0
  938.     ALIGN
  939.  
  940. numregs    AND    R0,R10,#1:SHL:15
  941.     MOV    R0,R0,LSR #15    ; Number of registers for LFM/SFM
  942.     AND    R1,R10,#1:SHL:22
  943.     ORRS    R0,R0,R1,LSR #21
  944.     MOVEQ    R0,#4
  945.     ADD    R0,R0,#"0"
  946.     STRB    R0,[R8],#1
  947.     B    decode
  948.  
  949. c_5to7    MOV    R0,R10,LSR #5    ; Constant
  950.     ANDS    R0,R0,#7
  951.     MOVNE    R1,#","
  952.     STRNEB    R1,[R8],#1
  953.     BLNE    regno
  954.     B    decode
  955.  
  956. pc_offset12
  957.     MOV    R0,R10,LSL #20    ; [PC,#offset] -> address, for LDR/STR
  958.     MOV    R0,R0,ASR #20
  959. pc_offset
  960.     TST    R10,#1:SHL:23
  961.     SUBEQ    R0,R11,R0
  962.     ADDNE    R0,R11,R0
  963.     ADD    R0,R0,#8
  964.     BIC    R0,R0,#&FC000000
  965.     B    address
  966.  
  967. pc_offset8
  968.     MOV    R0,R10,LSL #24    ; [PC,#offset] -> address, for copro
  969.     MOV    R0,R0,ASR #22
  970.     B    pc_offset
  971.  
  972. offsetis
  973.     TEQ    R6,#0        ; Append comment with offset as decimal
  974.     BEQ    decode        ; if > 9
  975.     BL    tab        ; (this is because the offset code above
  976.     ADRL    R0,comment    ; doesn't set this flag if offset < 10)
  977.     BL    copy
  978.     MOV    R0,R6
  979.     MOV    R1,R8
  980.     MOV    R2,#9
  981.     SWI    XOS_ConvertInteger4
  982.     MOV    R8,R1
  983.     B    decode
  984.  
  985. b_20to23
  986.     MOV    R0,R10,LSR #20    ; Constant
  987.     AND    R0,R0,#15
  988.     B    regno_x
  989.  
  990. lflag    TST    R10,#1:SHL:22    ; "L" flag
  991.     MOVNE    R0,#"L"
  992.     STRNEB    R0,[R8],#1
  993.     B    decode
  994.  
  995. cache    AND    R0,R10,#&F00    ; Append comment for cache control
  996.     TEQ    R0,#&F00    ; (if copro 15)
  997.     BNE    decode
  998.     MOV    R2,R10,LSR #16
  999.     AND    R2,R2,#15
  1000.     BL    tab
  1001.     LDR    R0,flags
  1002.     TST    R0,#flag_arm6    ; Test 'ARM6 or later' flag
  1003.     ADREQ    R0,cache3x
  1004.     ADRNE    R0,cache6x
  1005.     BL    copy
  1006.     ADREQ    R0,cache3
  1007.     BEQ    cachex
  1008.     TST    R10,#1:SHL:20    ; MCR or MRC?
  1009.     ADREQ    R0,cache6w
  1010.     ADRNE    R0,cache6r
  1011. cachex    LDRB    R2,[R0,R2]
  1012.     ADD    R0,R0,R2
  1013.     BL    copy
  1014.     B    decode
  1015. cache3    = cache30-cache3,cache31-cache3,cache32-cache3,cache33-cache3
  1016.     = cache34-cache3,cache35-cache3,cache3u-cache3,cache3u-cache3
  1017.     = cache3u-cache3,cache3u-cache3,cache3u-cache3,cache3u-cache3
  1018.     = cache3u-cache3,cache3u-cache3,cache3u-cache3,cache3u-cache3
  1019. cache6r    = cache60r-cache6r,cache6u -cache6r,cache6u -cache6r,cache6u -cache6r
  1020.     = cache6u -cache6r,cache65r-cache6r,cache66r-cache6r,cache6u -cache6r
  1021.     = cache6u -cache6r,cache6u -cache6r,cache6u -cache6r,cache6u -cache6r
  1022.     = cache6u -cache6r,cache6u -cache6r,cache6u -cache6r,cache6u -cache6r
  1023. cache6w    = cache6u -cache6w,cache61w-cache6w,cache62w-cache6w,cache63w-cache6w
  1024.     = cache6u -cache6w,cache65w-cache6w,cache66w-cache6w,cache67w-cache6w
  1025.     = cache6u -cache6w,cache6u -cache6w,cache6u -cache6w,cache6u -cache6w
  1026.     = cache6u -cache6w,cache6u -cache6w,cache6u -cache6w,cache6u -cache6w
  1027. cache3x        = "; ARM3 ",0
  1028. cache30
  1029. cache60r    = "ID",0
  1030. cache32
  1031. cache61w    = "control",0
  1032. cache33        = "cacheable",0
  1033. cache34        = "updateable",0
  1034. cache35        = "disruptive",0
  1035. cache3u
  1036. cache6u        = "- bad reg",0
  1037. cache6x        = "; ARM6 ",0
  1038. cache62w    = "MMU base",0
  1039. cache63w    = "domains",0
  1040. cache65r    = "FSR",0
  1041. cache65w    = "TLB flush ctrl",0
  1042. cache66r    = "FAR",0
  1043. cache66w    = "TLB purge ctrl",0
  1044. cache67w    = "IDC "
  1045. cache31        = "flush",0
  1046.     ALIGN
  1047.  
  1048. adr    ADD    R2,R11,#8    ; ADR address
  1049.     LDR    R1,flags
  1050.     TST    R1,#flag_useadrl ; If flag set, then
  1051.     MOVNE    R1,#1        ; set up ADRL/ADRX flag for poss. ADRL
  1052.     MOVEQ    R1,#0
  1053. adr_cmn    STR    R1,adrlx_f
  1054.     AND    R0,R10,#255    ; Base address in R2
  1055.     MOV    R1,R10,LSR #7    ; Calculate the offset
  1056.     AND    R1,R1,#30
  1057.     TST    R10,#1:SHL:22    ; then the referenced address
  1058.     ADDEQ    R0,R2,R0,ROR R1    ; (for efficiency we do the rotate NOW!)
  1059.     SUBNE    R0,R2,R0,ROR R1
  1060.     BIC    R0,R0,#&FC000000 ; mask for 26-bit value
  1061.     STR    R0,adrlx
  1062.     B    address        ; Now append the address
  1063.  
  1064. adrl    LDR    R3,prev        ; ADRL/ADRX address
  1065.     LDR    R2,adrlx    ; Get ADR address
  1066.     LDR    R1,adrlx_f
  1067.     ADD    R1,R1,#1    ; Set up for poss. ADRX
  1068.     TEQ    R1,#3        ; If already ADRX, set up for next ADR
  1069.     MOVEQ    R1,#0
  1070.     B    adr_cmn        ; Now sort out the extra offset
  1071.  
  1072. lfm_sfm    LDR    R1,flags    ; LFM and SFM - select display format
  1073.     TST    R1,#flag_lfmstack + flag_lfs
  1074.     BEQ    usefm        ; If no special format selected, use standard
  1075.     TST    R10,#1:SHL:20
  1076.     ADRNE    R9,mload
  1077.     ADREQ    R9,mstore
  1078.     TST    R1,#flag_lfs    ; Try to use LFS/SFS if selected
  1079.     ADDNE    R9,R9,#4    ; else try stack form of LFM/SFM
  1080.     MOV    R0,R10,LSR #15    ; Get number of FP registers
  1081.     BIC    R0,R0,#&7E
  1082.     ORR    R0,R0,R0,LSR #6
  1083.     ANDS    R0,R0,#3
  1084.     MOVEQ    R0,#4
  1085.     ADD    R0,R0,R0,LSL #1    ; Multiply by 3
  1086.     AND    R2,R10,#255    ; Get the offset (div 4)
  1087.     AND    R14,R10,#3:SHL:23
  1088.     TEQ    R14,#1:SHL:23    ; Post-indexed, +ve offset? IA form
  1089.     ADDEQ    R9,R9,#1
  1090.     BEQ    fmpos
  1091.     TEQ    R14,#2:SHL:23    ; Pre-indexed, -ve offset? DB form
  1092.     BNE    usefm
  1093.     TST    R10,#1:SHL:21    ; DB form: check writeback
  1094.     TEQEQ    R2,#0        ; If clear, and offset = 0, use this
  1095.     BEQ    usefmsm
  1096.     TEQ    R2,R0        ; DB form: offset = num of regs?
  1097.     BNE    usefm        ; If not, use standard form
  1098.     B    usefmsm        ; else use selected form
  1099. fmpos    TEQ    R2,#0        ; IA form: offset = 0?
  1100.     BICEQ    R10,R10,#1:SHL:21    ; if so, no writeback required
  1101.     TEQNE    R2,R0        ; IA form: offset = num of regs?
  1102.     BEQ    usefmsm
  1103. usefm    TST    R10,#1:SHL:24    ; Use standard form
  1104.     ADREQ    R9,fmsmpos
  1105.     ADRNE    R9,fmsmpre
  1106.     B    decode
  1107. usefmsm    TST    R1,#flag_stack    ; Use selected form
  1108.     BEQ    iadb        ; 'Stack' option selected?
  1109.     AND    R0,R10,#&F0000    ; If so, is R13 used?
  1110.     TEQ    R0,#&D0000
  1111.     ADDEQ    R9,R9,#2    ; If so, use FD/EA form
  1112. iadb    ADR    R0,iadb
  1113.     LDRB    R9,[R9]
  1114.     ADD    R9,R9,R0
  1115.     B    decode
  1116. mload    = fmdb-iadb, fmia-iadb, fmea-iadb, fmfd-iadb
  1117.     = fsdb-iadb, fsia-iadb, fsea-iadb, fsfd-iadb
  1118. mstore    = fmdb-iadb, fmia-iadb, fmfd-iadb, fmea-iadb
  1119.     = fsdb-iadb, fsia-iadb, fsfd-iadb, fsea-iadb
  1120. fmsmpos    = "M© F¬,À,[R³],#¢¾Ä",0        ; LFM/SFM normal
  1121. fmsmpre    = "M© F¬,À,[R³,#¢¾]¼Ä",0    ; LFM/SFM normal
  1122. fmdb    = "M©DB F¬,À,[R³]¼",0
  1123. fmia    = "M©IA F¬,À,[R³]¼",0
  1124. fmea    = "M©EA F¬,À,[R³]¼",0
  1125. fmfd    = "M©FD F¬,À,[R³]¼",0
  1126. fsdb    = "S©DB R³¼,{Ë}",0
  1127. fsia    = "S©IA R³¼,{Ë}",0
  1128. fsea    = "S©EA R³¼,{Ë}",0
  1129. fsfd    = "S©FD R³¼,{Ë}",0
  1130.     ALIGN
  1131.  
  1132. lfs_sfs    MOV    R0,R10,LSR #15    ; Get number of FP registers
  1133.     BIC    R0,R0,#&7E
  1134.     ORR    R0,R0,R0,LSR #6
  1135.     ANDS    R0,R0,#3
  1136.     MOVEQ    R0,#4
  1137.     SUBS    R0,R0,#1
  1138.     MOV    R1,R10,LSR #12
  1139.     MOV    R2,#"F"
  1140.     STRB    R2,[R8],#1
  1141.     AND    R1,R1,#7
  1142.     ADD    R1,R1,#"0"
  1143.     STRB    R1,[R8],#1
  1144.     BEQ    decode
  1145.     ADD    R1,R1,R0
  1146.     BIC    R1,R1,#8
  1147.     TEQ    R0,#1
  1148.     MOVEQ    R0,#","
  1149.     MOVNE    R0,#"-"
  1150.     STRB    R0,[R8],#1
  1151.     STRB    R2,[R8],#1
  1152.     STRB    R1,[R8],#1
  1153.     B    decode
  1154.  
  1155. arith    ADR    R0,arithlist
  1156. arith_test
  1157.     MOV    R1,R10,LSR #21
  1158.     AND    R1,R1,#7
  1159. arith_test_fp
  1160.     ADD    R0,R0,R1,LSL #2
  1161.     B    copy_x
  1162. arithlist = "AND",0,"EOR",0,"SUB",0,"RSB",0,"ADD",0,"ADC",0,"SBC",0,"RSC",0
  1163.  
  1164. test    ADR    R0,testlist
  1165.     B    arith_test
  1166. testlist = "TST",0,"TEQ",0,"CMP",0,"CMN",0,"ORR",0,"MOV",0,"BIC",0,"MVN",0
  1167.  
  1168. fparith    ADR    R0,fparithlist
  1169.     MOV    R1,R10,LSR #20
  1170.     AND    R1,R1,#15
  1171.     B    arith_test_fp
  1172. fparithlist
  1173.     = "ADF",0,"MUF",0,"SUF",0,"RSF",0,"DVF",0,"RDF",0,"POW",0,"RPW",0
  1174.     = "RMF",0,"FML",0,"FDV",0,"FRD",0,"POL",0,"F0D",0,"F0E",0,"F0F",0
  1175.  
  1176. fparithunary
  1177.     ADR    R0,fparithunarylist
  1178.     MOV    R1,R10,LSR #20
  1179.     AND    R1,R1,#15
  1180.     B    arith_test_fp
  1181. fparithunarylist
  1182.     = "MVF",0,"MNF",0,"ABS",0,"RND",0,"SQT",0,"LOG",0,"LGN",0,"EXP",0
  1183.     = "SIN",0,"COS",0,"TAN",0,"ASN",0,"ACS",0,"ATN",0,"URD",0,"NRM",0
  1184.  
  1185. fptrans    ADR    R0,fptranslist
  1186.     MOV    R1,R10,LSR #20
  1187.     AND    R1,R1,#15
  1188.     SUB    R1,R1,#2
  1189.     CMP    R1,#4
  1190.     BLT    arith_test_fp
  1191.     ADR    R0,fptransundef
  1192.     BL    copy
  1193.     CMP    R1,#8
  1194.     ADDLT    R1,R1,#"2"
  1195.     ADDGE    R1,R1,#"C"-10
  1196.     STRB    R1,[R8],#1
  1197.     B    decode
  1198. fptranslist    = "WFS",0,"RFS",0,"WFC",0,"RFC",0
  1199. fptransundef    = "FT",0,0
  1200.  
  1201. mull    ADR    R0,mulllist
  1202.     MOV    R1,R10,LSR #21
  1203.     AND    R1,R1,#3
  1204.     ADD    R0,R0,R1
  1205.     B    arith_test_fp
  1206. mulllist = "UMUL",0,"UMLA",0,"SMUL",0,"SMLA",0
  1207.  
  1208. fpcompare
  1209.     MOV    R0,#"C"
  1210.     STRB    R0,[R8],#1
  1211.     TST    R10,#1:SHL:21
  1212.     MOVEQ    R0,#"M"
  1213.     MOVNE    R0,#"N"
  1214.     STRB    R0,[R8],#1
  1215.     MOV    R0,#"F"
  1216.     STRB    R0,[R8],#1
  1217.     TST    R10,#1:SHL:22
  1218.     MOVNE    R0,#"E"
  1219.     STRNEB    R0,[R8],#1
  1220.     B    decode
  1221.  
  1222. char    AND    R0,R10,#&FF
  1223.     B    vdu_com
  1224.  
  1225. r12offset
  1226.     LDR    R0,flags
  1227.     TST    R0,#flag_useadrw
  1228.     BEQ    notr12
  1229.     AND    R0,R10,#&0FF00000
  1230.     TEQ    R0,#&02400000
  1231.     TEQNE    R0,#&02800000
  1232.     ANDNE    R0,R10,#&0C000000
  1233.     TEQNE    R0,#&04000000
  1234.     ANDEQ    R0,R10,#&F000
  1235.     TEQEQ    R0,#&C000    ; No W form if R12 is destination register
  1236.     BEQ    notr12
  1237.     B    decode
  1238. notr12    SUB    R2,R2,#10
  1239.     ADD    R9,R9,R2
  1240.     B    find
  1241.  
  1242.  
  1243. adrwoff    AND    R0,R10,#&FF
  1244.     AND    R1,R10,#&F00
  1245.     MOV    R1,R1,LSR #7
  1246.     MOV    R0,R0,ROR R1
  1247.     B    address
  1248.  
  1249. ldrwoff    MOV    R0,R10,LSL #20
  1250.     MOV    R0,R0,LSR #20
  1251.     B    address
  1252.  
  1253. mul_check
  1254.     AND    R0,R10,#&F    ; Check for silly thing like MUL Rx,Rx,Ry
  1255.     AND    R1,R10,#&F0000    ; or MUL R15,Rx,Ry
  1256.     TEQ    R0,R1,LSR #16
  1257.     TEQNE    R1,#&F0000
  1258.     BLEQ    tab
  1259.     ADREQ    R0,rdisrm    ; Append comment if found
  1260.     BLEQ    copy
  1261.     B    decode
  1262. rdisrm    = "; *** Rd=Rm or Rd=PC",0
  1263.     ALIGN
  1264.  
  1265. minus    TST    R10,#1:SHL:23    ; Negative offset?
  1266.     MOVEQ    R0,#"-"
  1267.     STREQB    R0,[R8],#1
  1268.     B    decode
  1269.  
  1270. arm250orlater
  1271.     ADR    R2,arm250
  1272.     B    armxorlater
  1273. arm3orlater
  1274.     ADR    R2,arm3
  1275.     B    armxorlater
  1276. arm6orlater
  1277.     ADR    R2,arm6
  1278.     B    armxorlater
  1279. arm7orlater
  1280.     ADR    R2,arm7
  1281. armxorlater
  1282.     BL    tab        ; Append comment "ARMxxx or later"
  1283.     ADR    R0,arm
  1284.     BL    copy
  1285.     MOV    R0,R2
  1286.     BL    copy
  1287.     ADR    R0,orlater
  1288.     B    copy_x
  1289. arm    = "; ARM",0
  1290. arm250    = "250",0
  1291. arm3    = "3",0
  1292. arm6    = "6",0
  1293. arm7    = "7",0
  1294. orlater    = " and later",0
  1295.     ALIGN
  1296.  
  1297.  
  1298. ; This is the instruction templates list.
  1299.  
  1300. ; The order in which the tokens appear is important, since the list is
  1301. ; scanned sequentially.
  1302. ; Format is:
  1303. ;    +0    AND mask
  1304. ;    +4    TEQ value  (instruction AND mask == value)
  1305. ;    +8    Offset to next token (from one AND mask to the next)
  1306. ;    +9    Template string, null terminated
  1307. ;    Nulls appended to ensure word alignment
  1308. ; If offset to next token = 0, then this is the list terminator, not a token
  1309.  
  1310. withvdu
  1311.     Token    FFFFF00,F000100,"VDU© Ö"
  1312.     Token    FFFFF00,F020100,"VDU©X Ö"
  1313.  
  1314. instructions
  1315.  
  1316.     Token    FE000F0,0000090,"MUL©¸ R³,Rº,R§¡"
  1317.     Token    FE000F0,0200090,"MLA©¸ R³,Rº,R§,Rª¡"
  1318.     Token    FB000F0,1000090,"SWP©¨ Rª,Rº,[R³]Ó"
  1319.  
  1320.     Token    F8000F0,0800090,"Ò©¸ Rª,R³,Rº,R§Õ"
  1321.  
  1322.     Token    E0000F0,0000090,""
  1323.     Token    E0000F0,00000B0,""
  1324.     Token    E0000F0,00000D0,""
  1325.     Token    E0000F0,00000F0,""
  1326.     Token    E000010,6000010,""
  1327.  
  1328.     Token    FB0F000,120F000,"MSR© ·½,RºÔ"
  1329.     Token    FB6F000,320F000,"MSR© ·½,#¯Ô"
  1330.     Token    FBF0000,10F0000,"MRS© Rª,·Ô"
  1331.  
  1332.     Token    FFF0000,24C0000,"×ADR©W Rª,-&Ø"
  1333.     Token    FFF0000,28C0000,"×ADR©W Rª,&Ø"
  1334.  
  1335.     Token    FFF0000,24F0000,"ADR© Rª,&È"
  1336.     Token    FFF0000,28F0000,"ADR© Rª,&È"
  1337.  
  1338.     Token    F000000,0000000,"Ì©¸ Rª,R³,Rº¿"
  1339.     Token    F000000,2000000,"Ì©¸ Rª,R³,#¯"
  1340.  
  1341.     Token    F900000,1100000,"Í©µ R³,Rº¿"
  1342.     Token    F900000,3100000,"Í©µ R³,#¯"
  1343.     Token    FA00000,1800000,"Í©¸ Rª,R³,Rº¿"
  1344.     Token    FA00000,3800000,"Í©¸ Rª,R³,#¯"
  1345.     Token    FA00000,1A00000,"Í©¸ Rª,Rº¿"
  1346.     Token    FA00000,3A00000,"Í©¸ Rª,#¯"
  1347.  
  1348.     Token    F2F0000,50C0000,"×£R©¨W Rª,¢&Ù"
  1349.  
  1350.     Token    F000000,4000000,"£R©¨¹ Rª,[R³],#¢´Ä"
  1351.     Token    F2F0000,50F0000,"£R©¨¹ Rª,&Â"
  1352.     Token    F000000,5000000,"£R©¨ Rª,[R³,#¢´]¼Ä"
  1353.     Token    F000000,6000000,"£R©¨¹ Rª,[R³],¢Rº¿Ä"
  1354.     Token    F000000,7000000,"£R©¨ Rª,[R³,¢Rº¿]¼Ä"
  1355.  
  1356.     Token    E000000,8000000,"£M©± R³¼,{²}¤"
  1357.  
  1358.     Token    F000000,A000000,"B© &°"
  1359.     Token    F000000,B000000,"BL© &°"
  1360.     Token    F000000,F000000,"SWI© ¶"
  1361.  
  1362.     Token    F200000,C000000,""
  1363.  
  1364.     Token    F200F00,C200100,"£F©« F¬,[R³],#¢¾Ä"
  1365.     Token    F2F0F00,D0F0100,"£F©« F¬,&Ã"
  1366.     Token    F000F00,D000100,"£F©« F¬,[R³,#¢¾]¼Ä"
  1367.  
  1368.     Token    F3F0F00,C0F0200,"SFM© F¬,À,&Ã"
  1369.     Token    E100F00,C000200,"SFÊ"
  1370.     Token    F3F0F00,D1F0200,"LFM© F¬,À,&Ã"
  1371.     Token    E100F00,C100200,"LFÊ"
  1372.  
  1373.     Token    F008F10,E000100,"Ω«» F¬,F­,®"
  1374.     Token    F008F10,E008100,"Ï©«» F¬,®"
  1375.  
  1376.     Token    F90FF10,E90F110,"Ñ© F­,®"
  1377.  
  1378.     Token    FF00F10,E000110,"FLT©« F¥,Rª"
  1379.     Token    FF00F10,E100110,"FIX« Rª,®"
  1380.     Token    F000F10,E000110,"Щ Rª"
  1381.  
  1382.     Token    F000010,E000000,"CDP© CP§,Å,Cª,C³,CºÁ"
  1383.     Token    F100010,E000010,"MCR© CP§,¦,Rª,C³,CºÁÇ"
  1384.     Token    F100010,E100010,"MRC© CP§,¦,Rª,C³,CºÁÇ"
  1385.  
  1386.     Token    F000000,C000000,"£C©¹Æ CP§,Cª,[R³],#¢¾Ä"
  1387.     Token    F2F0000,D0F0000,"£C©Æ CP§,Cª,&Ã"
  1388.     Token    F000000,D000000,"£C©Æ CP§,Cª,[R³,#¢¾]¼Ä"
  1389.  
  1390.     & 0,0,0
  1391.  
  1392. memoryflags
  1393.     MOV    R1,#1
  1394. memoryflags1
  1395.     STMFD    R13!,{R1-R12,R14}
  1396.     LDR    R12,[R12]
  1397.     MOV    R10,R1
  1398.     MOV    R1,R0
  1399.     ADR    R0,args
  1400.     ADR    R2,buffer
  1401.     MOV    R3,#256-buffptr
  1402.     SWI    XOS_ReadArgs
  1403.     LDMVSFD    R13!,{R1-R12,PC}
  1404.     TEQ    R3,#256-buffptr-4*flag__b
  1405.     TEQEQ    R10,#1
  1406.     BEQ    current
  1407.     MOV    R2,#1:SHL:(flag__b-1)
  1408.     LDR    R3,flags
  1409.     ADR    R4,buffer+4*flag__b
  1410. flagbit    LDR    R0,[R4,#-4]!
  1411.     BL    yesno
  1412.     LDMVSFD    R13!,{R1-R12,PC}
  1413.     MOVS    R2,R2,LSR #1
  1414.     BNE    flagbit
  1415.     STR    R3,flags
  1416.     LDMFD    R13!,{R1-R12,PC}^
  1417. notyn_err
  1418.     & 220
  1419.     = "Bad switch state",0
  1420. args    = "fdwithr13=fd=f,"
  1421.     = "apcs=a,"
  1422.     = "lfmstack=sfmstack=lfm=sfm=m,"
  1423.     = "lfs=sfs=s,"
  1424.     = "quoteswis=quote=swi=q,"
  1425.     = "usedcd=dcd=d,"
  1426.     = "usevdu=vdu=v,"
  1427.     = "andeqasdcd=andeq=nop=n,"
  1428.     = "useadrl=adrl=l,"
  1429.     = "useadrw=adrw=w",0
  1430.     ALIGN
  1431. yesno    TEQ    R0,#0
  1432.     MOVEQS    PC,R14
  1433.     LDRB    R1,[R0,#1]
  1434.     TEQ    R1,#0
  1435.     BNE    notyn
  1436.     LDRB    R1,[R0]
  1437.     TEQ    R1,#"0"
  1438.     TEQNE    R1,#"N"
  1439.     TEQNE    R1,#"n"
  1440.     BICEQ    R3,R3,R2
  1441.     MOVEQS    PC,R14
  1442.     TEQ    R1,#"1"
  1443.     TEQNE    R1,#"Y"
  1444.     TEQNE    R1,#"y"
  1445.     ORREQ    R3,R3,R2
  1446.     MOVEQS    PC,R14
  1447. notyn    ADR    R0,notyn_err
  1448.     ORRS    PC,R14,#1:SHL:28
  1449. current    LDR    R8,flags
  1450.     ADR    R0,flagtext
  1451.     MOV    R7,#1
  1452. showflag
  1453.     LDRB    R1,[R0]
  1454.     TEQ    R1,#0
  1455.     LDMEQFD    R13!,{R1-R12,PC}^
  1456.     SWI    XOS_Write0
  1457.     LDMVSFD    R13!,{R1-R12,PC}
  1458.     TST    R8,R7
  1459.     BL    printyesno
  1460.     MOVVC    R7,R7,LSL #1
  1461.     BVC    showflag
  1462.     LDMFD    R13!,{R1-R12,PC}
  1463. printyesno
  1464.     STMFD    R13!,{R0,R14}
  1465.     ADREQ    R0,printno
  1466.     ADRNE    R0,printyes
  1467.     SWI    XOS_Write0
  1468.     SWIVC    XOS_NewLine
  1469.     LDMFD    R13!,{R0,PC}
  1470. printyes = " Yes",0
  1471. printno    = " No",0
  1472. flagtext
  1473.     = "                   Use FD with R13 :",0
  1474.     = "                    Use APCS names :",0
  1475.     = "      LFM/SFM stack where possible :",0
  1476.     = "LFS/SFS for LFM/SFM where possible :",0
  1477.     = "       Put quotes around SWI names :",0
  1478.     = "Use DCD for undefined instructions :",0
  1479.     = "  Use VDU instead of SWI OS_WriteI :",0
  1480.     = "Use DCD instead of ANDEQ & similar :",0
  1481.     = "     Use ADRL/X for ADR + ADD/SUBs :",0
  1482.     = "  Use ADRW/LDRW for R12±m/[R12,#m] :",0
  1483.     = 0
  1484.  
  1485.  
  1486.     END
  1487.