49a5758f70904dd7de347f06e53e4e1ce0c74da2
[fw/openocd] / 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 ((cur_level >= 1) && (cur_level < max_level)) {
40                 if (reg_no == IR0) {
41                         LOG_DEBUG("Map PSW to IPSW");
42                         return IR1;
43                 } else if (reg_no == PC) {
44                         LOG_DEBUG("Map PC to IPC");
45                         return IR9;
46                 }
47         } else if ((cur_level >= 2) && (cur_level < max_level)) {
48                 if (reg_no == R26) {
49                         LOG_DEBUG("Mapping P0 to P_P0");
50                         return IR12;
51                 } else if (reg_no == R27) {
52                         LOG_DEBUG("Mapping P1 to P_P1");
53                         return IR13;
54                 } else if (reg_no == IR1) {
55                         LOG_DEBUG("Mapping IPSW to P_IPSW");
56                         return IR2;
57                 } else if (reg_no == IR4) {
58                         LOG_DEBUG("Mapping EVA to P_EVA");
59                         return IR5;
60                 } else if (reg_no == IR6) {
61                         LOG_DEBUG("Mapping ITYPE to P_ITYPE");
62                         return IR7;
63                 } else if (reg_no == IR9) {
64                         LOG_DEBUG("Mapping IPC to P_IPC");
65                         return IR10;
66                 }
67         } else if (cur_level == max_level) {
68                 if (reg_no == PC) {
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" TARGET_PRIxADDR, 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" TARGET_PRIxADDR, 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 watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " 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 watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " 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 original 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 (nds32_examine_debug_reason(nds32) != ERROR_OK) {
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                 target_addr_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 (result != ERROR_OK) {
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                 target_addr_t entry_point,
565                 target_addr_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, target_addr_t *address)
639 {
640         struct nds32 *nds32 = target_to_nds32(target);
641         struct nds32_memory *memory = &(nds32->memory);
642         target_addr_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 ((memory->access_channel == NDS_MEMORY_ACC_BUS) ||
648                         ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
649                          nds32_reach_max_interrupt_level(nds32))) {
650                 if (target->type->virt2phys(target, *address, &physical_address) == ERROR_OK)
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, target_addr_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 ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
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, target_addr_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 ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
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, target_addr_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 ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
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, target_addr_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 ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
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 };