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.ia32;
014    
015    import org.jikesrvm.classloader.Atom;
016    import org.jikesrvm.classloader.RVMField;
017    import org.jikesrvm.classloader.MethodReference;
018    import org.jikesrvm.classloader.TypeReference;
019    import org.jikesrvm.compilers.opt.MagicNotImplementedException;
020    import org.jikesrvm.compilers.opt.bc2ir.BC2IR;
021    import org.jikesrvm.compilers.opt.bc2ir.GenerationContext;
022    import org.jikesrvm.compilers.opt.ir.Binary;
023    import org.jikesrvm.compilers.opt.ir.CacheOp;
024    import org.jikesrvm.compilers.opt.ir.Empty;
025    import org.jikesrvm.compilers.opt.ir.GetField;
026    import org.jikesrvm.compilers.opt.ir.Load;
027    import org.jikesrvm.compilers.opt.ir.Move;
028    import org.jikesrvm.compilers.opt.ir.Operators;
029    import org.jikesrvm.compilers.opt.ir.Store;
030    import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet;
031    import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand;
032    import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
033    import org.jikesrvm.compilers.opt.ir.operand.LocationOperand;
034    import org.jikesrvm.compilers.opt.ir.operand.Operand;
035    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
036    import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
037    import org.jikesrvm.ia32.StackframeLayoutConstants;
038    import org.jikesrvm.runtime.ArchEntrypoints;
039    import org.jikesrvm.runtime.Magic;
040    import org.jikesrvm.runtime.MagicNames;
041    
042    /**
043     * This class implements the machine-specific magics for the opt compiler.
044     *
045     * @see org.jikesrvm.compilers.opt.bc2ir.GenerateMagic for the machine-independent magics
046     */
047    public abstract class GenerateMachineSpecificMagic implements Operators, StackframeLayoutConstants {
048    
049      /**
050       * "Semantic inlining" of methods of the Magic class.
051       * Based on the methodName, generate a sequence of opt instructions
052       * that implement the magic, updating the stack as necessary
053       *
054       * @param bc2ir the bc2ir object generating the ir containing this magic
055       * @param gc == bc2ir.gc
056       * @param meth the RVMMethod that is the magic method
057       */
058      public static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth)
059          throws MagicNotImplementedException {
060    
061        Atom methodName = meth.getName();
062        PhysicalRegisterSet phys = gc.temps.getPhysicalRegisterSet();
063    
064        if (methodName == MagicNames.getESIAsThread) {
065          RegisterOperand rop = gc.temps.makeTROp();
066          bc2ir.markGuardlessNonNull(rop);
067          bc2ir.push(rop);
068        } else if (methodName == MagicNames.setESIAsThread) {
069          Operand val = bc2ir.popRef();
070          if (val instanceof RegisterOperand) {
071            bc2ir.appendInstruction(Move.create(REF_MOVE, gc.temps.makeTROp(), val));
072          } else {
073            String msg = " Unexpected operand Magic.setESIAsThread";
074            throw MagicNotImplementedException.UNEXPECTED(msg);
075          }
076        } else if (methodName == MagicNames.getFramePointer) {
077          gc.allocFrame = true;
078          RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
079          RVMField f = ArchEntrypoints.framePointerField;
080          RegisterOperand pr = new RegisterOperand(phys.getESI(), TypeReference.Int);
081          bc2ir.appendInstruction(GetField.create(GETFIELD,
082                                                  val,
083                                                  pr.copy(),
084                                                  new AddressConstantOperand(f.getOffset()),
085                                                  new LocationOperand(f),
086                                                  new TrueGuardOperand()));
087          bc2ir.push(val.copyD2U());
088        } else if (methodName == MagicNames.getJTOC || methodName == MagicNames.getTocPointer) {
089          TypeReference t = (methodName == MagicNames.getJTOC ? TypeReference.IntArray : TypeReference.Address);
090          RegisterOperand val = gc.temps.makeTemp(t);
091          AddressConstantOperand addr = new AddressConstantOperand(Magic.getTocPointer());
092          bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr));
093          bc2ir.push(val.copyD2U());
094        } else if (methodName == MagicNames.isync) {
095          // nothing required on Intel
096        } else if (methodName == MagicNames.sync) {
097          // nothing required on Intel
098        } else if (methodName == MagicNames.prefetch) {
099          bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress()));
100        } else if (methodName == MagicNames.pause) {
101          bc2ir.appendInstruction(Empty.create(PAUSE));
102        } else if (methodName == MagicNames.getCallerFramePointer) {
103          Operand fp = bc2ir.popAddress();
104          RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
105          bc2ir.appendInstruction(Load.create(REF_LOAD,
106                                              val,
107                                              fp,
108                                              new IntConstantOperand(STACKFRAME_FRAME_POINTER_OFFSET),
109                                              null));
110          bc2ir.push(val.copyD2U());
111        } else if (methodName == MagicNames.setCallerFramePointer) {
112          Operand val = bc2ir.popAddress();
113          Operand fp = bc2ir.popAddress();
114          bc2ir.appendInstruction(Store.create(REF_STORE,
115                                               val,
116                                               fp,
117                                               new IntConstantOperand(STACKFRAME_FRAME_POINTER_OFFSET),
118                                               null));
119        } else if (methodName == MagicNames.getCompiledMethodID) {
120          Operand fp = bc2ir.popAddress();
121          RegisterOperand val = gc.temps.makeTempInt();
122          bc2ir.appendInstruction(Load.create(INT_LOAD,
123                                              val,
124                                              fp,
125                                              new IntConstantOperand(STACKFRAME_METHOD_ID_OFFSET),
126                                              null));
127          bc2ir.push(val.copyD2U());
128        } else if (methodName == MagicNames.setCompiledMethodID) {
129          Operand val = bc2ir.popInt();
130          Operand fp = bc2ir.popAddress();
131          bc2ir.appendInstruction(Store.create(INT_STORE,
132                                               val,
133                                               fp,
134                                               new IntConstantOperand(STACKFRAME_METHOD_ID_OFFSET),
135                                               null));
136        } else if (methodName == MagicNames.getReturnAddressLocation) {
137          Operand fp = bc2ir.popAddress();
138          RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
139          bc2ir.appendInstruction(Binary.create(REF_ADD,
140                                                val,
141                                                fp,
142                                                new IntConstantOperand(STACKFRAME_RETURN_ADDRESS_OFFSET)));
143          bc2ir.push(val.copyD2U());
144        } else {
145          // Distinguish between magics that we know we don't implement
146          // (and never plan to implement) and those (usually new ones)
147          // that we want to be warned that we don't implement.
148          String msg = " Magic method not implemented: " + meth;
149          if (methodName == MagicNames.returnToNewStack) {
150            throw MagicNotImplementedException.EXPECTED(msg);
151          } else {
152            return false;
153            // throw MagicNotImplementedException.UNEXPECTED(msg);
154          }
155        }
156        return true;
157      }
158    }