| Index: src/arm/disasm-arm.cc
|
| ===================================================================
|
| --- src/arm/disasm-arm.cc (revision 3208)
|
| +++ src/arm/disasm-arm.cc (working copy)
|
| @@ -97,6 +97,10 @@
|
|
|
| // Printing of common values.
|
| void PrintRegister(int reg);
|
| + void PrintSRegister(int reg);
|
| + void PrintDRegister(int reg);
|
| + int FormatVFPRegister(Instr* instr, const char* format);
|
| + int FormatVFPinstruction(Instr* instr, const char* format);
|
| void PrintCondition(Instr* instr);
|
| void PrintShiftRm(Instr* instr);
|
| void PrintShiftImm(Instr* instr);
|
| @@ -121,7 +125,11 @@
|
| void DecodeType6(Instr* instr);
|
| void DecodeType7(Instr* instr);
|
| void DecodeUnconditional(Instr* instr);
|
| + // For VFP support.
|
| + void DecodeTypeVFP(Instr* instr);
|
| + void DecodeType6CoprocessorIns(Instr* instr);
|
|
|
| +
|
| const disasm::NameConverter& converter_;
|
| v8::internal::Vector<char> out_buffer_;
|
| int out_buffer_pos_;
|
| @@ -171,7 +179,17 @@
|
| Print(converter_.NameOfCPURegister(reg));
|
| }
|
|
|
| +// Print the VFP S register name according to the active name converter.
|
| +void Decoder::PrintSRegister(int reg) {
|
| + Print(assembler::arm::VFPRegisters::Name(reg));
|
| +}
|
|
|
| +// Print the VFP D register name according to the active name converter.
|
| +void Decoder::PrintDRegister(int reg) {
|
| + Print(assembler::arm::VFPRegisters::Name(reg + 32));
|
| +}
|
| +
|
| +
|
| // These shift names are defined in a way to match the native disassembler
|
| // formatting. See for example the command "objdump -d <binary file>".
|
| static const char* shift_names[max_shift] = {
|
| @@ -290,6 +308,10 @@
|
| int reg = instr->RmField();
|
| PrintRegister(reg);
|
| return 2;
|
| + } else if (format[1] == 't') { // 'rt: Rt register
|
| + int reg = instr->RtField();
|
| + PrintRegister(reg);
|
| + return 2;
|
| } else if (format[1] == 'l') {
|
| // 'rlist: register list for load and store multiple instructions
|
| ASSERT(STRING_STARTS_WITH(format, "rlist"));
|
| @@ -314,7 +336,40 @@
|
| return -1;
|
| }
|
|
|
| +// Handle all VFP register based formatting in this function to reduce the
|
| +// complexity of FormatOption.
|
| +int Decoder::FormatVFPRegister(Instr* instr, const char* format) {
|
| + ASSERT((format[0] == 'S') || (format[0] == 'D'));
|
|
|
| + if (format[1] == 'n') {
|
| + int reg = instr->VnField();
|
| + if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField()));
|
| + if (format[0] == 'D') PrintDRegister(reg);
|
| + return 2;
|
| + } else if (format[1] == 'm') {
|
| + int reg = instr->VmField();
|
| + if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->MField()));
|
| + if (format[0] == 'D') PrintDRegister(reg);
|
| + return 2;
|
| + } else if (format[1] == 'd') {
|
| + int reg = instr->VdField();
|
| + if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->DField()));
|
| + if (format[0] == 'D') PrintDRegister(reg);
|
| + return 2;
|
| + }
|
| +
|
| + UNREACHABLE();
|
| + return -1;
|
| +}
|
| +
|
| +int Decoder::FormatVFPinstruction(Instr* instr, const char* format) {
|
| + Print(format);
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +
|
| +
|
| // FormatOption takes a formatting string and interprets it based on
|
| // the current instructions. The format string points to the first
|
| // character of the option string (the option escape has already been
|
| @@ -459,6 +514,13 @@
|
| }
|
| return 1;
|
| }
|
| + case 'v': {
|
| + return FormatVFPinstruction(instr, format);
|
| + }
|
| + case 'S':
|
| + case 'D': {
|
| + return FormatVFPRegister(instr, format);
|
| + }
|
| case 'w': { // 'w: W field of load and store instructions
|
| if (instr->HasW()) {
|
| Print("!");
|
| @@ -761,8 +823,7 @@
|
|
|
|
|
| void Decoder::DecodeType6(Instr* instr) {
|
| - // Coprocessor instructions currently not supported.
|
| - Unknown(instr);
|
| + DecodeType6CoprocessorIns(instr);
|
| }
|
|
|
|
|
| @@ -770,12 +831,10 @@
|
| if (instr->Bit(24) == 1) {
|
| Format(instr, "swi'cond 'swi");
|
| } else {
|
| - // Coprocessor instructions currently not supported.
|
| - Unknown(instr);
|
| + DecodeTypeVFP(instr);
|
| }
|
| }
|
|
|
| -
|
| void Decoder::DecodeUnconditional(Instr* instr) {
|
| if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
|
| Format(instr, "'memop'h'pu 'rd, ");
|
| @@ -837,6 +896,138 @@
|
| }
|
|
|
|
|
| +// void Decoder::DecodeTypeVFP(Instr* instr)
|
| +// Implements the following
|
| +// VFP instructions
|
| +// fmsr :Sn = Rt
|
| +// fmrs :Rt = Sn
|
| +// fsitod: Dd = Sm
|
| +// ftosid: Sd = Dm
|
| +// Dd = faddd(Dn, Dm)
|
| +// Dd = fsubd(Dn, Dm)
|
| +// Dd = fmuld(Dn, Dm)
|
| +// Dd = fdivd(Dn, Dm)
|
| +// vcmp(Dd, Dm)
|
| +// VMRS
|
| +void Decoder::DecodeTypeVFP(Instr* instr) {
|
| + ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
|
| +
|
| + if (instr->Bit(23) == 1) {
|
| + if ((instr->Bits(21, 19) == 0x7) &&
|
| + (instr->Bits(18, 16) == 0x5) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 1) &&
|
| + (instr->Bit(6) == 1) &&
|
| + (instr->Bit(4) == 0)) {
|
| + Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
|
| + } else if ((instr->Bits(21, 19) == 0x7) &&
|
| + (instr->Bits(18, 16) == 0x0) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 1) &&
|
| + (instr->Bit(7) == 1) &&
|
| + (instr->Bit(6) == 1) &&
|
| + (instr->Bit(4) == 0)) {
|
| + Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
|
| + } else if ((instr->Bit(21) == 0x0) &&
|
| + (instr->Bit(20) == 0x0) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 1) &&
|
| + (instr->Bit(6) == 0) &&
|
| + (instr->Bit(4) == 0)) {
|
| + Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
|
| + } else if ((instr->Bits(21, 20) == 0x3) &&
|
| + (instr->Bits(19, 16) == 0x4) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 0x1) &&
|
| + (instr->Bit(6) == 0x1) &&
|
| + (instr->Bit(4) == 0x0)) {
|
| + Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
|
| + } else if ((instr->Bits(23, 20) == 0xF) &&
|
| + (instr->Bits(19, 16) == 0x1) &&
|
| + (instr->Bits(11, 8) == 0xA) &&
|
| + (instr->Bits(7, 5) == 0x0) &&
|
| + (instr->Bit(4) == 0x1) &&
|
| + (instr->Bits(3, 0) == 0x0)) {
|
| + if (instr->Bits(15, 12) == 0xF)
|
| + Format(instr, "vmrs'cond APSR, FPSCR");
|
| + else
|
| + Unknown(instr); // not used by V8
|
| + } else {
|
| + Unknown(instr); // not used by V8
|
| + }
|
| + } else if (instr->Bit(21) == 1) {
|
| + if ((instr->Bit(20) == 0x1) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 0x1) &&
|
| + (instr->Bit(6) == 0) &&
|
| + (instr->Bit(4) == 0)) {
|
| + Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
|
| + } else if ((instr->Bit(20) == 0x1) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 0x1) &&
|
| + (instr->Bit(6) == 1) &&
|
| + (instr->Bit(4) == 0)) {
|
| + Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
|
| + } else if ((instr->Bit(20) == 0x0) &&
|
| + (instr->Bits(11, 9) == 0x5) &&
|
| + (instr->Bit(8) == 0x1) &&
|
| + (instr->Bit(6) == 0) &&
|
| + (instr->Bit(4) == 0)) {
|
| + Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
|
| + } else {
|
| + Unknown(instr); // not used by V8
|
| + }
|
| + } else {
|
| + if ((instr->Bit(20) == 0x0) &&
|
| + (instr->Bits(11, 8) == 0xA) &&
|
| + (instr->Bits(6, 5) == 0x0) &&
|
| + (instr->Bit(4) == 1) &&
|
| + (instr->Bits(3, 0) == 0x0)) {
|
| + Format(instr, "vmov'cond 'Sn, 'rt");
|
| + } else if ((instr->Bit(20) == 0x1) &&
|
| + (instr->Bits(11, 8) == 0xA) &&
|
| + (instr->Bits(6, 5) == 0x0) &&
|
| + (instr->Bit(4) == 1) &&
|
| + (instr->Bits(3, 0) == 0x0)) {
|
| + Format(instr, "vmov'cond 'rt, 'Sn");
|
| + } else {
|
| + Unknown(instr); // not used by V8
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +
|
| +// Decode Type 6 coprocessor instructions
|
| +// Dm = fmdrr(Rt, Rt2)
|
| +// <Rt, Rt2> = fmrrd(Dm)
|
| +void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
|
| + ASSERT((instr->TypeField() == 6));
|
| +
|
| + if (instr->Bit(23) == 1) {
|
| + Unknown(instr); // not used by V8
|
| + } else if (instr->Bit(22) == 1) {
|
| + if ((instr->Bits(27, 24) == 0xC) &&
|
| + (instr->Bit(22) == 1) &&
|
| + (instr->Bits(11, 8) == 0xB) &&
|
| + (instr->Bits(7, 6) == 0x0) &&
|
| + (instr->Bit(4) == 1)) {
|
| + if (instr->Bit(20) == 0) {
|
| + Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
|
| + } else if (instr->Bit(20) == 1) {
|
| + Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
|
| + }
|
| + } else {
|
| + Unknown(instr); // not used by V8
|
| + }
|
| + } else if (instr->Bit(21) == 1) {
|
| + Unknown(instr); // not used by V8
|
| + } else {
|
| + Unknown(instr); // not used by V8
|
| + }
|
| +}
|
| +
|
| +
|
| // Disassemble the instruction at *instr_ptr into the output buffer.
|
| int Decoder::InstructionDecode(byte* instr_ptr) {
|
| Instr* instr = Instr::At(instr_ptr);
|
|
|