aboutsummaryrefslogtreecommitdiff
path: root/isa/rv64mi/breakpoint.S
blob: 153963a710572ee1d52fdbd322d2ec40b4b0abaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# 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