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     */
013    package org.jikesrvm.compilers.opt.bc2ir;
014    
015    import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_ADDRESS;
016    import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_INT;
017    import static org.jikesrvm.compilers.opt.ir.Operators.ADDR_2INT;
018    import static org.jikesrvm.compilers.opt.ir.Operators.ADDR_2LONG;
019    import static org.jikesrvm.compilers.opt.ir.Operators.ARRAYLENGTH;
020    import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_ADDR;
021    import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_INT;
022    import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_LONG;
023    import static org.jikesrvm.compilers.opt.ir.Operators.BOOLEAN_CMP_ADDR;
024    import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_LOAD;
025    import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_STORE;
026    import static org.jikesrvm.compilers.opt.ir.Operators.CALL;
027    import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_AS_LONG_BITS;
028    import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_LOAD;
029    import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_SQRT;
030    import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_STORE;
031    import static org.jikesrvm.compilers.opt.ir.Operators.FENCE;
032    import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_AS_INT_BITS;
033    import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_LOAD;
034    import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_SQRT;
035    import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_STORE;
036    import static org.jikesrvm.compilers.opt.ir.Operators.GET_OBJ_TIB;
037    import static org.jikesrvm.compilers.opt.ir.Operators.GET_TIME_BASE;
038    import static org.jikesrvm.compilers.opt.ir.Operators.GET_TYPE_FROM_TIB;
039    import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRSigExt;
040    import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRZerExt;
041    import static org.jikesrvm.compilers.opt.ir.Operators.INT_ADD;
042    import static org.jikesrvm.compilers.opt.ir.Operators.INT_BITS_AS_FLOAT;
043    import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD;
044    import static org.jikesrvm.compilers.opt.ir.Operators.INT_SHL;
045    import static org.jikesrvm.compilers.opt.ir.Operators.INT_STORE;
046    import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2ADDR;
047    import static org.jikesrvm.compilers.opt.ir.Operators.LONG_BITS_AS_DOUBLE;
048    import static org.jikesrvm.compilers.opt.ir.Operators.LONG_LOAD;
049    import static org.jikesrvm.compilers.opt.ir.Operators.LONG_STORE;
050    import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_ADDR;
051    import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_INT;
052    import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_LONG;
053    import static org.jikesrvm.compilers.opt.ir.Operators.READ_CEILING;
054    import static org.jikesrvm.compilers.opt.ir.Operators.REF_ADD;
055    import static org.jikesrvm.compilers.opt.ir.Operators.REF_AND;
056    import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD;
057    import static org.jikesrvm.compilers.opt.ir.Operators.REF_MOVE;
058    import static org.jikesrvm.compilers.opt.ir.Operators.REF_NOT;
059    import static org.jikesrvm.compilers.opt.ir.Operators.REF_OR;
060    import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHL;
061    import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHR;
062    import static org.jikesrvm.compilers.opt.ir.Operators.REF_STORE;
063    import static org.jikesrvm.compilers.opt.ir.Operators.REF_SUB;
064    import static org.jikesrvm.compilers.opt.ir.Operators.REF_USHR;
065    import static org.jikesrvm.compilers.opt.ir.Operators.REF_XOR;
066    import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_LOAD;
067    import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_STORE;
068    import static org.jikesrvm.compilers.opt.ir.Operators.SYSCALL;
069    import static org.jikesrvm.compilers.opt.ir.Operators.UBYTE_LOAD;
070    import static org.jikesrvm.compilers.opt.ir.Operators.USHORT_LOAD;
071    import static org.jikesrvm.compilers.opt.ir.Operators.WRITE_FLOOR;
072    
073    import org.jikesrvm.VM;
074    import org.jikesrvm.ArchitectureSpecificOpt.GenerateMachineSpecificMagic;
075    import org.jikesrvm.classloader.Atom;
076    import org.jikesrvm.classloader.RVMField;
077    import org.jikesrvm.classloader.MemberReference;
078    import org.jikesrvm.classloader.MethodReference;
079    import org.jikesrvm.classloader.TypeReference;
080    import org.jikesrvm.compilers.opt.MagicNotImplementedException;
081    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
082    import org.jikesrvm.compilers.opt.ir.Attempt;
083    import org.jikesrvm.compilers.opt.ir.Binary;
084    import org.jikesrvm.compilers.opt.ir.BooleanCmp;
085    import org.jikesrvm.compilers.opt.ir.Call;
086    import org.jikesrvm.compilers.opt.ir.Empty;
087    import org.jikesrvm.compilers.opt.ir.GuardedUnary;
088    import org.jikesrvm.compilers.opt.ir.Instruction;
089    import org.jikesrvm.compilers.opt.ir.Load;
090    import org.jikesrvm.compilers.opt.ir.Move;
091    import org.jikesrvm.compilers.opt.ir.Nullary;
092    import org.jikesrvm.compilers.opt.ir.Operator;
093    import org.jikesrvm.compilers.opt.ir.Prepare;
094    import org.jikesrvm.compilers.opt.ir.Store;
095    import org.jikesrvm.compilers.opt.ir.Unary;
096    import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand;
097    import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand;
098    import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand;
099    import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
100    import org.jikesrvm.compilers.opt.ir.operand.LocationOperand;
101    import org.jikesrvm.compilers.opt.ir.operand.MethodOperand;
102    import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand;
103    import org.jikesrvm.compilers.opt.ir.operand.Operand;
104    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
105    import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
106    import org.jikesrvm.objectmodel.TIBLayoutConstants;
107    import org.jikesrvm.runtime.ArchEntrypoints;
108    import org.jikesrvm.runtime.MagicNames;
109    import org.vmmagic.pragma.Interruptible;
110    import org.vmmagic.unboxed.Address;
111    import org.vmmagic.unboxed.Offset;
112    
113    /**
114     * This class implements the non-machine-specific magics for the opt compiler.
115     * By non-machine-specific we mean that the IR generated to implement the magic
116     * is independent of the target-architecture.
117     * It does not mean that the eventual MIR that implements the magic
118     * won't differ from architecture to architecture.
119     */
120    public class GenerateMagic implements TIBLayoutConstants  {
121    
122      /**
123       * "Semantic inlining" of methods of the Magic class.
124       * Based on the methodName, generate a sequence of opt instructions
125       * that implement the magic, updating the expression stack as necessary.
126       *
127       * @param bc2ir the bc2ir object that is generating the
128       *              ir containing this magic
129       * @param gc must be bc2ir.gc
130       * @param meth the RVMMethod that is the magic method
131       */
132      static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth)
133          throws MagicNotImplementedException {
134    
135        if (gc.method.hasNoInlinePragma()) gc.allocFrame = true;
136    
137        // HACK: Don't schedule any bbs containing unsafe magics.
138        // TODO: move this to individual magics that are unsafe.
139        // -- igor 08/13/1999
140        bc2ir.markBBUnsafeForScheduling();
141        Atom methodName = meth.getName();
142    
143        boolean address = (meth.getType() == TypeReference.Address);
144    
145        // Address magic
146        TypeReference[] types = meth.getParameterTypes();
147        TypeReference returnType = meth.getReturnType();
148    
149        if (address && isLoad(methodName)) {
150          // LOAD
151          Operand offset = (types.length == 0) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
152          Operand base = bc2ir.popAddress();
153          RegisterOperand result = gc.temps.makeTemp(returnType);
154          bc2ir.appendInstruction(Load.create(getOperator(returnType, LOAD_OP), result, base, offset, null));
155          bc2ir.push(result.copyD2U(), returnType);
156    
157        } else if (address && isPrepare(methodName)) {
158          // PREPARE
159          Operand offset = (types.length == 0) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
160          Operand base = bc2ir.popAddress();
161          RegisterOperand result = gc.temps.makeTemp(returnType);
162          bc2ir.appendInstruction(Prepare.create(getOperator(returnType, PREPARE_OP), result, base, offset, null));
163          bc2ir.push(result.copyD2U(), returnType);
164    
165        } else if (address && methodName == MagicNames.attempt) {
166          // ATTEMPT
167          TypeReference attemptType = types[0];
168    
169          Operand offset = (types.length == 2) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
170    
171          Operand newVal = bc2ir.pop();
172          Operand oldVal = bc2ir.pop();
173          Operand base = bc2ir.popAddress();
174          RegisterOperand test = gc.temps.makeTempInt();
175          bc2ir.appendInstruction(Attempt.create(getOperator(attemptType, ATTEMPT_OP),
176                                                 test,
177                                                 base,
178                                                 offset,
179                                                 oldVal,
180                                                 newVal,
181                                                 null));
182          bc2ir.push(test.copyD2U(), returnType);
183    
184        } else if (address && methodName == MagicNames.store) {
185          // STORE
186          TypeReference storeType = types[0];
187    
188          Operand offset = (types.length == 1) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
189    
190          Operand val = bc2ir.pop(storeType);
191          Operand base = bc2ir.popAddress();
192          bc2ir.appendInstruction(Store.create(getOperator(storeType, STORE_OP), val, base, offset, null));
193    
194        } else if (methodName == MagicNames.getThreadRegister) {
195          RegisterOperand rop = gc.temps.makeTROp();
196          bc2ir.markGuardlessNonNull(rop);
197          bc2ir.push(rop);
198        } else if (methodName == MagicNames.setThreadRegister) {
199          Operand val = bc2ir.popRef();
200          if (val instanceof RegisterOperand) {
201            bc2ir.appendInstruction(Move.create(REF_MOVE, gc.temps.makeTROp(), val));
202          } else {
203            String msg = " Unexpected operand Magic.setThreadRegister";
204            throw MagicNotImplementedException.UNEXPECTED(msg);
205          }
206        } else if (methodName == MagicNames.addressArrayCreate) {
207          Instruction s = bc2ir.generateAnewarray(null, meth.getType().getArrayElementType());
208          bc2ir.appendInstruction(s);
209        } else if (methodName == MagicNames.addressArrayLength) {
210          Operand op1 = bc2ir.pop();
211          bc2ir.clearCurrentGuard();
212          if (bc2ir.do_NullCheck(op1)) {
213            return true;
214          }
215          RegisterOperand t = gc.temps.makeTempInt();
216          Instruction s = GuardedUnary.create(ARRAYLENGTH, t, op1, bc2ir.getCurrentGuard());
217          bc2ir.push(t.copyD2U());
218          bc2ir.appendInstruction(s);
219        } else if (methodName == MagicNames.addressArrayGet) {
220          TypeReference elementType = meth.getReturnType();
221          Operand index = bc2ir.popInt();
222          Operand ref = bc2ir.popRef();
223          RegisterOperand offsetI = gc.temps.makeTempInt();
224          RegisterOperand offset = gc.temps.makeTempOffset();
225          RegisterOperand result;
226          if (meth.getType().isCodeArrayType()) {
227            if (VM.BuildForIA32) {
228              result = gc.temps.makeTemp(TypeReference.Byte);
229              bc2ir.appendInstruction(Load.create(BYTE_LOAD,
230                                                  result,
231                                                  ref,
232                                                  index,
233                                                  new LocationOperand(elementType),
234                                                  new TrueGuardOperand()));
235            } else if (VM.BuildForPowerPC) {
236              result = gc.temps.makeTemp(TypeReference.Int);
237              bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT)));
238              bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
239              bc2ir.appendInstruction(Load.create(INT_LOAD,
240                                                  result,
241                                                  ref,
242                                                  offset.copy(),
243                                                  new LocationOperand(elementType),
244                                                  new TrueGuardOperand()));
245            }
246          } else {
247            result = gc.temps.makeTemp(elementType);
248            bc2ir.appendInstruction(Binary.create(INT_SHL,
249                                                  offsetI,
250                                                  index,
251                                                  new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
252            bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
253            bc2ir.appendInstruction(Load.create(REF_LOAD,
254                                                result,
255                                                ref,
256                                                offset.copy(),
257                                                new LocationOperand(elementType),
258                                                new TrueGuardOperand()));
259          }
260          bc2ir.push(result.copyD2U());
261        } else if (methodName == MagicNames.addressArraySet) {
262          TypeReference elementType = meth.getParameterTypes()[1];
263          Operand val = bc2ir.pop();
264          Operand index = bc2ir.popInt();
265          Operand ref = bc2ir.popRef();
266          RegisterOperand offsetI = gc.temps.makeTempInt();
267          RegisterOperand offset = gc.temps.makeTempOffset();
268          if (meth.getType().isCodeArrayType()) {
269            if (VM.BuildForIA32) {
270              bc2ir.appendInstruction(Store.create(BYTE_STORE,
271                                                   val,
272                                                   ref,
273                                                   index,
274                                                   new LocationOperand(elementType),
275                                                   new TrueGuardOperand()));
276            } else if (VM.BuildForPowerPC) {
277              bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT)));
278              bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
279              bc2ir.appendInstruction(Store.create(INT_STORE,
280                                                   val,
281                                                   ref,
282                                                   offset.copy(),
283                                                   new LocationOperand(elementType),
284                                                   new TrueGuardOperand()));
285            }
286          } else {
287            bc2ir.appendInstruction(Binary.create(INT_SHL,
288                                                  offsetI,
289                                                  index,
290                                                  new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
291            bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
292            bc2ir.appendInstruction(Store.create(REF_STORE,
293                                                 val,
294                                                 ref,
295                                                 offset.copy(),
296                                                 new LocationOperand(elementType),
297                                                 new TrueGuardOperand()));
298          }
299        } else if (methodName == MagicNames.getIntAtOffset) {
300          Operand offset = bc2ir.popAddress();
301          Operand object = bc2ir.popRef();
302          RegisterOperand val = gc.temps.makeTempInt();
303          bc2ir.appendInstruction(Load.create(INT_LOAD, val, object, offset, null));
304          bc2ir.push(val.copyD2U());
305        } else if (methodName == MagicNames.setIntAtOffset) {
306          LocationOperand loc = null;
307          if (meth.getParameterTypes().length == 4) {
308            loc = mapToMetadata(bc2ir.popInt());
309          }
310          Operand val = bc2ir.popInt();
311          Operand offset = bc2ir.popAddress();
312          Operand object = bc2ir.popRef();
313          bc2ir.appendInstruction(Store.create(INT_STORE, val, object, offset, loc));
314        } else if (methodName == MagicNames.getFloatAtOffset) {
315          Operand offset = bc2ir.popAddress();
316          Operand object = bc2ir.popRef();
317          RegisterOperand val = gc.temps.makeTempFloat();
318          bc2ir.appendInstruction(Load.create(FLOAT_LOAD, val, object, offset, null));
319          bc2ir.push(val.copyD2U());
320        } else if (methodName == MagicNames.setFloatAtOffset) {
321          LocationOperand loc = null;
322          if (meth.getParameterTypes().length == 4) {
323            loc = mapToMetadata(bc2ir.popInt());
324          }
325          Operand val = bc2ir.popFloat();
326          Operand offset = bc2ir.popAddress();
327          Operand object = bc2ir.popRef();
328          bc2ir.appendInstruction(Store.create(FLOAT_STORE, val, object, offset, loc));
329        } else if (methodName == MagicNames.getWordAtOffset) {
330          LocationOperand loc = null;
331          if (meth.getParameterTypes().length == 3) {
332            loc = mapToMetadata(bc2ir.popInt());
333          }
334          Operand offset = bc2ir.popAddress();
335          Operand object = bc2ir.popRef();
336          RegisterOperand val = gc.temps.makeTemp(TypeReference.Word);
337          bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
338          bc2ir.push(val.copyD2U());
339        } else if (methodName == MagicNames.getAddressAtOffset) {
340          LocationOperand loc = null;
341          if (meth.getParameterTypes().length == 3) {
342            loc = mapToMetadata(bc2ir.popInt());
343          }
344          Operand offset = bc2ir.popAddress();
345          Operand object = bc2ir.popRef();
346          RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
347          bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
348          bc2ir.push(val.copyD2U());
349        } else if (methodName == MagicNames.getExtentAtOffset) {
350          LocationOperand loc = null;
351          if (meth.getParameterTypes().length == 3) {
352            loc = mapToMetadata(bc2ir.popInt());
353          }
354          Operand offset = bc2ir.popAddress();
355          Operand object = bc2ir.popRef();
356          RegisterOperand val = gc.temps.makeTemp(TypeReference.Extent);
357          bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
358          bc2ir.push(val.copyD2U());
359        } else if (methodName == MagicNames.getOffsetAtOffset) {
360          LocationOperand loc = null;
361          if (meth.getParameterTypes().length == 3) {
362            loc = mapToMetadata(bc2ir.popInt());
363          }
364          Operand offset = bc2ir.popAddress();
365          Operand object = bc2ir.popRef();
366          RegisterOperand val = gc.temps.makeTemp(TypeReference.Offset);
367          bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
368          bc2ir.push(val.copyD2U());
369        } else if (methodName == MagicNames.setWordAtOffset ||
370            methodName == MagicNames.setAddressAtOffset ||
371            methodName == MagicNames.setOffsetAtOffset ||
372            methodName == MagicNames.setExtentAtOffset) {
373          LocationOperand loc = null;
374          if (meth.getParameterTypes().length == 4) {
375            loc = mapToMetadata(bc2ir.popInt());
376          }
377          Operand val = bc2ir.popRef();
378          Operand offset = bc2ir.popAddress();
379          Operand object = bc2ir.popRef();
380          bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc));
381        } else if (methodName == MagicNames.getLongAtOffset) {
382          Operand offset = bc2ir.popAddress();
383          Operand object = bc2ir.popRef();
384          RegisterOperand val = gc.temps.makeTempLong();
385          bc2ir.appendInstruction(Load.create(LONG_LOAD, val, object, offset, null));
386          bc2ir.pushDual(val.copyD2U());
387        } else if (methodName == MagicNames.setLongAtOffset) {
388          LocationOperand loc = null;
389          if (meth.getParameterTypes().length == 4) {
390            loc = mapToMetadata(bc2ir.popInt());
391          }
392          Operand val = bc2ir.popLong();
393          Operand offset = bc2ir.popAddress();
394          Operand object = bc2ir.popRef();
395          bc2ir.appendInstruction(Store.create(LONG_STORE, val, object, offset, loc));
396        } else if (methodName == MagicNames.getDoubleAtOffset) {
397          Operand offset = bc2ir.popAddress();
398          Operand object = bc2ir.popRef();
399          RegisterOperand val = gc.temps.makeTempDouble();
400          bc2ir.appendInstruction(Load.create(DOUBLE_LOAD, val, object, offset, null));
401          bc2ir.pushDual(val.copyD2U());
402        } else if (methodName == MagicNames.setDoubleAtOffset) {
403          LocationOperand loc = null;
404          if (meth.getParameterTypes().length == 4) {
405            loc = mapToMetadata(bc2ir.popInt());
406          }
407          Operand val = bc2ir.popDouble();
408          Operand offset = bc2ir.popAddress();
409          Operand object = bc2ir.popRef();
410          bc2ir.appendInstruction(Store.create(DOUBLE_STORE, val, object, offset, loc));
411        } else if (methodName == MagicNames.getObjectAtOffset) {
412          LocationOperand loc = null;
413          if (meth.getParameterTypes().length == 3) {
414            loc = mapToMetadata(bc2ir.popInt());
415          }
416          Operand offset = bc2ir.popAddress();
417          Operand object = bc2ir.popRef();
418          RegisterOperand val = gc.temps.makeTemp(TypeReference.JavaLangObject);
419          bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
420          bc2ir.push(val.copyD2U());
421        } else if (methodName == MagicNames.getTIBAtOffset) {
422          Operand offset = bc2ir.popAddress();
423          Operand object = bc2ir.popRef();
424          RegisterOperand val = gc.temps.makeTemp(TypeReference.TIB);
425          bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, null));
426          bc2ir.push(val.copyD2U());
427        } else if (methodName == MagicNames.setObjectAtOffset) {
428          LocationOperand loc = null;
429          if (meth.getParameterTypes().length == 4) {
430            loc = mapToMetadata(bc2ir.popInt());
431          }
432          Operand val = bc2ir.popRef();
433          Operand offset = bc2ir.popAddress();
434          Operand object = bc2ir.popRef();
435          bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc));
436        } else if (methodName == MagicNames.getByteAtOffset) {
437          Operand offset = bc2ir.popAddress();
438          Operand object = bc2ir.popRef();
439          RegisterOperand val = gc.temps.makeTemp(TypeReference.Byte);
440          bc2ir.appendInstruction(Load.create(BYTE_LOAD, val, object, offset, null));
441          bc2ir.push(val.copyD2U());
442        } else if (methodName == MagicNames.getUnsignedByteAtOffset) {
443          Operand offset = bc2ir.popAddress();
444          Operand object = bc2ir.popRef();
445          RegisterOperand val = gc.temps.makeTemp(TypeReference.Byte);
446          bc2ir.appendInstruction(Load.create(UBYTE_LOAD, val, object, offset, null));
447          bc2ir.push(val.copyD2U());
448        } else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) {
449          LocationOperand loc = null;
450          if (meth.getParameterTypes().length == 4) {
451            loc = mapToMetadata(bc2ir.popInt());
452          }
453          Operand val = bc2ir.popInt();
454          Operand offset = bc2ir.popAddress();
455          Operand object = bc2ir.popRef();
456          bc2ir.appendInstruction(Store.create(BYTE_STORE, val, object, offset, loc));
457        } else if (methodName == MagicNames.getShortAtOffset) {
458          Operand offset = bc2ir.popAddress();
459          Operand object = bc2ir.popRef();
460          RegisterOperand val = gc.temps.makeTemp(TypeReference.Char);
461          bc2ir.appendInstruction(Load.create(SHORT_LOAD, val, object, offset, null));
462          bc2ir.push(val.copyD2U());
463        } else if (methodName == MagicNames.getCharAtOffset) {
464          Operand offset = bc2ir.popAddress();
465          Operand object = bc2ir.popRef();
466          RegisterOperand val = gc.temps.makeTemp(TypeReference.Char);
467          bc2ir.appendInstruction(Load.create(USHORT_LOAD, val, object, offset, null));
468          bc2ir.push(val.copyD2U());
469        } else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) {
470          LocationOperand loc = null;
471          if (meth.getParameterTypes().length == 4) {
472            loc = mapToMetadata(bc2ir.popInt());
473          }
474          Operand val = bc2ir.popInt();
475          Operand offset = bc2ir.popAddress();
476          Operand object = bc2ir.popRef();
477          bc2ir.appendInstruction(Store.create(SHORT_STORE, val, object, offset, loc));
478        } else if (methodName == MagicNames.getMemoryInt) {
479          Operand memAddr = bc2ir.popAddress();
480          RegisterOperand val = gc.temps.makeTempInt();
481          bc2ir.appendInstruction(Load.create(INT_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null));
482          bc2ir.push(val.copyD2U());
483        } else if (methodName == MagicNames.getMemoryWord) {
484          Operand memAddr = bc2ir.popAddress();
485          RegisterOperand val = gc.temps.makeTemp(TypeReference.Word);
486          bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null));
487          bc2ir.push(val.copyD2U());
488        } else if (methodName == MagicNames.getMemoryAddress) {
489          Operand memAddr = bc2ir.popAddress();
490          RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
491          bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null));
492          bc2ir.push(val.copyD2U());
493        } else if (methodName == MagicNames.setMemoryInt) {
494          Operand val = bc2ir.popInt();
495          Operand memAddr = bc2ir.popAddress();
496          bc2ir.appendInstruction(Store.create(INT_STORE,
497                                               val,
498                                               memAddr,
499                                               new AddressConstantOperand(Offset.zero()),
500                                               null));
501        } else if (methodName == MagicNames.setMemoryWord) {
502          Operand val = bc2ir.popRef();
503          Operand memAddr = bc2ir.popAddress();
504          bc2ir.appendInstruction(Store.create(REF_STORE,
505                                               val,
506                                               memAddr,
507                                               new AddressConstantOperand(Offset.zero()),
508                                               null));
509        } else if (meth.isSysCall()) {
510          // All methods of SysCall have the following signature:
511          // callNAME(Address functionAddress, <var args to pass via native calling convention>)
512          // With POWEROPEN_ABI, functionAddress points to the function descriptor
513          TypeReference[] args = meth.getParameterTypes();
514          Instruction call = Call.create(SYSCALL, null, null, null, null, args.length - 1);
515          for (int i = args.length - 1; i >= 1; i--) {
516            Call.setParam(call, i - 1, bc2ir.pop(args[i]));
517          }
518          Operand functionAddress = bc2ir.pop(args[0]);
519          Call.setAddress(call, functionAddress);
520          if (!returnType.isVoidType()) {
521            RegisterOperand op0 = gc.temps.makeTemp(returnType);
522            Call.setResult(call, op0);
523            bc2ir.push(op0.copyD2U(), returnType);
524          }
525          Call.setMethod(call, MethodOperand.STATIC(meth, meth.peekResolvedMethod()));
526          bc2ir.appendInstruction(call);
527        } else if (meth.isSpecializedInvoke()) {
528          // The callsite looks like              RETURN = INVOKE (ID, OBJECT, P0, P1 .. PN)
529          // And the actual method will look like RETURN = INVOKE     (OBJECT, P0, P1 .. PN)
530    
531          // Create the call instruction
532          Instruction call = Call.create(CALL, null, null, null, null, types.length - 1);
533    
534          // Plumb all of the normal parameters into the call
535          for (int i = types.length - 1; i >= 2; i--) {
536            Call.setParam(call, i - 1, bc2ir.pop(types[i]));
537          }
538          // The object being specialized
539          Operand objectOperand = bc2ir.pop(types[1]);
540          Call.setParam(call, 0, objectOperand);
541          Operand guard = BC2IR.getGuard(objectOperand);
542          if (guard == null) {
543            // it's magic, so assume that it's OK....
544            guard = new TrueGuardOperand();
545          }
546          Call.setGuard(call, guard);
547    
548          // Load the tib of this object
549          RegisterOperand tibObject = gc.temps.makeTemp(TypeReference.TIB);
550          bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibObject, objectOperand.copy(), guard.copy()));
551    
552          // The index of the specialized method
553          Operand methodId = bc2ir.popInt();
554    
555          // Add the base offset for specialized methods and convert from index to address
556          RegisterOperand tibOffset = gc.temps.makeTemp(TypeReference.Int);
557          bc2ir.appendInstruction(Binary.create(INT_ADD, tibOffset, methodId, new IntConstantOperand(TIB_FIRST_SPECIALIZED_METHOD_INDEX)));
558          bc2ir.appendInstruction(Binary.create(INT_SHL, tibOffset.copyRO(), tibOffset.copyD2U(), new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
559    
560          // Load the code address from the TIB
561          RegisterOperand codeAddress = gc.temps.makeTemp(TypeReference.Address);
562          bc2ir.appendInstruction(Load.create(REF_LOAD, codeAddress, tibObject.copyD2U(), tibOffset.copyD2U(), null));
563    
564          Call.setAddress(call, codeAddress.copyD2U());
565          if (!returnType.isVoidType()) {
566            RegisterOperand op0 = gc.temps.makeTemp(returnType);
567            Call.setResult(call, op0);
568            bc2ir.push(op0.copyD2U(), returnType);
569          }
570          bc2ir.appendInstruction(call);
571        } else if (methodName == MagicNames.objectAsType) {
572          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Type);
573          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
574          bc2ir.push(reg.copyD2U());
575        } else if (methodName == MagicNames.objectAsThread) {
576          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Thread);
577          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
578          bc2ir.push(reg.copyD2U());
579        } else if (methodName == MagicNames.objectAsAddress) {
580          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Address);
581          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
582          bc2ir.push(reg.copyD2U());
583        } else if (methodName == MagicNames.addressAsObject) {
584          RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
585          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
586          bc2ir.push(reg.copyD2U());
587        } else if (methodName == MagicNames.addressAsTIB) {
588          RegisterOperand reg = gc.temps.makeTemp(TypeReference.TIB);
589          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
590          bc2ir.push(reg.copyD2U());
591        } else if (methodName == MagicNames.addressAsByteArray) {
592          RegisterOperand reg = gc.temps.makeTemp(TypeReference.ByteArray);
593          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
594          bc2ir.push(reg.copyD2U());
595        } else if (methodName == MagicNames.objectAsShortArray) {
596          RegisterOperand reg = gc.temps.makeTemp(TypeReference.ShortArray);
597          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
598          bc2ir.push(reg.copyD2U());
599        } else if (methodName == MagicNames.objectAsIntArray) {
600          RegisterOperand reg = gc.temps.makeTemp(TypeReference.IntArray);
601          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
602          bc2ir.push(reg.copyD2U());
603        } else if (methodName == MagicNames.floatAsIntBits) {
604          Operand val = bc2ir.popFloat();
605          RegisterOperand op0 = gc.temps.makeTempInt();
606          bc2ir.appendInstruction(Unary.create(FLOAT_AS_INT_BITS, op0, val));
607          bc2ir.push(op0.copyD2U());
608        } else if (methodName == MagicNames.intBitsAsFloat) {
609          Operand val = bc2ir.popInt();
610          RegisterOperand op0 = gc.temps.makeTempFloat();
611          bc2ir.appendInstruction(Unary.create(INT_BITS_AS_FLOAT, op0, val));
612          bc2ir.push(op0.copyD2U());
613        } else if (methodName == MagicNames.doubleAsLongBits) {
614          Operand val = bc2ir.popDouble();
615          RegisterOperand op0 = gc.temps.makeTempLong();
616          bc2ir.appendInstruction(Unary.create(DOUBLE_AS_LONG_BITS, op0, val));
617          bc2ir.pushDual(op0.copyD2U());
618        } else if (methodName == MagicNames.longBitsAsDouble) {
619          Operand val = bc2ir.popLong();
620          RegisterOperand op0 = gc.temps.makeTempDouble();
621          bc2ir.appendInstruction(Unary.create(LONG_BITS_AS_DOUBLE, op0, val));
622          bc2ir.pushDual(op0.copyD2U());
623        } else if (methodName == MagicNames.sqrt) {
624          TypeReference[] args = meth.getParameterTypes();
625          if (args[0] == TypeReference.Float) {
626            Operand val = bc2ir.popFloat();
627            RegisterOperand op0 = gc.temps.makeTempFloat();
628            bc2ir.appendInstruction(Unary.create(FLOAT_SQRT, op0, val));
629            bc2ir.push(op0.copyD2U());
630          } else if (args[0] == TypeReference.Double) {
631            Operand val = bc2ir.popDouble();
632            RegisterOperand op0 = gc.temps.makeTempDouble();
633            bc2ir.appendInstruction(Unary.create(DOUBLE_SQRT, op0, val));
634            bc2ir.pushDual(op0.copyD2U());
635          } else {
636            if (VM.VerifyAssertions)
637              VM._assert(VM.NOT_REACHED,"SQRT only handles Double or Float operands");
638          }
639        } else if (methodName == MagicNames.getObjectType) {
640          Operand val = bc2ir.popRef();
641          if(val.isObjectConstant()) {
642            bc2ir.push(new ObjectConstantOperand(val.getType().peekType(), Offset.zero()));
643          } else {
644            Operand guard = BC2IR.getGuard(val);
645            if (guard == null) {
646              // it's magic, so assume that it's OK....
647              guard = new TrueGuardOperand();
648            }
649            RegisterOperand tibPtr = gc.temps.makeTemp(TypeReference.TIB);
650            bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibPtr, val, guard));
651            RegisterOperand op0;
652            TypeReference argType = val.getType();
653            if (argType.isArrayType()) {
654              op0 = gc.temps.makeTemp(TypeReference.RVMArray);
655            } else {
656              if (argType == TypeReference.JavaLangObject ||
657                  argType == TypeReference.JavaLangCloneable ||
658                  argType == TypeReference.JavaIoSerializable) {
659                // could be an array or a class, so make op0 be a RVMType
660                op0 = gc.temps.makeTemp(TypeReference.Type);
661              } else {
662                op0 = gc.temps.makeTemp(TypeReference.Class);
663              }
664            }
665            bc2ir.markGuardlessNonNull(op0);
666            bc2ir.appendInstruction(Unary.create(GET_TYPE_FROM_TIB, op0, tibPtr.copyD2U()));
667            bc2ir.push(op0.copyD2U());
668          }
669        } else if (methodName == MagicNames.getArrayLength) {
670          Operand val = bc2ir.popRef();
671          RegisterOperand op0 = gc.temps.makeTempInt();
672          bc2ir.appendInstruction(GuardedUnary.create(ARRAYLENGTH, op0, val, new TrueGuardOperand()));
673          bc2ir.push(op0.copyD2U());
674        } else if (methodName == MagicNames.invokeClassInitializer) {
675          Instruction s = Call.create0(CALL, null, bc2ir.popRef(), null);
676          bc2ir.appendInstruction(s);
677        } else if ((methodName == MagicNames.invokeMethodReturningObject) ||
678                   (methodName == MagicNames.invokeMethodReturningVoid) ||
679                   (methodName == MagicNames.invokeMethodReturningLong) ||
680                   (methodName == MagicNames.invokeMethodReturningDouble) ||
681                   (methodName == MagicNames.invokeMethodReturningFloat) ||
682                   (methodName == MagicNames.invokeMethodReturningInt)) {
683          Operand spills = bc2ir.popRef();
684          Operand fprmeta = bc2ir.popRef();
685          Operand fprs = bc2ir.popRef();
686          Operand gprs = bc2ir.popRef();
687          Operand code = bc2ir.popRef();
688          RegisterOperand res = null;
689          if (methodName == MagicNames.invokeMethodReturningObject) {
690            res = gc.temps.makeTemp(TypeReference.JavaLangObject);
691            bc2ir.push(res.copyD2U());
692          } else if (methodName == MagicNames.invokeMethodReturningLong) {
693            res = gc.temps.makeTemp(TypeReference.Long);
694            bc2ir.push(res.copyD2U(), TypeReference.Long);
695          } else if (methodName == MagicNames.invokeMethodReturningDouble) {
696            res = gc.temps.makeTempDouble();
697            bc2ir.push(res.copyD2U(), TypeReference.Double);
698          } else if (methodName == MagicNames.invokeMethodReturningFloat) {
699            res = gc.temps.makeTempFloat();
700            bc2ir.push(res.copyD2U(), TypeReference.Float);
701          } else if (methodName == MagicNames.invokeMethodReturningInt) {
702            res = gc.temps.makeTempInt();
703            bc2ir.push(res.copyD2U());
704          }
705          RVMField target = ArchEntrypoints.reflectiveMethodInvokerInstructionsField;
706          MethodOperand met = MethodOperand.STATIC(target);
707          Instruction s =
708              Call.create5(CALL, res, new AddressConstantOperand(target.getOffset()), met, code, gprs, fprs, fprmeta, spills);
709          bc2ir.appendInstruction(s);
710        } else if (methodName == MagicNames.saveThreadState) {
711          Operand p1 = bc2ir.popRef();
712          RVMField target = ArchEntrypoints.saveThreadStateInstructionsField;
713          MethodOperand mo = MethodOperand.STATIC(target);
714          bc2ir.appendInstruction(Call.create1(CALL, null, new AddressConstantOperand(target.getOffset()), mo, p1));
715        } else if (methodName == MagicNames.threadSwitch) {
716          Operand p2 = bc2ir.popRef();
717          Operand p1 = bc2ir.popRef();
718          RVMField target = ArchEntrypoints.threadSwitchInstructionsField;
719          MethodOperand mo = MethodOperand.STATIC(target);
720          bc2ir.appendInstruction(Call.create2(CALL, null, new AddressConstantOperand(target.getOffset()), mo, p1, p2));
721        } else if (methodName == MagicNames.restoreHardwareExceptionState) {
722          RVMField target = ArchEntrypoints.restoreHardwareExceptionStateInstructionsField;
723          MethodOperand mo = MethodOperand.STATIC(target);
724          bc2ir.appendInstruction(Call.create1(CALL,
725                                               null,
726                                               new AddressConstantOperand(target.getOffset()),
727                                               mo,
728                                               bc2ir.popRef()));
729        } else if (methodName == MagicNames.prepareInt) {
730          Operand offset = bc2ir.popAddress();
731          Operand base = bc2ir.popRef();
732          RegisterOperand val = gc.temps.makeTempInt();
733          bc2ir.appendInstruction(Prepare.create(PREPARE_INT, val, base, offset, null));
734          bc2ir.push(val.copyD2U());
735        } else if (methodName == MagicNames.prepareLong) {
736          Operand offset = bc2ir.popAddress();
737          Operand base = bc2ir.popRef();
738          RegisterOperand val = gc.temps.makeTempLong();
739          bc2ir.appendInstruction(Prepare.create(PREPARE_LONG, val, base, offset, null));
740          bc2ir.pushDual(val.copyD2U());
741        } else if (methodName == MagicNames.prepareObject) {
742          Operand offset = bc2ir.popAddress();
743          Operand base = bc2ir.popRef();
744          RegisterOperand val = gc.temps.makeTemp(TypeReference.JavaLangObject);
745          bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
746          bc2ir.push(val.copyD2U());
747        } else if (methodName == MagicNames.prepareAddress) {
748          Operand offset = bc2ir.popAddress();
749          Operand base = bc2ir.popRef();
750          RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
751          bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
752          bc2ir.push(val.copyD2U());
753        } else if (methodName == MagicNames.prepareWord) {
754          Operand offset = bc2ir.popAddress();
755          Operand base = bc2ir.popRef();
756          RegisterOperand val = gc.temps.makeTemp(TypeReference.Word);
757          bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
758          bc2ir.push(val.copyD2U());
759        } else if (methodName == MagicNames.attemptInt) {
760          Operand newVal = bc2ir.popInt();
761          Operand oldVal = bc2ir.popInt();
762          Operand offset = bc2ir.popAddress();
763          Operand base = bc2ir.popRef();
764          RegisterOperand test = gc.temps.makeTempBoolean();
765          bc2ir.appendInstruction(Attempt.create(ATTEMPT_INT, test, base, offset, oldVal, newVal, null));
766          bc2ir.push(test.copyD2U());
767        } else if (methodName == MagicNames.attemptLong) {
768          Operand newVal = bc2ir.popLong();
769          Operand oldVal = bc2ir.popLong();
770          Operand offset = bc2ir.popAddress();
771          Operand base = bc2ir.popRef();
772          RegisterOperand test = gc.temps.makeTempBoolean();
773          bc2ir.appendInstruction(Attempt.create(ATTEMPT_LONG, test, base, offset, oldVal, newVal, null));
774          bc2ir.push(test.copyD2U());
775        } else if (methodName == MagicNames.attemptObject) {
776          Operand newVal = bc2ir.popRef();
777          Operand oldVal = bc2ir.popRef();
778          Operand offset = bc2ir.popAddress();
779          Operand base = bc2ir.popRef();
780          RegisterOperand test = gc.temps.makeTempBoolean();
781          bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
782          bc2ir.push(test.copyD2U());
783        } else if (methodName == MagicNames.attemptAddress) {
784          Operand newVal = bc2ir.popAddress();
785          Operand oldVal = bc2ir.popAddress();
786          Operand offset = bc2ir.popAddress();
787          Operand base = bc2ir.popRef();
788          RegisterOperand test = gc.temps.makeTempBoolean();
789          bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
790          bc2ir.push(test.copyD2U());
791        } else if (methodName == MagicNames.attemptWord) {
792          Operand newVal = bc2ir.pop();
793          Operand oldVal = bc2ir.pop();
794          Operand offset = bc2ir.popAddress();
795          Operand base = bc2ir.popRef();
796          RegisterOperand test = gc.temps.makeTempBoolean();
797          bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
798          bc2ir.push(test.copyD2U());
799        } else if (methodName == MagicNames.fence) {
800          bc2ir.appendInstruction(Empty.create(FENCE));
801        } else if (methodName == MagicNames.readCeiling) {
802          bc2ir.appendInstruction(Empty.create(READ_CEILING));
803        } else if (methodName == MagicNames.writeFloor) {
804          bc2ir.appendInstruction(Empty.create(WRITE_FLOOR));
805        } else if (generatePolymorphicMagic(bc2ir, gc, meth, methodName)) {
806          return true;
807        } else if (methodName == MagicNames.getTimeBase) {
808          RegisterOperand op0 = gc.temps.makeTempLong();
809          bc2ir.appendInstruction(Nullary.create(GET_TIME_BASE, op0));
810          bc2ir.pushDual(op0.copyD2U());
811        } else if (methodName == MagicNames.getInlineDepth) {
812          bc2ir.push(new IntConstantOperand(gc.inlineSequence.getInlineDepth()));
813        } else if (methodName == MagicNames.isConstantParameter) {
814          Operand requestedOperand = bc2ir.pop();
815          if (!(requestedOperand instanceof IntConstantOperand)) {
816            throw new OptimizingCompilerException("Must supply constant to Magic.isConstantParameter");
817          }
818          int requested = ((IntConstantOperand)(requestedOperand)).value;
819          boolean isConstant = gc.arguments[requested].isConstant();
820          bc2ir.push(new IntConstantOperand(isConstant ? 1 : 0));
821        } else {
822          // Wasn't machine-independent, so try the machine-dependent magics next.
823          return GenerateMachineSpecificMagic.generateMagic(bc2ir, gc, meth);
824        }
825        return true;
826      } // generateMagic
827    
828      // Generate magic where the untype operational semantics is identified by name.
829      // The operands' types are determined from the method signature.
830      //
831      static boolean generatePolymorphicMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth,
832                                              Atom methodName) {
833        TypeReference resultType = meth.getReturnType();
834        if (methodName == MagicNames.wordFromInt || methodName == MagicNames.wordFromIntSignExtend) {
835          RegisterOperand reg = gc.temps.makeTemp(resultType);
836          bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, reg, bc2ir.popInt()));
837          bc2ir.push(reg.copyD2U());
838        } else if (methodName == MagicNames.wordFromIntZeroExtend) {
839          RegisterOperand reg = gc.temps.makeTemp(resultType);
840          bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, reg, bc2ir.popInt()));
841          bc2ir.push(reg.copyD2U());
842        } else if (methodName == MagicNames.wordFromLong) {
843          RegisterOperand reg = gc.temps.makeTemp(resultType);
844          bc2ir.appendInstruction(Unary.create(LONG_2ADDR, reg, bc2ir.popLong()));
845          bc2ir.push(reg.copyD2U());
846        } else if (methodName == MagicNames.wordToInt) {
847          RegisterOperand reg = gc.temps.makeTempInt();
848          bc2ir.appendInstruction(Unary.create(ADDR_2INT, reg, bc2ir.popAddress()));
849          bc2ir.push(reg.copyD2U());
850        } else if (methodName == MagicNames.wordToLong) {
851          RegisterOperand lreg = gc.temps.makeTempLong();
852          bc2ir.appendInstruction(Unary.create(ADDR_2LONG, lreg, bc2ir.popAddress()));
853          bc2ir.pushDual(lreg.copyD2U());
854        } else if (methodName == MagicNames.wordToWord) {
855          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Word);
856          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
857          bc2ir.push(reg.copyD2U());
858        } else if (methodName == MagicNames.wordToAddress) {
859          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Address);
860          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
861          bc2ir.push(reg.copyD2U());
862        } else if (methodName == MagicNames.wordToObject) {
863          RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
864          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
865          bc2ir.push(reg.copyD2U());
866        } else if (methodName == MagicNames.wordToObjectReference || methodName == MagicNames.wordFromObject) {
867          RegisterOperand reg = gc.temps.makeTemp(TypeReference.ObjectReference);
868          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
869          bc2ir.push(reg.copyD2U());
870        } else if (methodName == MagicNames.wordToOffset) {
871          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Offset);
872          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
873          bc2ir.push(reg.copyD2U());
874        } else if (methodName == MagicNames.wordToExtent) {
875          RegisterOperand reg = gc.temps.makeTemp(TypeReference.Extent);
876          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
877          bc2ir.push(reg.copyD2U());
878        } else if (methodName == MagicNames.codeArrayAsObject) {
879          RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
880          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.pop(TypeReference.CodeArray)));
881          bc2ir.push(reg.copyD2U());
882        } else if (methodName == MagicNames.tibAsObject) {
883          RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
884          bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.pop(TypeReference.TIB)));
885          bc2ir.push(reg.copyD2U());
886        } else if (methodName == MagicNames.wordPlus) {
887          Operand o2 = bc2ir.pop();
888          Operand o1 = bc2ir.pop();
889          RegisterOperand op0 = gc.temps.makeTemp(resultType);
890          if (VM.BuildFor64Addr && o2.isInt()) {
891            RegisterOperand op1 = gc.temps.makeTemp(resultType);
892            bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, op1, o2));
893            bc2ir.appendInstruction(Binary.create(REF_ADD, op0, o1, op1.copyD2U()));
894          } else {
895            bc2ir.appendInstruction(Binary.create(REF_ADD, op0, o1, o2));
896          }
897          bc2ir.push(op0.copyD2U());
898        } else if (methodName == MagicNames.wordMinus) {
899          Operand o2 = bc2ir.pop();
900          Operand o1 = bc2ir.pop();
901          RegisterOperand op0 = gc.temps.makeTemp(resultType);
902          if (VM.BuildFor64Addr && o2.isInt()) {
903            RegisterOperand op1 = gc.temps.makeTemp(resultType);
904            bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, op1, o2));
905            bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, op1));
906          } else {
907            bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, o2));
908          }
909          bc2ir.push(op0.copyD2U());
910        } else if (methodName == MagicNames.wordDiff) {
911          Operand o2 = bc2ir.pop();
912          Operand o1 = bc2ir.pop();
913          RegisterOperand op0 = gc.temps.makeTemp(resultType);
914          bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, o2));
915          bc2ir.push(op0.copyD2U());
916        } else if (methodName == MagicNames.wordAnd) {
917          Operand o2 = bc2ir.pop();
918          Operand o1 = bc2ir.pop();
919          RegisterOperand op0 = gc.temps.makeTemp(resultType);
920          bc2ir.appendInstruction(Binary.create(REF_AND, op0, o1, o2));
921          bc2ir.push(op0.copyD2U());
922        } else if (methodName == MagicNames.wordOr) {
923          Operand o2 = bc2ir.pop();
924          Operand o1 = bc2ir.pop();
925          RegisterOperand op0 = gc.temps.makeTemp(resultType);
926          bc2ir.appendInstruction(Binary.create(REF_OR, op0, o1, o2));
927          bc2ir.push(op0.copyD2U());
928        } else if (methodName == MagicNames.wordXor) {
929          Operand o2 = bc2ir.pop();
930          Operand o1 = bc2ir.pop();
931          RegisterOperand op0 = gc.temps.makeTemp(resultType);
932          bc2ir.appendInstruction(Binary.create(REF_XOR, op0, o1, o2));
933          bc2ir.push(op0.copyD2U());
934        } else if (methodName == MagicNames.wordNot) {
935          Operand o1 = bc2ir.pop();
936          RegisterOperand op0 = gc.temps.makeTemp(resultType);
937          bc2ir.appendInstruction(Unary.create(REF_NOT, op0, o1));
938          bc2ir.push(op0.copyD2U());
939        } else if (methodName == MagicNames.wordZero || methodName == MagicNames.wordNull) {
940          RegisterOperand op0 = gc.temps.makeTemp(resultType);
941          bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero())));
942          bc2ir.push(op0.copyD2U());
943        } else if (methodName == MagicNames.wordOne) {
944          RegisterOperand op0 = gc.temps.makeTemp(resultType);
945          bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.fromIntZeroExtend(1))));
946          bc2ir.push(op0.copyD2U());
947        } else if (methodName == MagicNames.wordMax) {
948          RegisterOperand op0 = gc.temps.makeTemp(resultType);
949          bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.max())));
950          bc2ir.push(op0.copyD2U());
951        } else if (methodName == MagicNames.wordIsNull) {
952          RegisterOperand op0 = gc.temps.makeTemp(resultType);
953          bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero())));
954          ConditionOperand cond = ConditionOperand.EQUAL();
955          cmpHelper(bc2ir, gc, cond, op0.copyRO());
956        } else if (methodName == MagicNames.wordIsZero) {
957          RegisterOperand op0 = gc.temps.makeTemp(resultType);
958          bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero())));
959          ConditionOperand cond = ConditionOperand.EQUAL();
960          cmpHelper(bc2ir, gc, cond, op0.copyRO());
961        } else if (methodName == MagicNames.wordIsMax) {
962          RegisterOperand op0 = gc.temps.makeTemp(resultType);
963          bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.max())));
964          ConditionOperand cond = ConditionOperand.EQUAL();
965          cmpHelper(bc2ir, gc, cond, op0.copyRO());
966        } else if (methodName == MagicNames.wordEQ) {
967          ConditionOperand cond = ConditionOperand.EQUAL();
968          cmpHelper(bc2ir, gc, cond, null);
969        } else if (methodName == MagicNames.wordNE) {
970          ConditionOperand cond = ConditionOperand.NOT_EQUAL();
971          cmpHelper(bc2ir, gc, cond, null);
972        } else if (methodName == MagicNames.wordLT) {
973          ConditionOperand cond = ConditionOperand.LOWER();
974          cmpHelper(bc2ir, gc, cond, null);
975        } else if (methodName == MagicNames.wordLE) {
976          ConditionOperand cond = ConditionOperand.LOWER_EQUAL();
977          cmpHelper(bc2ir, gc, cond, null);
978        } else if (methodName == MagicNames.wordGT) {
979          ConditionOperand cond = ConditionOperand.HIGHER();
980          cmpHelper(bc2ir, gc, cond, null);
981        } else if (methodName == MagicNames.wordGE) {
982          ConditionOperand cond = ConditionOperand.HIGHER_EQUAL();
983          cmpHelper(bc2ir, gc, cond, null);
984        } else if (methodName == MagicNames.wordsLT) {
985          ConditionOperand cond = ConditionOperand.LESS();
986          cmpHelper(bc2ir, gc, cond, null);
987        } else if (methodName == MagicNames.wordsLE) {
988          ConditionOperand cond = ConditionOperand.LESS_EQUAL();
989          cmpHelper(bc2ir, gc, cond, null);
990        } else if (methodName == MagicNames.wordsGT) {
991          ConditionOperand cond = ConditionOperand.GREATER();
992          cmpHelper(bc2ir, gc, cond, null);
993        } else if (methodName == MagicNames.wordsGE) {
994          ConditionOperand cond = ConditionOperand.GREATER_EQUAL();
995          cmpHelper(bc2ir, gc, cond, null);
996        } else if (methodName == MagicNames.wordLsh) {
997          Operand op2 = bc2ir.popInt();
998          Operand op1 = bc2ir.popAddress();
999          RegisterOperand res = gc.temps.makeTemp(resultType);
1000          bc2ir.appendInstruction(Binary.create(REF_SHL, res, op1, op2));
1001          bc2ir.push(res.copyD2U());
1002        } else if (methodName == MagicNames.wordRshl) {
1003          Operand op2 = bc2ir.popInt();
1004          Operand op1 = bc2ir.popAddress();
1005          RegisterOperand res = gc.temps.makeTemp(resultType);
1006          bc2ir.appendInstruction(Binary.create(REF_USHR, res, op1, op2));
1007          bc2ir.push(res.copyD2U());
1008        } else if (methodName == MagicNames.wordRsha) {
1009          Operand op2 = bc2ir.popInt();
1010          Operand op1 = bc2ir.popAddress();
1011          RegisterOperand res = gc.temps.makeTemp(resultType);
1012          bc2ir.appendInstruction(Binary.create(REF_SHR, res, op1, op2));
1013          bc2ir.push(res.copyD2U());
1014        } else {
1015          return false;
1016        }
1017        return true;
1018      }
1019    
1020      private static void cmpHelper(BC2IR bc2ir, GenerationContext gc, ConditionOperand cond,
1021                                    Operand given_o2) {
1022        Operand o2 = given_o2 == null ? bc2ir.pop() : given_o2;
1023        Operand o1 = bc2ir.pop();
1024        RegisterOperand res = gc.temps.makeTempInt();
1025        bc2ir.appendInstruction(BooleanCmp.create(BOOLEAN_CMP_ADDR,
1026                                                  res.copyRO(),
1027                                                  o1,
1028                                                  o2,
1029                                                  cond,
1030                                                  new BranchProfileOperand()));
1031        bc2ir.push(res.copyD2U());
1032      }
1033    
1034      private static LocationOperand mapToMetadata(Operand metadata) {
1035        if (metadata instanceof IntConstantOperand) {
1036          int index = ((IntConstantOperand) metadata).value;
1037          if (index == 0) return null;
1038          MemberReference mr = MemberReference.getMemberRef(index);
1039          return new LocationOperand(mr.asFieldReference());
1040        }
1041        return null;
1042      }
1043    
1044      private static final int LOAD_OP = 1;
1045      private static final int PREPARE_OP = 2;
1046      private static final int STORE_OP = 3;
1047      private static final int ATTEMPT_OP = 4;
1048    
1049      private static Operator getOperator(TypeReference type, int operatorClass)
1050          throws MagicNotImplementedException {
1051        if (operatorClass == LOAD_OP) {
1052          if (type == TypeReference.Address) return REF_LOAD;
1053          if (type == TypeReference.ObjectReference) return REF_LOAD;
1054          if (type == TypeReference.Word) return REF_LOAD;
1055          if (type == TypeReference.Offset) return REF_LOAD;
1056          if (type == TypeReference.Extent) return REF_LOAD;
1057          if (type == TypeReference.Int) return INT_LOAD;
1058          if (type == TypeReference.Byte) return BYTE_LOAD;
1059          if (type == TypeReference.Short) return SHORT_LOAD;
1060          if (type == TypeReference.Char) return USHORT_LOAD;
1061          if (type == TypeReference.Float) return FLOAT_LOAD;
1062          if (type == TypeReference.Double) return DOUBLE_LOAD;
1063          if (type == TypeReference.Long) return LONG_LOAD;
1064        } else if (operatorClass == PREPARE_OP) {
1065          if (type == TypeReference.Address) return PREPARE_ADDR;
1066          if (type == TypeReference.ObjectReference) return PREPARE_ADDR;
1067          if (type == TypeReference.Word) return PREPARE_ADDR;
1068          if (type == TypeReference.Int) return PREPARE_INT;
1069          if (type == TypeReference.Long) return PREPARE_LONG;
1070        } else if (operatorClass == ATTEMPT_OP) {
1071          if (type == TypeReference.Address) return ATTEMPT_ADDR;
1072          if (type == TypeReference.ObjectReference) return ATTEMPT_ADDR;
1073          if (type == TypeReference.Word) return ATTEMPT_ADDR;
1074          if (type == TypeReference.Int) return ATTEMPT_INT;
1075          if (type == TypeReference.Long) return ATTEMPT_LONG;
1076        } else if (operatorClass == STORE_OP) {
1077          if (type == TypeReference.Address) return REF_STORE;
1078          if (type == TypeReference.ObjectReference) return REF_STORE;
1079          if (type == TypeReference.Word) return REF_STORE;
1080          if (type == TypeReference.Offset) return REF_STORE;
1081          if (type == TypeReference.Extent) return REF_STORE;
1082          if (type == TypeReference.Int) return INT_STORE;
1083          if (type == TypeReference.Byte || type == TypeReference.Boolean) return BYTE_STORE;
1084          if (type == TypeReference.Short) return SHORT_STORE;
1085          if (type == TypeReference.Char) return SHORT_STORE;
1086          if (type == TypeReference.Float) return FLOAT_STORE;
1087          if (type == TypeReference.Double) return DOUBLE_STORE;
1088          if (type == TypeReference.Long) return LONG_STORE;
1089        }
1090        String msg = " Unexpected call to getOperator";
1091        throw MagicNotImplementedException.UNEXPECTED(msg);
1092      }
1093    
1094      private static boolean isLoad(Atom methodName) {
1095        return isPrefix(MagicNames.loadPrefix, methodName.toByteArray());
1096      }
1097    
1098      private static boolean isPrepare(Atom methodName) {
1099        return isPrefix(MagicNames.preparePrefix, methodName.toByteArray());
1100      }
1101    
1102      /**
1103       * Is string <code>a</code> a prefix of string
1104       * <code>b</code>. String <code>b</code> is encoded as an ASCII byte
1105       * array.
1106       *
1107       * @param prefix  Prefix atom
1108       * @param b       String which may contain prefix, encoded as an ASCII
1109       * byte array.
1110       * @return <code>true</code> if <code>a</code> is a prefix of
1111       * <code>b</code>
1112       */
1113      @Interruptible
1114      private static boolean isPrefix(Atom prefix, byte[] b) {
1115        byte[] a = prefix.toByteArray();
1116        int aLen = a.length;
1117        if (aLen > b.length) {
1118          return false;
1119        }
1120        for (int i = 0; i < aLen; i++) {
1121          if (a[i] != b[i]) {
1122            return false;
1123          }
1124        }
1125        return true;
1126      }
1127    
1128    }