diff mbox

[RFC] target-arm: provide skeleton for a64 insn decoding

Message ID 1384182837-5925-1-git-send-email-claudio.fontana@linaro.org
State New
Headers show

Commit Message

Claudio Fontana Nov. 11, 2013, 3:13 p.m. UTC
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) C3

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
---
The following patch has been started during Linaro Connect
by me and Alex Bennee.
The goal is to provide a decoder that is easy to match against
the ARM Architecture Reference Manual.
The plan here is a process of cleaning up / refactoring the SuSE
patchset.
 
We will be posting actual instruction implementations in the
following days and weeks.

However, as we currently have between 60-120 patches in the
backlog we thought it would be worth getting the basic decoding
skeleton agreed (and merged?) first to reduce any patch
ordering problems and ease the reviewing burden.

The first set of instruction patches will be based on
Alexander Graf's 60 patch set after we have applied fixes,
review comments and run some instruction testing using
Peter Maydell's risu tool patched for aarch64:

https://github.com/hw-claudio/risu-aarch64.git (master)

We hope from there to quickly progress through the rest of
the SUSE patch-set for getting a functional aarch64 linux-user
setup before turning our attention to system emulation.

 target-arm/translate-a64.c | 367 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 359 insertions(+), 8 deletions(-)

Comments

Richard Henderson Nov. 11, 2013, 7:25 p.m. UTC | #1
On 11/12/2013 01:13 AM, Claudio Fontana wrote:
> +/* 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 0x4a: /* Unconditional branch (immediate) */
> +        disas_uncond_b_imm(s, insn);
> +        break;

Bit 25 is "-" for unconditional branch, so this entry should be

 0x0a, 0x0b, 0x4a, 0x4b

All of the other decodings look good.


r~
Alex Bennée Nov. 12, 2013, 10:59 a.m. UTC | #2
claudio.fontana@linaro.org writes:

> 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) C3
>
> Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
> ---
> The following patch has been started during Linaro Connect
> by me and Alex Bennee.
<snip>

With the proviso of Richard's decode comment you can add:

Reviewed-by: Alex Bennée <alex@bennee.com>
Signed-of-by: Alex Bennée <alex@bennee.com>
diff mbox

Patch

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index f120088..7105728 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -107,17 +107,345 @@  static void gen_exception_insn(DisasContext *s, int offset, int excp)
     s->is_jmp = DISAS_JUMP;
 }
 
-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", \
+                      __FILE__, __LINE__, insn);                        \
+        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_sys(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 0x4a: /* 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_sys(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_csel(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_csel(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;
+        }
+    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 */
 void disas_a64_insn(CPUARMState *env, DisasContext *s)
 {
     uint32_t insn;
@@ -126,10 +454,33 @@  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;
     }
 
     if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) {