home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
documentation
/
documents
/
a252cmhg
< prev
next >
Wrap
Internet Message Format
|
1999-04-27
|
4KB
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.