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