#11767 - poslundc - Sat Oct 18, 2003 5:46 pm
If I save r13 at the beginning of my routine to somewhere relative to my code in IWRAM (this is for an ARM routine in IWRAM), can I safely use the register and then replace it at the end of my routine?
Or do interrupts require the register to be pointing to the proper stack location?
Thanks,
Dan.
#11771 - DekuTree64 - Sat Oct 18, 2003 6:17 pm
Depends on what you're doing in your interrupts. When an IRQ occurs, the CPU swaps r13 and r14 for r13_irq and r14_irq, copies r15 into r14_irq so you can return from the interrupt like a normal function, switches to ARM mode and executes from the address stored at 0x3007ffc (which is hardwired into the BIOS, so you can't change it). Normally it is safe to use r13 for whatever you want. The only problem is that the IRQ stack is only 64 bytes (you can make it bigger/smaller if you want though), so if you're doing much in your interrupts, you'll need to switch back to the user stack, which is the normal r13, and if it was being used for something else when it got interrupted, bad things will happen. But as long as you don't specifically switch to the user stack in your interrupts (by changing processor modes with msr/mrs), you can use r13 freely.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#11772 - poslundc - Sat Oct 18, 2003 6:22 pm
Sweet... that's not a problem, since currently I only have an HBlank interrupt and it only uses the IRQ stack to preserve the previous function's registers.
That means one more register I can play with!
Dan.
#11784 - NEiM0D - Sat Oct 18, 2003 9:49 pm
When an interrupt occurs in the GBA, the BIOS saves registers {r0-r3,r12} to r13.
It gets the address from 0x04000000-4 (=0x03007ffc mirrored), and jumps to there (= user IRQ handler).
If you got alot of interrupts going off very quickly, I would not suggest changing r13 at all.
If you really need r13, I suggest you change it back as soon as possible, before the next interrupt fires off, ifnot, the GBA will crash.
#11789 - DekuTree64 - Sat Oct 18, 2003 10:26 pm
Ah, I thought it would save them on r13_irq. But now that's got me thinking, what's r13_irq even there for if it doesn't allow you to free up r13?
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#11790 - torne - Sat Oct 18, 2003 10:37 pm
You can't use r13 and r13_irq at the same time; whichever maps to the current CPU mode is the one that's 'r13'. The point is so that you can switch to the IRQ stack without having to save the user stack pointer (because, uhm, where would you save it to? You don't know where the IRQ stack is..)
#11791 - DekuTree64 - Sat Oct 18, 2003 11:16 pm
Yeah, what I mean is why would you need a seprate IRQ stack if the user stack pointer always has to point to a stack when the IRQ occurs? Then you might as well use the user stack in your IRQ.
But I checked GBATEK and CowBite and they both say that it DOES switch to IRQ mode before pushing r0-r3, r12 so they do indeed go onto the interrupt stack, and therefore the user mode r13 is free to corrupt as I originally said.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#11794 - torne - Sun Oct 19, 2003 1:15 am
You have a seperate IRQ stack (in general, this is, not just the GBA) for a lot of reasons; the most likely being that the user stack pointer might be invalid, or pointing to userspace memory. I can't think of any reason that actually applies on the GBA. It's not at all unreasonable to switch to the userspace stack on entry to your ISR. The mode switch is done by the CPU core on taking an exception, before the BIOS handler is called and thus before any data is pushed.
You're right that user mode r13 never needs to point anywhere sensible; I misinterpreted what was being asked. Whatever you do to the normal r13 matters only to your code; all BIOS code, interrupt handlers..etc run in IRQ or supervisor mode and have their own stacks.
So yes, as long as you restore it, you can trash r13 during a function, though it'll have to be PC-relative since you won't have a stack pointer to load it back through. =)