310 lines
		
	
	
	
		
			6.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			310 lines
		
	
	
	
		
			6.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Macro used to simplify coding multi-line assembler. | ||
|  |  * Some of the bit test macro can simplify down to one line | ||
|  |  * depending on the mask value. | ||
|  |  * | ||
|  |  * Copyright (C) 2004 Microtronix Datacom Ltd. | ||
|  |  * | ||
|  |  * All rights reserved. | ||
|  |  * | ||
|  |  * This program is free software; you can redistribute it and/or modify | ||
|  |  * it under the terms of the GNU General Public License as published by | ||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||
|  |  * (at your option) any later version. | ||
|  |  * | ||
|  |  * This program is distributed in the hope that it will be useful, but | ||
|  |  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  |  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
|  |  * NON INFRINGEMENT.  See the GNU General Public License for more | ||
|  |  * details. | ||
|  |  * | ||
|  |  */ | ||
|  | #ifndef _ASM_NIOS2_ASMMACROS_H
 | ||
|  | #define _ASM_NIOS2_ASMMACROS_H
 | ||
|  | /*
 | ||
|  |  * ANDs reg2 with mask and places the result in reg1. | ||
|  |  * | ||
|  |  * You cannnot use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro ANDI32	reg1, reg2, mask | ||
|  | .if \mask & 0xffff | ||
|  | 	.if \mask & 0xffff0000 | ||
|  | 		movhi	\reg1, %hi(\mask) | ||
|  | 		movui	\reg1, %lo(\mask) | ||
|  | 		and	\reg1, \reg1, \reg2 | ||
|  | 	.else | ||
|  | 		andi	\reg1, \reg2, %lo(\mask) | ||
|  | 	.endif | ||
|  | .else | ||
|  | 	andhi	\reg1, \reg2, %hi(\mask) | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * ORs reg2 with mask and places the result in reg1. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro ORI32	reg1, reg2, mask | ||
|  | .if \mask & 0xffff | ||
|  | 	.if \mask & 0xffff0000 | ||
|  | 		orhi	\reg1, \reg2, %hi(\mask) | ||
|  | 		ori	\reg1, \reg2, %lo(\mask) | ||
|  | 	.else | ||
|  | 		ori	\reg1, \reg2, %lo(\mask) | ||
|  | 	.endif | ||
|  | .else | ||
|  | 	orhi	\reg1, \reg2, %hi(\mask) | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * XORs reg2 with mask and places the result in reg1. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro XORI32	reg1, reg2, mask | ||
|  | .if \mask & 0xffff | ||
|  | 	.if \mask & 0xffff0000 | ||
|  | 		xorhi	\reg1, \reg2, %hi(\mask) | ||
|  | 		xori	\reg1, \reg1, %lo(\mask) | ||
|  | 	.else | ||
|  | 		xori	\reg1, \reg2, %lo(\mask) | ||
|  | 	.endif | ||
|  | .else | ||
|  | 	xorhi	\reg1, \reg2, %hi(\mask) | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * This is a support macro for BTBZ & BTBNZ.  It checks | ||
|  |  * the bit to make sure it is valid 32 value. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BT	reg1, reg2, bit | ||
|  | .if \bit > 31 | ||
|  | 	.err | ||
|  | .else | ||
|  | 	.if \bit < 16 | ||
|  | 		andi	\reg1, \reg2, (1 << \bit) | ||
|  | 	.else | ||
|  | 		andhi	\reg1, \reg2, (1 << (\bit - 16)) | ||
|  | 	.endif | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and branches to label if the | ||
|  |  * bit is zero.  The result of the bit test is stored in reg1. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTBZ	reg1, reg2, bit, label | ||
|  | 	BT	\reg1, \reg2, \bit | ||
|  | 	beq	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and branches to label if the | ||
|  |  * bit is non-zero.  The result of the bit test is stored in reg1. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTBNZ	reg1, reg2, bit, label | ||
|  | 	BT	\reg1, \reg2, \bit | ||
|  | 	bne	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then compliments the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTC	reg1, reg2, bit | ||
|  | .if \bit > 31 | ||
|  | 	.err | ||
|  | .else | ||
|  | 	.if \bit < 16 | ||
|  | 		andi	\reg1, \reg2, (1 << \bit) | ||
|  | 		xori	\reg2, \reg2, (1 << \bit) | ||
|  | 	.else | ||
|  | 		andhi	\reg1, \reg2, (1 << (\bit - 16)) | ||
|  | 		xorhi	\reg2, \reg2, (1 << (\bit - 16)) | ||
|  | 	.endif | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then sets the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTS	reg1, reg2, bit | ||
|  | .if \bit > 31 | ||
|  | 	.err | ||
|  | .else | ||
|  | 	.if \bit < 16 | ||
|  | 		andi	\reg1, \reg2, (1 << \bit) | ||
|  | 		ori	\reg2, \reg2, (1 << \bit) | ||
|  | 	.else | ||
|  | 		andhi	\reg1, \reg2, (1 << (\bit - 16)) | ||
|  | 		orhi	\reg2, \reg2, (1 << (\bit - 16)) | ||
|  | 	.endif | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then resets the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTR	reg1, reg2, bit | ||
|  | .if \bit > 31 | ||
|  | 	.err | ||
|  | .else | ||
|  | 	.if \bit < 16 | ||
|  | 		andi	\reg1, \reg2, (1 << \bit) | ||
|  | 		andi	\reg2, \reg2, %lo(~(1 << \bit)) | ||
|  | 	.else | ||
|  | 		andhi	\reg1, \reg2, (1 << (\bit - 16)) | ||
|  | 		andhi	\reg2, \reg2, %lo(~(1 << (\bit - 16))) | ||
|  | 	.endif | ||
|  | .endif | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then compliments the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1.  If the | ||
|  |  * original bit was zero it branches to label. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTCBZ	reg1, reg2, bit, label | ||
|  | 	BTC	\reg1, \reg2, \bit | ||
|  | 	beq	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then compliments the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1.  If the | ||
|  |  * original bit was non-zero it branches to label. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTCBNZ	reg1, reg2, bit, label | ||
|  | 	BTC	\reg1, \reg2, \bit | ||
|  | 	bne	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then sets the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1.  If the | ||
|  |  * original bit was zero it branches to label. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTSBZ	reg1, reg2, bit, label | ||
|  | 	BTS	\reg1, \reg2, \bit | ||
|  | 	beq	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then sets the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1.  If the | ||
|  |  * original bit was non-zero it branches to label. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTSBNZ	reg1, reg2, bit, label | ||
|  | 	BTS	\reg1, \reg2, \bit | ||
|  | 	bne	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then resets the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1.  If the | ||
|  |  * original bit was zero it branches to label. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTRBZ	reg1, reg2, bit, label | ||
|  | 	BTR	\reg1, \reg2, \bit | ||
|  | 	bne	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bit in reg2 and then resets the bit in reg2. | ||
|  |  * The result of the bit test is stored in reg1.  If the | ||
|  |  * original bit was non-zero it branches to label. | ||
|  |  * | ||
|  |  * It is NOT safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro BTRBNZ	reg1, reg2, bit, label | ||
|  | 	BTR	\reg1, \reg2, \bit | ||
|  | 	bne	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bits in mask against reg2 stores the result in reg1. | ||
|  |  * If the all the bits in the mask are zero it branches to label. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro TSTBZ	reg1, reg2, mask, label | ||
|  | 	ANDI32	\reg1, \reg2, \mask | ||
|  | 	beq	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Tests the bits in mask against reg2 stores the result in reg1. | ||
|  |  * If the any of the bits in the mask are 1 it branches to label. | ||
|  |  * | ||
|  |  * It is safe to use the same register for reg1 & reg2. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro TSTBNZ	reg1, reg2, mask, label | ||
|  | 	ANDI32	\reg1, \reg2, \mask | ||
|  | 	bne	\reg1, r0, \label | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Pushes reg onto the stack. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro PUSH	reg | ||
|  | 	addi	sp, sp, -4 | ||
|  | 	stw	\reg, 0(sp) | ||
|  | .endm | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Pops the top of the stack into reg. | ||
|  |  */ | ||
|  | 
 | ||
|  | .macro POP	reg | ||
|  | 	ldw	\reg, 0(sp) | ||
|  | 	addi	sp, sp, 4 | ||
|  | .endm | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif /* _ASM_NIOS2_ASMMACROS_H */
 |