root/arch/nios2/include/asm/asm-macros.h
/* 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 */