|  | /* SPDX-License-Identifier: GPL-2.0-or-later */ | 
|  | /* | 
|  | * 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. | 
|  | */ | 
|  | #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 */ |