162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Macro used to simplify coding multi-line assembler.
462306a36Sopenharmony_ci * Some of the bit test macro can simplify down to one line
562306a36Sopenharmony_ci * depending on the mask value.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2004 Microtronix Datacom Ltd.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * All rights reserved.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#ifndef _ASM_NIOS2_ASMMACROS_H
1262306a36Sopenharmony_ci#define _ASM_NIOS2_ASMMACROS_H
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci * ANDs reg2 with mask and places the result in reg1.
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * You cannnot use the same register for reg1 & reg2.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci.macro ANDI32	reg1, reg2, mask
2062306a36Sopenharmony_ci.if \mask & 0xffff
2162306a36Sopenharmony_ci	.if \mask & 0xffff0000
2262306a36Sopenharmony_ci		movhi	\reg1, %hi(\mask)
2362306a36Sopenharmony_ci		movui	\reg1, %lo(\mask)
2462306a36Sopenharmony_ci		and	\reg1, \reg1, \reg2
2562306a36Sopenharmony_ci	.else
2662306a36Sopenharmony_ci		andi	\reg1, \reg2, %lo(\mask)
2762306a36Sopenharmony_ci	.endif
2862306a36Sopenharmony_ci.else
2962306a36Sopenharmony_ci	andhi	\reg1, \reg2, %hi(\mask)
3062306a36Sopenharmony_ci.endif
3162306a36Sopenharmony_ci.endm
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*
3462306a36Sopenharmony_ci * ORs reg2 with mask and places the result in reg1.
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci.macro ORI32	reg1, reg2, mask
4062306a36Sopenharmony_ci.if \mask & 0xffff
4162306a36Sopenharmony_ci	.if \mask & 0xffff0000
4262306a36Sopenharmony_ci		orhi	\reg1, \reg2, %hi(\mask)
4362306a36Sopenharmony_ci		ori	\reg1, \reg2, %lo(\mask)
4462306a36Sopenharmony_ci	.else
4562306a36Sopenharmony_ci		ori	\reg1, \reg2, %lo(\mask)
4662306a36Sopenharmony_ci	.endif
4762306a36Sopenharmony_ci.else
4862306a36Sopenharmony_ci	orhi	\reg1, \reg2, %hi(\mask)
4962306a36Sopenharmony_ci.endif
5062306a36Sopenharmony_ci.endm
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/*
5362306a36Sopenharmony_ci * XORs reg2 with mask and places the result in reg1.
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
5662306a36Sopenharmony_ci */
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci.macro XORI32	reg1, reg2, mask
5962306a36Sopenharmony_ci.if \mask & 0xffff
6062306a36Sopenharmony_ci	.if \mask & 0xffff0000
6162306a36Sopenharmony_ci		xorhi	\reg1, \reg2, %hi(\mask)
6262306a36Sopenharmony_ci		xori	\reg1, \reg1, %lo(\mask)
6362306a36Sopenharmony_ci	.else
6462306a36Sopenharmony_ci		xori	\reg1, \reg2, %lo(\mask)
6562306a36Sopenharmony_ci	.endif
6662306a36Sopenharmony_ci.else
6762306a36Sopenharmony_ci	xorhi	\reg1, \reg2, %hi(\mask)
6862306a36Sopenharmony_ci.endif
6962306a36Sopenharmony_ci.endm
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * This is a support macro for BTBZ & BTBNZ.  It checks
7362306a36Sopenharmony_ci * the bit to make sure it is valid 32 value.
7462306a36Sopenharmony_ci *
7562306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci.macro BT	reg1, reg2, bit
7962306a36Sopenharmony_ci.if \bit > 31
8062306a36Sopenharmony_ci	.err
8162306a36Sopenharmony_ci.else
8262306a36Sopenharmony_ci	.if \bit < 16
8362306a36Sopenharmony_ci		andi	\reg1, \reg2, (1 << \bit)
8462306a36Sopenharmony_ci	.else
8562306a36Sopenharmony_ci		andhi	\reg1, \reg2, (1 << (\bit - 16))
8662306a36Sopenharmony_ci	.endif
8762306a36Sopenharmony_ci.endif
8862306a36Sopenharmony_ci.endm
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/*
9162306a36Sopenharmony_ci * Tests the bit in reg2 and branches to label if the
9262306a36Sopenharmony_ci * bit is zero.  The result of the bit test is stored in reg1.
9362306a36Sopenharmony_ci *
9462306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
9562306a36Sopenharmony_ci */
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci.macro BTBZ	reg1, reg2, bit, label
9862306a36Sopenharmony_ci	BT	\reg1, \reg2, \bit
9962306a36Sopenharmony_ci	beq	\reg1, r0, \label
10062306a36Sopenharmony_ci.endm
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/*
10362306a36Sopenharmony_ci * Tests the bit in reg2 and branches to label if the
10462306a36Sopenharmony_ci * bit is non-zero.  The result of the bit test is stored in reg1.
10562306a36Sopenharmony_ci *
10662306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
10762306a36Sopenharmony_ci */
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci.macro BTBNZ	reg1, reg2, bit, label
11062306a36Sopenharmony_ci	BT	\reg1, \reg2, \bit
11162306a36Sopenharmony_ci	bne	\reg1, r0, \label
11262306a36Sopenharmony_ci.endm
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/*
11562306a36Sopenharmony_ci * Tests the bit in reg2 and then compliments the bit in reg2.
11662306a36Sopenharmony_ci * The result of the bit test is stored in reg1.
11762306a36Sopenharmony_ci *
11862306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci.macro BTC	reg1, reg2, bit
12262306a36Sopenharmony_ci.if \bit > 31
12362306a36Sopenharmony_ci	.err
12462306a36Sopenharmony_ci.else
12562306a36Sopenharmony_ci	.if \bit < 16
12662306a36Sopenharmony_ci		andi	\reg1, \reg2, (1 << \bit)
12762306a36Sopenharmony_ci		xori	\reg2, \reg2, (1 << \bit)
12862306a36Sopenharmony_ci	.else
12962306a36Sopenharmony_ci		andhi	\reg1, \reg2, (1 << (\bit - 16))
13062306a36Sopenharmony_ci		xorhi	\reg2, \reg2, (1 << (\bit - 16))
13162306a36Sopenharmony_ci	.endif
13262306a36Sopenharmony_ci.endif
13362306a36Sopenharmony_ci.endm
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/*
13662306a36Sopenharmony_ci * Tests the bit in reg2 and then sets the bit in reg2.
13762306a36Sopenharmony_ci * The result of the bit test is stored in reg1.
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci.macro BTS	reg1, reg2, bit
14362306a36Sopenharmony_ci.if \bit > 31
14462306a36Sopenharmony_ci	.err
14562306a36Sopenharmony_ci.else
14662306a36Sopenharmony_ci	.if \bit < 16
14762306a36Sopenharmony_ci		andi	\reg1, \reg2, (1 << \bit)
14862306a36Sopenharmony_ci		ori	\reg2, \reg2, (1 << \bit)
14962306a36Sopenharmony_ci	.else
15062306a36Sopenharmony_ci		andhi	\reg1, \reg2, (1 << (\bit - 16))
15162306a36Sopenharmony_ci		orhi	\reg2, \reg2, (1 << (\bit - 16))
15262306a36Sopenharmony_ci	.endif
15362306a36Sopenharmony_ci.endif
15462306a36Sopenharmony_ci.endm
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci/*
15762306a36Sopenharmony_ci * Tests the bit in reg2 and then resets the bit in reg2.
15862306a36Sopenharmony_ci * The result of the bit test is stored in reg1.
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
16162306a36Sopenharmony_ci */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci.macro BTR	reg1, reg2, bit
16462306a36Sopenharmony_ci.if \bit > 31
16562306a36Sopenharmony_ci	.err
16662306a36Sopenharmony_ci.else
16762306a36Sopenharmony_ci	.if \bit < 16
16862306a36Sopenharmony_ci		andi	\reg1, \reg2, (1 << \bit)
16962306a36Sopenharmony_ci		andi	\reg2, \reg2, %lo(~(1 << \bit))
17062306a36Sopenharmony_ci	.else
17162306a36Sopenharmony_ci		andhi	\reg1, \reg2, (1 << (\bit - 16))
17262306a36Sopenharmony_ci		andhi	\reg2, \reg2, %lo(~(1 << (\bit - 16)))
17362306a36Sopenharmony_ci	.endif
17462306a36Sopenharmony_ci.endif
17562306a36Sopenharmony_ci.endm
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci/*
17862306a36Sopenharmony_ci * Tests the bit in reg2 and then compliments the bit in reg2.
17962306a36Sopenharmony_ci * The result of the bit test is stored in reg1.  If the
18062306a36Sopenharmony_ci * original bit was zero it branches to label.
18162306a36Sopenharmony_ci *
18262306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
18362306a36Sopenharmony_ci */
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci.macro BTCBZ	reg1, reg2, bit, label
18662306a36Sopenharmony_ci	BTC	\reg1, \reg2, \bit
18762306a36Sopenharmony_ci	beq	\reg1, r0, \label
18862306a36Sopenharmony_ci.endm
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/*
19162306a36Sopenharmony_ci * Tests the bit in reg2 and then compliments the bit in reg2.
19262306a36Sopenharmony_ci * The result of the bit test is stored in reg1.  If the
19362306a36Sopenharmony_ci * original bit was non-zero it branches to label.
19462306a36Sopenharmony_ci *
19562306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
19662306a36Sopenharmony_ci */
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci.macro BTCBNZ	reg1, reg2, bit, label
19962306a36Sopenharmony_ci	BTC	\reg1, \reg2, \bit
20062306a36Sopenharmony_ci	bne	\reg1, r0, \label
20162306a36Sopenharmony_ci.endm
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci/*
20462306a36Sopenharmony_ci * Tests the bit in reg2 and then sets the bit in reg2.
20562306a36Sopenharmony_ci * The result of the bit test is stored in reg1.  If the
20662306a36Sopenharmony_ci * original bit was zero it branches to label.
20762306a36Sopenharmony_ci *
20862306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci.macro BTSBZ	reg1, reg2, bit, label
21262306a36Sopenharmony_ci	BTS	\reg1, \reg2, \bit
21362306a36Sopenharmony_ci	beq	\reg1, r0, \label
21462306a36Sopenharmony_ci.endm
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/*
21762306a36Sopenharmony_ci * Tests the bit in reg2 and then sets the bit in reg2.
21862306a36Sopenharmony_ci * The result of the bit test is stored in reg1.  If the
21962306a36Sopenharmony_ci * original bit was non-zero it branches to label.
22062306a36Sopenharmony_ci *
22162306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
22262306a36Sopenharmony_ci */
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci.macro BTSBNZ	reg1, reg2, bit, label
22562306a36Sopenharmony_ci	BTS	\reg1, \reg2, \bit
22662306a36Sopenharmony_ci	bne	\reg1, r0, \label
22762306a36Sopenharmony_ci.endm
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/*
23062306a36Sopenharmony_ci * Tests the bit in reg2 and then resets the bit in reg2.
23162306a36Sopenharmony_ci * The result of the bit test is stored in reg1.  If the
23262306a36Sopenharmony_ci * original bit was zero it branches to label.
23362306a36Sopenharmony_ci *
23462306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci.macro BTRBZ	reg1, reg2, bit, label
23862306a36Sopenharmony_ci	BTR	\reg1, \reg2, \bit
23962306a36Sopenharmony_ci	bne	\reg1, r0, \label
24062306a36Sopenharmony_ci.endm
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci/*
24362306a36Sopenharmony_ci * Tests the bit in reg2 and then resets the bit in reg2.
24462306a36Sopenharmony_ci * The result of the bit test is stored in reg1.  If the
24562306a36Sopenharmony_ci * original bit was non-zero it branches to label.
24662306a36Sopenharmony_ci *
24762306a36Sopenharmony_ci * It is NOT safe to use the same register for reg1 & reg2.
24862306a36Sopenharmony_ci */
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci.macro BTRBNZ	reg1, reg2, bit, label
25162306a36Sopenharmony_ci	BTR	\reg1, \reg2, \bit
25262306a36Sopenharmony_ci	bne	\reg1, r0, \label
25362306a36Sopenharmony_ci.endm
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/*
25662306a36Sopenharmony_ci * Tests the bits in mask against reg2 stores the result in reg1.
25762306a36Sopenharmony_ci * If the all the bits in the mask are zero it branches to label.
25862306a36Sopenharmony_ci *
25962306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci.macro TSTBZ	reg1, reg2, mask, label
26362306a36Sopenharmony_ci	ANDI32	\reg1, \reg2, \mask
26462306a36Sopenharmony_ci	beq	\reg1, r0, \label
26562306a36Sopenharmony_ci.endm
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci/*
26862306a36Sopenharmony_ci * Tests the bits in mask against reg2 stores the result in reg1.
26962306a36Sopenharmony_ci * If the any of the bits in the mask are 1 it branches to label.
27062306a36Sopenharmony_ci *
27162306a36Sopenharmony_ci * It is safe to use the same register for reg1 & reg2.
27262306a36Sopenharmony_ci */
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci.macro TSTBNZ	reg1, reg2, mask, label
27562306a36Sopenharmony_ci	ANDI32	\reg1, \reg2, \mask
27662306a36Sopenharmony_ci	bne	\reg1, r0, \label
27762306a36Sopenharmony_ci.endm
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci/*
28062306a36Sopenharmony_ci * Pushes reg onto the stack.
28162306a36Sopenharmony_ci */
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci.macro PUSH	reg
28462306a36Sopenharmony_ci	addi	sp, sp, -4
28562306a36Sopenharmony_ci	stw	\reg, 0(sp)
28662306a36Sopenharmony_ci.endm
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci/*
28962306a36Sopenharmony_ci * Pops the top of the stack into reg.
29062306a36Sopenharmony_ci */
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci.macro POP	reg
29362306a36Sopenharmony_ci	ldw	\reg, 0(sp)
29462306a36Sopenharmony_ci	addi	sp, sp, 4
29562306a36Sopenharmony_ci.endm
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci#endif /* _ASM_NIOS2_ASMMACROS_H */
299