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