; 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.
;
; > s.swi

; ****************************************************************************
; * This source file was written by Acorn Computers Limited. It is part of   *
; * the "cwimp" library for writing applications in C for RISC OS. It may be *
; * used freely in the creation of programs for Archimedes. It should be     *
; * used with Acorn's objasm assembler                                       *
; *                                                                          *
; * No support can be given to programmers using this code and, while we     *
; * believe that it is correct, no correspondence can be entered into        *
; * concerning behaviour or bugs.                                            *
; *                                                                          *
; * Upgrades of this code may or may not appear, and while every effort will *
; * be made to keep such upgrades upwards compatible, no guarantees can be   *
; * given.                                                                   *
; ****************************************************************************

; Title  : s.swi
; Purpose: provide access to RISC OS SWIs from C
; Version: 0.1     created
;          0.2 RCM bbc_vdu & bbc_vduw now return ->os_error in R0
;          0.3 SKS made os_swi, os_swix accept NULL inout regset
;                  bbc_get now returns &1xx when an ESCAPE condition is present
;                  optional with names assembly for postmortem
;              ECN 08-May-91 Removed bbc_get for ROM release

        GBLL    names
names   SETL    {TRUE}

        GBLL    ModeMayBeNonUser
ModeMayBeNonUser   SETL  {FALSE}

        GET     Hdr:ListOpts
        GET     Hdr:APCS.Common
        GET     Hdr:Macros

XOS_MASK      * &00020000 ; mask to make a swi a RISC OS V-error SWI

XOS_WriteC      * XOS_MASK + 0
XOS_ReadC       * XOS_MASK + 4
XOS_Byte        * XOS_MASK + 6
XOS_Word        * XOS_MASK + 7
XOS_ReadVarVal  * XOS_MASK + &23
XOS_CallASWIR12 * XOS_MASK + &71


; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Register names


        [ :LNOT:UROM
        EXPORT  |bbc_get|
        ]
        EXPORT  |bbc_vdu|
        EXPORT  |bbc_vduw|
        EXPORT  |os_swi|
        EXPORT  |os_swix|
        EXPORT  |os_swi0|
        EXPORT  |os_swi1|
        EXPORT  |os_swi2|
        EXPORT  |os_swi3|
        EXPORT  |os_swi4|
        EXPORT  |os_swi5|
        EXPORT  |os_swi6|
        EXPORT  |os_swi1r|
        EXPORT  |os_swi2r|
        EXPORT  |os_swi3r|
        EXPORT  |os_swi4r|
        EXPORT  |os_swi5r|
        EXPORT  |os_swi6r|
        EXPORT  |os_swix0|
        EXPORT  |os_swix1|
        EXPORT  |os_swix2|
        EXPORT  |os_swix3|
        EXPORT  |os_swix4|
        EXPORT  |os_swix5|
        EXPORT  |os_swix6|
        EXPORT  |os_swix1r|
        EXPORT  |os_swix2r|
        EXPORT  |os_swix3r|
        EXPORT  |os_swix4r|
        EXPORT  |os_swix5r|
        EXPORT  |os_swix6r|
        EXPORT  |os_byte|
        EXPORT  |os_word|
        EXPORT  |os_read_var_val|

        AREA    |C$$code|, CODE, READONLY

|v$codesegment|

        [ :LNOT:UROM
bbc_get SWI     XOS_ReadC
        Return  ,LinkNotStacked,VS
        ORRCS   a1, a1, #&100           ; SKS
        Return  ,LinkNotStacked
        ]

bbc_vduw
        SWI     XOS_WriteC
        Return  ,LinkNotStacked,VS
        MOV     a1, a1, LSR #8
bbc_vdu SWI     XOS_WriteC
        MOVVC   a1, #0
        Return  ,LinkNotStacked


; void os_swi(int swicode, os_regset* /*inout*/);

; In    a1 contains swi number, a2 points to ARM register structure

os_swi
        STMDB   sp!, {v1-v6, lr}
        MOV     r12, r0
        CMP     r1, #0
        BEQ     os_swi_noregset
        STMDB   sp!, {r1}
        LDMIA   r1, {r0-r9}
        SWI     XOS_CallASWIR12
        LDMIA   sp!, {ip}
        STMIA   ip, {r0-r9}
        Return  "v1-v6"
os_swi_noregset
        SWI     XOS_CallASWIR12
        Return  "v1-v6"


; os_error *os_swix(int swicode, os_regset* /*inout*/);

; In    a1 contains swi number, a2 points to ARM register structure

os_swix
        STMDB   sp!, {v1-v6, lr}
        ORR     a1, a1, #XOS_MASK       ; make a SWI of V-error type
        MOV     r12, r0
        CMP     r1, #0
        BEQ     os_swix_noregset
        STMDB   sp!, {r1}
        LDMIA   r1, {r0-r9}
        SWI     XOS_CallASWIR12
        LDMIA   sp!, {ip}
        STMIA   ip, {r0-r9}
        MOVVC   a1, #0
        Return  "v1-v6"
os_swix_noregset
        SWI     XOS_CallASWIR12
        MOVVC   a1, #0
        Return  "v1-v6"

os_swix0
os_swix1
os_swix2
os_swix3
os_swix4
os_swix5
os_swix6
os_swix7
        ORR     a1, a1, #&20000
