Chromium Code Reviews| Index: src/arm/disasm-arm.cc |
| diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc |
| index abb13dd9f0d502de7a18b01af53913521d7ba498..7a42386d74aabd344294ac0d5fc731776cd7f24d 100644 |
| --- a/src/arm/disasm-arm.cc |
| +++ b/src/arm/disasm-arm.cc |
| @@ -1419,6 +1419,9 @@ int Decoder::DecodeType7(Instruction* instr) { |
| // Sd = vsqrt(Sm) |
| // vmrs |
| // vmsr |
| +// Qd = vdup.size(Qd, Rt) |
| +// vmov.size: Dd[i] = Rt |
| +// vmov.sign.size: Rt = Dn[i] |
| void Decoder::DecodeTypeVFP(Instruction* instr) { |
| VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); |
| VERIFY(instr->Bits(11, 9) == 0x5); |
| @@ -1531,21 +1534,71 @@ void Decoder::DecodeTypeVFP(Instruction* instr) { |
| if ((instr->VCValue() == 0x0) && |
| (instr->VAValue() == 0x0)) { |
| DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
| - } else if ((instr->VLValue() == 0x0) && |
| - (instr->VCValue() == 0x1) && |
| - (instr->Bit(23) == 0x0)) { |
| - if (instr->Bit(21) == 0x0) { |
| - Format(instr, "vmov'cond.32 'Dd[0], 'rt"); |
| + } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) { |
| + if (instr->Bit(23) == 0) { |
| + int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5); |
| + if ((opc1_opc2 & 0xb) == 0) { |
| + // NeonS32/NeonU32 |
| + if (instr->Bit(21) == 0x0) { |
| + Format(instr, "vmov'cond.32 'Dd[0], 'rt"); |
| + } else { |
| + Format(instr, "vmov'cond.32 'Dd[1], 'rt"); |
| + } |
| + } else { |
| + int vd = instr->VFPNRegValue(kDoublePrecision); |
| + int rt = instr->RtValue(); |
| + if ((opc1_opc2 & 0x8) != 0) { |
| + // NeonS8 / NeonU8 |
| + int i = opc1_opc2 & 0x7; |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
|
Rodolph Perfetta (ARM)
2016/12/14 12:06:30
the assembler allows conditional forms of those in
bbudge
2016/12/14 19:14:48
Ugh. It looks like a lot of work to allow Format t
|
| + "vmov.8 d%d[%d], r%d", vd, i, rt); |
| + } else if ((opc1_opc2 & 0x1) != 0) { |
| + // NeonS16 / NeonU16 |
| + int i = (opc1_opc2 >> 1) & 0x3; |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vmov.16 d%d[%d], r%d", vd, i, rt); |
| + } else { |
| + Unknown(instr); |
| + } |
| + } |
| } else { |
| - Format(instr, "vmov'cond.32 'Dd[1], 'rt"); |
| - } |
| - } else if ((instr->VLValue() == 0x1) && |
| - (instr->VCValue() == 0x1) && |
| - (instr->Bit(23) == 0x0)) { |
| - if (instr->Bit(21) == 0x0) { |
| - Format(instr, "vmov'cond.32 'rt, 'Dd[0]"); |
| + int size = 32; |
| + if (instr->Bit(5) != 0) |
| + size = 16; |
| + else if (instr->Bit(22) != 0) |
| + size = 8; |
| + int Vd = instr->VFPNRegValue(kSimd128Precision); |
| + int Rt = instr->RtValue(); |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
|
Rodolph Perfetta (ARM)
2016/12/14 12:06:30
ditto.
bbudge
2016/12/14 19:14:48
No longer conditional.
|
| + "vdup.%i q%d, r%d", size, Vd, Rt); |
| + } |
| + } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) { |
| + int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5); |
| + if ((opc1_opc2 & 0xb) == 0) { |
| + // NeonS32 / NeonU32 |
| + if (instr->Bit(21) == 0x0) { |
| + Format(instr, "vmov'cond.32 'rt, 'Dd[0]"); |
| + } else { |
| + Format(instr, "vmov'cond.32 'rt, 'Dd[1]"); |
| + } |
| } else { |
| - Format(instr, "vmov'cond.32 'rt, 'Dd[1]"); |
| + const char* sign = instr->Bit(23) != 0 ? "u" : "s"; |
| + int rt = instr->RtValue(); |
| + int vn = instr->VFPNRegValue(kDoublePrecision); |
| + if ((opc1_opc2 & 0x8) != 0) { |
| + // NeonS8 / NeonU8 |
| + int i = opc1_opc2 & 0x7; |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
|
Rodolph Perfetta (ARM)
2016/12/14 12:06:30
handle conditional.
bbudge
2016/12/14 19:14:48
No longer conditional.
|
| + "vmov.%s8 r%d, d%d[%d]", sign, rt, vn, i); |
| + } else if ((opc1_opc2 & 0x1) != 0) { |
| + // NeonS16 / NeonU16 |
| + int i = (opc1_opc2 >> 1) & 0x3; |
| + out_buffer_pos_ += |
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%s16 r%d, d%d[%d]", |
|
Rodolph Perfetta (ARM)
2016/12/14 12:06:30
ditto.
bbudge
2016/12/14 19:14:48
No longer conditional.
|
| + sign, rt, vn, i); |
| + } else { |
| + Unknown(instr); |
| + } |
| } |
| } else if ((instr->VCValue() == 0x0) && |
| (instr->VAValue() == 0x7) && |
| @@ -1563,6 +1616,8 @@ void Decoder::DecodeTypeVFP(Instruction* instr) { |
| Format(instr, "vmrs'cond 'rt, FPSCR"); |
| } |
| } |
| + } else { |
| + Unknown(instr); // Not used by V8. |
| } |
| } |
| } |
| @@ -1809,6 +1864,25 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { |
| int Vm = instr->VFPMRegValue(kSimd128Precision); |
| out_buffer_pos_ += |
| SNPrintF(out_buffer_ + out_buffer_pos_, "vmov q%d, q%d", Vd, Vm); |
| + } else if (instr->Bits(11, 8) == 8) { |
| + const char* op = (instr->Bit(4) == 0) ? "vadd" : "vtst"; |
| + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kSimd128Precision); |
| + int Vn = instr->VFPNRegValue(kSimd128Precision); |
| + // vadd/vtst.i<size> Qd, Qm, Qn. |
| + out_buffer_pos_ += |
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s.i%d q%d, q%d, q%d", op, |
| + size, Vd, Vn, Vm); |
| + } else if (instr->Bits(11, 8) == 0xd && instr->Bit(4) == 0) { |
| + const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub"; |
| + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kSimd128Precision); |
| + int Vn = instr->VFPNRegValue(kSimd128Precision); |
| + // vadd/vsub.f32 Qd, Qm, Qn. |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); |
| } else { |
| Unknown(instr); |
| } |
| @@ -1828,8 +1902,29 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { |
| } |
| break; |
| case 6: |
| - if (instr->Bits(21, 20) == 0 && instr->Bits(11, 8) == 1 && |
| - instr->Bit(4) == 1) { |
| + if (instr->Bits(11, 8) == 8) { |
| + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kSimd128Precision); |
| + int Vn = instr->VFPNRegValue(kSimd128Precision); |
| + if (instr->Bit(4) == 0) { |
| + out_buffer_pos_ += |
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vsub.i%d q%d, q%d, q%d", |
| + size, Vd, Vn, Vm); |
| + } else { |
| + out_buffer_pos_ += |
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vceq.i%d q%d, q%d, q%d", |
| + size, Vd, Vn, Vm); |
| + } |
| + } else if (instr->Bits(21, 20) == 1 && instr->Bits(11, 8) == 1 && |
| + instr->Bit(4) == 1) { |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kSimd128Precision); |
| + int Vn = instr->VFPNRegValue(kSimd128Precision); |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vbsl q%d, q%d, q%d", Vd, Vn, Vm); |
| + } else if (instr->Bits(21, 20) == 0 && instr->Bits(11, 8) == 1 && |
| + instr->Bit(4) == 1) { |
| if (instr->Bit(6) == 0) { |
| // veor Dd, Dn, Dm |
| int Vd = instr->VFPDRegValue(kDoublePrecision); |
| @@ -1860,6 +1955,35 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { |
| int imm3 = instr->Bits(21, 19); |
| out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm); |
| + } else if (instr->Opc1Value() == 7 && instr->Bits(19, 16) == 0 && |
| + instr->Bits(11, 6) == 0x17 && instr->Bit(4) == 0) { |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kSimd128Precision); |
| + out_buffer_pos_ += |
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vmvn q%d, q%d", Vd, Vm); |
| + } else if (instr->Opc1Value() == 7 && instr->Bits(19, 16) == 0xB && |
| + instr->Bits(11, 9) == 0x3 && instr->Bit(6) == 1 && |
| + instr->Bit(4) == 0) { |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kSimd128Precision); |
| + const char* suffix = nullptr; |
| + int op = instr->Bits(8, 7); |
| + switch (op) { |
| + case 0: |
| + suffix = "f32.s32"; |
| + break; |
| + case 1: |
| + suffix = "f32.u32"; |
| + break; |
| + case 2: |
| + suffix = "s32.f32"; |
| + break; |
| + case 3: |
| + suffix = "u32.f32"; |
| + break; |
| + } |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vcvt.%s q%d, q%d", suffix, Vd, Vm); |
| } else if ((instr->Bits(21, 16) == 0x32) && (instr->Bits(11, 7) == 0) && |
| (instr->Bit(4) == 0)) { |
| if (instr->Bit(6) == 0) { |
| @@ -1873,6 +1997,26 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { |
| out_buffer_pos_ += |
| SNPrintF(out_buffer_ + out_buffer_pos_, "vswp q%d, q%d", Vd, Vm); |
| } |
| + } else if (instr->Opc1Value() == 0x7 && instr->Bits(11, 7) == 0x18 && |
| + instr->Bit(4) == 0x0) { |
| + int Vd = instr->VFPDRegValue(kSimd128Precision); |
| + int Vm = instr->VFPMRegValue(kDoublePrecision); |
| + int index = instr->Bit(19); |
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vdup q%d, d%d[%d]", Vd, Vm, index); |
| + } else if (instr->Opc1Value() == 0x7 && instr->Bits(11, 10) == 0x2 && |
| + instr->Bit(4) == 0x0) { |
| + int Vd = instr->VFPDRegValue(kDoublePrecision); |
| + int Vn = instr->VFPNRegValue(kDoublePrecision); |
| + int Vm = instr->VFPMRegValue(kDoublePrecision); |
| + int len = instr->Bits(9, 8); |
| + NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1); |
| + out_buffer_pos_ += |
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ", |
| + instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd); |
| + FormatNeonList(Vn, list.type()); |
| + Print(", "); |
| + PrintDRegister(Vm); |
| } else { |
| Unknown(instr); |
| } |