aboutsummaryrefslogtreecommitdiff
path: root/sim/testsuite/or1k/or1k-asm-test.h
diff options
context:
space:
mode:
Diffstat (limited to 'sim/testsuite/or1k/or1k-asm-test.h')
-rw-r--r--sim/testsuite/or1k/or1k-asm-test.h226
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 */