void part_emulation_return (urj_chain_t *chain, int n) { part_emuir_set (chain, n, INSN_RTE, URJ_CHAIN_EXITMODE_UPDATE); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_emeen (chain, n); part_dbgctl_bit_clear_wakeup (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_IDLE); /* get the RTE out of EMUIR so we don't execute it more than once */ part_emuir_set (chain, n, INSN_NOP, URJ_CHAIN_EXITMODE_IDLE); }
uint32_t part_register_get (urj_chain_t *chain, int n, enum core_regnum reg) { urj_part_t *part; urj_tap_register_t *r; uint32_t r0 = 0; if (DREG_P (reg) || PREG_P (reg)) part_emuir_set (chain, n, gen_move (REG_EMUDAT, reg), URJ_CHAIN_EXITMODE_IDLE); else { r0 = part_register_get (chain, n, REG_R0); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_set_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_emuir_set_2 (chain, n, gen_move (REG_R0, reg), gen_move (REG_EMUDAT, REG_R0), URJ_CHAIN_EXITMODE_IDLE); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); } part_scan_select (chain, n, EMUDAT_SCAN); urj_tap_chain_shift_data_registers_mode (chain, 1, 1, URJ_CHAIN_EXITMODE_UPDATE); part = chain->parts->parts[n]; r = part->active_instruction->data_register->out; if (!DREG_P (reg) && !PREG_P (reg)) part_register_set (chain, n, REG_R0, r0); return emudat_value (r); }
void bfin_core_reset (urj_chain_t *chain, int n) { part_emulation_disable (chain, n); part_emuir_set (chain, n, INSN_NOP, URJ_CHAIN_EXITMODE_UPDATE); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_set_sram_init (chain, n); part_dbgctl_bit_set_sysrst (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_wait_in_reset (chain, n); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_sysrst (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_wait_reset (chain, n); part_emulation_enable (chain, n); part_emulation_trigger (chain, n); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_sram_init (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); }
uint32_t part_mmr_read_clobber_r0 (urj_chain_t *chain, int n, int32_t offset, int size) { uint32_t value; assert (size == 2 || size == 4); if (offset == 0) { part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_set_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); if (size == 2) part_emuir_set_2 (chain, n, gen_load16z (REG_R0, REG_P0), gen_move (REG_EMUDAT, REG_R0), URJ_CHAIN_EXITMODE_UPDATE); else part_emuir_set_2 (chain, n, gen_load32 (REG_R0, REG_P0), gen_move (REG_EMUDAT, REG_R0), URJ_CHAIN_EXITMODE_UPDATE); } else { if (size == 2) part_emuir_set (chain, n, gen_load16z_offset (REG_R0, REG_P0, offset), URJ_CHAIN_EXITMODE_IDLE); else part_emuir_set (chain, n, gen_load32_offset (REG_R0, REG_P0, offset), URJ_CHAIN_EXITMODE_IDLE); part_emuir_set (chain, n, gen_move (REG_EMUDAT, REG_R0), URJ_CHAIN_EXITMODE_UPDATE); } value = part_emudat_get (chain, n, URJ_CHAIN_EXITMODE_IDLE); if (offset == 0) { part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); } return value; }
void part_mmr_write_clobber_r0 (urj_chain_t *chain, int n, int32_t offset, uint32_t data, int size) { assert (size == 2 || size == 4); part_emudat_set (chain, n, data, URJ_CHAIN_EXITMODE_UPDATE); if (offset == 0) { part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_set_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); if (size == 2) part_emuir_set_2 (chain, n, gen_move (REG_R0, REG_EMUDAT), gen_store16 (REG_P0, REG_R0), URJ_CHAIN_EXITMODE_IDLE); else part_emuir_set_2 (chain, n, gen_move (REG_R0, REG_EMUDAT), gen_store32 (REG_P0, REG_R0), URJ_CHAIN_EXITMODE_IDLE); } else { part_emuir_set (chain, n, gen_move (REG_R0, REG_EMUDAT), URJ_CHAIN_EXITMODE_IDLE); if (size == 2) part_emuir_set (chain, n, gen_store16_offset (REG_P0, offset, REG_R0), URJ_CHAIN_EXITMODE_IDLE); else part_emuir_set (chain, n, gen_store32_offset (REG_P0, offset, REG_R0), URJ_CHAIN_EXITMODE_IDLE); } if (offset == 0) { part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); } }
void chain_system_reset (urj_chain_t *chain) { uint32_t p0, r0; p0 = part_get_p0 (chain, chain->main_part); r0 = part_get_r0 (chain, chain->main_part); /* * Flush all system events like cache line fills. Otherwise, * when we reset the system side, any events that the core was * waiting on no longer exist, and the core hangs. */ part_emuir_set (chain, chain->main_part, INSN_SSYNC, URJ_CHAIN_EXITMODE_IDLE); /* Write 0x7 to SWRST to start system reset. */ part_set_p0 (chain, chain->main_part, SWRST); part_set_r0 (chain, chain->main_part, 0x7); part_emuir_set (chain, chain->main_part, gen_store16_offset (REG_P0, 0, REG_R0), URJ_CHAIN_EXITMODE_IDLE); /* * Delay at least 10 SCLKs instead of doing an SSYNC insn. * Since the system is being reset, the sync signal might * not be asserted, and so the core hangs waiting for it. * The magic "10" number was given to us by ADI designers * who looked at the schematic and ran some simulations. */ usleep (100); /* Write 0x0 to SWRST to stop system reset. */ part_set_r0 (chain, chain->main_part, 0); part_emuir_set (chain, chain->main_part, gen_store16_offset (REG_P0, 0, REG_R0), URJ_CHAIN_EXITMODE_IDLE); /* Delay at least 1 SCLK; see comment above for more info. */ usleep (100); part_set_p0 (chain, chain->main_part, p0); part_set_r0 (chain, chain->main_part, r0); }
void part_execute_instructions (urj_chain_t *chain, int n, struct bfin_insn *insns) { while (insns) { if (insns->type == BFIN_INSN_NORMAL) part_emuir_set (chain, n, insns->i, URJ_CHAIN_EXITMODE_IDLE); else /* insns->type == BFIN_INSN_SET_EMUDAT */ part_emudat_set (chain, n, insns->i, URJ_CHAIN_EXITMODE_UPDATE); insns = insns->next; } return; }
void part_emupc_reset (urj_chain_t *chain, int n, uint32_t new_pc) { urj_part_t *part = chain->parts->parts[n]; uint32_t p0; p0 = part_register_get (chain, n, REG_P0); BFIN_PART_EMUPC (part) = new_pc; part_register_set (chain, n, REG_P0, new_pc); part_emuir_set (chain, n, gen_jump_reg (REG_P0), URJ_CHAIN_EXITMODE_IDLE); part_register_set (chain, n, REG_P0, p0); }
void part_emulation_trigger (urj_chain_t *chain, int n) { part_emuir_set (chain, n, INSN_NOP, URJ_CHAIN_EXITMODE_UPDATE); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_set_wakeup (chain, n); part_dbgctl_bit_set_emeen (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_IDLE); /* I don't know why, but the following code works. */ /* Enter the emulation mode */ urj_tap_chain_defer_clock (chain, 1, 0, 1); /* Bring the TAP state to Update-DR */ urj_tap_chain_defer_clock (chain, 0, 0, 1); urj_tap_chain_defer_clock (chain, 1, 0, 2); }
void part_register_set (urj_chain_t *chain, int n, enum core_regnum reg, uint32_t value) { urj_part_t *part; urj_tap_register_t *r; uint32_t r0 = 0; if (!DREG_P (reg) && !PREG_P (reg)) r0 = part_register_get (chain, n, REG_R0); part_scan_select (chain, n, EMUDAT_SCAN); part = chain->parts->parts[n]; r = part->active_instruction->data_register->in; BFIN_PART_EMUDAT_IN (part) = value; emudat_init_value (r, value); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); if (DREG_P (reg) || PREG_P (reg)) part_emuir_set (chain, n, gen_move (reg, REG_EMUDAT), URJ_CHAIN_EXITMODE_IDLE); else { part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_set_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_emuir_set_2 (chain, n, gen_move (REG_R0, REG_EMUDAT), gen_move (reg, REG_R0), URJ_CHAIN_EXITMODE_IDLE); part_scan_select (chain, n, DBGCTL_SCAN); part_dbgctl_bit_clear_emuirlpsz_2 (chain, n); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_register_set (chain, n, REG_R0, r0); } }
static int cmd_bfin_run (urj_chain_t *chain, char *params[]) { int num_params; num_params = urj_cmd_params (params); if (num_params < 2) { urj_error_set (URJ_ERROR_SYNTAX, "#parameters should be >= 2, not %d", num_params); return URJ_STATUS_FAIL; } /* The remaining commands require cable or parts. */ if (urj_cmd_test_cable (chain) != URJ_STATUS_OK) return URJ_STATUS_FAIL; if (!chain->parts) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no parts, Run '%s' first", "detect"); return URJ_STATUS_FAIL; } if (chain->active_part >= chain->parts->len) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no active part"); return URJ_STATUS_FAIL; } if (!part_is_bfin (chain, chain->active_part)) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "not a Blackfin part"); return URJ_STATUS_FAIL; } assert (chain->active_part >= 0 && chain->active_part < chain->parts->len); if (strcmp (params[1], "emulation") == 0) { if (num_params != 3) { urj_error_set (URJ_ERROR_BFIN, "'bfin emulation' requires 1 parameter, not %d", num_params - 2); return URJ_STATUS_FAIL; } if (strcmp (params[2], "enable") == 0) { part_emulation_enable (chain, chain->active_part); } else if (strcmp (params[2], "trigger") == 0) { part_emulation_trigger (chain, chain->active_part); } else if (strcmp (params[2], "enter") == 0) { part_emulation_enable (chain, chain->active_part); part_emulation_trigger (chain, chain->active_part); } else if (strcmp (params[2], "return") == 0) { part_emulation_return (chain, chain->active_part); } else if (strcmp (params[2], "disable") == 0) { part_emulation_disable (chain, chain->active_part); } else if (strcmp (params[2], "exit") == 0) { part_emulation_return (chain, chain->active_part); part_emulation_disable (chain, chain->active_part); } else if (strcmp (params[2], "status") == 0) { uint16_t dbgstat, excause; const char *str_excause; urj_part_t *part; part_dbgstat_get (chain, chain->active_part); part = chain->parts->parts[chain->active_part]; dbgstat = BFIN_PART_DBGSTAT (part); excause = part_dbgstat_emucause (chain, chain->active_part); switch (excause) { case 0x0: str_excause = "EMUEXCPT was executed"; break; case 0x1: str_excause = "EMUIN pin was asserted"; break; case 0x2: str_excause = "Watchpoint event occurred"; break; case 0x4: str_excause = "Performance Monitor 0 overflowed"; break; case 0x5: str_excause = "Performance Monitor 1 overflowed"; break; case 0x8: str_excause = "Emulation single step"; break; default: str_excause = "Reserved??"; break; } urj_log (URJ_LOG_LEVEL_NORMAL, "Core [%d] DBGSTAT = 0x%"PRIx16"\n", chain->active_part, dbgstat); urj_log (URJ_LOG_LEVEL_NORMAL, "\tEMUDOF = %u\n" "\tEMUDIF = %u\n" "\tEMUDOOVF = %u\n" "\tEMUDIOVF = %u\n" "\tEMUREADY = %u\n" "\tEMUACK = %u\n" "\tEMUCAUSE = 0x%x (%s)\n" "\tBIST_DONE = %u\n" "\tLPDEC0 = %u\n" "\tIN_RESET = %u\n" "\tIDLE = %u\n" "\tCORE_FAULT = %u\n" "\tLPDEC1 = %u\n", part_dbgstat_is_emudof (chain, chain->active_part), part_dbgstat_is_emudif (chain, chain->active_part), part_dbgstat_is_emudoovf (chain, chain->active_part), part_dbgstat_is_emudiovf (chain, chain->active_part), part_dbgstat_is_emuready (chain, chain->active_part), part_dbgstat_is_emuack (chain, chain->active_part), excause, str_excause, part_dbgstat_is_bist_done (chain, chain->active_part), part_dbgstat_is_lpdec0 (chain, chain->active_part), part_dbgstat_is_in_reset (chain, chain->active_part), part_dbgstat_is_idle (chain, chain->active_part), part_dbgstat_is_core_fault (chain, chain->active_part), part_dbgstat_is_lpdec1 (chain, chain->active_part)); } else if (strcmp (params[2], "singlestep") == 0) { part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } /* TODO Allow an argument to specify how many single steps. */ part_scan_select (chain, chain->active_part, DBGCTL_SCAN); part_dbgctl_bit_set_esstep (chain, chain->active_part); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_emuir_set (chain, chain->active_part, INSN_RTE, URJ_CHAIN_EXITMODE_IDLE); part_scan_select (chain, chain->active_part, DBGCTL_SCAN); part_dbgctl_bit_clear_esstep (chain, chain->active_part); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); } else { urj_error_set (URJ_ERROR_BFIN, "unknown emulation subcommand '%s'", params[2]); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; } else if (strcmp (params[1], "execute") == 0) { int execute_ret = URJ_STATUS_FAIL; part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } if (num_params > 2) { int i; struct bfin_insn *insns = NULL; struct bfin_insn **last = &insns; char tmp[8]; char *tmpfile = NULL; for (i = 2; i < num_params; i++) { if (params[i][0] == '[' && params[i][1] == '0') { uint64_t n; if (sscanf (params[i], "[0%[xX]%"PRIx64"]", tmp, &n) != 2) goto execute_cleanup; *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_SET_EMUDAT; (*last)->next = NULL; last = &((*last)->next); } else if (params[i][0] == '0') { uint64_t n; if (sscanf (params[i], "0%[xX]%"PRIx64, tmp, &n) != 2) goto execute_cleanup; *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_NORMAL; (*last)->next = NULL; last = &((*last)->next); } else { #ifndef HAVE_SYS_WAIT_H urj_error_set (URJ_ERROR_BFIN, "Sorry, dynamic code not available for your platform"); goto execute_cleanup; #else unsigned char raw_insn[4]; char *tmp_buf; char *tuples[] = {"uclinux", "linux-uclibc", "elf"}; size_t t; FILE *fp; /* 1024 should be plenty. */ char insns_string[1024]; char *p = insns_string; for (; i < num_params; i++) { p += snprintf (p, sizeof (insns_string) - (p - insns_string), "%s ", params[i]); if (params[i][strlen (params[i]) - 1] == '"') break; if (params[i][strlen (params[i]) - 1] == ';') break; } if (i == num_params) { urj_error_set (URJ_ERROR_BFIN, "unbalanced double quotes"); goto execute_cleanup; } /* p points past the '\0'. p - 1 points to the ending '\0'. p - 2 points to the last double quote. */ *(p - 2) = ';'; if (insns_string[0] == '"') insns_string[0] = ' '; /* HRM states that branches and hardware loop setup results in undefined behavior. Should check opcode instead? */ if (strcasestr(insns_string, "jump") || strcasestr(insns_string, "call") || strcasestr(insns_string, "lsetup")) urj_warning (_("jump/call/lsetup insns may not work in emulation\n")); /* get a temporary file to work with -- a little racy */ if (!tmpfile) { tmpfile = tmpnam (NULL); if (!tmpfile) goto execute_cleanup; tmpfile = strdup (tmpfile); if (!tmpfile) goto execute_cleanup; } /* try to find a toolchain in $PATH */ for (t = 0; t < ARRAY_SIZE(tuples); ++t) { int ret; /* TODO Pass -mcpu= to gas. */ ret = asprintf (&tmp_buf, "bfin-%3$s-as --version >/dev/null 2>&1 || exit $?;" "echo '%1$s' | bfin-%3$s-as - -o \"%2$s\"" " && bfin-%3$s-objcopy -O binary \"%2$s\"", insns_string, tmpfile, tuples[t]); if (ret == -1) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("asprintf() failed")); goto execute_cleanup; } ret = system (tmp_buf); free (tmp_buf); if (WIFEXITED(ret)) { if (WEXITSTATUS(ret) == 0) break; /* 127 -> not found in $PATH */ else if (WEXITSTATUS(ret) == 127) continue; else { urj_error_set (URJ_ERROR_BFIN, "GAS failed parsing: %s", insns_string); goto execute_cleanup; } } } if (t == ARRAY_SIZE(tuples)) { urj_error_set (URJ_ERROR_BFIN, "unable to find Blackfin toolchain in $PATH\n"); goto execute_cleanup; } /* Read the binary blob from the toolchain */ fp = fopen (tmpfile, FOPEN_R); if (fp == NULL) goto execute_cleanup; /* Figure out how many instructions there are */ t = 0; p = insns_string; while ((p = strchr(p, ';')) != NULL) { ++t; ++p; } while (t-- && fread (raw_insn, 1, 2, fp) == 2) { uint16_t iw = raw_insn[0] | (raw_insn[1] << 8); uint64_t n = iw; int is_multiinsn = INSN_IS_MULTI (raw_insn[1]); if ((iw & 0xf000) >= 0xc000) { if (fread (raw_insn, 1, 2, fp) != 2) goto execute_cleanup; iw = raw_insn[0] | (raw_insn[1] << 8); n = (n << 16) | iw; } if (is_multiinsn) { if (fread (raw_insn, 1, 4, fp) != 4) goto execute_cleanup; n = (n << 32) | ((uint64_t)raw_insn[0] << 16) | ((uint64_t)raw_insn[1] << 24) | raw_insn[2] | (raw_insn[3] << 8); } *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_NORMAL; (*last)->next = NULL; last = &((*last)->next); } fclose (fp); #endif } } part_execute_instructions (chain, chain->active_part, insns); execute_ret = URJ_STATUS_OK; execute_cleanup: if (tmpfile) { unlink (tmpfile); free (tmpfile); } while (insns) { struct bfin_insn *tmp = insns->next; free (insns); insns = tmp; } } if (execute_ret == URJ_STATUS_OK) { uint64_t emudat; emudat = part_emudat_get (chain, chain->active_part, URJ_CHAIN_EXITMODE_UPDATE); urj_log (URJ_LOG_LEVEL_NORMAL, "EMUDAT = 0x%"PRIx64"\n", emudat); part_dbgstat_get (chain, chain->active_part); if (part_dbgstat_is_core_fault (chain, chain->active_part)) urj_warning (_("core fault detected\n")); } return execute_ret; } else if (strcmp (params[1], "reset") == 0) { int reset_what = 0; part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } if (num_params == 3) { if (!strcmp (params[2], "core")) reset_what |= 0x1; else if (!strcmp (params[2], "system")) reset_what |= 0x2; else { urj_error_set (URJ_ERROR_BFIN, "bad parameter '%s'", params[2]); return URJ_STATUS_FAIL; } } else if (num_params == 2) reset_what = 0x1 | 0x2; else { urj_error_set (URJ_ERROR_BFIN, "'bfin emulation' requires 0 or 1 parameter, not %d", num_params - 2); return URJ_STATUS_FAIL; } urj_log (URJ_LOG_LEVEL_NORMAL, _("%s: reseting processor ... "), "bfin"); fflush (stdout); if (reset_what == 0x3) software_reset (chain, chain->active_part); else if (reset_what & 0x1) bfin_core_reset (chain, chain->active_part); else if (reset_what & 0x2) chain_system_reset (chain); urj_log (URJ_LOG_LEVEL_NORMAL, _("OK\n")); return URJ_STATUS_OK; } else { urj_error_set (URJ_ERROR_BFIN, "unknown command '%s'", params[1]); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; }