; Copyright 1996 Acorn Computers Ltd
;
; 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.
;
        TTL     => SWINaming

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

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

;***********************************************************************
;
;       SWI OS_SWINumberToString
;
; in:   R0 = SWI number
;       R1 = buffer pointer
;       R2 = buffer length
;
; out:  Buffer holds SWI name, null-terminated
;

SWINumberToString_Code    ROUT
        WritePSRc SVC_mode, r12         ; interrupts on!
        MOV     r12, lr                 ; keep here so subroutines can update flags
        Push    "r3, r9"
        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
        BCS     NotASystemSWI           ; TMD 11-May-89: changed from GE

        ADR     r11, OS_Prefix
        BL      AddString
        MOV     r10, #"_"
        BL      AddChar

        CMP     r0, #256
        BCS     Swi_Is_WriteI           ; TMD 11-May-89: changed from GE
        CMP     r0, #NCORESWIS
        BCS     SWINotInTable           ; TMD 11-May-89: changed from GE

        ADR     r11, System_Swi_Names
        BL      GetStringFromTable

AddStringAndExit
        BL      AddString

ExitSwiSwi
        MOV     r10, #0
        BL      AddChar

        MOV     r0, r9                  ; error pointer or restoration
        Pull    "r3, r9"
        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
        AddSwiNameToDecodeTab ChangeRedirection
        AddSwiNameToDecodeTab RemoveCallBack
        AddSwiNameToDecodeTab FindMemMapEntries
        AddSwiNameToDecodeTab SetColour
        AddSwiNameToDecodeTab ClaimSWI          ; These two are not actually
        AddSwiNameToDecodeTab ReleaseSWI        ; kernel SWIs.
        AddSwiNameToDecodeTab Pointer
        AddSwiNameToDecodeTab ScreenMode
        AddSwiNameToDecodeTab DynamicArea
        AddSwiNameToDecodeTab AbortTrap
        AddSwiNameToDecodeTab Memory
        AddSwiNameToDecodeTab ClaimProcessorVector
        AddSwiNameToDecodeTab Reset
        AddSwiNameToDecodeTab MMUControl
        AddSwiNameToDecodeTab ResyncTime
        AddSwiNameToDecodeTab PlatformFeatures
        AddSwiNameToDecodeTab SynchroniseCodeAreas
        AddSwiNameToDecodeTab CallASWI
        AddSwiNameToDecodeTab AMBControl
        AddSwiNameToDecodeTab CallASWIR12
        AddSwiNameToDecodeTab SpecialControl
        AddSwiNameToDecodeTab EnterUSR32
        AddSwiNameToDecodeTab EnterUSR26
        AddSwiNameToDecodeTab VIDCDivider
        AddSwiNameToDecodeTab NVMemory
        AddSwiNameToDecodeTab ClaimOSSWI
        AddSwiNameToDecodeTab TaskControl
        AddSwiNameToDecodeTab DeviceDriver
        AddSwiNameToDecodeTab Hardware
        AddSwiNameToDecodeTab IICOp
        AddSwiNameToDecodeTab LeaveOS
        AddSwiNameToDecodeTab ReadLine32
        AddSwiNameToDecodeTab SubstituteArgs32
        AddSwiNameToDecodeTab HeapSort32
        = 0

 [ SwisInSystemTable+1 <> NCORESWIS
 ! 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
        AddSwiNameToDecodeTab  ConvertVariform
        =  0
        ALIGN


SWINotInTable
        SUB     r11, r0, #OS_ConvertHex1
        CMP     r11, #OS_ConvertVariform - 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

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

        ALIGN

NotASystemSWI
        Push    "r9, r12"
        BIC     r10, r0, #Module_SWIChunkSize-1
        ModSWIHashvalOffset r9, r10
      [ ZeroPage = 0
        LDR     r9, [r9, #ModuleSWI_HashTab]
      |
        LDR     r12, =ZeroPage+ModuleSWI_HashTab
        LDR     r9, [r9, r12]
      ]
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]
        LDR     r14, [r9, #-4]                          ; get module size
        CMP     r10, #1                                 ; must be non-zero
        CMPCS   r14, r10                                ; and must be within code
        BLS     trymodule_SWIdecode_code
        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"
        BVC     AddStringAndExit
        B       AddNumericBit                           ; not in table

trymodule_SWIdecode_code
        LDR     r10, [r9, #Module_NameCode]
        TST     r10, #12,2                              ; test bottom 2 bits and clear carry
        CMPEQ   r10, #1                                 ; must be non-zero
        CMPCS   r14, r10                                ; and must be within code
        BLS     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, r9, r12"
        BVC     ExitSwiSwi

dont_confuse_the_poor_dears
      [ International
        Push    "r0"
        ADRL    r0, BufferOFloError
        BL      TranslateError
        MOV     r9,r0
        Pull    "r0"
      |
        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
        BCS     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
;
; in:   R1 = buffer pointer
;       R2 = buffer position
;       R3 = buffer size
;       R10 = character
;
; out:  If overflow, V_bit set in R12, and R9 -> error
;       PSR preserved

AddChar ROUT
        EntryS
        CMP     r2, r3
        BGE     %FT01
        STRB    r10, [r1, r2]
        ADD     r2, r2, #1
        EXITS

01
      [ International
        Push    "r0,lr"
        ADRL    r0, BufferOFloError
        BL      TranslateError
        MOV     r9,r0
        Pull    "r0,lr"
      |
        ADRL    r9, BufferOFloError
      ]
        EXITVS

; AddString
;
; in:   R11 points at string to add
;
; out:  R10, R11 corrupted

AddString Entry
01
        LDRB    r10, [r11], #1
        CMP     r10, #0
        BLNE    AddChar
        BNE     %BT01
        EXIT

; GetStringFromTable
;
; in:   R0 is table offset
;       R11 points at first SWI name in table
;
; out:  R11 -> string or V set if not in table
;       R0, R10 corrupted

GetStringFromTable ROUT
        LDRB    r10, [r11]
        CMP     r10, #0
        BEQ     %FT02                   ; end of table
        SUBS    r0, r0, #1
        BPL     %FT01
        CLRV
        MOV     pc, lr
01
        LDRB    r10, [r11], #1
        CMP     r10, #0
        BNE     %BT01
        B       GetStringFromTable
02
        SETV
        MOV     pc, lr

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

; R1 pointer to name terminated by char <= " "
; return R0 as SWI number

SWINumberFromString_Code Entry "r1,r2"

        WritePSRc SVC_mode, r10                 ; enable interrupts
        LDRB    R10, [R1]
        CMP     R10, #"X"
        MOVEQ   R0, #Auto_Error_SWI_bit
        ADDEQ   R1, R1, #1
        MOVNE   R0, #0

        MOV     r10, #0                         ; indicate doing OS SWIs, so disallow OS_<number>
        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, andfiddleaboutwithWriteI
        BL      LookForSwiName
        ORRVC   r0, r0, #OS_WriteI
        BVC     GotTheSWIName

        LDR     r12, =ZeroPage+Module_List
10
        LDR     r12, [r12]
        CMP     r12, #0
        BEQ     this_swi_nexiste_pas
        LDR     r10, [r12, #Module_code_pointer]
        LDR     r11, [r10, #Module_SWIChunk]            ; first validate swi chunk
        BICS    r11, r11, #Auto_Error_SWI_bit
        BEQ     %BT10                                   ; SWI chunk zero not allowed
        TST     r11, #Module_SWIChunkSize-1
        TSTEQ   r11, #&FF000000
        BNE     %BT10                                   ; invalid SWI chunk

        LDR     r2, [r10, #-4]
        LDR     r11, [r10, #Module_SWIEntry]
        TST     r11, #12,2                              ; test bottom 2 bits and clear carry
        CMPEQ   r11, #1                                 ; must be non-zero
        CMPCS   r2, r11                                 ; and must be within code
        BLS     %BT10

        LDR     r11, [r10, #Module_NameTable]
        CMP     r11, #1                                 ; must be non-zero
        CMPCS   r2, r11                                 ; and must be within code
        BLS     %FT20                                   ; if no name table, try name code

        ADD     r11, r10, r11
        BIC     r0, r0, #Module_SWIChunkSize-1
        BL      LookForSwiName
        BVS     %FT20
gotmodulejobbie
        LDR     r11, [r10, #Module_SWIChunk]
        BIC     r11, r11, #Auto_Error_SWI_bit
        ORR     r0, r0, r11
        B       GotTheSWIName

; call module code if it exists

20
        LDR     r11, [r10, #Module_NameCode]
        TST     r11, #12,2                              ; test bottom 2 bits and clear carry
        CMPEQ   r11, #1                                 ; must be non-zero
        CMPCS   r2, r11                                 ; and must be within code
        BLS     %FT30                                   ; try <module-title>_<numeric>

; 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
        ADDS    r2, r0, #0                              ; NB clears V for SWI return
        Pull    "r0"
        ADDPL   r0, r0, r2
        Pull    "r1-r6, r12"
        BPL     gotmodulejobbie

; check against module title

30
        LDR     r11, [r10, #Module_Title]
        ADD     r11, r10, r11
        Push    r10
        MOV     r10, #1                                 ; indicate only check for prefix_numeric
        BL      LookForSwiName
        Pull    r10
        BVS     %BT10
        B       gotmodulejobbie

this_swi_nexiste_pas
        SETV
GotTheSWIName
        PullEnv
        ADRVS   r0, ErrorBlock_NoSuchSWI2
      [ International
        Push    "lr",VS
        BLVS    TranslateError
        Pull    "lr",VS
      ]
        B       SLVK_TestV

        MakeErrorBlock NoSuchSWI2


LookForSwiName ROUT
; R11 points at name table
; R1 points at name
; R10 = 0 => allow only prefix_name (for OS_SWI)
; R10 = 1 => allow only prefix_numeric (for checking moduletitle_numeric)
;       otherwise => allow prefix_name or prefix_numeric
; return R0 ORed with number if found
; V set if not

        Entry   "r8,r9, r12"
        MOV     r12, #0                                 ; offset in name

; first check that prefix matches
10
        LDRB    r14, [r1, r12]
        CMP     r14, #" "                               ; if we terminate before we get an "_", then fail
        BLE     %FT50
        ADD     r12, r12, #1
        LDRB    r9, [r11], #1
        CMP     r9, r14
        BEQ     %BT10

        CMP     r14, #"_"                               ; check correct terminators
        CMPEQ   r9,  #0
        BNE     %FT50

; prefix OK: scan table for rest of name

        TEQ     r10, #1                                 ; if doing modulename_numeric
        BEQ     CheckForNumericPostFix                  ; don't look for any names
        MOV     r8, r12                                 ; keep pointer to after prefix
20
        LDRB    r14, [r11], #1
        CMP     r14, #0
        BEQ     CheckForNumericPostFix
30
        LDRB    r9, [r1, r12]
        ADD     r12, r12, #1
        CMP     r14, #0
        CMPEQ   r9, #" "
        BGT     %FT35
        CLRV
        EXIT

35
        CMP     r9, r14
        LDREQB  r14, [r11], #1
        BEQ     %BT30

        MOV     r12, r8                                 ; restore name pointer
        ADD     r0, r0, #1                              ; step SWI number
40
        CMP     r14, #0                                 ; find end of failed name
        LDRNEB  r14, [r11], #1
        BNE     %BT40
        B       %BT20
50
        SETV
        EXIT

CheckForNumericPostFix
; [R1, R12] points at postfix
        Push    "r0-r2"
        ADD     r1, r1, r12
        CMP     r10, #0                                 ; if OS SWI then EQ,VC else NE,VC
        SETV    EQ                                      ; if OS SWI then VS else VC
        MOVVC   r0, #10 + (1 :SHL: 29)
        MOVVC   r2, #Module_SWIChunkSize -1
        SWIVC   XOS_ReadUnsigned
        Pull    "r0"
        BIC     r0, r0, #Module_SWIChunkSize -1
        ADDVC   r0, r0, r2
        Pull    "r1, r2, r8,r9, r12, pc"

        END