ubsan: m68hc1x: left shift of negative value

* m68hc11-dis.c (read_memory): Delete forward decls.
	(print_indexed_operand, print_insn): Likewise.
	(print_indexed_operand): Formatting.  Don't rely on short being
	exactly 16 bits, make sign extension explicit.
	(print_insn): Likewise.  Avoid signed overflow.
This commit is contained in:
Alan Modra
2019-12-20 10:56:29 +10:30
parent 9d78076ef8
commit 000fe1a756
2 changed files with 81 additions and 105 deletions

View File

@ -1,3 +1,11 @@
2019-12-20 Alan Modra <amodra@gmail.com>
* m68hc11-dis.c (read_memory): Delete forward decls.
(print_indexed_operand, print_insn): Likewise.
(print_indexed_operand): Formatting. Don't rely on short being
exactly 16 bits, make sign extension explicit.
(print_insn): Likewise. Avoid signed overflow.
2019-12-19 Alan Modra <amodra@gmail.com> 2019-12-19 Alan Modra <amodra@gmail.com>
* vax-dis.c (print_insn_mode): Stop index mode recursion. * vax-dis.c (print_insn_mode): Stop index mode recursion.

View File

@ -45,11 +45,6 @@ static const char *const reg_dst_table[] =
#define OP_PAGE_MASK (M6811_OP_PAGE2|M6811_OP_PAGE3|M6811_OP_PAGE4) #define OP_PAGE_MASK (M6811_OP_PAGE2|M6811_OP_PAGE3|M6811_OP_PAGE4)
/* Prototypes for local functions. */
static int read_memory (bfd_vma, bfd_byte *, int, struct disassemble_info *);
static int print_indexed_operand (bfd_vma, struct disassemble_info *,
int*, int, int, bfd_vma, int);
static int print_insn (bfd_vma, struct disassemble_info *, int);
static int static int
read_memory (bfd_vma memaddr, bfd_byte* buffer, int size, read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
@ -79,7 +74,7 @@ print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
bfd_byte buffer[4]; bfd_byte buffer[4];
int reg; int reg;
int status; int status;
short sval; bfd_vma val;
int pos = 1; int pos = 1;
if (indirect) if (indirect)
@ -95,21 +90,20 @@ print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
if ((buffer[0] & 0x20) == 0) if ((buffer[0] & 0x20) == 0)
{ {
reg = (buffer[0] >> 6) & 3; reg = (buffer[0] >> 6) & 3;
sval = (buffer[0] & 0x1f); val = ((buffer[0] & 0x1f) ^ 0x10) - 0x10;
if (sval & 0x10)
sval |= 0xfff0;
/* 68HC12 requires an adjustment for movb/movw pc relative modes. */ /* 68HC12 requires an adjustment for movb/movw pc relative modes. */
if (reg == PC_REGNUM && info->mach == bfd_mach_m6812 && mov_insn) if (reg == PC_REGNUM && info->mach == bfd_mach_m6812 && mov_insn)
sval += pc_offset; val += pc_offset;
(*info->fprintf_func) (info->stream, "0x%x,%s", (*info->fprintf_func) (info->stream, "0x%x,%s",
(unsigned short) sval, reg_name[reg]); (unsigned) val & 0xffff, reg_name[reg]);
if (reg == PC_REGNUM) if (reg == PC_REGNUM)
{ {
(* info->fprintf_func) (info->stream, " {"); (* info->fprintf_func) (info->stream, " {");
if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */ /* Avoid duplicate 0x from core binutils. */
if (info->symtab_size > 0)
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
(* info->print_address_func) (endaddr + sval, info); (* info->print_address_func) (endaddr + val, info);
(* info->fprintf_func) (info->stream, "}"); (* info->fprintf_func) (info->stream, "}");
} }
} }
@ -120,22 +114,21 @@ print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
const char *mode; const char *mode;
reg = (buffer[0] >> 6) & 3; reg = (buffer[0] >> 6) & 3;
sval = (buffer[0] & 0x0f); val = buffer[0] & 7;
if (sval & 0x8) if (buffer[0] & 8)
{ {
sval |= 0xfff0; val = 8 - val;
sval = -sval;
mode = "-"; mode = "-";
} }
else else
{ {
sval = sval + 1; val = val + 1;
mode = "+"; mode = "+";
} }
(*info->fprintf_func) (info->stream, "%d,%s%s%s", (*info->fprintf_func) (info->stream, "%d,%s%s%s",
(unsigned short) sval, (unsigned) val,
(buffer[0] & 0x10 ? "" : mode), buffer[0] & 0x10 ? "" : mode,
reg_name[reg], (buffer[0] & 0x10 ? mode : "")); reg_name[reg], buffer[0] & 0x10 ? mode : "");
} }
/* [n,r] 16-bits offset indexed indirect. */ /* [n,r] 16-bits offset indexed indirect. */
@ -150,14 +143,12 @@ print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
reg = (buffer[0] >> 3) & 0x03; reg = (buffer[0] >> 3) & 0x03;
status = read_memory (memaddr + pos, &buffer[0], 2, info); status = read_memory (memaddr + pos, &buffer[0], 2, info);
if (status != 0) if (status != 0)
{
return status; return status;
}
pos += 2; pos += 2;
sval = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); val = (buffer[0] << 8) | buffer[1];
(*info->fprintf_func) (info->stream, "[0x%x,%s]", (*info->fprintf_func) (info->stream, "[0x%x,%s]",
sval & 0x0ffff, reg_name[reg]); (unsigned) val & 0xffff, reg_name[reg]);
if (indirect) if (indirect)
*indirect = 1; *indirect = 1;
} }
@ -176,30 +167,26 @@ print_indexed_operand (bfd_vma memaddr, struct disassemble_info* info,
status = read_memory (memaddr + pos, status = read_memory (memaddr + pos,
&buffer[1], (buffer[0] & 0x2 ? 2 : 1), info); &buffer[1], (buffer[0] & 0x2 ? 2 : 1), info);
if (status != 0) if (status != 0)
{
return status; return status;
}
if (buffer[0] & 2) if (buffer[0] & 2)
{ {
sval = ((buffer[1] << 8) | (buffer[2] & 0x0FF)); val = (((buffer[1] << 8) | buffer[2]) ^ 0x8000) - 0x8000;
sval &= 0x0FFFF;
pos += 2; pos += 2;
endaddr += 2; endaddr += 2;
} }
else else
{ {
sval = buffer[1] & 0x00ff; val = buffer[1] - ((buffer[0] & 1) << 8);
if (buffer[0] & 0x01)
sval |= 0xff00;
pos++; pos++;
endaddr++; endaddr++;
} }
(*info->fprintf_func) (info->stream, "0x%x,%s", (*info->fprintf_func) (info->stream, "0x%x,%s",
(unsigned short) sval, reg_name[reg]); (unsigned) val & 0xffff, reg_name[reg]);
if (reg == PC_REGNUM) if (reg == PC_REGNUM)
{ {
(* info->fprintf_func) (info->stream, " {0x"); (* info->fprintf_func) (info->stream, " {0x");
(* info->print_address_func) (endaddr + sval, info); (* info->print_address_func) (endaddr + val, info);
(* info->fprintf_func) (info->stream, "}"); (* info->fprintf_func) (info->stream, "}");
} }
} }
@ -238,12 +225,11 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
bfd_byte buffer[4]; bfd_byte buffer[4];
unsigned int code; unsigned int code;
long format, pos, i; long format, pos, i;
short sval; bfd_vma val;
const struct m68hc11_opcode *opcode; const struct m68hc11_opcode *opcode;
if (arch & cpuxgate) if (arch & cpuxgate)
{ {
int val;
/* Get two bytes as all XGATE instructions are 16bit. */ /* Get two bytes as all XGATE instructions are 16bit. */
status = read_memory (memaddr, buffer, 2, info); status = read_memory (memaddr, buffer, 2, info);
if (status != 0) if (status != 0)
@ -295,17 +281,14 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
else if (format & M68XG_OP_REL9) else if (format & M68XG_OP_REL9)
{ {
(*info->fprintf_func) (info->stream, " 0x"); (*info->fprintf_func) (info->stream, " 0x");
val = (buffer[0] & 0x1) ? buffer[1] | 0xFFFFFF00 : buffer[1]; val = buffer[1] - ((buffer[0] & 1) << 8);
(*info->print_address_func) (memaddr + (val << 1) + 2, info); (*info->print_address_func) (memaddr + (val << 1) + 2, info);
} }
else if (format & M68XG_OP_REL10) else if (format & M68XG_OP_REL10)
{ {
(*info->fprintf_func) (info->stream, " 0x"); (*info->fprintf_func) (info->stream, " 0x");
val = (buffer[0] << 8) | (unsigned int) buffer[1]; val = (buffer[0] << 8) | buffer[1];
if (val & 0x200) val = ((val & 0x3ff) ^ 0x200) - 0x200;
val |= 0xfffffc00;
else
val &= 0x000001ff;
(*info->print_address_func) (memaddr + (val << 1) + 2, info); (*info->print_address_func) (memaddr + (val << 1) + 2, info);
} }
else if ((code & 0x00ff) == 0x00f8) else if ((code & 0x00ff) == 0x00f8)
@ -639,13 +622,11 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
(*info->fprintf_func) (info->stream, "%s,", (*info->fprintf_func) (info->stream, "%s,",
reg_src_table[buffer[0] & 0x07]); reg_src_table[buffer[0] & 0x07]);
sval = buffer[1] & 0x0ff; val = buffer[1] - ((buffer[0] & 0x10) << 4);
if (buffer[0] & 0x10)
sval |= 0xff00;
pos += 2; pos += 2;
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
(*info->print_address_func) (memaddr + pos + sval, info); (*info->print_address_func) (memaddr + pos + val, info);
format &= ~(M6812_OP_REG | M6811_OP_JUMP_REL); format &= ~(M6812_OP_REG | M6811_OP_JUMP_REL);
} }
else if (format & (M6812_OP_REG | M6812_OP_REG_2)) else if (format & (M6812_OP_REG | M6812_OP_REG_2))
@ -662,7 +643,6 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
if (format & (M6811_OP_IMM16 | M6811_OP_IND16)) if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
{ {
int val;
bfd_vma addr; bfd_vma addr;
unsigned page = 0; unsigned page = 0;
@ -676,9 +656,7 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
offset = 0; offset = 0;
pos += 2; pos += 2;
val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); addr = val = (buffer[0] << 8) | buffer[1];
val &= 0x0FFFF;
addr = val;
pc_dst_offset = 2; pc_dst_offset = 2;
if (format & M6812_OP_PAGE) if (format & M6812_OP_PAGE)
{ {
@ -686,16 +664,15 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
if (status != 0) if (status != 0)
return status; return status;
page = (unsigned) buffer[0]; page = buffer[0];
if (addr >= M68HC12_BANK_BASE && addr < 0x0c000) if (addr >= M68HC12_BANK_BASE && addr < 0x0c000)
addr = ((val - M68HC12_BANK_BASE) addr = (val - M68HC12_BANK_BASE + (page << M68HC12_BANK_SHIFT)
| (page << M68HC12_BANK_SHIFT)) + M68HC12_BANK_VIRT);
+ M68HC12_BANK_VIRT;
} }
else if ((arch & cpu6812) else if ((arch & cpu6812)
&& addr >= M68HC12_BANK_BASE && addr < 0x0c000) && addr >= M68HC12_BANK_BASE && addr < 0x0c000)
{ {
int cur_page; unsigned cur_page;
bfd_vma vaddr; bfd_vma vaddr;
if (memaddr >= M68HC12_BANK_VIRT) if (memaddr >= M68HC12_BANK_VIRT)
@ -704,9 +681,8 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
else else
cur_page = 0; cur_page = 0;
vaddr = ((addr - M68HC12_BANK_BASE) vaddr = (addr - M68HC12_BANK_BASE
+ (cur_page << M68HC12_BANK_SHIFT)) + (cur_page << M68HC12_BANK_SHIFT)) + M68HC12_BANK_VIRT;
+ M68HC12_BANK_VIRT;
if (!info->symbol_at_address_func (addr, info) if (!info->symbol_at_address_func (addr, info)
&& info->symbol_at_address_func (vaddr, info)) && info->symbol_at_address_func (vaddr, info))
addr = vaddr; addr = vaddr;
@ -721,14 +697,16 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
format &= ~M6811_OP_IND16; format &= ~M6811_OP_IND16;
} }
if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */ /* Avoid duplicate 0x from core binutils. */
if (info->symtab_size > 0)
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
(*info->print_address_func) (addr, info); (*info->print_address_func) (addr, info);
if (format & M6812_OP_PAGE) if (format & M6812_OP_PAGE)
{ {
(* info->fprintf_func) (info->stream, " {"); (* info->fprintf_func) (info->stream, " {");
if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */ /* Avoid duplicate 0x from core binutils. */
if (info->symtab_size > 0)
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
(* info->print_address_func) (val, info); (* info->print_address_func) (val, info);
(* info->fprintf_func) (info->stream, ", 0x%x}", page); (* info->fprintf_func) (info->stream, ", 0x%x}", page);
@ -750,8 +728,6 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
if (format & M6812_OP_IND16_P2) if (format & M6812_OP_IND16_P2)
{ {
int val;
(*info->fprintf_func) (info->stream, ", "); (*info->fprintf_func) (info->stream, ", ");
status = read_memory (memaddr + pos + offset, &buffer[0], 2, info); status = read_memory (memaddr + pos + offset, &buffer[0], 2, info);
@ -760,9 +736,9 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
pos += 2; pos += 2;
val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); val = (buffer[0] << 8) | buffer[1];
val &= 0x0FFFF; /* Avoid duplicate 0x from core binutils. */
if (info->symtab_size > 0) /* Avoid duplicate 0x from core binutils. */ if (info->symtab_size > 0)
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
(*info->print_address_func) (val, info); (*info->print_address_func) (val, info);
} }
@ -784,30 +760,24 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
} }
if (format & M6811_OP_JUMP_REL) if (format & M6811_OP_JUMP_REL)
{ {
int val;
status = read_memory (memaddr + pos, &buffer[0], 1, info); status = read_memory (memaddr + pos, &buffer[0], 1, info);
if (status != 0) if (status != 0)
return status; return status;
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
pos++; pos++;
val = (buffer[0] & 0x80) ? buffer[0] | 0xFFFFFF00 : buffer[0]; val = (buffer[0] ^ 0x80) - 0x80;
(*info->print_address_func) (memaddr + pos + val, info); (*info->print_address_func) (memaddr + pos + val, info);
format &= ~M6811_OP_JUMP_REL; format &= ~M6811_OP_JUMP_REL;
} }
else if (format & M6812_OP_JUMP_REL16) else if (format & M6812_OP_JUMP_REL16)
{ {
int val;
status = read_memory (memaddr + pos, &buffer[0], 2, info); status = read_memory (memaddr + pos, &buffer[0], 2, info);
if (status != 0) if (status != 0)
return status; return status;
pos += 2; pos += 2;
val = ((buffer[0] << 8) | (buffer[1] & 0x0FF)); val = (((buffer[0] << 8) | buffer[1]) ^ 0x8000) - 0x8000;
if (val & 0x8000)
val |= 0xffff0000;
(*info->fprintf_func) (info->stream, "0x"); (*info->fprintf_func) (info->stream, "0x");
(*info->print_address_func) (memaddr + pos + val, info); (*info->print_address_func) (memaddr + pos + val, info);
@ -816,16 +786,14 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info, int arch)
if (format & M6812_OP_PAGE) if (format & M6812_OP_PAGE)
{ {
int val;
status = read_memory (memaddr + pos + offset, &buffer[0], 1, info); status = read_memory (memaddr + pos + offset, &buffer[0], 1, info);
if (status != 0) if (status != 0)
return status; return status;
pos += 1; pos += 1;
val = buffer[0] & 0x0ff; val = buffer[0];
(*info->fprintf_func) (info->stream, ", 0x%x", val); (*info->fprintf_func) (info->stream, ", 0x%x", (unsigned) val);
} }
#ifdef DEBUG #ifdef DEBUG