target/arm: Rearrange disas_data_proc_reg

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).

Backports commit 2fba34f70d9a81bab56e61bb99a4d6632bdfe531 from qemu
This commit is contained in:
Richard Henderson 2019-03-05 22:52:47 -05:00 committed by Lioncash
parent 45c297c99b
commit 65a3f3be5b
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -4577,11 +4577,10 @@ static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
} }
/* Add/subtract (with carry) /* Add/subtract (with carry)
* 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0 * 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 | * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | 0 0 0 0 0 0 | Rn | Rd |
* +--+--+--+------------------------+------+---------+------+-----+ * +--+--+--+------------------------+------+-------------+------+-----+
* [000000]
*/ */
static void disas_adc_sbc(DisasContext *s, uint32_t insn) static void disas_adc_sbc(DisasContext *s, uint32_t insn)
@ -4590,11 +4589,6 @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
unsigned int sf, op, setflags, rm, rn, rd; unsigned int sf, op, setflags, rm, rn, rd;
TCGv_i64 tcg_y, tcg_rn, tcg_rd; TCGv_i64 tcg_y, tcg_rn, tcg_rd;
if (extract32(insn, 10, 6) != 0) {
unallocated_encoding(s);
return;
}
sf = extract32(insn, 31, 1); sf = extract32(insn, 31, 1);
op = extract32(insn, 30, 1); op = extract32(insn, 30, 1);
setflags = extract32(insn, 29, 1); setflags = extract32(insn, 29, 1);
@ -5263,47 +5257,76 @@ 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) static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
{ {
switch (extract32(insn, 24, 5)) { int op0 = extract32(insn, 30, 1);
case 0x0a: /* Logical (shifted register) */ int op1 = extract32(insn, 28, 1);
disas_logic_reg(s, insn); int op2 = extract32(insn, 21, 4);
break; int op3 = extract32(insn, 10, 6);
case 0x0b: /* Add/subtract */
if (insn & (1 << 21)) { /* (extended register) */ if (!op1) {
disas_add_sub_ext_reg(s, insn); 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 { } else {
disas_add_sub_reg(s, insn); /* Logical (shifted register) */
disas_logic_reg(s, insn);
} }
break; return;
case 0x1b: /* Data-processing (3 source) */ }
disas_data_proc_3src(s, insn);
break; switch (op2) {
case 0x1a: case 0x0:
switch (extract32(insn, 21, 3)) { switch (op3) {
case 0x0: /* Add/subtract (with carry) */ case 0x00: /* Add/subtract (with carry) */
disas_adc_sbc(s, insn); disas_adc_sbc(s, insn);
break; 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: default:
unallocated_encoding(s); goto do_unallocated;
break;
} }
break; 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:
case 0x9:
case 0xA:
case 0xB:
case 0xC:
case 0xD:
case 0xE:
case 0xF:
disas_data_proc_3src(s, insn);
break;
default: default:
do_unallocated:
unallocated_encoding(s); unallocated_encoding(s);
break; break;
} }