Esempio n. 1
0
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);
}
Esempio n. 2
0
File: bfin.c Progetto: bgelb/urjtag
void
part_emudat_set (urj_chain_t *chain, int n, uint32_t value, int exit)
{
    urj_part_t *part;
    urj_tap_register_t *r;

    assert (exit == URJ_CHAIN_EXITMODE_UPDATE || exit == URJ_CHAIN_EXITMODE_IDLE);

    if (part_scan_select (chain, n, EMUDAT_SCAN) < 0)
        return;

    part = chain->parts->parts[n];
    r = part->active_instruction->data_register->in;
    emudat_init_value (r, value);
    urj_tap_chain_shift_data_registers_mode (chain, 0, 1, exit);

    if (exit == URJ_CHAIN_EXITMODE_IDLE && bfin_check_emuready)
        part_check_emuready (chain, n);
}
Esempio n. 3
0
File: bfin.c Progetto: bgelb/urjtag
uint32_t
part_emupc_get (urj_chain_t *chain, int n, int save)
{
    urj_part_t *part;
    urj_tap_register_t *r;

    assert (n >= 0 && n < chain->parts->len);

    part_scan_select (chain, n, EMUPC_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;
    BFIN_PART_EMUPC (part) = bfin_register_get_value (r);
    if (save)
        BFIN_PART_EMUPC_ORIG (part) = BFIN_PART_EMUPC (part);

    return BFIN_PART_EMUPC (part);
}
Esempio n. 4
0
File: bfin.c Progetto: bgelb/urjtag
void
part_emuir_set_2 (urj_chain_t *chain, int n, uint64_t insn1, uint64_t insn2, int exit)
{
    int emuir_scan;
    urj_part_t *part;
    urj_tap_register_t *r;
    int *changed;
    int scan_changed;
    int i;

    assert (exit == URJ_CHAIN_EXITMODE_UPDATE || exit == URJ_CHAIN_EXITMODE_IDLE);

    if ((insn1 & 0xffffffff00000000ULL) == 0
        && (insn2 & 0xffffffff00000000ULL) == 0)
    {
        emuir_scan = EMUIR_SCAN;

        part_scan_select (chain, n, DBGCTL_SCAN);
        part_dbgctl_bit_set_emuirsz_32 (chain, n);
        urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);
    }
    else
    {
        emuir_scan = EMUIR64_SCAN;

        part_scan_select (chain, n, DBGCTL_SCAN);
        part_dbgctl_bit_set_emuirsz_64 (chain, n);
        urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);
    }

    assert (n >= 0 && n < chain->parts->len);

    changed = (int *) malloc (chain->parts->len * sizeof (int));

    for (i = 0; i < chain->parts->len; i++)
    {
        if (!part_is_bfin (chain, i))
            continue;

        if (i == n
            && (BFIN_PART_EMUIR_A (chain->parts->parts[i]) != insn1
                || BFIN_PART_EMUIR_B (chain->parts->parts[i]) != insn2))
        {
            BFIN_PART_EMUIR_A (chain->parts->parts[i]) = insn1;
            BFIN_PART_EMUIR_B (chain->parts->parts[i]) = insn2;
            changed[i] = 1;
        }
        else if (i != n
                 && BFIN_PART_EMUIR_A (chain->parts->parts[i]) != INSN_NOP)
        {
            BFIN_PART_EMUIR_A (chain->parts->parts[i]) = INSN_NOP;
            changed[i] = 1;
        }
        else
            changed[i] = 0;
    }

    scan_changed = 0;

    for (i = 0; i < chain->parts->len; i++)
    {
        if (part_is_bfin (chain, i) && changed[i])
            scan_changed += bfin_set_scan (chain->parts->parts[i], emuir_scan);
        else
            scan_changed += bfin_set_scan (chain->parts->parts[i], BYPASS);
    }

    if (scan_changed)
        urj_tap_chain_shift_instructions_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);

    for (i = 0; i < chain->parts->len; i++)
    {
        if (!part_is_bfin (chain, i))
            continue;

        if (changed[i] && i == n)
        {
            part = chain->parts->parts[i];
            r = part->active_instruction->data_register->in;
            emuir_init_value (r, insn2);
            urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);

            emuir_init_value (r, insn1);
        }
        else if (changed[i])
        {
            part = chain->parts->parts[i];
            r = part->active_instruction->data_register->in;
            emuir_init_value (r, BFIN_PART_EMUIR_A (part));
        }
    }

    free (changed);

    urj_tap_chain_shift_data_registers_mode (chain, 0, 1, exit);

    if (exit == URJ_CHAIN_EXITMODE_IDLE && bfin_check_emuready)
        part_check_emuready (chain, n);
}
Esempio n. 5
0
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;
}