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