8e2ce5dbd524881e4ecb3b5856b312e84a517976
[fw/openocd] / src / target / riscv / program.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #include "target/target.h"
8 #include "target/register.h"
9 #include "riscv.h"
10 #include "program.h"
11 #include "helper/log.h"
12
13 #include "asm.h"
14 #include "encoding.h"
15
16 /* Program interface. */
17 int riscv_program_init(struct riscv_program *p, struct target *target)
18 {
19         memset(p, 0, sizeof(*p));
20         p->target = target;
21         p->instruction_count = 0;
22         p->target_xlen = riscv_xlen(target);
23         for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i)
24                 p->writes_xreg[i] = 0;
25
26         for (size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i)
27                 p->debug_buffer[i] = -1;
28
29         return ERROR_OK;
30 }
31
32 int riscv_program_write(struct riscv_program *program)
33 {
34         for (unsigned i = 0; i < program->instruction_count; ++i) {
35                 LOG_DEBUG("debug_buffer[%02x] = DASM(0x%08x)", i, program->debug_buffer[i]);
36                 if (riscv_write_debug_buffer(program->target, i,
37                                         program->debug_buffer[i]) != ERROR_OK)
38                         return ERROR_FAIL;
39         }
40         return ERROR_OK;
41 }
42
43 /** Add ebreak and execute the program. */
44 int riscv_program_exec(struct riscv_program *p, struct target *t)
45 {
46         keep_alive();
47
48         riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1];
49         for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) {
50                 if (p->writes_xreg[i]) {
51                         LOG_DEBUG("Saving register %d as used by program", (int)i);
52                         int result = riscv_get_register(t, &saved_registers[i], i);
53                         if (result != ERROR_OK)
54                                 return result;
55                 }
56         }
57
58         if (riscv_program_ebreak(p) != ERROR_OK) {
59                 LOG_ERROR("Unable to write ebreak");
60                 for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
61                         LOG_ERROR("ram[%02x]: DASM(0x%08" PRIx32 ") [0x%08" PRIx32 "]",
62                                         (int)i, p->debug_buffer[i], p->debug_buffer[i]);
63                 return ERROR_FAIL;
64         }
65
66         if (riscv_program_write(p) != ERROR_OK)
67                 return ERROR_FAIL;
68
69         if (riscv_execute_debug_buffer(t) != ERROR_OK) {
70                 LOG_DEBUG("Unable to execute program %p", p);
71                 return ERROR_FAIL;
72         }
73
74         for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
75                 if (i >= riscv_debug_buffer_size(p->target))
76                         p->debug_buffer[i] = riscv_read_debug_buffer(t, i);
77
78         for (size_t i = GDB_REGNO_ZERO; i <= GDB_REGNO_XPR31; ++i)
79                 if (p->writes_xreg[i])
80                         riscv_set_register(t, i, saved_registers[i]);
81
82         return ERROR_OK;
83 }
84
85 int riscv_program_sdr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
86 {
87         return riscv_program_insert(p, sd(d, b, offset));
88 }
89
90 int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
91 {
92         return riscv_program_insert(p, sw(d, b, offset));
93 }
94
95 int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
96 {
97         return riscv_program_insert(p, sh(d, b, offset));
98 }
99
100 int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
101 {
102         return riscv_program_insert(p, sb(d, b, offset));
103 }
104
105 int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
106 {
107         return riscv_program_insert(p, ld(d, b, offset));
108 }
109
110 int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
111 {
112         return riscv_program_insert(p, lw(d, b, offset));
113 }
114
115 int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
116 {
117         return riscv_program_insert(p, lh(d, b, offset));
118 }
119
120 int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
121 {
122         return riscv_program_insert(p, lb(d, b, offset));
123 }
124
125 int riscv_program_csrrsi(struct riscv_program *p, enum gdb_regno d, unsigned int z, enum gdb_regno csr)
126 {
127         assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
128         return riscv_program_insert(p, csrrsi(d, z, csr - GDB_REGNO_CSR0));
129 }
130
131 int riscv_program_csrrci(struct riscv_program *p, enum gdb_regno d, unsigned int z, enum gdb_regno csr)
132 {
133         assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
134         return riscv_program_insert(p, csrrci(d, z, csr - GDB_REGNO_CSR0));
135 }
136
137 int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr)
138 {
139         assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
140         return riscv_program_insert(p, csrrs(d, GDB_REGNO_ZERO, csr - GDB_REGNO_CSR0));
141 }
142
143 int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr)
144 {
145         assert(csr >= GDB_REGNO_CSR0);
146         return riscv_program_insert(p, csrrw(GDB_REGNO_ZERO, s, csr - GDB_REGNO_CSR0));
147 }
148
149 int riscv_program_fence_i(struct riscv_program *p)
150 {
151         return riscv_program_insert(p, fence_i());
152 }
153
154 int riscv_program_fence(struct riscv_program *p)
155 {
156         return riscv_program_insert(p, fence());
157 }
158
159 int riscv_program_ebreak(struct riscv_program *p)
160 {
161         struct target *target = p->target;
162         RISCV_INFO(r);
163         if (p->instruction_count == riscv_debug_buffer_size(p->target) &&
164                         r->impebreak) {
165                 return ERROR_OK;
166         }
167         return riscv_program_insert(p, ebreak());
168 }
169
170 int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t u)
171 {
172         return riscv_program_insert(p, addi(d, s, u));
173 }
174
175 int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
176 {
177         if (p->instruction_count >= riscv_debug_buffer_size(p->target)) {
178                 LOG_ERROR("Unable to insert instruction:");
179                 LOG_ERROR("  instruction_count=%d", (int)p->instruction_count);
180                 LOG_ERROR("  buffer size      =%d", (int)riscv_debug_buffer_size(p->target));
181                 return ERROR_FAIL;
182         }
183
184         p->debug_buffer[p->instruction_count] = i;
185         p->instruction_count++;
186         return ERROR_OK;
187 }