123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /* Testsuite architecture macros for OpenRISC.
- Copyright (C) 2017-2022 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 */
|