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