diff --git a/urjtag/ChangeLog b/urjtag/ChangeLog index 2583838a..c8051a18 100644 --- a/urjtag/ChangeLog +++ b/urjtag/ChangeLog @@ -3,6 +3,10 @@ * src/cmd/cmd_bfin.c: Replace one-insn-a-file option with dynamic instruction counting so multi-instructions are properly parsed. + * include/urjtag/tap_register.h, src/tap/register.c: Add new helper functions + for setting tap registers based on hex/bit strings. + * src/cmd/cmd_dr.c: Drop parsing code in favor of new helper functions. + 2010-01-28 Arnim Laeuger * src/bus/mpc837x.c, src/bus/buses_list.h, src/bus/Makefile.am, diff --git a/urjtag/include/urjtag/tap_register.h b/urjtag/include/urjtag/tap_register.h index 610cb5e3..81a35866 100644 --- a/urjtag/include/urjtag/tap_register.h +++ b/urjtag/include/urjtag/tap_register.h @@ -39,6 +39,8 @@ urj_tap_register_t *urj_tap_register_alloc (int len); urj_tap_register_t *urj_tap_register_duplicate (const urj_tap_register_t *tr); void urj_tap_register_free (urj_tap_register_t *tr); urj_tap_register_t *urj_tap_register_fill (urj_tap_register_t *tr, int val); +int urj_tap_register_set_string (urj_tap_register_t *tr, const char *str); +int urj_tap_register_set_value (urj_tap_register_t *tr, uint64_t val); const char *urj_tap_register_get_string (const urj_tap_register_t *tr); uint64_t urj_tap_register_get_value (const urj_tap_register_t *tr); /** @return 0 or 1 on success; -1 on error */ diff --git a/urjtag/src/cmd/cmd_dr.c b/urjtag/src/cmd/cmd_dr.c index a7510540..9e6cb435 100644 --- a/urjtag/src/cmd/cmd_dr.c +++ b/urjtag/src/cmd/cmd_dr.c @@ -24,6 +24,7 @@ #include +#include #include #include @@ -85,28 +86,9 @@ cmd_dr_run (urj_chain_t *chain, char *params[]) dir = 1; else { - unsigned int bit; - if (strspn (params[1], "01") != strlen (params[1])) - { - urj_error_set (URJ_ERROR_SYNTAX, - "bit patterns should be 0s and 1s, not '%s'", - params[1]); - return URJ_STATUS_FAIL; - } - - r = dr->in; - if (r->len != strlen (params[1])) - { - urj_error_set (URJ_ERROR_OUT_OF_BOUNDS, - _("%s: register length %d mismatch: %zd"), - "dr", r->len, strlen (params[1])); - return URJ_STATUS_FAIL; - } - for (bit = 0; params[1][bit]; bit++) - { - r->data[r->len - 1 - bit] = (params[1][bit] == '1'); - } - + int ret = urj_tap_register_set_string (dr->in, params[1]); + if (ret != URJ_STATUS_OK) + return ret; dir = 0; } } @@ -115,7 +97,9 @@ cmd_dr_run (urj_chain_t *chain, char *params[]) r = dr->out; else r = dr->in; - urj_log (URJ_LOG_LEVEL_NORMAL, _("%s\n"), urj_tap_register_get_string (r)); + urj_log (URJ_LOG_LEVEL_NORMAL, "%s (0x%0*" PRIX64 ")\n", + urj_tap_register_get_string (r), r->len / 4, + urj_tap_register_get_value (r)); return URJ_STATUS_OK; } @@ -126,12 +110,14 @@ cmd_dr_help (void) urj_log (URJ_LOG_LEVEL_NORMAL, _("Usage: %s [DIR]\n" "Usage: %s BITSTRING\n" + "Usage: %s HEXSTRING\n" "Display input or output data register content or set current register.\n" "\n" "DIR requested data register; possible values: 'in' for\n" " input and 'out' for output; default is 'out'\n" - "BITSTRING set current data register with BITSTRING (e.g. 01010)\n"), - "dr", "dr"); + "BITSTRING set current data register with BITSTRING (e.g. 01010)\n" + "HEXSTRING set current data register with HEXSTRING (e.g. 0x123)\n"), + "dr", "dr", "dr"); } const urj_cmd_t urj_cmd_dr = { diff --git a/urjtag/src/tap/register.c b/urjtag/src/tap/register.c index 269bbee9..0c012c8b 100644 --- a/urjtag/src/tap/register.c +++ b/urjtag/src/tap/register.c @@ -22,6 +22,9 @@ * */ +#include + +#include #include #include @@ -108,6 +111,69 @@ urj_tap_register_fill (urj_tap_register_t *tr, int val) return tr; } +int +urj_tap_register_set_string (urj_tap_register_t *tr, const char *str) +{ + if (strncmp (str, "0x", 2) == 0) + { + /* Hex values */ + uint64_t val; + + if (sscanf (str, "%"PRIX64, &val) != 1) + { + urj_error_set (URJ_ERROR_SYNTAX, + _("invalid hex string '%s'"), + str); + return URJ_STATUS_FAIL; + } + return urj_tap_register_set_value (tr, val); + } + else + { + /* Bit string */ + unsigned int bit; + + if (strspn (str, "01") != strlen (str)) + { + urj_error_set (URJ_ERROR_SYNTAX, + _("bit patterns should be 0s and 1s, not '%s'"), + str); + return URJ_STATUS_FAIL; + } + else if (tr->len != strlen (str)) + { + urj_error_set (URJ_ERROR_OUT_OF_BOUNDS, + _("register length %d mismatch: %zd"), + tr->len, strlen (str)); + return URJ_STATUS_FAIL; + } + + for (bit = 0; str[bit]; ++bit) + tr->data[tr->len - 1 - bit] = (str[bit] == '1'); + + return URJ_STATUS_OK; + } +} + +int +urj_tap_register_set_value (urj_tap_register_t *tr, uint64_t val) +{ + unsigned int bit; + + if (val >> tr->len) + { + urj_error_set (URJ_ERROR_OUT_OF_BOUNDS, + _("register value 0x%"PRIX64" will not fit in %d bits"), + val, tr->len); + return URJ_STATUS_FAIL; + } + + for (bit = 0; bit < tr->len; ++bit) + tr->data[tr->len - 1 - bit] = !!(val & (1 << (tr->len - 1 - bit))); + + return URJ_STATUS_OK; +} + const char * urj_tap_register_get_string (const urj_tap_register_t *tr) {