changeset 36:18922e417eb4

Fix bugs in reg2mem and mem2reg of T_LONG & needs_patching cases.
author Ao Qi <aoqi@loongson.cn>
date Wed, 01 Dec 2010 17:47:08 +0800
parents dd1d79f9798b
children 15f398a44411
files hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp
diffstat 1 files changed, 336 insertions(+), 333 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp	Wed Dec 01 17:39:16 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp	Wed Dec 01 17:47:08 2010 +0800
@@ -432,7 +432,7 @@
 	#endif // ASSERT
  
 	compilation()->offsets()->set_value(CodeOffsets::Deopt, code_offset());
- 
+
 	__ call(SharedRuntime::deopt_blob()->unpack());
 	__ delayed()->nop(); 
  
@@ -811,156 +811,155 @@
 void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info,bool pop_fpu_stack, bool/*unaliged*/) {
   LIR_Address* to_addr = dest->as_address_ptr();
   Register dest_reg = to_addr->base()->as_register();	
-	PatchingStub* patch = NULL;
-	bool needs_patching = (patch_code != lir_patch_none);
+  PatchingStub* patch = NULL;
+  bool needs_patching = (patch_code != lir_patch_none);
   Register disp_reg = NOREG;
-	int disp_value = to_addr->disp();
-
-	if (type == T_ARRAY || type == T_OBJECT) {
+  int disp_value = to_addr->disp();
+
+  if (type == T_ARRAY || type == T_OBJECT) {
     __ verify_oop(src->as_register());
   }
 
-	if (needs_patching) {
-		patch = new PatchingStub(_masm, PatchingStub::access_field_id);
-		assert(!src->is_double_cpu() || 
-				patch_code == lir_patch_none || 
-				patch_code == lir_patch_normal, 
-				"patching doesn't match register");
-	}
-        
-	if (info != NULL) {
-     	add_debug_info_for_null_check_here(info);
+  if (needs_patching) {
+    patch = new PatchingStub(_masm, PatchingStub::access_field_id);
+    assert(!src->is_double_cpu() || 
+	patch_code == lir_patch_none || 
+	patch_code == lir_patch_normal, 
+	"patching doesn't match register");
+  }
+
+  if (info != NULL) {
+    add_debug_info_for_null_check_here(info);
+  }
+  if (needs_patching) {
+    disp_reg = AT;
+    __ lui(AT, Assembler::split_high(disp_value));
+    __ addiu(AT, AT, Assembler::split_low(disp_value));
+  } else if (!Assembler::is_simm16(disp_value)) { 
+    disp_reg = AT;
+    __ lui(AT, Assembler::split_high(disp_value));
   }
-	if (needs_patching) {
-		disp_reg = AT;
-		__ lui(AT, Assembler::split_high(disp_value));
-		__ addiu(AT, AT, Assembler::split_low(disp_value));
-	} else if (!Assembler::is_simm16(disp_value)) { 
-		disp_reg = AT;
-		__ lui(AT, Assembler::split_high(disp_value));
-	}
-	int offset = code_offset();
-
-	switch(type) {
-	case T_DOUBLE:
-		assert(src->is_double_fpu(), "just check");
-		if (disp_reg == noreg) {
-			__ swc1(src->as_double_reg(), dest_reg, disp_value);
-			__ swc1(src->as_double_reg()+1, dest_reg, disp_value+4);
-		} else if (needs_patching) {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ swc1(src->as_double_reg(), AT, 0);
-			__ swc1(src->as_double_reg()+1, AT, 4);
-		} else {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ swc1(src->as_double_reg(), AT, Assembler::split_low(disp_value));
-			__ swc1(src->as_double_reg()+1, AT, Assembler::split_low(disp_value) + 4);
-		}
-		break;
-
-	case T_FLOAT:
-	//	assert(src->is_single_cpu(), "just check");
-
-		if (disp_reg == noreg) {
-			__ swc1(src->as_float_reg(), dest_reg, disp_value);
-		} else if(needs_patching) {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ swc1(src->as_float_reg(), AT, 0);
-		} else {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ swc1(src->as_float_reg(), AT, Assembler::split_low(disp_value));
-		}
-		break;
-		
-	case T_LONG: {
-    Register from_lo = src->as_register_lo();
-  	Register from_hi = src->as_register_hi();
-  	Register base = to_addr->base()->as_register();
-   	Register index = noreg;
-    if (to_addr->index()->is_register()) {
-   	  index = to_addr->index()->as_register();
-  	}
-  	if (base == from_lo || index == from_lo) {
-      assert(base != from_hi, "can't be");
-      assert(index == noreg || (index != base && index != from_hi), "can't handle this");
-      __ sw(from_hi,as_Address_hi(to_addr));  
-		  if (patch != NULL) {
-        patching_epilog(patch, lir_patch_high, base, info);
-        patch = new PatchingStub(_masm, PatchingStub::access_field_id);
-        patch_code = lir_patch_low;
+  int offset = code_offset();
+
+  switch(type) {
+    case T_DOUBLE:
+      assert(src->is_double_fpu(), "just check");
+      if (disp_reg == noreg) {
+	__ swc1(src->as_double_reg(), dest_reg, disp_value);
+	__ swc1(src->as_double_reg()+1, dest_reg, disp_value+4);
+      } else if (needs_patching) {
+	__ add(AT, dest_reg, disp_reg);
+	offset = code_offset();
+	__ swc1(src->as_double_reg(), AT, 0);
+	__ swc1(src->as_double_reg()+1, AT, 4);
+      } else {
+	__ add(AT, dest_reg, disp_reg);
+	offset = code_offset();
+	__ swc1(src->as_double_reg(), AT, Assembler::split_low(disp_value));
+	__ swc1(src->as_double_reg()+1, AT, Assembler::split_low(disp_value) + 4);
+      }
+      break;
+
+    case T_FLOAT:
+      if (disp_reg == noreg) {
+	__ swc1(src->as_float_reg(), dest_reg, disp_value);
+      } else if(needs_patching) {
+	__ add(AT, dest_reg, disp_reg);
+	offset = code_offset();
+	__ swc1(src->as_float_reg(), AT, 0);
+      } else {
+	__ add(AT, dest_reg, disp_reg);
+	offset = code_offset();
+	__ swc1(src->as_float_reg(), AT, Assembler::split_low(disp_value));
       }
-      __ sw(from_lo,as_Address_lo(to_addr)); 
-		} else {
-      assert(index == noreg || (index != base && index != from_lo), "can't handle this");
-    	__ sw(from_lo,as_Address_lo(to_addr)); 
-		  if (patch != NULL) {
-        patching_epilog(patch, lir_patch_low, base, info);
-        patch = new PatchingStub(_masm, PatchingStub::access_field_id);
-        patch_code = lir_patch_high;
-      }
-      __ sw(from_hi,as_Address_hi(to_addr));  
-    }
-		break;
+      break;
+
+    case T_LONG: {
+		   Register from_lo = src->as_register_lo();
+		   Register from_hi = src->as_register_hi();
+		   Register base = to_addr->base()->as_register();
+		   Register index = noreg;
+		   if (to_addr->index()->is_register()) {
+		     index = to_addr->index()->as_register();
+		   }
+		   if (base == from_lo || index == from_lo) {
+		     assert(base != from_hi, "can't be");
+		     assert(index == noreg || (index != base && index != from_hi), "can't handle this");
+		     if (needs_patching) {
+		       __ add(AT, dest_reg, disp_reg);
+		       offset = code_offset();
+		       __ sw(from_hi,AT, longSize/2);
+		       __ sw(from_lo, AT, 0);  
+		     } else {
+		       __ sw(from_hi,as_Address_hi(to_addr));  
+		       __ sw(from_lo,as_Address_lo(to_addr));
+		     }
+		   } else {
+		     assert(index == noreg || (index != base && index != from_lo), "can't handle this");
+		     if (needs_patching) {
+		       __ add(AT, dest_reg, disp_reg);
+		       offset = code_offset();
+		       __ sw(from_lo,AT, 0);
+		       __ sw(from_hi, AT, longSize/2);  
+		     } else {
+		       __ sw(from_lo,as_Address_lo(to_addr)); 
+		       __ sw(from_hi,as_Address_hi(to_addr));  
+		     }
+		   }
+		   break;
+		 }
+    case T_ADDRESS:
+    case T_ARRAY:
+    case T_OBJECT:
+    case T_INT:
+		 if (disp_reg == noreg) {
+		   __ sw(src->as_register(), dest_reg, disp_value);
+		 } else if (needs_patching) {
+		   __ add(AT, dest_reg, disp_reg);
+		   offset = code_offset();
+		   __ sw(src->as_register(), AT, 0);
+		 } else {
+		   __ add(AT, dest_reg, disp_reg);
+		   offset = code_offset();
+		   __ sw(src->as_register(), AT, Assembler::split_low(disp_value));
+		 }
+		 break;
+
+    case T_CHAR:
+    case T_SHORT:
+		 if (disp_reg == noreg) {
+		   __ sh(src->as_register(), dest_reg, disp_value);
+		 } else if (needs_patching) {
+		   __ add(AT, dest_reg, disp_reg);
+		   offset = code_offset();
+		   __ sh(src->as_register(), AT, 0);
+		 } else {
+		   __ add(AT, dest_reg, disp_reg);
+		   offset = code_offset();
+		   __ sh(src->as_register(), AT, Assembler::split_low(disp_value));
+		 }
+		 break;
+
+    case T_BYTE:
+    case T_BOOLEAN:
+		 assert(src->is_single_cpu(), "just check");
+
+		 if (disp_reg == noreg) {
+		   __ sb(src->as_register(), dest_reg, disp_value);
+		 } else if (needs_patching) {
+		   __ add(AT, dest_reg, disp_reg);
+		   offset = code_offset();
+		   __ sb(src->as_register(), AT, 0);
+		 } else {
+		   __ add(AT, dest_reg, disp_reg);
+		   offset = code_offset();
+		   __ sb(src->as_register(), AT, Assembler::split_low(disp_value));
+		 }
+		 break;
+
+    default:
+		 ShouldNotReachHere();
   }
-	case T_ADDRESS:
-	case T_ARRAY:
-	case T_OBJECT:
-	case T_INT:
-		//assert(from_reg.is_word(), "just check");
-		if (disp_reg == noreg) {
-			__ sw(src->as_register(), dest_reg, disp_value);
-		} else if (needs_patching) {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ sw(src->as_register(), AT, 0);
-		} else {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ sw(src->as_register(), AT, Assembler::split_low(disp_value));
-		}
-		break;
-
-	case T_CHAR:
-	case T_SHORT:
-//		assert(from_reg.is_word(), "just check");
-
-		if (disp_reg == noreg) {
-			__ sh(src->as_register(), dest_reg, disp_value);
-		} else if (needs_patching) {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ sh(src->as_register(), AT, 0);
-		} else {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ sh(src->as_register(), AT, Assembler::split_low(disp_value));
-		}
-		break;
-
-	case T_BYTE:
-	case T_BOOLEAN:
-		assert(src->is_single_cpu(), "just check");
-
-		if (disp_reg == noreg) {
-			__ sb(src->as_register(), dest_reg, disp_value);
-		} else if (needs_patching) {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ sb(src->as_register(), AT, 0);
-		} else {
-			__ add(AT, dest_reg, disp_reg);
-			offset = code_offset();
-			__ sb(src->as_register(), AT, Assembler::split_low(disp_value));
-		}
-		break;
-
-	default:
-		ShouldNotReachHere();
-	}
 
   if (needs_patching) {
     patching_epilog(patch, patch_code, to_addr->base()->as_register(), info);
@@ -970,32 +969,32 @@
 
 
 void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) {
-	assert(src->is_stack(), "should not call otherwise");
+  assert(src->is_stack(), "should not call otherwise");
   assert(dest->is_register(), "should not call otherwise");
-	if (dest->is_single_cpu()) {
+  if (dest->is_single_cpu()) {
     __ lw(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()));
     if (type == T_ARRAY || type == T_OBJECT) {
       __ verify_oop(dest->as_register());
     }
-	} else if (dest->is_double_cpu()) {
-		Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes);
-		Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes);
-		__ lw(dest->as_register_lo(), src_addr_LO);
-		__ lw(dest->as_register_hi(), src_addr_HI);
-	}else if (dest->is_single_fpu()) {
-		Address addr = frame_map()->address_for_slot(src->single_stack_ix());
-		__ lwc1(dest->as_float_reg(), addr);
-	} else if (dest->is_double_fpu())  {
-		Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes);
-		Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes);
-		__ lwc1(dest->as_double_reg(), src_addr_LO);
-		__ lwc1(dest->as_double_reg()+1, src_addr_HI);
-	} else {
-		assert(dest->is_single_cpu(), "cannot be anything else but a single cpu");
-		assert(type!= T_ILLEGAL, "Bad type in stack2reg")
-		Address addr = frame_map()->address_for_slot(src->single_stack_ix());
-		__ lw(dest->as_register(), addr);
-	}
+  } else if (dest->is_double_cpu()) {
+    Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes);
+    Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes);
+    __ lw(dest->as_register_lo(), src_addr_LO);
+    __ lw(dest->as_register_hi(), src_addr_HI);
+  }else if (dest->is_single_fpu()) {
+    Address addr = frame_map()->address_for_slot(src->single_stack_ix());
+    __ lwc1(dest->as_float_reg(), addr);
+  } else if (dest->is_double_fpu())  {
+    Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes);
+    Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes);
+    __ lwc1(dest->as_double_reg(), src_addr_LO);
+    __ lwc1(dest->as_double_reg()+1, src_addr_HI);
+  } else {
+    assert(dest->is_single_cpu(), "cannot be anything else but a single cpu");
+    assert(type!= T_ILLEGAL, "Bad type in stack2reg")
+    Address addr = frame_map()->address_for_slot(src->single_stack_ix());
+    __ lw(dest->as_register(), addr);
+  }
 }
 
 void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) {
@@ -1016,189 +1015,193 @@
 
 // if patching needed, be sure the instruction at offset is a MoveMemReg
 void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool) {
-	assert(src->is_address(), "should not call otherwise");
+  assert(src->is_address(), "should not call otherwise");
   assert(dest->is_register(), "should not call otherwise");
   LIR_Address* addr = src->as_address_ptr();
   Address from_addr = as_Address(addr);
-	
-	Register src_reg = addr->base()->as_register();
-	Register disp_reg = noreg;
-	int disp_value = addr->disp();
-	bool needs_patching = (patch_code != lir_patch_none);
-
-	PatchingStub* patch = NULL;
-	if (needs_patching) {
-		patch = new PatchingStub(_masm, PatchingStub::access_field_id);
-//		assert(!to_reg.is_long() || patch_code == LIR_Op1::patch_low || patch_code == LIR_Op1::patch_high, "patching doesn't match register");
-	}
-
-	// we must use lui&addiu, 
-	if (needs_patching) {
-		disp_reg = AT;
-		__ lui(AT, Assembler::split_high(disp_value));
-		__ addiu(AT, AT, Assembler::split_low(disp_value));
-	} else if (!Assembler::is_simm16(disp_value)) {
-		disp_reg = AT;
-		__ lui(AT, Assembler::split_high(disp_value));
-	}
-
-	// remember the offset of the load.  The patching_epilog must be done
-	// before the call to add_debug_info, otherwise the PcDescs don't get
-	// entered in increasing order.
-	int offset = code_offset();
-
-	switch(type) {
+
+  Register src_reg = addr->base()->as_register();
+  Register disp_reg = noreg;
+  int disp_value = addr->disp();
+  bool needs_patching = (patch_code != lir_patch_none);
+
+  PatchingStub* patch = NULL;
+  if (needs_patching) {
+    patch = new PatchingStub(_masm, PatchingStub::access_field_id);
+  }
+
+  // we must use lui&addiu, 
+  if (needs_patching) {
+    disp_reg = AT;
+    __ lui(AT, Assembler::split_high(disp_value));
+    __ addiu(AT, AT, Assembler::split_low(disp_value));
+  } else if (!Assembler::is_simm16(disp_value)) {
+    disp_reg = AT;
+    __ lui(AT, Assembler::split_high(disp_value));
+  }
+
+  // remember the offset of the load.  The patching_epilog must be done
+  // before the call to add_debug_info, otherwise the PcDescs don't get
+  // entered in increasing order.
+  int offset = code_offset();
+
+  switch(type) {
     case T_BOOLEAN:
     case T_BYTE: {
-    	//assert(to_reg.is_word(), "just check");
-    	if (disp_reg == noreg) {
-    		__ lb(dest->as_register(), src_reg, disp_value);
-    	} else if (needs_patching) {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lb(dest->as_register(), AT, 0);
-    	} else {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lb(dest->as_register(), AT, Assembler::split_low(disp_value));
-    	}
-    }
-    break;
-    
+		   //assert(to_reg.is_word(), "just check");
+		   if (disp_reg == noreg) {
+		     __ lb(dest->as_register(), src_reg, disp_value);
+		   } else if (needs_patching) {
+		     __ add(AT, src_reg, disp_reg);
+		     offset = code_offset();
+		     __ lb(dest->as_register(), AT, 0);
+		   } else {
+		     __ add(AT, src_reg, disp_reg);
+		     offset = code_offset();
+		     __ lb(dest->as_register(), AT, Assembler::split_low(disp_value));
+		   }
+		 }
+		 break;
+
     case T_CHAR: {
-    		//assert(to_reg.is_word(), "just check");
-    	if (disp_reg == noreg) {
-    		__ lhu(dest->as_register(), src_reg, disp_value);
-    	} else if (needs_patching) {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lhu(dest->as_register(), AT, 0);
-    	} else {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lhu(dest->as_register(), AT, Assembler::split_low(disp_value));
-    	}
-    }
-    break;
-    
+		   //assert(to_reg.is_word(), "just check");
+		   if (disp_reg == noreg) {
+		     __ lhu(dest->as_register(), src_reg, disp_value);
+		   } else if (needs_patching) {
+		     __ add(AT, src_reg, disp_reg);
+		     offset = code_offset();
+		     __ lhu(dest->as_register(), AT, 0);
+		   } else {
+		     __ add(AT, src_reg, disp_reg);
+		     offset = code_offset();
+		     __ lhu(dest->as_register(), AT, Assembler::split_low(disp_value));
+		   }
+		 }
+		 break;
+
     case T_SHORT: {
-    	//	assert(to_reg.is_word(), "just check");
-    	if (disp_reg == noreg) {
-    		__ lh(dest->as_register(), src_reg, disp_value);
-    	} else if (needs_patching) {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lh(dest->as_register(), AT, 0);
-    	} else {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lh(dest->as_register(), AT, Assembler::split_low(disp_value));
-    	}
-    }
-    break;
-    
+		    //	assert(to_reg.is_word(), "just check");
+		    if (disp_reg == noreg) {
+		      __ lh(dest->as_register(), src_reg, disp_value);
+		    } else if (needs_patching) {
+		      __ add(AT, src_reg, disp_reg);
+		      offset = code_offset();
+		      __ lh(dest->as_register(), AT, 0);
+		    } else {
+		      __ add(AT, src_reg, disp_reg);
+		      offset = code_offset();
+		      __ lh(dest->as_register(), AT, Assembler::split_low(disp_value));
+		    }
+		  }
+		  break;
+
     case T_INT:
     case T_OBJECT:
     case T_ARRAY: {
-    		//assert(to_reg.is_word(), "just check");
-    	if (disp_reg == noreg) {
-    		__ lw(dest->as_register(), src_reg, disp_value);
-    	} else if (needs_patching) {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lw(dest->as_register(), AT, 0);
-    	} else {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lw(dest->as_register(), AT, Assembler::split_low(disp_value));
-    	}
-    }
-    break;
-    
+		    //assert(to_reg.is_word(), "just check");
+		    if (disp_reg == noreg) {
+		      __ lw(dest->as_register(), src_reg, disp_value);
+		    } else if (needs_patching) {
+		      __ add(AT, src_reg, disp_reg);
+		      offset = code_offset();
+		      __ lw(dest->as_register(), AT, 0);
+		    } else {
+		      __ add(AT, src_reg, disp_reg);
+		      offset = code_offset();
+		      __ lw(dest->as_register(), AT, Assembler::split_low(disp_value));
+		    }
+		  }
+		  break;
+
     case T_LONG: {	
-    	Register to_lo = dest->as_register_lo();
-      Register to_hi = dest->as_register_hi();
-      Register base = addr->base()->as_register();
-      Register index = noreg;
-      if (addr->index()->is_register()) {
-      	index = addr->index()->as_register();
-      }
-      if ((base == to_lo && index == to_hi) ||(base == to_hi && index == to_lo)) {
-        // addresses with 2 registers are only formed as a result of
-        // array access so this code will never have to deal with
-        // patches or null checks.
-        assert(info == NULL && patch == NULL, "must be");
-        __ lea(to_hi, as_Address(addr));
-        __ lw(to_lo, Address(to_hi));
-        __ lw(to_hi, Address(to_hi, BytesPerWord));
-      } else if (base == to_lo || index == to_lo) {
-        assert(base != to_hi, "can't be");
-        assert(index == noreg || (index != base && index != to_hi), "can't handle this");
-        __ lw(to_hi, as_Address_hi(addr));
-        if (patch != NULL) {
-        	patching_epilog(patch, lir_patch_high, base, info);
-        	patch = new PatchingStub(_masm, PatchingStub::access_field_id);
-        	patch_code = lir_patch_low;
-        }
-        __ lw(to_lo, as_Address_lo(addr));
-      } else {
-        assert(index == noreg || (index != base && index != to_lo), "can't handle this");
-        __ lw(to_lo, as_Address_lo(addr));
-        if (patch != NULL) {
-        	patching_epilog(patch, lir_patch_low, base, info);
-        	patch = new PatchingStub(_masm, PatchingStub::access_field_id);
-        	patch_code = lir_patch_high;
-        }
-        __ lw(to_hi, as_Address_hi(addr));
-      }
-    }
-    break;
+		   Register to_lo = dest->as_register_lo();
+		   Register to_hi = dest->as_register_hi();
+		   Register base = addr->base()->as_register();
+		   Register index = noreg;
+		   if (addr->index()->is_register()) {
+		     index = addr->index()->as_register();
+		   }
+		   if ((base == to_lo && index == to_hi) ||(base == to_hi && index == to_lo)) {
+		     // addresses with 2 registers are only formed as a result of
+		     // array access so this code will never have to deal with
+		     // patches or null checks.
+		     assert(info == NULL && patch == NULL, "must be");
+		     __ lea(to_hi, as_Address(addr));
+		     __ lw(to_lo, Address(to_hi));
+		     __ lw(to_hi, Address(to_hi, BytesPerWord));
+		   } else if (base == to_lo || index == to_lo) {
+		     assert(base != to_hi, "can't be");
+		     assert(index == noreg || (index != base && index != to_hi), "can't handle this");
+		     if (needs_patching) {
+		       __ add(AT, src_reg, disp_reg);
+		       offset = code_offset();
+		       __ lw(to_hi, AT, longSize/2);
+		       __ lw(to_lo, AT, 0);
+		     } else {
+		       __ lw(to_hi, as_Address_hi(addr));
+		       __ lw(to_lo, as_Address_lo(addr));
+		     }
+		   } else {
+		     assert(index == noreg || (index != base && index != to_lo), "can't handle this");
+		     if (needs_patching) {
+		       __ add(AT, src_reg, disp_reg);
+		       offset = code_offset();
+		       __ lw(to_lo, AT, 0);
+		       }
+		       __ lw(to_hi, AT, longSize/2);
+		     } else {
+		       __ lw(to_lo, as_Address_lo(addr));
+		       __ lw(to_hi, as_Address_hi(addr));
+		     }
+		   }
+		 }
+		 break;
 
     case T_FLOAT: {
-    	//assert(to_reg.is_float(), "just check");
-    	if (disp_reg == noreg) {
-    		__ lwc1(dest->as_float_reg(), src_reg, disp_value);
-    	} else if (needs_patching) {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lwc1(dest->as_float_reg(), AT, 0);
-    	} else {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lwc1(dest->as_float_reg(), AT, Assembler::split_low(disp_value));
-    	}
-    }
-    break;
-    
+		    //assert(to_reg.is_float(), "just check");
+		    if (disp_reg == noreg) {
+		      __ lwc1(dest->as_float_reg(), src_reg, disp_value);
+		    } else if (needs_patching) {
+		      __ add(AT, src_reg, disp_reg);
+		      offset = code_offset();
+		      __ lwc1(dest->as_float_reg(), AT, 0);
+		    } else {
+		      __ add(AT, src_reg, disp_reg);
+		      offset = code_offset();
+		      __ lwc1(dest->as_float_reg(), AT, Assembler::split_low(disp_value));
+		    }
+		  }
+		  break;
+
     case T_DOUBLE: {
-    	//assert(to_reg.is_double(), "just check");
-    
-    	if (disp_reg == noreg) {
-    		__ lwc1(dest->as_double_reg(), src_reg, disp_value);
-    		__ lwc1(dest->as_double_reg()+1, src_reg, disp_value+4);
-    	} else if (needs_patching) {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lwc1(dest->as_double_reg(), AT, 0);
-    		__ lwc1(dest->as_double_reg()+1, AT, 4);
-    	} else {
-    		__ add(AT, src_reg, disp_reg);
-    		offset = code_offset();
-    		__ lwc1(dest->as_double_reg(), AT, Assembler::split_low(disp_value));
-    		__ lwc1(dest->as_double_reg()+1, AT, Assembler::split_low(disp_value) + 4);
-    	}
-    }
-    break;
-    	
+		     //assert(to_reg.is_double(), "just check");
+
+		     if (disp_reg == noreg) {
+		       __ lwc1(dest->as_double_reg(), src_reg, disp_value);
+		       __ lwc1(dest->as_double_reg()+1, src_reg, disp_value+4);
+		     } else if (needs_patching) {
+		       __ add(AT, src_reg, disp_reg);
+		       offset = code_offset();
+		       __ lwc1(dest->as_double_reg(), AT, 0);
+		       __ lwc1(dest->as_double_reg()+1, AT, 4);
+		     } else {
+		       __ add(AT, src_reg, disp_reg);
+		       offset = code_offset();
+		       __ lwc1(dest->as_double_reg(), AT, Assembler::split_low(disp_value));
+		       __ lwc1(dest->as_double_reg()+1, AT, Assembler::split_low(disp_value) + 4);
+		     }
+		   }
+		   break;
+
     default:
-    	ShouldNotReachHere();
-	}
-
-	if (needs_patching) {
-		patching_epilog(patch, patch_code, src_reg, info);
-	}
-
-	if (info != NULL) add_debug_info_for_null_check(offset, info);
+		   ShouldNotReachHere();
+  }
+
+  if (needs_patching) {
+    patching_epilog(patch, patch_code, src_reg, info);
+  }
+
+  if (info != NULL) add_debug_info_for_null_check(offset, info);
 }