SCU interrupts

I'm revisiting an old problem I had with interrupts, maybe somebody can explain what's going on.

To my knowledge when an interrupt is generated, it has to be acknowledged - the SCU doesn't auto-acknowledge interrupts.

Based on the first SCU manual, you have these:

$25FE00A0 - Interrupt mask register. Write '0' in a bit position to enable an interrupt source, write '1' to disable it.

OK, so I can set it to something like $0000BFFE to enable the V-Blank IN interrupt only.

$25FE00A4 - Interrupt status register. Read to return interrupt status, write '0' to acknowledge (they say 'reset') interrupt source, writing '1' does nothing.

To my understanding within an interrupt handler I'd write something like $FFFFFFFE to acknowledge the V-Blank IN interrupt source only.

Of course there's a catch:

Writing to the interrupt status register does nothing. In fact the system gets all crazy because the interrupt isn't really acknowledged. Furthermore the updated SCU manual says not to write to it.

What I had done in my timer 0/1 example program was to re-write the original value last set to the interrupt mask register (to keep the interrupts I wanted enabled) which seemed to acknowledge interrupts too. So I'd re-write $0000BFFE to keep the V-Blank IN interrupt enabled and automagically acknowledge it at the same time.

I'd like to know what's really going on in respect to how interrupts are handled by the system, and what I need to do on my end to properly acknowledge an interrupt. If anyone has looked at commercial games in an emulator or debugger, what do they do?

The other thing I'm interested in is how to call a "C" function from assembly code. I'm assuming to tie a "C" function to an interrupt, I'll need to have a stub function in assembly to save all the registers that GCC won't normally save, then call the function (just void foobar(void); in this case, no parameters) and return.

For performance reasons I want to push the registers GCC will trash, how do I know what they are? Or do I really have to push every single one?
 

antime

Extra Hard Mid Boss
The SuperH calling convention is described in Renesas' toolchain manuals ("SuperH RISC C/C++ Compiler, Assembler, Optimizing Linkage Editor"). R0-R7 are caller-saved, R8-R15, MACH, MACL and PR are callee-saved. The manual also describes the parameter passing and layout rules.
 
Originally posted by antime@Mon, 2005-07-11 @ 12:29 PM

The SuperH calling convention is described in Renesas' toolchain manuals ("SuperH RISC C/C++ Compiler, Assembler, Optimizing Linkage Editor"). R0-R7 are caller-saved, R8-R15, MACH, MACL and PR are callee-saved. The manual also describes the parameter passing and layout rules.

[post=136593]Quoted post[/post]​


Great stuff, now I won't have to save all the registers in my interrupt handlers that are written in assembly. Should help with the interrupt response time too.

I also found (by reading the GNUSH documentation, oddly enough) that you can have GCC handle "C" functions that are ISRs for you like this:

// Specify extra attributes in the prototype declaration:

void foobar(void) __attribute__((interrupt_handler));

:

void foobar(void)

{

// Your code goes here

}

Then you just point the vector table entry to your function, and that's it.
 

antime

Extra Hard Mid Boss
Hmm, looking at the GCC docs, there seems to be two conventions for SH: -mrenesas/-mhitachi and -mno-renesas. However I don't recall ever seeing any other convention for basic register saving, so that probably covers things like stack layout.
 
Top