1/* Testsuite architecture macros for OpenRISC.
2
3   Copyright (C) 2017-2023 Free Software Foundation, Inc.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#ifndef OR1K_ASM_TEST_H
19#define OR1K_ASM_TEST_H
20
21#include "spr-defs.h"
22
23/* Register definitions */
24
25/* The "jump and link" instructions store the return address in R9.  */
26#define LINK_REGISTER_R9 r9
27
28/* These register definitions match the ABI.  */
29#define ZERO_R0          r0
30#define STACK_POINTER_R1 r1
31#define FRAME_POINTER_R2 r2
32#define RETURN_VALUE_R11 r11
33
34	/* Load/move/clear helpers  */
35
36	.macro LOAD_IMMEDIATE  reg, val
37	l.movhi \reg,       hi ( \val )
38	l.ori   \reg, \reg, lo ( \val )
39	.endm
40
41	.macro MOVE_REG  dest_reg, src_reg
42	.ifnes "\dest_reg","\src_reg"
43	l.ori \dest_reg, \src_reg, 0
44	.endif
45	.endm
46
47	.macro CLEAR_REG reg
48	l.movhi \reg, 0
49	.endm
50
51	.macro MOVE_FROM_SPR  reg, spr_reg
52	l.mfspr \reg, ZERO_R0, \spr_reg
53	.endm
54
55	.macro MOVE_TO_SPR  spr_reg, reg
56	l.mtspr ZERO_R0, \reg, \spr_reg
57	.endm
58
59	.macro SET_SPR_SR_FLAGS flag_mask, scratch_reg_1, scratch_reg_2
60	/* We cannot use PUSH and POP here because some flags like Carry
61	   would get overwritten.  */
62
63	/* We could optimise this routine, as instruction l.mtspr already
64	   does a logical OR.  */
65	MOVE_FROM_SPR \scratch_reg_2, SPR_SR
66	LOAD_IMMEDIATE \scratch_reg_1, \flag_mask
67	l.or \scratch_reg_2, \scratch_reg_2, \scratch_reg_1
68	MOVE_TO_SPR SPR_SR, \scratch_reg_2
69	.endm
70
71	.macro CLEAR_SPR_SR_FLAGS flag_mask, scratch_reg_1, scratch_reg_2
72	/* We cannot use PUSH and POP here because some flags like Carry
73	   would get overwritten.  */
74
75	MOVE_FROM_SPR \scratch_reg_2, SPR_SR
76	LOAD_IMMEDIATE \scratch_reg_1, ~\flag_mask
77	l.and \scratch_reg_2, \scratch_reg_2, \scratch_reg_1
78	MOVE_TO_SPR SPR_SR, \scratch_reg_2
79
80	.endm
81
82	/* Stack helpers  */
83
84/* This value is defined in the OpenRISC 1000 specification.  */
85#define EXCEPTION_STACK_SKIP_SIZE  128
86
87	/* WARNING: Functions without prolog cannot use these PUSH or POP
88	   macros.
89
90	   PERFORMANCE WARNING: These PUSH/POP macros are convenient, but
91	   can lead to slow code.  If you need to PUSH or POP several
92	   registers, it's faster to use non-zero offsets when
93	   loading/storing and then increment/decrement the stack pointer
94	   just once.  */
95
96	.macro PUSH reg
97	l.addi STACK_POINTER_R1, STACK_POINTER_R1, -4
98	l.sw   0(STACK_POINTER_R1), \reg
99	.endm
100
101	/* WARNING: see the warnings for PUSH.  */
102	.macro POP reg
103	l.lwz  \reg, 0(STACK_POINTER_R1)
104	l.addi STACK_POINTER_R1, STACK_POINTER_R1, 4
105	.endm
106
107/* l.nop definitions for simulation control and console output.  */
108
109/* Register definitions for the simulation l.nop codes.  */
110#define NOP_REPORT_R3 r3
111#define NOP_EXIT_R3   r3
112
113/* SEC = Simulation Exit Code  */
114#define SEC_SUCCESS            0
115#define SEC_RETURNED_FROM_MAIN 1
116#define SEC_GENERIC_ERROR      2
117
118	/* When running under the simulator, this l.nop code terminates the
119	   simulation.  */
120	.macro EXIT_SIMULATION_WITH_IMMEDIATE_EXIT_CODE immediate_value
121	LOAD_IMMEDIATE NOP_EXIT_R3, \immediate_value
122	l.nop 1
123	.endm
124
125	.macro EXIT_SIMULATION_WITH_REG_EXIT_CODE reg
126	MOVE_REG NOP_EXIT_R3, \reg
127	l.nop 1
128	.endm
129
130	/* When running under the simulator, this l.nop code prints the
131	   value of R3 to the console.  */
132	.macro REPORT_TO_CONSOLE
133	l.nop 2
134	.endm
135
136	/* NOTE: The stack must be set up, as this macro uses PUSH and POP.  */
137	.macro REPORT_REG_TO_CONSOLE reg
138	.ifeqs "\reg","r3"
139	 /* Nothing more to do here, R3 is the register that gets printed.  */
140	 REPORT_TO_CONSOLE
141	.else
142	 PUSH     NOP_REPORT_R3
143	 MOVE_REG NOP_REPORT_R3, \reg
144	 REPORT_TO_CONSOLE
145	 POP      NOP_REPORT_R3
146	.endif
147	.endm
148
149	/* NOTE: The stack must be set up, as this macro uses PUSH and POP.  */
150	.macro REPORT_IMMEDIATE_TO_CONSOLE val
151	PUSH     NOP_REPORT_R3
152	LOAD_IMMEDIATE NOP_REPORT_R3, \val
153	REPORT_TO_CONSOLE
154	POP      NOP_REPORT_R3
155	.endm
156
157	.macro PRINT_NEWLINE_TO_CONSOLE
158	PUSH  r3
159	LOAD_IMMEDIATE r3, 0x0A
160	l.nop 4
161	POP   r3
162	.endm
163
164	/* If SR[F] is set, writes 0x00000001 to the console, otherwise it
165	   writes 0x00000000.  */
166	.macro REPORT_SRF_TO_CONSOLE
167	OR1K_DELAYED_NOP (l.bnf \@1$)
168	REPORT_IMMEDIATE_TO_CONSOLE 0x00000001
169	OR1K_DELAYED_NOP (l.j \@2$)
170\@1$:
171	REPORT_IMMEDIATE_TO_CONSOLE 0x00000000
172\@2$:
173	.endm
174
175	/* If the given register is 0, writes 0x00000000 to the console,
176	   otherwise it writes 0x00000001.  */
177	.macro REPORT_BOOL_TO_CONSOLE  reg
178	l.sfne \reg, ZERO_R0
179	REPORT_SRF_TO_CONSOLE
180	.endm
181
182	/* Writes to the console the value of the given register bit.  */
183	.macro REPORT_BIT_TO_CONSOLE  reg, single_bit_mask
184	PUSH r2
185	PUSH r3
186	PUSH r4
187	MOVE_REG r2, \reg
188	LOAD_IMMEDIATE r4, \single_bit_mask
189	l.and   r3, r2, r4
190	REPORT_BOOL_TO_CONSOLE r3
191	POP r4
192	POP r3
193	POP r2
194	.endm
195
196	/* Jump helpers */
197
198	.macro CALL overwritten_reg, subroutine_name
199	LOAD_IMMEDIATE \overwritten_reg, \subroutine_name
200	OR1K_DELAYED_NOP (l.jalr  \overwritten_reg)
201	.endm
202
203	.macro RETURN_TO_LINK_REGISTER_R9
204	OR1K_DELAYED_NOP (l.jr LINK_REGISTER_R9)
205	.endm
206
207	/* Clear the BSS section on start-up */
208
209	.macro CLEAR_BSS overwritten_reg1, overwritten_reg2
210	LOAD_IMMEDIATE \overwritten_reg1, _bss_begin
211	LOAD_IMMEDIATE \overwritten_reg2, _bss_end
212	l.sfgeu \overwritten_reg1, \overwritten_reg2
213	OR1K_DELAYED_NOP (l.bf    bss_is_empty)
214bss_clear_loop:
215	/* Possible optimisation to investigate:
216	   move "l.sw 0(\overwritten_reg1), r0" to the jump delay slot as
217	   "l.sw -4(\overwritten_reg1), r0" or similar. But keep in mind that
218	   there are plans to remove the jump delay slot.  */
219	l.sw    0(\overwritten_reg1), r0
220	l.addi  \overwritten_reg1, \overwritten_reg1, 4
221	l.sfgtu \overwritten_reg2, \overwritten_reg1
222	OR1K_DELAYED_NOP (l.bf    bss_clear_loop)
223bss_is_empty:
224	.endm
225
226#endif /* OR1K_ASM_TEST_H */
227