gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > IRQ vector fun :)

#44855 - DekuTree64 - Mon Jun 06, 2005 2:10 am

Since you can use bit13 of P15.c1 to set the exception vector base to either 0xFFFF0000 (where it normally is, in the BIOS) or 0x00000000, and you can map ITCM to address 0x00000000 if you want, I couldn't help but wonder if that meant I could bypass the default BIOS handler altogether.

I finally decided to give it a try just now and lo and behold, it works!
Then you can put a direct branch to your handler at address 0x18 (the IRQ vector) and save the ordeal the BIOS goes through of getting the DTCM address and loading the handler address first.

And if that's not enough fun for you, you can even go so far as to use an msr instruction to switch into FIQ mode to avoid having to store any registers before doing anything. Of course, that means you have to write all your interrupt functions in assembly since normal functions expect r0-r3 and r12 to be free, and FIQ mode bankswaps r8-r14, but anything worthy of shaving off a few cycles this way should be in assembly anyway.
Then when you're all done, just msr back to IRQ, and bx lr to your caller.

This concludes today's issue of How to Waste Your Time.

EDIT: Oops, make that subs pc, lr, #4 instead of bx lr to return to the caller, which swaps back spsr_irq to cpsr, and returns to the right address.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#132084 - Ant6n - Sat Jun 23, 2007 5:56 am

while searching this forum for fiq, i came across this. This is pretty cool stuff. Other thoughts on top of this.
I think it might be possible to keep all code in FIQ mode and have the interrupts in IRQ mode. then one could save switching back and forth between three modes (user, irq, fiq), but two instead (fiq as normal, irq as irq).
Another idea:
Have all your regular code in itcm, consider data abort. The exception vector is
Code:

  BASE+00h   Reset                      Supervisor (_svc)  I=1, F=1
  BASE+04h   Undefined Instruction      Undefined  (_und)  I=1, F=unchanged
  BASE+08h   Software Interrupt (SWI)   Supervisor (_svc)  I=1, F=unchanged
  BASE+0Ch   Prefetch Abort             Abort      (_abt)  I=1, F=unchanged
  BASE+10h   Data Abort                 Abort      (_abt)  I=1, F=unchanged
  BASE+14h   (Reserved)                 -          -       -
  BASE+18h   Normal Interrupt (IRQ)     IRQ        (_irq)  I=1, F=unchanged
  BASE+1Ch   Fast Interrupt (FIQ)       FIQ        (_fiq)  I=1, F=1

now make sure the interrupt following the one considered never occurs. in this case its reserved anyway. now you have 2 instructions free in your exception vector. you can do something like this
Code:

1)  reg <- 1FFF & (r14>>2)
2)  pc  <- byte@[base + reg]

here 1FFF and 'base' is in a banked register. base specifies the address to a list of 8192 entries. That way one can jump to a location in tcm based on what instruction in the itcm caused the abort exception. Here I assume that the list has 8bit values, so you can jump only 256 bytes away from 0.
One could also do 16bit or 32bit pointers. One could also, instead of specifying a jump location for every excepted instruction, specify one for every 2,4... instructions by shifting more to the left in 1).
anton