| /* | |
| * 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 */ |