; 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. ; AREA |C$$code|, CODE, READONLY EXPORT |_swix| EXPORT |_swi| |_swi| ; Construct a stack frame that looks something like this: ; LDMIA r12!, {r0..rn} ; Or NOP if no input regs ; ADD Rb, R12, #Nout * 4 ; Or NOP if no parameter block ; SWI xxxxxx ; MOV R0, Rn ; Use ADD because Rn is correct bitfield ; B SWIReturn ; saved r4-r11,lr ; saved r1 ; saved input values (r2...rn) STMFD sp!, {r2-r3} ; Save r1 and put 1st two variadic args on stack STMDB sp!, {r1, r4-r9, lr} ADR r6, SWIReturn-4 B swix0 |_swix| ORR r0, r0, #&20000 STMDB sp!, {r2-r3} STMDB sp!, {r1, r4-r9, lr} ADR r6, SWIXReturn-4 swix0 ORR r3, r0, #&ef000000 ; Construct SWI instruction MOV r0, r1, LSL #22 ; Construct LDMIA R12!, {regs} instruction MOVS r0, r0, LSR #22 ; {regs} = {} (IE no input regs) we must not ORRNE r0, r0, #&e8000000 ; use an LDMIA R12!, {} instruction as this is an ORRNE r0, r0, #&00bc0000 ; invalid instruction, we use a suitable NOP instead. MOV r5, r1, LSR #16 AND r5, r5, #&f ORR r5, r5, #&e1000000 ORR r5, r5, #&a00000 ANDS r2, r1, #&800 BLNE BuildBlockInst SUB r6, r6, sp MOV r6, r6, LSR #2 BIC r6, r6, #&ff000000 ADD r6, r6, #&ea000000 STMDB sp!, {r0,r2,r3,r5,r6} ADD r12, sp, #(5+8)*4 ; Point R12 at input regs on stack. [ StrongARM ;oh my gawd ... ;in case we are running on StrongARM, have to synchronise with respect to modified code ;this is all highly inefficient, and the mechanism needs sorting properly later STMDB sp!,{r0-r2,lr} ;don't know whether any of these are trashable MOV r0,#1 ;means range specified in r1,r2 ADD r1,sp,#4*4 ;start address (allowing for stacked r0-r2,lr) ADD r2,r1,#4*4 ;end address (inclusive) for 5 words of code SWI XOS_SynchroniseCodeAreas ;do the necessary LDMIA sp!,{r0-r2,lr} ] MOV pc, sp ; Call routine on stack SWIReturn STR pc, [sp, #4*4]! ; no PC+12/PC+8 problem (old/new ARM) since only condition codes used LDR lr, [sp, #1*4] MOVS lr, lr, ASL #1 ; Shift out setting C if R0 to be written, N LDRCS lr, [r12], #4 ; if R1 to be written. STRCS r0, [lr] LDRMI lr, [r12], #4 STRMI r1, [lr] LDR lr, [sp, #1*4] B ReturnTail SWIXReturn STR pc, [sp, #4*4]! ; no PC+12/PC+8 problem (old/new ARM) since only condition codes used LDR lr, [sp, #1*4] BVS VSetReturn MOVS lr, lr, ASL #1 ; Shift out setting C if R0 to be written, N LDRCS lr, [r12], #4 ; if R1 to be written. STRCS r0, [lr] LDRMI lr, [r12], #4 STRMI r1, [lr] LDR lr, [sp, #1*4] TST lr, #&f0000 MOVEQ r0, #0 ReturnTail MOVS lr, lr, ASL #3 ; Shift 2 bits each time for the next 2 regs LDRCS r1, [r12], #4 STRCS r2, [r1] LDRMI r1, [r12], #4 STRMI r3, [r1] AND lr, lr, #&ff000000 MOVS lr, lr, ASL #2 LDRCS r1, [r12], #4 STRCS r4, [r1] BEQ VSetReturn ; Typically saves 16S - (3S + 1N) LDRMI r1, [r12], #4 STRMI r5, [r1] MOVS lr, lr, ASL #2 LDRCS r1, [r12], #4 STRCS r6, [r1] LDRMI r1, [r12], #4 STRMI r7, [r1] MOVS lr, lr, ASL #2 LDRCS r1, [r12], #4 STRCS r8, [r1] LDRMI r1, [r12], #4 STRMI r9, [r1] MOVS lr, lr, ASL #2 LDRCS r9, [sp] LDRCS r1, [r12], #4 STRCS r9, [r1] VSetReturn ADD sp, sp, #2*4 LDMIA sp!, {r4-r9,lr} ADD sp, sp, #2 * 4 MOVS pc, lr BuildBlockInst MOV r4, #6 AND r2, r1, #&f000 ORR r2, r2, #&e2000000 ORR r2, r2, #&008c0000 BuildBlockInst1 MOVS r1, r1, ASL #2 ADDCS r2, r2, #4 ADDMI r2, r2, #4 SUBS r4, r4, #1 BNE BuildBlockInst1 MOVS pc, lr END