Remove FSF address from GPL notices
[openocd.git] / src / target / nds32_v2.c
1 /***************************************************************************
2 * Copyright (C) 2013 Andes Technology *
3 * Hsiangkai Wang <hkwang@andestech.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <helper/time_support.h>
24 #include <helper/binarybuffer.h>
25 #include "breakpoints.h"
26 #include "nds32_insn.h"
27 #include "nds32_reg.h"
28 #include "nds32_edm.h"
29 #include "nds32_cmd.h"
30 #include "nds32_v2.h"
31 #include "nds32_aice.h"
32 #include "target_type.h"
33
34 static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no)
35 {
36 uint32_t max_level = nds32->max_interrupt_level;
37 uint32_t cur_level = nds32->current_interrupt_level;
38
39 if ((1 <= cur_level) && (cur_level < max_level)) {
40 if (IR0 == reg_no) {
41 LOG_DEBUG("Map PSW to IPSW");
42 return IR1;
43 } else if (PC == reg_no) {
44 LOG_DEBUG("Map PC to IPC");
45 return IR9;
46 }
47 } else if ((2 <= cur_level) && (cur_level < max_level)) {
48 if (R26 == reg_no) {
49 LOG_DEBUG("Mapping P0 to P_P0");
50 return IR12;
51 } else if (R27 == reg_no) {
52 LOG_DEBUG("Mapping P1 to P_P1");
53 return IR13;
54 } else if (IR1 == reg_no) {
55 LOG_DEBUG("Mapping IPSW to P_IPSW");
56 return IR2;
57 } else if (IR4 == reg_no) {
58 LOG_DEBUG("Mapping EVA to P_EVA");
59 return IR5;
60 } else if (IR6 == reg_no) {
61 LOG_DEBUG("Mapping ITYPE to P_ITYPE");
62 return IR7;
63 } else if (IR9 == reg_no) {
64 LOG_DEBUG("Mapping IPC to P_IPC");
65 return IR10;
66 }
67 } else if (cur_level == max_level) {
68 if (PC == reg_no) {
69 LOG_DEBUG("Mapping PC to O_IPC");
70 return IR11;
71 }
72 }
73
74 return reg_no;
75 }
76
77 static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
78 {
79 uint32_t val_itype;
80 struct aice_port_s *aice = target_to_aice(nds32->target);
81
82 aice_read_register(aice, IR6, &val_itype);
83
84 *reason = val_itype & 0x0F;
85
86 return ERROR_OK;
87 }
88
89 static int nds32_v2_activate_hardware_breakpoint(struct target *target)
90 {
91 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
92 struct aice_port_s *aice = target_to_aice(target);
93 struct breakpoint *bp;
94 int32_t hbr_index = 0;
95
96 for (bp = target->breakpoints; bp; bp = bp->next) {
97 if (bp->type == BKPT_SOFT) {
98 /* already set at nds32_v2_add_breakpoint() */
99 continue;
100 } else if (bp->type == BKPT_HARD) {
101 /* set address */
102 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
103 /* set mask */
104 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
105 /* set value */
106 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
107
108 if (nds32_v2->nds32.memory.address_translation)
109 /* enable breakpoint (virtual address) */
110 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
111 else
112 /* enable breakpoint (physical address) */
113 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
114
115 LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index,
116 bp->address);
117
118 hbr_index++;
119 } else {
120 return ERROR_FAIL;
121 }
122 }
123
124 return ERROR_OK;
125 }
126
127 static int nds32_v2_deactivate_hardware_breakpoint(struct target *target)
128 {
129 struct aice_port_s *aice = target_to_aice(target);
130 struct breakpoint *bp;
131 int32_t hbr_index = 0;
132
133 for (bp = target->breakpoints; bp; bp = bp->next) {
134 if (bp->type == BKPT_SOFT)
135 continue;
136 else if (bp->type == BKPT_HARD)
137 /* disable breakpoint */
138 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
139 else
140 return ERROR_FAIL;
141
142 LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index,
143 bp->address);
144
145 hbr_index++;
146 }
147
148 return ERROR_OK;
149 }
150
151 static int nds32_v2_activate_hardware_watchpoint(struct target *target)
152 {
153 struct aice_port_s *aice = target_to_aice(target);
154 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
155 struct watchpoint *wp;
156 int32_t wp_num = nds32_v2->next_hbr_index;
157 uint32_t wp_config = 0;
158
159 for (wp = target->watchpoints; wp; wp = wp->next) {
160
161 wp_num--;
162 wp->mask = wp->length - 1;
163 if ((wp->address % wp->length) != 0)
164 wp->mask = (wp->mask << 1) + 1;
165
166 if (wp->rw == WPT_READ)
167 wp_config = 0x3;
168 else if (wp->rw == WPT_WRITE)
169 wp_config = 0x5;
170 else if (wp->rw == WPT_ACCESS)
171 wp_config = 0x7;
172
173 /* set/unset physical address bit of BPCn according to PSW.DT */
174 if (nds32_v2->nds32.memory.address_translation == false)
175 wp_config |= 0x8;
176
177 /* set address */
178 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
179 wp->address - (wp->address % wp->length));
180 /* set mask */
181 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
182 /* enable watchpoint */
183 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
184 /* set value */
185 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
186
187 LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num,
188 wp->address, wp->mask);
189
190 }
191
192 return ERROR_OK;
193 }
194
195 static int nds32_v2_deactivate_hardware_watchpoint(struct target *target)
196 {
197 struct aice_port_s *aice = target_to_aice(target);
198 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
199 int32_t wp_num = nds32_v2->next_hbr_index;
200 struct watchpoint *wp;
201
202 for (wp = target->watchpoints; wp; wp = wp->next) {
203 wp_num--;
204 /* disable watchpoint */
205 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
206
207 LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32,
208 wp_num, wp->address, wp->mask);
209 }
210
211 return ERROR_OK;
212 }
213
214 static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2)
215 {
216 struct nds32 *nds32 = &(nds32_v2->nds32);
217 struct aice_port_s *aice = target_to_aice(nds32->target);
218 uint32_t val_ir0;
219 uint32_t val_ir1;
220 uint32_t val_ir2;
221 uint32_t modified_psw;
222
223 /* Save interrupt level */
224 aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */
225
226 /* backup $IR0 */
227 nds32_v2->backup_ir0 = val_ir0;
228
229 nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
230
231 if (nds32_reach_max_interrupt_level(nds32)) {
232 LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
233 nds32->current_interrupt_level);
234
235 /* decrease interrupt level */
236 modified_psw = val_ir0 - 0x2;
237
238 /* disable GIE, IT, DT, HSS */
239 modified_psw &= (~0x8C1);
240
241 aice_write_register(aice, IR0, modified_psw);
242
243 return ERROR_OK;
244 }
245
246 /* There is a case that single step also trigger another interrupt,
247 then HSS bit in psw(ir0) will push to ipsw(ir1).
248 Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2
249 Therefore, HSS bit in p_ipsw(ir2) also need clear.
250
251 Only update $ir2 as current interrupt level is 2, because $ir2 will be random
252 value if the target never reaches interrupt level 2. */
253 if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) {
254 aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */
255 val_ir2 &= ~(0x01 << 11);
256 aice_write_register(aice, IR2, val_ir2);
257 }
258
259 /* get origianl DT bit and set to current state let debugger has same memory view
260 PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */
261 aice_read_register(aice, IR1, &val_ir1);
262 modified_psw = val_ir0 | (val_ir1 & 0x80);
263 aice_write_register(aice, IR0, modified_psw);
264
265 return ERROR_OK;
266 }
267
268 static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2)
269 {
270 struct nds32 *nds32 = &(nds32_v2->nds32);
271 struct aice_port_s *aice = target_to_aice(nds32->target);
272
273 /* restore origin $IR0 */
274 aice_write_register(aice, IR0, nds32_v2->backup_ir0);
275
276 return ERROR_OK;
277 }
278
279 /**
280 * Save processor state. This is called after a HALT instruction
281 * succeeds, and on other occasions the processor enters debug mode
282 * (breakpoint, watchpoint, etc).
283 */
284 static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
285 {
286 LOG_DEBUG("nds32_v2_debug_entry");
287
288 if (nds32->virtual_hosting)
289 LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported "
290 "under V1/V2 architecture. -->");
291
292 enum target_state backup_state = nds32->target->state;
293 nds32->target->state = TARGET_HALTED;
294
295 if (nds32->init_arch_info_after_halted == false) {
296 /* init architecture info according to config registers */
297 CHECK_RETVAL(nds32_config(nds32));
298
299 nds32->init_arch_info_after_halted = true;
300 }
301
302 /* REVISIT entire cache should already be invalid !!! */
303 register_cache_invalidate(nds32->core_cache);
304
305 /* deactivate all hardware breakpoints */
306 CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target));
307
308 if (enable_watchpoint)
309 CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target));
310
311 if (ERROR_OK != nds32_examine_debug_reason(nds32)) {
312 nds32->target->state = backup_state;
313
314 /* re-activate all hardware breakpoints & watchpoints */
315 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
316
317 if (enable_watchpoint) {
318 /* activate all watchpoints */
319 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
320 }
321
322 return ERROR_FAIL;
323 }
324
325 /* check interrupt level before .full_context(), because
326 * get_mapped_reg() in nds32_full_context() needs current_interrupt_level
327 * information */
328 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
329 nds32_v2_check_interrupt_stack(nds32_v2);
330
331 /* Save registers. */
332 nds32_full_context(nds32);
333
334 return ERROR_OK;
335 }
336
337 /* target request support */
338 static int nds32_v2_target_request_data(struct target *target,
339 uint32_t size, uint8_t *buffer)
340 {
341 /* AndesCore could use DTR register to communicate with OpenOCD
342 * to output messages
343 * Target data will be put in buffer
344 * The format of DTR is as follow
345 * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
346 * target_req_cmd has three possible values:
347 * TARGET_REQ_TRACEMSG
348 * TARGET_REQ_DEBUGMSG
349 * TARGET_REQ_DEBUGCHAR
350 * if size == 0, target will call target_asciimsg(),
351 * else call target_hexmsg()
352 */
353 LOG_WARNING("Not implemented: %s", __func__);
354
355 return ERROR_OK;
356 }
357
358 /**
359 * Restore processor state.
360 */
361 static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
362 {
363 LOG_DEBUG("nds32_v2_leave_debug_state");
364
365 struct target *target = nds32->target;
366
367 /* activate all hardware breakpoints */
368 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
369
370 if (enable_watchpoint) {
371 /* activate all watchpoints */
372 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
373 }
374
375 /* restore interrupt stack */
376 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
377 nds32_v2_restore_interrupt_stack(nds32_v2);
378
379 /* restore PSW, PC, and R0 ... after flushing any modified
380 * registers.
381 */
382 CHECK_RETVAL(nds32_restore_context(target));
383
384 register_cache_invalidate(nds32->core_cache);
385
386 return ERROR_OK;
387 }
388
389 static int nds32_v2_deassert_reset(struct target *target)
390 {
391 int retval;
392
393 CHECK_RETVAL(nds32_poll(target));
394
395 if (target->state != TARGET_HALTED) {
396 /* reset only */
397 LOG_WARNING("%s: ran after reset and before halt ...",
398 target_name(target));
399 retval = target_halt(target);
400 if (retval != ERROR_OK)
401 return retval;
402 }
403
404 return ERROR_OK;
405 }
406
407 static int nds32_v2_checksum_memory(struct target *target,
408 uint32_t address, uint32_t count, uint32_t *checksum)
409 {
410 LOG_WARNING("Not implemented: %s", __func__);
411
412 return ERROR_FAIL;
413 }
414
415 static int nds32_v2_add_breakpoint(struct target *target,
416 struct breakpoint *breakpoint)
417 {
418 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
419 struct nds32 *nds32 = &(nds32_v2->nds32);
420 int result;
421
422 if (breakpoint->type == BKPT_HARD) {
423 /* check hardware resource */
424 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
425 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
426 "breakpoints/watchpoints! The limit of "
427 "combined hardware breakpoints/watchpoints "
428 "is %" PRId32 ". -->", nds32_v2->n_hbr);
429 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
430 }
431
432 /* update next place to put hardware breakpoint */
433 nds32_v2->next_hbr_index++;
434
435 /* hardware breakpoint insertion occurs before 'continue' actually */
436 return ERROR_OK;
437 } else if (breakpoint->type == BKPT_SOFT) {
438 result = nds32_add_software_breakpoint(target, breakpoint);
439 if (ERROR_OK != result) {
440 /* auto convert to hardware breakpoint if failed */
441 if (nds32->auto_convert_hw_bp) {
442 /* convert to hardware breakpoint */
443 breakpoint->type = BKPT_HARD;
444
445 return nds32_v2_add_breakpoint(target, breakpoint);
446 }
447 }
448
449 return result;
450 } else /* unrecognized breakpoint type */
451 return ERROR_FAIL;
452
453 return ERROR_OK;
454 }
455
456 static int nds32_v2_remove_breakpoint(struct target *target,
457 struct breakpoint *breakpoint)
458 {
459 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
460
461 if (breakpoint->type == BKPT_HARD) {
462 if (nds32_v2->next_hbr_index <= 0)
463 return ERROR_FAIL;
464
465 /* update next place to put hardware breakpoint */
466 nds32_v2->next_hbr_index--;
467
468 /* hardware breakpoint removal occurs after 'halted' actually */
469 return ERROR_OK;
470 } else if (breakpoint->type == BKPT_SOFT) {
471 return nds32_remove_software_breakpoint(target, breakpoint);
472 } else /* unrecognized breakpoint type */
473 return ERROR_FAIL;
474
475 return ERROR_OK;
476 }
477
478 static int nds32_v2_add_watchpoint(struct target *target,
479 struct watchpoint *watchpoint)
480 {
481 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
482
483 /* check hardware resource */
484 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
485 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
486 "breakpoints/watchpoints! The limit of "
487 "combined hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v2->n_hbr);
488 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
489 }
490
491 /* update next place to put hardware watchpoint */
492 nds32_v2->next_hbr_index++;
493
494 return ERROR_OK;
495 }
496
497 static int nds32_v2_remove_watchpoint(struct target *target,
498 struct watchpoint *watchpoint)
499 {
500 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
501
502 if (nds32_v2->next_hbr_index <= 0)
503 return ERROR_FAIL;
504
505 /* update next place to put hardware breakpoint */
506 nds32_v2->next_hbr_index--;
507
508 return ERROR_OK;
509 }
510
511 static int nds32_v2_get_exception_address(struct nds32 *nds32,
512 uint32_t *address, uint32_t reason)
513 {
514 struct aice_port_s *aice = target_to_aice(nds32->target);
515
516 aice_read_register(aice, IR4, address); /* read $EVA directly */
517
518 /* TODO: hit multiple watchpoints */
519
520 return ERROR_OK;
521 }
522
523 /**
524 * find out which watchpoint hits
525 * get exception address and compare the address to watchpoints
526 */
527 static int nds32_v2_hit_watchpoint(struct target *target,
528 struct watchpoint **hit_watchpoint)
529 {
530 uint32_t exception_address;
531 struct watchpoint *wp;
532 static struct watchpoint scan_all_watchpoint;
533 struct nds32 *nds32 = target_to_nds32(target);
534
535 scan_all_watchpoint.address = 0;
536 scan_all_watchpoint.rw = WPT_WRITE;
537 scan_all_watchpoint.next = 0;
538 scan_all_watchpoint.unique_id = 0x5CA8;
539
540 exception_address = nds32->watched_address;
541
542 if (exception_address == 0) {
543 /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
544 *hit_watchpoint = &scan_all_watchpoint;
545 return ERROR_OK;
546 }
547
548 for (wp = target->watchpoints; wp; wp = wp->next) {
549 if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
550 /* TODO: dispel false match */
551 *hit_watchpoint = wp;
552 return ERROR_OK;
553 }
554 }
555
556 return ERROR_FAIL;
557 }
558
559 static int nds32_v2_run_algorithm(struct target *target,
560 int num_mem_params,
561 struct mem_param *mem_params,
562 int num_reg_params,
563 struct reg_param *reg_params,
564 uint32_t entry_point,
565 uint32_t exit_point,
566 int timeout_ms,
567 void *arch_info)
568 {
569 LOG_WARNING("Not implemented: %s", __func__);
570
571 return ERROR_FAIL;
572 }
573
574 static int nds32_v2_target_create(struct target *target, Jim_Interp *interp)
575 {
576 struct nds32_v2_common *nds32_v2;
577
578 nds32_v2 = calloc(1, sizeof(*nds32_v2));
579 if (!nds32_v2)
580 return ERROR_FAIL;
581
582 nds32_v2->nds32.register_map = nds32_v2_register_mapping;
583 nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason;
584 nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry;
585 nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state;
586 nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address;
587
588 nds32_init_arch_info(target, &(nds32_v2->nds32));
589
590 return ERROR_OK;
591 }
592
593 static int nds32_v2_init_target(struct command_context *cmd_ctx,
594 struct target *target)
595 {
596 /* Initialize anything we can set up without talking to the target */
597
598 struct nds32 *nds32 = target_to_nds32(target);
599
600 nds32_init(nds32);
601
602 return ERROR_OK;
603 }
604
605 /* talk to the target and set things up */
606 static int nds32_v2_examine(struct target *target)
607 {
608 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
609 struct nds32 *nds32 = &(nds32_v2->nds32);
610 struct aice_port_s *aice = target_to_aice(target);
611
612 if (!target_was_examined(target)) {
613 CHECK_RETVAL(nds32_edm_config(nds32));
614
615 if (nds32->reset_halt_as_examine)
616 CHECK_RETVAL(nds32_reset_halt(nds32));
617 }
618
619 uint32_t edm_cfg;
620 aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
621
622 /* get the number of hardware breakpoints */
623 nds32_v2->n_hbr = (edm_cfg & 0x7) + 1;
624
625 nds32_v2->next_hbr_index = 0;
626
627 LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
628 nds32_v2->n_hbr);
629
630 nds32->target->state = TARGET_RUNNING;
631 nds32->target->debug_reason = DBG_REASON_NOTHALTED;
632
633 target_set_examined(target);
634
635 return ERROR_OK;
636 }
637
638 static int nds32_v2_translate_address(struct target *target, uint32_t *address)
639 {
640 struct nds32 *nds32 = target_to_nds32(target);
641 struct nds32_memory *memory = &(nds32->memory);
642 uint32_t physical_address;
643
644 /* Following conditions need to do address translation
645 * 1. BUS mode
646 * 2. CPU mode under maximum interrupt level */
647 if ((NDS_MEMORY_ACC_BUS == memory->access_channel) ||
648 ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
649 nds32_reach_max_interrupt_level(nds32))) {
650 if (ERROR_OK == target->type->virt2phys(target, *address, &physical_address))
651 *address = physical_address;
652 else
653 return ERROR_FAIL;
654 }
655
656 return ERROR_OK;
657 }
658
659 static int nds32_v2_read_buffer(struct target *target, uint32_t address,
660 uint32_t size, uint8_t *buffer)
661 {
662 struct nds32 *nds32 = target_to_nds32(target);
663 struct nds32_memory *memory = &(nds32->memory);
664
665 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
666 (target->state != TARGET_HALTED)) {
667 LOG_WARNING("target was not halted");
668 return ERROR_TARGET_NOT_HALTED;
669 }
670
671 /* BUG: If access range crosses multiple pages, the translation will not correct
672 * for second page or so. */
673
674 nds32_v2_translate_address(target, &address);
675
676 return nds32_read_buffer(target, address, size, buffer);
677 }
678
679 static int nds32_v2_write_buffer(struct target *target, uint32_t address,
680 uint32_t size, const uint8_t *buffer)
681 {
682 struct nds32 *nds32 = target_to_nds32(target);
683 struct nds32_memory *memory = &(nds32->memory);
684
685 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
686 (target->state != TARGET_HALTED)) {
687 LOG_WARNING("target was not halted");
688 return ERROR_TARGET_NOT_HALTED;
689 }
690
691 /* BUG: If access range crosses multiple pages, the translation will not correct
692 * for second page or so. */
693
694 nds32_v2_translate_address(target, &address);
695
696 return nds32_write_buffer(target, address, size, buffer);
697 }
698
699 static int nds32_v2_read_memory(struct target *target, uint32_t address,
700 uint32_t size, uint32_t count, uint8_t *buffer)
701 {
702 struct nds32 *nds32 = target_to_nds32(target);
703 struct nds32_memory *memory = &(nds32->memory);
704
705 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
706 (target->state != TARGET_HALTED)) {
707 LOG_WARNING("target was not halted");
708 return ERROR_TARGET_NOT_HALTED;
709 }
710
711 /* BUG: If access range crosses multiple pages, the translation will not correct
712 * for second page or so. */
713
714 nds32_v2_translate_address(target, &address);
715
716 return nds32_read_memory(target, address, size, count, buffer);
717 }
718
719 static int nds32_v2_write_memory(struct target *target, uint32_t address,
720 uint32_t size, uint32_t count, const uint8_t *buffer)
721 {
722 struct nds32 *nds32 = target_to_nds32(target);
723 struct nds32_memory *memory = &(nds32->memory);
724
725 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
726 (target->state != TARGET_HALTED)) {
727 LOG_WARNING("target was not halted");
728 return ERROR_TARGET_NOT_HALTED;
729 }
730
731 /* BUG: If access range crosses multiple pages, the translation will not correct
732 * for second page or so. */
733
734 nds32_v2_translate_address(target, &address);
735
736 return nds32_write_memory(target, address, size, count, buffer);
737 }
738
739 /** Holds methods for V2 targets. */
740 struct target_type nds32_v2_target = {
741 .name = "nds32_v2",
742
743 .poll = nds32_poll,
744 .arch_state = nds32_arch_state,
745
746 .target_request_data = nds32_v2_target_request_data,
747
748 .halt = nds32_halt,
749 .resume = nds32_resume,
750 .step = nds32_step,
751
752 .assert_reset = nds32_assert_reset,
753 .deassert_reset = nds32_v2_deassert_reset,
754
755 /* register access */
756 .get_gdb_reg_list = nds32_get_gdb_reg_list,
757
758 /* memory access */
759 .read_buffer = nds32_v2_read_buffer,
760 .write_buffer = nds32_v2_write_buffer,
761 .read_memory = nds32_v2_read_memory,
762 .write_memory = nds32_v2_write_memory,
763
764 .checksum_memory = nds32_v2_checksum_memory,
765
766 /* breakpoint/watchpoint */
767 .add_breakpoint = nds32_v2_add_breakpoint,
768 .remove_breakpoint = nds32_v2_remove_breakpoint,
769 .add_watchpoint = nds32_v2_add_watchpoint,
770 .remove_watchpoint = nds32_v2_remove_watchpoint,
771 .hit_watchpoint = nds32_v2_hit_watchpoint,
772
773 /* MMU */
774 .mmu = nds32_mmu,
775 .virt2phys = nds32_virtual_to_physical,
776 .read_phys_memory = nds32_read_phys_memory,
777 .write_phys_memory = nds32_write_phys_memory,
778
779 .run_algorithm = nds32_v2_run_algorithm,
780
781 .commands = nds32_command_handlers,
782 .target_create = nds32_v2_target_create,
783 .init_target = nds32_v2_init_target,
784 .examine = nds32_v2_examine,
785 };