Fix interrupt handling for or1k.

- During interrupt handling the PICSR, table pointers and current
  interrupt line have been saved in incorrect registers and/or stored on
  the stack.

- Save the pointer in r16/r18, PICSR in r20 and the current interrupt
  line in r22. Those are callee-saved registers, so that the register
  values will be preserved.

        * or1k/interruts-asm.S: Change registers to callee-saved.
This commit is contained in:
Jeff Johnston 2015-05-26 15:19:13 -04:00
parent 068f669e49
commit f4d7fbe5a1
2 changed files with 28 additions and 28 deletions

View File

@ -1,3 +1,7 @@
2015-05-26 Stefan Wallentowitz <stefan.wallentowitz@tum.de>
* or1k/interruts-asm.S: Change registers to callee-saved.
2015-05-18 Nick Clifton <nickc@redhat.com> 2015-05-18 Nick Clifton <nickc@redhat.com>
* msp430/msp430-sim.ld (.stack): Add an assertion to make sure * msp430/msp430-sim.ld (.stack): Add an assertion to make sure

View File

@ -38,49 +38,51 @@
.type _or1k_interrupt_handler,@function .type _or1k_interrupt_handler,@function
_or1k_interrupt_handler: _or1k_interrupt_handler:
/* Make room on stack, save link register */ /* Make room on stack, save link address register */
l.addi r1,r1,-12 l.addi r1,r1,-4
l.sw 0(r1),r9 l.sw 0(r1),r9
/* Read PICSR */ /* Read PICSR */
l.mfspr r3,r0,OR1K_SPR_PIC_PICSR_ADDR l.mfspr r20,r0,OR1K_SPR_PIC_PICSR_ADDR
/* Load handler table base address */ /* Load handler table base address */
l.movhi r7,hi(_or1k_interrupt_handler_table) // Needs to be callee-saved register
l.ori r7,r7,lo(_or1k_interrupt_handler_table) l.movhi r16,hi(_or1k_interrupt_handler_table)
l.ori r16,r16,lo(_or1k_interrupt_handler_table)
/* Load data pointer table base address */ /* Load data pointer table base address */
l.movhi r12,hi(_or1k_interrupt_handler_data_ptr_table) // Needs to be callee-saved register
l.ori r12,r12,lo(_or1k_interrupt_handler_data_ptr_table) l.movhi r18,hi(_or1k_interrupt_handler_data_ptr_table)
l.ori r18,r18,lo(_or1k_interrupt_handler_data_ptr_table)
#ifdef __OR1K_MULTICORE__ #ifdef __OR1K_MULTICORE__
/* Read the addresses of the arrays of cores */ /* Read the addresses of the arrays of cores */
/* r7 = (*or1k_interrupt_handler_table) */ /* r7 = (*or1k_interrupt_handler_table) */
l.lwz r7,0(r7) l.lwz r16,0(r16)
/* r12 = (*or1k_interrupt_handler_data_ptr_table) */ /* r12 = (*or1k_interrupt_handler_data_ptr_table) */
l.lwz r12,0(r12) l.lwz r18,0(r18)
/* Generate offset in arrays */ /* Generate offset in arrays */
/* r14 = coreid */ /* r14 = coreid */
l.mfspr r14,r0,OR1K_SPR_SYS_COREID_ADDR l.mfspr r14,r0,OR1K_SPR_SYS_COREID_ADDR
/* r14 = coreid*32*4 = off */ /* r14 = coreid*32*4 = off */
l.slli r14,r14,7 l.slli r14,r14,7
/* r7 = (*or1k_exception_handler_table)[coreid] */ /* r7 = (*or1k_exception_handler_table)[coreid] */
l.add r7,r7,r14 l.add r16,r16,r14
/* r12 = (*or1k_exception_handler_table)[coreid] */ /* r12 = (*or1k_exception_handler_table)[coreid] */
l.add r12,r12,r14 l.add r18,r18,r14
#endif #endif
.L0: .L0:
/* Find first set bit in PICSR */ /* Find first set bit in PICSR */
l.ff1 r4,r3 l.ff1 r4,r20
/* Any bits set? */ /* Any bits set? */
l.sfne r4,r0 l.sfne r4,r0
/* If none, finish */ /* If none, finish */
OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L2)) OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L2))
/* What is IRQ function table offset? */ /* What is IRQ function table offset? */
l.addi r5,r4,-1 l.addi r22,r4,-1
l.slli r6,r5,2 l.slli r6,r22,2
/* Add this to table bases */ /* Add this to table bases */
l.add r14,r6,r7 l.add r14,r6,r16
l.add r13,r6,r12 l.add r13,r6,r18
/* Fetch handler function address */ /* Fetch handler function address */
l.lwz r14,0(r14) l.lwz r14,0(r14)
@ -90,33 +92,27 @@ _or1k_interrupt_handler:
/* Skip if no handler: TODO: Indicate interrupt fired but no handler*/ /* Skip if no handler: TODO: Indicate interrupt fired but no handler*/
OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L1)) OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L1))
/* Pull out data pointer from table, save r3, we'll write over it */ /* Call handler, load data pointer */
l.sw 4(r1),r3
l.lwz r3,0(r13)
/* Call handler, save r5 in delay slot */
OR1K_DELAYED( OR1K_DELAYED(
OR1K_INST(l.sw 8(r1),r5), OR1K_INST(l.lwz r3,0(r13)),
OR1K_INST(l.jalr r14) OR1K_INST(l.jalr r14)
) )
/* Reload r3,r5 */
l.lwz r3,4(r1)
l.lwz r5,8(r1)
.L1: .L1:
/* Clear bit from PICSR, return to start of checking loop */ /* Clear bit from PICSR, return to start of checking loop */
l.ori r6,r0,1 l.ori r6,r0,1
l.sll r6,r6,r5 l.sll r6,r6,r22
OR1K_DELAYED( OR1K_DELAYED(
OR1K_INST(l.xor r3,r3,r6), OR1K_INST(l.xor r20,r20,r6),
OR1K_INST(l.j .L0) OR1K_INST(l.j .L0)
) )
.L2: .L2:
/* Finish up - write PICSR back, restore r9*/ /* Finish up - write PICSR back, restore r9*/
l.lwz r9,0(r1) l.lwz r9,0(r1)
l.mtspr r0,r3,OR1K_SPR_PIC_PICSR_ADDR l.mtspr r0,r20,OR1K_SPR_PIC_PICSR_ADDR
OR1K_DELAYED( OR1K_DELAYED(
OR1K_INST(l.addi r1,r1,12), OR1K_INST(l.addi r1,r1,4),
OR1K_INST(l.jr r9) OR1K_INST(l.jr r9)
) )