163 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| /* interrupts-asm.S -- interrupt handling for OpenRISC 1000.
 | |
|  *
 | |
|  * Copyright (c) 2011, 2012, 2014 Authors
 | |
|  *
 | |
|  * Contributor Julius Baxter <juliusbaxter@gmail.com>
 | |
|  * Contributor Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
 | |
|  * Contributor Stefan Wallentowitz <stefan.wallentowitz@tum.de>
 | |
|  *
 | |
|  * The authors hereby grant permission to use, copy, modify, distribute,
 | |
|  * and license this software and its documentation for any purpose, provided
 | |
|  * that existing copyright notices are retained in all copies and that this
 | |
|  * notice is included verbatim in any distributions. No written agreement,
 | |
|  * license, or royalty fee is required for any of the authorized uses.
 | |
|  * Modifications to this software may be copyrighted by their authors
 | |
|  * and need not follow the licensing terms described here, provided that
 | |
|  * the new terms are clearly indicated on the first page of each file where
 | |
|  * they apply.
 | |
|  */
 | |
| 
 | |
| /* -------------------------------------------------------------------------- */
 | |
| /*!Generic interrupt handler function for or1k
 | |
|                                                                               */
 | |
| /* -------------------------------------------------------------------------- */
 | |
| 
 | |
| #include "include/or1k-asm.h"
 | |
| #include "include/or1k-sprs.h"
 | |
| 
 | |
| 	.extern _or1k_interrupt_handler_table
 | |
| 	.extern _or1k_interrupt_handler_data_ptr_table
 | |
| 
 | |
| /* -------------------------------------------------------------------------- */
 | |
| /*!Function to call appropriate interrupt handler
 | |
|                                                                               */
 | |
| /* -------------------------------------------------------------------------- */
 | |
| 
 | |
| 	.section .text
 | |
| 	.global	_or1k_interrupt_handler
 | |
| 	.type	_or1k_interrupt_handler,@function
 | |
| 
 | |
| _or1k_interrupt_handler:
 | |
| 	/* Make room on stack, save link address register */
 | |
| 	l.addi	r1,r1,-4
 | |
| 	l.sw	0(r1),r9
 | |
| 
 | |
| 	/* Read PICSR */
 | |
| 	l.mfspr	r20,r0,OR1K_SPR_PIC_PICSR_ADDR
 | |
| 
 | |
| 	/* Load handler table base address */
 | |
| 	// 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 */
 | |
| 	// 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	r16,0(r16)
 | |
| 	/* r12 = (*or1k_interrupt_handler_data_ptr_table)  */
 | |
| 	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	r16,r16,r14
 | |
| 	/* r12 = (*or1k_exception_handler_table)[coreid] */
 | |
| 	l.add	r18,r18,r14
 | |
| #endif
 | |
| 
 | |
| .L0:
 | |
| 	/* Find first set bit in PICSR */
 | |
| 	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	r22,r4,-1
 | |
| 	l.slli	r6,r22,2
 | |
| 	/* Add this to table bases */
 | |
| 	l.add	r14,r6,r16
 | |
| 	l.add	r13,r6,r18
 | |
| 
 | |
| 	/* Fetch handler function address */
 | |
| 	l.lwz	r14,0(r14)
 | |
| 
 | |
| 	/* Double check it's valid, compare against INTERRUPT_HANDLER_NOT_SET */
 | |
| 	l.sfne	r14,r0
 | |
| 	/* Skip if no handler: TODO: Indicate interrupt fired but no handler*/
 | |
| 	OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L1))
 | |
| 
 | |
| 	/* Call handler, load data pointer */
 | |
| 	OR1K_DELAYED(
 | |
| 		OR1K_INST(l.lwz  r3,0(r13)),
 | |
| 		OR1K_INST(l.jalr r14)
 | |
| 	)
 | |
| 
 | |
| .L1:
 | |
| 	/* Clear bit from PICSR, return to start of checking loop */
 | |
| 	l.ori	r6,r0,1
 | |
| 	l.sll	r6,r6,r22
 | |
| 	OR1K_DELAYED(
 | |
| 		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,r20,OR1K_SPR_PIC_PICSR_ADDR
 | |
| 	OR1K_DELAYED(
 | |
| 		OR1K_INST(l.addi r1,r1,4),
 | |
| 		OR1K_INST(l.jr   r9)
 | |
| 	)
 | |
| 
 | |
| /* -------------------------------------------------------------------------- */
 | |
| /*!Function to enable an interrupt handler in the PICMR
 | |
|                                                                               */
 | |
| /* -------------------------------------------------------------------------- */
 | |
| 	.global	or1k_interrupt_enable
 | |
| 	.type	or1k_interrupt_enable,@function
 | |
| 
 | |
| 	/* r3 should have IRQ line for peripheral */
 | |
| or1k_interrupt_enable:
 | |
| 	l.addi 	r1,r1,-4
 | |
| 	l.sw	0(r1),r4
 | |
| 	l.ori	r4,r0,0x1
 | |
| 	l.sll	r4,r4,r3
 | |
| 	l.mfspr	r3,r0,OR1K_SPR_PIC_PICMR_ADDR
 | |
| 	l.or	r3,r3,r4
 | |
| 	l.mtspr	r0,r3,OR1K_SPR_PIC_PICMR_ADDR
 | |
| 	l.lwz	r4,0(r1)
 | |
| 	OR1K_DELAYED(
 | |
| 		OR1K_INST(l.addi	r1,r1,4),
 | |
| 		OR1K_INST(l.jr	r9)
 | |
| 	)
 | |
| 
 | |
| /* -------------------------------------------------------------------------- */
 | |
| /*!Function to disable an interrupt handler in the PICMR
 | |
|                                                                               */
 | |
| /* -------------------------------------------------------------------------- */
 | |
| 	.global	or1k_interrupt_disable
 | |
| 	.type	or1k_interrupt_disable,@function
 | |
| 
 | |
| 	/* r3 should have IRQ line for peripheral */
 | |
| or1k_interrupt_disable:
 | |
| 	l.addi 	r1,r1,-4
 | |
| 	l.sw	0(r1),r4
 | |
| 	l.ori	r4,r0,0x1
 | |
| 	l.sll	r4,r4,r3
 | |
| 	l.xori	r4,r4,0xffff
 | |
| 	l.mfspr	r3,r0,OR1K_SPR_PIC_PICMR_ADDR
 | |
| 	l.and	r3,r3,r4
 | |
| 	l.mtspr	r0,r3,OR1K_SPR_PIC_PICMR_ADDR
 | |
| 	l.lwz	r4,0(r1)
 | |
| 	OR1K_DELAYED(
 | |
| 		OR1K_INST(l.addi r1,r1,4),
 | |
| 		OR1K_INST(l.jr   r9)
 | |
| 	)
 |