;
; xmodule.s
;
; CLib stubs replacement
;
;  1993-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's C library stubs (xstubs).
;
; xstubs 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.
;
; xstubs 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 xstubs.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Standard stuff -------------------------------------------------------

		GET	libs:header
		GET	libs:swis

;----- External dependencies ------------------------------------------------

		IMPORT	|_kernel_moduleinit|
		IMPORT	|_kernel_entermodule|
		IMPORT  |_clib_initialise|

		IMPORT	|Image$$RO$$Base|
		IMPORT	|Image$$RW$$Base|
		IMPORT	|Image$$RW$$Limit|
		IMPORT	|Image$$ZI$$Base|
		IMPORT	|RTSK$$Data$$Base|
		IMPORT	|RTSK$$Data$$Limit|
		IMPORT	|__RelocCode|,WEAK

		IMPORT	xstub__ktable
		IMPORT	xstub__ektable
		IMPORT	xstub__ctable
		IMPORT	xstub__ectable
		IMPORT	xstub__kdata
		IMPORT	xstub__ekdata
		IMPORT	xstub__cdata
		IMPORT	xstub__ecdata
		IMPORT	|__root_stack_size|,WEAK

;----- Exports from this file -----------------------------------------------

		EXPORT	|_clib_entermodule|
		EXPORT	|_clib_initialisemodule|
		EXPORT  |Stub$$Code|
		EXPORT	|_Lib$Reloc$Off|
		EXPORT	|_Mod$Reloc$Off|
		EXPORT	|_Lib$Reloc$Off$DP|
		EXPORT  |__main|

;----- Initialise the library -----------------------------------------------

		AREA	|Stub$$Code|,CODE,READONLY

xstub__stack	EQU	4096			;Standard stack size thing
xstub__error	EQU	&800E90			;Error number base
xstub__version	EQU	5			;Version number of stubs

|_Lib$Reloc$Off|	EQU	&21c
|_Mod$Reloc$Off|	EQU	&218
|_Lib$Reloc$Off$DP|	EQU	&f87

|_clib_initialisemodule|
		STMFD	R13!,{R14}		;Look after R14
		BL	xstub__initMod		;Try and initialise myself
		LDMVSIA	R13!,{PC}		;If it failed, stop there now
		STMFD	R13!,{R9}		;Weird.  Must be done, though
		BL	|_clib_initialise|	;Start up the C library now
		LDMFD	R13!,{R0,PC}^		;Return to caller

|_clib_entermodule|
|__main|
		ADR	R0,xstub__kernel	;Point to kernel descriptor
		MOV	R8,R12			;Look after private word
		MOV	R12,#-1			;Dunno
		LDR	R6,=|__root_stack_size|	;Load root stack size
		CMP	R6,#0			;Has it been specified?
		MOVEQ	R6,#xstub__stack	;No -- substitute a default
		LDRNE	R6,[R6]			;Otherwise, read the size
		B	|_kernel_entermodule|	;Start the module up now

xstub__initMod	STMFD	R13!,{R14}		;Look after our link register
		MOV	R9,R0			;R9 corrupted by relocation
		BL	|__RelocCode|		;Relocate myself properly
		MOV	R4,#0
		MOV	R5,#0
		CMP	R9,#0
		MOVEQ	R3,#12			;Need 12 bytes for relocation
		LDRNE	R4,=|Image$$RW$$Base|	;Point to base of data
		LDRNE	R5,=|Image$$RW$$Limit|	;Point to end of data
		SUBNE	R3,R5,R4		;Calculate the difference...
		ADDNE	R3,R3,#12		;And add on that 12 bytes
		MOV	R0,#6			;Allocate some memory
		SWI	XOS_Module		;Do the allocation
		LDMVSFD	R13!,{PC}		;If it squeals, let it go
		STR	R2,[R12]		;Store this in private word
		STR	R3,[R2]			;Remember the data size
		MOV	R9,R12			;Keep hold of priv word ptr
		MOV	R12,R2			;Point R12 at workspace now
		ADD	R1,R12,#12		;Point past relocation stuff
		ADD	R2,R3,R1		;Point R2 at end of workspace
		LDR	R3,=|Image$$ZI$$Base|	;Point R3 at zero inited bit
		ADR	R0,xstub__stubs		;Point to stub descriptions
		LDR	R6,=|__root_stack_size|	;Load root stack size
		CMP	R6,#0			;Has it been specified?
		MOVEQ	R6,#xstub__stack	;No -- substitute a default
		LDRNE	R6,[R6]			;Otherwise, read the size
		MOV	R6,R6,ASR #10		;Convert to kilobytes
		MOV	R6,R6,LSL #16		;And shift to top halfword
		SWI	XSharedCLibrary_LibInitModule ;Initialise everything
		BVS	xstub__errMod		;Error in initialisation
		CMP	R6,#xstub__version	;Ensure version number
		BLT	xstub__errMod		;Mark this as an error
		ADD	R8,R1,#20		;Point to relocs in the stack
		LDMIA	R8,{R7,R8}		;Get relocated words
		STMIB	R12,{R7,R8}		;Store in workspace
		MOV	R4,R0			;Point to workspace limit
		ADR	R0,xstub__kernel	;Point to kernel info block
		B	|_kernel_moduleinit|	;Start the kernel up now

xstub__noCLib	DCD	xstub__error+&00	;Error number (official)
		DCB	"Couldn't find Shared C Library",0
		ALIGN

xstub__oldCLib	DCD	xstub__error+&01	;Error number (also official)
		DCB	"Shared C Library is out of date",0
		ALIGN

xstub__errMod	ADRVS	R1,xstub__noCLib	;If error, assume no library
		ADRVC	R1,xstub__oldCLib	;If not, assume version prob
		MOV	R0,#7			;Ready to free workspace
		MOV	R2,R12			;Point to workspace
		SWI	XOS_Module		;Free the workspace
		MOV	R0,R1			;Get the error pointer
		LDMFD	R13!,{R14}		;Get return address
		ORRS	PC,R14,#V_flag		;Set V flag on exit

;----- Stub description block -----------------------------------------------

xstub__stubs

		; --- Magic numbers ---

xstub__krnlID	EQU	1			;Kernel's chunk ID
xstub__clibID	EQU	2			;C library's chunk ID

		; --- Kernel section ---

		DCD	xstub__krnlID
		DCD	xstub__ktable
		DCD	xstub__ektable
		DCD	xstub__kdata
		DCD	xstub__ekdata

		; --- C library section ---

		DCD	xstub__clibID
		DCD	xstub__ctable
		DCD	xstub__ectable
		DCD	xstub__cdata
		DCD	xstub__ecdata

		DCD	-1			;Terminate the table

;----- Kernel description block ---------------------------------------------

xstub__kernel

		DCD	|Image$$RO$$Base|
		DCD	|RTSK$$Data$$Base|
		DCD	|RTSK$$Data$$Limit|

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

		END
