* [Qemu-devel] [PATCH 1/3] target/arm: Rearrange disas_data_proc_reg
2019-02-20 5:04 [Qemu-devel] [PATCH 0/3] target/arm: Implement ARMv8.5-CondM Richard Henderson
@ 2019-02-20 5:04 ` Richard Henderson
2019-02-20 5:04 ` [Qemu-devel] [PATCH 2/3] target/arm: Implement ARMv8.4-CondM Richard Henderson
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2019-02-20 5:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell
This decoding more closely matches the ARMv8.4 Table C4-6,
Encoding table for Data Processing - Register Group.
In particular, op2 == 0 is now more than just Add/sub (with carry).
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/translate-a64.c | 98 ++++++++++++++++++++++----------------
1 file changed, 57 insertions(+), 41 deletions(-)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 951c8f4129..0e16487be0 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -4694,11 +4694,10 @@ static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
}
/* Add/subtract (with carry)
- * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
- * +--+--+--+------------------------+------+---------+------+-----+
- * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | opcode2 | Rn | Rd |
- * +--+--+--+------------------------+------+---------+------+-----+
- * [000000]
+ * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
+ * +--+--+--+------------------------+------+-------------+------+-----+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | 0 0 0 0 0 0 | Rn | Rd |
+ * +--+--+--+------------------------+------+-------------+------+-----+
*/
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
@@ -4706,11 +4705,6 @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
unsigned int sf, op, setflags, rm, rn, rd;
TCGv_i64 tcg_y, tcg_rn, tcg_rd;
- if (extract32(insn, 10, 6) != 0) {
- unallocated_encoding(s);
- return;
- }
-
sf = extract32(insn, 31, 1);
op = extract32(insn, 30, 1);
setflags = extract32(insn, 29, 1);
@@ -5397,47 +5391,69 @@ static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
}
}
-/* Data processing - register */
+/*
+ * Data processing - register
+ * 31 30 29 28 25 21 20 16 10 0
+ * +--+---+--+---+-------+-----+-------+-------+---------+
+ * | |op0| |op1| 1 0 1 | op2 | | op3 | |
+ * +--+---+--+---+-------+-----+-------+-------+---------+
+ */
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);
+ int op0 = extract32(insn, 30, 1);
+ int op1 = extract32(insn, 28, 1);
+ int op2 = extract32(insn, 21, 4);
+ int op3 = extract32(insn, 10, 6);
+
+ if (!op1) {
+ if (op2 & 8) {
+ if (op2 & 1) {
+ /* Add/sub (extended register) */
+ disas_add_sub_ext_reg(s, insn);
+ } else {
+ /* Add/sub (shifted register) */
+ disas_add_sub_reg(s, insn);
+ }
} else {
- disas_add_sub_reg(s, insn);
+ /* Logical (shifted register) */
+ disas_logic_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) */
+ return;
+ }
+
+ switch (op2) {
+ case 0x0:
+ switch (op3) {
+ case 0x00: /* Add/subtract (with carry) */
disas_adc_sbc(s, insn);
break;
- case 0x2: /* Conditional compare */
- disas_cc(s, insn); /* both imm and reg forms */
- 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;
+ goto do_unallocated;
}
break;
+
+ case 0x2: /* Conditional compare */
+ disas_cc(s, insn); /* both imm and reg forms */
+ break;
+
+ case 0x4: /* Conditional select */
+ disas_cond_select(s, insn);
+ break;
+
+ case 0x6: /* Data-processing */
+ if (op0) { /* (1 source) */
+ disas_data_proc_1src(s, insn);
+ } else { /* (2 source) */
+ disas_data_proc_2src(s, insn);
+ }
+ break;
+ case 0x8 ... 0xf: /* (3 source) */
+ disas_data_proc_3src(s, insn);
+ break;
+
default:
+ do_unallocated:
unallocated_encoding(s);
break;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 2/3] target/arm: Implement ARMv8.4-CondM
2019-02-20 5:04 [Qemu-devel] [PATCH 0/3] target/arm: Implement ARMv8.5-CondM Richard Henderson
2019-02-20 5:04 ` [Qemu-devel] [PATCH 1/3] target/arm: Rearrange disas_data_proc_reg Richard Henderson
@ 2019-02-20 5:04 ` Richard Henderson
2019-02-20 5:04 ` [Qemu-devel] [PATCH 3/3] target/arm: Implement ARMv8.5-CondM Richard Henderson
2019-02-20 10:07 ` [Qemu-devel] [PATCH 0/3] " Laurent Desnogues
3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2019-02-20 5:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 5 ++
linux-user/elfload.c | 1 +
target/arm/cpu64.c | 1 +
target/arm/translate-a64.c | 97 +++++++++++++++++++++++++++++++++++++-
4 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index f8ff795dcf..000e778619 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3375,6 +3375,11 @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
}
+static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
+}
+
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 3a50d587ff..ef7138839d 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -602,6 +602,7 @@ static uint32_t get_elf_hwcap(void)
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
+ GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
#undef GET_FEATURE_ID
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 7bd761b8f5..27b95ef787 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -334,6 +334,7 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR0, TS, 1);
cpu->isar.id_aa64isar0 = t;
t = cpu->isar.id_aa64isar1;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 0e16487be0..b88eccef53 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1655,6 +1655,14 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
s->base.is_jmp = DISAS_TOO_MANY;
switch (op) {
+ case 0x00: /* CFINV */
+ if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
+ goto do_unallocated;
+ }
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
+ s->base.is_jmp = DISAS_NEXT;
+ break;
+
case 0x05: /* SPSel */
if (s->current_el == 0) {
goto do_unallocated;
@@ -1719,7 +1727,6 @@ static void gen_get_nzcv(TCGv_i64 tcg_rt)
}
static void gen_set_nzcv(TCGv_i64 tcg_rt)
-
{
TCGv_i32 nzcv = tcg_temp_new_i32();
@@ -4729,6 +4736,82 @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
}
}
+/* Rotate right into flags
+ * 31 30 29 21 15 10 5 4 0
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | imm6 | 0 0 0 0 1 | Rn |o2| mask |
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
+ */
+static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
+{
+ int mask = extract32(insn, 0, 4);
+ int o2 = extract32(insn, 4, 1);
+ int rn = extract32(insn, 5, 5);
+ int imm6 = extract32(insn, 15, 6);
+ int sf_op_s = extract32(insn, 29, 3);
+ TCGv_i64 tcg_rn;
+ TCGv_i32 nzcv;
+
+ if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+
+ tcg_rn = read_cpu_reg(s, rn, 1);
+ tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
+
+ nzcv = tcg_temp_new_i32();
+ tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
+
+ if (mask & 8) { /* N */
+ tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
+ }
+ if (mask & 4) { /* Z */
+ tcg_gen_not_i32(cpu_ZF, nzcv);
+ tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
+ }
+ if (mask & 2) { /* C */
+ tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
+ }
+ if (mask & 1) { /* V */
+ tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
+ }
+
+ tcg_temp_free_i32(nzcv);
+}
+
+/* Evaluate into flags
+ * 31 30 29 21 15 14 10 5 4 0
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 | Rn |o3| mask |
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
+ */
+static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
+{
+ int o3_mask = extract32(insn, 0, 5);
+ int rn = extract32(insn, 5, 5);
+ int o2 = extract32(insn, 15, 6);
+ int sz = extract32(insn, 14, 1);
+ int sf_op_s = extract32(insn, 29, 3);
+ TCGv_i32 tmp;
+ int shift;
+
+ if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
+ !dc_isar_feature(aa64_condm_4, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ shift = sz ? 16 : 24; /* SETF16 or SETF8 */
+
+ tmp = tcg_temp_new_i32();
+ tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
+ tcg_gen_shli_i32(cpu_NF, tmp, shift);
+ tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+ tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
+ tcg_temp_free_i32(tmp);
+}
+
/* Conditional compare (immediate / register)
* 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
* +--+--+--+------------------------+--------+------+----+--+------+--+-----+
@@ -5428,6 +5511,18 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
disas_adc_sbc(s, insn);
break;
+ case 0x01: /* Rotate right into flags */
+ case 0x21:
+ disas_rotate_right_into_flags(s, insn);
+ break;
+
+ case 0x02: /* Evaluate into flags */
+ case 0x12:
+ case 0x22:
+ case 0x32:
+ disas_evaluate_into_flags(s, insn);
+ break;
+
default:
goto do_unallocated;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 3/3] target/arm: Implement ARMv8.5-CondM
2019-02-20 5:04 [Qemu-devel] [PATCH 0/3] target/arm: Implement ARMv8.5-CondM Richard Henderson
2019-02-20 5:04 ` [Qemu-devel] [PATCH 1/3] target/arm: Rearrange disas_data_proc_reg Richard Henderson
2019-02-20 5:04 ` [Qemu-devel] [PATCH 2/3] target/arm: Implement ARMv8.4-CondM Richard Henderson
@ 2019-02-20 5:04 ` Richard Henderson
2019-02-20 10:07 ` [Qemu-devel] [PATCH 0/3] " Laurent Desnogues
3 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2019-02-20 5:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 5 ++++
target/arm/translate-a64.c | 58 ++++++++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 000e778619..0480f9baba 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3380,6 +3380,11 @@ static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
}
+static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
+}
+
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index b88eccef53..1d9bf81c0e 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1644,6 +1644,48 @@ static void handle_sync(DisasContext *s, uint32_t insn,
}
}
+static void gen_xaflag(void)
+{
+ TCGv_i32 z = tcg_temp_new_i32();
+
+ tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
+
+ /*
+ * (!C & !Z) << 31
+ * (!(C | Z)) << 31
+ * ~((C | Z) << 31)
+ * ~-(C | Z)
+ * (C | Z) - 1
+ */
+ tcg_gen_or_i32(cpu_NF, cpu_CF, z);
+ tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
+
+ /* !(Z & C) */
+ tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
+ tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
+
+ /* (!C & Z) << 31 -> -(Z & ~C) */
+ tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
+ tcg_gen_neg_i32(cpu_VF, cpu_VF);
+
+ /* C | Z */
+ tcg_gen_or_i32(cpu_CF, cpu_CF, z);
+
+ tcg_temp_free_i32(z);
+}
+
+static void gen_axflag(void)
+{
+ tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
+ tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
+
+ /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
+ tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
+
+ tcg_gen_movi_i32(cpu_NF, 0);
+ tcg_gen_movi_i32(cpu_VF, 0);
+}
+
/* MSR (immediate) - move immediate to processor state field */
static void handle_msr_i(DisasContext *s, uint32_t insn,
unsigned int op1, unsigned int op2, unsigned int crm)
@@ -1663,6 +1705,22 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
s->base.is_jmp = DISAS_NEXT;
break;
+ case 0x01: /* XAFlag */
+ if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+ goto do_unallocated;
+ }
+ gen_xaflag();
+ s->base.is_jmp = DISAS_NEXT;
+ break;
+
+ case 0x02: /* AXFlag */
+ if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+ goto do_unallocated;
+ }
+ gen_axflag();
+ s->base.is_jmp = DISAS_NEXT;
+ break;
+
case 0x05: /* SPSel */
if (s->current_el == 0) {
goto do_unallocated;
--
2.17.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] target/arm: Implement ARMv8.5-CondM
2019-02-20 5:04 [Qemu-devel] [PATCH 0/3] target/arm: Implement ARMv8.5-CondM Richard Henderson
` (2 preceding siblings ...)
2019-02-20 5:04 ` [Qemu-devel] [PATCH 3/3] target/arm: Implement ARMv8.5-CondM Richard Henderson
@ 2019-02-20 10:07 ` Laurent Desnogues
2019-02-20 15:18 ` Richard Henderson
3 siblings, 1 reply; 6+ messages in thread
From: Laurent Desnogues @ 2019-02-20 10:07 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel@nongnu.org, Peter Maydell
Hi,
On Wed, Feb 20, 2019 at 6:05 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Based-on: https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg02733.html
> aka the v3 ARMv8.5-MemTag patch set,
> or at least some of the early patches that split handle_msr_i.
>
> The v8.4 parts have been tested vs FVP, but there's no released
> version that supports v8.5 yet, so XAFlag and AXFlag are untested.
> But they seem fairly straightforward, unless I've done something silly.
I tested xaflag/axflag (after setting the ID_AA64ISAR0 TS field to 2).
I also tested rmif/setf8/setf16.
Everything passes.
tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Thanks,
Laurent
>
> r~
>
>
> Richard Henderson (3):
> target/arm: Rearrange disas_data_proc_reg
> target/arm: Implement ARMv8.4-CondM
> target/arm: Implement ARMv8.5-CondM
>
> target/arm/cpu.h | 10 ++
> linux-user/elfload.c | 1 +
> target/arm/cpu64.c | 1 +
> target/arm/translate-a64.c | 249 +++++++++++++++++++++++++++++++------
> 4 files changed, 221 insertions(+), 40 deletions(-)
>
> --
> 2.17.2
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread