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