English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 16 May 2008, 16:02   #1
alexh
Thalion Webshrine
 
alexh's Avatar
 
Join Date: Jan 2004
Location: Oxford
Posts: 14,354
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
alexh is online now  
Old 16 May 2008, 18:08   #2
frost242
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 ?
frost242 is offline  
Old 16 May 2008, 18:30   #3
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,517
Quote:
IRQ wants to push the current program counter + 1 onto the stack
Why does it store PC+1? Shouldn't sane CPUs store current PC?
Toni Wilen is offline  
Old 16 May 2008, 19:13   #4
alexh
Thalion Webshrine
 
alexh's Avatar
 
Join Date: Jan 2004
Location: Oxford
Posts: 14,354
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
  • I fetch and execute the instruction at address 12
  • push the PC+1 (13) onto the stack
  • fetch and execute the instructions at address 20 & 21
  • the RTS pops the PC off the stack
  • I fetch and execute the instruction at address 13
If I stored 12 then I'd fetch and execute the same instruction twice (and get stuck in a loop).

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.
alexh is online now  
Old 16 May 2008, 21:20   #5
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,517
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
Toni Wilen is offline  
Old 16 May 2008, 22:43   #6
alexh
Thalion Webshrine
 
alexh's Avatar
 
Join Date: Jan 2004
Location: Oxford
Posts: 14,354
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.
alexh is online now  
Old 16 May 2008, 23:59   #7
Kalms
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.
Kalms is offline  
Old 17 May 2008, 10:35   #8
alexh
Thalion Webshrine
 
alexh's Avatar
 
Join Date: Jan 2004
Location: Oxford
Posts: 14,354
Quote:
Originally Posted by Kalms View Post
This is how all other CPUs I've encountered function.
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:
So, the first instruction in the interrupt handler must disable interrupts or acknowledge the interrupt (so that IRQ goes low).
Yes. That is how all ISR's work isnt it? It is certainly how mine work.

Quote:
Originally Posted by Kalms View Post
- store current PC+SR to stack
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.
alexh is online now  
Old 17 May 2008, 13:19   #9
Wepl
Moderator
 
Wepl's Avatar
 
Join Date: Nov 2001
Location: Germany
Posts: 866
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
Wepl is offline  
Old 17 May 2008, 13:40   #10
Kalms
Registered User
 
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
Quote:
Originally Posted by alexh
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.
In the model I described above, after an instruction has completed execution, the instruction at the current PC is the next one to be executed. That is, the instruction at the current PC hasn't been executed. That is why it is safe to push the current PC. And that is also why there is no special condition necessary when handling control flow.
Kalms is offline  
Old 20 May 2008, 09:32   #11
Kalms
Registered User
 
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
Quote:
Originally Posted by alexh View Post
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.
And this is specifically the bit which I don't get. At the point where you check the interrupt status, I would expect the PC to always point to the instruction that is next in line for execution.

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?
Kalms is offline  
Old 20 May 2008, 09:42   #12
alexh
Thalion Webshrine
 
alexh's Avatar
 
Join Date: Jan 2004
Location: Oxford
Posts: 14,354
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.
alexh is online now  
 


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

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 13:16.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.26902 seconds with 13 queries