Extend assembler and codegen with more fpu arithmetic
authorolivf@chromium.org <olivf@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 9 Sep 2013 16:57:35 +0000 (16:57 +0000)
committerolivf@chromium.org <olivf@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 9 Sep 2013 16:57:35 +0000 (16:57 +0000)
BUG=
R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/21509003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16600 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/assembler-ia32.cc
src/ia32/assembler-ia32.h
src/ia32/disasm-ia32.cc
src/ia32/lithium-codegen-ia32.cc

index 7ff6913..e5456da 100644 (file)
@@ -1721,12 +1721,24 @@ void Assembler::fadd(int i) {
 }
 
 
+void Assembler::fadd_i(int i) {
+  EnsureSpace ensure_space(this);
+  emit_farith(0xD8, 0xC0, i);
+}
+
+
 void Assembler::fsub(int i) {
   EnsureSpace ensure_space(this);
   emit_farith(0xDC, 0xE8, i);
 }
 
 
+void Assembler::fsub_i(int i) {
+  EnsureSpace ensure_space(this);
+  emit_farith(0xD8, 0xE0, i);
+}
+
+
 void Assembler::fisub_s(const Operand& adr) {
   EnsureSpace ensure_space(this);
   EMIT(0xDA);
@@ -1752,6 +1764,12 @@ void Assembler::fdiv(int i) {
 }
 
 
+void Assembler::fdiv_i(int i) {
+  EnsureSpace ensure_space(this);
+  emit_farith(0xD8, 0xF0, i);
+}
+
+
 void Assembler::faddp(int i) {
   EnsureSpace ensure_space(this);
   emit_farith(0xDE, 0xC0, i);
index 551d031..55eff93 100644 (file)
@@ -956,10 +956,13 @@ class Assembler : public AssemblerBase {
   void fninit();
 
   void fadd(int i);
+  void fadd_i(int i);
   void fsub(int i);
+  void fsub_i(int i);
   void fmul(int i);
   void fmul_i(int i);
   void fdiv(int i);
+  void fdiv_i(int i);
 
   void fisub_s(const Operand& adr);
 
index 293d428..a1d4e9d 100644 (file)
@@ -743,7 +743,14 @@ int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
 
   switch (escape_opcode) {
     case 0xD8:
-      UnimplementedInstruction();
+      has_register = true;
+      switch (modrm_byte & 0xF8) {
+        case 0xC0: mnem = "fadd_i"; break;
+        case 0xE0: mnem = "fsub_i"; break;
+        case 0xC8: mnem = "fmul_i"; break;
+        case 0xF0: mnem = "fdiv_i"; break;
+        default: UnimplementedInstruction();
+      }
       break;
 
     case 0xD9:
@@ -767,6 +774,7 @@ int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
             case 0xEE: mnem = "fldz"; break;
             case 0xF0: mnem = "f2xm1"; break;
             case 0xF1: mnem = "fyl2x"; break;
+            case 0xF4: mnem = "fxtract"; break;
             case 0xF5: mnem = "fprem1"; break;
             case 0xF7: mnem = "fincstp"; break;
             case 0xF8: mnem = "fprem"; break;
@@ -815,6 +823,7 @@ int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
       has_register = true;
       switch (modrm_byte & 0xF8) {
         case 0xC0: mnem = "ffree"; break;
+        case 0xD0: mnem = "fst"; break;
         case 0xD8: mnem = "fstp"; break;
         default: UnimplementedInstruction();
       }
@@ -1448,6 +1457,7 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
         data += D1D3C1Instruction(data);
         break;
 
+      case 0xD8:  // fall through
       case 0xD9:  // fall through
       case 0xDA:  // fall through
       case 0xDB:  // fall through
index b3b9813..536f952 100644 (file)
@@ -2232,11 +2232,36 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
     X87Register left = ToX87Register(instr->left());
     X87Register right = ToX87Register(instr->right());
     X87Register result = ToX87Register(instr->result());
-    X87PrepareBinaryOp(left, right, result);
+    if (instr->op() != Token::MOD) {
+      X87PrepareBinaryOp(left, right, result);
+    }
     switch (instr->op()) {
+      case Token::ADD:
+        __ fadd_i(1);
+        break;
+      case Token::SUB:
+        __ fsub_i(1);
+        break;
       case Token::MUL:
         __ fmul_i(1);
         break;
+      case Token::DIV:
+        __ fdiv_i(1);
+        break;
+      case Token::MOD: {
+        // Pass two doubles as arguments on the stack.
+        __ PrepareCallCFunction(4, eax);
+        X87Mov(Operand(esp, 1 * kDoubleSize), right);
+        X87Mov(Operand(esp, 0), left);
+        X87PrepareToWrite(result);
+        __ CallCFunction(
+            ExternalReference::double_fp_operation(Token::MOD, isolate()),
+            4);
+
+        // Return value is in st(0) on ia32.
+        X87CommitWrite(result);
+        break;
+      }
       default:
         UNREACHABLE();
         break;