; ; misc.s ; ; Miscellaneous things for DLL Manager ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Dynamic Linking System (SDLS) ; ; SDLS 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. ; ; SDLS 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 SDLS. 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 ------------------------------------------------ GET sh.wSpace GET sh.messages ;----- Some magic numbers --------------------------------------------------- misc_entkrnl EQU 4*48 ;48 kernel entries misc_entclib EQU 4*183 ;183 CLib entries misc_wspkrnl EQU &31C ;&31C bytes of kernel vars misc_wspclib EQU &B48 ;&B48 bytes of clib vars misc_clibVer EQU 5 ;Current CLib version ;----- External routines ---------------------------------------------------- AREA |DLLM$$Code|,CODE,READONLY ; --- misc_getCLib --- ; ; On entry: -- ; On exit: -- EXPORT misc_getCLib misc_getCLib ROUT BIC R14,R14,#V_flag ;Clear error indicator STMFD R13!,{R1-R6,R14} ;Store registers nicely ; --- Allocate workspace for SharedCLibrary to corrupt --- ; ; The SharedCLibrary wants some workspace that it can ; initialise. We're not actually using it, so we don't need ; any workspace, although it still wants some. So we ; allocate some for a bit, and get rid of it again. MOV R0,#6 ;Allocate space for CLib LDR R4,=misc_wspkrnl ;Amount of space for kernel LDR R5,=misc_wspclib ;Amount of space for C lib ADD R3,R3,#1024 ;Add an extra 1K for luck ADD R3,R4,R5 ;Amount of space reqd SWI XOS_Module ;Try to allocate memory LDMVSFD R13!,{R1-R6,PC} ;Return if it failed ; --- Set up stub table temporarily on the stack --- SUB R13,R13,#44 ;Reserve space for stub table MOV R0,R13 ;Point to base of table STR R2,[R0,#12] ;Store workspace pointer ADD R2,R2,R4 ;Limit of kernel space STR R2,[R0,#16] ;Store workspace pointer STR R2,[R0,#32] ;Store as Clib pointer ADD R2,R2,R5 ;Limit of C lib space STR R2,[R0,#36] ;Store as C lib limit ; --- Set up pointers to branch table in the stub block --- ADR R2,misc__stubs ;Point to entry point table LDR R4,=misc_entkrnl ;Get size of kernel entries LDR R5,=misc_entclib ;Get size of C lib entries STR R2,[R0,#4] ;Store kernel entry start ADD R2,R2,R4 ;Limit of kernel entries STR R2,[R0,#8] ;Store kernel entry limit STR R2,[R0,#24] ;Store C lib entry start ADD R2,R2,R5 ;Limit of C lib entries STR R2,[R0,#28] ;Store C lib entry limit ; --- Finish off the stub table --- MOV R2,#1 ;Kernel chunk ID STR R2,[R0,#0] ;Store in correct place MOV R2,#2 ;C lib chunk ID STR R2,[R0,#20] ;Store in correct place MOV R2,#-1 ;Chunk table end marker STR R2,[R0,#40] ;Store at end of table ; --- Get the branch table from the C Library --- LDR R1,[R0,#36] ;Get limit of that space ADD R2,R1,#1024 ;Point to end of block MOV R3,#-1 ;No zero-inited space MOV R4,#0 ;No static data to move MOV R5,#-1 ;No static data to move MOV R6,#&1000 ;4096 byte stack please :-) SWI XSharedCLibrary_LibInitModule ;Do the stuff ADRVSL R5,msg_errNoCLib ;If it failed, point to err MOVVC R5,#0 ;Otherwise, clear error mark ; --- Tidy up the stack and the temporary space --- MOV R0,#7 ;Free that memory I nabbed LDR R2,[R13,#12] ;Get pointer to the space ADD R13,R13,#44 ;Move stack pointer back SWI XOS_Module ;Free it now LDMVSFD R13!,{R1-R6,PC} ;If that failed, return error MOVS R0,R5 ;Copy error pointer LDMNEFD R13!,{R1-R6,R14} ;If there was an error, unstk ORRNES PC,R14,#V_flag ;And quit with V set ; --- Make sure the library was new enough --- CMP R6,#misc_clibVer ;Ensure returned version ADRLTL R0,msg_errOldCLib ;If too low, point to error LDMFD R13!,{R1-R6,R14} ;Get registers anyway ORRLTS PC,R14,#V_flag ;If too old, quit with V set BICS PC,R14,#V_flag ;Otherwise, clear V flag LTORG ; --- misc_copyStubs --- ; ; On entry: R0 == pointer to stubs table ; On exit: -- EXPORT misc_copyStubs misc_copyStubs ROUT STMFD R13!,{R0-R3,R14} ;Preserve registers ADR R1,misc__stubs ;Get pointer to stub table LDR R14,[R1,#0] ;Load the first entry CMP R14,#0 ;Has it been filled in? BLEQ misc_getCLib ;No -- find C library stuff BVS %80misc_copyStubs ;If it failed, return error LDR R0,[R13],#4 ;Load branch table pointer LDR R2,=misc_entkrnl+misc_entclib ;Get size of table SUB R3,R1,R0 ;Find ptr_diff 'tween tables MOV R3,R3,LSR #2 ;Shift off bottom two 0 bits SUBS R2,R2,#4 ;Decrement counter for table 00misc_copyStubs LDR R14,[R1,R2] ;Get the word from the table ADD R14,R14,R3 ;Relocate to destination BIC R14,R14,#&FF000000 ;Clear some bits, for safety ORR R14,R14,#&EA000000 ;Add on the opcode nicely STR R14,[R0,R2] ;Store in destination table SUBS R2,R2,#4 ;Decrement counter for table BGE %00misc_copyStubs ;Continue if anything left LDMFD R13!,{R1-R3,R14} ;Return if complete BICS PC,R14,#V_flag ;Return with no errors 80misc_copyStubs ADD R13,R13,#4 ;Don't restore R0 LDMFD R13!,{R1-R3,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return with V set LTORG ; --- misc_strcmp --- ; ; On entry: R0 == pointer to string A ; R1 == pointer to string B ; R2 == 0 => case insensitive, 1 => case sensitive ; ; On exit: Flags as appropriate ; ; Recently bodged to allow space-separated strings, which CLIGuard approves ; of more. EXPORT misc_strcmp misc_strcmp ROUT STMFD R13!,{R0,R1,R3,R4,R14} 00misc_strcmp LDRB R3,[R0],#1 ;Get a character from A LDRB R4,[R1],#1 ;And one from B CMP R2,#0 ;Do we want to do case xlate? BNE %10misc_strcmp ;No -- miss it out then SUB R14,R3,#'a' ;Subtract the bottom limit CMP R14,#26 ;Is it a lower case letter? BICLO R3,R3,#&20 ;Yes -- convert to upper SUB R14,R4,#'a' ;Subtract the bottom limit CMP R14,#26 ;Is it a lower case letter? BICLO R4,R4,#&20 ;Yes -- convert to upper 10misc_strcmp CMP R3,#&21 ;Is that the end of A? MOVCC R3,#0 ;Yes -- pretend it's null CMP R4,#&21 ;Is that the end of B? MOVCC R4,#0 ;Yes -- pretend it's null CMP R3,R4 ;How do they match up? LDMNEFD R13!,{R0,R1,R3,R4,PC} ;If NE, return condition CMP R3,#0 ;Is this the end? BNE %00misc_strcmp ;No -- loop again LDMFD R13!,{R0,R1,R3,R4,PC} ;Return to caller LTORG ; --- misc_memcpy --- ; ; On entry: R0 == pointer to destination ; R1 == pointer to source ; R2 == length to copy ; On exit: -- EXPORT misc_memcpy misc_memcpy ROUT STMFD R13!,{R1-R9,R14} ;Stack registers ; --- Do the fast copy of most of the data --- 00misc_memcpy SUBS R2,R2,#32 ;Check there's 32 bytes left LDMGEIA R1!,{R3-R9,R14} ;Load 8 words (32 bytes) STMGEIA R0!,{R3-R9,R14} ;And store in workspace BGE %00misc_memcpy ;Try for another one ; --- Now do a word-by-word copy --- ADD R2,R2,#32 ;Reinstate the byte count 01misc_memcpy SUBS R2,R2,#4 ;Check there's 4 bytes left LDRGE R14,[R1],#4 ;Load 1 word (4 bytes) STRGE R14,[R0],#4 ;And store in workspace BGE %01misc_memcpy ;Try for another one LDMFD R13!,{R1-R9,PC}^ ;Return to caller LTORG ; --- misc_zinit --- ; ; On entry: R0 == pointer to base of area ; R1 == pointer to limit ; On exit: -- EXPORT misc_zinit misc_zinit ROUT STMFD R13!,{R1-R8,R14} ;Stack registers ; --- Set up *lots* of zeroes --- MOV R2,#0 MOV R3,#0 MOV R4,#0 MOV R5,#0 MOV R6,#0 MOV R7,#0 MOV R8,#0 MOV R14,#0 ; --- Do the fast copy of most of the data --- SUB R1,R1,R0 ;Convert limit to length 00misc_zinit SUBS R1,R1,#32 ;Check there's 32 bytes left STMGEIA R0!,{R2-R8,R14} ;And store in workspace BGE %00misc_zinit ;Try for another one ; --- Now do a word-by-word copy --- ADD R1,R1,#32 ;Reinstate the byte count 01misc_zinit SUBS R1,R1,#4 ;Check there's 4 bytes left STRGE R14,[R0],#4 ;And store in workspace BGE %01misc_zinit ;Try for another one LDMFD R13!,{R1-R8,PC}^ ;Return to caller LTORG ; --- misc_strcpy --- ; ; On entry: R0 == destination string ; R1 == source string ; On exit: R0 == pointer to terminator of destination EXPORT misc_strcpy misc_strcpy ROUT STMFD R13!,{R1,R14} ;Keep return address safe 00misc_strcpy LDRB R14,[R1],#1 ;Get a byte from source CMP R14,#' ' ;Is it a control character MOVLT R14,#0 ;Yes -- translate to a 0 STRB R14,[R0],#1 ;Store in destination BGE %00misc_strcpy ;No -- copy another byte SUB R0,R0,#1 ;Point back at terminator LDMFD R13!,{R1,PC}^ ;Return to caller ; --- misc__subst --- ; ; On entry: R0 == Pointer to error message skeleton ; R1 == Filler 1 ; R2 == Filler 2 ; R3 == Filler 3 ; R4 == Filler 4 ; R5 == Pointer to buffer ; On exit: -- misc__subst ROUT STMFD R13!,{R1-R5,R14} ;Save some registers 00misc__subst LDRB R14,[R0],#1 ;Get an input character CMP R14,#'%' ;Is it a '%' sign? BEQ %01misc__subst ;Yes -- deal with it 02misc__subst STRB R14,[R5],#1 ;Not special, so store it CMP R14,#0 ;Is it the end of input? BNE %00misc__subst ;No -- get another one LDMFD R13!,{R1-R5,PC}^ ;And return to caller 01misc__subst LDRB R14,[R0],#1 ;Get the next character SUB R1,R14,#'0' ;Get the index CMP R1,#4 ;Is it in range? BCS %02misc__subst ;No -- just ignore the '%' LDR R1,[R13,R1,LSL #2] ;Load appropriate register 03misc__subst LDRB R14,[R1],#1 ;Get an input byte CMP R14,#&20 ;Is it the end of the string? STRCSB R14,[R5],#1 ;No -- store it in output BCS %03misc__subst ;... and get another one B %00misc__subst ;Yes -- read main string LTORG ; --- misc_error --- ; ; On entry: R0 == Pointer to error message skeleton ; R1 == Filler 1 ; R2 == Filler 2 ; R3 == Filler 3 ; R4 == Filler 4 ; On exit: R0 == Pointer to constructed error in misc__errorBuf EXPORT misc_error misc_error ROUT STMFD R13!,{R5,R14} ADR R5,misc__errorBuf ;Point to error buffer LDR R14,[R0],#4 ;Read the error's number STR R14,[R5],#4 ;And store in the new buffer BL misc__subst ;Do the substitution SUB R0,R5,#4 ;Point at the buffer LDMFD R13!,{R5,PC}^ ;And return to caller LTORG ; --- misc_subst --- ; ; On entry: R0 == Pointer to error message skeleton ; R1 == Filler 1 ; R2 == Filler 2 ; R3 == Filler 3 ; R4 == Filler 4 ; On exit: R0 == Pointer to constructed string in misc__errorBuf EXPORT misc_subst misc_subst ROUT STMFD R13!,{R5,R14} ADR R5,misc__errorBuf ;Point to error buffer BL misc__subst ;Do the substitution MOV R0,R5 ;Point at the buffer LDMFD R13!,{R5,PC}^ ;And return to caller LTORG ;----- That's all folks ----------------------------------------------------- END