target_t -> struct target
[openocd.git] / src / target / mips32.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2007,2008 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 ***************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "mips32.h"
30
31
32 char* mips32_core_reg_list[] =
33 {
34 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
35 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
36 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
37 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
38 "status", "lo", "hi", "badvaddr", "cause", "pc"
39 };
40
41 struct mips32_core_reg mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] =
42 {
43 {0, NULL, NULL},
44 {1, NULL, NULL},
45 {2, NULL, NULL},
46 {3, NULL, NULL},
47 {4, NULL, NULL},
48 {5, NULL, NULL},
49 {6, NULL, NULL},
50 {7, NULL, NULL},
51 {8, NULL, NULL},
52 {9, NULL, NULL},
53 {10, NULL, NULL},
54 {11, NULL, NULL},
55 {12, NULL, NULL},
56 {13, NULL, NULL},
57 {14, NULL, NULL},
58 {15, NULL, NULL},
59 {16, NULL, NULL},
60 {17, NULL, NULL},
61 {18, NULL, NULL},
62 {19, NULL, NULL},
63 {20, NULL, NULL},
64 {21, NULL, NULL},
65 {22, NULL, NULL},
66 {23, NULL, NULL},
67 {24, NULL, NULL},
68 {25, NULL, NULL},
69 {26, NULL, NULL},
70 {27, NULL, NULL},
71 {28, NULL, NULL},
72 {29, NULL, NULL},
73 {30, NULL, NULL},
74 {31, NULL, NULL},
75
76 {32, NULL, NULL},
77 {33, NULL, NULL},
78 {34, NULL, NULL},
79 {35, NULL, NULL},
80 {36, NULL, NULL},
81 {37, NULL, NULL},
82 };
83
84 /* number of mips dummy fp regs fp0 - fp31 + fsr and fir
85 * we also add 18 unknown registers to handle gdb requests */
86
87 #define MIPS32NUMFPREGS 34 + 18
88
89 uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
90
91 struct reg mips32_gdb_dummy_fp_reg =
92 {
93 "GDB dummy floating-point register", mips32_gdb_dummy_fp_value, 0, 1, 32, NULL, 0, NULL, 0
94 };
95
96 int mips32_core_reg_arch_type = -1;
97
98 int mips32_get_core_reg(struct reg *reg)
99 {
100 int retval;
101 struct mips32_core_reg *mips32_reg = reg->arch_info;
102 struct target *target = mips32_reg->target;
103 struct mips32_common *mips32_target = target->arch_info;
104
105 if (target->state != TARGET_HALTED)
106 {
107 return ERROR_TARGET_NOT_HALTED;
108 }
109
110 retval = mips32_target->read_core_reg(target, mips32_reg->num);
111
112 return retval;
113 }
114
115 int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
116 {
117 struct mips32_core_reg *mips32_reg = reg->arch_info;
118 struct target *target = mips32_reg->target;
119 uint32_t value = buf_get_u32(buf, 0, 32);
120
121 if (target->state != TARGET_HALTED)
122 {
123 return ERROR_TARGET_NOT_HALTED;
124 }
125
126 buf_set_u32(reg->value, 0, 32, value);
127 reg->dirty = 1;
128 reg->valid = 1;
129
130 return ERROR_OK;
131 }
132
133 int mips32_read_core_reg(struct target *target, int num)
134 {
135 uint32_t reg_value;
136 struct mips32_core_reg *mips_core_reg;
137
138 /* get pointers to arch-specific information */
139 struct mips32_common *mips32 = target->arch_info;
140
141 if ((num < 0) || (num >= MIPS32NUMCOREREGS))
142 return ERROR_INVALID_ARGUMENTS;
143
144 mips_core_reg = mips32->core_cache->reg_list[num].arch_info;
145 reg_value = mips32->core_regs[num];
146 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
147 mips32->core_cache->reg_list[num].valid = 1;
148 mips32->core_cache->reg_list[num].dirty = 0;
149
150 return ERROR_OK;
151 }
152
153 int mips32_write_core_reg(struct target *target, int num)
154 {
155 uint32_t reg_value;
156 struct mips32_core_reg *mips_core_reg;
157
158 /* get pointers to arch-specific information */
159 struct mips32_common *mips32 = target->arch_info;
160
161 if ((num < 0) || (num >= MIPS32NUMCOREREGS))
162 return ERROR_INVALID_ARGUMENTS;
163
164 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
165 mips_core_reg = mips32->core_cache->reg_list[num].arch_info;
166 mips32->core_regs[num] = reg_value;
167 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
168 mips32->core_cache->reg_list[num].valid = 1;
169 mips32->core_cache->reg_list[num].dirty = 0;
170
171 return ERROR_OK;
172 }
173
174 int mips32_invalidate_core_regs(struct target *target)
175 {
176 /* get pointers to arch-specific information */
177 struct mips32_common *mips32 = target->arch_info;
178 int i;
179
180 for (i = 0; i < mips32->core_cache->num_regs; i++)
181 {
182 mips32->core_cache->reg_list[i].valid = 0;
183 mips32->core_cache->reg_list[i].dirty = 0;
184 }
185
186 return ERROR_OK;
187 }
188
189 int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
190 {
191 /* get pointers to arch-specific information */
192 struct mips32_common *mips32 = target->arch_info;
193 int i;
194
195 /* include floating point registers */
196 *reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS;
197 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
198
199 for (i = 0; i < MIPS32NUMCOREREGS; i++)
200 {
201 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
202 }
203
204 /* add dummy floating points regs */
205 for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++)
206 {
207 (*reg_list)[i] = &mips32_gdb_dummy_fp_reg;
208 }
209
210 return ERROR_OK;
211 }
212
213 int mips32_save_context(struct target *target)
214 {
215 int i;
216
217 /* get pointers to arch-specific information */
218 struct mips32_common *mips32 = target->arch_info;
219 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
220
221 /* read core registers */
222 mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
223
224 for (i = 0; i < MIPS32NUMCOREREGS; i++)
225 {
226 if (!mips32->core_cache->reg_list[i].valid)
227 {
228 mips32->read_core_reg(target, i);
229 }
230 }
231
232 return ERROR_OK;
233 }
234
235 int mips32_restore_context(struct target *target)
236 {
237 int i;
238
239 /* get pointers to arch-specific information */
240 struct mips32_common *mips32 = target->arch_info;
241 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
242
243 for (i = 0; i < MIPS32NUMCOREREGS; i++)
244 {
245 if (mips32->core_cache->reg_list[i].dirty)
246 {
247 mips32->write_core_reg(target, i);
248 }
249 }
250
251 /* write core regs */
252 mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
253
254 return ERROR_OK;
255 }
256
257 int mips32_arch_state(struct target *target)
258 {
259 struct mips32_common *mips32 = target->arch_info;
260
261 if (mips32->common_magic != MIPS32_COMMON_MAGIC)
262 {
263 LOG_ERROR("BUG: called for a non-MIPS32 target");
264 exit(-1);
265 }
266
267 LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
268 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name ,
269 buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
270
271 return ERROR_OK;
272 }
273
274 struct reg_cache *mips32_build_reg_cache(struct target *target)
275 {
276 /* get pointers to arch-specific information */
277 struct mips32_common *mips32 = target->arch_info;
278
279 int num_regs = MIPS32NUMCOREREGS;
280 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
281 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
282 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
283 struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
284 int i;
285
286 if (mips32_core_reg_arch_type == -1)
287 mips32_core_reg_arch_type = register_reg_arch_type(mips32_get_core_reg, mips32_set_core_reg);
288
289 register_init_dummy(&mips32_gdb_dummy_fp_reg);
290
291 /* Build the process context cache */
292 cache->name = "mips32 registers";
293 cache->next = NULL;
294 cache->reg_list = reg_list;
295 cache->num_regs = num_regs;
296 (*cache_p) = cache;
297 mips32->core_cache = cache;
298
299 for (i = 0; i < num_regs; i++)
300 {
301 arch_info[i] = mips32_core_reg_list_arch_info[i];
302 arch_info[i].target = target;
303 arch_info[i].mips32_common = mips32;
304 reg_list[i].name = mips32_core_reg_list[i];
305 reg_list[i].size = 32;
306 reg_list[i].value = calloc(1, 4);
307 reg_list[i].dirty = 0;
308 reg_list[i].valid = 0;
309 reg_list[i].bitfield_desc = NULL;
310 reg_list[i].num_bitfields = 0;
311 reg_list[i].arch_type = mips32_core_reg_arch_type;
312 reg_list[i].arch_info = &arch_info[i];
313 }
314
315 return cache;
316 }
317
318 int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
319 {
320 target->arch_info = mips32;
321 mips32->common_magic = MIPS32_COMMON_MAGIC;
322
323 /* has breakpoint/watchpint unit been scanned */
324 mips32->bp_scanned = 0;
325 mips32->data_break_list = NULL;
326
327 mips32->ejtag_info.tap = tap;
328 mips32->read_core_reg = mips32_read_core_reg;
329 mips32->write_core_reg = mips32_write_core_reg;
330
331 return ERROR_OK;
332 }
333
334 int mips32_register_commands(struct command_context_s *cmd_ctx)
335 {
336 return ERROR_OK;
337 }
338
339 int mips32_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
340 {
341 /*TODO*/
342 return ERROR_OK;
343 }
344
345 int mips32_examine(struct target *target)
346 {
347 struct mips32_common *mips32 = target->arch_info;
348
349 if (!target_was_examined(target))
350 {
351 target_set_examined(target);
352
353 /* we will configure later */
354 mips32->bp_scanned = 0;
355 mips32->num_inst_bpoints = 0;
356 mips32->num_data_bpoints = 0;
357 mips32->num_inst_bpoints_avail = 0;
358 mips32->num_data_bpoints_avail = 0;
359 }
360
361 return ERROR_OK;
362 }
363
364 int mips32_configure_break_unit(struct target *target)
365 {
366 /* get pointers to arch-specific information */
367 struct mips32_common *mips32 = target->arch_info;
368 int retval;
369 uint32_t dcr, bpinfo;
370 int i;
371
372 if (mips32->bp_scanned)
373 return ERROR_OK;
374
375 /* get info about breakpoint support */
376 if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
377 return retval;
378
379 if (dcr & (1 << 16))
380 {
381 /* get number of inst breakpoints */
382 if ((retval = target_read_u32(target, EJTAG_IBS, &bpinfo)) != ERROR_OK)
383 return retval;
384
385 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
386 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
387 mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator));
388 for (i = 0; i < mips32->num_inst_bpoints; i++)
389 {
390 mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i);
391 }
392
393 /* clear IBIS reg */
394 if ((retval = target_write_u32(target, EJTAG_IBS, 0)) != ERROR_OK)
395 return retval;
396 }
397
398 if (dcr & (1 << 17))
399 {
400 /* get number of data breakpoints */
401 if ((retval = target_read_u32(target, EJTAG_DBS, &bpinfo)) != ERROR_OK)
402 return retval;
403
404 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
405 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
406 mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator));
407 for (i = 0; i < mips32->num_data_bpoints; i++)
408 {
409 mips32->data_break_list[i].reg_address = EJTAG_DBA1 + (0x100 * i);
410 }
411
412 /* clear DBIS reg */
413 if ((retval = target_write_u32(target, EJTAG_DBS, 0)) != ERROR_OK)
414 return retval;
415 }
416
417 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints, mips32->num_data_bpoints);
418
419 mips32->bp_scanned = 1;
420
421 return ERROR_OK;
422 }
423
424 int mips32_enable_interrupts(struct target *target, int enable)
425 {
426 int retval;
427 int update = 0;
428 uint32_t dcr;
429
430 /* read debug control register */
431 if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
432 return retval;
433
434 if (enable)
435 {
436 if (!(dcr & (1 << 4)))
437 {
438 /* enable interrupts */
439 dcr |= (1 << 4);
440 update = 1;
441 }
442 }
443 else
444 {
445 if (dcr & (1 << 4))
446 {
447 /* disable interrupts */
448 dcr &= ~(1 << 4);
449 update = 1;
450 }
451 }
452
453 if (update)
454 {
455 if ((retval = target_write_u32(target, EJTAG_DCR, dcr)) != ERROR_OK)
456 return retval;
457 }
458
459 return ERROR_OK;
460 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)