From: enevill@acorn.co.uk (Edward Nevill) Subject: Re: Modules in C Date: 4 Oct 91 14:01:06 GMT In article <1991Oct01.212021.16581@demon.co.uk> pmoore@cix.compulink.co.uk (Paul Moore) writes: >The second problem is more of a pain. I have worked out that I should >declare my vector handler to CMHG as an IRQ handler, so that I get the >proper veneer round my code. BUT... the vector I want to claim is (you >guessed it!) OS_ReadLine, which requires the C flag to be set on exit >based on the results of the call. As far as I can see, the standard >veneer does not allow the setting of flags on return. > >As far as I can see, the only way round this is to write my own entry >veneer for the handler. However, I'm not 100% sure what the 'standard' >veneer does. I can probably work it out by disassembling the code >generated by CMHG, but can anybody *tell* me what it does - to save me >some work? If so, I'd be very grateful. Also, maybe later versions of >CMHG would benefit from an extra keyword 'irq-handlers-c' or some such? > irq_entry STMDB sp!, {r0-r9, sl, fp, lr} ; Save regs on IRQ | SVC stack MOV r0, sp ; Set up _kernel_swi_regs * argument + ADD r2, sp, #12 * 4 ; Set up pointer to carry arg (= LR!!!) MOV r6, pc BIC r6, r6, #3 TEQP r3, #3 ; To SVC mode, preserve IRQ / FIQ state MOV fp, #0 ; Halt C backtrace at this stack level MOV r7, lr ; Save SVC lr MOV sl, sp, LSR #20 MOV sl, sl, ASL #20 ; Get LWM of SVC stack LDMIA sl, {r4, r5} ; Save static data relocations across fn call MOV r1, r12 ; Set up private workspace argument LDR r12, [r12] ; Get pointer to static relocations for module LDMIB r12, {r12, lr} ; IB skips first word STMIA sl, {r12, lr} ; Set up static data relocations ADD sl, sl, #512+40 ; 40 = size of stack chunk structure BL c_function ; Do the function SUB sl, sl, #512+40 ; Point back to base of SVC stack STMIA sl, {r4, r5} ; Restore old static data relocations MOV lr, r7 ; Restore SVC lr TEQP r6, #0 ; Back to entry mode CMPS r0, #0 ; Intercept? LDMNEIA sp!, {r0-r9, sl, fp, pc}^ ; No (carry arg will not be written!!!) - LDMIA sp!, {r0-r9, sl, fp, lr, pc}^ ; Yes + LDMIA sp!, {r0-r9, sl, fp, ip, lr} ; Yes (ip = carry value to ret) + BIC lr, lr, #1:SHL:29 + CMP ip, #0 + ORRNE lr, lr, #1:SHL:29 + MOVS pc, lr The veneer genererated for an IRQ handler by cmhg is something like the above without the '+' lines. Remove the '-' line and add the '+' lines to produce a veneer which allows you to return the carry flag. The declaration the a handler using this looks something like int c_function(_kernel_swi_regs *r, void *pw, int *carry); NOTE: you must not write the carry arg unless you are intercepting the call (ie you are returning 0 from c_function). Doing so will lead to disaster (it will continue executing at the address you write to carry, so if you write 0 it will continue executing at location 0!!!). I may consider making this more robust in a later version. To claim the vector in your init code extern int irq_entry; _kernel_oserror *user_init(char *cmd_tail, int podule_base, void *pw) { _kernel_swi_regs r; ... r.r[0] = 0x0e; /* ReadLineV */ r.r[1] = (int)&irq_entry; r.r[2] = (int)pw; _kernel_swi(OS_Claim, &r, &r); ... return 0; } NOTE: If you claim a vector in your initialisation code like this you must either return 0 indicating no error or release the vector before returning an error (your finalisation is not called if there is an error in initialisation). Have fun, Edward.