[arm] Add formatting helpers for disassembly

Add a new option to disassembler NEON size encoded in instructions with
two registers, 'size2. Rename the current only to 'size3.

Clean up existing operations to use this new formatting option.

Bug: v8:11074
Change-Id: Ie309d93d24602439c3293c8bbfd6c2ecbc9fdfb7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2575786
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71670}
This commit is contained in:
Zhi An Ng 2020-12-08 06:17:38 +00:00 committed by Commit Bot
parent 135b15a6bd
commit be7d3ebcbf

View File

@ -585,11 +585,14 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
Print("s");
}
return 4;
} else { // 'size, for Advanced SIMD instructions
DCHECK(STRING_STARTS_WITH(format, "size"));
int sz = 8 << instr->Bits(21, 20);
} else {
// 'size2 or 'size3, for Advanced SIMD instructions, 2 or 3 registers.
DCHECK(STRING_STARTS_WITH(format, "size2") ||
STRING_STARTS_WITH(format, "size3"));
int sz = 8 << (format[4] == '2' ? instr->Bits(19, 18)
: instr->Bits(21, 20));
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sz);
return 4;
return 5;
}
} else if (format[1] == 'p') {
if (format[8] == '_') { // 'spec_reg_fields
@ -2041,7 +2044,7 @@ void Decoder::DecodeAdvancedSIMDDataProcessing(Instruction* instr) {
int sz = instr->Bits(21, 20);
if (!u && opc == 0 && op1) {
Format(instr, "vqadd.s'size 'Qd, 'Qn, 'Qm");
Format(instr, "vqadd.s'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 1 && sz == 2 && q && op1) {
if (Vm == Vn) {
Format(instr, "vmov 'Qd, 'Qm");
@ -2053,29 +2056,29 @@ void Decoder::DecodeAdvancedSIMDDataProcessing(Instruction* instr) {
} else if (!u && opc == 1 && sz == 0 && q && op1) {
Format(instr, "vand 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 2 && op1) {
Format(instr, "vqsub.s'size 'Qd, 'Qn, 'Qm");
Format(instr, "vqsub.s'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 3 && op1) {
Format(instr, "vcge.s'size 'Qd, 'Qn, 'Qm");
Format(instr, "vcge.s'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 3 && !op1) {
Format(instr, "vcgt.s'size 'Qd, 'Qn, 'Qm");
Format(instr, "vcgt.s'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 4 && !op1) {
Format(instr, "vshl.s'size 'Qd, 'Qm, 'Qn");
Format(instr, "vshl.s'size3 'Qd, 'Qm, 'Qn");
} else if (!u && opc == 6 && op1) {
Format(instr, "vmin.s'size 'Qd, 'Qn, 'Qm");
Format(instr, "vmin.s'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 6 && !op1) {
Format(instr, "vmax.s'size 'Qd, 'Qn, 'Qm");
Format(instr, "vmax.s'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 8 && op1) {
Format(instr, "vtst.i'size 'Qd, 'Qn, 'Qm");
Format(instr, "vtst.i'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 8 && !op1) {
Format(instr, "vadd.i'size 'Qd, 'Qn, 'Qm");
Format(instr, "vadd.i'size3 'Qd, 'Qn, 'Qm");
} else if (opc == 9 && op1) {
Format(instr, "vmul.i'size 'Qd, 'Qn, 'Qm");
Format(instr, "vmul.i'size3 'Qd, 'Qn, 'Qm");
} else if (!u && opc == 0xA && op1) {
Format(instr, "vpmin.s'size 'Dd, 'Dn, 'Dm");
Format(instr, "vpmin.s'size3 'Dd, 'Dn, 'Dm");
} else if (!u && opc == 0xA && !op1) {
Format(instr, "vpmax.s'size 'Dd, 'Dn, 'Dm");
Format(instr, "vpmax.s'size3 'Dd, 'Dn, 'Dm");
} else if (!u && opc == 0xB) {
Format(instr, "vpadd.i'size 'Dd, 'Dn, 'Dm");
Format(instr, "vpadd.i'size3 'Dd, 'Dn, 'Dm");
} else if (!u && !(sz >> 1) && opc == 0xD && !op1) {
Format(instr, "vadd.f32 'Qd, 'Qn, 'Qm");
} else if (!u && (sz >> 1) && opc == 0xD && !op1) {
@ -2091,7 +2094,7 @@ void Decoder::DecodeAdvancedSIMDDataProcessing(Instruction* instr) {
} else if (!u && (sz >> 1) && opc == 0xF && !op1) {
Format(instr, "vmin.f32 'Qd, 'Qn, 'Qm");
} else if (u && opc == 0 && op1) {
Format(instr, "vqadd.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vqadd.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 1 && sz == 1 && op1) {
Format(instr, "vbsl 'Qd, 'Qn, 'Qm");
} else if (u && opc == 1 && sz == 0 && q && op1) {
@ -2099,27 +2102,27 @@ void Decoder::DecodeAdvancedSIMDDataProcessing(Instruction* instr) {
} else if (u && opc == 1 && sz == 0 && !q && op1) {
Format(instr, "veor 'Dd, 'Dn, 'Dm");
} else if (u && opc == 1 && !op1) {
Format(instr, "vrhadd.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vrhadd.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 2 && op1) {
Format(instr, "vqsub.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vqsub.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 3 && op1) {
Format(instr, "vcge.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vcge.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 3 && !op1) {
Format(instr, "vcgt.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vcgt.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 4 && !op1) {
Format(instr, "vshl.u'size 'Qd, 'Qm, 'Qn");
Format(instr, "vshl.u'size3 'Qd, 'Qm, 'Qn");
} else if (u && opc == 6 && op1) {
Format(instr, "vmin.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vmin.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 6 && !op1) {
Format(instr, "vmax.u'size 'Qd, 'Qn, 'Qm");
Format(instr, "vmax.u'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 8 && op1) {
Format(instr, "vceq.i'size 'Qd, 'Qn, 'Qm");
Format(instr, "vceq.i'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 8 && !op1) {
Format(instr, "vsub.i'size 'Qd, 'Qn, 'Qm");
Format(instr, "vsub.i'size3 'Qd, 'Qn, 'Qm");
} else if (u && opc == 0xA && op1) {
Format(instr, "vpmin.u'size 'Dd, 'Dn, 'Dm");
Format(instr, "vpmin.u'size3 'Dd, 'Dn, 'Dm");
} else if (u && opc == 0xA && !op1) {
Format(instr, "vpmax.u'size 'Dd, 'Dn, 'Dm");
Format(instr, "vpmax.u'size3 'Dd, 'Dn, 'Dm");
} else if (u && opc == 0xD && sz == 0 && q && op1) {
Format(instr, "vmul.f32 'Qd, 'Qn, 'Qm");
} else if (u && opc == 0xD && sz == 0 && !q && !op1) {
@ -2250,15 +2253,8 @@ void Decoder::DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction* instr) {
int opc1 = instr->Bits(17, 16);
int opc2 = instr->Bits(10, 7);
int q = instr->Bit(6);
int Vd, Vm;
if (q) {
Vd = instr->VFPDRegValue(kSimd128Precision);
Vm = instr->VFPMRegValue(kSimd128Precision);
} else {
Vd = instr->VFPDRegValue(kDoublePrecision);
Vm = instr->VFPMRegValue(kDoublePrecision);
}
int Vd = instr->VFPDRegValue(q ? kSimd128Precision : kDoublePrecision);
int Vm = instr->VFPMRegValue(q ? kSimd128Precision : kDoublePrecision);
int esize = kBitsPerByte * (1 << size);
if (opc1 == 0 && (opc2 >> 2) == 0) {
@ -2270,37 +2266,20 @@ void Decoder::DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction* instr) {
Format(instr, q ? "vswp 'Qd, 'Qm" : "vswp 'Dd, 'Dm");
} else if (opc1 == 0 && opc2 == 0b1011) {
Format(instr, "vmvn 'Qd, 'Qm");
} else if (opc1 == 0b01 && (opc2 & 0b0111) == 0b110) {
// vabs<type>.<esize> Qd, Qm.
char type = instr->Bit(10) != 0 ? 'f' : 's';
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vabs.%c%d q%d, q%d", type, esize, Vd, Vm);
} else if (opc1 == 0b01 && (opc2 & 0b0111) == 0b111) {
// vneg<type>.<esize> Qd, Qm.
char type = instr->Bit(10) != 0 ? 'f' : 's';
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vneg.%c%d q%d, q%d", type, esize, Vd, Vm);
} else if (opc1 == 0b01 && opc2 == 0b0110) {
Format(instr, q ? "vabs.s'size2 'Qd, 'Qm" : "vabs.s.'size2 'Dd, 'Dm");
} else if (opc1 == 0b01 && opc2 == 0b1110) {
Format(instr, q ? "vabs.f'size2 'Qd, 'Qm" : "vabs.f.'size2 'Dd, 'Dm");
} else if (opc1 == 0b01 && opc2 == 0b0111) {
Format(instr, q ? "vneg.s'size2 'Qd, 'Qm" : "vneg.s.'size2 'Dd, 'Dm");
} else if (opc1 == 0b01 && opc2 == 0b1111) {
Format(instr, q ? "vneg.f'size2 'Qd, 'Qm" : "vneg.f.'size2 'Dd, 'Dm");
} else if (opc1 == 0b10 && opc2 == 0b0001) {
if (q) {
// vtrn.<esize> Qd, Qm.
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vtrn.%d q%d, q%d", esize, Vd, Vm);
} else {
// vtrn.<esize> Dd, Dm.
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vtrn.%d d%d, d%d", esize, Vd, Vm);
}
} else if (opc1 == 0b10 && (opc2 & 0b1110) == 0b0010) {
const char* op = instr->Bit(7) != 0 ? "vzip" : "vuzp";
if (q) {
// vzip/vuzp.<esize> Qd, Qm.
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"%s.%d q%d, q%d", op, esize, Vd, Vm);
} else {
// vzip/vuzp.<esize> Dd, Dm.
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"%s.%d d%d, d%d", op, esize, Vd, Vm);
}
Format(instr, q ? "vtrn.'size2 'Qd, 'Qm" : "vtrn.'size2 'Dd, 'Dm");
} else if (opc1 == 0b10 && opc2 == 0b0010) {
Format(instr, q ? "vuzp.'size2 'Qd, 'Qm" : "vuzp.'size2 'Dd, 'Dm");
} else if (opc1 == 0b10 && opc2 == 0b0011) {
Format(instr, q ? "vzip.'size2 'Qd, 'Qm" : "vzip.'size2 'Dd, 'Dm");
} else if (opc1 == 0b10 && (opc2 & 0b1110) == 0b0100) {
// vqmov{u}n.<type><esize> Dd, Qm.
int Vd = instr->VFPDRegValue(kDoublePrecision);
@ -2391,22 +2370,11 @@ void Decoder::DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction* instr) {
int u = instr->Bit(24);
int opc = instr->Bits(11, 8);
if (opc == 0b1000) {
// vmlal.u<esize> <Qd>, <Dn>, <Dm>
int Vd = instr->VFPDRegValue(kSimd128Precision);
int Vn = instr->VFPNRegValue(kDoublePrecision);
int Vm = instr->VFPMRegValue(kDoublePrecision);
int esize = 8 << instr->Bits(21, 20);
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vmlal.u%d q%d, d%d, d%d", esize, Vd, Vn, Vm);
Format(instr,
u ? "vmlal.u'size3 'Qd, 'Dn, 'Dm" : "vmlal.s'size3 'Qd, 'Dn, 'Dm");
} else if (opc == 0b1100) {
// vmull.s/u<esize> Qd, Dn, Dm
int Vd = instr->VFPDRegValue(kSimd128Precision);
int Vn = instr->VFPNRegValue(kDoublePrecision);
int Vm = instr->VFPMRegValue(kDoublePrecision);
int esize = 8 << instr->Bits(21, 20);
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "vmull.%s%d q%d, d%d, d%d",
u ? "u" : "s", esize, Vd, Vn, Vm);
Format(instr,
u ? "vmull.u'size3 'Qd, 'Dn, 'Dm" : "vmull.s'size3 'Qd, 'Dn, 'Dm");
}
} else if (op1 != 0b11 && op3) {
// The instructions specified by this encoding are not used in V8.