;
; swihack
;
; Calling SWIs under all versions of RISC OS
;
;  1996-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's core libraries (corelib)
;
; Corelib is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Corelib is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Corelib.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

		[	:LNOT::DEF:swihack__dfn

;----- Main code ------------------------------------------------------------

; --- |_swihack| ---
;
; On entry:	Registers for SWI call
;		R10 == SWI number to call
;
; On exit:	As from the SWI
;
; Use:		On first call, works out the right way to call SWIs.  On
;		subsequent calls, the vector is snapped to the right place.

|_swihack|	DCD	|__swihack|

		; --- Initial sorting out and dispatching routine ---

|__swihack|	STMFD	R13!,{R0,R1,R14}	;Store some registers away
		MOV	R0,#0			;Read feature flags
		SWI	XOS_PlatformFeatures	;Read the features then
		ADRVC	R0,|_swihack_call|	;If SWI there, call directly
		ADRVS	R0,|_swihack_build|	;Otherwise build the call
		STR	R0,|_swihack|		;Store the value away
		LDMFD	R13!,{R0,R1,R14}	;Restore the registers
		TEQP	R14,#0			;Reset flags from R14
		LDR	PC,|_swihack|		;And snap the pointer

		; --- Dispatch to OS_CallASWI ---

|_swihack_call|	MOV	R12,R14			;Save the return address
		SWI	OS_CallASWI		;Just call the SWI: easy
|_ret_R12|	MOV	PC,R12			;And return to caller

		; --- Dispatch by building code dynamically ---

|_swihack_build|
		STMFD	R13!,{R14}		;Save the return address
		BIC	R10,R10,#&FF000000	;Clear the opcode byte
		ORR	R10,R10,#&EF000000	;And make it SWIAL
		LDR	R14,|_ret_R12|		;And load the return instr
		STMFD	R13!,{R10,R14}		;Save code on the stack
		MOV	R12,PC			;Set up return address
		MOV	PC,R13			;And call the code
		ADD	R13,R13,#8		;Reclaim stack space
		LDMFD	R13!,{PC}		;And return with SWI's flags

		LTORG

		]

;----- That's all, folks ----------------------------------------------------

		END
