2 * MIPS64 generic target support
4 * Copyright (C) 2014 by Andrey Sidorov <anysidorov@gmail.com>
5 * Copyright (C) 2014 by Aleksey Kuleshov <rndfax@yandex.ru>
6 * Copyright (C) 2014-2019 by Peter Mamonov <pmamonov@gmail.com>
8 * Based on the work of:
9 * Copyright (C) 2008 by Spencer Oliver
10 * Copyright (C) 2008 by David T.L. Wong
12 * SPDX-License-Identifier: GPL-2.0-or-later
19 #if BUILD_TARGET64 == 1
21 #include "breakpoints.h"
24 #include "mips_mips64.h"
25 #include "target_type.h"
28 static int mips_mips64_unset_breakpoint(struct target *target,
29 struct breakpoint *breakpoint);
31 static uint64_t mips64_extend_sign(uint64_t addr)
36 return addr | (ULLONG_MAX << 32);
40 static int mips_mips64_examine_debug_reason(struct target *target)
42 if ((target->debug_reason != DBG_REASON_DBGRQ)
43 && (target->debug_reason != DBG_REASON_SINGLESTEP))
44 target->debug_reason = DBG_REASON_BREAKPOINT;
49 static int mips_mips64_debug_entry(struct target *target)
51 struct mips64_common *mips64 = target->arch_info;
52 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
53 struct reg *pc = &mips64->core_cache->reg_list[MIPS64_PC];
55 mips64_save_context(target);
57 /* make sure stepping disabled, SSt bit in CP0 debug register cleared */
58 mips64_ejtag_config_step(ejtag_info, 0);
60 /* make sure break unit configured */
61 mips64_configure_break_unit(target);
63 /* attempt to find halt reason */
64 mips_mips64_examine_debug_reason(target);
66 LOG_DEBUG("entered debug state at PC 0x%" PRIx64 ", target->state: %s",
67 *(uint64_t *)pc->value, target_state_name(target));
72 static int mips_mips64_poll(struct target *target)
75 struct mips64_common *mips64 = target->arch_info;
76 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
77 uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl;
79 /* read ejtag control reg */
80 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
81 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
83 /* clear this bit before handling polling
84 * as after reset registers will read zero */
85 if (ejtag_ctrl & EJTAG_CTRL_ROCC) {
86 /* we have detected a reset, clear flag
87 * otherwise ejtag will not work */
88 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
90 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
91 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
92 LOG_DEBUG("Reset Detected");
95 /* check for processor halted */
96 if (ejtag_ctrl & EJTAG_CTRL_BRKST) {
97 if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
98 target->state = TARGET_HALTED;
99 retval = mips_mips64_debug_entry(target);
100 if (retval != ERROR_OK)
102 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
103 } else if (target->state == TARGET_DEBUG_RUNNING) {
104 target->state = TARGET_HALTED;
105 retval = mips_mips64_debug_entry(target);
106 if (retval != ERROR_OK)
109 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
112 target->state = TARGET_RUNNING;
118 static int mips_mips64_halt(struct target *target)
120 struct mips64_common *mips64 = target->arch_info;
121 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
123 LOG_DEBUG("target->state: %s",
124 target_state_name(target));
126 if (target->state == TARGET_HALTED) {
127 LOG_DEBUG("target was already halted");
131 if (target->state == TARGET_UNKNOWN)
132 LOG_WARNING("target was in unknown state when halt was requested");
134 if (target->state == TARGET_RESET) {
135 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
136 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
137 return ERROR_TARGET_FAILURE;
139 /* we came here in a reset_halt or reset_init sequence
140 * debug entry was already prepared in mips64_prepare_reset_halt()
142 target->debug_reason = DBG_REASON_DBGRQ;
148 /* break processor */
149 mips_ejtag_enter_debug(ejtag_info);
151 target->debug_reason = DBG_REASON_DBGRQ;
156 static int mips_mips64_assert_reset(struct target *target)
158 struct mips64_common *mips64 = target->arch_info;
159 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
162 LOG_DEBUG("target->state: %s",
163 target_state_name(target));
165 enum reset_types jtag_reset_config = jtag_get_reset_config();
166 if (!(jtag_reset_config & RESET_HAS_SRST)) {
167 LOG_ERROR("Can't assert SRST");
171 if (target->reset_halt)
172 /* use hardware to catch reset */
173 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
175 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
177 /* here we should issue a srst only, but we may have to assert trst as well */
178 if (jtag_reset_config & RESET_SRST_PULLS_TRST)
179 jtag_add_reset(1, 1);
181 jtag_add_reset(0, 1);
183 target->state = TARGET_RESET;
184 jtag_add_sleep(5000);
186 retval = mips64_invalidate_core_regs(target);
187 if (retval != ERROR_OK)
190 if (target->reset_halt) {
191 retval = target_halt(target);
192 if (retval != ERROR_OK)
199 static int mips_mips64_deassert_reset(struct target *target)
201 LOG_DEBUG("target->state: %s",
202 target_state_name(target));
204 /* deassert reset lines */
205 jtag_add_reset(0, 0);
210 static int mips_mips64_soft_reset_halt(struct target *target)
216 static int mips_mips64_single_step_core(struct target *target)
218 struct mips64_common *mips64 = target->arch_info;
219 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
222 /* configure single step mode */
223 mips64_ejtag_config_step(ejtag_info, 1);
225 /* disable interrupts while stepping */
226 retval = mips64_enable_interrupts(target, false);
227 if (retval != ERROR_OK)
230 /* exit debug mode */
231 retval = mips64_ejtag_exit_debug(ejtag_info);
232 if (retval != ERROR_OK)
235 mips_mips64_debug_entry(target);
240 /* TODO: HW breakpoints are in EJTAG spec. Should we share it for MIPS32? */
241 static int mips_mips64_set_hwbp(struct target *target, struct breakpoint *bp)
243 struct mips64_common *mips64 = target->arch_info;
244 struct mips64_comparator *c, *cl = mips64->inst_break_list;
246 int retval, bp_num = 0;
248 while (cl[bp_num].used && (bp_num < mips64->num_inst_bpoints))
251 if (bp_num >= mips64->num_inst_bpoints) {
252 LOG_DEBUG("ERROR Can not find free FP Comparator(bpid: %d)",
254 LOG_WARNING("ERROR Can not find free FP Comparator");
260 c->bp_value = bp->address;
261 bp_value = bp->address;
263 /* Instruction Breakpoint Address n (IBAn) Register */
264 retval = target_write_u64(target, c->reg_address, bp_value);
265 if (retval != ERROR_OK)
268 /* TODO: use defines */
269 /* Instruction Breakpoint Address Mask n (IBMn) Register */
270 retval = target_write_u64(target, c->reg_address + 0x08, 0);
271 if (retval != ERROR_OK)
274 /* Instruction Breakpoint Control n (IBCn) Register */
275 retval = target_write_u64(target, c->reg_address + 0x18, 1);
276 if (retval != ERROR_OK)
279 LOG_DEBUG("bpid: %d, bp_num %i bp_value 0x%" PRIx64 "", bp->unique_id,
280 bp_num, c->bp_value);
285 /* TODO: is it MIPS64 or MIPS32 instruction. If MIPS32, can it be shared with
287 static int mips_mips64_set_sdbbp(struct target *target, struct breakpoint *bp)
292 retval = target_read_memory(target,
293 bp->address, bp->length, 1,
295 if (retval != ERROR_OK)
298 retval = target_write_u32(target, bp->address, MIPS64_SDBBP);
299 if (retval != ERROR_OK)
302 retval = target_read_u32(target, bp->address, &verify);
303 if (retval != ERROR_OK)
306 if (verify != MIPS64_SDBBP) {
307 LOG_ERROR("Unable to set 32bit breakpoint at address %16" PRIx64,
315 /* TODO do MIPS64 support MIPS16 instructions? Can it be shared with MIPS32
317 static int mips_mips16_set_sdbbp(struct target *target, struct breakpoint *bp)
319 uint32_t isa_req = bp->length & 1;
323 retval = target_read_memory(target,
324 bp->address, bp->length, 1,
326 if (retval != ERROR_OK)
329 retval = target_write_u16(target, bp->address, MIPS16_SDBBP(isa_req));
330 if (retval != ERROR_OK)
333 retval = target_read_u16(target, bp->address, &verify);
334 if (retval != ERROR_OK)
337 if (verify != MIPS16_SDBBP(isa_req)) {
338 LOG_ERROR("Unable to set 16bit breakpoint at address %16" PRIx64,
346 static int mips_mips64_set_breakpoint(struct target *target,
347 struct breakpoint *bp)
352 LOG_WARNING("breakpoint already set");
356 if (bp->type == BKPT_HARD) {
357 retval = mips_mips64_set_hwbp(target, bp);
359 LOG_DEBUG("bpid: %d", bp->unique_id);
361 switch (bp->length) {
362 case MIPS64_SDBBP_SIZE:
363 retval = mips_mips64_set_sdbbp(target, bp);
365 case MIPS16_SDBBP_SIZE:
366 retval = mips_mips16_set_sdbbp(target, bp);
373 if (retval != ERROR_OK) {
374 LOG_ERROR("can't unset breakpoint. Some thing wrong happened");
383 static int mips_mips64_enable_breakpoints(struct target *target)
385 struct breakpoint *bp = target->breakpoints;
386 int retval = ERROR_OK;
388 /* set any pending breakpoints */
391 retval = mips_mips64_set_breakpoint(target, bp);
392 if (retval != ERROR_OK)
401 /* TODO: HW data breakpoints are in EJTAG spec. Should we share it for MIPS32? */
402 static int mips_mips64_set_watchpoint(struct target *target,
403 struct watchpoint *watchpoint)
406 struct mips64_common *mips64 = target->arch_info;
407 struct mips64_comparator *c, *cl = mips64->data_break_list;
408 int retval, wp_num = 0;
411 * watchpoint enabled, ignore all byte lanes in value register
412 * and exclude both load and store accesses from watchpoint
413 * condition evaluation
415 int enable = EJTAG_DBCn_NOSB | EJTAG_DBCn_NOLB | EJTAG_DBCn_BE
416 | (0xff << EJTAG_DBCn_BLM_SHIFT);
418 if (watchpoint->set) {
419 LOG_WARNING("watchpoint already set");
423 while (cl[wp_num].used && (wp_num < mips64->num_data_bpoints))
426 if (wp_num >= mips64->num_data_bpoints) {
427 LOG_ERROR("ERROR Can not find free comparator");
428 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
431 if (watchpoint->length != 4) {
432 LOG_ERROR("Only watchpoints of length 4 are supported");
433 return ERROR_TARGET_UNALIGNED_ACCESS;
436 if (watchpoint->address % 4) {
437 LOG_ERROR("Watchpoints address should be word aligned");
438 return ERROR_TARGET_UNALIGNED_ACCESS;
441 switch (watchpoint->rw) {
443 enable &= ~EJTAG_DBCn_NOLB;
446 enable &= ~EJTAG_DBCn_NOSB;
449 enable &= ~(EJTAG_DBCn_NOLB | EJTAG_DBCn_NOSB);
452 LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
456 watchpoint->set = wp_num + 1;
458 c->bp_value = watchpoint->address;
460 wp_value = watchpoint->address;
461 if (wp_value & 0x80000000)
462 wp_value |= ULLONG_MAX << 32;
464 retval = target_write_u64(target, c->reg_address, wp_value);
465 if (retval != ERROR_OK)
468 retval = target_write_u64(target, c->reg_address + 0x08, 0);
469 if (retval != ERROR_OK)
472 retval = target_write_u64(target, c->reg_address + 0x10, 0);
473 if (retval != ERROR_OK)
476 retval = target_write_u64(target, c->reg_address + 0x18, enable);
477 if (retval != ERROR_OK)
480 retval = target_write_u64(target, c->reg_address + 0x20, 0);
481 if (retval != ERROR_OK)
484 LOG_DEBUG("wp_num %i bp_value 0x%" PRIx64 "", wp_num, c->bp_value);
489 static int mips_mips64_enable_watchpoints(struct target *target)
491 struct watchpoint *watchpoint = target->watchpoints;
494 /* set any pending watchpoints */
496 if (watchpoint->set == 0) {
497 retval = mips_mips64_set_watchpoint(target, watchpoint);
498 if (retval != ERROR_OK)
501 watchpoint = watchpoint->next;
507 static int mips_mips64_unset_hwbp(struct target *target, struct breakpoint *bp)
509 struct mips64_common *mips64 = target->arch_info;
510 struct mips64_comparator *comparator_list = mips64->inst_break_list;
513 bp_num = bp->set - 1;
515 if ((bp_num < 0) || (bp_num >= mips64->num_inst_bpoints)) {
516 LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %d)",
521 LOG_DEBUG("bpid: %d - releasing hw: %d", bp->unique_id, bp_num);
522 comparator_list[bp_num].used = false;
523 comparator_list[bp_num].bp_value = 0;
525 return target_write_u64(target,
526 comparator_list[bp_num].reg_address + 0x18, 0);
529 static int mips_mips64_unset_sdbbp(struct target *target, struct breakpoint *bp)
531 uint8_t buf[MIPS64_SDBBP_SIZE];
535 retval = target_read_memory(target, bp->address, MIPS64_SDBBP_SIZE, 1,
537 if (retval != ERROR_OK)
540 instr = target_buffer_get_u32(target, &buf[0]);
541 if (instr != MIPS64_SDBBP)
544 return target_write_memory(target, bp->address, MIPS64_SDBBP_SIZE, 1,
548 static int mips_mips16_unset_sdbbp(struct target *target, struct breakpoint *bp)
550 uint8_t buf[MIPS16_SDBBP_SIZE];
554 retval = target_read_memory(target, bp->address, MIPS16_SDBBP_SIZE, 1,
556 if (retval != ERROR_OK)
559 instr = target_buffer_get_u16(target, &buf[0]);
560 if (instr != MIPS16_SDBBP(bp->length & 1))
563 return target_write_memory(target, bp->address, MIPS16_SDBBP_SIZE, 1,
567 static int mips_mips64_unset_breakpoint(struct target *target,
568 struct breakpoint *bp)
570 /* get pointers to arch-specific information */
574 LOG_WARNING("breakpoint not set");
578 if (bp->type == BKPT_HARD) {
579 retval = mips_mips64_unset_hwbp(target, bp);
581 LOG_DEBUG("bpid: %d", bp->unique_id);
583 switch (bp->length) {
584 case MIPS64_SDBBP_SIZE:
585 retval = mips_mips64_unset_sdbbp(target, bp);
587 case MIPS16_SDBBP_SIZE:
588 retval = mips_mips16_unset_sdbbp(target, bp);
594 if (retval != ERROR_OK) {
595 LOG_ERROR("can't unset breakpoint. Some thing wrong happened");
604 static int mips_mips64_resume(struct target *target, int current,
605 uint64_t address, int handle_breakpoints,
608 struct mips64_common *mips64 = target->arch_info;
609 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
610 int retval = ERROR_OK;
614 if (mips64->mips64mode32)
615 address = mips64_extend_sign(address);
617 if (target->state != TARGET_HALTED) {
618 LOG_WARNING("target not halted %d", target->state);
619 return ERROR_TARGET_NOT_HALTED;
622 if (!debug_execution) {
623 target_free_all_working_areas(target);
624 retval = mips_mips64_enable_breakpoints(target);
625 if (retval != ERROR_OK)
628 retval = mips_mips64_enable_watchpoints(target);
629 if (retval != ERROR_OK)
633 pc = &mips64->core_cache->reg_list[MIPS64_PC];
634 /* current = 1: continue on current pc, otherwise continue at <address> */
636 buf_set_u64(pc->value, 0, 64, address);
641 resume_pc = buf_get_u64(pc->value, 0, 64);
643 retval = mips64_restore_context(target);
644 if (retval != ERROR_OK)
647 /* the front-end may request us not to handle breakpoints */
648 if (handle_breakpoints) {
649 struct breakpoint *bp;
651 /* Single step past breakpoint at current address */
652 bp = breakpoint_find(target, (uint64_t) resume_pc);
654 LOG_DEBUG("unset breakpoint at 0x%16.16" PRIx64 "",
656 retval = mips_mips64_unset_breakpoint(target, bp);
657 if (retval != ERROR_OK)
660 retval = mips_mips64_single_step_core(target);
661 if (retval != ERROR_OK)
664 retval = mips_mips64_set_breakpoint(target, bp);
665 if (retval != ERROR_OK)
670 /* enable interrupts if we are running */
671 retval = mips64_enable_interrupts(target, !debug_execution);
672 if (retval != ERROR_OK)
675 /* exit debug mode */
676 retval = mips64_ejtag_exit_debug(ejtag_info);
677 if (retval != ERROR_OK)
680 target->debug_reason = DBG_REASON_NOTHALTED;
682 /* registers are now invalid */
683 retval = mips64_invalidate_core_regs(target);
684 if (retval != ERROR_OK)
687 if (!debug_execution) {
688 target->state = TARGET_RUNNING;
689 retval = target_call_event_callbacks(target,
690 TARGET_EVENT_RESUMED);
691 if (retval != ERROR_OK)
694 LOG_DEBUG("target resumed at 0x%" PRIx64 "", resume_pc);
696 target->state = TARGET_DEBUG_RUNNING;
697 retval = target_call_event_callbacks(target,
698 TARGET_EVENT_DEBUG_RESUMED);
699 if (retval != ERROR_OK)
702 LOG_DEBUG("target debug resumed at 0x%" PRIx64 "", resume_pc);
708 static int mips_mips64_step(struct target *target, int current,
709 uint64_t address, int handle_breakpoints)
711 struct mips64_common *mips64 = target->arch_info;
712 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
713 struct reg *pc = &mips64->core_cache->reg_list[MIPS64_PC];
714 struct breakpoint *bp = NULL;
715 int retval = ERROR_OK;
717 if (target->state != TARGET_HALTED) {
718 LOG_WARNING("target not halted");
719 return ERROR_TARGET_NOT_HALTED;
722 if (mips64->mips64mode32)
723 address = mips64_extend_sign(address);
725 /* current = 1: continue on current pc, otherwise continue at
728 buf_set_u64(pc->value, 0, 64, address);
733 /* the front-end may request us not to handle breakpoints */
734 if (handle_breakpoints) {
735 bp = breakpoint_find(target, buf_get_u64(pc->value, 0, 64));
737 retval = mips_mips64_unset_breakpoint(target, bp);
738 if (retval != ERROR_OK)
743 retval = mips64_restore_context(target);
744 if (retval != ERROR_OK)
747 /* configure single step mode */
748 retval = mips64_ejtag_config_step(ejtag_info, 1);
749 if (retval != ERROR_OK)
752 target->debug_reason = DBG_REASON_SINGLESTEP;
754 retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
755 if (retval != ERROR_OK)
758 /* disable interrupts while stepping */
759 retval = mips64_enable_interrupts(target, false);
760 if (retval != ERROR_OK)
763 /* exit debug mode */
764 retval = mips64_ejtag_exit_debug(ejtag_info);
765 if (retval != ERROR_OK)
768 /* registers are now invalid */
769 retval = mips64_invalidate_core_regs(target);
770 if (retval != ERROR_OK)
774 retval = mips_mips64_set_breakpoint(target, bp);
775 if (retval != ERROR_OK)
779 LOG_DEBUG("target stepped ");
781 retval = mips_mips64_debug_entry(target);
782 if (retval != ERROR_OK)
785 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
788 static int mips_mips64_add_breakpoint(struct target *target,
789 struct breakpoint *bp)
791 struct mips64_common *mips64 = target->arch_info;
793 if (mips64->mips64mode32)
794 bp->address = mips64_extend_sign(bp->address);
796 if (bp->type == BKPT_HARD) {
797 if (mips64->num_inst_bpoints_avail < 1) {
798 LOG_INFO("no hardware breakpoint available");
799 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
802 mips64->num_inst_bpoints_avail--;
805 return mips_mips64_set_breakpoint(target, bp);
808 static int mips_mips64_remove_breakpoint(struct target *target,
809 struct breakpoint *bp)
811 /* get pointers to arch-specific information */
812 struct mips64_common *mips64 = target->arch_info;
813 int retval = ERROR_OK;
815 if (target->state != TARGET_HALTED) {
816 LOG_WARNING("target not halted");
817 return ERROR_TARGET_NOT_HALTED;
821 retval = mips_mips64_unset_breakpoint(target, bp);
823 if (bp->type == BKPT_HARD)
824 mips64->num_inst_bpoints_avail++;
829 static int mips_mips64_unset_watchpoint(struct target *target,
830 struct watchpoint *watchpoint)
832 /* get pointers to arch-specific information */
833 struct mips64_common *mips64 = target->arch_info;
834 struct mips64_comparator *comparator_list = mips64->data_break_list;
836 if (!watchpoint->set) {
837 LOG_WARNING("watchpoint not set");
841 int wp_num = watchpoint->set - 1;
842 if ((wp_num < 0) || (wp_num >= mips64->num_data_bpoints)) {
843 LOG_DEBUG("Invalid FP Comparator number in watchpoint");
846 comparator_list[wp_num].used = false;
847 comparator_list[wp_num].bp_value = 0;
848 target_write_u64(target, comparator_list[wp_num].reg_address + 0x18, 0);
854 static int mips_mips64_add_watchpoint(struct target *target,
855 struct watchpoint *watchpoint)
857 struct mips64_common *mips64 = target->arch_info;
859 if (mips64->num_data_bpoints_avail < 1) {
860 LOG_INFO("no hardware watchpoints available");
861 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
864 mips64->num_data_bpoints_avail--;
866 return mips_mips64_set_watchpoint(target, watchpoint);
869 static int mips_mips64_remove_watchpoint(struct target *target,
870 struct watchpoint *watchpoint)
872 /* get pointers to arch-specific information */
873 struct mips64_common *mips64 = target->arch_info;
874 int retval = ERROR_OK;
876 if (target->state != TARGET_HALTED) {
877 LOG_WARNING("target not halted");
878 return ERROR_TARGET_NOT_HALTED;
882 retval = mips_mips64_unset_watchpoint(target, watchpoint);
884 mips64->num_data_bpoints_avail++;
889 static int mips_mips64_read_memory(struct target *target, uint64_t address,
890 uint32_t size, uint32_t count, uint8_t *buffer)
892 struct mips64_common *mips64 = target->arch_info;
893 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
897 if (target->state != TARGET_HALTED) {
898 LOG_WARNING("target not halted %d", target->state);
899 return ERROR_TARGET_NOT_HALTED;
902 if (mips64->mips64mode32)
903 address = mips64_extend_sign(address);
905 /* sanitize arguments */
906 if (((size != 8) && (size != 4) && (size != 2) && (size != 1))
907 || !count || !buffer)
908 return ERROR_COMMAND_ARGUMENT_INVALID;
910 if (((size == 8) && (address & 0x7)) || ((size == 4) && (address & 0x3))
911 || ((size == 2) && (address & 0x1)))
912 return ERROR_TARGET_UNALIGNED_ACCESS;
915 t = calloc(count, size);
917 LOG_ERROR("Out of memory");
923 LOG_DEBUG("address: 0x%16.16" PRIx64 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
924 address, size, count);
925 retval = mips64_pracc_read_mem(ejtag_info, address, size, count,
928 if (ERROR_OK != retval) {
929 LOG_ERROR("mips64_pracc_read_mem filed");
935 target_buffer_set_u64_array(target, buffer, count, t);
938 target_buffer_set_u32_array(target, buffer, count, t);
941 target_buffer_set_u16_array(target, buffer, count, t);
952 static int mips_mips64_bulk_write_memory(struct target *target,
953 target_addr_t address, uint32_t count,
954 const uint8_t *buffer)
956 struct mips64_common *mips64 = target->arch_info;
957 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
958 struct working_area *fast_data_area;
961 LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "",
965 return ERROR_TARGET_UNALIGNED_ACCESS;
967 if (!mips64->fast_data_area) {
968 /* Get memory for block write handler
969 * we preserve this area between calls and gain a speed increase
970 * of about 3kb/sec when writing flash
971 * this will be released/nulled by the system when the target is resumed or reset */
972 retval = target_alloc_working_area(target,
973 MIPS64_FASTDATA_HANDLER_SIZE,
974 &mips64->fast_data_area);
975 if (retval != ERROR_OK) {
976 LOG_ERROR("No working area available");
980 /* reset fastadata state so the algo get reloaded */
981 ejtag_info->fast_access_save = -1;
984 fast_data_area = mips64->fast_data_area;
986 if (address <= fast_data_area->address + fast_data_area->size &&
987 fast_data_area->address <= address + count) {
988 LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area "
989 "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").",
990 fast_data_area->address, address, address + count);
991 LOG_ERROR("Change work-area-phys or load_image address!");
995 /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */
996 /* but byte array represents target endianness */
999 t = calloc(count, sizeof(uint64_t));
1001 LOG_ERROR("Out of memory");
1005 target_buffer_get_u64_array(target, buffer, count, t);
1007 retval = mips64_pracc_fastdata_xfer(ejtag_info, mips64->fast_data_area,
1008 true, address, count, t);
1010 if (retval != ERROR_OK)
1011 LOG_ERROR("Fastdata access Failed");
1018 static int mips_mips64_write_memory(struct target *target, uint64_t address,
1019 uint32_t size, uint32_t count, const uint8_t *buffer)
1021 struct mips64_common *mips64 = target->arch_info;
1022 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
1025 if (target->state != TARGET_HALTED) {
1026 LOG_WARNING("target not halted");
1027 return ERROR_TARGET_NOT_HALTED;
1030 if (mips64->mips64mode32)
1031 address = mips64_extend_sign(address);
1033 /* sanitize arguments */
1034 if (((size != 8) && (size != 4) && (size != 2) && (size != 1))
1035 || !count || !buffer)
1036 return ERROR_COMMAND_ARGUMENT_INVALID;
1038 if (((size == 8) && (address & 0x7)) || ((size == 4) && (address & 0x3))
1039 || ((size == 2) && (address & 0x1)))
1040 return ERROR_TARGET_UNALIGNED_ACCESS;
1044 if (size == 8 && count > 8) {
1045 retval = mips_mips64_bulk_write_memory(target, address, count,
1047 if (retval == ERROR_OK)
1050 LOG_WARNING("Falling back to non-bulk write");
1055 t = calloc(count, size);
1057 LOG_ERROR("unable to allocate t for write buffer");
1063 target_buffer_get_u64_array(target, buffer, count,
1067 target_buffer_get_u32_array(target, buffer, count,
1071 target_buffer_get_u16_array(target, buffer, count,
1078 LOG_DEBUG("address: 0x%16.16" PRIx64 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
1079 address, size, count);
1081 retval = mips64_pracc_write_mem(ejtag_info, address, size, count,
1088 static int mips_mips64_init_target(struct command_context *cmd_ctx,
1089 struct target *target)
1091 return mips64_build_reg_cache(target);
1094 static int mips_mips64_target_create(struct target *target, Jim_Interp *interp)
1096 struct mips_mips64_common *mips_mips64;
1097 struct mips64_common *mips64;
1099 mips_mips64 = calloc(1, sizeof(*mips_mips64));
1101 LOG_ERROR("unable to allocate mips_mips64");
1105 mips_mips64->common_magic = MIPS64_COMMON_MAGIC;
1107 mips64 = &mips_mips64->mips64_common;
1108 mips64->arch_info = mips_mips64;
1109 target->arch_info = mips64;
1111 return mips64_init_arch_info(target, mips64, target->tap);
1114 static int mips_mips64_examine(struct target *target)
1117 struct mips64_common *mips64 = target->arch_info;
1119 retval = mips_ejtag_init(&mips64->ejtag_info);
1120 if (retval != ERROR_OK)
1123 return mips64_examine(target);
1126 static int mips_mips64_checksum_memory(struct target *target, uint64_t address,
1127 uint32_t size, uint32_t *checksum)
1129 return ERROR_FAIL; /* use bulk read method */
1132 COMMAND_HANDLER(handle_mips64mode32)
1134 struct target *target = get_current_target(CMD_CTX);
1135 struct mips64_common *mips64 = target->arch_info;
1138 COMMAND_PARSE_BOOL(CMD_ARGV[0], mips64->mips64mode32, "on", "off");
1140 if (mips64->mips64mode32)
1141 command_print(CMD, "enabled");
1143 command_print(CMD, "disabled");
1149 static const struct command_registration mips64_commands_handlers[] = {
1151 .name = "mips64mode32",
1152 .mode = COMMAND_EXEC,
1153 .help = "Enable/disable 32 bit mode",
1155 .handler = handle_mips64mode32
1157 COMMAND_REGISTRATION_DONE
1160 struct target_type mips_mips64_target = {
1161 .name = "mips_mips64",
1163 .poll = mips_mips64_poll,
1164 .arch_state = mips64_arch_state,
1166 .target_request_data = NULL,
1168 .halt = mips_mips64_halt,
1169 .resume = mips_mips64_resume,
1170 .step = mips_mips64_step,
1172 .assert_reset = mips_mips64_assert_reset,
1173 .deassert_reset = mips_mips64_deassert_reset,
1174 .soft_reset_halt = mips_mips64_soft_reset_halt,
1176 .get_gdb_reg_list = mips64_get_gdb_reg_list,
1178 .read_memory = mips_mips64_read_memory,
1179 .write_memory = mips_mips64_write_memory,
1180 .checksum_memory = mips_mips64_checksum_memory,
1181 .blank_check_memory = NULL,
1183 .run_algorithm = mips64_run_algorithm,
1185 .add_breakpoint = mips_mips64_add_breakpoint,
1186 .remove_breakpoint = mips_mips64_remove_breakpoint,
1187 .add_watchpoint = mips_mips64_add_watchpoint,
1188 .remove_watchpoint = mips_mips64_remove_watchpoint,
1190 .target_create = mips_mips64_target_create,
1191 .init_target = mips_mips64_init_target,
1192 .examine = mips_mips64_examine,
1194 .commands = mips64_commands_handlers,
1197 #endif /* BUILD_TARGET64 */