16 May 2008, 16:02 | #1 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 14,460
|
Advice on interrupts and jumps
This is not really an Amiga related question, more of a microprocessor design question.
I design custom mini-microprocessors for embedded applications and I often lean heavily on my Amiga knowledge and 68k knowledge. I was recently asked to improve one of my designs to include the ability to get nested interrupts, a feature that I had deliberately omitted from the original design because it had some gotchas. Ok, so what is my question?? What happens if you get an IRQ whilst the current instruction is an RTS? The RTS wants to load the program counter with the last value on the stack and the IRQ wants to push the current program counter + 1 onto the stack and jump to the ISR address. It's sort of a chicken and egg scenario. I kinda need the IRQ to be held off until the next instruction is not RTS (however long that might be). My uP is not that similar to 68k but any suggestions appreciated, it might give me that spark of inspiration |
16 May 2008, 18:08 | #2 |
Registered User
Join Date: Oct 2007
Location: France, 87
Age: 44
Posts: 96
|
I think the best way to handle this chicken and egg scenario is to behave like the 060 (at least, I think that the other members of the 68k family behaves the same way) and wait until the current instruction is completly executed and the CPU ready to go for another instruction.
Maybe I didn't understand well the question ? |
16 May 2008, 18:30 | #3 | |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,567
|
Quote:
|
|
16 May 2008, 19:13 | #4 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 14,460
|
Probably bad design
The reason I chose to store PC+1 is that if we look at this snippet of totally made up crap Code:
10 add.i #20, d0 11 and.i #5, d2 12 jsr #20 <- PC = 12 13 sub.i #255, d3 14 jne #2000 .. .. .. 20 add d0, d1 21 sub d2, d4 22 rts
It's highly probably that CPU's (in general) don't do this... they probably store the current PC to the stack but fetch and execute instruction at (SP)+1 following an RTS? This was my first attempt, and seemed to me the right thing at the time. As an Engineer I like simple, ask my girlfriend It's happily working inside the worlds fastest external eSATA RAID controller. I was just looking to improve interrupt handling for the next chip. Last edited by alexh; 16 May 2008 at 19:40. |
16 May 2008, 21:20 | #5 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,567
|
I meant why you do PC+1 when jumping to interrupt routine? Why not check interrupt status before fetching next opcode? (and store current PC)
I am still confused |
16 May 2008, 22:43 | #6 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 14,460
|
That is exactly what I do. Before fetching the next opcode, I "check" the interrupt status. If a bit is set, I use an address from vector table to fetch the next opcode.
But at that point I've just finished executing the instruction at the current PC. So when the RTE opcode is executed at the end of the ISR, the next opcode I want to fetch is at the old stored PC +1. The problem I have is if I get an IRQ while I am executing an RTE/RTS, current PC+1 is not a valid return address. I was fortunate enough that the first silicon containing my uP had errors for all interrupt sources so no ISR ever had an RTE (they all have a jmp #0) and no subroutines had IRQ's enabled so the bug never showed itself. Last edited by alexh; 16 May 2008 at 23:33. |
16 May 2008, 23:59 | #7 |
Registered User
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
|
Aaah. I think I just saw what you're getting at.
How about if you consider the step of updating the PC to point to the next instruction, to be part of the processing of the current instruction? That would give you an interpretation of the instructions like: * a JSR instruction will store the return address (which is current PC + 1) to the stack, and then it will write a new value into the PC. * an RTS instruction will load a value from the stack, and write that value into the PC. * ordinary (non-control-flow) instructions will, apart from performing their intended computations, compute PC+1 and write that value to PC. This is how all other CPUs I've encountered function. If your CPU only checks for IRQs between processing of individual instructions, then the above protocol is safe. The following 2-phase instruction handling flow works with recursive interrupts: * check if IRQ is set, and the requested interrupt is allowed to trigger. If so, do special processing: - possibly do something to avoid infinite recursion here - store current PC+SR to stack - load value from interrupt vector table into PC (otherwise, the PC register will be left untouched) * process instruction at PC The "possibly do something to avoid recursion here" step deserves a bit more explanation. If IRQ goes high, and no magic is done at that step, then the first instruction in the interrupt handler will be executed after which another interrupt is entered. So, the first instruction in the interrupt handler must disable interrupts or acknowledge the interrupt (so that IRQ goes low). You can also include that sort of logic inside the uP's interrupt handling logic itself (at the spot marked above). When you start supporting nested interrupts, you may find that interrupt priority levels is a good choice; if you're inside an interrupt of level 3 or higher, then interrupt requests of a lower priority will be ignored (so they trigger once the CPU drops to processing interrupts with a lower level, or finishes interrupt processing altogether). Perhaps just having a bitmask with interrupt sources is enough (think INTENA/INTREQ style masks); think how you would implement a shared AUDx interrupt handler on the Amiga for a good example. So, um, I'm not sure if this will help. But, well, one can at least hope. |
17 May 2008, 10:35 | #8 | |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 14,460
|
And this is the model I had in my mind having (lightly) programed 68k and other cpu's in ASM over the years and what I implemented for my mini uP.
Quote:
Why store current PC as the return address? A return address of current PC would not be valid for my architecture as when the interrupt is taken, the opcode at the current PC has already been executed. I store current PC+1 just like I would had this been a JSR and not an interrupt. This works well in most cases, but if you service an interrupt at the same time you are executing an RTS of a subroutine, or an RTE of an iterrupt service routine, the return address PC+1 is not valid. I could (in hardware) mask interrupts when the current opcode is RTS or RTE, that would work... but the side effect means that edge sensitive interrupts could be missed. Which could be fixed by converting all my edge triggered interrupts into level triggered ones.... Last edited by alexh; 17 May 2008 at 10:58. |
|
17 May 2008, 13:19 | #9 |
Moderator
Join Date: Nov 2001
Location: Germany
Posts: 874
|
as long as interrupts are only taken between instructions I see no point.
you may need some logic (bits) to make sure that interrupts are only taken after an instruction has finished... for nested interrupts you need some kind of interrupt level/mask which is modified during entering interrupt and permits lower level interrupts |
17 May 2008, 13:40 | #10 | |
Registered User
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
|
Quote:
|
|
20 May 2008, 09:32 | #11 | |
Registered User
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
|
Quote:
If the PC still points to the latest instruction which was executed, then it means that the instruction has just been executed, but the PC has not been updated. This will only happen if updating of the PC is not considered to be part of the execution of the instruction. What am I (we?) missing here? |
|
20 May 2008, 09:42 | #12 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 14,460
|
The PC cannot have been updated at the point where I check the interrupt status as this is a single cycle processor... but the new PC had been calculated and is available (combinatorially).
The PC for the next instruction (in the case of RTS/RTE the one being popped off the stack) is "calculated" at exactly the same time as the PC for an IRQ. However which one actually becomes the next PC is priority encoded with the IRQ having the higher priority (obviously). The result is that the RTS return PC is lost and I store an invalid return address of PC+1 to the stack. I suppose it wouldnt be too hard to make it so that if the current opcode is one of those that is trying to change the PC that instead of storing the IRQ return address as PC+1 (as in JSR)... I could store whatever the current opcode was trying to change the PC to. (Which is kinda what you were saying). In fact I think it just involves taking lines out rather than putting any in! I've thought a little more about it over the last couple of days (cos I've been off work ill) and I realised that my problem is much worse that I thought. Not only does this bug affect interrupts during RTS/RTE opcodes, but any instruction that wants to change the PC! That means all branches, jumps and returns will result in some sort of incorrect execution, either an invalid return address, or worse missed branches! And I noticed that I have a potential bug in my stack-pointer logic if there is a push and a pop in the same cycle. Damn, I didnt realise until now how lucky I had been that no programs ever wanted to return from interrupts on the MK1 Last edited by alexh; 20 May 2008 at 10:38. |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Legend of Faerghail: Titlemusic 'jumps' | lomaxx | support.Games | 1 | 03 December 2013 01:15 |
Mouse jumps around chaotically | LaurenceV | support.WinUAE | 11 | 18 November 2011 14:19 |
Mouse pointer jumps to centre of screen | ral-clan | support.WinUAE | 0 | 30 January 2011 02:41 |
A little advice please !!! | synchro | Amiga scene | 9 | 17 July 2004 18:24 |
New CD on the way....Advice please :) | synchro | Amiga scene | 17 | 17 June 2004 16:01 |
|
|