;Compiled code conventions ;
;Registers:
;
;RB         8    Called address     ;can be used without saving
;RL         12   Caller's static
;RTS        11   Top of stack (empty word above)
;RP         10   Frame pointer
;RG         9    Global base
;RGB        7    Special global base
;
;There is an upwards-growing stack, addressed by two registers.  R(F)P is the
;frame pointer, RTS the top of stack+1 free word pointer.
;RG points at the base of the global vector; RGB addresses a set of subroutines
;within the library.
;
;On procedure entry, RB holds the address of the called procedure.  It need not
;be preserved.  RL holds the address of the caller's static data, and must be
;preserved.  R14 holds the link: this must be written to both PC and PSR on
;return.  R1 to R4 hold the first four arguments, with others on the stack
;above RTS in the usual way. Thus, a general procedure would look like:
;        STMEA   rts!, {rb, rp, rl, r14} ; save linkage
;        SUB     rp, rts, #16            ; new frame pointer
;        STMEA   rts!, {a1, ...}         ; arguments
;           ...
;
;R0 to R6 and RB(8) may be used without saving their values; so may R13 and
;moreover it is accessible from BCPL through the name NIL (assignment to NIL
;from BCPL has the side-effect of updating R6).  R6 and R13 are guaranteed
;untouched by the library, and by BCPL code which does not update NIL.
;
;On return, a1 holds value received.


          Result2 = 13 << 2

          .include  "regnames"
          .include  "swinames"
Timersw=400         ; <= 0 to remove report
          .AREA     Code
Start:    .ascii     "BCPL"
          .LONG     Globinits-Start
          .ascii    "Byte&SWI"
          .ASCII    "25 Dec 89 00-00-00  "
          .LONG     0
          .long     -1
          .ascic    "OSNewln"
OSNewLine:swi       OS_NewLine
          mov       pc,lr
          .long     -1
          .ascic    "OSRdMdV"
