Abstract register read mostly working.
[riscv-isa-sim.git] / debug_rom / debug_rom.S
1 # This code should be functional. Doesn't have to be optimal.
2 # I'm writing it to prove that it can be done.
3
4 #include "riscv/encoding.h"
5
6 # TODO: Update these constants once they're finalized in the doc.
7
8 #define DEBUG_RAM 0x400
9 #ifndef DEBUG_RAM_SIZE
10 # define DEBUG_RAM_SIZE 64
11 #endif
12
13 #define CLEARDEBINT 0x100
14 #define SETHALTNOT 0x10c
15
16 #if (defined(RV32) + defined(RV64) + defined(RV128)) > 1
17 # define MULTI_XLEN
18 #elif (defined(RV32) + defined(RV64) + defined(RV128)) == 0
19 # error define one or more of RV32, RV64, RV128
20 #endif
21
22 .global entry
23 .global resume
24 .global exception
25
26 # Automatically called when Debug Mode is first entered.
27 entry: j _entry
28 # Should be called by Debug RAM code that has finished execution and
29 # wants to return to Debug Mode.
30 resume:
31 j _resume
32 exception:
33 # Set the last word of Debug RAM to all ones, to indicate that we hit
34 # an exception.
35 li s0, ~0
36 j _resume2
37
38 _resume:
39 li s0, 0
40 _resume2:
41 fence
42
43 # Restore s1.
44 #ifdef MULTI_XLEN
45 csrr s1, CSR_MISA
46 #endif
47
48 #ifdef RV32
49 # ifdef MULTI_XLEN
50 bltz s1, restore_not_32
51 # endif
52
53 restore_32:
54 lw s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
55 # if defined(RV64) || defined(RV128)
56 j finish_restore
57 # endif
58 #endif
59
60 restore_not_32:
61 #if defined(RV64) && defined(RV128)
62 slli s1, s1, 1
63 bltz s1, restore_128
64 #endif
65
66 #ifdef RV64
67 restore_64:
68 ld s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 8)(zero)
69 #endif
70 #if defined(RV64) && defined(RV128)
71 j finish_restore
72 #endif
73 #ifdef RV128
74 restore_128:
75 lq s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
76 #endif
77
78 finish_restore:
79 # s0 contains ~0 if we got here through an exception, and 0 otherwise.
80 # Store this to the last word in Debug RAM so the debugger can tell if
81 # an exception occurred.
82 sw s0, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
83
84 # Clear debug interrupt.
85 csrr s0, CSR_MHARTID
86 sw s0, CLEARDEBINT(zero)
87
88 check_halt:
89 csrr s0, CSR_DCSR
90 andi s0, s0, DCSR_HALT
91 bnez s0, wait_for_interrupt
92
93 exit:
94 # Restore s0.
95 csrr s0, CSR_DSCRATCH
96 dret
97
98 _entry:
99 # Save s0 in DSCRATCH
100 csrw CSR_DSCRATCH, s0
101
102 # Check why we're here
103 csrr s0, CSR_DCSR
104 # cause is in bits 8:6 of dcsr
105 andi s0, s0, DCSR_CAUSE
106 addi s0, s0, -(DCSR_CAUSE_DEBUGINT<<6)
107 bnez s0, spontaneous_halt
108
109 jdebugram:
110 # Save s1 so that the debug program can use two registers.
111 #ifdef MULTI_XLEN
112 csrr s0, CSR_MISA
113 #endif
114
115 #ifdef RV32
116 # ifdef MULTI_XLEN
117 bltz s0, save_not_32
118 # endif
119 save_32:
120 sw s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
121 jr zero, DEBUG_RAM
122 #endif
123
124 save_not_32:
125 #if defined(RV64) && defined(RV128)
126 slli s0, s0, 1
127 bltz s0, save_128
128 #endif
129
130 #ifdef RV64
131 save_64:
132 sd s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 8)(zero)
133 jr zero, DEBUG_RAM
134 #endif
135
136 #ifdef RV128
137 save_128:
138 sq s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
139 jr zero, DEBUG_RAM
140 #endif
141
142 spontaneous_halt:
143 csrr s0, CSR_MHARTID
144 sw s0, SETHALTNOT(zero)
145 csrsi CSR_DCSR, DCSR_HALT
146
147 wait_for_interrupt:
148 csrr s0, CSR_DCSR
149 andi s0, s0, DCSR_DEBUGINT
150 beqz s0, wait_for_interrupt
151
152 j jdebugram