xref: /netbsd-src/external/gpl3/gdb/dist/sim/testsuite/or1k/or1k-asm-test.h (revision 2dd295436a0082eb4f8d294f4aa73c223413d0f2)
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)
214 bss_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)
223 bss_is_empty:
224 	.endm
225 
226 #endif /* OR1K_ASM_TEST_H */
227