chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Core / s / oxswi
1 ;
2 ; oxswi.s
3 ;
4 ; Original version of _swi[x] SWI veneers
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's C library stubs (xstubs).
12 ;
13 ; xstubs is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
16 ; any later version.
17 ;
18 ; xstubs is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ; GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public License
24 ; along with xstubs.  If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Standard header ------------------------------------------------------
28
29                 GET     libs:header
30                 GET     libs:swis
31
32                 GET     libs:stream
33
34 ;----- Main code ------------------------------------------------------------
35
36                 AREA    |C$$code|,CODE,READONLY
37
38 ; --- _swi, _swix ---
39 ;
40 ; On entry:     R0 == SWI number
41 ;               R1 == flags
42 ;               R2,R3 == arguments
43 ;               More arguments on stack
44 ;
45 ; On exit:      R0 == output register, if any
46 ;
47 ; Use:          Generalised SWI veneer, compatible with Acorn's latest.
48
49                 EXPORT  |_swi|
50                 EXPORT  |_swix|
51
52 swi             ROUT
53
54 |_swi|          MOV     R12,R13                 ;Keep stack pointer safe
55                 STMFD   R13!,{R2,R3}            ;Save variadic args on stack
56                 STMFD   R13!,{R4-R12,R14}       ;Save loads of other regs
57                 ADR     R10,%20swi              ;Go to the SWI return pt
58                 B       %00swi                  ;Do the main job thing
59
60 |_swix|         MOV     R12,R13                 ;Keep stack pointer safe
61                 STMFD   R13!,{R2,R3}            ;Save variadic args on stack
62                 STMFD   R13!,{R4-R12,R14}       ;Save loads of other regs
63                 ORR     R0,R0,#&20000           ;Set the SWI's X bit
64                 BIC     R1,R1,#&000F0000        ;Make it return R0
65                 ADR     R10,%10swi              ;Go to the SWIX return pt
66
67                 ; --- Build entry stack frame ---
68
69 00swi           MOV     R2,R1,LSL #22           ;Get the input registers
70                 MOVS    R2,R2,LSR #22
71                 ORRNE   R2,R2,#&E8000000        ;Build that as an LDMIA
72                 ORRNE   R2,R2,#&00BC0000        ;Based on R12 (ip)
73
74                 ANDS    R3,R1,#&800             ;Does he want a local block?
75                 BLNE    %80swi                  ;Yes -- better find it then
76
77                 ORR     R4,R0,#&EF000000        ;Build the SWI instruction
78
79                 MOV     R6,#&E1000000           ;Build a MOV skeleton
80                 ORR     R6,R6,#&00A00000
81
82                 AND     R5,R1,#&000F0000        ;Get return register value
83                 ORR     R5,R6,R5,LSR #16        ;Put in the source register
84                 ORR     R5,R5,#&0000E000        ;Put in destination
85
86                 ORR     R6,R6,#&0000F000        ;Set up return instruction
87                 ORR     R6,R6,#&0000000A
88
89                 SUB     R12,R12,#8              ;Find variadic arguments
90                 STMFD   R13!,{R2-R6}            ;Build SWI-calling frame
91
92                 BARRIER
93                 MOV     R11,R1                  ;Look after the flags word
94                 MOV     PC,R13                  ;And call the stack code
95
96                 ; --- Process a return from the SWI ---
97
98 10swi           MOVVC   R14,#0                  ;If no error, return 0
99 20swi           STR     PC,[R13,#0]             ;Save my program counter
100
101                 ; --- Output the output registers ---
102
103                 MOVS    R11,R11,LSL #1          ;Shift bits to C and N
104                 LDRCS   R10,[R12],#4            ;If we write R0, find addr
105                 STRCS   R0,[R10,#0]             ;And write it out
106                 LDRMI   R10,[R12],#4            ;If we write R1, find addr
107                 STRMI   R1,[R10,#0]             ;And write it out
108
109                 MOVS    R11,R11,LSL #2          ;Move next two bits out
110                 LDRCS   R10,[R12],#4            ;If we write R2, find addr
111                 STRCS   R2,[R10,#0]             ;And write it out
112                 LDRMI   R10,[R12],#4            ;If we write R3, find addr
113                 STRMI   R3,[R10,#0]             ;And write it out
114                 TST     R11,#&7F000000          ;Any more to do?
115                 BEQ     %30swi                  ;No -- save 16 cycles
116
117                 MOVS    R11,R11,LSL #2          ;Move next two bits out
118                 LDRCS   R10,[R12],#4            ;If we write R4, find addr
119                 STRCS   R4,[R10,#0]             ;And write it out
120                 LDRMI   R10,[R12],#4            ;If we write R5, find addr
121                 STRMI   R5,[R10,#0]             ;And write it out
122
123                 MOVS    R11,R11,LSL #2          ;Move next two bits out
124                 LDRCS   R10,[R12],#4            ;If we write R6, find addr
125                 STRCS   R6,[R10,#0]             ;And write it out
126                 LDRMI   R10,[R12],#4            ;If we write R7, find addr
127                 STRMI   R7,[R10,#0]             ;And write it out
128
129                 MOVS    R11,R11,LSL #2          ;Move next two bits out
130                 LDRCS   R10,[R12],#4            ;If we write R8, find addr
131                 STRCS   R8,[R10,#0]             ;And write it out
132                 LDRMI   R10,[R12],#4            ;If we write R9, find addr
133                 STRMI   R9,[R10,#0]             ;And write it out
134
135                 TST     R11,#&40000000          ;Is the `write PC' bit set?
136                 LDRNE   R0,[R13,#0]             ;Yes -- load the one I saved
137                 LDRNE   R10,[R12],#4            ;Load the address
138                 STRNE   R0,[R10,#0]             ;And write the PC value out
139
140 30swi           ADD     R13,R13,#20             ;Restore the stack pointer
141                 MOV     R0,R14                  ;Get the return value
142                 LDMFD   R13!,{R4-R11,R13,PC}^   ;And return to caller
143
144                 ; --- Work out address of literal block ---
145
146 80swi           MOVS    R4,R1,LSL #1            ;Look after flags word
147                 MOV     R5,#6                   ;Simple counter thingy
148                 AND     R3,R1,#&0000F000        ;Get the block register
149                 ORR     R3,R3,#&E2000000        ;Build into ADD instruction
150                 ORR     R3,R3,#&008C0000
151
152 85swi           ADDCS   R3,R3,#4                ;Move pointer on for each reg
153                 ADDMI   R3,R3,#4
154                 SUBS    R5,R5,#1                ;Decrement counter too
155                 MOVLE   PC,R14                  ;If finished, return
156                 MOVS    R4,R4,LSL #2            ;Shift next two bits out
157                 B       %85swi                  ;And loop round again
158
159                 LTORG
160
161 ;----- That's all, folks ----------------------------------------------------
162
163                 END