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.ir.operand; 014 015import org.jikesrvm.compilers.opt.OptimizingCompilerException; 016import org.vmmagic.unboxed.Address; 017import org.vmmagic.unboxed.Offset; 018 019/** 020 * A memory operand. 021 * Used to represent complex addressing modes on CISC machines. 022 * A memory operand contains some set of other operands that are used 023 * in the address calculation. 024 * <p> 025 * May contain 0, 1, or 2 RegisterOperands as well as a scale factor and 026 * displacement. 027 * <p> 028 * The effective address represented by this operand is: 029 * <pre> 030 * [base] + [index]*(2^scale) + disp 031 * </pre> 032 * 033 * @see Operand 034 */ 035public final class MemoryOperand extends Operand { 036 037 /** 038 * The location operand describing this memory access 039 */ 040 public LocationOperand loc; 041 042 /** 043 * The guard operand that validates this memory access 044 */ 045 public Operand guard; 046 047 /** 048 * The base register (may be {@code null}) 049 */ 050 public RegisterOperand base; 051 052 /** 053 * The index register (may be {@code null}) 054 */ 055 public RegisterOperand index; 056 057 /** 058 * The scale value (log power of 2) 059 * valid values are 0,1,2,3 060 */ 061 public byte scale; 062 063 /** 064 * The displacement 065 */ 066 public Offset disp; 067 068 /** 069 * Number of bytes being accessed (1,2,4,8) 070 */ 071 public byte size; 072 073 public MemoryOperand(RegisterOperand base, RegisterOperand index, byte scale, Offset disp, byte size, 074 LocationOperand loc, Operand guard) { 075 this.loc = loc; 076 this.guard = guard; 077 this.base = base; 078 this.index = index; 079 this.scale = scale; 080 this.disp = disp; 081 this.size = size; 082 if (loc != null) loc.instruction = null; 083 if (guard != null) guard.instruction = null; 084 if (base != null) base.instruction = null; 085 if (index != null) index.instruction = null; 086 } 087 088 // Shortcuts for some common addressing modes 089 public static MemoryOperand B(RegisterOperand base, byte size, LocationOperand loc, Operand guard) { 090 return new MemoryOperand(base, null, (byte) 0, Offset.zero(), size, loc, guard); 091 } 092 093 public static MemoryOperand BI(RegisterOperand base, RegisterOperand index, byte size, 094 LocationOperand loc, Operand guard) { 095 return new MemoryOperand(base, index, (byte) 0, Offset.zero(), size, loc, guard); 096 } 097 098 public static MemoryOperand BD(RegisterOperand base, Offset disp, byte size, LocationOperand loc, 099 Operand guard) { 100 return new MemoryOperand(base, null, (byte) 0, disp, size, loc, guard); 101 } 102 103 public static MemoryOperand BID(RegisterOperand base, RegisterOperand index, Offset disp, byte size, 104 LocationOperand loc, Operand guard) { 105 return new MemoryOperand(base, index, (byte) 0, disp, size, loc, guard); 106 } 107 108 public static MemoryOperand BIS(RegisterOperand base, RegisterOperand index, byte scale, byte size, 109 LocationOperand loc, Operand guard) { 110 return new MemoryOperand(base, index, scale, Offset.zero(), size, loc, guard); 111 } 112 113 public static MemoryOperand D(Address disp, byte size, LocationOperand loc, Operand guard) { 114 return new MemoryOperand(null, null, (byte) 0, disp.toWord().toOffset(), size, loc, guard); 115 } 116 117 public static MemoryOperand I(RegisterOperand base, byte size, LocationOperand loc, Operand guard) { 118 return new MemoryOperand(base, null, (byte) 0, Offset.zero(), size, loc, guard); 119 } 120 121 @Override 122 public Operand copy() { 123 RegisterOperand newBase = (base != null) ? (RegisterOperand) base.copy() : null; 124 RegisterOperand newIndex = (index != null) ? (RegisterOperand) index.copy() : null; 125 LocationOperand newLoc = (loc != null) ? (LocationOperand) loc.copy() : null; 126 Operand newGuard = (guard != null) ? guard.copy() : null; 127 return new MemoryOperand(newBase, newIndex, scale, disp, size, newLoc, newGuard); 128 } 129 130 @Override 131 public boolean similar(Operand op) { 132 if (op instanceof MemoryOperand) { 133 MemoryOperand mop = (MemoryOperand) op; 134 if (base == null) { 135 if (mop.base != null) return false; 136 } else { 137 if (mop.base == null) return false; 138 if (!base.similar(mop.base)) return false; 139 } 140 if (index == null) { 141 if (mop.index != null) return false; 142 } else { 143 if (mop.index == null) return false; 144 if (!index.similar(mop.index)) return false; 145 } 146 return (mop.scale == scale) && (mop.disp.EQ(disp)) && (mop.size == size); 147 } else { 148 return false; 149 } 150 } 151 152 /** 153 * Return a string rep of the operand (ie the effective address) 154 */ 155 @Override 156 public String toString() { 157 String addr = (base == null) ? "<0" : "<[" + base + "]"; 158 if (index != null) { 159 addr += "+[" + index; 160 switch (scale) { 161 case 0: 162 addr += "]"; 163 break; 164 case 1: 165 addr += "*2]"; 166 break; 167 case 2: 168 addr += "*4]"; 169 break; 170 case 3: 171 addr += "*8]"; 172 break; 173 default: 174 OptimizingCompilerException.UNREACHABLE(); 175 } 176 } 177 if (!disp.isZero()) { 178 addr += "+" + disp.toInt(); 179 } 180 switch (size) { 181 case 1: 182 addr += ">B"; 183 break; 184 case 2: 185 addr += ">W"; 186 break; 187 case 4: 188 addr += ">DW"; 189 break; 190 case 8: 191 addr += ">QW"; 192 break; 193 case 16: 194 addr += ">PARAGRAPH"; 195 break; 196 default: 197 OptimizingCompilerException.UNREACHABLE(); 198 } 199 if (loc != null && guard != null) { 200 addr += " (" + loc + ", " + guard + ")"; 201 } else if (loc != null) { 202 addr += " (" + loc + ")"; 203 } else if (guard != null) { 204 addr += " (" + guard + ")"; 205 } 206 return addr; 207 } 208}