        TTL     => SWINaming

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        MACRO
$l      AddSwiNameToDecodeTab   $name
$l      = "$name", 0
SwisInSystemTable SETA SwisInSystemTable+1
        MEND

SWINumberToString_Code    ROUT

     [ ChopOffTheGoolies
        ADR     R0, %FT01
        ORR     lr, lr, #V_bit
        ExitSWIHandler
01
        &       0
        =      "Removed for Greenwich version",0
        ALIGN
     |
; R0 SWI number
; R1 buffer pointer
; R2 buffer length

        TEQP    PC, #SVC_mode     ; interrupts on!

        MOV     R12, lr           ; keep here so subroutines can update flags

        Push   "R9, R3"

        MOV     R9, R0            ; R0 to pass back
        MOV     R3, R2            ; buffer limit
        MOV     R2, #0            ; characters so far

        TST     R0, #Auto_Error_SWI_bit
        MOVNE   R10, #"X"
        BLNE    AddChar
        BIC     R0, R0, #Auto_Error_SWI_bit
        CMP     R0, #512
        BGE     NotASystemSWI

        ADR     R11, OS_Prefix
        BL      AddString
        MOV     R10, #"_"
        BL      AddChar

        CMP     R0, #256
        BGE     Swi_Is_WriteI
        CMP     R0, #MaxSwi
        BGE     SWINotInTable

        ADR     R11, System_Swi_Names
        BL      GetStringFromTable

AddStringAndExit
        BL      AddString

ExitSwiSwi
        MOV     R10, #0
        BL      AddChar

        MOV     R0, R9            ; error pointer or restoration
        Pull   "R9, R3"
        MOV     lr, R12
        ExitSWIHandler

                  GBLA SwisInSystemTable
SwisInSystemTable SETA -1

OS_Prefix =    "OS",0

System_Swi_Names
        AddSwiNameToDecodeTab WriteC
        AddSwiNameToDecodeTab WriteS
        AddSwiNameToDecodeTab Write0
        AddSwiNameToDecodeTab NewLine
        AddSwiNameToDecodeTab ReadC
        AddSwiNameToDecodeTab CLI
        AddSwiNameToDecodeTab Byte
        AddSwiNameToDecodeTab Word
        AddSwiNameToDecodeTab File
        AddSwiNameToDecodeTab Args
        AddSwiNameToDecodeTab BGet
        AddSwiNameToDecodeTab BPut
        AddSwiNameToDecodeTab GBPB
        AddSwiNameToDecodeTab Find
        AddSwiNameToDecodeTab ReadLine
        AddSwiNameToDecodeTab Control
        AddSwiNameToDecodeTab GetEnv
        AddSwiNameToDecodeTab Exit
        AddSwiNameToDecodeTab SetEnv
        AddSwiNameToDecodeTab IntOn
        AddSwiNameToDecodeTab IntOff
        AddSwiNameToDecodeTab CallBack
        AddSwiNameToDecodeTab EnterOS
        AddSwiNameToDecodeTab BreakPt
        AddSwiNameToDecodeTab BreakCtrl
        AddSwiNameToDecodeTab UnusedSWI
        AddSwiNameToDecodeTab UpdateMEMC
        AddSwiNameToDecodeTab SetCallBack
        AddSwiNameToDecodeTab Mouse

        AddSwiNameToDecodeTab Heap
        AddSwiNameToDecodeTab Module
        AddSwiNameToDecodeTab Claim
        AddSwiNameToDecodeTab Release
        AddSwiNameToDecodeTab ReadUnsigned
        AddSwiNameToDecodeTab GenerateEvent
        AddSwiNameToDecodeTab ReadVarVal
        AddSwiNameToDecodeTab SetVarVal
        AddSwiNameToDecodeTab GSInit
        AddSwiNameToDecodeTab GSRead
        AddSwiNameToDecodeTab GSTrans
        AddSwiNameToDecodeTab BinaryToDecimal
        AddSwiNameToDecodeTab FSControl
        AddSwiNameToDecodeTab ChangeDynamicArea
        AddSwiNameToDecodeTab GenerateError
        AddSwiNameToDecodeTab ReadEscapeState
        AddSwiNameToDecodeTab EvaluateExpression
        AddSwiNameToDecodeTab SpriteOp
        AddSwiNameToDecodeTab ReadPalette
        AddSwiNameToDecodeTab ServiceCall
        AddSwiNameToDecodeTab ReadVduVariables
        AddSwiNameToDecodeTab ReadPoint
        AddSwiNameToDecodeTab UpCall
        AddSwiNameToDecodeTab CallAVector
        AddSwiNameToDecodeTab ReadModeVariable
        AddSwiNameToDecodeTab RemoveCursors
        AddSwiNameToDecodeTab RestoreCursors
        AddSwiNameToDecodeTab SWINumberToString
        AddSwiNameToDecodeTab SWINumberFromString
        AddSwiNameToDecodeTab ValidateAddress
        AddSwiNameToDecodeTab CallAfter
        AddSwiNameToDecodeTab CallEvery
        AddSwiNameToDecodeTab RemoveTickerEvent
        AddSwiNameToDecodeTab InstallKeyHandler
        AddSwiNameToDecodeTab CheckModeValid
        AddSwiNameToDecodeTab ChangeEnvironment
        AddSwiNameToDecodeTab ClaimScreenMemory
        AddSwiNameToDecodeTab ReadMonotonicTime
        AddSwiNameToDecodeTab SubstituteArgs
        AddSwiNameToDecodeTab PrettyPrint
        AddSwiNameToDecodeTab Plot
        AddSwiNameToDecodeTab WriteN
        AddSwiNameToDecodeTab AddToVector
        AddSwiNameToDecodeTab WriteEnv
        AddSwiNameToDecodeTab ReadArgs
        AddSwiNameToDecodeTab ReadRAMFsLimits
        AddSwiNameToDecodeTab ClaimDeviceVector
        AddSwiNameToDecodeTab ReleaseDeviceVector
        AddSwiNameToDecodeTab DelinkApplication
        AddSwiNameToDecodeTab RelinkApplication
        AddSwiNameToDecodeTab HeapSort
        AddSwiNameToDecodeTab ExitAndDie
        AddSwiNameToDecodeTab ReadMemMapInfo
        AddSwiNameToDecodeTab ReadMemMapEntries
        AddSwiNameToDecodeTab SetMemMapEntries
        AddSwiNameToDecodeTab AddCallBack
        AddSwiNameToDecodeTab ReadDefaultHandler
        AddSwiNameToDecodeTab SetECFOrigin
        AddSwiNameToDecodeTab SerialOp
        AddSwiNameToDecodeTab ReadSysInfo
        AddSwiNameToDecodeTab Confirm
        AddSwiNameToDecodeTab ChangedBox
        AddSwiNameToDecodeTab CRC
        AddSwiNameToDecodeTab ReadDynamicArea
        AddSwiNameToDecodeTab PrintChar
        = 0

 [ SwisInSystemTable+1 <> MaxSwi
 ! 1, :CHR:10:CC::CHR:13:CC::CHR:7:CC::CHR:7:CC:"Swi Disassembly table not consistent with despatch table":CC::CHR:10:CC::CHR:13
 ]

convswitab = "OS",0

Conversion_Swi_Names
        AddSwiNameToDecodeTab  ConvertHex1
        AddSwiNameToDecodeTab  ConvertHex2
        AddSwiNameToDecodeTab  ConvertHex4
        AddSwiNameToDecodeTab  ConvertHex6
        AddSwiNameToDecodeTab  ConvertHex8
        AddSwiNameToDecodeTab  ConvertCardinal1
        AddSwiNameToDecodeTab  ConvertCardinal2
        AddSwiNameToDecodeTab  ConvertCardinal3
        AddSwiNameToDecodeTab  ConvertCardinal4
        AddSwiNameToDecodeTab  ConvertInteger1
        AddSwiNameToDecodeTab  ConvertInteger2
        AddSwiNameToDecodeTab  ConvertInteger3
        AddSwiNameToDecodeTab  ConvertInteger4
        AddSwiNameToDecodeTab  ConvertBinary1
        AddSwiNameToDecodeTab  ConvertBinary2
        AddSwiNameToDecodeTab  ConvertBinary3
        AddSwiNameToDecodeTab  ConvertBinary4
        AddSwiNameToDecodeTab  ConvertSpacedCardinal1
        AddSwiNameToDecodeTab  ConvertSpacedCardinal2
        AddSwiNameToDecodeTab  ConvertSpacedCardinal3
        AddSwiNameToDecodeTab  ConvertSpacedCardinal4
        AddSwiNameToDecodeTab  ConvertSpacedInteger1
        AddSwiNameToDecodeTab  ConvertSpacedInteger2
        AddSwiNameToDecodeTab  ConvertSpacedInteger3
        AddSwiNameToDecodeTab  ConvertSpacedInteger4
        AddSwiNameToDecodeTab  ConvertFixedNetStation
        AddSwiNameToDecodeTab  ConvertNetStation
        AddSwiNameToDecodeTab  ConvertFixedFileSize
        AddSwiNameToDecodeTab  ConvertFileSize
        =  0
        ALIGN


SWINotInTable
        SUB     r11, r0, #OS_ConvertHex1
        CMP     r11, #OS_ConvertFileSize - OS_ConvertHex1
        BHI     %FT10

        MOV     r0, r11
        addr    r11, Conversion_Swi_Names
        BL      GetStringFromTable
        B       AddStringAndExit

10      ADR     R11, %FT01
        CMP     R0, #OS_ConvertStandardDateAndTime
        ADREQ   R11, %FT05
        CMP     R0, #OS_ConvertDateAndTime
        ADREQ   R11, %FT06
        B       AddStringAndExit
01
        = "Undefined", 0

othersysswitab
        = "OS",0
05
        = "ConvertStandardDateAndTime", 0
06
        = "ConvertDateAndTime", 0
        =  0

02
        = "User", 0

andpissaboutwithWriteI
        = "OS",0
        = "WriteI", 0
        =  0
03
        = "WriteI+", 0

        ALIGN

NotASystemSWI
        Push   "R9, R12"
        BIC     R10, R0, #Module_SWIChunkSize-1
        ModSWIHashval R9, R10
        LDR     R9, [R9]
lohc    CMP     R9, #0
        BEQ     giveemaboringname
        LDR     R12, [R9, #ModSWINode_Number]
        CMP     R10, R12
        LDRNE   R9,[R9, #ModSWINode_Link]
        BNE     lohc

        LDR     R12, [R9, #ModSWINode_MListNode]
        LDR     R9, [R12, #Module_code_pointer]
        LDR     R10, [R9, #Module_NameTable]
        CMP     R10, #0
        BEQ     trymodule_SWIdecode_code
        CMP     R10, #4*1024*1024         ; offset too big?
        BHI     usethemoduletitle
        ADD     R11, R10, R9
        Pull   "R9, R12"
        BL      AddString
        MOV     R10, #"_"
        BL      AddChar
        AND     R0, R0, #Module_SWIChunkSize-1
        Push   "R0"
        BL      GetStringFromTable
        Pull   "R0"
        BVS     AddNumericBit              ; not in table
        B       AddStringAndExit

trymodule_SWIdecode_code
        LDR     R10, [R9, #Module_NameCode]
        CMP     R10, #0
        BEQ     usethemoduletitle
        TST     R10, #ARM_CC_Mask
        BNE     usethemoduletitle
        CMP     R10, #4*1024*1024         ; offset too big?
        BHI     usethemoduletitle
        
; got R0 is SWI number, R1 buffer pointer, R2 is buffer offset to use
; R3 is buffer limit
        CMP     R2, R3
        BGE     dont_confuse_the_poor_dears
        Push   "R4-R6"
        AND     R0, R0, #Module_SWIChunkSize - 1
        LDR     R12, [R12, #Module_incarnation_list]
        ADDS    R12, R12, #Incarnation_Workspace      ; force V clear
        MOV     lr, PC
        ADD     PC, R9, R10
        Pull   "R4-R6"
        Pull   "R9, R12"
        BVC     ExitSwiSwi

dont_confuse_the_poor_dears
        ADRL    R9, BufferOFloError
        ORR     R12, R12, #V_bit
        B       ExitSwiSwi

usethemoduletitle
        LDR     R10, [R9, #Module_Title]
        ADD     R11, R10, R9
        Pull   "R9, R12"
        BL      AddString
        MOV     R10, #"_"
        BL      AddChar
        AND     R0, R0, #Module_SWIChunkSize-1
        B       AddNumericBit

giveemaboringname                         ; not found anywhere interesting
        Pull   "R9, R12"
        ADR     R11, %BT02
        B       AddStringAndExit

Swi_Is_WriteI
        ADR     R11, %BT03
        BL      AddString

        AND     R0, R0, #255
        CMP     R0, #32
        BLT     AddNumericBit
        CMP     R0, #127
        BGE     AddNumericBit
        MOV     R10, #""""
        BL      AddChar
        MOV     R10, R0
        BL      AddChar
        MOV     R10, #""""
        BL      AddChar
        B       ExitSwiSwi

AddNumericBit
        Push   "R1, R2"
        ADD     R1, R1, R2                 ; point at remaining buffer
        SUB     R2, R3, R2                 ; buffer left
        SWI     XOS_BinaryToDecimal
        ORRVS   R12, R12, #V_bit
        MOVVS   R9, R0
        MOV     R0, R2
        Pull   "R1, R2"
        ADD     R2, R2, R0                 ; adjust chars given
        B       ExitSwiSwi

AddChar ROUT
; R10 character
; R1 buffer pointer
; R2 buffer position
; R3 buffer limit
        CMP     R2, R3
        BGE     %FT01
        STRB    R10, [R1, R2]
        ADD     R2, R2, #1
        MOVS    PC, lr

01      ADRL    R9, BufferOFloError
        ORR     R12, R12, #V_bit
        MOVS    PC, lr

AddString       ROUT
 ; R11 points at string to add
        Push    lr
01      LDRB    R10, [R11], #1
        CMP     R10, #0
        BLNE    AddChar
        BNE     %BT01
        Pull    PC

GetStringFromTable
; R11 points at first SWI name in table
; R0 is table offset
; return with R11 pointing at string, or V set for not in table
; R10, R0 corrupted
        LDRB    R10, [R11]
        CMP     R10, #0
        ORREQS  PC, lr, #V_bit           ; end of table
        SUBS    R0, R0, #1
        BICMIS  PC, lr, #V_bit
01      LDRB    R10, [R11], #1
        CMP     R10, #0
        BNE     %BT01
        B       GetStringFromTable
     ]

;***********************************************************************

SWINumberFromString_Code   ROUT

     [ ChopOffTheGoolies
        ADR     R0, %FT01
        ORR     lr, lr, #V_bit
        ExitSWIHandler
01
        &       0
        =      "Removed for Greenwich version",0
        ALIGN
     |
; R1 pointer to name terminated by char <= " "
; return R0 as SWI number
        Push   "R1, lr"
        TEQP    PC, #SVC_mode       ; enable interrupts
        LDRB    R10, [R1]
        CMP     R10, #"X"
        MOVEQ   R0, #Auto_Error_SWI_bit
        ADDEQ   R1, R1, #1
        MOVNE   R0, #0
        ADRL    R11, OS_Prefix         ; point at system table
        BL      LookForSwiName
        BVC     GotTheSWIName

        BIC     R0, R0, #255
        ADRL    R11, othersysswitab
        BL      LookForSwiName
        ORRVC   R0, R0, #OS_ConvertStandardDateAndTime
        BVC     GotTheSWIName

        BIC     R0, R0, #255
        ADRL    R11, convswitab
        BL      LookForSwiName
        ADDVC   R0, R0, #OS_ConvertHex1
        BVC     GotTheSWIName

        BIC     R0, R0, #255
        ADRL    R11, andpissaboutwithWriteI
        BL      LookForSwiName
        ORRVC   R0, R0, #OS_WriteI
        BVC     GotTheSWIName

        MOV     R12, #Module_List
01      LDR     R12, [R12]
        CMP     R12, #0
        BEQ     this_swi_nexiste_pas
        LDR     R10, [R12, #Module_code_pointer]
        LDR     R11, [R10, #Module_SWIEntry]
        TST     R11, #ARM_CC_Mask
        BNE     %BT01

        LDR     R11, [R10, #Module_SWIChunk]
        BIC     R11, R11, #Auto_Error_SWI_bit
        TST     R11, #Module_SWIChunkSize-1
        TST     R11, #&FF000000
        BNE     %BT01

        LDR     R11, [R10, #Module_NameTable]
        CMP     R11, #4*1024*1024
        BHI     %FT02
        ADD     R11, R10, R11

        BL      LookForSwiName
        BVS     %FT03
gotmodulejobbie
        LDR     R11, [R10, #Module_SWIChunk]
        BIC     R11, R11, #Auto_Error_SWI_bit
        ORR     R0, R0, R11
        B       GotTheSWIName

03  ; call module code if it exists.
        LDR     R11, [R10, #Module_NameCode]
        CMP     R11, #0
        BEQ     %BT01
        TST     R11, #ARM_CC_Mask
        BNE     %BT01
        CMP     R11, #4*1024*1024         ; offset too big?
        BHI     %BT01
        
; got R1 string pointer

        Push   "R0-R6, R12"
        MOV     R0, #-1                   ; indicate string being given
        LDR     R12, [R12, #Module_incarnation_list]
        ADDS    R12, R12, #Incarnation_Workspace      ; force V clear
        MOV     lr, PC
        ADD     PC, R11, R10
        MOV     R2, R0
        Pull   "R0"
        CMP     R2, #0
        ADDPL   R0, R0, R2
        Pull   "R1-R6, R12"
        BMI     %BT01
        B       gotmodulejobbie

02   ; check against module title
        Push    "R9, R10, R12"
        MOV     R12, #0                 ; offset in name
        LDR     R11, [R10, #Module_Title]
        CMP     R11, #0
        Pull    "R9, R10, R12",EQ
        BEQ     %BT01
        ADD     R11, R11, R10

; first check that prefix matches the title
CheckAgainstTitle
        LDRB    R10, [R1, R12]
        ADD     R12, R12, #1
        LDRB    R9, [R11], #1
        CMP     R9, R10
        BEQ     CheckAgainstTitle

        CMP     R10, #"_"               ; check correct terminators
        CMPEQ   R9,  #0
        Pull   "R9, R10, R12", NE
        BNE     %BT01
; title matches: check for numeric postfix
        Push    "R0-R2"
        ADD     R1, R1, R12
        MOV     R0, #10 + (1 :SHL: 29)
        MOV     R2, #Module_SWIChunkSize-1 ; restrict to this range
        SWI     XOS_ReadUnsigned
        Pull    "R0"
        Pull    "R1, R2, R9, R10, R12", VS
        BVS     %BT01
        ADD     R0, R0, R2
        LDRB    R2, [R1]
        CMP     R2, #" "                ; check termination
        Pull    "R1, R2, R9, R10, R12"
        BLE     gotmodulejobbie
        B       %BT01

this_swi_nexiste_pas
        SETV
GotTheSWIName
        Pull    "R1, lr"
        ADRVS   R0, ErrorBlock_NoSuchSWI2
        B       SLVK_TestV

        MakeErrorBlock NoSuchSWI2


LookForSwiName
; R11 points at name table
; R1 points at name
; return R0 ORed with number if found
; V set if not

        Push    "R8-R10, R12, lr"
        BIC     R0, R0, #Module_SWIChunkSize -1
        MOV     R12, #0                 ; offset in name

; first check that prefix matches
CheckPrefix
        LDRB    R10, [R1, R12]
        ADD     R12, R12, #1
        LDRB    R9, [R11], #1
        CMP     R9, R10
        BEQ     CheckPrefix

        CMP     R10, #"_"               ; check correct terminators
        CMPEQ   R9,  #0
        Pull    "R8-R10, R12, lr", NE
        ORRNES  PC, lr, #V_bit

; prefix OK: scan table for rest of name

        MOV     R8, R12                 ; keep pointer to after prefix
ScanForName
        LDRB    R10, [R11], #1
        CMP     R10, #0
        BEQ     CheckForNumericPostFix
ScanName
        LDRB    R9, [R1, R12]
        ADD     R12, R12, #1

        CMP     R10, #0
        CMPEQ   R9, #" "
        Pull    "R8-R10, R12, lr", LE
        BICLES  PC, lr, #V_bit

        CMP     R9, R10
        LDREQB  R10, [R11], #1
        BEQ     ScanName

        MOV     R12, R8                 ; restore name pointer
        ADD     R0, R0, #1              ; step SWI number
FindNameEnd
        CMP     R10, #0
        BEQ     ScanForName
        LDRB    R10, [R11], #1
        B       FindNameEnd

CheckForNumericPostFix
; [R1, R12] points at postfix
        Push    "R0-R2"
        ADD     R1, R1, R12
        MOV     R0, #10 + (1 :SHL: 29)
        MOV     R2, #Module_SWIChunkSize -1
        SWI     XOS_ReadUnsigned
        Pull    "R0"
        BIC     R0, R0, #Module_SWIChunkSize -1
        ADDVC   R0, R0, R2
        Pull    "R1, R2, R8-R10, R12, PC"
    ]

        LNK     TickEvents
