001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.regalloc.ia32; 014 015import static org.jikesrvm.compilers.opt.ir.IRTools.IC; 016import static org.jikesrvm.compilers.opt.ir.IRTools.LC; 017import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_ADD; 018import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOV; 019import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOVSXQ__W; 020import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_SHL; 021import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IMMQ_MOV; 022 023import org.jikesrvm.VM; 024import org.jikesrvm.classloader.TypeReference; 025import org.jikesrvm.compilers.opt.OptOptions; 026import org.jikesrvm.compilers.opt.driver.CompilerPhase; 027import org.jikesrvm.compilers.opt.ir.IR; 028import org.jikesrvm.compilers.opt.ir.Instruction; 029import org.jikesrvm.compilers.opt.ir.ia32.MIR_BinaryAcc; 030import org.jikesrvm.compilers.opt.ir.ia32.MIR_Move; 031import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 032import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; 033import org.jikesrvm.compilers.opt.ir.operand.Operand; 034import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 035import org.jikesrvm.util.Bits; 036 037/** 038 * Processes memory operands with a displacement that doesn't fit 039 * into 32 bits. This is only necessary on x64. 040 */ 041public class RewriteMemoryOperandsWithOversizedDisplacements extends CompilerPhase { 042 043 @Override 044 public final boolean shouldPerform(OptOptions options) { 045 return VM.BuildFor64Addr; 046 } 047 048 @Override 049 public String getName() { 050 return "Rewrite MemoryOperands with 64-bit displacements"; 051 } 052 053 @Override 054 public void perform(IR ir) { 055 for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = 056 inst.nextInstructionInCodeOrder()) { 057 for (int i = 0; i < inst.getNumberOfOperands(); i++) { 058 Operand op = inst.getOperand(i); 059 if (op instanceof MemoryOperand) { 060 MemoryOperand mo = (MemoryOperand)op; 061 disp64MemOperandConversion(ir, inst, mo); 062 } 063 } 064 } 065 } 066 067 @Override 068 public CompilerPhase newExecution(IR ir) { 069 return this; 070 } 071 072 private static void disp64MemOperandConversion(IR ir, Instruction inst, MemoryOperand mo) { 073 if (!mo.disp.isZero() && !Bits.fits(mo.disp, 32)) { 074 RegisterOperand effectiveAddress = ir.regpool.makeTempLong(); 075 RegisterOperand temp = null; 076 inst.insertBefore(MIR_Move.create(IMMQ_MOV, effectiveAddress, LC(mo.disp.toLong()))); 077 if (mo.index != null) { 078 if (mo.scale != 0) { 079 temp = ir.regpool.makeTempLong(); 080 if (mo.index.getType() != TypeReference.Long) { 081 inst.insertBefore(MIR_Move.create(IA32_MOVSXQ__W, temp, mo.index)); 082 } else { 083 inst.insertBefore(MIR_Move.create(IA32_MOV, temp, mo.index)); 084 } 085 inst.insertBefore(MIR_BinaryAcc.create(IA32_SHL, temp, IC(mo.scale))); 086 inst.insertBefore(MIR_BinaryAcc.create(IA32_ADD, effectiveAddress, temp)); 087 } else { 088 if (mo.index.getType() != TypeReference.Long) { 089 temp = ir.regpool.makeTempLong(); 090 inst.insertBefore(MIR_Move.create(IA32_MOVSXQ__W, temp, mo.index)); 091 inst.insertBefore(MIR_BinaryAcc.create(IA32_ADD, effectiveAddress, temp)); 092 } else { 093 inst.insertBefore(MIR_BinaryAcc.create(IA32_ADD, effectiveAddress, mo.index)); 094 } 095 } 096 } 097 if (mo.base != null) { 098 inst.insertBefore(MIR_BinaryAcc.create(IA32_ADD, effectiveAddress, mo.base)); 099 } 100 MemoryOperand newMo = MemoryOperand.I(effectiveAddress, mo.size, null != mo.loc ? (LocationOperand)mo.loc.copy() : null, 101 mo.guard != null ? mo.guard.copy() : null); 102 inst.replaceOperand(mo, newMo); 103 } 104 } 105 106}