Revision 99e051b2904f7c1dbf451725494f5d39fba4519d authored by Eric Blake on 11 June 2018, 21:39:27 UTC, committed by Michael Roth on 21 June 2018, 01:45:07 UTC
Although qemu-img creates aligned files (by rounding up), it must also gracefully handle files that are not sector-aligned. Test that the bug fixed in the previous patch does not recur. It's a bit annoying that we can see the (implicit) hole past the end of the file on to the next sector boundary, so if we ever reach the point where we report a byte-accurate size rather than our current behavior of always rounding up, this test will probably need a slight modification. Signed-off-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> (cherry picked from commit c6a9d2f6f9bc0c163b3a3073126464a2446bad5f) Conflicts: tests/qemu-iotests/group * drop context dep on tests not present in 2.11 Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
1 parent 9c5a843
moxie.c
/* Disassemble moxie instructions.
Copyright (c) 2009 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
#include "qemu/osdep.h"
#define STATIC_TABLE
#define DEFINE_TABLE
#include "disas/bfd.h"
static void *stream;
/* Form 1 instructions come in different flavors:
Some have no arguments (MOXIE_F1_NARG)
Some only use the A operand (MOXIE_F1_A)
Some use A and B registers (MOXIE_F1_AB)
Some use A and consume a 4 byte immediate value (MOXIE_F1_A4)
Some use just a 4 byte immediate value (MOXIE_F1_4)
Some use just a 4 byte memory address (MOXIE_F1_M)
Some use B and an indirect A (MOXIE_F1_AiB)
Some use A and an indirect B (MOXIE_F1_ABi)
Some consume a 4 byte immediate value and use X (MOXIE_F1_4A)
Some use B and an indirect A plus 4 bytes (MOXIE_F1_AiB4)
Some use A and an indirect B plus 4 bytes (MOXIE_F1_ABi4)
Form 2 instructions also come in different flavors:
Some have no arguments (MOXIE_F2_NARG)
Some use the A register and an 8-bit value (MOXIE_F2_A8V)
Form 3 instructions also come in different flavors:
Some have no arguments (MOXIE_F3_NARG)
Some have a 10-bit PC relative operand (MOXIE_F3_PCREL). */
#define MOXIE_F1_NARG 0x100
#define MOXIE_F1_A 0x101
#define MOXIE_F1_AB 0x102
/* #define MOXIE_F1_ABC 0x103 */
#define MOXIE_F1_A4 0x104
#define MOXIE_F1_4 0x105
#define MOXIE_F1_AiB 0x106
#define MOXIE_F1_ABi 0x107
#define MOXIE_F1_4A 0x108
#define MOXIE_F1_AiB4 0x109
#define MOXIE_F1_ABi4 0x10a
#define MOXIE_F1_M 0x10b
#define MOXIE_F2_NARG 0x200
#define MOXIE_F2_A8V 0x201
#define MOXIE_F3_NARG 0x300
#define MOXIE_F3_PCREL 0x301
typedef struct moxie_opc_info_t {
short opcode;
unsigned itype;
const char * name;
} moxie_opc_info_t;
extern const moxie_opc_info_t moxie_form1_opc_info[64];
extern const moxie_opc_info_t moxie_form2_opc_info[4];
extern const moxie_opc_info_t moxie_form3_opc_info[16];
/* The moxie processor's 16-bit instructions come in two forms:
FORM 1 instructions start with a 0 bit...
0oooooooaaaabbbb
0 F
ooooooo - form 1 opcode number
aaaa - operand A
bbbb - operand B
FORM 2 instructions start with bits "10"...
10ooaaaavvvvvvvv
0 F
oo - form 2 opcode number
aaaa - operand A
vvvvvvvv - 8-bit immediate value
FORM 3 instructions start with a bits "11"...
11oooovvvvvvvvvv
0 F
oooo - form 3 opcode number
vvvvvvvvvv - 10-bit immediate value. */
const moxie_opc_info_t moxie_form1_opc_info[64] =
{
{ 0x00, MOXIE_F1_NARG, "nop" },
{ 0x01, MOXIE_F1_A4, "ldi.l" },
{ 0x02, MOXIE_F1_AB, "mov" },
{ 0x03, MOXIE_F1_M, "jsra" },
{ 0x04, MOXIE_F1_NARG, "ret" },
{ 0x05, MOXIE_F1_AB, "add.l" },
{ 0x06, MOXIE_F1_AB, "push" },
{ 0x07, MOXIE_F1_AB, "pop" },
{ 0x08, MOXIE_F1_A4, "lda.l" },
{ 0x09, MOXIE_F1_4A, "sta.l" },
{ 0x0a, MOXIE_F1_ABi, "ld.l" },
{ 0x0b, MOXIE_F1_AiB, "st.l" },
{ 0x0c, MOXIE_F1_ABi4, "ldo.l" },
{ 0x0d, MOXIE_F1_AiB4, "sto.l" },
{ 0x0e, MOXIE_F1_AB, "cmp" },
{ 0x0f, MOXIE_F1_NARG, "bad" },
{ 0x10, MOXIE_F1_NARG, "bad" },
{ 0x11, MOXIE_F1_NARG, "bad" },
{ 0x12, MOXIE_F1_NARG, "bad" },
{ 0x13, MOXIE_F1_NARG, "bad" },
{ 0x14, MOXIE_F1_NARG, "bad" },
{ 0x15, MOXIE_F1_NARG, "bad" },
{ 0x16, MOXIE_F1_NARG, "bad" },
{ 0x17, MOXIE_F1_NARG, "bad" },
{ 0x18, MOXIE_F1_NARG, "bad" },
{ 0x19, MOXIE_F1_A, "jsr" },
{ 0x1a, MOXIE_F1_M, "jmpa" },
{ 0x1b, MOXIE_F1_A4, "ldi.b" },
{ 0x1c, MOXIE_F1_ABi, "ld.b" },
{ 0x1d, MOXIE_F1_A4, "lda.b" },
{ 0x1e, MOXIE_F1_AiB, "st.b" },
{ 0x1f, MOXIE_F1_4A, "sta.b" },
{ 0x20, MOXIE_F1_A4, "ldi.s" },
{ 0x21, MOXIE_F1_ABi, "ld.s" },
{ 0x22, MOXIE_F1_A4, "lda.s" },
{ 0x23, MOXIE_F1_AiB, "st.s" },
{ 0x24, MOXIE_F1_4A, "sta.s" },
{ 0x25, MOXIE_F1_A, "jmp" },
{ 0x26, MOXIE_F1_AB, "and" },
{ 0x27, MOXIE_F1_AB, "lshr" },
{ 0x28, MOXIE_F1_AB, "ashl" },
{ 0x29, MOXIE_F1_AB, "sub.l" },
{ 0x2a, MOXIE_F1_AB, "neg" },
{ 0x2b, MOXIE_F1_AB, "or" },
{ 0x2c, MOXIE_F1_AB, "not" },
{ 0x2d, MOXIE_F1_AB, "ashr" },
{ 0x2e, MOXIE_F1_AB, "xor" },
{ 0x2f, MOXIE_F1_AB, "mul.l" },
{ 0x30, MOXIE_F1_4, "swi" },
{ 0x31, MOXIE_F1_AB, "div.l" },
{ 0x32, MOXIE_F1_AB, "udiv.l" },
{ 0x33, MOXIE_F1_AB, "mod.l" },
{ 0x34, MOXIE_F1_AB, "umod.l" },
{ 0x35, MOXIE_F1_NARG, "brk" },
{ 0x36, MOXIE_F1_ABi4, "ldo.b" },
{ 0x37, MOXIE_F1_AiB4, "sto.b" },
{ 0x38, MOXIE_F1_ABi4, "ldo.s" },
{ 0x39, MOXIE_F1_AiB4, "sto.s" },
{ 0x3a, MOXIE_F1_NARG, "bad" },
{ 0x3b, MOXIE_F1_NARG, "bad" },
{ 0x3c, MOXIE_F1_NARG, "bad" },
{ 0x3d, MOXIE_F1_NARG, "bad" },
{ 0x3e, MOXIE_F1_NARG, "bad" },
{ 0x3f, MOXIE_F1_NARG, "bad" }
};
const moxie_opc_info_t moxie_form2_opc_info[4] =
{
{ 0x00, MOXIE_F2_A8V, "inc" },
{ 0x01, MOXIE_F2_A8V, "dec" },
{ 0x02, MOXIE_F2_A8V, "gsr" },
{ 0x03, MOXIE_F2_A8V, "ssr" }
};
const moxie_opc_info_t moxie_form3_opc_info[16] =
{
{ 0x00, MOXIE_F3_PCREL,"beq" },
{ 0x01, MOXIE_F3_PCREL,"bne" },
{ 0x02, MOXIE_F3_PCREL,"blt" },
{ 0x03, MOXIE_F3_PCREL,"bgt" },
{ 0x04, MOXIE_F3_PCREL,"bltu" },
{ 0x05, MOXIE_F3_PCREL,"bgtu" },
{ 0x06, MOXIE_F3_PCREL,"bge" },
{ 0x07, MOXIE_F3_PCREL,"ble" },
{ 0x08, MOXIE_F3_PCREL,"bgeu" },
{ 0x09, MOXIE_F3_PCREL,"bleu" },
{ 0x0a, MOXIE_F3_NARG, "bad" },
{ 0x0b, MOXIE_F3_NARG, "bad" },
{ 0x0c, MOXIE_F3_NARG, "bad" },
{ 0x0d, MOXIE_F3_NARG, "bad" },
{ 0x0e, MOXIE_F3_NARG, "bad" },
{ 0x0f, MOXIE_F3_NARG, "bad" }
};
/* Macros to extract operands from the instruction word. */
#define OP_A(i) ((i >> 4) & 0xf)
#define OP_B(i) (i & 0xf)
#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
static const char * reg_names[16] =
{ "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
"$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
int
print_insn_moxie(bfd_vma addr, struct disassemble_info * info)
{
int length = 2;
int status;
stream = info->stream;
const moxie_opc_info_t * opcode;
bfd_byte buffer[4];
unsigned short iword;
fprintf_function fpr = info->fprintf_func;
if ((status = info->read_memory_func(addr, buffer, 2, info)))
goto fail;
iword = (bfd_getb16(buffer) >> 16);
/* Form 1 instructions have the high bit set to 0. */
if ((iword & (1<<15)) == 0) {
/* Extract the Form 1 opcode. */
opcode = &moxie_form1_opc_info[iword >> 8];
switch (opcode->itype) {
case MOXIE_F1_NARG:
fpr(stream, "%s", opcode->name);
break;
case MOXIE_F1_A:
fpr(stream, "%s\t%s", opcode->name,
reg_names[OP_A(iword)]);
break;
case MOXIE_F1_AB:
fpr(stream, "%s\t%s, %s", opcode->name,
reg_names[OP_A(iword)],
reg_names[OP_B(iword)]);
break;
case MOXIE_F1_A4:
{
unsigned imm;
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
goto fail;
imm = bfd_getb32(buffer);
fpr(stream, "%s\t%s, 0x%x", opcode->name,
reg_names[OP_A(iword)], imm);
length = 6;
}
break;
case MOXIE_F1_4:
{
unsigned imm;
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
goto fail;
imm = bfd_getb32(buffer);
fpr(stream, "%s\t0x%x", opcode->name, imm);
length = 6;
}
break;
case MOXIE_F1_M:
{
unsigned imm;
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
goto fail;
imm = bfd_getb32(buffer);
fpr(stream, "%s\t", opcode->name);
info->print_address_func((bfd_vma) imm, info);
length = 6;
}
break;
case MOXIE_F1_AiB:
fpr (stream, "%s\t(%s), %s", opcode->name,
reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
break;
case MOXIE_F1_ABi:
fpr(stream, "%s\t%s, (%s)", opcode->name,
reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
break;
case MOXIE_F1_4A:
{
unsigned imm;
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
goto fail;
imm = bfd_getb32(buffer);
fpr(stream, "%s\t0x%x, %s",
opcode->name, imm, reg_names[OP_A(iword)]);
length = 6;
}
break;
case MOXIE_F1_AiB4:
{
unsigned imm;
if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
goto fail;
imm = bfd_getb32(buffer);
fpr(stream, "%s\t0x%x(%s), %s", opcode->name,
imm,
reg_names[OP_A(iword)],
reg_names[OP_B(iword)]);
length = 6;
}
break;
case MOXIE_F1_ABi4:
{
unsigned imm;
if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
goto fail;
imm = bfd_getb32(buffer);
fpr(stream, "%s\t%s, 0x%x(%s)",
opcode->name,
reg_names[OP_A(iword)],
imm,
reg_names[OP_B(iword)]);
length = 6;
}
break;
default:
abort();
}
}
else if ((iword & (1<<14)) == 0) {
/* Extract the Form 2 opcode. */
opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
switch (opcode->itype) {
case MOXIE_F2_A8V:
fpr(stream, "%s\t%s, 0x%x",
opcode->name,
reg_names[(iword >> 8) & 0xf],
iword & ((1 << 8) - 1));
break;
case MOXIE_F2_NARG:
fpr(stream, "%s", opcode->name);
break;
default:
abort();
}
} else {
/* Extract the Form 3 opcode. */
opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
switch (opcode->itype) {
case MOXIE_F3_PCREL:
fpr(stream, "%s\t", opcode->name);
info->print_address_func((bfd_vma) (addr + INST2OFFSET(iword) + 2),
info);
break;
default:
abort();
}
}
return length;
fail:
info->memory_error_func(status, addr, info);
return -1;
}
Computing file changes ...