target-arm: A64: provide skeleton for a64 insn decoding

Provide a skeleton for a64 instruction decoding in translate-a64.c,
by dividing instructions into the classes defined by the
ARM Architecture Reference Manual(DDI0487A_a) section C3.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Claudio Fontana 2013-12-17 19:42:32 +00:00 committed by Peter Maydell
parent d3e35a1fe4
commit ad7ee8a290

View File

@ -146,17 +146,348 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
}
}
static void real_unallocated_encoding(DisasContext *s)
static void unallocated_encoding(DisasContext *s)
{
fprintf(stderr, "Unknown instruction: %#x\n", s->insn);
gen_exception_insn(s, 4, EXCP_UDEF);
}
#define unallocated_encoding(s) do { \
fprintf(stderr, "unallocated encoding at line: %d\n", __LINE__); \
real_unallocated_encoding(s); \
} while (0)
#define unsupported_encoding(s, insn) \
do { \
qemu_log_mask(LOG_UNIMP, \
"%s:%d: unsupported instruction encoding 0x%08x " \
"at pc=%016" PRIx64 "\n", \
__FILE__, __LINE__, insn, s->pc - 4); \
unallocated_encoding(s); \
} while (0);
/*
* the instruction disassembly implemented here matches
* the instruction encoding classifications in chapter 3 (C3)
* of the ARM Architecture Reference Manual (DDI0487A_a)
*/
/* Unconditional branch (immediate) */
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Compare & branch (immediate) */
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Test & branch (immediate) */
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Conditional branch (immediate) */
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* System */
static void disas_system(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Exception generation */
static void disas_exc(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Unconditional branch (register) */
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* C3.2 Branches, exception generating and system instructions */
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
{
switch (extract32(insn, 25, 7)) {
case 0x0a: case 0x0b:
case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
disas_uncond_b_imm(s, insn);
break;
case 0x1a: case 0x5a: /* Compare & branch (immediate) */
disas_comp_b_imm(s, insn);
break;
case 0x1b: case 0x5b: /* Test & branch (immediate) */
disas_test_b_imm(s, insn);
break;
case 0x2a: /* Conditional branch (immediate) */
disas_cond_b_imm(s, insn);
break;
case 0x6a: /* Exception generation / System */
if (insn & (1 << 24)) {
disas_system(s, insn);
} else {
disas_exc(s, insn);
}
break;
case 0x6b: /* Unconditional branch (register) */
disas_uncond_b_reg(s, insn);
break;
default:
unallocated_encoding(s);
break;
}
}
/* Load/store exclusive */
static void disas_ldst_excl(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Load register (literal) */
static void disas_ld_lit(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Load/store pair (all forms) */
static void disas_ldst_pair(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Load/store register (all forms) */
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* AdvSIMD load/store multiple structures */
static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* AdvSIMD load/store single structure */
static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* C3.3 Loads and stores */
static void disas_ldst(DisasContext *s, uint32_t insn)
{
switch (extract32(insn, 24, 6)) {
case 0x08: /* Load/store exclusive */
disas_ldst_excl(s, insn);
break;
case 0x18: case 0x1c: /* Load register (literal) */
disas_ld_lit(s, insn);
break;
case 0x28: case 0x29:
case 0x2c: case 0x2d: /* Load/store pair (all forms) */
disas_ldst_pair(s, insn);
break;
case 0x38: case 0x39:
case 0x3c: case 0x3d: /* Load/store register (all forms) */
disas_ldst_reg(s, insn);
break;
case 0x0c: /* AdvSIMD load/store multiple structures */
disas_ldst_multiple_struct(s, insn);
break;
case 0x0d: /* AdvSIMD load/store single structure */
disas_ldst_single_struct(s, insn);
break;
default:
unallocated_encoding(s);
break;
}
}
/* PC-rel. addressing */
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Add/subtract (immediate) */
static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Logical (immediate) */
static void disas_logic_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Move wide (immediate) */
static void disas_movw_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Bitfield */
static void disas_bitfield(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Extract */
static void disas_extract(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* C3.4 Data processing - immediate */
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
{
switch (extract32(insn, 23, 6)) {
case 0x20: case 0x21: /* PC-rel. addressing */
disas_pc_rel_adr(s, insn);
break;
case 0x22: case 0x23: /* Add/subtract (immediate) */
disas_add_sub_imm(s, insn);
break;
case 0x24: /* Logical (immediate) */
disas_logic_imm(s, insn);
break;
case 0x25: /* Move wide (immediate) */
disas_movw_imm(s, insn);
break;
case 0x26: /* Bitfield */
disas_bitfield(s, insn);
break;
case 0x27: /* Extract */
disas_extract(s, insn);
break;
default:
unallocated_encoding(s);
break;
}
}
/* Logical (shifted register) */
static void disas_logic_reg(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Add/subtract (extended register) */
static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Add/subtract (shifted register) */
static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Data-processing (3 source) */
static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Add/subtract (with carry) */
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Conditional compare (immediate) */
static void disas_cc_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Conditional compare (register) */
static void disas_cc_reg(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Conditional select */
static void disas_cond_select(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Data-processing (1 source) */
static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* Data-processing (2 source) */
static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* C3.5 Data processing - register */
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
{
switch (extract32(insn, 24, 5)) {
case 0x0a: /* Logical (shifted register) */
disas_logic_reg(s, insn);
break;
case 0x0b: /* Add/subtract */
if (insn & (1 << 21)) { /* (extended register) */
disas_add_sub_ext_reg(s, insn);
} else {
disas_add_sub_reg(s, insn);
}
break;
case 0x1b: /* Data-processing (3 source) */
disas_data_proc_3src(s, insn);
break;
case 0x1a:
switch (extract32(insn, 21, 3)) {
case 0x0: /* Add/subtract (with carry) */
disas_adc_sbc(s, insn);
break;
case 0x2: /* Conditional compare */
if (insn & (1 << 11)) { /* (immediate) */
disas_cc_imm(s, insn);
} else { /* (register) */
disas_cc_reg(s, insn);
}
break;
case 0x4: /* Conditional select */
disas_cond_select(s, insn);
break;
case 0x6: /* Data-processing */
if (insn & (1 << 30)) { /* (1 source) */
disas_data_proc_1src(s, insn);
} else { /* (2 source) */
disas_data_proc_2src(s, insn);
}
break;
default:
unallocated_encoding(s);
break;
}
break;
default:
unallocated_encoding(s);
break;
}
}
/* C3.6 Data processing - SIMD and floating point */
static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
}
/* C3.1 A64 instruction index by encoding */
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{
uint32_t insn;
@ -165,10 +496,33 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
s->insn = insn;
s->pc += 4;
switch ((insn >> 24) & 0x1f) {
default:
switch (extract32(insn, 25, 4)) {
case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
unallocated_encoding(s);
break;
case 0x8: case 0x9: /* Data processing - immediate */
disas_data_proc_imm(s, insn);
break;
case 0xa: case 0xb: /* Branch, exception generation and system insns */
disas_b_exc_sys(s, insn);
break;
case 0x4:
case 0x6:
case 0xc:
case 0xe: /* Loads and stores */
disas_ldst(s, insn);
break;
case 0x5:
case 0xd: /* Data processing - register */
disas_data_proc_reg(s, insn);
break;
case 0x7:
case 0xf: /* Data processing - SIMD and floating point */
disas_data_proc_simd_fp(s, insn);
break;
default:
assert(FALSE); /* all 15 cases should be handled above */
break;
}
}