; ; csapph.s ; ; C support for Sapphire programs ; ; © 1995 Straylight ; ;----- Notice --------------------------------------------------------------- ; ; We haven't lost our minds. We aren't planning to move over to development ; in C. Nothing like that. This will allow us to use C code from other ; sources (a bit) in Sapphire programs, and maybe sort out algorithms before ; committing to register allocations. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- __sapph_veneer --- ; ; On entry: R0-R12 == argument registers ; R14 == routine to call ; Return address on stack ; ; On exit: R0-R12 == returned values ; Flags may be altered by called routine ; ; Use: Calls a C routine, passing it arguments, and getting results ; back. EXPORT |__sapph_veneer| |__sapph_veneer| ROUT STMFD R13!,{R0-R12,PC} ;Save registers MOV sl,R11 ;Look after env pointer MOV a1,R13 ;Point to the regset MOV a2,R10 ;Pass object pointer MOV a3,R12 ;Pass workspace pointer MOV a4,R11 ;And the scratchpad MOV fp,#0 ;Terminate stack frame list MOV ip,R14 ;Point to the routine MOV lr,pc ;Set up a return address MOV pc,ip ;And call the routine LDR ip,[R13,#52] ;Load the flags word AND a2,a1,#&F0 ;Get the mask bits out BIC ip,ip,a2,LSL #24 ;Mask some flags out TEQP ip,a1,LSL #28 ;Toggle and set the flags MOV R0,R0 ;No-op LDMFD R13!,{R0-R12,R14,PC} ;And return to caller LTORG ; --- call --- ; ; On entry: a1 == pointer to routine ; a2 == pointer to regset ; ; On exit: a1 == 0, or pointer to error, as seems to be usual ; ; Use: Calls a random routine in Sapphire, or anywhere else. The ; Scratchpad pointer is forced into R11. EXPORT call call ROUT STMFD sp!,{a1,a2,v1-v6,sl,fp,ip,lr} ;Save lots of registers STR sl,[a2,#44] ;Store Scratchpad away MOV lr,pc ;Set up current flags AND lr,lr,#&0C000003 ;Leave important flags TEQP lr,#0 ;Clear the others please LDMIA a2,{R0-R12} ;Load lots of registers MOV lr,pc ;Set up return address LDR pc,[sp],#4 ;Call the routine LDR lr,[sp],#4 ;Load the base address back STMIA lr,{R0-R12,PC} ;Store all the registers MOVVC R0,#0 ;If no error, return 0 LDMFD sp!,{v1-v6,sl,fp,ip,pc}^ ;And return to caller LTORG ; --- swi --- ; ; On entry: R0 == SWI number ; R1 == pointer to regset ; ; On exit: R0 == zero, or pointer to error ; ; Use: Calls a SWI in a versatile, fast, and inconvenient way. EXPORT swi swi ROUT STMFD R13!,{R4-R10,R14} ;Save some registers MOV R10,R1 ;Remember this pointer ORR R0,R0,#&EF000000 ;Make the SWI number LDR R14,=&E1A0F00C ;Get the return instruction STMFD R13!,{R0,R14} ;Save them on the stack LDMIA R10,{R0-R9} ;Load registers to pass MOV R12,PC ;Set up return address MOV PC,R13 ;Call the SWI instruction STMIA R10,{R0-R9} ;Store the output registers STR PC,[R10,#52] ;Store the output flags too MOVVC R0,#0 ;If no error, return zero ADD R13,R13,#8 ;Restore stack pointer LDMFD R13!,{R4-R10,PC}^ ;And return to caller LTORG GBLL OPT_CALL GBLL OPT_SAPPHIRE GET libs:s.xswi ;----- That's all, folks ---------------------------------------------------- END