@@ -1663,85 +1663,74 @@ cris_constraint (const char *cs,
/* Format number as hex with a leading "0x" into outbuffer. */
-static char *
-format_hex (unsigned long number,
- char *outbuffer)
+static void
+format_hex(unsigned long number, GString *str)
{
/* Truncate negative numbers on >32-bit hosts. */
number &= 0xffffffff;
- sprintf (outbuffer, "0x%lx", number);
-
- return outbuffer + strlen (outbuffer);
+ g_string_append_printf(str, "0x%lx", number);
}
/* Format number as decimal into outbuffer. Parameter signedp says
whether the number should be formatted as signed (!= 0) or
unsigned (== 0). */
-static char *
-format_dec (long number, char *outbuffer, size_t outsize, int signedp)
+static void
+format_dec(long number, GString *str, int signedp)
{
- snprintf (outbuffer, outsize, signedp ? "%ld" : "%lu", number);
-
- return outbuffer + strlen (outbuffer);
+ if (signedp)
+ g_string_append_printf(str, "%ld", number);
+ else
+ g_string_append_printf(str, "%lu", number);
}
/* Format the name of the general register regno into outbuffer. */
-static char *
-format_reg (struct cris_disasm_data *disdata,
- int regno,
- char *outbuffer_start)
+static void
+format_reg(struct cris_disasm_data *disdata, int regno, GString *str)
{
- char *outbuffer = outbuffer_start;
-
- *outbuffer++ = REGISTER_PREFIX_CHAR;
+ g_string_append_c(str, REGISTER_PREFIX_CHAR);
switch (regno)
{
case 15:
/* For v32, there is no context in which we output PC. */
if (disdata->distype == cris_dis_v32)
- strcpy (outbuffer, "acr");
+ g_string_append(str, "acr");
else
- strcpy (outbuffer, "pc");
+ g_string_append(str, "pc");
break;
case 14:
- strcpy (outbuffer, "sp");
+ g_string_append(str, "sp");
break;
default:
- sprintf (outbuffer, "r%d", regno);
+ g_string_append_printf(str, "r%d", regno);
break;
}
-
- return outbuffer_start + strlen (outbuffer_start);
}
/* Format the name of a support register into outbuffer. */
-static char *
-format_sup_reg (unsigned int regno,
- char *outbuffer_start)
+static void
+format_sup_reg(unsigned int regno, GString *str)
{
- char *outbuffer = outbuffer_start;
int i;
- *outbuffer++ = REGISTER_PREFIX_CHAR;
+ g_string_append_c(str, REGISTER_PREFIX_CHAR);
for (i = 0; cris_support_regs[i].name != NULL; i++)
if (cris_support_regs[i].number == regno)
{
- sprintf (outbuffer, "%s", cris_support_regs[i].name);
- return outbuffer_start + strlen (outbuffer_start);
+ g_string_append(str, cris_support_regs[i].name);
+ return;
}
/* There's supposed to be register names covering all numbers, though
some may be generic names. */
- sprintf (outbuffer, "format_sup_reg-BUG");
- return outbuffer_start + strlen (outbuffer_start);
+ g_string_append(str, "format_sup_reg-BUG");
}
/* Return the length of an instruction. */
@@ -1797,8 +1786,8 @@ bytes_to_skip (unsigned int insn,
/* Print condition code flags. */
-static char *
-print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
+static void
+print_flags(struct cris_disasm_data *disdata, unsigned int insn, GString *str)
{
/* Use the v8 (Etrax 100) flag definitions for disassembly.
The differences with v0 (Etrax 1..4) vs. Svinto are:
@@ -1815,17 +1804,9 @@ print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
for (i = 0; i < 8; i++)
if (flagbits & (1 << i))
- *cp++ = fnames[i];
-
- return cp;
+ g_string_append_c(str, fnames[i]);
}
-#define FORMAT_DEC(number, tp, signedp) \
- format_dec (number, tp, ({ \
- assert(tp >= temp && tp <= temp + sizeof(temp)); \
- temp + sizeof(temp) - tp; \
- }), signedp)
-
/* Print out an insn with its operands, and update the info->insn_type
fields. The prefix_opcodep and the rest hold a prefix insn that is
supposed to be output as an address mode. */
@@ -1843,19 +1824,13 @@ print_with_operands (const struct cris_opcode *opcodep,
unsigned int prefix_insn,
unsigned char *prefix_buffer)
{
- /* Get a buffer of somewhat reasonable size where we store
- intermediate parts of the insn. */
- char temp[sizeof (".d [$r13=$r12-2147483648],$r10") * 2];
- char *tp = temp;
+ g_autoptr(GString) str = g_string_new(opcodep->name);
static const char mode_char[] = "bwd?";
const char *s;
const char *cs;
struct cris_disasm_data *disdata
= (struct cris_disasm_data *) info->private_data;
- /* Print out the name first thing we do. */
- (*info->fprintf_func) (info->stream, "%s", opcodep->name);
-
cs = opcodep->args;
s = cs;
@@ -1865,13 +1840,13 @@ print_with_operands (const struct cris_opcode *opcodep,
if (*s == 'm' || *s == 'M' || *s == 'z')
{
- *tp++ = '.';
+ g_string_append_c(str, '.');
/* Get the size-letter. */
- *tp++ = *s == 'M'
- ? (insn & 0x8000 ? 'd'
- : insn & 0x4000 ? 'w' : 'b')
- : mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)];
+ if (*s == 'M')
+ g_string_append_c(str, insn & 0x8000 ? 'd' : insn & 0x4000 ? 'w' : 'b');
+ else
+ g_string_append_c(str, mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)]);
/* Ignore the size and the space character that follows. */
s += 2;
@@ -1880,7 +1855,7 @@ print_with_operands (const struct cris_opcode *opcodep,
/* Add a space if this isn't a long-branch, because for those will add
the condition part of the name later. */
if (opcodep->match != (BRANCH_PC_LOW + BRANCH_INCR_HIGH * 256))
- *tp++ = ' ';
+ g_string_append_c(str, ' ');
/* Fill in the insn-type if deducible from the name (and there's no
better way). */
@@ -1903,20 +1878,18 @@ print_with_operands (const struct cris_opcode *opcodep,
switch (*s)
{
case 'T':
- tp = format_sup_reg ((insn >> 12) & 15, tp);
+ format_sup_reg((insn >> 12) & 15, str);
break;
case 'A':
- *tp++ = REGISTER_PREFIX_CHAR;
- *tp++ = 'a';
- *tp++ = 'c';
- *tp++ = 'r';
+ g_string_append_c(str, REGISTER_PREFIX_CHAR);
+ g_string_append(str, "acr");
break;
case '[':
case ']':
case ',':
- *tp++ = *s;
+ g_string_append_c(str, *s);
break;
case '!':
@@ -1939,11 +1912,11 @@ print_with_operands (const struct cris_opcode *opcodep,
case 'D':
case 'r':
- tp = format_reg (disdata, insn & 15, tp);
+ format_reg(disdata, insn & 15, str);
break;
case 'R':
- tp = format_reg (disdata, (insn >> 12) & 15, tp);
+ format_reg(disdata, (insn >> 12) & 15, str);
break;
case 'n':
@@ -1953,13 +1926,7 @@ print_with_operands (const struct cris_opcode *opcodep,
= (buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+ buffer[5] * 0x1000000 + addr);
- /* Finish off and output previous formatted bytes. */
- *tp = 0;
- if (temp[0])
- (*info->fprintf_func) (info->stream, "%s", temp);
- tp = temp;
-
- (*info->print_address_func) ((bfd_vma) number, info);
+ format_hex(number, str);
}
break;
@@ -1968,13 +1935,7 @@ print_with_operands (const struct cris_opcode *opcodep,
/* Like n but the offset is bits <3:0> in the instruction. */
unsigned long number = (buffer[0] & 0xf) * 2 + addr;
- /* Finish off and output previous formatted bytes. */
- *tp = 0;
- if (temp[0])
- (*info->fprintf_func) (info->stream, "%s", temp);
- tp = temp;
-
- (*info->print_address_func) ((bfd_vma) number, info);
+ format_hex(number, str);
}
break;
@@ -2045,43 +2006,16 @@ print_with_operands (const struct cris_opcode *opcodep,
break;
default:
- strcpy (tp, "bug");
- tp += 3;
+ g_string_append(str, "bug");
number = 42;
}
if ((*cs == 'z' && (insn & 0x20))
|| (opcodep->match == BDAP_QUICK_OPCODE
&& (nbytes <= 2 || buffer[1 + nbytes] == 0)))
- tp = FORMAT_DEC (number, tp, signedp);
+ format_dec(number, str, signedp);
else
- {
- unsigned int highbyte = (number >> 24) & 0xff;
-
- /* Either output this as an address or as a number. If it's
- a dword with the same high-byte as the address of the
- insn, assume it's an address, and also if it's a non-zero
- non-0xff high-byte. If this is a jsr or a jump, then
- it's definitely an address. */
- if (nbytes == 4
- && (highbyte == ((addr >> 24) & 0xff)
- || (highbyte != 0 && highbyte != 0xff)
- || info->insn_type == dis_branch
- || info->insn_type == dis_jsr))
- {
- /* Finish off and output previous formatted bytes. */
- *tp = 0;
- tp = temp;
- if (temp[0])
- (*info->fprintf_func) (info->stream, "%s", temp);
-
- (*info->print_address_func) ((bfd_vma) number, info);
-
- info->target = number;
- }
- else
- tp = format_hex (number, tp);
- }
+ format_hex(number, str);
}
else
{
@@ -2116,7 +2050,7 @@ print_with_operands (const struct cris_opcode *opcodep,
info->data_size = size;
}
- *tp++ = '[';
+ g_string_append_c(str, '[');
if (prefix_opcodep
/* We don't match dip with a postincremented field
@@ -2126,8 +2060,8 @@ print_with_operands (const struct cris_opcode *opcodep,
{
if (insn & 0x400)
{
- tp = format_reg (disdata, insn & 15, tp);
- *tp++ = '=';
+ format_reg(disdata, insn & 15, str);
+ g_string_append_c(str, '=');
}
@@ -2146,16 +2080,7 @@ print_with_operands (const struct cris_opcode *opcodep,
+ prefix_buffer[4] * 65536
+ prefix_buffer[5] * 0x1000000;
- info->target = (bfd_vma) number;
-
- /* Finish off and output previous formatted
- data. */
- *tp = 0;
- tp = temp;
- if (temp[0])
- (*info->fprintf_func) (info->stream, "%s", temp);
-
- (*info->print_address_func) ((bfd_vma) number, info);
+ format_hex(number, str);
}
else
{
@@ -2167,11 +2092,11 @@ print_with_operands (const struct cris_opcode *opcodep,
info->target2 = prefix_insn & 15;
- *tp++ = '[';
- tp = format_reg (disdata, prefix_insn & 15, tp);
+ g_string_append_c(str, '[');
+ format_reg(disdata, prefix_insn & 15, str);
if (prefix_insn & 0x400)
- *tp++ = '+';
- *tp++ = ']';
+ g_string_append_c(str, '+');
+ g_string_append_c(str, ']');
}
break;
@@ -2184,10 +2109,10 @@ print_with_operands (const struct cris_opcode *opcodep,
number -= 256;
/* Output "reg+num" or, if num < 0, "reg-num". */
- tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp);
+ format_reg(disdata, (prefix_insn >> 12) & 15, str);
if (number >= 0)
- *tp++ = '+';
- tp = FORMAT_DEC (number, tp, 1);
+ g_string_append_c(str, '+');
+ format_dec(number, str, 1);
info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
info->target = (prefix_insn >> 12) & 15;
@@ -2197,16 +2122,15 @@ print_with_operands (const struct cris_opcode *opcodep,
case BIAP_OPCODE:
/* Output "r+R.m". */
- tp = format_reg (disdata, prefix_insn & 15, tp);
- *tp++ = '+';
- tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp);
- *tp++ = '.';
- *tp++ = mode_char[(prefix_insn >> 4) & 3];
+ format_reg(disdata, prefix_insn & 15, str);
+ g_string_append_c(str, '+');
+ format_reg(disdata, (prefix_insn >> 12) & 15, str);
+ g_string_append_c(str, '.');
+ g_string_append_c(str, mode_char[(prefix_insn >> 4) & 3]);
info->flags
|= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
| CRIS_DIS_FLAG_MEM_TARGET_IS_REG
-
| ((prefix_insn & 0x8000)
? CRIS_DIS_FLAG_MEM_TARGET2_MULT4
: ((prefix_insn & 0x8000)
@@ -2214,9 +2138,8 @@ print_with_operands (const struct cris_opcode *opcodep,
break;
case BDAP_INDIR_OPCODE:
- /* Output "r+s.m", or, if "s" is [pc+], "r+s" or
- "r-s". */
- tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp);
+ /* Output "r+s.m", or, if "s" is [pc+], "r+s" or "r-s". */
+ format_reg(disdata, (prefix_insn >> 12) & 15, str);
if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
{
@@ -2253,8 +2176,7 @@ print_with_operands (const struct cris_opcode *opcodep,
break;
default:
- strcpy (tp, "bug");
- tp += 3;
+ g_string_append(str, "bug");
number = 42;
}
@@ -2265,39 +2187,32 @@ print_with_operands (const struct cris_opcode *opcodep,
address. */
if (nbytes == 4)
{
- /* Finish off and output previous formatted
- bytes. */
- *tp++ = '+';
- *tp = 0;
- tp = temp;
- (*info->fprintf_func) (info->stream, "%s", temp);
-
- (*info->print_address_func) ((bfd_vma) number, info);
+ g_string_append_c(str, '+');
+ format_hex(number, str);
}
else
{
if (number >= 0)
- *tp++ = '+';
- tp = FORMAT_DEC (number, tp, 1);
+ g_string_append_c(str, '+');
+ format_dec(number, str, 1);
}
}
else
{
/* Output "r+[R].m" or "r+[R+].m". */
- *tp++ = '+';
- *tp++ = '[';
- tp = format_reg (disdata, prefix_insn & 15, tp);
+ g_string_append_c(str, '+');
+ g_string_append_c(str, '[');
+ format_reg(disdata, prefix_insn & 15, str);
if (prefix_insn & 0x400)
- *tp++ = '+';
- *tp++ = ']';
- *tp++ = '.';
- *tp++ = mode_char[(prefix_insn >> 4) & 3];
+ g_string_append_c(str, '+');
+ g_string_append_c(str, ']');
+ g_string_append_c(str, '.');
+ g_string_append_c(str, mode_char[(prefix_insn >> 4) & 3]);
info->flags
|= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
| CRIS_DIS_FLAG_MEM_TARGET2_MEM
| CRIS_DIS_FLAG_MEM_TARGET_IS_REG
-
| (((prefix_insn >> 4) == 2)
? 0
: (((prefix_insn >> 4) & 3) == 1
@@ -2315,26 +2230,26 @@ print_with_operands (const struct cris_opcode *opcodep,
}
else
{
- tp = format_reg (disdata, insn & 15, tp);
+ format_reg(disdata, insn & 15, str);
info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
info->target = insn & 15;
if (insn & 0x400)
- *tp++ = '+';
+ g_string_append_c(str, '+');
}
- *tp++ = ']';
+ g_string_append_c(str, ']');
}
break;
case 'x':
- tp = format_reg (disdata, (insn >> 12) & 15, tp);
- *tp++ = '.';
- *tp++ = mode_char[(insn >> 4) & 3];
+ format_reg(disdata, (insn >> 12) & 15, str);
+ g_string_append_c(str, '.');
+ g_string_append_c(str, mode_char[(insn >> 4) & 3]);
break;
case 'I':
- tp = FORMAT_DEC (insn & 63, tp, 0);
+ format_dec(insn & 63, str, 0);
break;
case 'b':
@@ -2353,21 +2268,17 @@ print_with_operands (const struct cris_opcode *opcodep,
info->target = (bfd_vma) where;
- *tp = 0;
- tp = temp;
- (*info->fprintf_func) (info->stream, "%s%s ",
- temp, cris_cc_strings[insn >> 12]);
-
- (*info->print_address_func) ((bfd_vma) where, info);
+ g_string_append(str, cris_cc_strings[insn >> 12]);
+ format_hex(where, str);
}
break;
case 'c':
- tp = FORMAT_DEC (insn & 31, tp, 0);
+ format_dec(insn & 31, str, 0);
break;
case 'C':
- tp = FORMAT_DEC (insn & 15, tp, 0);
+ format_dec(insn & 15, str, 0);
break;
case 'o':
@@ -2385,10 +2296,7 @@ print_with_operands (const struct cris_opcode *opcodep,
target = addr + ((disdata->distype == cris_dis_v32) ? 0 : 2) + offset;
info->target = target;
- *tp = 0;
- tp = temp;
- (*info->fprintf_func) (info->stream, "%s", temp);
- (*info->print_address_func) (target, info);
+ format_hex(target, str);
}
break;
@@ -2400,18 +2308,18 @@ print_with_operands (const struct cris_opcode *opcodep,
if (number > 127)
number = number - 256;
- tp = FORMAT_DEC (number, tp, 1);
- *tp++ = ',';
- tp = format_reg (disdata, (insn >> 12) & 15, tp);
+ format_dec(number, str, 1);
+ g_string_append_c(str, ',');
+ format_reg(disdata, (insn >> 12) & 15, str);
}
break;
case 'f':
- tp = print_flags (disdata, insn, tp);
+ print_flags(disdata, insn, str);
break;
case 'i':
- tp = FORMAT_DEC ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
+ format_dec((insn & 32) ? (insn & 31) | ~31L : insn & 31, str, 1);
break;
case 'P':
@@ -2421,29 +2329,25 @@ print_with_operands (const struct cris_opcode *opcodep,
if (sregp == NULL || sregp->name == NULL)
/* Should have been caught as a non-match earlier. */
- *tp++ = '?';
+ g_string_append_c(str, '?');
else
{
- *tp++ = REGISTER_PREFIX_CHAR;
- strcpy (tp, sregp->name);
- tp += strlen (tp);
+ g_string_append_c(str, REGISTER_PREFIX_CHAR);
+ g_string_append(str, sregp->name);
}
}
break;
default:
- strcpy (tp, "???");
- tp += 3;
+ g_string_append(str, "???");
}
}
- *tp = 0;
-
if (prefix_opcodep)
- (*info->fprintf_func) (info->stream, " (OOPS unused prefix \"%s: %s\")",
+ (*info->fprintf_func) (info->stream, "(OOPS unused prefix \"%s: %s\") ",
prefix_opcodep->name, prefix_opcodep->args);
- (*info->fprintf_func) (info->stream, "%s", temp);
+ (*info->fprintf_func) (info->stream, "%s", str->str);
}
sprintf() is deprecated on Darwin since macOS 13.0 / XCode 14.1. Use GString in the core of the disassembler instead of buffering the string locally. Instead of info->print_address_func, use format_hex for addresses. Printing a hex number is what print_address_func does, and using format_hex properly truncates the 32-bit bit address. E.g. -0x00080988: move.d 0xfffffffffeda49ff,$r4 +0x00080988: move.d 0xfeda49ff,$r4 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- disas/cris.c | 288 +++++++++++++++++---------------------------------- 1 file changed, 96 insertions(+), 192 deletions(-)