143 lines
2.8 KiB
ArmAsm
143 lines
2.8 KiB
ArmAsm
|
# See LICENSE for license details.
|
||
|
|
||
|
#*****************************************************************************
|
||
|
# breakpoint.S
|
||
|
#-----------------------------------------------------------------------------
|
||
|
#
|
||
|
# Test breakpoints, if they are implemented.
|
||
|
#
|
||
|
|
||
|
#include "riscv_test.h"
|
||
|
#include "test_macros.h"
|
||
|
|
||
|
RVTEST_RV64M
|
||
|
RVTEST_CODE_BEGIN
|
||
|
|
||
|
# Set up breakpoint to trap on M-mode fetches.
|
||
|
li TESTNUM, 2
|
||
|
|
||
|
# Set tcontrol.mte, otherwise breakpoints are disabled. This may trap,
|
||
|
# because tcontrol is an optional register.
|
||
|
la a0, 1f
|
||
|
csrrw a0, mtvec, a0
|
||
|
li a1, 0x8
|
||
|
csrs tcontrol, a1
|
||
|
.p2align 2
|
||
|
1:
|
||
|
csrw mtvec, a0
|
||
|
|
||
|
# Enable interrupts; see https://github.com/riscv/riscv-debug-spec/blob/f510a7dd33317d0eee0f26b4fa082cd43a5ac7ea/Sdtrig.tex#L213-L214
|
||
|
csrsi mstatus, MSTATUS_MIE
|
||
|
|
||
|
# Skip tselect if hard-wired.
|
||
|
csrw tselect, x0
|
||
|
csrr a1, tselect
|
||
|
bne x0, a1, pass
|
||
|
|
||
|
la a2, 1f
|
||
|
csrw tdata2, a2
|
||
|
li a0, (2 << (__riscv_xlen - 4)) | MCONTROL_M | MCONTROL_EXECUTE
|
||
|
csrw tdata1, a0
|
||
|
# Skip if breakpoint type is unsupported.
|
||
|
csrr a1, tdata1
|
||
|
bne a0, a1, 2f
|
||
|
.align 2
|
||
|
1:
|
||
|
# Trap handler should skip this instruction.
|
||
|
beqz x0, fail
|
||
|
|
||
|
# Make sure reads don't trap.
|
||
|
li TESTNUM, 3
|
||
|
lw a0, (a2)
|
||
|
|
||
|
2:
|
||
|
# Set up breakpoint to trap on M-mode reads.
|
||
|
li TESTNUM, 4
|
||
|
li a0, (2 << (__riscv_xlen - 4)) | MCONTROL_M | MCONTROL_LOAD
|
||
|
csrw tdata1, a0
|
||
|
# Skip if breakpoint type is unsupported.
|
||
|
csrr a1, tdata1
|
||
|
bne a0, a1, 2f
|
||
|
la a2, data1
|
||
|
csrw tdata2, a2
|
||
|
|
||
|
# Trap handler should skip this instruction.
|
||
|
lw a2, (a2)
|
||
|
beqz a2, fail
|
||
|
|
||
|
# Make sure writes don't trap.
|
||
|
li TESTNUM, 5
|
||
|
sw x0, (a2)
|
||
|
|
||
|
2:
|
||
|
# Set up breakpoint to trap on M-mode stores.
|
||
|
li TESTNUM, 6
|
||
|
li a0, (2 << (__riscv_xlen - 4)) | MCONTROL_M | MCONTROL_STORE
|
||
|
csrw tdata1, a0
|
||
|
# Skip if breakpoint type is unsupported.
|
||
|
csrr a1, tdata1
|
||
|
bne a0, a1, 2f
|
||
|
|
||
|
# Trap handler should skip this instruction.
|
||
|
sw a2, (a2)
|
||
|
|
||
|
# Make sure store didn't succeed.
|
||
|
li TESTNUM, 7
|
||
|
lw a2, (a2)
|
||
|
bnez a2, fail
|
||
|
|
||
|
# Try to set up a second breakpoint.
|
||
|
li a0, 1
|
||
|
csrw tselect, a0
|
||
|
csrr a1, tselect
|
||
|
bne a0, a1, pass
|
||
|
|
||
|
li a0, (2 << (__riscv_xlen - 4)) | MCONTROL_M | MCONTROL_LOAD
|
||
|
csrw tdata1, a0
|
||
|
la a3, data2
|
||
|
csrw tdata2, a3
|
||
|
|
||
|
# Make sure the second breakpoint triggers.
|
||
|
li TESTNUM, 8
|
||
|
lw a3, (a3)
|
||
|
beqz a3, fail
|
||
|
|
||
|
# Make sure the first breakpoint still triggers.
|
||
|
li TESTNUM, 10
|
||
|
la a2, data1
|
||
|
sw a2, (a2)
|
||
|
li TESTNUM, 11
|
||
|
lw a2, (a2)
|
||
|
bnez a2, fail
|
||
|
|
||
|
2:
|
||
|
TEST_PASSFAIL
|
||
|
|
||
|
.align 2
|
||
|
.global mtvec_handler
|
||
|
mtvec_handler:
|
||
|
# Only even-numbered tests should trap.
|
||
|
andi t0, TESTNUM, 1
|
||
|
bnez t0, fail
|
||
|
|
||
|
li t0, CAUSE_BREAKPOINT
|
||
|
csrr t1, mcause
|
||
|
bne t0, t1, fail
|
||
|
|
||
|
csrr t0, mepc
|
||
|
addi t0, t0, 4
|
||
|
csrw mepc, t0
|
||
|
mret
|
||
|
|
||
|
RVTEST_CODE_END
|
||
|
|
||
|
.data
|
||
|
RVTEST_DATA_BEGIN
|
||
|
|
||
|
TEST_DATA
|
||
|
|
||
|
data1: .word 0
|
||
|
data2: .word 0
|
||
|
|
||
|
RVTEST_DATA_END
|