4 ; Original version of _swi[x] SWI veneers
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's C library stubs (xstubs).
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)
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.
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.
27 ;----- Standard header ------------------------------------------------------
34 ;----- Main code ------------------------------------------------------------
36 AREA |C$$code|,CODE,READONLY
40 ; On entry: R0 == SWI number
43 ; More arguments on stack
45 ; On exit: R0 == output register, if any
47 ; Use: Generalised SWI veneer, compatible with Acorn's latest.
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
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
67 ; --- Build entry stack frame ---
69 00swi MOV R2,R1,LSL #22 ;Get the input registers
71 ORRNE R2,R2,#&E8000000 ;Build that as an LDMIA
72 ORRNE R2,R2,#&00BC0000 ;Based on R12 (ip)
74 ANDS R3,R1,#&800 ;Does he want a local block?
75 BLNE %80swi ;Yes -- better find it then
77 ORR R4,R0,#&EF000000 ;Build the SWI instruction
79 MOV R6,#&E1000000 ;Build a MOV skeleton
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
86 ORR R6,R6,#&0000F000 ;Set up return instruction
89 SUB R12,R12,#8 ;Find variadic arguments
90 STMFD R13!,{R2-R6} ;Build SWI-calling frame
93 MOV R11,R1 ;Look after the flags word
94 MOV PC,R13 ;And call the stack code
96 ; --- Process a return from the SWI ---
98 10swi MOVVC R14,#0 ;If no error, return 0
99 20swi STR PC,[R13,#0] ;Save my program counter
101 ; --- Output the output registers ---
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
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
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
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
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
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
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
144 ; --- Work out address of literal block ---
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
152 85swi ADDCS R3,R3,#4 ;Move pointer on for each reg
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
161 ;----- That's all, folks ----------------------------------------------------