; Copyright 2001 Pace Micro Technology plc
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
;> Command

APPEND  BL      AEEXPR
        BL      OSSTRI
        BL      AEDONE
        LDR     R0,[ARGP,#PAGE]
        MOV     R2,#0
APPENDNO
        LDRB    R3,[R0,#1]
        CMP     R3,#&FF
        LDRNEB  R3,[R0,#3]
        MOVNE   R2,R0
        ADDNE   R0,R0,R3
        BNE     APPENDNO
        LDRB    R3,[R2,#1]
        LDRB    R0,[R2,#2]
        ORR     R7,R0,R3,LSL #8
        TEQ     R2,#0
        MOVEQ   R7,#10
        LDR     LINE,[ARGP,#TOP]
        SUB     R2,LINE,#2
        BL      OSFILELOAD
        BL      ENDER
 [ FPOINT=0
        MOV     FACC,R7
        BL      IFLT
        MOV     FGRD,#0
        BL      FTENFQ
        BL      FTENFQ
        BL      SFIX
 ELIF FPOINT=1
        FLTD    FACC,R7
        DVFD    FACC,FACC,#10
        DVFD    FACC,FACC,#10
        FIXZ    IACC,FACC
 ELIF FPOINT=2
        ; If we have VFP, we definitely have SMULL, so just use that
        LDR     IACC,=&28F5C28+1 ; (1<<32)/100 plus a small correction
        SMULL   R14,IACC,R7,IACC
 |
        ! 1, "Unknown FPOINT setting"
 ]
        ADD     IACC,IACC,#1
        RSB     R4,IACC,IACC,LSL #2    ;5
        ADD     R4,IACC,R4,LSL #3      ;2
        MOV     R4,R4,LSL #2           ;3
        SUB     R0,LINE,#2
        MOV     R5,#10
        BL      RENUM2
        B       FSASET
AUTO    BL      GETTWO
        BL      ENDER
00      STMFD   SP!,{R4,R5}
        MOV     R0,R4
        MOV     TYPE,#0
        BL      NPRN
        BL      INLINE
        BL      AUMATCH
        LDR     R4,[SP]
        ADD     LINE,ARGP,#OUTPUT
        BL      INSRT
        BL      SETFSA
        LDMFD   SP!,{R4,R5}
        ADD     R4,R4,R5
        CMP     R4,#65280
        BCC     %B00
        B       FSASET
GETTWO  STR     R14,[SP,#-4]!
        MOV     R0,#10
        BL      SPTSTN
        SUBNE   LINE,LINE,#1           ;if not found go backwards
        MOV     R4,R0                  ;start
        MOV     R0,#10
        BL      SPACES
        CMP     R10,#","
        BNE     NO
        BL      SPTSTN
        BLEQ    SPACES
NO      BL      DONE
        MOVS    R5,R0                  ;step
        LDRNE   PC,[SP],#4
        B       ERSILL
CRUNCH  BL      AEEXDN
        LDR     R1,[ARGP,#PAGE]
        BL      CRUNCHROUTINE
        STR     R2,[ARGP,#TOP]
        B       FSASET
DELETE  BL      SPTSTN
        BNE     ERSYNT
        MOV     R4,R0
        BL      SPACES
        CMP     R10,#","
        BNE     ERCOMM
        BL      SPTSTN
        BNE     ERSYNT
        MOV     R5,R0
        BL      REMOVE
        B       FSASET
HELP    BL      SPACES
        BL      LEXTABADR              ;R2=Lexical Table
        SUB     R0,LINE,#1             ;R0=characters to interpret
        ADRL    R1,Basic_Title         ;R1=my name
        BL      HELPPRN
        CMP     R1,#0
        BEQ     CLRSTK                 ;keyword hit
 [ OWNERRORS=1
        ADR     R0,HELPTTL
        SWI     OS_Write0
        SWI     OS_WriteS
        =       " assembled on ",0
        ADR     R0,HELPDATE
        SWI     OS_Write0
        SWI     OS_WriteI+"."
        SWI     OS_NewLine
 |
        ADR     R1,HELPTTL
        ADR     R2,HELPDATE
        MOV     R0,#26
        BL      MSGPRNSSX
 ]
        LDR     R14,[ARGP,#PAGE]
        LDR     R1,[ARGP,#TOP]
        SUB     R1,R1,R14              ;R1:=TOP-PAGE
        LDR     R14,[ARGP,#FSA]        ;per GIVEEND
        LDR     R2,[ARGP,#LOMEM]
        SUB     R2,R14,R2              ;R2:=END-LOMEM
        LDR     R3,[ARGP,#HIMEM]
        SUB     R3,R3,R14              ;R3:=HIMEM-END
 [ OWNERRORS=1
        Push    "R4,R7"
        SWI     OS_WriteS
        =       "The program size is ",0
        MOV     R0,R1
        MOV     R7,#0
        BL      CARDINALPRINT
        SWI     OS_WriteS
        =       " bytes, the variables use ",0
        MOV     R0,R2
        BL      CARDINALPRINT
        SWI     OS_WriteS
        =       " bytes. Theres are ",0
        MOV     R0,R3
        BL      CARDINALPRINT
        SWI     OS_WriteS
        =       " bytes of memory remaining.",10,13,0
        Pull    "R4,R7"
 |
        MOV     R0,#25
        BL      MSGPRNCCC
 ]
        B       CLRSTK

HELPTTL =       "ARM BBC BASIC V"
 [ FPOINT=1
        =       "I (64b FPA)"
 ELIF FPOINT=2
        =       "I (64b VFP)"
 ]
        =       0
HELPDATE
        =       "$Module_Date.",0

INSTALL LDR     R0,[ARGP,#HIMEM]
        LDR     R1,[ARGP,#MEMLIMIT]
        CMP     R0,R1
        BNE     ERINSTALL
        BL      LIBSUB
        LDR     R1,[ARGP,#MEMLIMIT]
        SUB     R1,R1,R4
        LDR     R0,[ARGP,#INSTALLLIST]
        STR     R0,[R1,#-4]!
        STR     R1,[ARGP,#MEMLIMIT]
        STR     R1,[ARGP,#HIMEM]
        STR     R1,[ARGP,#INSTALLLIST]
INSTALLCOPY
        LDR     R0,[R2,#4]!
        STR     R0,[R1,#4]!
        SUBS    R4,R4,#4
        BHI     INSTALLCOPY
        B       CLRSTK
LOAD    BL      LOADER
        B       FSASET
TEXTLOAD
        BL      AEEXPR
        BL      OSSTRI
        BL      AEDONE
        BL      LOADFILEFINAL
        B       FSASET
LOADFILEFINAL
        MOV     R0,#5
        ADD     R1,ARGP,#STRACC
        SWI     OS_File
        SUB     R7,SP,#1024
        CMP     R0,#1
        SUBEQ   R7,R7,R4
        LDR     R2,[ARGP,#PAGE]
        ADD     R2,R2,#256             ;if getting tight on memory, don't want to leave too much
        CMP     R2,R7
        MOVCS   R7,R2
        MOV     R2,R7
        MOV     R3,#0
        MOV     R0,#&FF
        SWI     OS_File
        MOV     R0,#13
        LDR     R1,[ARGP,#PAGE]
        STRB    R0,[R1],#1
        MOV     R0,#&FF
        STRB    R0,[R1],#1             ;post index to get value for TOP
        STR     R1,[ARGP,#TOP]
        MOV     R1,R7                  ;start (duplicate)
        ADD     R5,R1,R4               ;finish
;major entry point for incore files
;check to see if valid tokenised file
;R1=R7 start; R5=END
LOADFILEINCORE
        LDRB    R6,[R7]
        TEQ     R6,#13
        BNE     LOADFILE0
        LDRB    R6,[R7,#1]
        CMP     R6,#&FF
        BEQ     LOADFILETOKENCOPY      ;initial file is in internal form: copy to right place
        LDRB    R6,[R7,#3]
        CMP     R6,#4                  ;reality check for offset
        ADDCS   R7,R7,R6
        BCS     LOADFILEINCORE
;failed to verify as tokenised. Lexically analyse from R1 to R5
LOADFILE0
        MOV     R4,#9                  ;initial line number
        STR     R14,[SP,#-4]!
        BIC     R9,R9,#1               ;clear bottom bit
LOADFILEENTRY
        STMFD   SP!,{R4,R5}
        BL      MATCH
        LDR     R4,[SP],#4               ;pop line number
        STR     R1,[SP,#-4]!               ;push address in source
        ADD     LINE,ARGP,#OUTPUT
        BL      SPTSTN
        BEQ     LOADFILEENTRYLINE      ;has number
        ORR     R9,R9,#1               ;needs renumber
        ADD     LINE,ARGP,#OUTPUT
        BL      INSERT                 ;put at current end of text with current line number
        B       LOADFILEENTRYDONE
LOADFILEENTRYLINE
        MOV     R4,R0
        BL      INSRT
LOADFILEENTRYDONE
        LDMFD   SP!,{R1,R5}
        CMP     R1,R5
        BCC     LOADFILEENTRY
        TST     R9,#1
        LDREQ   PC,[SP],#4
        MOV     R4,#10
        MOV     R5,#1
        BL      RENUM1
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Program renumbered",10,13,0
 |
        MOV     R0,#7
        BL      MSGPRNXXX
 ]
        LDR     PC,[SP],#4
LOADFILETOKENCOPY
        LDR     R0,[ARGP,#PAGE]
; Use compile-time architecture flags to decide how to handle the potential unaligned load
 [ NoARMv6 :LOR: NoUnaligned
        ; We have to run on pre-ARMv6 CPUs. Check for unaligned load.
        ANDS    R2,R1,#3               ;word mask
        BEQ     LOADFILEFCOPYALIGN
        MOV     R2,R2,LSL #3
        RSB     R3,R2,#32
LOADFILEFCOPYMIS
  [ SupportARMv6
        ; We may be running on ARMv6, or we may be running on an earlier architecture. Support both by emulating pre-ARMv6 unaligned load.
        BIC     R6,R1,#3
        LDMIA   R6,{R6,R7}
  |
        ; We only have to run on pre-ARMv6, where the bottom two address bits are ignored for LDM.
        LDMIA   R1,{R6,R7}
  ]
        MOV     R6,R6,LSR R2
        ORR     R6,R6,R7,LSL R3
        STR     R6,[R0],#4
        ADD     R1,R1,#4
        CMP     R1,R5
        BCC     LOADFILEFCOPYMIS
        B       ENDER
 ] ; Else if we're only running on ARMv6 and above, we don't have to do anything special for unaligned loads (assuming CP15 U bit is set)
LOADFILEFCOPYALIGN
        LDR     R7,[R1],#4
        STR     R7,[R0],#4
        CMP     R1,R5
        BCC     LOADFILEFCOPYALIGN
        B       ENDER
LOADER  STR     R14,[SP,#-4]!
        BL      AEEXPR
        BL      OSSTRI
        BL      AEDONE
        BL      OSFILEINFO
        LDR     R2,[ARGP,#PAGE]
        CMP     R0,#1
        BNE     LOADER1
        ADD     R4,R4,#3
        BIC     R4,R4,#3
        ADD     R4,R2,R4
        LDR     R3,[ARGP,#HIMEM]
        SUB     R3,R3,#20*4
        CMP     R4,R3
        BCS     CANTLOAD
LOADER1 BL      OSFILELOAD
        LDR     R14,[SP],#4
ENDER   LDR     R0,[ARGP,#PAGE]
FNDTOP  LDRB    R1,[R0]
        CMP     R1,#13
        BNE     BADPRO
        LDRB    R1,[R0,#1]
        CMP     R1,#&FF
        BEQ     SETTOP
        LDRB    R1,[R0,#3]
        CMP     R1,#4
        ADDCS   R0,R0,R1
        BCS     FNDTOP
BADPRO
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       13,10,"Bad program",10,13,0
 |
        MOV     R0,#8
        BL      MSGPRNXXX
 ]
        B       CLRSTK
SETTOP  ADD     R0,R0,#2
        STR     R0,[ARGP,#TOP]
        MOV     PC,R14
;print r0 in decimal, uses r4, r1. No limit on size of r0
CARDINALPRINT
        MOV     R4,#0
        STMFD   SP!,{R14,R5,R6,R2,R3}
        MOV     R3,#9
        B       PRNCOMMON
;print r0 in decimal
;uses r4,r1
POSITE  MOV     R4,#0
        B       PRN
NPRN    MOV     R4,#5
PRN     STMFD   SP!,{R14,R5,R6,R2,R3}
        MOV     R3,#4
PRNCOMMON
        MOV     R1,R0
        ADR     R5,VALUES
NUMLOP  MOV     R0,#"0"
        LDR     R6,[R5,R3,LSL #2]
00      SUBS    R1,R1,R6
        ADDCS   R0,R0,#1
        BCS     %B00
        ADD     R1,R1,R6
        CMP     R0,#"0"
        MOVNE   R4,#1
        TEQ     R4,#1
        TEQNE   R3,#0
        BEQ     NUMLPA
        TEQ     R4,#0
        BEQ     NUMLPB
        MOV     R0,#" "
NUMLPA  BL      CHOUT                  ;warning TYPE, R7 used
NUMLPB  SUBS    R3,R3,#1
        BCS     NUMLOP
        LDMFD   SP!,{PC,R5,R6,R2,R3}
VALUES  &       1
        &       10
        &       100
        &       1000
        &       10000                  ;numbers <=99999
        &       100000
        &       1000000
        &       10000000
        &       100000000
        &       1000000000
SPCSWC  MOV     TYPE,#0
;Print r0 spaces
SPCOUT  STMFD   SP!,{R14,R1}
        TEQ     R0,#0
        LDMMIFD SP!,{R1,PC}
        ANDS    R1,R0,#255
        LDMEQFD SP!,{R1,PC}
        MOV     R0,#" "
SPCLOP  BL      CHOUT
        SUBS    R1,R1,#1
        BNE     SPCLOP
        LDMFD   SP!,{R1,PC}
CHOUTNOCOUNT
        TST     R7,#128
        BEQ     CHOUTS1
CHOUT   TST     R7,#128
        BEQ     CHOUTS
        CMP     TYPE,#&8000
        BCC     CHOUTS
        BEQ     CHOUTTRACE
        STRB    R0,[TYPE],#1
        CMP     TYPE,SP
        MOVCC   PC,R14
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       10,13,"Not enough room to convert this program to text",10,13,0
 |
        MOV     R0,#9
        BL      MSGPRNXXX
 ]
        B       FSASET
CHOUTTRACE
        STMFD   SP!,{R0,R1}
        LDR     R1,[ARGP,#TRACEFILE]
        TEQ     R1,#0
        BEQ     CHOUTS2
        SWI     XOS_BPut
        LDMVCFD SP!,{R0,R1}
        MOVVC   PC,R14
        MOV     R0,#0
        STR     R0,[ARGP,#TRACEFILE]
        SWI     XOS_Find               ;close
        LDMFD   SP!,{R0,R1}
        MOV     PC,R14
CHOUTS  STMFD   SP!,{R0,R1}
CHOUTS2 LDR     R0,[ARGP,#WIDTHLOC]
        LDR     R1,[ARGP,#TALLY]
        CMP     R0,R1
        MOVCC   R1,#0
        SWICC   OS_NewLine
        ADD     R1,R1,#1
        STR     R1,[ARGP,#TALLY]
        LDMFD   SP!,{R0,R1}
CHOUTS1 SWI     OS_WriteC
        MOV     PC,R14
EDIT    ADR     R0,EDITENS
        SWI     OS_CLI
        BL      OSCLIREGS
        ADR     R0,EDITTXT
        SWI     OS_CLI
        LDR     R0,[ARGP,#TOP]
        CMP     R0,#0
        BPL     CLRSTK
        BIC     R0,R0,#&80000000
        STR     R0,[ARGP,#TOP]
        B       FSASET
EDITENS =       "RMEnsure ARMBasicEditor 0 RMLoad System:Modules.BasicEdit",0
EDITTXT =       "ARMBE",0
        ALIGN
LIST    LDRB    R7,[ARGP,#LISTOP]
        LDRB    R0,[LINE]
        CMP     R0,#"O"
        BNE     LISTGO
        ADDEQ   LINE,LINE,#1
        BL      AEEXDN
        CMP     IACC,#32
        BCS     ERLISTO
        STRB    IACC,[ARGP,#LISTOP]
        B       CLRSTK
TEXTSAVE
        MOV     R0,#64+128
        MOV     AELINE,LINE
        LDRB    R10,[AELINE]
        CMP     R10,#"O"
        BNE     TEXTSAVEGO
        ADDEQ   AELINE,AELINE,#1
        BL      INTEXC
        ORR     R0,R0,#64+128
TEXTSAVEGO
        STR     R0,[SP,#-4]!
        BL      EXPR
        BL      OSSTRI
        BL      AEDONE
        LDR     R7,[SP],#4
TWINGO  BL      SETFSA                 ;init fsa to top
        SUB     LINE,LINE,#1
        CMP     R10,#13
        BNE     ERSYNT
LISTGO  MOV     R4,#0                  ;start 0
        MOV     R5,#&FF
        ORR     R5,R5,#&FE00           ;end 65279
        BL      SPTSTN                 ;check for possible start
        BNE     NONUML                 ;no start given
        MOV     R4,R0                  ;start at this line
        BL      SPACES
        CMP     R10,#","
        BEQ     GOTCX                  ;followed by something
        MOV     R5,R4                  ;followed by nothing: set end to start
        B       GOTCFF
NONUML  CMP     R10,#","
        BNE     GOTCFF                 ;no number, no comma, could be IF
GOTCX   BL      SPTSTN
        MOVEQ   R5,R0                  ;second number to end
        BLEQ    SPACES
GOTCFF  CMP     R10,#TIF
        MOV     AELINE,LINE
        SUBNE   AELINE,LINE,#1         ;pointer to match string
        BLNE    DONE
        BL      ENDER                  ;fault if bad program
        BL      TWINBG                 ;get pointer for TWIN chout
        MOV     IACC,R4                ;move in start line number
        BL      FNDLNO                 ;find it
        MOV     LINE,R1
        MOV     R6,#0                  ;clear structure space count
        B       GETNUM
ENDLN   MOV     R0,#10
        BL      CHOUTNOCOUNT
        CMP     R7,#128
        SWICC   OS_WriteI+13           ;write out return as well if to screen etc.
        MOV     R0,#0
        STR     R0,[ARGP,#TALLY]
GETNEW  LDRB    R0,[R2,#3]             ;R2 has initial LINE in it
        ADD     LINE,R2,R0
GETNUM  LDRB    R0,[LINE,#1]
        LDRB    R1,[LINE,#2]
        ORR     R0,R1,R0,LSL #8        ;combine to word
        CMP     R0,R5                  ;test against limit
        BLS     LTTEST
        CMP     R7,#128
        BCC     CLRSTK                 ;end of LIST
        MOV     R5,TYPE                ;end address
        BL      TWINBG
        MOV     R4,TYPE                ;start address
        ADD     R1,ARGP,#STRACC
        MVN     R2,#0
        B       SAVEFILECLRSTK
TWINBG  LDR     TYPE,[ARGP,#FSA]       ;set TYPE = FSA ...
        CMP     TYPE,#&9000            ;but increase to &9000
        MOVCC   TYPE,#&9000            ;if below
        MOV     PC,R14
LTTEST  LDRB    R3,[ARGP,#ESCFLG]
        CMP     R3,#&80
        BCS     ESCAPE                 ;only reasonable exception
        MOV     R4,#0                  ;don't list line
        LDRB    R14,[AELINE]
        CMP     R14,#13
        MOVEQ   R4,#1                  ;list line if no search string
        MOV     R3,#0                  ;token expansion
        MOV     R2,LINE                ;save line
        ADD     LINE,LINE,#4
        TEQ     R6,#0
        MOVMI   R6,#0                  ;reset count if negative
        STR     R6,[SP,#-4]!               ;current indent
LTLOOP  LDRB    R10,[LINE],#1
        CMP     R10,#13
        BEQ     CHKLST                 ;finished prescan
        CMP     R10,#TREM
        MOVEQ   R3,R10                 ;if REM flip token expansion forever
        CMP     R10,#""""
        EOREQ   R3,R3,R10              ;if " flip token expansion
        TEQ     R3,#0
        BNE     LPSIMT
        CMP     R10,#TNEXT
        CMPNE   R10,#TUNTIL
        CMPNE   R10,#TENDWH
        CMPNE   R10,#TENDCA
        CMPNE   R10,#TENDIF
        SUBEQ   R6,R6,#2               ;dec count
        CMP     R10,#TFOR
        CMPNE   R10,#TREPEAT
        ADDEQ   R6,R6,#2               ;inc count
        LDRB    R14,[LINE,#-2]         ;previous character
        TEQ     R14,#TESCSTMT
; TEQNE R14,#TESCFN
; TEQNE R14,#TESCCOM
        BNE     LPSIMT
        CMP     R10,#TWHILE
        CMPNE   R10,#TCASE
        ADDEQ   R6,R6,#2
        B       LTLOOP
LPSIMT  TST     R4,#1
        BNE     LTLOOP                 ;already decided to list line
        MOV     R1,#0                  ;offset down string
LPSIMS  LDRB    R14,[AELINE,R1]
        CMP     R14,#13
        MOVEQ   R4,#1                  ;listable line
        BEQ     LTLOOP
        CMP     R10,#TCONST
        ADDEQ   LINE,LINE,#3
        CMP     R14,R10
        LDRB    R10,[LINE,R1]
        ADD     R1,R1,#1
        BEQ     LPSIMS                 ;loop if equal
        B       LTLOOP
CHKLST  LDRB    R14,[LINE,#-2]
        CMP     R14,#TTHEN
        ADDEQ   R6,R6,#2               ;do multiline if then else endif
        LDR     R3,[SP],#4               ;old count
        CMP     R3,R6
        MOVCS   R3,R6                  ;use minimum
        TEQ     R4,#0
        BEQ     GETNEW
        ADD     LINE,R2,#4             ;first char to list
        BL      LISTLINE
        B       ENDLN
LISTLINE
        STR     R14,[SP,#-4]!
        TST     R7,#8
        BLEQ    NPRN
        MOV     R4,#0
        ANDS    R0,R7,#1
        BLNE    SPCOUT
        B       LPSD1
LPSD    TST     R7,#4
        BEQ     LPQUOT
        BL      CHOUT
        MOV     R0,#10
        BL      CHOUTNOCOUNT
        CMP     R7,#128
        MOV     R0,#13
        BLCC    CHOUTNOCOUNT
        MOV     R0,#0
        STR     R0,[ARGP,#TALLY]
        AND     R0,R7,#1
        TST     R7,#8
        ADDEQ   R0,R0,#5
        BL      SPCOUT
LPSD1   MOVS    R0,R3
        TSTNE   R7,#2
        BLNE    SPCOUT
        B       LP
LPQUOT  BL      CHOUT
LP      LDRB    R0,[LINE],#1
        CMP     R0,#13
        LDREQ   PC,[SP],#4
        CMP     R0,#""""
        EOREQ   R4,R4,#1               ;flip expansion flag
        TEQ     R4,#0
        BNE     LPQUOT
        TEQ     R0,#":"
        BEQ     LPSD
        CMP     R0,#&7F
        BCC     LPQUOT
        CMP     R0,#TCONST
        BNE     LPSIMP
        BL      SPGETN
        BL      POSITE
        MOV     R4,#0
        TST     R7,#8
        BEQ     LP
        CMP     R7,#128
        SWICC   OS_NewLine
        B       USESLINENUMBERS
LPSIMP  CMP     R0,#TREM
        MOVEQ   R4,#4                  ;no more expansion after this
        BL      TOKOUT
        B       LP
LVAR    ROUT
        BL      DONES
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Static Integer variables:               @% = """,0
        ALIGN
 |
        MOV     R0,#10
        BL      MSGPRNXXX
 ]
LVAR1   ADD     R7,ARGP,#INTVAR
        LDR     R5,[R7],#4
        CMP     R5,#&1000000
        SWICS   OS_WriteI+"+"
        AND     R4,R5,#&F0000
        CMP     R4,#&10000
        SWICC   OS_WriteI+"g"
        SWIEQ   OS_WriteI+"e"
        SWIHI   OS_WriteI+"f"
        AND     R0,R5,#&FF
        MOV     TYPE,#0
        BL      POSITE
        TST     R5,#&800000
        SWIEQ   OS_WriteI+"."
        SWINE   OS_WriteI+","
        AND     R0,R5,#&FF00
        MOV     R0,R0,LSR #8
        BL      POSITE
        SWI     OS_WriteI+""""
        MOV     R6,#"A"
        MOV     R5,#3
10      ADD     R10,R0,#5
        ADD     R5,R5,#1
        TST     R5,#3
        SWIEQ   OS_NewLine
        BEQ     %12
13      SWI     OS_WriteI+" "
        ADD     R10,R10,#1
        CMP     R10,#20
        BCC     %13
12      MOV     R0,R6
        SWI     OS_WriteC
        SWI     OS_WriteS
        =       "% = ",0
        LDR     IACC,[R7],#4
        BL      LVRPINT
        ADD     R6,R6,#1
        TEQ     R6,#"Z"+1
        BNE     %10
        SWI     OS_NewLine
        MOV     R0,#0
        STR     R0,[ARGP,#FNTEMPLOC]
        STR     R0,[ARGP,#FNTEMPLOC+4]
        STR     R0,[ARGP,#FNTEMPLOC+8]
        STR     R0,[ARGP,#FNTEMPLOC+12]
        ADD     R5,ARGP,#VARPTR
        ADD     R7,R5,#("z"+1-"A")*4
        MOV     R6,#"A"-1
21      ADD     R6,R6,#1
        TEQ     R5,R7
        BEQ     LVARDX
        LDR     R4,[R5],#4
        TEQ     R4,#0
        BEQ     %21
        MOV     R11,#256
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Dynamic variables:",0
 |
        MOV     R0,#11
        BL      MSGPRNXXX
 ]
        B       %20
22      LDR     R4,[R5],#4             ;head of chain
23      TEQ     R4,#0
        BEQ     %29
20      RSBS    R0,R11,#20
        RSBLSS  R0,R11,#40
        RSBLSS  R0,R11,#60
        SWILS   OS_NewLine
        MOVLS   R11,#0
        BLS     LVRDFF
        ADD     R11,R11,R0
        MOV     TYPE,#0
        BL      SPCOUT
LVRDFF  MOV     R2,R4
        LDR     R4,[R2],#4             ;next in chain
        MOV     R0,R6
        SWI     OS_WriteC
LVRDNO  ADD     R11,R11,#1
        LDRB    R0,[R2],#1
        TEQ     R0,#0
        SWINE   OS_WriteC
        BNE     LVRDNO
        MOV     R0,R2
        LDRB    R2,[R0,#-2]
        TEQ     R2,#"("
        BEQ     %24
        TEQ     R2,#"$"
        BEQ     %25
        TEQ     R2,#"%"
        MOVEQ   TYPE,#4
        MOVNE   TYPE,#TFPLV
 [ FPOINT=0
        ADDEQ   R0,R0,#3
        BICEQ   R0,R0,#3
 |
        ADD     R0,R0,#3
        BIC     R0,R0,#3
 ]
        BL      VARIND
        SWI     OS_WriteS
        =       " = ",0
        ADD     R11,R11,#3
        STR     R4,[SP,#-4]!
        BL      LVRPRT
        LDR     R4,[SP],#4
        B       %23
24      ADD     R0,R0,#3
        BIC     R0,R0,#3
        LDR     R2,[R0]
        CMP     R2,#16
        BCC     LVRDAN
        LDR     R0,[R2],#4
LVRDAP  SUB     R0,R0,#1
        STMFD   SP!,{R2,R4}
        BL      LVRPINT
        LDMFD   SP!,{R2,R4}
        LDR     R0,[R2],#4
        ADD     R11,R11,#1
        TEQ     R0,#0
        SWINE   OS_WriteI+","
        BNE     LVRDAP
        SWI     OS_WriteI+")"
        B       %23
LVRDAN  CMP     R2,#1
        BEQ     LVRDAN2
        SWI     OS_WriteS
        =       "undimensioned)",0
        ADD     R11,R11,#14
        B       %23
LVRDAN2 SWI     OS_WriteS
        =       "local)",0
        ADD     R11,R11,#6
        B       %23
25      MOV     TYPE,#128
        BL      VARIND
        SWI     OS_WriteS
        =       " = """,0
        ADD     R11,R11,#5
        ADD     R1,ARGP,#STRACC
        TEQ     R1,CLEN
        BEQ     %28
27      LDRB    R0,[R1],#1
        TEQ     R0,#127
        CMPNE   R0,#" "-1
        MOVLS   R0,#"."
        SWI     OS_WriteC
        ADD     R11,R11,#1
        TEQ     R1,CLEN
        BNE     %27
28      SWI     OS_WriteI+""""
        B       %23
29      ADD     R6,R6,#1
        TEQ     R5,R7
        BNE     %22
        SWI     OS_NewLine
LVARDX  LDR     R1,[ARGP,#PROCPTR]
        TEQ     R1,#0
        BEQ     LVARPX
        MOV     R11,#0
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Procedures:",10,13,0
        ALIGN
 |
        MOV     R0,#12
        BL      MSGPRNXXX
 ]
LVARP1  BL      LVARFMT
        SWI     OS_WriteS
        =       "PROC",0
        ADD     R11,R11,#3
        BL      LVARFN
        BNE     LVARP1
        SWI     OS_NewLine
LVARPX  LDR     R1,[ARGP,#FNPTR]
        TEQ     R1,#0
        BEQ     LVARLIB
        MOV     R11,#0
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Functions:",10,13,0
        ALIGN
 |
        MOV     R0,#13
        BL      MSGPRNXXX
 ]
LVARF0  BL      LVARFMT
        SWI     OS_WriteS
        =       "FN",0
        ADD     R11,R11,#1
        BL      LVARFN
        BNE     LVARF0
        SWI     OS_NewLine
LVARLIB LDR     R1,[ARGP,#LIBRARYLIST]
        TEQ     R1,#0
        BEQ     LVARINST
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Libraries:",10,13,0
        ALIGN
 |
        MOV     R0,#14
        BL      MSGPRNXXX
 ]
LVARLIB0
        ADD     LINE,R1,#8
        BL      LVARLINE
        LDR     R1,[R1]
        CMP     R1,#0
        BNE     LVARLIB0
LVARINST
        LDR     R1,[ARGP,#INSTALLLIST]
        TEQ     R1,#0
        BEQ     LVAROVER
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Installed libraries:",10,13,0
        ALIGN
 |
        MOV     R0,#15
        BL      MSGPRNXXX
 ]
LVARILIB0
        ADD     LINE,R1,#8
        BL      LVARLINE
        LDR     R1,[R1]
        CMP     R1,#0
        BNE     LVARILIB0
LVAROVER
        LDR     R7,[ARGP,#OVERPTR]
        TEQ     R7,#0
        BEQ     LVARDONE
        LDR     R1,[R7]
        LDR     R2,[R7,#4]
        CMN     R2,#1
        BEQ     LVARDONE
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Current Overlay (from """,0
        ALIGN
 |
        MOV     R0,#16
        BL      MSGPRNXXX
 ]
LVARCUROVERLAY
        ADD     R2,R2,R2,LSL #2
        ADD     R0,R1,R2
        BL      VARSTR
        ADD     R0,ARGP,#STRACC
        SUB     R1,CLEN,R0
        SWI     OS_WriteN
        SWI     OS_WriteS
        =       """):",10,13,0
        ALIGN
        ADD     LINE,R7,#12+4
        BL      LVARLINE
LVARDONE
        B       CLRSTK
;list first line of program without line number!
LVARLINE
        MOV     R7,#8
        LDRB    R0,[LINE,#-2]
        CMP     R0,#255
        MOVEQ   PC,R14
        STMFD   SP!,{R1,R14}
        BL      LISTLINE
        SWI     OS_NewLine
        LDMFD   SP!,{R1,PC}
;list functions or procedures
LVARFN  STMFD   SP!,{R14,R8}
        LDR     R10,[R1],#4
        MOV     R0,R1
        SWI     OS_Write0
        SUB     R1,R0,R1
        ADD     R11,R11,R1
        ADD     R0,R0,#3
        BIC     R7,R0,#3
        LDMFD   R7!,{R0,R1}
        TEQ     R0,#0
        BEQ     LVARF1
        SWI     OS_WriteI+"("
        ADD     R11,R11,#2
LVARFA  TST     R1,#&100
        BEQ     %41
        TST     R1,#&8000
        BNE     %41
        SWI     OS_WriteS
        =       "RETURN ",0
        ADD     R11,R11,#7
41      ANDS    R2,R1,#255
        BNE     %42
        SWI     OS_WriteS
        =       "byte",0
        ADD     R11,R11,#4
42      TEQ     R2,#4
        BNE     %43
        SWI     OS_WriteS
        =       "integer",0
        ADD     R11,R11,#7
43      TEQ     R2,#TFPLV
        BNE     %44
        SWI     OS_WriteS
        =       "real",0
        ADD     R11,R11,#4
44      TEQ     R2,#128
        BNE     %45
        SWI     OS_WriteS
        =       "string",0
        ADD     R11,R11,#6
45      CMP     R2,#129
        BCC     %46
        SWI     OS_WriteS
        =       "$ string",0
        ADD     R11,R11,#8
46      TST     R1,#&8000
        BEQ     %49
        SWI     OS_WriteS
        =       " array",0
        ADD     R11,R11,#6
49      LDMFD   R7!,{R0,R1}
        TEQ     R0,#0
        ADDNE   R11,R11,#1
        SWINE   OS_WriteI+","
        BNE     LVARFA
        SWI     OS_WriteI+")"
LVARF1  MOVS    R1,R10
        LDMFD   SP!,{R8,PC}
LVARFMT STR     R14,[SP,#-4]!
        TEQ     R11,#0
        BEQ     LVRFMX
        RSBS    R0,R11,#40
        SWILS   OS_NewLine
        MOVLS   R11,#0
        BLS     LVRFMX
        ADD     R11,R11,R0
        MOV     TYPE,#0
        BL      SPCOUT
LVRFMX  LDR     PC,[SP],#4
LVRPINT MOV     TYPE,#TINTEGER
LVRPRT  MOV     R4,#&900               ;TEMPORARY!
        STMFD   SP!,{R5,R6,R7,R14}
        MOV     R5,#0
        BL      FCONFP
        ADD     R0,ARGP,#STRACC
        MOV     R5,#0
        STRB    R5,[TYPE]
        SWI     OS_Write0
        ADD     R0,ARGP,#STRACC
        SUB     R0,TYPE,R0
        ADD     R11,R11,R0
        LDMFD   SP!,{R5,R6,R7,PC}
OLD     BL      DONES
        MOV     R0,#0
        LDR     R1,[ARGP,#PAGE]
        STRB    R0,[R1,#1]
        BL      ENDER
        B       FSASET
RENUM   BL      GETTWO
        BL      RENUM1
        B       FSASET
RENUM1  LDR     R0,[ARGP,#PAGE]
RENUM2  STMFD   SP!,{R0,R14,TYPE}      ;renumber from r4 step r5 starting at r0
        BL      ENDER
        LDR     R7,[ARGP,#TOP]
        LDR     R1,[SP]
NUMBA   LDRB    R10,[R1,#1]            ;phase 1: remember current line numbers
        CMP     R10,#&FF
        BEQ     NUMBB
        STRB    R10,[R7],#1
        LDRB    R10,[R1,#2]
        STRB    R10,[R7],#1
        LDRB    R10,[R1,#3]
        ADD     R1,R1,R10
        CMP     R7,SP
        BCC     NUMBA
        B       ERNUMM
NUMBB   LDR     R1,[SP]
NUMBC   LDRB    R10,[R1,#1]
        CMP     R10,#&FF
        BEQ     NUMBD
        CMP     R4,#65280
        BCS     NUMBCFAIL
        STRB    R4,[R1,#2]
        MOV     R0,R4,LSR #8
        STRB    R0,[R1,#1]
        ADD     R4,R4,R5
        LDRB    R10,[R1,#3]
        ADD     R1,R1,R10
        B       NUMBC
NUMBCFAIL
        LDR     R6,[ARGP,#TOP]
        LDR     R1,[SP]
NUMBCFAIL1
        LDRB    R0,[R6],#1
        STRB    R0,[R1,#1]
        LDRB    R0,[R6],#1
        STRB    R0,[R1,#2]
        LDRB    R0,[R1,#3]
        ADD     R1,R1,R0
        CMP     R6,R7
        BCC     NUMBCFAIL1
        B       ERNUMO
NUMBD   LDR     LINE,[SP]
        ADD     LINE,LINE,#1
NUMBE   LDRB    R10,[LINE],#1
        CMP     R10,#&FF
        LDMEQFD SP!,{R0,TYPE,PC}
        LDRB    R7,[LINE],#1
        ADD     R7,R7,R10,LSL #8
        ADD     LINE,LINE,#1
        MOV     TYPE,#0                ;in strings
NUMBF   LDRB    R10,[LINE],#1
        CMP     R10,#""""
        EOREQ   TYPE,TYPE,#1
        CMP     R10,#13
        BEQ     NUMBE
        TEQ     TYPE,#0
        BNE     NUMBF
        CMP     R10,#TREM
        CMPNE   R10,#TDATA
        MOVEQ   TYPE,#2
        CMP     R10,#TCONST
        BNE     NUMBF
        MOV     AELINE,LINE
        BL      SPGETN
;have line number in R0
;must search cross reference for it
        LDR     R4,[ARGP,#TOP]
        LDR     R5,[SP]
NUMBH   LDRB    R10,[R5,#1]
        CMP     R10,#&FF
        BEQ     NUMBJ
        LDRB    R2,[R4],#1             ;hi
        LDRB    R1,[R4],#1             ;lo
        ORR     R1,R1,R2,LSL #8
        CMP     R1,R0
        LDRNEB  R1,[R5,#3]             ;if not found, continue
        ADDNE   R5,R5,R1
        BNE     NUMBH
;found number in xref process
        LDRB    R5,[R5,#2]             ;get lo byte of new number
        ORR     R5,R5,R10,LSL #8       ; new number
        MOV     R2,AELINE
        BL      CONSTI
        B       NUMBF
NUMBJ   MOV     R1,R0
        MOV     R2,R7
 [ OWNERRORS=1
        SWI     OS_WriteS
        =       "Failed with ",0
        MOV     R0,R1
        BL      POSITE
        SWI     OS_WriteS
        =       " on line ",0
        MOV     R0,R7
        BL      POSITE
        SWI     OS_NewLine
 |
        MOV     R0,#23
        BL      MSGPRNCCX
 ]
        B       NUMBF
SAVE    BL      SPACES
        TEQ     R10,#13
        BEQ     SAVEIC
        SUB     LINE,LINE,#1
        BL      AEEXPR
        BL      OSSTRI
        BL      AEDONE
        BL      ENDER
        ADD     R1,ARGP,#STRACC
SAVEFIL LDR     R4,[ARGP,#PAGE]
        LDR     R5,[ARGP,#TOP]
        MVN     R2,#0
        SUB     R2,R2,#&F00-&B00
;save date stamped file [R1] of type R2 from R4 to R5
SAVEFILECLRSTK
        STR     R1,[SP,#-4]!
        MOV     R0,#OsWord_ReadRealTimeClock
        SUB     R1,SP,#8
        MOV     R3,#3
        STR     R3,[R1]
        STR     R2,[R1,#4]
        SWI     OS_Word
        MOV     R0,#0
        LDR     R2,[R1,#4]
        LDR     R3,[R1]
        LDR     R1,[SP],#4
        SWI     OS_File
        B       CLRSTK
SAVEIC  BL      ENDER
        LDR     R1,[ARGP,#PAGE]
        LDRB    R0,[R1,#1]
        CMP     R0,#&FF
        BEQ     BADIC
        ADD     R1,R1,#4
SAVEI2  LDRB    R0,[R1],#1
        TEQ     R0,#" "
        BEQ     SAVEI2
        TEQ     R0,#TREM
        BNE     BADIC
SAVEI3  LDRB    R0,[R1],#1
        TEQ     R0,#" "
        BEQ     SAVEI3
        TEQ     R0,#">"
        BEQ     SAVEFIL
        B       BADIC
OSFILELOADSTRACC
        ADD     R1,ARGP,#STRACC
OSFILELOAD
        MOV     R0,#255
        MOV     R3,#0
OSFILERETURN
        SWI     OS_File
        MOV     PC,R14
OSFILEINFOSTRACC
        ADD     R1,ARGP,#STRACC
OSFILEINFO
        MOV     R0,#5
        B       OSFILERETURN

        LNK     HelpMsgs.s