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