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.lir2mir; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.compilers.opt.OptimizingCompilerException; 017import org.jikesrvm.compilers.opt.ir.ALoad; 018import org.jikesrvm.compilers.opt.ir.AStore; 019import org.jikesrvm.compilers.opt.ir.Binary; 020import org.jikesrvm.compilers.opt.ir.Load; 021import org.jikesrvm.compilers.opt.ir.Instruction; 022import org.jikesrvm.compilers.opt.ir.Store; 023import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; 024import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; 025import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 026import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 027import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand; 028import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; 029import org.jikesrvm.compilers.opt.ir.operand.Operand; 030import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 031import org.vmmagic.unboxed.Offset; 032import static org.jikesrvm.compilers.opt.ir.IRTools.TG; 033 034/** 035 * Contains common BURS helper functions for platforms with memory operands. 036 */ 037public abstract class BURS_MemOp_Helpers extends BURS_Common_Helpers { 038 // word size for memory operands 039 protected static final byte B = 0x01; // byte (8 bits) 040 protected static final byte W = 0x02; // word (16 bits) 041 protected static final byte DW = 0x04; // doubleword (32 bits) 042 protected static final byte QW = 0x08; // quadword (64 bits) 043 protected static final byte PARAGRAPH = 0x10; // paragraph (128 bits) 044 045 protected static final byte B_S = 0x00; // byte (8*2^0 bits) 046 protected static final byte W_S = 0x01; // word (8*2^116 bits) 047 protected static final byte DW_S = 0x02; // doubleword (8*2^2 bits) 048 protected static final byte QW_S = 0x03; // quadword (8*2^3 bits) 049 050 protected BURS_MemOp_Helpers(BURS burs) { 051 super(burs); 052 } 053 054 // Cost functions better suited to grammars with multiple non-termials 055 protected static int ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost) { 056 return ADDRESS_EQUAL(store, load, trueCost, INFINITE); 057 } 058 059 protected static int ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost, int falseCost) { 060 if (Store.getAddress(store).similar(Load.getAddress(load)) && 061 Store.getOffset(store).similar(Load.getOffset(load))) { 062 return trueCost; 063 } else { 064 return falseCost; 065 } 066 } 067 068 protected static int ARRAY_ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost) { 069 return ARRAY_ADDRESS_EQUAL(store, load, trueCost, INFINITE); 070 } 071 072 protected static int ARRAY_ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost, int falseCost) { 073 if (AStore.getArray(store).similar(ALoad.getArray(load)) && AStore.getIndex(store).similar(ALoad.getIndex(load))) { 074 return trueCost; 075 } else { 076 return falseCost; 077 } 078 } 079 080 // support to remember an address being computed in a subtree 081 private static final class AddrStackElement { 082 RegisterOperand base; 083 RegisterOperand index; 084 byte scale; 085 Offset displacement; 086 AddrStackElement next; 087 088 AddrStackElement(RegisterOperand b, RegisterOperand i, byte s, Offset d, AddrStackElement n) { 089 base = b; 090 index = i; 091 scale = s; 092 displacement = d; 093 next = n; 094 } 095 } 096 097 private AddrStackElement AddrStack; 098 099 protected final void pushAddress(RegisterOperand base, RegisterOperand index, byte scale, Offset disp) { 100 AddrStack = new AddrStackElement(base, index, scale, disp, AddrStack); 101 } 102 103 protected final void augmentAddress(Operand op) { 104 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to augment"); 105 if (op.isRegister()) { 106 RegisterOperand rop = op.asRegister(); 107 if (AddrStack.base == null) { 108 AddrStack.base = rop; 109 } else if (AddrStack.index == null) { 110 if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); 111 AddrStack.index = rop; 112 } else { 113 throw new OptimizingCompilerException("three base registers in address"); 114 } 115 } else { 116 if (VM.fullyBooted) { 117 if (VM.BuildFor64Addr && op instanceof IntConstantOperand) throw new OptimizingCompilerException("augmenting int to address in 64bit code"); 118 if (VM.BuildFor32Addr && op instanceof LongConstantOperand) throw new OptimizingCompilerException("augmenting long to address in 32bit code"); 119 } 120 int disp = op instanceof LongConstantOperand ? (int)((LongConstantOperand) op).value : ((IntConstantOperand) op).value; 121 AddrStack.displacement = AddrStack.displacement.plus(disp); 122 } 123 } 124 125 protected final void combineAddresses() { 126 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to combine"); 127 AddrStackElement tmp = AddrStack; 128 AddrStack = AddrStack.next; 129 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "only 1 address to combine"); 130 if (tmp.base != null) { 131 if (AddrStack.base == null) { 132 AddrStack.base = tmp.base; 133 } else if (AddrStack.index == null) { 134 if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); 135 AddrStack.index = tmp.base; 136 } else { 137 throw new OptimizingCompilerException("three base registers in address"); 138 } 139 } 140 if (tmp.index != null) { 141 if (AddrStack.index == null) { 142 if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); 143 AddrStack.index = tmp.index; 144 AddrStack.scale = tmp.scale; 145 } else if (AddrStack.base == null && tmp.scale == (byte) 0) { 146 AddrStack.base = tmp.base; 147 } else { 148 throw new OptimizingCompilerException("two scaled registers in address"); 149 } 150 } 151 AddrStack.displacement = AddrStack.displacement.plus(tmp.displacement.toInt()); 152 } 153 154 protected final MemoryOperand consumeAddress(byte size, LocationOperand loc, Operand guard) { 155 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to consume"); 156 MemoryOperand mo = 157 new MemoryOperand(AddrStack.base, 158 AddrStack.index, 159 AddrStack.scale, 160 AddrStack.displacement, 161 size, 162 loc, 163 guard); 164 AddrStack = AddrStack.next; 165 return mo; 166 } 167 168 // support to remember a memory operand computed in a subtree 169 private static final class MOStackElement { 170 MemoryOperand mo; 171 MOStackElement next; 172 173 MOStackElement(MemoryOperand m, MOStackElement n) { 174 mo = m; 175 next = n; 176 } 177 } 178 179 private MOStackElement MOStack; 180 181 protected final void pushMO(MemoryOperand mo) { 182 MOStack = new MOStackElement(mo, MOStack); 183 } 184 185 protected final MemoryOperand consumeMO() { 186 if (VM.VerifyAssertions) VM._assert(MOStack != null, "No memory operand to consume"); 187 MemoryOperand mo = MOStack.mo; 188 MOStack = MOStack.next; 189 return mo; 190 } 191 192 protected final MemoryOperand MO_L(Instruction s, byte size) { 193 return MO_L(s, size, 0); 194 } 195 196 protected final MemoryOperand MO_L(Instruction s, byte size, int disp) { 197 if (VM.VerifyAssertions) VM._assert(Load.conforms(s)); 198 return MO(Load.getAddress(s), 199 Load.getOffset(s), 200 size, 201 Offset.fromIntSignExtend(disp), 202 Load.getLocation(s), 203 Load.getGuard(s)); 204 } 205 206 protected final MemoryOperand MO_S(Instruction s, byte size) { 207 return MO_S(s, size, 0); 208 } 209 210 protected final MemoryOperand MO_S(Instruction s, byte size, int disp) { 211 if (VM.VerifyAssertions) VM._assert(Store.conforms(s)); 212 return MO(Store.getAddress(s), 213 Store.getOffset(s), 214 size, 215 Offset.fromIntSignExtend(disp), 216 Store.getLocation(s), 217 Store.getGuard(s)); 218 } 219 220 protected final MemoryOperand MO(Operand base, Operand offset, byte size, LocationOperand loc, 221 Operand guard) { 222 if (VM.BuildFor32Addr) { 223 if (base instanceof IntConstantOperand) { 224 if (offset instanceof IntConstantOperand) { 225 return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset)), size, loc, guard); 226 } else { 227 return MO_BD(offset, Offset.fromIntSignExtend(IV(base)), size, loc, guard); 228 } 229 } else { 230 if (offset instanceof IntConstantOperand) { 231 return MO_BD(base, Offset.fromIntSignExtend(IV(offset)), size, loc, guard); 232 } else { 233 return MO_BI(base, offset, size, loc, guard); 234 } 235 } 236 } else { 237 if (base instanceof LongConstantOperand) { 238 if (offset instanceof LongConstantOperand) { 239 return MO_D(Offset.fromLong(LV(base) + LV(offset)), size, loc, guard); 240 } else if (offset instanceof IntConstantOperand) { 241 return MO_D(Offset.fromLong(LV(base) + IV(offset)), size, loc, guard); 242 } else { 243 return MO_BD(offset, Offset.fromLong(LV(base)), size, loc, guard); 244 } 245 } else if (base instanceof IntConstantOperand) { 246 if (offset instanceof IntConstantOperand) { 247 return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset)), size, loc, guard); 248 } else if (offset instanceof LongConstantOperand) { 249 return MO_D(Offset.fromLong(IV(base) + LV(offset)), size, loc, guard); 250 } else { 251 return MO_BD(offset, Offset.fromIntSignExtend(IV(base)), size, loc, guard); 252 } 253 } else { 254 if (offset instanceof LongConstantOperand) { 255 return MO_BD(base, Offset.fromLong(LV(offset)), size, loc, guard); 256 } else if (offset instanceof IntConstantOperand) { 257 return MO_BD(base, Offset.fromIntSignExtend(IV(offset)), size, loc, guard); 258 } else { 259 return MO_BI(base, offset, size, loc, guard); 260 } 261 } 262 } 263 } 264 265 protected final MemoryOperand MO(Operand base, Operand offset, byte size, LocationOperand loc, 266 Operand guard, int disp) { 267 if (VM.BuildFor32Addr) { 268 if (base instanceof IntConstantOperand) { 269 if (offset instanceof IntConstantOperand) { 270 return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset) + disp), size, loc, guard); 271 } else { 272 return MO_BD(offset, Offset.fromIntSignExtend(IV(base) + disp), size, loc, guard); 273 } 274 } else { 275 if (offset instanceof IntConstantOperand) { 276 return MO_BD(base, Offset.fromIntSignExtend(IV(offset) + disp), size, loc, guard); 277 } else { 278 return MO_BID(base, offset, Offset.fromIntSignExtend(disp), size, loc, guard); 279 } 280 } 281 } else { 282 if (base instanceof LongConstantOperand) { 283 if (offset instanceof LongConstantOperand) { 284 return MO_D(Offset.fromLong(LV(base) + LV(offset) + disp), size, loc, guard); 285 } else if (offset instanceof IntConstantOperand) { 286 return MO_D(Offset.fromLong(LV(base) + IV(offset) + disp), size, loc, guard); 287 } else { 288 return MO_BD(offset, Offset.fromLong(LV(base) + disp), size, loc, guard); 289 } 290 } else if (base instanceof IntConstantOperand) { 291 if (offset instanceof LongConstantOperand) { 292 return MO_D(Offset.fromLong(IV(base) + LV(offset) + disp), size, loc, guard); 293 } else if (offset instanceof IntConstantOperand) { 294 return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset) + disp), size, loc, guard); 295 } else { 296 return MO_BD(offset, Offset.fromIntSignExtend(IV(base) + disp), size, loc, guard); 297 } 298 } else { 299 if (offset instanceof LongConstantOperand) { 300 return MO_BD(base, Offset.fromLong(LV(offset) + disp), size, loc, guard); 301 } else if (offset instanceof IntConstantOperand) { 302 return MO_BD(base, Offset.fromIntSignExtend(IV(offset) + disp), size, loc, guard); 303 } else { 304 return MO_BID(base, offset, Offset.fromIntSignExtend(disp), size, loc, guard); 305 } 306 } 307 } 308 } 309 310 protected final MemoryOperand MO(Operand base, Operand offset, byte size, Offset disp, 311 LocationOperand loc, Operand guard) { 312 if (VM.BuildFor32Addr) { 313 if (base instanceof IntConstantOperand) { 314 if (offset instanceof IntConstantOperand) { 315 return MO_D(disp.plus(IV(base) + IV(offset)), size, loc, guard); 316 } else { 317 return MO_BD(offset, disp.plus(IV(base)), size, loc, guard); 318 } 319 } else { 320 if (offset instanceof IntConstantOperand) { 321 return MO_BD(base, disp.plus(IV(offset)), size, loc, guard); 322 } else { 323 return MO_BID(base, offset, disp, size, loc, guard); 324 } 325 } 326 } else { 327 if (base instanceof LongConstantOperand) { 328 if (offset instanceof LongConstantOperand) { 329 return MO_D(Offset.fromLong(disp.toLong() + LV(base) + LV(offset)), size, loc, guard); 330 } else if (offset instanceof IntConstantOperand) { 331 return MO_D(Offset.fromLong(disp.toLong() + LV(base) + IV(offset)), size, loc, guard); 332 } else { 333 return MO_BD(offset, Offset.fromLong(disp.toLong() + LV(base)), size, loc, guard); 334 } 335 } else if (base instanceof IntConstantOperand) { 336 if (offset instanceof LongConstantOperand) { 337 return MO_D(Offset.fromLong(disp.toLong() + IV(base) + LV(offset)), size, loc, guard); 338 } else if (offset instanceof IntConstantOperand) { 339 return MO_D(disp.plus(IV(base) + IV(offset)), size, loc, guard); 340 } else { 341 return MO_BD(offset, disp.plus(IV(base)), size, loc, guard); 342 } 343 } else { 344 if (offset instanceof LongConstantOperand) { 345 return MO_BD(base, disp.plus(Offset.fromLong(LV(offset))), size, loc, guard); 346 } else if (offset instanceof IntConstantOperand) { 347 return MO_BD(base, disp.plus(IV(offset)), size, loc, guard); 348 } else { 349 return MO_BID(base, offset, disp, size, loc, guard); 350 } 351 } 352 } 353 } 354 355 356 protected final MemoryOperand MO_B(Operand base, byte size, LocationOperand loc, Operand guard) { 357 return MemoryOperand.B(R(base), size, loc, guard); 358 } 359 360 protected final MemoryOperand MO_BI(Operand base, Operand index, byte size, LocationOperand loc, 361 Operand guard) { 362 return MemoryOperand.BI(R(base), R(index), size, loc, guard); 363 } 364 365 protected final MemoryOperand MO_BD(Operand base, Offset disp, byte size, LocationOperand loc, 366 Operand guard) { 367 return MemoryOperand.BD(R(base), disp, size, loc, guard); 368 } 369 370 protected final MemoryOperand MO_BID(Operand base, Operand index, Offset disp, byte size, 371 LocationOperand loc, Operand guard) { 372 return MemoryOperand.BID(R(base), R(index), disp, size, loc, guard); 373 } 374 375 protected final MemoryOperand MO_BIS(Operand base, Operand index, byte scale, byte size, 376 LocationOperand loc, Operand guard) { 377 return MemoryOperand.BIS(R(base), R(index), scale, size, loc, guard); 378 } 379 380 protected final MemoryOperand MO_D(Offset disp, byte size, LocationOperand loc, Operand guard) { 381 return MemoryOperand.D(disp.toWord().toAddress(), size, loc, guard); 382 } 383 384 protected final MemoryOperand MO_AL(Instruction s, byte scale, byte size) { 385 return MO_AL(s, scale, size, 0); 386 } 387 388 protected final MemoryOperand MO_AL(Instruction s, byte scale, byte size, int disp) { 389 if (VM.VerifyAssertions) VM._assert(ALoad.conforms(s)); 390 return MO_ARRAY(ALoad.getArray(s), 391 ALoad.getIndex(s), 392 scale, 393 size, 394 Offset.fromIntSignExtend(disp), 395 ALoad.getLocation(s), 396 ALoad.getGuard(s)); 397 } 398 399 protected final MemoryOperand MO_AS(Instruction s, byte scale, byte size) { 400 return MO_AS(s, scale, size, 0); 401 } 402 403 404 protected final MemoryOperand MO_AS(Instruction s, byte scale, byte size, int disp) { 405 if (VM.VerifyAssertions) VM._assert(AStore.conforms(s)); 406 return MO_ARRAY(AStore.getArray(s), 407 AStore.getIndex(s), 408 scale, 409 size, 410 Offset.fromIntSignExtend(disp), 411 AStore.getLocation(s), 412 AStore.getGuard(s)); 413 } 414 415 private MemoryOperand MO_ARRAY(Operand base, Operand index, byte scale, byte size, Offset disp, 416 LocationOperand loc, Operand guard) { 417 if (index instanceof IntConstantOperand) { 418 if (VM.BuildFor32Addr && base instanceof IntConstantOperand) { 419 return MO_D(disp.plus(IV(base) + (IV(index) << scale)), size, loc, guard); 420 } else if (VM.BuildFor64Addr && base instanceof LongConstantOperand) { 421 return MO_D(disp.plus(Offset.fromLong(LV(base) + (IV(index) << scale))), size, loc, guard); 422 } else { 423 return MO_BD(base, disp.plus(IV(index) << scale), size, loc, guard); 424 } 425 } else { 426 if (VM.BuildFor32Addr && base instanceof IntConstantOperand) { 427 return new MemoryOperand(null, R(index), scale, disp.plus(IV(base)), size, loc, guard); 428 } else if (VM.BuildFor64Addr && base instanceof LongConstantOperand) { 429 return new MemoryOperand(null, R(index), scale, disp.plus(Offset.fromLong(LV(base))), size, loc, guard); 430 } else { 431 return new MemoryOperand(R(base), R(index), scale, disp, size, loc, guard); 432 } 433 } 434 } 435 436 protected final MemoryOperand MO_MC(Instruction s) { 437 Operand base = Binary.getVal1(s); // JTOC 438 Operand val = Binary.getVal2(s); // float or double value 439 if (val instanceof FloatConstantOperand) { 440 FloatConstantOperand fc = (FloatConstantOperand) val; 441 Offset offset = fc.offset; 442 LocationOperand loc = new LocationOperand(offset); 443 if (base instanceof IntConstantOperand) { 444 return MO_D(offset.plus(IV(base)), DW, loc, TG()); 445 } else if (VM.BuildFor64Addr && base instanceof LongConstantOperand) { 446 return MO_D(offset.plus(Offset.fromLong(LV(base))), DW, loc, TG()); 447 } else { 448 return MO_BD(base, offset, DW, loc, TG()); 449 } 450 } else { 451 DoubleConstantOperand dc = (DoubleConstantOperand) val; 452 Offset offset = dc.offset; 453 LocationOperand loc = new LocationOperand(offset); 454 if (base instanceof IntConstantOperand) { 455 return MO_D(offset.plus(IV(base)), QW, loc, TG()); 456 } else if (VM.BuildFor64Addr && base instanceof LongConstantOperand) { 457 return MO_D(offset.plus(Offset.fromLong(LV(base))), QW, loc, TG()); 458 } else { 459 return MO_BD(Binary.getVal1(s), dc.offset, QW, loc, TG()); 460 } 461 } 462 } 463}