67 lines
1.2 KiB
ArmAsm
67 lines
1.2 KiB
ArmAsm
|
/*
|
||
|
gint_vbr
|
||
|
|
||
|
Some of the work, especially related to setting and un-setting the vbr
|
||
|
address needs to be done in assembler.
|
||
|
*/
|
||
|
|
||
|
.global _gint_getVBR
|
||
|
.global _gint_setVBR
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
gint_getVBR()
|
||
|
Returns the current vbr address.
|
||
|
*/
|
||
|
_gint_getVBR:
|
||
|
rts
|
||
|
stc vbr, r0
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
gint_setVBR()
|
||
|
|
||
|
This is quite the hard part when modifying the vbr. We need to set
|
||
|
immediately the interrupt priorities of our own handler, or restore
|
||
|
the ones used by the system ; otherwise we may receive interrupts
|
||
|
requests that the new handler doesn't handle, which will cause the
|
||
|
whole program to freeze.
|
||
|
|
||
|
Therefore, we must set vbr *and* change interrupt priorities while
|
||
|
having disabled all the interrupts in the status register. That's why
|
||
|
this function takes as parameter the priority management function.
|
||
|
*/
|
||
|
_gint_setVBR:
|
||
|
sts.l pr, @-r15
|
||
|
|
||
|
/* Blocking all interrupts. */
|
||
|
mov.l sr_block, r0
|
||
|
stc sr, r3
|
||
|
or r0, r3
|
||
|
ldc r3, sr
|
||
|
|
||
|
/* Setting the vbr address. */
|
||
|
ldc r4, vbr
|
||
|
|
||
|
/* Calling the priority manager. */
|
||
|
jsr @r5
|
||
|
nop
|
||
|
|
||
|
/* Activating interrupts again. */
|
||
|
mov.l sr_block, r0
|
||
|
not r0, r0
|
||
|
stc sr, r3
|
||
|
and r0, r3
|
||
|
ldc r3, sr
|
||
|
|
||
|
lds.l @r15+, pr
|
||
|
rts
|
||
|
nop
|
||
|
|
||
|
.align 4
|
||
|
|
||
|
sr_block:
|
||
|
.long (1 << 28)
|