OSReadModeVariable:
          mov       r0, a1
          mov       a1, a2
          swi       OS_ReadModeVariable
          mov       a1, a2
          movcc     r0, #0
          mvncs     r0, #0
          strcc     r0, [ rg, #Result2 ]
          mov       pc, lr
          .long     -1
          .ascic    "OSModeV"
OSCheckModeValid:
          mov       r0, a1
          swi       OS_CheckModeValid
          movcc     a1, #0
          movcc     pc, lr
          str       a1, [ rg, #Result2 ]
          mov       a1, r0
          mov       pc, lr
          .long     -1
          .ascic    "OSGBPB "
OSGBPB:   mov       r0, a1              ; action
          mov       a1, a2              ; handle
          mov       rb, a3, lsl #2      ; Args
          ldmia     rb,{ a2 - r6 }      ; R2-5 from vector
          swi       OS_GBPB+XOS
          stmia     rb,{ a2 - r6 }      ; R2-5 to vector
          mov       a1, #0              ; OK return 0
          mvnvs     a1, #0              ; Error return -1
          mov       pc, lr
          .long     -1
          .ascic    "OSConfm"
OSConfirm:
          swi       OS_Confirm
          str       r0, [rg, #Result2]  ; character returned
          movcs     r1, #1
          movcs     pc, lr              ; returns 1 for escape
          mov       r1, #0              ;  0 No
          mvnvs     r1, #0              ; -1 Yes
          mov       pc, lr
          .long     -1
          .ascic    "OSFSctr"
OSGenerateEvent:
          mov       r0, a1            ; Event no
          mov       a1, a2
          mov       a2, a3
          mov       rb, a4, lsl #2      ; Args 4-6
          ldmia     rb, {a3 - r6}
          swi       OS_GenerateEvent
          mov       pc, lr
OSFSControl:
          stmea     rts!, {rgb, nil}
          mov       nil, a4, lsl #2     ; p4 (Args)
          mov       r0, a1
          mov       a1, a2, lsl #2
          ldrb      a2, [a1], #1        ; string byte base, length; incr a1
          add       a4, a2, a1          ; string byte terminator position
          mov       a2, a3              ; p3
          ldrb      r5, [a4]
          mov       rb, #0
          strb      rb, [a4]
          stmea     rts!, {a4, r5}
          ldmia     nil, {a3-rb}        ; a3 - a8
          swi       OS_FSControl + XOS
          stmia     nil, {a2-a3}         ; returns a2,3
          mov       rb, #0
          mvnvs     rb, #0
          str       rb, [rg, #Result2]  ; returns fault
          ldmea     rts!, {a4, r5}
          strb      r5, [a4]            ; restore terminator
          mov       a4, nil, lsr #2
          ldmea     rts!, {rgb, nil}
          mov       pc, lr
          .long     -1
          .ascic    "OSRdUns"
OSReadUnsigned:
          mov       r0, a1               ; base
          mov       a1, a3
          add       a1, a1, a2, lsl #2  ; bcpl string a2%a3
          mov       a2, a4              ; max val
          swi       OS_ReadUnsigned + XOS
          str       a1, [ rg, #Result2 ]     ; Terminator to Result2
          mov       a1, a2
          mov       pc, lr
          .long     -1
          .ascic    "OSRdvar"
OSReadVarVal:
          ldr       r0, [pc, #rvv-$-8]
rsvv:     str       r0, [pc, #swivv-$-8]
          mov       r0, #1
          add       r0, r0, a1, lsl #2  ; name
          cmp       a2, #0
          movge     a1, #1
          addge     a1, a1, a2, lsl #2  ; BCPL Word buffer if p2 >= 0
          sublt     a2, a2, #1
          mvnlt     a1, a2              ; Byte Buffer if p2 < 0
          mov       rb, a3, lsl #2      ; Args
          ldmia     rb, { a2 - a4 }     ; R2-4 from vector
          cmp       a4, #1              ; Number ?
          subeq     a1, a1, #1
swivv:    .long     0
          stmia     rb, { a2 - a4 }     ; R2-4 to vector
          mov       pc, lr
rvv:      swi       OS_ReadVarVal+XOS
          .long     -1
          .ascic    "OSSetvv"
OSSetVarVal:
          ldr       r0, [pc, #svv-$-8]
          b         rsvv
svv:      swi       OS_SetVarVal
          .long     -1
          .ascic    "OSEvExp"
OSEvaluateExpression:
          mov       r0, #1
          add       r0, r0, a1, lsl #2  ; String
          mov       a1, #1
          add       a1, a1, a2, lsl #2  ; Buffer
          mov       rb, a1
          mov       a2, a3              ; length of Buffer
          swi       OS_EvaluateExpression
res2:     str       a2, [ rg, #Result2 ]     ; Val/Length to Result2
          mov       a1, r0              ; type result
          mov       pc, lr
          .long     -1
          .ascic    "OSWrteN"
OSWriteN: cmp       a2, #0
          movle     pc, lr
          mov       r0, a1              ; String
          mov       a1, a2              ; Length
          SWI       OS_WriteN
          mov       pc, lr
          .long     -1
          .ascic    "OSWrte0"
OSWrite0: mov       r0, a1
          swi       OS_Write0
          mov       a1, r0
          mov       pc, lr
          .long     -1
          .ascic    "OSRdPal"
OSReadPalette:
          mov       r0, a1
          mov       a1, a2
          swi       OS_ReadPalette
          str       a3, [ rg, #Result2 ]
          mov       a1, a2
          mov       pc, lr
          .long     -1
          .ascic    "ADDrive"
ADFSFreeSpace:
          mov       r0, a1              ; Drive
          swi       ADFS_FreeSpace
          str       a1, [ rg, #Result2 ]     ; Largest Single area
          mov       a1, r0
          mov       pc, lr
          .long     -1
          .ascic    "OSRdArg"
OSReadArgs:
          mov       r0, #1
          add       r0, r0, a1, lsl #2  ; Key defn
          mov       a1, #1
          add       a1, a1, a2, lsl #2  ; Input string
          ldr       a2, [a1]
          cmp       a2, #0
          addeq     a1, a1, #1
          mov       a2, a3, lsl #2      ; Output vector
          mov       a3, a4              ; Bytes in ov
          swi       OS_ReadArgs + XOS
          str       r3, [ rg, #Result2 ]
          mov       a1, #0              ; OK return 0
          mvnvs     a1, #0              ; Error return -1
          mov       pc, lr
          .long     -1
          .ascic    "OSBtoA "
OSConvert:
          ldr       r5, [pc, #swi0-$-8]
          cmp       a4, #0
          suble     r5, r5, a4          ; decr -ve a4 -> Byte-addressed buffer
          addgt     r5, r5, a4
          str       r5, [pc, #swid-$-8]
          mov       r0, a1
          movle     a1, a2              ; byte addr
          movgt     a1, a2, lsl #2      ; word addr
          mov       a2, a3
swid:     .long     0
          sub       a1, a1, r0          ; Text length (next 0)
          mov       pc, lr
swi0:     swi       OS_WriteC           ;0
          .long     -1
          .ascic    "OSModul"
OSModule: mov       r0, a1
          mov       a1, a2
          mov       rb, a3, lsl #2
          ldmia     rb, { a2-a3 }
          swi       OS_Module
          stmia     rb, {a2-r5}
          str       a1, [rg, #Result2]
          mov       a1, a2
          mov       pc, lr
          .long     -1
          .ascic    "OSHeap "
OSHeap:   mov       r0, a1
          mov       a1, a2
          mov       a2, a3, lsl #2
          mov       a3, a4
          swi       OS_Heap
          mov       a1, a3
          str       a2, [ rg, #Result2 ]
          mov       pc, lr
          .long     -1
          .ascic    "OSRMTim"
OSReadMonotonicTime:
          swi       OS_ReadMonotonicTime
          mov       a1, r0
          mov       pc, lr
          .long     -1
          .ascic     "OSRemcr"
OSRemoveCursors:
          swi       OS_RemoveCursors
          mov       pc, lr
          .long     -1
          .ascic    "OSRescr"
OSRestoreCursors:
          swi       OS_RestoreCursors
          mov       pc, lr
          .long     -1
          .ascic    "OSPrint"
OSPrintChar:
          mov       r0, a1
          swi       OS_PrintChar
          mov       pc, lr
          .long     -1
          .ascic    "OSRdVdu"
OSReadVduVariables:
          mov       r0, a1, lsl #2
          mov       a1, a2, lsl #2
          swi       OS_ReadVduVariables
          mov       pc, lr
          .long     -1
          .ascic     "OSMouse"
OSMouse:  mov       rb, a1, lsl #2
          swi       OS_Mouse
          stmia     rb, {r0 - a3}
          mov       pc, lr
          .long     -1
          .ascic    "OSSprOp"
OSSpriteOp:
          mov       r0, a1              ; Reason Code
          mov       a1, a2, lsl #2      ; Control Block
          mov       a2, a3, lsl #2
          add       a2, a2, #1          ; Path Name
          str       rgb, [pc, #srgb-$-8]
          ldmia     rb, {a3-rgb }
          swi       OS_SpriteOp
          stmea     rb, {a3-rgb}
          ldr       rgb, [pc, #srgb-$-8]
          mov       pc, lr
srgb:     .long     0
          .long     -1
          .ascic    "OSPlotX"
OSPlot:   mov       r0, a1
          mov       a1, a2
          mov       a2, a3
          swi       OS_Plot
          mov       pc, lr
Globinits:
          .long     23
          .long     OSNewLine-Start
          .long     69
          .long     OSReadModeVariable - Start
          .long     70
          .long     OSCheckModeValid - Start
          .long     107
          .long     OSGBPB-Start
          .long     108
          .long     OSConfirm-Start
          .long     109
          .long     OSGenerateEvent - Start
          .long     114
          .long     OSWriteN-Start
          .long     115
          .long     OSFSControl-Start
          .long     116
          .long     OSSetVarVal-Start
          .long     117
          .long     OSReadVarVal-Start
          .long     120
          .long     OSEvaluateExpression-Start
          .long     121
          .long     OSReadUnsigned-Start
          .long     122
          .long     OSWrite0-Start
          .long     123
          .long     OSReadPalette-Start
          .long     125
          .long     ADFSFreeSpace-Start
          .long     126
          .long     OSReadArgs-Start
          .long     127
          .long     OSConvert-Start
          .long     128
          .long     OSModule-Start
          .long     129
          .long     OSHeap-Start
          .long     130
          .long     OSReadMonotonicTime-Start
          .long     131
          .long     OSRemoveCursors
          .long     132
          .long     OSRestoreCursors
          .long     133
          .long     OSPrintChar
          .long     134
          .long     OSReadVduVariables
          .long     143
          .long     OSMouse-Start
          .long     144
          .long     OSSpriteOp-Start
          .long     145
          .long     OSPlot-Start
          .long     150
          .long     0
          .LONG  0x12345678
          .LONG  Globinits + 4 - Start
          .LONG  Globinits + 12 - Start
          .LONG  Globinits + 20 - Start
          .LONG  Globinits + 28 - Start
          .LONG  Globinits + 36 - Start
          .LONG  Globinits + 44 - Start
          .LONG  Globinits + 52 - Start
          .LONG  Globinits + 60 - Start
          .LONG  Globinits + 68 - Start
          .LONG  Globinits + 76 - Start
          .LONG  Globinits + 84 - Start
          .LONG  Globinits + 92 - Start
          .LONG  Globinits + 100 - Start
          .LONG  Globinits + 108 - Start
          .LONG  Globinits + 116 - Start
          .LONG  Globinits + 124 - Start
          .LONG  Globinits + 132 - Start
          .LONG  Globinits + 140 - Start
          .LONG  Globinits + 148 - Start
          .LONG  Globinits + 156 - Start
          .LONG  Globinits + 164 - Start
          .LONG  Globinits + 172 - Start
          .LONG  Globinits + 180 - Start
          .LONG  Globinits + 188 - Start
          .LONG  Globinits + 196 - Start
          .LONG  Globinits + 204 - Start
          .LONG  Globinits + 212 - Start
          .LONG  0x87654321
