/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.lir2mir; import org.jikesrvm.VM; import org.jikesrvm.compilers.opt.OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.ALoad; import org.jikesrvm.compilers.opt.ir.AStore; import org.jikesrvm.compilers.opt.ir.Binary; import org.jikesrvm.compilers.opt.ir.Load; import org.jikesrvm.compilers.opt.ir.Instruction; import org.jikesrvm.compilers.opt.ir.Store; import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; import org.jikesrvm.compilers.opt.ir.operand.Operand; import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; import org.vmmagic.unboxed.Offset; /** * Contains common BURS helper functions for platforms with memory operands. */ public abstract class BURS_MemOp_Helpers extends BURS_Common_Helpers { // word size for memory operands protected static final byte B = 0x01; // byte (8 bits) protected static final byte W = 0x02; // word (16 bits) protected static final byte DW = 0x04; // doubleword (32 bits) protected static final byte QW = 0x08; // quadword (64 bits) protected static final byte PARAGRAPH = 0x10; // paragraph (128 bits) protected static final byte B_S = 0x00; // byte (8*2^0 bits) protected static final byte W_S = 0x01; // word (8*2^116 bits) protected static final byte DW_S = 0x02; // doubleword (8*2^2 bits) protected static final byte QW_S = 0x03; // quadword (8*2^3 bits) protected BURS_MemOp_Helpers(BURS burs) { super(burs); } // Cost functions better suited to grammars with multiple non-termials protected final int ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost) { return ADDRESS_EQUAL(store, load, trueCost, INFINITE); } protected final int ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost, int falseCost) { if (Store.getAddress(store).similar(Load.getAddress(load)) && Store.getOffset(store).similar(Load.getOffset(load))) { return trueCost; } else { return falseCost; } } protected final int ARRAY_ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost) { return ARRAY_ADDRESS_EQUAL(store, load, trueCost, INFINITE); } protected final int ARRAY_ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost, int falseCost) { if (AStore.getArray(store).similar(ALoad.getArray(load)) && AStore.getIndex(store).similar(ALoad.getIndex(load))) { return trueCost; } else { return falseCost; } } // support to remember an address being computed in a subtree private static final class AddrStackElement { RegisterOperand base; RegisterOperand index; byte scale; Offset displacement; AddrStackElement next; AddrStackElement(RegisterOperand b, RegisterOperand i, byte s, Offset d, AddrStackElement n) { base = b; index = i; scale = s; displacement = d; next = n; } } private AddrStackElement AddrStack; protected final void pushAddress(RegisterOperand base, RegisterOperand index, byte scale, Offset disp) { AddrStack = new AddrStackElement(base, index, scale, disp, AddrStack); } protected final void augmentAddress(Operand op) { if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to augment"); if (op.isRegister()) { RegisterOperand rop = op.asRegister(); if (AddrStack.base == null) { AddrStack.base = rop; } else if (AddrStack.index == null) { if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); AddrStack.index = rop; } else { throw new OptimizingCompilerException("three base registers in address"); } } else { int disp = ((IntConstantOperand) op).value; AddrStack.displacement = AddrStack.displacement.plus(disp); } } protected final void combineAddresses() { if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to combine"); AddrStackElement tmp = AddrStack; AddrStack = AddrStack.next; if (VM.VerifyAssertions) VM._assert(AddrStack != null, "only 1 address to combine"); if (tmp.base != null) { if (AddrStack.base == null) { AddrStack.base = tmp.base; } else if (AddrStack.index == null) { if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); AddrStack.index = tmp.base; } else { throw new OptimizingCompilerException("three base registers in address"); } } if (tmp.index != null) { if (AddrStack.index == null) { if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); AddrStack.index = tmp.index; AddrStack.scale = tmp.scale; } else if (AddrStack.base == null && tmp.scale == (byte) 0) { AddrStack.base = tmp.base; } else { throw new OptimizingCompilerException("two scaled registers in address"); } } AddrStack.displacement = AddrStack.displacement.plus(tmp.displacement.toInt()); } protected final MemoryOperand consumeAddress(byte size, LocationOperand loc, Operand guard) { if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to consume"); MemoryOperand mo = new MemoryOperand(AddrStack.base, AddrStack.index, AddrStack.scale, AddrStack.displacement, size, loc, guard); AddrStack = AddrStack.next; return mo; } // support to remember a memory operand computed in a subtree private static final class MOStackElement { MemoryOperand mo; MOStackElement next; MOStackElement(MemoryOperand m, MOStackElement n) { mo = m; next = n; } } private MOStackElement MOStack; protected final void pushMO(MemoryOperand mo) { MOStack = new MOStackElement(mo, MOStack); } protected final MemoryOperand consumeMO() { if (VM.VerifyAssertions) VM._assert(MOStack != null, "No memory operand to consume"); MemoryOperand mo = MOStack.mo; MOStack = MOStack.next; return mo; } /** * Construct a memory operand for the effective address of the * load instruction */ protected final MemoryOperand MO_L(Instruction s, byte size) { return MO_L(s, size, 0); } /** * Construct a displaced memory operand for the effective address of the * load instruction */ protected final MemoryOperand MO_L(Instruction s, byte size, int disp) { if (VM.VerifyAssertions) VM._assert(Load.conforms(s)); return MO(Load.getAddress(s), Load.getOffset(s), size, Offset.fromIntSignExtend(disp), Load.getLocation(s), Load.getGuard(s)); } /** * Construct a memory operand for the effective address of the * store instruction */ protected final MemoryOperand MO_S(Instruction s, byte size) { return MO_S(s, size, 0); } /** * Construct a displaced memory operand for the effective address of the * store instruction */ protected final MemoryOperand MO_S(Instruction s, byte size, int disp) { if (VM.VerifyAssertions) VM._assert(Store.conforms(s)); return MO(Store.getAddress(s), Store.getOffset(s), size, Offset.fromIntSignExtend(disp), Store.getLocation(s), Store.getGuard(s)); } protected final MemoryOperand MO(Operand base, Operand offset, byte size, LocationOperand loc, Operand guard) { if (base instanceof IntConstantOperand) { if (offset instanceof IntConstantOperand) { return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset)), size, loc, guard); } else { return MO_BD(offset, Offset.fromIntSignExtend(IV(base)), size, loc, guard); } } else { if (offset instanceof IntConstantOperand) { return MO_BD(base, Offset.fromIntSignExtend(IV(offset)), size, loc, guard); } else { return MO_BI(base, offset, size, loc, guard); } } } protected final MemoryOperand MO(Operand base, Operand offset, byte size, LocationOperand loc, Operand guard, int disp) { if (base instanceof IntConstantOperand) { if (offset instanceof IntConstantOperand) { return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset) + disp), size, loc, guard); } else { return MO_BD(offset, Offset.fromIntSignExtend(IV(base)+disp), size, loc, guard); } } else { if (offset instanceof IntConstantOperand) { return MO_BD(base, Offset.fromIntSignExtend(IV(offset)+disp), size, loc, guard); } else { return MO_BID(base, offset, Offset.fromIntSignExtend(disp), size, loc, guard); } } } protected final MemoryOperand MO(Operand base, Operand offset, byte size, Offset disp, LocationOperand loc, Operand guard) { if (base instanceof IntConstantOperand) { if (offset instanceof IntConstantOperand) { return MO_D(disp.plus(IV(base) + IV(offset)), size, loc, guard); } else { return MO_BD(offset, disp.plus(IV(base)), size, loc, guard); } } else { if (offset instanceof IntConstantOperand) { return MO_BD(base, disp.plus(IV(offset)), size, loc, guard); } else { return MO_BID(base, offset, disp, size, loc, guard); } } } protected final MemoryOperand MO_B(Operand base, byte size, LocationOperand loc, Operand guard) { return MemoryOperand.B(R(base), size, loc, guard); } protected final MemoryOperand MO_BI(Operand base, Operand index, byte size, LocationOperand loc, Operand guard) { return MemoryOperand.BI(R(base), R(index), size, loc, guard); } protected final MemoryOperand MO_BD(Operand base, Offset disp, byte size, LocationOperand loc, Operand guard) { return MemoryOperand.BD(R(base), disp, size, loc, guard); } protected final MemoryOperand MO_BID(Operand base, Operand index, Offset disp, byte size, LocationOperand loc, Operand guard) { return MemoryOperand.BID(R(base), R(index), disp, size, loc, guard); } protected final MemoryOperand MO_BIS(Operand base, Operand index, byte scale, byte size, LocationOperand loc, Operand guard) { return MemoryOperand.BIS(R(base), R(index), scale, size, loc, guard); } protected final MemoryOperand MO_D(Offset disp, byte size, LocationOperand loc, Operand guard) { return MemoryOperand.D(disp.toWord().toAddress(), size, loc, guard); } /** * Construct a memory operand for the effective address of the * array load instruction */ protected final MemoryOperand MO_AL(Instruction s, byte scale, byte size) { return MO_AL(s, scale, size, 0); } /** * Construct a memory operand for the effective address of the * array load instruction */ protected final MemoryOperand MO_AL(Instruction s, byte scale, byte size, int disp) { if (VM.VerifyAssertions) VM._assert(ALoad.conforms(s)); return MO_ARRAY(ALoad.getArray(s), ALoad.getIndex(s), scale, size, Offset.fromIntSignExtend(disp), ALoad.getLocation(s), ALoad.getGuard(s)); } /** * Construct a memory operand for the effective address of the * array store instruction */ protected final MemoryOperand MO_AS(Instruction s, byte scale, byte size) { return MO_AS(s, scale, size, 0); } // Construct a memory operand for the effective address of the array store instruction protected final MemoryOperand MO_AS(Instruction s, byte scale, byte size, int disp) { if (VM.VerifyAssertions) VM._assert(AStore.conforms(s)); return MO_ARRAY(AStore.getArray(s), AStore.getIndex(s), scale, size, Offset.fromIntSignExtend(disp), AStore.getLocation(s), AStore.getGuard(s)); } /** * Construct memory operand for an array access */ private MemoryOperand MO_ARRAY(Operand base, Operand index, byte scale, byte size, Offset disp, LocationOperand loc, Operand guard) { if (base instanceof IntConstantOperand) { if (index instanceof IntConstantOperand) { return MO_D(disp.plus(IV(base) + (IV(index) << scale)), size, loc, guard); } else { return new MemoryOperand(null, R(index), scale, disp.plus(IV(base)), size, loc, guard); } } else { if (index instanceof IntConstantOperand) { return MO_BD(base, disp.plus(IV(index) << scale), size, loc, guard); } else { return new MemoryOperand(R(base), R(index), scale, disp, size, loc, guard); } } } /** * Construct memory operand for a MATERIALIZE_FP_CONSTANT */ protected final MemoryOperand MO_MC(Instruction s) { Operand base = Binary.getVal1(s); // JTOC Operand val = Binary.getVal2(s); // float or double value if (val instanceof FloatConstantOperand) { FloatConstantOperand fc = (FloatConstantOperand) val; Offset offset = fc.offset; LocationOperand loc = new LocationOperand(offset); if (base instanceof IntConstantOperand) { return MO_D(offset.plus(IV(base)), DW, loc, TG()); } else { return MO_BD(base, offset, DW, loc, TG()); } } else { DoubleConstantOperand dc = (DoubleConstantOperand) val; Offset offset = dc.offset; LocationOperand loc = new LocationOperand(offset); if (base instanceof IntConstantOperand) { return MO_D(offset.plus(IV(base)), QW, loc, TG()); } else { return MO_BD(Binary.getVal1(s), dc.offset, QW, loc, TG()); } } } }