< prev index next >

src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp

Print this page
rev 12409 : 8171244: PPC64: Make interpreter's math entries consistent with C1 and C2 and support FMA
Reviewed-by:

@@ -290,32 +290,32 @@
 
   patching_epilog(patch, lir_patch_normal, reg, info);
 }
 
 
-void LIR_Assembler::emit_op3(LIR_Op3* op) {
-  const bool is_int = op->result_opr()->is_single_cpu();
-  Register Rdividend = is_int ? op->in_opr1()->as_register() : op->in_opr1()->as_register_lo();
+void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) {
+  const bool is_int = result->is_single_cpu();
+  Register Rdividend = is_int ? left->as_register() : left->as_register_lo();
   Register Rdivisor  = noreg;
-  Register Rscratch  = op->in_opr3()->as_register();
-  Register Rresult   = is_int ? op->result_opr()->as_register() : op->result_opr()->as_register_lo();
+  Register Rscratch  = temp->as_register();
+  Register Rresult   = is_int ? result->as_register() : result->as_register_lo();
   long divisor = -1;
 
-  if (op->in_opr2()->is_register()) {
-    Rdivisor = is_int ? op->in_opr2()->as_register() : op->in_opr2()->as_register_lo();
+  if (right->is_register()) {
+    Rdivisor = is_int ? right->as_register() : right->as_register_lo();
   } else {
-    divisor = is_int ? op->in_opr2()->as_constant_ptr()->as_jint()
-                     : op->in_opr2()->as_constant_ptr()->as_jlong();
+    divisor = is_int ? right->as_constant_ptr()->as_jint()
+                     : right->as_constant_ptr()->as_jlong();
   }
 
   assert(Rdividend != Rscratch, "");
   assert(Rdivisor  != Rscratch, "");
-  assert(op->code() == lir_idiv || op->code() == lir_irem, "Must be irem or idiv");
+  assert(code == lir_idiv || code == lir_irem, "Must be irem or idiv");
 
   if (Rdivisor == noreg) {
     if (divisor == 1) { // stupid, but can happen
-      if (op->code() == lir_idiv) {
+      if (code == lir_idiv) {
         __ mr_if_needed(Rresult, Rdividend);
       } else {
         __ li(Rresult, 0);
       }
 

@@ -338,11 +338,11 @@
         }
         __ clrldi(Rscratch, Rscratch, 64-log2);
       }
       __ add(Rscratch, Rdividend, Rscratch);
 
-      if (op->code() == lir_idiv) {
+      if (code == lir_idiv) {
         if (is_int) {
           __ srawi(Rresult, Rscratch, log2);
         } else {
           __ sradi(Rresult, Rscratch, log2);
         }

@@ -350,19 +350,19 @@
         __ clrrdi(Rscratch, Rscratch, log2);
         __ sub(Rresult, Rdividend, Rscratch);
       }
 
     } else if (divisor == -1) {
-      if (op->code() == lir_idiv) {
+      if (code == lir_idiv) {
         __ neg(Rresult, Rdividend);
       } else {
         __ li(Rresult, 0);
       }
 
     } else {
       __ load_const_optimized(Rscratch, divisor);
-      if (op->code() == lir_idiv) {
+      if (code == lir_idiv) {
         if (is_int) {
           __ divw(Rresult, Rdividend, Rscratch); // Can't divide minint/-1.
         } else {
           __ divd(Rresult, Rdividend, Rscratch); // Can't divide minint/-1.
         }

@@ -387,11 +387,11 @@
     __ cmpwi(CCR0, Rdivisor, -1);
   } else {
     __ cmpdi(CCR0, Rdivisor, -1);
   }
   __ bne(CCR0, regular);
-  if (op->code() == lir_idiv) {
+  if (code == lir_idiv) {
     __ neg(Rresult, Rdividend);
     __ b(done);
     __ bind(regular);
     if (is_int) {
       __ divw(Rresult, Rdividend, Rdivisor); // Can't divide minint/-1.

@@ -413,10 +413,30 @@
   }
   __ bind(done);
 }
 
 
+void LIR_Assembler::emit_op3(LIR_Op3* op) {
+  switch (op->code()) {
+  case lir_idiv:
+  case lir_irem:
+    arithmetic_idiv(op->code(), op->in_opr1(), op->in_opr2(), op->in_opr3(),
+                    op->result_opr(), op->info());
+    break;
+  case lir_fmad:
+    __ fmadd(op->result_opr()->as_double_reg(), op->in_opr1()->as_double_reg(),
+             op->in_opr2()->as_double_reg(), op->in_opr3()->as_double_reg());
+    break;
+  case lir_fmaf:
+    __ fmadds(op->result_opr()->as_float_reg(), op->in_opr1()->as_float_reg(),
+              op->in_opr2()->as_float_reg(), op->in_opr3()->as_float_reg());
+    break;
+  default: ShouldNotReachHere(); break;
+  }
+}
+
+
 void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) {
 #ifdef ASSERT
   assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label");
   if (op->block() != NULL)  _branch_target_blocks.append(op->block());
   if (op->ublock() != NULL) _branch_target_blocks.append(op->ublock());
< prev index next >