diff options
Diffstat (limited to 'sim/testsuite/or1k/or1k-asm-test.h')
-rw-r--r-- | sim/testsuite/or1k/or1k-asm-test.h | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/sim/testsuite/or1k/or1k-asm-test.h b/sim/testsuite/or1k/or1k-asm-test.h new file mode 100644 index 0000000..3525673 --- /dev/null +++ b/sim/testsuite/or1k/or1k-asm-test.h @@ -0,0 +1,226 @@ +/* Testsuite architecture macros for OpenRISC. + + Copyright (C) 2017-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef OR1K_ASM_TEST_H +#define OR1K_ASM_TEST_H + +#include "spr-defs.h" + +/* Register definitions */ + +/* The "jump and link" instructions store the return address in R9. */ +#define LINK_REGISTER_R9 r9 + +/* These register definitions match the ABI. */ +#define ZERO_R0 r0 +#define STACK_POINTER_R1 r1 +#define FRAME_POINTER_R2 r2 +#define RETURN_VALUE_R11 r11 + + /* Load/move/clear helpers */ + + .macro LOAD_IMMEDIATE reg, val + l.movhi \reg, hi ( \val ) + l.ori \reg, \reg, lo ( \val ) + .endm + + .macro MOVE_REG dest_reg, src_reg + .ifnes "\dest_reg","\src_reg" + l.ori \dest_reg, \src_reg, 0 + .endif + .endm + + .macro CLEAR_REG reg + l.movhi \reg, 0 + .endm + + .macro MOVE_FROM_SPR reg, spr_reg + l.mfspr \reg, ZERO_R0, \spr_reg + .endm + + .macro MOVE_TO_SPR spr_reg, reg + l.mtspr ZERO_R0, \reg, \spr_reg + .endm + + .macro SET_SPR_SR_FLAGS flag_mask, scratch_reg_1, scratch_reg_2 + /* We cannot use PUSH and POP here because some flags like Carry + would get overwritten. */ + + /* We could optimise this routine, as instruction l.mtspr already + does a logical OR. */ + MOVE_FROM_SPR \scratch_reg_2, SPR_SR + LOAD_IMMEDIATE \scratch_reg_1, \flag_mask + l.or \scratch_reg_2, \scratch_reg_2, \scratch_reg_1 + MOVE_TO_SPR SPR_SR, \scratch_reg_2 + .endm + + .macro CLEAR_SPR_SR_FLAGS flag_mask, scratch_reg_1, scratch_reg_2 + /* We cannot use PUSH and POP here because some flags like Carry + would get overwritten. */ + + MOVE_FROM_SPR \scratch_reg_2, SPR_SR + LOAD_IMMEDIATE \scratch_reg_1, ~\flag_mask + l.and \scratch_reg_2, \scratch_reg_2, \scratch_reg_1 + MOVE_TO_SPR SPR_SR, \scratch_reg_2 + + .endm + + /* Stack helpers */ + +/* This value is defined in the OpenRISC 1000 specification. */ +#define EXCEPTION_STACK_SKIP_SIZE 128 + + /* WARNING: Functions without prolog cannot use these PUSH or POP + macros. + + PERFORMANCE WARNING: These PUSH/POP macros are convenient, but + can lead to slow code. If you need to PUSH or POP several + registers, it's faster to use non-zero offsets when + loading/storing and then increment/decrement the stack pointer + just once. */ + + .macro PUSH reg + l.addi STACK_POINTER_R1, STACK_POINTER_R1, -4 + l.sw 0(STACK_POINTER_R1), \reg + .endm + + /* WARNING: see the warnings for PUSH. */ + .macro POP reg + l.lwz \reg, 0(STACK_POINTER_R1) + l.addi STACK_POINTER_R1, STACK_POINTER_R1, 4 + .endm + +/* l.nop definitions for simulation control and console output. */ + +/* Register definitions for the simulation l.nop codes. */ +#define NOP_REPORT_R3 r3 +#define NOP_EXIT_R3 r3 + +/* SEC = Simulation Exit Code */ +#define SEC_SUCCESS 0 +#define SEC_RETURNED_FROM_MAIN 1 +#define SEC_GENERIC_ERROR 2 + + /* When running under the simulator, this l.nop code terminates the + simulation. */ + .macro EXIT_SIMULATION_WITH_IMMEDIATE_EXIT_CODE immediate_value + LOAD_IMMEDIATE NOP_EXIT_R3, \immediate_value + l.nop 1 + .endm + + .macro EXIT_SIMULATION_WITH_REG_EXIT_CODE reg + MOVE_REG NOP_EXIT_R3, \reg + l.nop 1 + .endm + + /* When running under the simulator, this l.nop code prints the + value of R3 to the console. */ + .macro REPORT_TO_CONSOLE + l.nop 2 + .endm + + /* NOTE: The stack must be set up, as this macro uses PUSH and POP. */ + .macro REPORT_REG_TO_CONSOLE reg + .ifeqs "\reg","r3" + /* Nothing more to do here, R3 is the register that gets printed. */ + REPORT_TO_CONSOLE + .else + PUSH NOP_REPORT_R3 + MOVE_REG NOP_REPORT_R3, \reg + REPORT_TO_CONSOLE + POP NOP_REPORT_R3 + .endif + .endm + + /* NOTE: The stack must be set up, as this macro uses PUSH and POP. */ + .macro REPORT_IMMEDIATE_TO_CONSOLE val + PUSH NOP_REPORT_R3 + LOAD_IMMEDIATE NOP_REPORT_R3, \val + REPORT_TO_CONSOLE + POP NOP_REPORT_R3 + .endm + + .macro PRINT_NEWLINE_TO_CONSOLE + PUSH r3 + LOAD_IMMEDIATE r3, 0x0A + l.nop 4 + POP r3 + .endm + + /* If SR[F] is set, writes 0x00000001 to the console, otherwise it + writes 0x00000000. */ + .macro REPORT_SRF_TO_CONSOLE + OR1K_DELAYED_NOP (l.bnf \@1$) + REPORT_IMMEDIATE_TO_CONSOLE 0x00000001 + OR1K_DELAYED_NOP (l.j \@2$) +\@1$: + REPORT_IMMEDIATE_TO_CONSOLE 0x00000000 +\@2$: + .endm + + /* If the given register is 0, writes 0x00000000 to the console, + otherwise it writes 0x00000001. */ + .macro REPORT_BOOL_TO_CONSOLE reg + l.sfne \reg, ZERO_R0 + REPORT_SRF_TO_CONSOLE + .endm + + /* Writes to the console the value of the given register bit. */ + .macro REPORT_BIT_TO_CONSOLE reg, single_bit_mask + PUSH r2 + PUSH r3 + PUSH r4 + MOVE_REG r2, \reg + LOAD_IMMEDIATE r4, \single_bit_mask + l.and r3, r2, r4 + REPORT_BOOL_TO_CONSOLE r3 + POP r4 + POP r3 + POP r2 + .endm + + /* Jump helpers */ + + .macro CALL overwritten_reg, subroutine_name + LOAD_IMMEDIATE \overwritten_reg, \subroutine_name + OR1K_DELAYED_NOP (l.jalr \overwritten_reg) + .endm + + .macro RETURN_TO_LINK_REGISTER_R9 + OR1K_DELAYED_NOP (l.jr LINK_REGISTER_R9) + .endm + + /* Clear the BSS section on start-up */ + + .macro CLEAR_BSS overwritten_reg1, overwritten_reg2 + LOAD_IMMEDIATE \overwritten_reg1, _bss_begin + LOAD_IMMEDIATE \overwritten_reg2, _bss_end + l.sfgeu \overwritten_reg1, \overwritten_reg2 + OR1K_DELAYED_NOP (l.bf bss_is_empty) +bss_clear_loop: + /* Possible optimisation to investigate: + move "l.sw 0(\overwritten_reg1), r0" to the jump delay slot as + "l.sw -4(\overwritten_reg1), r0" or similar. But keep in mind that + there are plans to remove the jump delay slot. */ + l.sw 0(\overwritten_reg1), r0 + l.addi \overwritten_reg1, \overwritten_reg1, 4 + l.sfgtu \overwritten_reg2, \overwritten_reg1 + OR1K_DELAYED_NOP (l.bf bss_clear_loop) +bss_is_empty: + .endm + +#endif /* OR1K_ASM_TEST_H */ |