os_swi0
os_swi1
os_swi2
os_swi3
os_swi4
os_swi5
os_swi6
        STMDB   sp!, {v1-v6, lr}
        MOV     r12, r0
        MOV     a1, a2
        MOV     a2, a3
        MOV     a3, a4
        ADD     lr, sp, #7*4
        LDMIA   lr, {a4, v1, v2}
        SWI     XOS_CallASWIR12
        MOVVC   a1, #0
        Return  "v1-v6"

swi_ret_inst
        MOV     pc, ip

os_swix1r
        ORR     a1, a1, #&20000
os_swi1r
        STMDB   sp!, {a3, v1-v6, lr}
        MOV     r12, r0
        MOV     r0, a2
        SWI     XOS_CallASWIR12
        LDR     ip, [sp]
        Return  "a2,v1-v6",,VS
        TEQ     ip, #0
        STRNE   a1, [ip]
        MOV     a1, #0
        Return  "a2,v1-v6"

os_swix2r
        ORR     a1, a1, #&20000
os_swi2r
        STMDB   sp!, {a4, v1-v6, lr}
        MOV     r12, r0
        MOV     a1, a2
        MOV     a2, a3
        SWI     XOS_CallASWIR12
        LDR     ip, [sp]
        Return  "a2,v1-v6",,VS
        TEQ     ip, #0
        STRNE   a1, [ip]
        LDR     ip, [sp, #8 * 4]
        TEQ     ip, #0
        STRNE   a2, [ip]
        MOV     a1, #0
        Return  "a2,v1-v6"

os_swix3r
        ORR     a1, a1, #&20000
os_swi3r
        STMDB   sp!, {v1-v6, lr}
        MOV     r12, r0
        MOV     a1, a2
        MOV     a2, a3
        MOV     a3, a4
        SWI     XOS_CallASWIR12
        ADD     ip, sp, #7 * 4
        LDMIA   ip, {v1, v2, v3}
        Return  "v1-v6",,VS
        TEQ     v1, #0
        STRNE   a1, [v1]
        TEQ     v2, #0
        STRNE   a2, [v2]
        TEQ     v3, #0
        STRNE   a3, [v3]
        MOV     a1, #0
        Return  "v1-v6"

os_swix4r
        ORR     a1, a1, #&20000
os_swi4r
        STMDB   sp!, {v1-v6, lr}
        MOV     r12, r0
        MOV     a1, a2
        MOV     a2, a3
        MOV     a3, a4
        LDR     a4, [sp, #7 * 4]
        SWI     XOS_CallASWIR12
        ADD     ip, sp, #8 * 4
        LDMIA   ip, {v1-v4}
        Return  "v1-v6",,VS
        TEQ     v1, #0
        STRNE   a1, [v1]
        TEQ     v2, #0
        STRNE   a2, [v2]
        TEQ     v3, #0
        STRNE   a3, [v3]
        TEQ     v4, #0
        STRNE   a4, [v4]
        MOV     a1, #0
        Return  "v1-v6"

os_swix5r
        ORR     a1, a1, #&20000
os_swi5r
        STMDB   sp!, {v1-v6, lr}
        MOV     r12, r0
        MOV     a1, a2
        MOV     a2, a3
        MOV     a3, a4
        ADD     lr, sp, #7 * 4
        LDMIA   lr, {a4, v1}
        SWI     XOS_CallASWIR12
        ADD     ip, sp, #9 * 4
        LDMIA   ip, {v3-v6, ip}
        Return  "v1-v6",,VS
        TEQ     v3, #0
        STRNE   a1, [v3]
        TEQ     v4, #0
        STRNE   a2, [v4]
        TEQ     v5, #0
        STRNE   a3, [v5]
        TEQ     v6, #0
        STRNE   a4, [v6]
        TEQ     ip, #0
        STRNE   v1, [ip]
        MOV     a1, #0
        Return  "v1-v6"

os_swix6r
        ORR     a1, a1, #&20000
os_swi6r
        STMDB   sp!, {v1-v6, lr}
        MOV     r12, r0
        MOV     a1, a2
        MOV     a2, a3
        MOV     a3, a4
        ADD     lr, sp, #7 * 4
        LDMIA   lr, {a4, v1, v2}
        SWI     XOS_CallASWIR12
        ADD     ip, sp, #10 * 4
        LDMIA   ip, {v3-v6, ip, lr}     ; APCS-R assumption here
        Return  "v1-v6",,VS
        TEQ     v3, #0
        STRNE   a1, [v3]
        TEQ     v4, #0
        STRNE   a2, [v4]
        TEQ     v5, #0
        STRNE   a3, [v5]
        TEQ     v6, #0
        STRNE   a4, [v6]
        TEQ     ip, #0
        STRNE   v1, [ip]
        TEQ     lr, #0
        STRNE   v2, [lr]
        MOV     a1, #0
        Return  "v1-v6"

os_byte
        FunctionEntry
        MOV     r3, r1
        MOV     ip, r2
        LDR     r1, [r1]
        LDR     r2, [r2]
        SWI     XOS_Byte
        STR     r1, [r3]
        STR     r2, [ip]
        MOVVC   r0, #0
        Return

os_word
        MOV     ip, lr
        SWI     XOS_Word
        MOVVC   r0, #0
        Return  ,LinkNotStacked,,ip

os_read_var_val
        FunctionEntry "r4"
        MOV     r3, #0
        MOV     r4, #3
        SWI     XOS_ReadVarVal
        MOV     r0, #0
        STRVSB  r0, [r1]
        STRVCB  r0, [r1, r2]
        Return  "r4"

        END