Search in sources :

Example 1 with CodeArray

use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.

the class BootImageWriter method writeAddressMap.

/**
 * Write method address map for use with dbx debugger.
 *
 * @param fileName name of file to write the map to
 */
private static void writeAddressMap(String mapFileName) throws IOException {
    if (verbosity.isAtLeast(SUMMARY))
        say("writing ", mapFileName);
    // Restore previously unnecessary Statics data structures
    Statics.bootImageReportGeneration(staticsJunk);
    FileOutputStream fos = new FileOutputStream(mapFileName);
    BufferedOutputStream bos = new BufferedOutputStream(fos, 128);
    PrintStream out = new PrintStream(bos, false);
    out.println("#! /bin/bash");
    out.println("# This is a method address map, for use with the ``dbx'' debugger.");
    out.println("# To sort by \"code\" address, type \"bash <name-of-this-file>\".");
    out.println("# Bootimage data: " + Integer.toHexString(BOOT_IMAGE_DATA_START.toInt()) + "..." + Integer.toHexString(BOOT_IMAGE_DATA_START.toInt() + bootImage.getDataSize()));
    out.println("# Bootimage code: " + Integer.toHexString(BOOT_IMAGE_CODE_START.toInt()) + "..." + Integer.toHexString(BOOT_IMAGE_CODE_START.toInt() + bootImage.getCodeSize()));
    out.println("# Bootimage refs: " + Integer.toHexString(BOOT_IMAGE_RMAP_START.toInt()) + "..." + Integer.toHexString(BOOT_IMAGE_RMAP_START.toInt() + bootImage.getRMapSize()));
    out.println();
    out.println("(/bin/grep 'code     0x' | /bin/sort -k 4.3,4) << EOF-EOF-EOF");
    out.println();
    out.println("JTOC Map");
    out.println("--------");
    out.println("slot  offset     category contents            details");
    out.println("----  ------     -------- --------            -------");
    String pad = "        ";
    // Numeric JTOC fields
    for (int jtocSlot = Statics.getLowestInUseSlot(); jtocSlot < Statics.middleOfTable; jtocSlot++) {
        Offset jtocOff = Statics.slotAsOffset(jtocSlot);
        String category;
        String contents;
        String details;
        RVMField field = getRvmStaticField(jtocOff);
        RVMField field2 = getRvmStaticField(jtocOff.plus(4));
        boolean couldBeLongLiteral = Statics.isLongSizeLiteral(jtocSlot);
        boolean couldBeIntLiteral = Statics.isIntSizeLiteral(jtocSlot);
        if (couldBeLongLiteral && ((field == null) || (field2 == null))) {
            if ((field == null) && (field2 == null)) {
                category = "literal      ";
                long lval = Statics.getSlotContentsAsLong(jtocOff);
                contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
                details = lval + "L";
            } else if ((field == null) && (field2 != null)) {
                category = "literal/field";
                long lval = Statics.getSlotContentsAsLong(jtocOff);
                contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
                details = lval + "L / " + field2.toString();
            } else if ((field != null) && (field2 == null)) {
                category = "literal/field";
                long lval = Statics.getSlotContentsAsLong(jtocOff);
                contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
                details = lval + "L / " + field.toString();
            } else {
                throw new Error("Unreachable");
            }
            jtocSlot++;
        } else if (couldBeIntLiteral) {
            if (field != null) {
                category = "literal/field";
                int ival = Statics.getSlotContentsAsInt(jtocOff);
                contents = Services.intAsHexString(ival) + pad;
                details = Integer.toString(ival) + " / " + field.toString();
            } else {
                category = "literal      ";
                int ival = Statics.getSlotContentsAsInt(jtocOff);
                contents = Services.intAsHexString(ival) + pad;
                details = Integer.toString(ival);
            }
        } else {
            if (field != null) {
                category = "field        ";
                details = field.toString();
                TypeReference type = field.getType();
                if (type.isIntLikeType()) {
                    int ival = Statics.getSlotContentsAsInt(jtocOff);
                    contents = Services.intAsHexString(ival) + pad;
                } else if (type.isLongType()) {
                    long lval = Statics.getSlotContentsAsLong(jtocOff);
                    contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
                    jtocSlot++;
                } else if (type.isFloatType()) {
                    int ival = Statics.getSlotContentsAsInt(jtocOff);
                    contents = Float.toString(Float.intBitsToFloat(ival)) + pad;
                } else if (type.isDoubleType()) {
                    long lval = Statics.getSlotContentsAsLong(jtocOff);
                    contents = Double.toString(Double.longBitsToDouble(lval)) + pad;
                    jtocSlot++;
                } else if (type.isWordLikeType()) {
                    if (VM.BuildFor32Addr) {
                        int ival = Statics.getSlotContentsAsInt(jtocOff);
                        contents = Services.intAsHexString(ival) + pad;
                    } else {
                        long lval = Statics.getSlotContentsAsLong(jtocOff);
                        contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
                        jtocSlot++;
                    }
                } else {
                    // Unknown?
                    int ival = Statics.getSlotContentsAsInt(jtocOff);
                    category = "<? - field>  ";
                    details = "<? - " + field.toString() + ">";
                    contents = Services.intAsHexString(ival) + pad;
                }
            } else {
                // Unknown?
                int ival = Statics.getSlotContentsAsInt(jtocOff);
                category = "<?>        ";
                details = "<?>";
                contents = Services.intAsHexString(ival) + pad;
            }
        }
        out.println((jtocSlot + "        ").substring(0, 8) + Services.addressAsHexString(jtocOff.toWord().toAddress()) + " " + category + "  " + contents + "  " + details);
    }
    // Reference JTOC fields
    for (int jtocSlot = Statics.middleOfTable, n = Statics.getHighestInUseSlot(); jtocSlot <= n; jtocSlot += Statics.getReferenceSlotSize()) {
        Offset jtocOff = Statics.slotAsOffset(jtocSlot);
        Object obj = BootImageMap.getObject(getIVal(jtocOff));
        String category;
        String details;
        String contents = Services.addressAsHexString(getReferenceAddr(jtocOff, false)) + pad;
        RVMField field = getRvmStaticField(jtocOff);
        if (Statics.isReferenceLiteral(jtocSlot)) {
            if (field != null) {
                category = "literal/field";
            } else {
                category = "literal      ";
            }
            if (obj == null) {
                details = "(null)";
            } else if (obj instanceof String) {
                details = "\"" + obj + "\"";
            } else if (obj instanceof Class) {
                details = obj.toString();
                ;
            } else if (obj instanceof TIB) {
                category = "literal tib  ";
                RVMType type = ((TIB) obj).getType();
                details = (type == null) ? "?" : type.toString();
            } else {
                details = "object " + obj.getClass();
            }
            if (field != null) {
                details += " / " + field.toString();
            }
        } else if (field != null) {
            category = "field        ";
            details = field.toString();
        } else if (obj instanceof TIB) {
            // TIBs confuse the statics as their backing is written into the boot image
            category = "tib          ";
            RVMType type = ((TIB) obj).getType();
            details = (type == null) ? "?" : type.toString();
        } else {
            category = "unknown      ";
            if (obj instanceof String) {
                details = "\"" + obj + "\"";
            } else if (obj instanceof Class) {
                details = obj.toString();
            } else {
                CompiledMethod m = findMethodOfCode(obj);
                if (m != null) {
                    category = "code         ";
                    details = m.getMethod().toString();
                } else if (obj != null) {
                    details = "<?> - unrecognized field or literal of type " + obj.getClass();
                } else {
                    details = "<?>";
                }
            }
        }
        out.println((jtocSlot + "        ").substring(0, 8) + Services.addressAsHexString(jtocOff.toWord().toAddress()) + " " + category + "  " + contents + "  " + details);
    }
    out.println();
    out.println("Method Map");
    out.println("----------");
    out.println("                          address             method");
    out.println("                          -------             ------");
    out.println();
    for (int i = 0; i < CompiledMethods.numCompiledMethods(); ++i) {
        CompiledMethod compiledMethod = CompiledMethods.getCompiledMethodUnchecked(i);
        if (compiledMethod != null) {
            RVMMethod m = compiledMethod.getMethod();
            if (m != null && compiledMethod.isCompiled()) {
                CodeArray instructions = compiledMethod.getEntryCodeArray();
                Address code = BootImageMap.getImageAddress(instructions.getBacking(), true);
                out.println(".     .          code     " + Services.addressAsHexString(code) + "          " + compiledMethod.getMethod());
            }
        }
    }
    // Extra information on the layout of objects in the boot image
    if (false) {
        out.println();
        out.println("Object Map");
        out.println("----------");
        out.println("                          address             type");
        out.println("                          -------             ------");
        out.println();
        SortedSet<BootImageMap.Entry> set = new TreeSet<BootImageMap.Entry>(new Comparator<BootImageMap.Entry>() {

            @Override
            public int compare(BootImageMap.Entry a, BootImageMap.Entry b) {
                return Integer.valueOf(a.imageAddress.toInt()).compareTo(b.imageAddress.toInt());
            }
        });
        for (Enumeration<BootImageMap.Entry> e = BootImageMap.elements(); e.hasMoreElements(); ) {
            BootImageMap.Entry entry = e.nextElement();
            set.add(entry);
        }
        for (Iterator<BootImageMap.Entry> i = set.iterator(); i.hasNext(); ) {
            BootImageMap.Entry entry = i.next();
            Address data = entry.imageAddress;
            out.println(".     .          data     " + Services.addressAsHexString(data) + "          " + entry.jdkObject.getClass());
        }
    }
    out.println();
    out.println("EOF-EOF-EOF");
    out.flush();
    out.close();
}
Also used : Address(org.vmmagic.unboxed.Address) RVMType(org.jikesrvm.classloader.RVMType) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) CodeArray(org.jikesrvm.compilers.common.CodeArray) TreeSet(java.util.TreeSet) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) BufferedOutputStream(java.io.BufferedOutputStream) PrintStream(java.io.PrintStream) TIB(org.jikesrvm.objectmodel.TIB) Offset(org.vmmagic.unboxed.Offset) RVMMethod(org.jikesrvm.classloader.RVMMethod) FileOutputStream(java.io.FileOutputStream) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 2 with CodeArray

use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.

the class BootImageWriter method main.

/**
 * Main.
 * @param args command line arguments
 */
public static void main(String[] args) {
    String logFile = null;
    String bootImageCodeName = null;
    String bootImageDataName = null;
    String bootImageRMapName = null;
    String bootImageMapName = null;
    Vector<String> bootImageTypeNames = null;
    String bootImageTypeNamesFile = null;
    String[] bootImageCompilerArgs = {};
    // 
    // This may look useless, but it is not: it is a kludge to prevent
    // forName blowing up.  By forcing the system to load some classes
    // now, we ensure that forName does not cause security violations by
    // trying to load into java.util later.
    // 
    java.util.HashMap<Object, Class<?>> x = new java.util.HashMap<Object, Class<?>>();
    x.put(x, x.getClass());
    sillyhack = x;
    // 
    for (int i = 0; i < args.length; ++i) {
        // name of class library
        if (args[i].equals("-classlib")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -classlib flag without a following class library name");
            classLibrary = args[i].toLowerCase().intern();
            continue;
        }
        // name of code image file
        if (args[i].equals("-oc")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -oc flag without a following code image file name");
            bootImageCodeName = args[i];
            continue;
        }
        // name of data image file
        if (args[i].equals("-od")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -od flag without a following data image file name");
            bootImageDataName = args[i];
            continue;
        }
        // name of ref map image file
        if (args[i].equals("-or")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -or flag without a following ref map file name");
            bootImageRMapName = args[i];
            continue;
        }
        // name of map file
        if (args[i].equals("-m")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -m flag without a following bootImageMap file name");
            bootImageMapName = args[i];
            continue;
        }
        // image code start address
        if (args[i].equals("-ca")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -ca flag without a following image address");
            bootImageCodeAddress = decodeAddress(args[i]);
            continue;
        }
        // image data start address
        if (args[i].equals("-da")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -da flag without a following image address");
            bootImageDataAddress = decodeAddress(args[i]);
            continue;
        }
        // image ref map start address
        if (args[i].equals("-ra")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -ra flag without a following image address");
            bootImageRMapAddress = decodeAddress(args[i]);
            continue;
        }
        // file containing names of types to be placed into bootimage
        if (args[i].equals("-n")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -n flag without a following file name");
            if (bootImageTypeNamesFile != null)
                fail("argument syntax error: We've already read in the bootImageTypeNames from" + bootImageTypeNamesFile + "; just got another -n argument" + " telling us to read them from " + args[i]);
            bootImageTypeNamesFile = args[i];
            continue;
        }
        // bootimage compiler argument
        if (args[i].startsWith("-X:bc:")) {
            String[] nbca = new String[bootImageCompilerArgs.length + 1];
            for (int j = 0; j < bootImageCompilerArgs.length; j++) {
                nbca[j] = bootImageCompilerArgs[j];
            }
            nbca[nbca.length - 1] = args[i].substring(6);
            bootImageCompilerArgs = nbca;
            say("compiler arg: ", bootImageCompilerArgs[nbca.length - 1]);
            continue;
        }
        // places where rvm components live, at build time
        if (args[i].equals("-classpath")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -classpath flag without a following classpath for build-time RVM components");
            bootImageRepositoriesAtBuildTime = args[i];
            continue;
        }
        // places where rvm components live, at execution time
        if (args[i].equals("-xclasspath")) {
            if (++i >= args.length)
                fail("argument syntax error: Got an -xclasspath flag without a following execution-time classpath for RVM components");
            bootImageRepositoriesAtExecutionTime = args[i];
            continue;
        }
        // generate trace messages while writing bootimage (for debugging)
        if (args[i].equals("-trace")) {
            verbosity = verbosity.increaseBy(1);
            continue;
        }
        // generate info by type
        if (args[i].equals("-demographics")) {
            demographics = true;
            continue;
        }
        // numThreads
        if (args[i].startsWith("-numThreads=")) {
            int desiredThreadCount = Integer.parseInt(args[i].substring(12));
            if (desiredThreadCount < 0) {
                fail("numThreads must be a non-negative number, value supplied:  " + desiredThreadCount);
            }
            // already does this so there's nothing to do here.
            if (desiredThreadCount == 0)
                continue;
            // use the explicit value provided by the user
            numThreads = desiredThreadCount;
            continue;
        }
        // profile
        if (args[i].equals("-profile")) {
            profile = true;
            continue;
        }
        // log
        if (args[i].equals("-log")) {
            if (++i >= args.length)
                fail("argument syntax error: Got a -log flag without a following argument for the log file");
            logFile = args[i];
            continue;
        }
        // generate detailed information about traversed objects (for debugging)
        if (args[i].equals("-detailed")) {
            verbosity = verbosity.increaseBy(2);
            continue;
        }
        // write words to bootimage in little endian format
        if (args[i].equals("-littleEndian")) {
            littleEndian = true;
            continue;
        }
        fail("unrecognized command line argument: " + args[i]);
    }
    if (verbosity.isAtLeast(Verbosity.DETAILED))
        traversed = new Hashtable<Object, Integer>(500);
    // 
    if (bootImageCodeName == null)
        fail("please specify \"-oc <boot-image-code-filename>\"");
    if (bootImageDataName == null)
        fail("please specify \"-od <boot-image-data-filename>\"");
    if (bootImageRMapName == null)
        fail("please specify \"-or <boot-image-rmap-filename>\"");
    if (bootImageTypeNamesFile == null)
        fail("please specify \"-n <boot-image-type-names-filename>\"");
    if (bootImageRepositoriesAtBuildTime == null)
        fail("please specify \"-classpath <path>\"");
    if (bootImageRepositoriesAtExecutionTime == null)
        bootImageRepositoriesAtExecutionTime = bootImageRepositoriesAtBuildTime;
    if (bootImageDataAddress.isZero())
        fail("please specify boot-image address with \"-da <addr>\"");
    if (!(bootImageDataAddress.toWord().and(Word.fromIntZeroExtend(0x00FFFFFF)).isZero()))
        fail("please specify a boot-image address that is a multiple of 0x01000000");
    if (bootImageCodeAddress.isZero())
        fail("please specify boot-image address with \"-ca <addr>\"");
    if (!(bootImageCodeAddress.toWord().and(Word.fromIntZeroExtend(0x00FFFFFF)).isZero()))
        fail("please specify a boot-image address that is a multiple of 0x01000000");
    if (bootImageRMapAddress.isZero())
        fail("please specify boot-image address with \"-ra <addr>\"");
    if (!(bootImageRMapAddress.toWord().and(Word.fromIntZeroExtend(0x00FFFFFF)).isZero()))
        fail("please specify a boot-image address that is a multiple of 0x01000000");
    // Redirect the log file
    if (logFile != null) {
        try {
            PrintStream logFileStream = new PrintStream(logFile);
            System.setOut(logFileStream);
            System.setErr(logFileStream);
        } catch (IOException ex) {
            fail("Failed to open log file for redirecting: " + ex.getMessage());
        }
    }
    // 
    try {
        bootImage = new BootImage(littleEndian, verbosity.isAtLeast(Verbosity.SUMMARY), bootImageCodeName, bootImageDataName, bootImageRMapName);
    } catch (IOException e) {
        fail("unable to write bootImage: " + e);
    }
    // 
    // Install handler that intercepts all object address references made by
    // xxx classes executed on host jdk and substitutes a value that can be
    // fixed up later when those objects are copied from host jdk to bootimage.
    // 
    enableObjectAddressRemapper();
    // 
    if (verbosity.isAtLeast(SUMMARY))
        say("starting up");
    // try {
    VM.initForBootImageWriter(bootImageRepositoriesAtBuildTime, bootImageCompilerArgs);
    // } catch (Exception e) {
    // fail("unable to initialize VM: "+e);
    // }
    // 
    // Create (in host jdk address space) the rvm objects that will be
    // needed at run time to execute enough of the virtual machine
    // to dynamically load and compile the remainder of itself.
    // 
    long startTime = 0;
    long stopTime = 0;
    if (profile)
        startTime = System.currentTimeMillis();
    try {
        bootImageTypeNames = readTypeNames(bootImageTypeNamesFile);
    } catch (IOException e) {
        fail("unable to read the type names from " + bootImageTypeNamesFile + ": " + e);
    }
    if (profile) {
        stopTime = System.currentTimeMillis();
        System.out.println("PROF: readingTypeNames " + (stopTime - startTime) + " ms");
    }
    if (profile)
        startTime = System.currentTimeMillis();
    try {
        createBootImageObjects(bootImageTypeNames, bootImageTypeNamesFile);
    } catch (Exception e) {
        e.printStackTrace(System.out);
        fail("unable to create objects: " + e);
    }
    if (profile) {
        stopTime = System.currentTimeMillis();
        System.out.println("PROF: createBootImageObjects " + (stopTime - startTime) + " ms");
    }
    // 
    // No further bootimage object references should get generated.
    // If they are, they'll be assigned an objectId of "-1" (see Magic)
    // and will manifest themselves as an array subscript out of bounds
    // error when BootImageMap attempts to look up the object references.
    // 
    disableObjectAddressRemapper();
    // //////////////////////////////////////////////////
    // Copy rvm objects from host jdk into bootimage.
    // //////////////////////////////////////////////////
    VM.writingImage = true;
    if (verbosity.isAtLeast(SUMMARY))
        say("Memory available: ", String.valueOf(Runtime.getRuntime().freeMemory()), " bytes out of ", String.valueOf(Runtime.getRuntime().totalMemory()), " bytes");
    if (profile)
        startTime = System.currentTimeMillis();
    // 
    if (verbosity.isAtLeast(SUMMARY))
        say("copying boot record");
    BootRecord bootRecord = BootRecord.the_boot_record;
    Address bootRecordImageAddress = Address.zero();
    try {
        // copy just the boot record
        bootRecordImageAddress = copyToBootImage(bootRecord, true, Address.max(), null, false, AlignmentEncoding.ALIGN_CODE_NONE);
        if (bootRecordImageAddress.EQ(OBJECT_NOT_PRESENT)) {
            fail("can't copy boot record");
        }
    } catch (IllegalAccessException e) {
        fail("can't copy boot record: " + e);
    }
    // 
    if (verbosity.isAtLeast(SUMMARY))
        say("copying jtoc");
    // Pointer to middle of JTOC
    Address jtocImageAddress = Address.max();
    try {
        if (VM.BuildForIA32) {
            // Force 16byte alignment of the JTOC on Intel
            int[] slots = Statics.getSlotsAsIntArray();
            jtocImageAddress = bootImage.allocateArray(RVMArray.IntArray, slots.length, false, 0, 16, AlignmentEncoding.ALIGN_CODE_NONE);
            BootImageMap.Entry jtocEntry = BootImageMap.findOrCreateEntry(slots);
            jtocEntry.imageAddress = jtocImageAddress;
        }
        jtocImageAddress = copyToBootImage(Statics.getSlotsAsIntArray(), false, jtocImageAddress, null, false, AlignmentEncoding.ALIGN_CODE_NONE);
        if (jtocImageAddress.EQ(OBJECT_NOT_PRESENT)) {
            fail("can't copy jtoc");
        }
    } catch (IllegalAccessException e) {
        fail("can't copy jtoc: " + e);
    }
    Address jtocPtr = jtocImageAddress.plus(Statics.middleOfTable << LOG_BYTES_IN_INT);
    if (jtocPtr.NE(bootRecord.tocRegister))
        fail("mismatch in JTOC placement " + Services.addressAsHexString(jtocPtr) + " != " + Services.addressAsHexString(bootRecord.tocRegister));
    // 
    if (verbosity.isAtLeast(SUMMARY))
        say("copying statics");
    try {
        int refSlotSize = Statics.getReferenceSlotSize();
        for (int i = Statics.middleOfTable + refSlotSize, n = Statics.getHighestInUseSlot(); i <= n; i += refSlotSize) {
            if (!Statics.isReference(i)) {
                throw new Error("Static " + i + " of " + n + " isn't reference");
            }
            // for diagnostic
            jtocCount = i;
            Offset jtocOff = Statics.slotAsOffset(i);
            int objCookie;
            if (VM.BuildFor32Addr)
                objCookie = Statics.getSlotContentsAsInt(jtocOff);
            else
                objCookie = (int) Statics.getSlotContentsAsLong(jtocOff);
            // if (verbose.isAtLeast(ADDRESSES))
            // say("       jtoc[", String.valueOf(i), "] = ", String.valueOf(objCookie));
            Object jdkObject = BootImageMap.getObject(objCookie);
            if (jdkObject == null)
                continue;
            if (verbosity.isAtLeast(DETAILED))
                traceContext.push(jdkObject.getClass().getName(), getRvmStaticField(jtocOff) + "");
            copyReferenceFieldToBootImage(jtocPtr.plus(jtocOff), jdkObject, Statics.getSlotsAsIntArray(), false, false, null, null);
            if (verbosity.isAtLeast(DETAILED))
                traceContext.pop();
        }
        // Copy entries that are in the pending queue
        processPendingEntries();
        // Find and copy unallocated entries
        for (int i = 0; i < BootImageMap.objectIdToEntry.size(); i++) {
            BootImageMap.Entry mapEntry = BootImageMap.objectIdToEntry.get(i);
            if (mapEntry.imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
                mapEntry.imageAddress = copyToBootImage(mapEntry.jdkObject, false, Address.max(), null, false, AlignmentEncoding.ALIGN_CODE_NONE);
                fixupLinkAddresses(mapEntry);
            }
        }
    } catch (IllegalAccessException e) {
        fail("unable to copy statics: " + e);
    }
    jtocCount = -1;
    if (profile) {
        stopTime = System.currentTimeMillis();
        System.out.println("PROF: filling bootimage byte[] " + (stopTime - startTime) + " ms");
    }
    // 
    if (verbosity.isAtLeast(SUMMARY))
        say("updating boot record");
    byte[] startupStack = startupThread.getStack();
    CodeArray startupCode = Entrypoints.bootMethod.getCurrentEntryCodeArray();
    bootRecord.spRegister = BootImageMap.getImageAddress(startupStack, true).plus(startupStack.length);
    bootRecord.ipRegister = BootImageMap.getImageAddress(startupCode.getBacking(), true);
    bootRecord.bootThreadOffset = Entrypoints.bootThreadField.getOffset();
    bootRecord.bootImageDataStart = bootImageDataAddress;
    bootRecord.bootImageDataEnd = bootImageDataAddress.plus(bootImage.getDataSize());
    bootRecord.bootImageCodeStart = bootImageCodeAddress;
    bootRecord.bootImageCodeEnd = bootImageCodeAddress.plus(bootImage.getCodeSize());
    bootRecord.bootImageRMapStart = bootImageRMapAddress;
    bootRecord.bootImageRMapEnd = bootImageRMapAddress.plus(bootImage.getRMapSize());
    // 
    if (verbosity.isAtLeast(SUMMARY))
        say("re-copying boot record (and its TIB)");
    try {
        Address newBootRecordImageAddress = copyToBootImage(bootRecord, false, bootRecordImageAddress, null, false, AlignmentEncoding.ALIGN_CODE_NONE);
        if (!newBootRecordImageAddress.EQ(bootRecordImageAddress)) {
            VM.sysWriteln("bootRecordImageOffset = ", bootRecordImageAddress);
            VM.sysWriteln("newBootRecordImageOffset = ", newBootRecordImageAddress);
            if (VM.VerifyAssertions) {
                VM._assert(newBootRecordImageAddress.EQ(bootRecordImageAddress));
            }
        }
        // Make sure pending entries are fully written out
        processPendingEntries();
    } catch (IllegalAccessException e) {
        fail("unable to update boot record: " + e);
    }
    if (VM.BuildWithGCTrace) {
        /* Set the values in fields updated during the build process */
        Offset prevAddrOffset = Entrypoints.tracePrevAddressField.getOffset();
        bootImage.setAddressWord(jtocPtr.plus(prevAddrOffset), MiscHeader.getBootImageLink().toWord(), false, false);
        Offset oIDOffset = Entrypoints.traceOIDField.getOffset();
        bootImage.setAddressWord(jtocPtr.plus(oIDOffset), MiscHeader.getOID(), false, false);
    }
    // 
    if (profile)
        startTime = System.currentTimeMillis();
    try {
        bootImage.write();
    } catch (IOException e) {
        fail("unable to write bootImage: " + e);
    }
    if (profile) {
        stopTime = System.currentTimeMillis();
        System.out.println("PROF: writing RVM.map " + (stopTime - startTime) + " ms");
    }
    // 
    if (demographics) {
        spaceReport();
    }
    // 
    if (verbosity.isAtLeast(DETAILED)) {
        for (int i = FIRST_TYPE_DICTIONARY_INDEX; i < RVMType.numTypes(); ++i) {
            RVMType type = RVMType.getType(i);
            if (type == null)
                continue;
            if (!type.isResolved()) {
                say("type referenced but not resolved: ", type.toString());
            } else if (!type.isInstantiated()) {
                say("type referenced but not instantiated: ", type.toString());
            } else if (!type.isInitialized()) {
                say("type referenced but not initialized: ", type.toString());
            }
        }
    }
    // 
    try {
        if (bootImageMapName != null)
            writeAddressMap(bootImageMapName);
    } catch (IOException e) {
        fail("unable to write address map: " + e);
    }
    if (verbosity.isAtLeast(SUMMARY))
        say("done");
}
Also used : Address(org.vmmagic.unboxed.Address) HashMap(java.util.HashMap) RVMType(org.jikesrvm.classloader.RVMType) CodeArray(org.jikesrvm.compilers.common.CodeArray) PrintStream(java.io.PrintStream) Hashtable(java.util.Hashtable) IOException(java.io.IOException) IOException(java.io.IOException) Offset(org.vmmagic.unboxed.Offset) BootRecord(org.jikesrvm.runtime.BootRecord) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 3 with CodeArray

use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.

the class AssemblerOpt method genCode.

protected final int genCode(IR ir, boolean shouldPrint) {
    int mi = 0;
    CodeArray machinecodes = ir.MIRInfo.machinecode;
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    int labelCountEstimate = ir.cfg.numberOfNodes();
    branchBackPatching = new BranchInformationForBackPatching(labelCountEstimate);
    boolean unsafeCondDispl = machinecodes.length() > MAX_COND_DISPL;
    // boolean unsafeDispl = machinecodes.length() > MAX_DISPL;
    MachineCodeOffsets mcOffsets = ir.MIRInfo.mcOffsets;
    for (Instruction p = ir.firstInstructionInCodeOrder(); p != null; p = p.nextInstructionInCodeOrder()) {
        int inst = p.operator().instTemplate();
        switch(p.getOpcode()) {
            case LABEL_opcode:
                backpatchForwardBranches(p, machinecodes, mi, mcOffsets);
                break;
            case BBEND_opcode:
            case UNINT_BEGIN_opcode:
            case UNINT_END_opcode:
            case GUARD_MOVE_opcode:
            case GUARD_COMBINE_opcode:
                mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                break;
            case PPC_DATA_INT_opcode:
                {
                    int value = MIR_DataInt.getValue(p).value;
                    machinecodes.set(mi++, value);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_DATA_LABEL_opcode:
                {
                    Instruction target = MIR_DataLabel.getTarget(p).target;
                    int targetOffset = resolveBranch(p, target, mi, mcOffsets);
                    machinecodes.set(mi++, targetOffset);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_CRAND_opcode:
            case PPC_CRANDC_opcode:
            case PPC_CROR_opcode:
            case PPC_CRORC_opcode:
                {
                    int op0 = MIR_Condition.getResultBit(p).value & REG_MASK;
                    int op1 = MIR_Condition.getValue1Bit(p).value & REG_MASK;
                    int op2 = MIR_Condition.getValue2Bit(p).value & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_ADD_opcode:
            case PPC_ADDr_opcode:
            case PPC_ADDC_opcode:
            case PPC_ADDE_opcode:
            case PPC_SUBF_opcode:
            case PPC_SUBFr_opcode:
            case PPC_SUBFC_opcode:
            case PPC_SUBFCr_opcode:
            case PPC_SUBFE_opcode:
            case PPC_FADD_opcode:
            case PPC_FADDS_opcode:
            case PPC_FDIV_opcode:
            case PPC_FDIVS_opcode:
            case PPC_DIVW_opcode:
            case PPC_DIVWU_opcode:
            case PPC_MULLW_opcode:
            case PPC_MULHW_opcode:
            case PPC_MULHWU_opcode:
            case PPC_FSUB_opcode:
            case PPC_FSUBS_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_MULLD_opcode:
            case PPC64_DIVD_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_LWZX_opcode:
            case PPC_LWARX_opcode:
            case PPC_LBZX_opcode:
            case PPC_LHAX_opcode:
            case PPC_LHZX_opcode:
            case PPC_LFDX_opcode:
            case PPC_LFSX_opcode:
            case PPC_LIntX_opcode:
            case PPC_LAddrARX_opcode:
            case PPC_LAddrX_opcode:
                {
                    int op0 = MIR_Load.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Load.getAddress(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Load.getOffset(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_LDX_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Load.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Load.getAddress(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Load.getOffset(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_STWX_opcode:
            case PPC_STWCXr_opcode:
            case PPC_STBX_opcode:
            case PPC_STHX_opcode:
            case PPC_STFDX_opcode:
            case PPC_STFSX_opcode:
            case PPC_STAddrCXr_opcode:
            case PPC_STAddrX_opcode:
            case PPC_STAddrUX_opcode:
                {
                    int op0 = MIR_Store.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Store.getAddress(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Store.getOffset(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_LWZUX_opcode:
            case PPC_LBZUX_opcode:
            case PPC_LIntUX_opcode:
            case PPC_LAddrUX_opcode:
                {
                    int op0 = MIR_LoadUpdate.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_LoadUpdate.getAddress(p).getRegister().number & REG_MASK;
                    int op2 = MIR_LoadUpdate.getOffset(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_LWZU_opcode:
                {
                    int op0 = MIR_LoadUpdate.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_LoadUpdate.getAddress(p).getRegister().number & REG_MASK;
                    int op2 = MIR_LoadUpdate.getOffset(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_TW_opcode:
            case PPC_TAddr_opcode:
                {
                    int op0 = MIR_Trap.getCond(p).value;
                    int op1 = MIR_Trap.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Trap.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_TD_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Trap.getCond(p).value;
                    int op1 = MIR_Trap.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Trap.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_TWI_opcode:
                {
                    int op0 = MIR_Trap.getCond(p).value;
                    int op1 = MIR_Trap.getValue1(p).getRegister().number & REG_MASK;
                    int op2;
                    if (VM.BuildFor64Addr && MIR_Trap.getValue2(p).isLongConstant()) {
                        op2 = ((int) MIR_Trap.getValue2(p).asLongConstant().value) & SHORT_MASK;
                    } else {
                        op2 = MIR_Trap.getValue2(p).asIntConstant().value & SHORT_MASK;
                    }
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_TDI_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Trap.getCond(p).value;
                    int op1 = MIR_Trap.getValue1(p).getRegister().number & REG_MASK;
                    int op2;
                    if (MIR_Trap.getValue2(p).isLongConstant()) {
                        op2 = ((int) MIR_Trap.getValue2(p).asLongConstant().value) & SHORT_MASK;
                    } else {
                        op2 = MIR_Trap.getValue2(p).asIntConstant().value & SHORT_MASK;
                    }
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case NULL_CHECK_opcode:
                /* Just a nicer name for a twi <ref> lessthan 1 */
                {
                    int op0 = PowerPCTrapOperand.LOWER;
                    int op1 = ((RegisterOperand) NullCheck.getRef(p)).getRegister().number & REG_MASK;
                    int op2 = 1;
                    inst = VM.BuildFor64Addr ? PPC64_TDI.instTemplate() : PPC_TWI.instTemplate();
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_LDI_opcode:
            case PPC_LDIS_opcode:
                // D_Form. pseudo instructions derived from PPC_ADDI and PPC_ADDIS
                {
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | op1));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_ADDIC_opcode:
            case PPC_ADDICr_opcode:
            case PPC_SUBFIC_opcode:
            case PPC_MULLI_opcode:
            case PPC_ADDI_opcode:
            case PPC_ADDIS_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_CNTLZW_opcode:
            case PPC_CNTLZAddr_opcode:
            case PPC_EXTSB_opcode:
            case PPC_EXTSBr_opcode:
            case PPC_EXTSH_opcode:
            case PPC_EXTSHr_opcode:
                {
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_EXTSW_opcode:
            case PPC64_EXTSWr_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_EXTZW_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asRegister().getRegister().number & REG_MASK;
                    // op3low = 0, so op3 == 32
                    int op3high = 1;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op3high << 5)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_ADDZE_opcode:
            case PPC_SUBFZE_opcode:
            case PPC_NEG_opcode:
            case PPC_NEGr_opcode:
            case PPC_ADDME_opcode:
                {
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            // Bit positions of op1 and op2 are reversed.
            case PPC_XORI_opcode:
            case PPC_XORIS_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            // Bit positions of op1 and op2 are reversed.
            case PPC_AND_opcode:
            case PPC_ANDr_opcode:
            case PPC_NAND_opcode:
            case PPC_NANDr_opcode:
            case PPC_ANDC_opcode:
            case PPC_ANDCr_opcode:
            case PPC_OR_opcode:
            case PPC_ORr_opcode:
            case PPC_NOR_opcode:
            case PPC_NORr_opcode:
            case PPC_ORC_opcode:
            case PPC_ORCr_opcode:
            case PPC_XOR_opcode:
            case PPC_XORr_opcode:
            case PPC_EQV_opcode:
            case PPC_EQVr_opcode:
            case PPC_SLW_opcode:
            case PPC_SLWr_opcode:
            case PPC_SRW_opcode:
            case PPC_SRWr_opcode:
            case PPC_SRAW_opcode:
            case PPC_SRAWr_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_SLD_opcode:
            case PPC64_SLDr_opcode:
            case PPC64_SRD_opcode:
            case PPC64_SRDr_opcode:
            case PPC64_SRAD_opcode:
            case PPC64_SRADr_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_MOVE_opcode:
                /* pseudo opcode, equal to PPC_ORI with 0 */
                {
                    int op0 = MIR_Move.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Move.getValue(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_SRWI_opcode:
            /* pseudo opcode, equal to rlwinm Rx,Ry,32-n,n,31 */
            case PPC_SRWIr_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int shift = MIR_Binary.getValue2(p).asIntConstant().value & REG_MASK;
                    int op2 = (32 - shift);
                    int op3 = shift;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11) | (op3 << 6)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            // Bit positions of op1 and op2 are reversed.
            case PPC_SLWI_opcode:
            case PPC_SLWIr_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int shift = MIR_Binary.getValue2(p).asIntConstant().value & REG_MASK;
                    int op2 = shift;
                    int op3 = (31 - shift);
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11) | (op3 << 1)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_SRAWI_opcode:
            case PPC_SRAWIr_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_SRAddrI_opcode:
                {
                    if (VM.BuildFor32Addr) {
                        int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                        int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                        int shift = MIR_Binary.getValue2(p).asIntConstant().value & REG_MASK;
                        int op2 = (32 - shift);
                        int op3 = shift;
                        machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11) | (op3 << 6)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    } else {
                        int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                        int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                        int op3 = MIR_Binary.getValue2(p).asIntConstant().value & SIXBIT_MASK;
                        int op2 = 64 - op3;
                        int op2low = op2 & 0x1F;
                        int op2high = (op2 & 0x20) >>> 5;
                        int op3low = op3 & 0x1F;
                        int op3high = (op3 & 0x20) >>> 5;
                        machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1) | (op3low << 6) | (op3high << 5)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    }
                }
                break;
            case PPC_SRAAddrI_opcode:
                {
                    if (VM.BuildFor32Addr) {
                        int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                        int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                        int op2 = MIR_Binary.getValue2(p).asIntConstant().value & REG_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    } else {
                        int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                        int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                        int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SIXBIT_MASK;
                        int op2low = op2 & 0x1F;
                        int op2high = (op2 & 0x20) >>> 5;
                        machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    }
                }
                break;
            case PPC64_SRADI_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SIXBIT_MASK;
                    int op2low = op2 & 0x1F;
                    int op2high = (op2 & 0x20) >>> 5;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_SRDI_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op3 = MIR_Binary.getValue2(p).asIntConstant().value & SIXBIT_MASK;
                    int op2 = 64 - op3;
                    int op2low = op2 & 0x1F;
                    int op2high = (op2 & 0x20) >>> 5;
                    int op3low = op3 & 0x1F;
                    int op3high = (op3 & 0x20) >>> 5;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1) | (op3low << 6) | (op3high << 5)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case // shorthand via RLDICR
            PPC64_SLDI_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int shift = MIR_Binary.getValue2(p).asIntConstant().value & SIXBIT_MASK;
                    int op2 = shift;
                    int op2low = op2 & 0x1F;
                    int op2high = (op2 & 0x20) >>> 5;
                    int op3 = 63 - shift;
                    int op3low = op3 & 0x1F;
                    int op3high = (op3 & 0x20) >>> 5;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1) | (op3low << 6) | (op3high << 5)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_RLDICR_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_RotateAndMask.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_RotateAndMask.getValue(p).getRegister().number & REG_MASK;
                    // shift
                    int op2 = MIR_RotateAndMask.getShift(p).asIntConstant().value & SIXBIT_MASK;
                    int op2low = op2 & 0x1F;
                    int op2high = (op2 & 0x20) >>> 5;
                    // mask
                    int op3 = MIR_RotateAndMask.getMaskEnd(p).value & SIXBIT_MASK;
                    int op3low = op3 & 0x1F;
                    int op3high = (op3 & 0x20) >>> 5;
                    if (VM.VerifyAssertions) {
                        int op4 = MIR_RotateAndMask.getMaskBegin(p).value & SIXBIT_MASK;
                        VM._assert(op4 == 0);
                    }
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1) | (op3low << 6) | (op3high << 5)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_RLDICL_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_RotateAndMask.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_RotateAndMask.getValue(p).getRegister().number & REG_MASK;
                    // shift
                    int op2 = MIR_RotateAndMask.getShift(p).asIntConstant().value & SIXBIT_MASK;
                    int op2low = op2 & 0x1F;
                    int op2high = (op2 & 0x20) >>> 5;
                    // mask
                    int op3 = MIR_RotateAndMask.getMaskBegin(p).value & SIXBIT_MASK;
                    int op3low = op3 & 0x1F;
                    int op3high = (op3 & 0x20) >>> 5;
                    if (VM.VerifyAssertions) {
                        int op4 = MIR_RotateAndMask.getMaskEnd(p).value & SIXBIT_MASK;
                        VM._assert(op4 == 63);
                    }
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2low << 11) | (op2high << 1) | (op3low << 6) | (op3high << 5)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            // Bit positions of op1 and op2 are reversed.
            case PPC_ANDIr_opcode:
            case PPC_ANDISr_opcode:
            case PPC_ORI_opcode:
            case PPC_ORIS_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_RLWINM_opcode:
            case PPC_RLWINMr_opcode:
                {
                    int op0 = MIR_RotateAndMask.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_RotateAndMask.getValue(p).getRegister().number & REG_MASK;
                    int op2 = MIR_RotateAndMask.getShift(p).asIntConstant().value & REG_MASK;
                    int op3 = MIR_RotateAndMask.getMaskBegin(p).value & REG_MASK;
                    int op4 = MIR_RotateAndMask.getMaskEnd(p).value & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11) | (op3 << 6) | (op4 << 1)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_RLWIMI_opcode:
            case PPC_RLWIMIr_opcode:
                {
                    int op0 = MIR_RotateAndMask.getResult(p).getRegister().number & REG_MASK;
                    int op0f = MIR_RotateAndMask.getSource(p).getRegister().number & REG_MASK;
                    if (op0 != op0f) {
                        throw new OptimizingCompilerException("CodeGen", "format for RLWIMI is incorrect");
                    }
                    int op1 = MIR_RotateAndMask.getValue(p).getRegister().number & REG_MASK;
                    int op2 = MIR_RotateAndMask.getShift(p).asIntConstant().value & REG_MASK;
                    int op3 = MIR_RotateAndMask.getMaskBegin(p).value & REG_MASK;
                    int op4 = MIR_RotateAndMask.getMaskEnd(p).value & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11) | (op3 << 6) | (op4 << 1)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_RLWNM_opcode:
            case PPC_RLWNMr_opcode:
                {
                    int op0 = MIR_RotateAndMask.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_RotateAndMask.getValue(p).getRegister().number & REG_MASK;
                    int op2 = MIR_RotateAndMask.getShift(p).asRegister().getRegister().number & REG_MASK;
                    int op3 = MIR_RotateAndMask.getMaskBegin(p).value & REG_MASK;
                    int op4 = MIR_RotateAndMask.getMaskEnd(p).value & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21) | (op2 << 11) | (op3 << 6) | (op4 << 1)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_B_opcode:
                {
                    BranchOperand o = MIR_Branch.getTarget(p);
                    int targetOffset = resolveBranch(p, o.target, mi, mcOffsets);
                    machinecodes.set(mi++, inst | (targetOffset & LI_MASK));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_BLR_opcode:
            case PPC_BCTR_opcode:
                /* p   , == bcctr  0x14,BI */
                {
                    // INDIRECT BRANCH (Target == null)
                    machinecodes.set(mi++, inst);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_BC_opcode:
            case PPC_BCOND_opcode:
            /* p 38, BO == 001zy or 011zy */
            case PPC_BCC_opcode:
                /* p 38, BO == 0000y, 0001y, 0100y or 0101y */
                {
                    // COND BRANCH
                    int op0 = MIR_CondBranch.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_CondBranch.getCond(p).value;
                    // Add (CR field)<<2 to make BI represent the correct
                    // condition bit (0..3) in the correct condition field (0..7).
                    // 1 <= op <= 7
                    int bo_bi = op0 << 2 | op1;
                    BranchOperand o = MIR_CondBranch.getTarget(p);
                    int targetOffset = resolveBranch(p, o.target, mi, mcOffsets);
                    if (targetOffset == 0) {
                        // unresolved branch
                        if (DEBUG)
                            VM.sysWriteln("**** Forward Cond. Branch ****");
                        machinecodes.set(mi++, inst | (bo_bi << 16));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                        if (DEBUG)
                            VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                        if (unsafeCondDispl) {
                            // assume we might need two words
                            // for now fill with NOP
                            machinecodes.set(mi++, NOPtemplate);
                            if (DEBUG)
                                VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                        }
                    } else if (targetOffset < MIN_COND_DISPL << 2) {
                        // one word is not enough
                        if (DEBUG)
                            VM.sysWriteln("**** Backward Long Cond. Branch ****");
                        // flip the condition and skip the following branch instruction
                        if (DEBUG)
                            VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                        machinecodes.set(mi++, inst | flipCondition(bo_bi << 16) | (2 << 2));
                        if (DEBUG)
                            VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                        // make a long branch to the target
                        machinecodes.set(mi++, Btemplate | ((targetOffset - 4) & LI_MASK));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                        if (DEBUG)
                            VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                    } else {
                        // one word is enough
                        if (DEBUG)
                            VM.sysWriteln("**** Backward Short Cond. Branch ****");
                        machinecodes.set(mi++, inst | (bo_bi << 16) | (targetOffset & BD_MASK));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                        if (DEBUG)
                            VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                    }
                }
                break;
            case PPC_BCLR_opcode:
            case PPC_BCCTR_opcode:
                /* p   , BO == 0z10y or 0z11y */
                {
                    // INDIRECT COND BRANCH
                    int op0 = MIR_CondBranch.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_CondBranch.getCond(p).value;
                    // Add (CR field)<<2 to make BI represent the correct
                    // condition bit (0..3) in the correct condition field (0..7).
                    // 1 <= op <= 7
                    int bo_bi = op0 << 2 | op1;
                    machinecodes.set(mi++, inst | (bo_bi << 16));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    if (DEBUG)
                        VM.sysWrite(disasm(machinecodes.get(mi - 1), 0));
                }
                break;
            case PPC_BL_opcode:
            case PPC_BL_SYS_opcode:
                {
                    // CALL
                    BranchOperand o = MIR_Call.getTarget(p);
                    int targetOffset = resolveBranch(p, o.target, mi, mcOffsets);
                    machinecodes.set(mi++, inst | (targetOffset & LI_MASK));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_BLRL_opcode:
            /* p 39, == bclrl  0x14,BI */
            case PPC_BCTRL_opcode:
            /* p   , == bcctrl 0x14,BI */
            case PPC_BCTRL_SYS_opcode:
                /* p   , == bcctrl 0x14,BI */
                {
                    // INDIRECT CALL (Target == null)
                    machinecodes.set(mi++, inst);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_BCL_opcode:
                {
                    // COND CALL
                    int op0 = MIR_CondCall.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_CondCall.getCond(p).value;
                    // Add (CR field)<<2 to make BI represent the correct
                    // condition bit (0..3) in the correct condition field (0..7).
                    // 1 <= op <= 7
                    int bo_bi = op0 << 2 | op1;
                    BranchOperand o = MIR_CondCall.getTarget(p);
                    int targetOffset = resolveBranch(p, o.target, mi, mcOffsets);
                    if (targetOffset == 0) {
                        // unresolved branch
                        if (DEBUG)
                            VM.sysWriteln("**** Forward Cond. Branch ****");
                        machinecodes.set(mi++, inst | (bo_bi << 16));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                        if (DEBUG)
                            VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                        if (unsafeCondDispl) {
                            // assume we need two words
                            // for now fill with NOP
                            machinecodes.set(mi++, NOPtemplate);
                            if (DEBUG)
                                VM.sysWriteln(disasm(machinecodes.get(mi - 1), 0));
                        }
                    } else if (targetOffset < MIN_COND_DISPL << 2) {
                        // one instruction is not enough
                        throw new OperationNotImplementedException(// --dave
                        "Support for long backwards conditional branch and link is incorrect.");
                    /*
              -- we have to branch (and not link) around an
              unconditional branch and link.
              -- the code below generates a conditional branch and
              link around an unconditional branch.
              if (DEBUG) VM.sysWriteln("**** Backward Long Cond. Branch ****");
              // flip the condition and skip the following branch instruction
              machinecodes.set(mi++, inst | flipCondition(bo_bi<<16) | (2<<2));
              if (DEBUG) printInstruction(mi-1, inst,
              flipCondition(bo_bi<<16), 2<<2);
              // make a long branch to the target
              machinecodes.set(mi++, Btemplate | ((targetOffset-4) & LI_MASK));
              mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
              if (DEBUG) printInstruction(mi-1, Btemplate, targetOffset-4);
            */
                    } else {
                        // one instruction is enough
                        if (DEBUG)
                            VM.sysWriteln("**** Backward Short Cond. Branch ****");
                        machinecodes.set(mi++, inst | (bo_bi << 16) | (targetOffset & BD_MASK));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                        if (DEBUG)
                            VM.sysWrite(disasm(machinecodes.get(mi - 1), 0));
                    }
                }
                break;
            case PPC_BCLRL_opcode:
                {
                    // INDIRECT COND CALL
                    int op0 = MIR_CondCall.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_CondCall.getCond(p).value;
                    // Add (CR field)<<2 to make BI represent the correct
                    // condition bit (0..3) in the correct condition field (0..7).
                    // 1 <= op <= 7
                    int bo_bi = op0 << 2 | op1;
                    machinecodes.set(mi++, inst | (bo_bi << 16));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    if (DEBUG)
                        VM.sysWrite(disasm(machinecodes.get(mi - 1), 0));
                }
                break;
            case PPC_CMP_opcode:
            case PPC_CMPL_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 23) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_CMP_opcode:
            case PPC64_CMPL_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 23) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_CMPI_opcode:
            case PPC_CMPLI_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 23) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_CMPI_opcode:
            case PPC64_CMPLI_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 23) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_FMR_opcode:
                {
                    int op0 = MIR_Move.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Move.getValue(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_FABS_opcode:
            case PPC_FNEG_opcode:
            case PPC_FSQRT_opcode:
            case PPC_FSQRTS_opcode:
            case PPC_FRSP_opcode:
            case PPC_FCTIW_opcode:
            case PPC_FCTIWZ_opcode:
                {
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_FCFID_opcode:
            case PPC64_FCTIDZ_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Unary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Unary.getValue(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_FCMPO_opcode:
            case PPC_FCMPU_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 23) | (op1 << 16) | (op2 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_FMUL_opcode:
            case PPC_FMULS_opcode:
                {
                    int op0 = MIR_Binary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Binary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Binary.getValue2(p).asRegister().getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 6)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_FMADD_opcode:
            case PPC_FMADDS_opcode:
            case PPC_FMSUB_opcode:
            case PPC_FMSUBS_opcode:
            case PPC_FNMADD_opcode:
            case PPC_FNMADDS_opcode:
            case PPC_FNMSUB_opcode:
            case PPC_FNMSUBS_opcode:
            case PPC_FSEL_opcode:
                {
                    int op0 = MIR_Ternary.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Ternary.getValue1(p).getRegister().number & REG_MASK;
                    int op2 = MIR_Ternary.getValue2(p).getRegister().number & REG_MASK;
                    int op3 = MIR_Ternary.getValue3(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | (op2 << 6) | (op3 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_LWZ_opcode:
            case PPC_LBZ_opcode:
            case PPC_LHA_opcode:
            case PPC_LHZ_opcode:
            case PPC_LFD_opcode:
            case PPC_LFS_opcode:
            case PPC_LMW_opcode:
                {
                    int op0 = MIR_Load.getResult(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Load.getOffset(p).asIntConstant().value & SHORT_MASK;
                    int op2 = MIR_Load.getAddress(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | op1 | (op2 << 16)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_LD_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Load.getResult(p).getRegister().number & REG_MASK;
                    int op1 = (MIR_Load.getOffset(p).asIntConstant().value >> 2) & SHORT14_MASK;
                    int op2 = MIR_Load.getAddress(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 2) | (op2 << 16)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_LAddr_opcode:
            case PPC_LInt_opcode:
                {
                    if (VM.BuildFor32Addr) {
                        int op0 = MIR_Load.getResult(p).getRegister().number & REG_MASK;
                        int op1 = MIR_Load.getOffset(p).asIntConstant().value & SHORT_MASK;
                        int op2 = MIR_Load.getAddress(p).getRegister().number & REG_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 21) | op1 | (op2 << 16)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    } else {
                        int op0 = MIR_Load.getResult(p).getRegister().number & REG_MASK;
                        int op1 = (MIR_Load.getOffset(p).asIntConstant().value >> 2) & SHORT14_MASK;
                        int op2 = MIR_Load.getAddress(p).getRegister().number & REG_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 2) | (op2 << 16)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    }
                }
                break;
            case PPC_STW_opcode:
            case PPC_STB_opcode:
            case PPC_STH_opcode:
            case PPC_STFD_opcode:
            case PPC_STFS_opcode:
            case PPC_STMW_opcode:
                {
                    int op0 = MIR_Store.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_Store.getOffset(p).asIntConstant().value & SHORT_MASK;
                    int op2 = MIR_Store.getAddress(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | op1 | (op2 << 16)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_STWU_opcode:
            case PPC_STFDU_opcode:
            case PPC_STFSU_opcode:
                {
                    int op0 = MIR_StoreUpdate.getValue(p).getRegister().number & REG_MASK;
                    int op1 = MIR_StoreUpdate.getAddress(p).getRegister().number & REG_MASK;
                    int op2 = MIR_StoreUpdate.getOffset(p).asIntConstant().value & SHORT_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC64_STD_opcode:
                {
                    if (VM.VerifyAssertions)
                        VM._assert(VM.BuildFor64Addr);
                    int op0 = MIR_Store.getValue(p).getRegister().number & REG_MASK;
                    int op1 = (MIR_Store.getOffset(p).asIntConstant().value >> 2) & SHORT14_MASK;
                    int op2 = MIR_Store.getAddress(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 2) | (op2 << 16)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_STAddr_opcode:
                {
                    if (VM.BuildFor32Addr) {
                        int op0 = MIR_Store.getValue(p).getRegister().number & REG_MASK;
                        int op1 = MIR_Store.getOffset(p).asIntConstant().value & SHORT_MASK;
                        int op2 = MIR_Store.getAddress(p).getRegister().number & REG_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 21) | op1 | (op2 << 16)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    } else {
                        int op0 = MIR_Store.getValue(p).getRegister().number & REG_MASK;
                        int op1 = (MIR_Store.getOffset(p).asIntConstant().value >> 2) & SHORT14_MASK;
                        int op2 = MIR_Store.getAddress(p).getRegister().number & REG_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 2) | (op2 << 16)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    }
                }
                break;
            case PPC_STAddrU_opcode:
                {
                    if (VM.BuildFor32Addr) {
                        int op0 = MIR_StoreUpdate.getValue(p).getRegister().number & REG_MASK;
                        int op1 = MIR_StoreUpdate.getAddress(p).getRegister().number & REG_MASK;
                        int op2 = MIR_StoreUpdate.getOffset(p).asIntConstant().value & SHORT_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16) | op2));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    } else {
                        int op0 = MIR_StoreUpdate.getValue(p).getRegister().number & REG_MASK;
                        int op1 = (MIR_StoreUpdate.getOffset(p).asIntConstant().value >> 2) & SHORT14_MASK;
                        int op2 = MIR_StoreUpdate.getAddress(p).getRegister().number & REG_MASK;
                        machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 2) | (op2 << 16)));
                        mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    }
                }
                break;
            case PPC_MFSPR_opcode:
                {
                    int op0 = MIR_Move.getResult(p).getRegister().number & REG_MASK;
                    int op1 = phys.getSPR(MIR_Move.getValue(p).getRegister());
                    machinecodes.set(mi++, (inst | (op0 << 21) | (op1 << 16)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_MTSPR_opcode:
                {
                    int op0 = phys.getSPR(MIR_Move.getResult(p).getRegister());
                    int op1 = MIR_Move.getValue(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 21)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_MFTB_opcode:
            case PPC_MFTBU_opcode:
                {
                    int op0 = MIR_Move.getResult(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 21)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_HWSYNC_opcode:
            case PPC_SYNC_opcode:
            case PPC_ISYNC_opcode:
                {
                    machinecodes.set(mi++, inst);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_DCBST_opcode:
            case PPC_DCBT_opcode:
            case PPC_DCBTST_opcode:
            case PPC_DCBZ_opcode:
            case PPC_DCBZL_opcode:
            case PPC_DCBF_opcode:
            case PPC_ICBI_opcode:
                {
                    int op0 = MIR_CacheOp.getAddress(p).getRegister().number & REG_MASK;
                    int op1 = MIR_CacheOp.getOffset(p).getRegister().number & REG_MASK;
                    machinecodes.set(mi++, (inst | (op0 << 16) | (op1 << 11)));
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case PPC_ILLEGAL_INSTRUCTION_opcode:
                {
                    machinecodes.set(mi++, inst);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                }
                break;
            case IG_PATCH_POINT_opcode:
                {
                    BranchOperand bop = InlineGuard.getTarget(p);
                    Instruction target = bop.target;
                    if (VM.VerifyAssertions) {
                        VM._assert(target.getOpcode() == LABEL_opcode);
                    }
                    // resolve the target instruction, in LABEL_opcode,
                    // add one case for IG_PATCH_POINT
                    /* int targetOffset = */
                    resolveBranch(p, target, mi, mcOffsets);
                    machinecodes.set(mi++, NOPtemplate);
                    mcOffsets.setMachineCodeOffset(p, mi << LG_INSTRUCTION_WIDTH);
                    if (DEBUG_CODE_PATCH) {
                        VM.sysWrite("to be patched at ", mi - 1);
                        VM.sysWrite(" inst ");
                        VM.sysWriteHex(machinecodes.get(mi - 1));
                        VM.sysWriteln();
                    }
                }
                break;
            default:
                throw new OptimizingCompilerException("CodeGen", "OPCODE not implemented:", p);
        }
    }
    if (unresolvedBranches != 0) {
        throw new OptimizingCompilerException("CodeGen", " !!! Unresolved Branch Targets Exist!!! \n");
    }
    if (shouldPrint) {
        OptimizingCompiler.header("Final machine code", ir.method);
        Lister lister = new Lister(null);
        lister.addLinesForCode(machinecodes);
        lister.endAndPrintListing();
    }
    return mi;
}
Also used : CodeArray(org.jikesrvm.compilers.common.CodeArray) Lister(org.jikesrvm.compilers.common.assembler.ppc.Lister) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) MachineCodeOffsets(org.jikesrvm.compilers.opt.mir2mc.MachineCodeOffsets) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OperationNotImplementedException(org.jikesrvm.compilers.opt.OperationNotImplementedException) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 4 with CodeArray

use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.

the class JNICompiler method compile.

/**
 * Compiles a method to handle the Java to C transition and back
 * Transitioning from Java to C then back:
 * <ol>
 * <li>Set up stack frame and save non-volatile registers<li>
 * <li>Set up jniEnv - set up a register to hold JNIEnv and store
 *     the Processor in the JNIEnv for easy access</li>
 * <li>Move all native method arguments on to stack (NB at this point all
 *     non-volatile state is saved)</li>
 * <li>Record the frame pointer of the last Java frame (this) in the jniEnv</li>
 * <li>Call out to convert reference arguments to IDs</li>
 * <li>Set processor as being "in native"</li>
 * <li>Set up stack frame and registers for transition to C</li>
 * <li>Call out to C</li>
 * <li>Save result to stack</li>
 * <li>Transition back from "in native" to "in Java", take care that the
 *     Processor isn't "blocked in native", ie other processors have decided to
 *     start a GC and we're not permitted to execute Java code whilst this
 *     occurs</li>
 * <li>Convert a reference result (currently a JNI ref) into a true reference</li>
 * <li>Release JNI refs</li>
 * <li>Restore stack and place result in register</li>
 * </ol>
 *
 * @param method the method to compile
 * @return the compiled method (always a {@link JNICompiledMethod})
 */
public static synchronized CompiledMethod compile(NativeMethod method) {
    // Meaning of constant offset into frame (assuming 4byte word size):
    // Stack frame:
    // on entry          after prolog
    // 
    // high address        high address
    // |          |        |          | Caller frame
    // |          |        |          |
    // +    |arg 0     |        |arg 0     | <- firstParameterOffset
    // +    |arg 1     |        |arg 1     |
    // +    |...       |        |...       |
    // +8   |arg n-1   |        |arg n-1   | <- lastParameterOffset
    // +4   |returnAddr|        |returnAddr|
    // 0   +          +        +saved FP  + <- EBP/FP value in glue frame
    // -4   |          |        |methodID  |
    // -8   |          |        |saved EDI |
    // -C   |          |        |saved EBX |
    // -10  |          |        |saved EBP |
    // -14  |          |        |saved ENV |  (JNIEnvironment)
    // -18  |          |        |arg n-1   |  reordered args to native method
    // -1C  |          |        | ...      |  ...
    // -20  |          |        |arg 1     |  ...
    // -24  |          |        |arg 0     |  ...
    // -28  |          |        |class/obj |  required second arg to native method
    // -2C  |          |        |jni funcs |  required first arg to native method
    // -30  |          |        |          |
    // |          |        |          |
    // |          |        |          |
    // low address         low address
    // Register values:
    // EBP    - after step 1 EBP holds a frame pointer allowing easy
    // access to both this and the proceeding frame
    // ESP    - gradually floats down as the stack frame is initialized
    // S0/ECX - reference to the JNI environment after step 3
    JNICompiledMethod cm = (JNICompiledMethod) CompiledMethods.createCompiledMethod(method, CompiledMethod.JNI);
    // some size for the instruction array
    Assembler asm = new Assembler(100);
    Address nativeIP = method.getNativeIP();
    final Offset lastParameterOffset = Offset.fromIntSignExtend(2 * WORDSIZE);
    // final Offset firstParameterOffset = Offset.fromIntSignExtend(WORDSIZE+(method.getParameterWords() << LG_WORDSIZE));
    final TypeReference[] args = method.getParameterTypes();
    // (1) Set up stack frame and save non-volatile registers
    // TODO:  check and resize stack once on the lowest Java to C transition
    // on the stack.  Not needed if we use the thread original stack
    // set 2nd word of header = return address already pushed by CALL
    asm.emitPUSH_RegDisp(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset());
    // establish new frame
    if (VM.BuildFor32Addr) {
        asm.emitMOV_RegDisp_Reg(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset(), SP);
    } else {
        asm.emitMOV_RegDisp_Reg_Quad(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset(), SP);
    }
    // set first word of header: method ID
    if (VM.VerifyAssertions)
        VM._assert(STACKFRAME_METHOD_ID_OFFSET.toInt() == -WORDSIZE);
    asm.emitPUSH_Imm(cm.getId());
    // save nonvolatile registrs: EDI, EBX, EBP
    if (VM.VerifyAssertions)
        VM._assert(EDI_SAVE_OFFSET.toInt() == -2 * WORDSIZE);
    // save nonvolatile EDI register
    asm.emitPUSH_Reg(EDI);
    if (VM.VerifyAssertions)
        VM._assert(EBX_SAVE_OFFSET.toInt() == -3 * WORDSIZE);
    // save nonvolatile EBX register
    asm.emitPUSH_Reg(EBX);
    if (VM.VerifyAssertions)
        VM._assert(EBP_SAVE_OFFSET.toInt() == -4 * WORDSIZE);
    // save nonvolatile EBP register
    asm.emitPUSH_Reg(EBP);
    // Establish EBP as the framepointer for use in the rest of the glue frame
    if (VM.BuildFor32Addr) {
        asm.emitLEA_Reg_RegDisp(EBP, SP, Offset.fromIntSignExtend(4 * WORDSIZE));
    } else {
        asm.emitLEA_Reg_RegDisp_Quad(EBP, SP, Offset.fromIntSignExtend(4 * WORDSIZE));
    }
    // S0 = RVMThread.jniEnv
    if (VM.BuildFor32Addr) {
        asm.emitMOV_Reg_RegDisp(S0, THREAD_REGISTER, Entrypoints.jniEnvField.getOffset());
    } else {
        asm.emitMOV_Reg_RegDisp_Quad(S0, THREAD_REGISTER, Entrypoints.jniEnvField.getOffset());
    }
    if (VM.VerifyAssertions)
        VM._assert(JNI_ENV_OFFSET.toInt() == -5 * WORDSIZE);
    // save JNI Env for after call
    asm.emitPUSH_Reg(S0);
    if (VM.VerifyAssertions)
        VM._assert(BP_ON_ENTRY_OFFSET.toInt() == -6 * WORDSIZE);
    asm.emitPUSH_RegDisp(S0, Entrypoints.JNIEnvBasePointerOnEntryToNative.getOffset());
    // save BP into JNIEnv
    if (VM.BuildFor32Addr) {
        asm.emitMOV_RegDisp_Reg(S0, Entrypoints.JNIEnvBasePointerOnEntryToNative.getOffset(), EBP);
    } else {
        asm.emitMOV_RegDisp_Reg_Quad(S0, Entrypoints.JNIEnvBasePointerOnEntryToNative.getOffset(), EBP);
    }
    // (3) Move all native method arguments on to stack (NB at this
    // point all non-volatile state is saved)
    // (3.1) Count how many arguments could be passed in either FPRs or GPRs
    int numFprArgs = 0;
    int numGprArgs = 0;
    for (TypeReference arg : args) {
        if (arg.isFloatingPointType()) {
            numFprArgs++;
        } else if (VM.BuildFor32Addr && arg.isLongType()) {
            numGprArgs += 2;
        } else {
            numGprArgs++;
        }
    }
    // (3.2) add stack aligning padding
    if (VM.BuildFor64Addr) {
        int argsInRegisters = Math.min(numFprArgs, NATIVE_PARAMETER_FPRS.length) + Math.min(numGprArgs + 2, NATIVE_PARAMETER_GPRS.length);
        int argsOnStack = numGprArgs + numFprArgs + 2 - argsInRegisters;
        if (VM.VerifyAssertions)
            VM._assert(argsOnStack >= 0);
        if ((argsOnStack & 1) != 0) {
            // need odd alignment prior to pushes
            asm.emitAND_Reg_Imm_Quad(SP, -16);
            asm.emitPUSH_Reg(T0);
        } else {
            // need even alignment prior to pushes
            asm.emitAND_Reg_Imm_Quad(SP, -16);
        }
    }
    // (we always pass a this or a class but we only pop this)
    if (!method.isStatic()) {
        numGprArgs++;
    }
    // (3.3) Walk over arguments backwards pushing either from memory or registers
    Offset currentArg = lastParameterOffset;
    int argFpr = numFprArgs - 1;
    int argGpr = numGprArgs - 1;
    for (int i = args.length - 1; i >= 0; i--) {
        TypeReference arg = args[i];
        if (arg.isFloatType()) {
            if (argFpr < PARAMETER_FPRS.length) {
                // make space
                asm.emitPUSH_Reg(T0);
                if (SSE2_FULL) {
                    asm.emitMOVSS_RegInd_Reg(SP, (XMM) PARAMETER_FPRS[argFpr]);
                } else {
                    asm.emitFSTP_RegInd_Reg(SP, FP0);
                }
            } else {
                asm.emitPUSH_RegDisp(EBP, currentArg);
            }
            argFpr--;
        } else if (arg.isDoubleType()) {
            if (VM.BuildFor32Addr) {
                if (argFpr < PARAMETER_FPRS.length) {
                    // make space
                    asm.emitPUSH_Reg(T0);
                    // need 2 slots with 32bit addresses
                    asm.emitPUSH_Reg(T0);
                    if (SSE2_FULL) {
                        asm.emitMOVSD_RegInd_Reg(SP, (XMM) PARAMETER_FPRS[argFpr]);
                    } else {
                        asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
                    }
                } else {
                    asm.emitPUSH_RegDisp(EBP, currentArg.plus(WORDSIZE));
                    // need 2 slots with 32bit addresses
                    asm.emitPUSH_RegDisp(EBP, currentArg);
                }
            } else {
                if (argFpr < PARAMETER_FPRS.length) {
                    // make space
                    asm.emitPUSH_Reg(T0);
                    if (SSE2_FULL) {
                        asm.emitMOVSD_RegInd_Reg(SP, (XMM) PARAMETER_FPRS[argFpr]);
                    } else {
                        asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
                    }
                } else {
                    asm.emitPUSH_RegDisp(EBP, currentArg);
                }
            }
            argFpr--;
            currentArg = currentArg.plus(WORDSIZE);
        } else if (VM.BuildFor32Addr && arg.isLongType()) {
            if (argGpr < PARAMETER_GPRS.length) {
                asm.emitPUSH_Reg(PARAMETER_GPRS[argGpr - 1]);
                asm.emitPUSH_Reg(PARAMETER_GPRS[argGpr]);
            } else if (argGpr - 1 < PARAMETER_GPRS.length) {
                asm.emitPUSH_Reg(PARAMETER_GPRS[argGpr - 1]);
                asm.emitPUSH_RegDisp(EBP, currentArg);
            } else {
                asm.emitPUSH_RegDisp(EBP, currentArg.plus(WORDSIZE));
                asm.emitPUSH_RegDisp(EBP, currentArg);
            }
            argGpr -= 2;
            currentArg = currentArg.plus(WORDSIZE);
        } else {
            if (argGpr < PARAMETER_GPRS.length) {
                asm.emitPUSH_Reg(PARAMETER_GPRS[argGpr]);
            } else {
                asm.emitPUSH_RegDisp(EBP, currentArg);
            }
            argGpr--;
            if (VM.BuildFor64Addr && arg.isLongType()) {
                currentArg = currentArg.plus(WORDSIZE);
            }
        }
        currentArg = currentArg.plus(WORDSIZE);
    }
    // (3.4) push class or object argument
    if (method.isStatic()) {
        // push java.lang.Class object for klass
        Offset klassOffset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(method.getDeclaringClass().getClassForType()));
        asm.generateJTOCpush(klassOffset);
    } else {
        if (VM.VerifyAssertions)
            VM._assert(argGpr == 0);
        asm.emitPUSH_Reg(PARAMETER_GPRS[0]);
    }
    // (3.5) push a pointer to the JNI functions that will be
    // dereferenced in native code
    asm.emitPUSH_Reg(S0);
    if (jniExternalFunctionsFieldOffset != 0) {
        if (VM.BuildFor32Addr) {
            asm.emitADD_RegInd_Imm(ESP, jniExternalFunctionsFieldOffset);
        } else {
            asm.emitADD_RegInd_Imm_Quad(ESP, jniExternalFunctionsFieldOffset);
        }
    }
    // (4) Call out to convert reference arguments to IDs, set thread as
    // being "in native" and record the frame pointer of the last Java frame
    // (this) in the jniEnv
    // Encode reference arguments into a long
    int encodedReferenceOffsets = 0;
    for (int i = 0, pos = 0; i < args.length; i++, pos++) {
        TypeReference arg = args[i];
        if (arg.isReferenceType()) {
            if (VM.VerifyAssertions)
                VM._assert(pos < 32);
            encodedReferenceOffsets |= 1 << pos;
        } else if (VM.BuildFor32Addr && (arg.isLongType() || arg.isDoubleType())) {
            pos++;
        }
    }
    // Call out to JNI environment JNI entry
    if (VM.BuildFor32Addr) {
        asm.emitMOV_Reg_RegDisp(PARAMETER_GPRS[0], EBP, JNI_ENV_OFFSET);
    } else {
        asm.emitMOV_Reg_RegDisp_Quad(PARAMETER_GPRS[0], EBP, JNI_ENV_OFFSET);
    }
    asm.emitPUSH_Reg(PARAMETER_GPRS[0]);
    asm.emitMOV_Reg_Imm(PARAMETER_GPRS[1], encodedReferenceOffsets);
    asm.emitPUSH_Reg(PARAMETER_GPRS[1]);
    asm.baselineEmitLoadTIB(S0, PARAMETER_GPRS[0]);
    asm.emitCALL_RegDisp(S0, Entrypoints.jniEntry.getOffset());
    // (5) Set up stack frame and registers for transition to C
    int stackholes = 0;
    int position = 0;
    int argsPassedInRegister = 0;
    if (VM.BuildFor64Addr) {
        int gpRegistersInUse = 2;
        int fpRegistersInUse = 0;
        boolean dataOnStack = false;
        // JNI env
        asm.emitPOP_Reg(NATIVE_PARAMETER_GPRS[0]);
        // Object/Class
        asm.emitPOP_Reg(NATIVE_PARAMETER_GPRS[1]);
        argsPassedInRegister += 2;
        for (TypeReference arg : method.getParameterTypes()) {
            if (arg.isFloatType()) {
                if (fpRegistersInUse < NATIVE_PARAMETER_FPRS.length) {
                    asm.emitMOVSS_Reg_RegDisp((XMM) NATIVE_PARAMETER_FPRS[fpRegistersInUse], SP, Offset.fromIntZeroExtend(position << LG_WORDSIZE));
                    if (dataOnStack) {
                        stackholes |= 1 << position;
                    } else {
                        asm.emitPOP_Reg(T0);
                    }
                    fpRegistersInUse++;
                    argsPassedInRegister++;
                } else {
                    // no register available so we have data on the stack
                    dataOnStack = true;
                }
            } else if (arg.isDoubleType()) {
                if (fpRegistersInUse < NATIVE_PARAMETER_FPRS.length) {
                    asm.emitMOVSD_Reg_RegDisp((XMM) NATIVE_PARAMETER_FPRS[fpRegistersInUse], SP, Offset.fromIntZeroExtend(position << LG_WORDSIZE));
                    if (dataOnStack) {
                        stackholes |= 1 << position;
                    } else {
                        asm.emitPOP_Reg(T0);
                    }
                    if (VM.BuildFor32Addr)
                        asm.emitPOP_Reg(T0);
                    fpRegistersInUse++;
                    argsPassedInRegister += VM.BuildFor32Addr ? 2 : 1;
                } else {
                    // no register available so we have data on the stack
                    dataOnStack = true;
                }
            } else {
                if (gpRegistersInUse < NATIVE_PARAMETER_GPRS.length) {
                    // TODO: we can't have holes in the data that is on the stack, we need to shuffle it up
                    asm.emitMOV_Reg_RegDisp_Quad(NATIVE_PARAMETER_GPRS[gpRegistersInUse], SP, Offset.fromIntZeroExtend(position << LG_WORDSIZE));
                    if (dataOnStack) {
                        stackholes |= 1 << position;
                    } else {
                        asm.emitPOP_Reg(T0);
                    }
                    gpRegistersInUse++;
                    argsPassedInRegister++;
                } else {
                    // no register available so we have data on the stack
                    dataOnStack = true;
                }
            }
            if (dataOnStack) {
                position++;
            }
        }
        position--;
        int onStackOffset = position;
        int mask = 0;
        for (int i = position; i >= 0; i--) {
            mask = 1 << i;
            if ((stackholes & mask) != 0) {
                continue;
            }
            if (i < onStackOffset) {
                asm.emitMOV_Reg_RegDisp_Quad(T0, SP, Offset.fromIntZeroExtend(i << LOG_BYTES_IN_WORD));
                asm.emitMOV_RegDisp_Reg_Quad(SP, Offset.fromIntZeroExtend(onStackOffset << LOG_BYTES_IN_WORD), T0);
            }
            onStackOffset--;
        }
        while (onStackOffset >= 0) {
            asm.emitPOP_Reg(T0);
            onStackOffset--;
        }
    }
    // move address of native code to invoke into T0
    if (VM.BuildFor32Addr) {
        asm.emitMOV_Reg_Imm(T0, nativeIP.toInt());
    } else {
        asm.emitMOV_Reg_Imm_Quad(T0, nativeIP.toLong());
    }
    // Trap if stack alignment fails
    if (VM.ExtremeAssertions && VM.BuildFor64Addr) {
        asm.emitBT_Reg_Imm(ESP, 3);
        ForwardReference fr = asm.forwardJcc(LGE);
        asm.emitINT_Imm(3);
        fr.resolve(asm);
    }
    // make the call to native code
    asm.emitCALL_Reg(T0);
    // (7) Discard parameters on stack
    if (VM.BuildFor32Addr) {
        // throw away args, class/this ptr and env
        int argsToThrowAway = method.getParameterWords() + 2 - argsPassedInRegister;
        if (argsToThrowAway != 0) {
            asm.emitLEA_Reg_RegDisp(SP, EBP, BP_ON_ENTRY_OFFSET);
        }
    } else {
        // throw away args, class/this ptr and env (and padding)
        asm.emitLEA_Reg_RegDisp_Quad(SP, EBP, BP_ON_ENTRY_OFFSET);
    }
    // (8) Save result to stack
    final TypeReference returnType = method.getReturnType();
    if (returnType.isVoidType()) {
    // Nothing to save
    } else if (returnType.isFloatType()) {
        // adjust stack
        asm.emitPUSH_Reg(T0);
        if (VM.BuildFor32Addr) {
            asm.emitFSTP_RegInd_Reg(ESP, FP0);
        } else {
            asm.emitMOVSS_RegInd_Reg(ESP, XMM0);
        }
    } else if (returnType.isDoubleType()) {
        // adjust stack
        asm.emitPUSH_Reg(T0);
        // adjust stack
        asm.emitPUSH_Reg(T0);
        if (VM.BuildFor32Addr) {
            asm.emitFSTP_RegInd_Reg_Quad(ESP, FP0);
        } else {
            asm.emitMOVSD_RegInd_Reg(ESP, XMM0);
        }
    } else if (VM.BuildFor32Addr && returnType.isLongType()) {
        asm.emitPUSH_Reg(T0);
        asm.emitPUSH_Reg(T1);
    } else {
        // Ensure sign-extension is correct
        if (returnType.isBooleanType()) {
            asm.emitMOVZX_Reg_Reg_Byte(T0, T0);
        } else if (returnType.isByteType()) {
            asm.emitMOVSX_Reg_Reg_Byte(T0, T0);
        } else if (returnType.isCharType()) {
            asm.emitMOVZX_Reg_Reg_Word(T0, T0);
        } else if (returnType.isShortType()) {
            asm.emitMOVSX_Reg_Reg_Word(T0, T0);
        }
        asm.emitPUSH_Reg(T0);
    }
    // (9.1) reload JNIEnvironment from glue frame
    if (VM.BuildFor32Addr) {
        asm.emitMOV_Reg_RegDisp(S0, EBP, JNICompiler.JNI_ENV_OFFSET);
    } else {
        asm.emitMOV_Reg_RegDisp_Quad(S0, EBP, JNICompiler.JNI_ENV_OFFSET);
    }
    // (9.2) Reload thread register from JNIEnvironment
    if (VM.BuildFor32Addr) {
        asm.emitMOV_Reg_RegDisp(THREAD_REGISTER, S0, Entrypoints.JNIEnvSavedTRField.getOffset());
    } else {
        asm.emitMOV_Reg_RegDisp_Quad(THREAD_REGISTER, S0, Entrypoints.JNIEnvSavedTRField.getOffset());
    }
    // (9.3) Establish frame pointer to this glue method
    if (VM.BuildFor32Addr) {
        asm.emitMOV_RegDisp_Reg(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset(), EBP);
    } else {
        asm.emitMOV_RegDisp_Reg_Quad(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset(), EBP);
    }
    // result (currently a JNI ref) into a true reference, release JNI refs
    if (VM.BuildFor32Addr) {
        // 1st arg is JNI Env
        asm.emitMOV_Reg_Reg(PARAMETER_GPRS[0], S0);
    } else {
        // 1st arg is JNI Env
        asm.emitMOV_Reg_Reg_Quad(PARAMETER_GPRS[0], S0);
    }
    if (returnType.isReferenceType()) {
        // 2nd arg is ref result
        asm.emitPOP_Reg(PARAMETER_GPRS[1]);
    } else {
        // place dummy (null) operand on stack
        asm.emitXOR_Reg_Reg(PARAMETER_GPRS[1], PARAMETER_GPRS[1]);
    }
    // save JNIEnv
    asm.emitPUSH_Reg(S0);
    // push arg 1
    asm.emitPUSH_Reg(S0);
    // push arg 2
    asm.emitPUSH_Reg(PARAMETER_GPRS[1]);
    // Do the call
    asm.baselineEmitLoadTIB(S0, S0);
    asm.emitCALL_RegDisp(S0, Entrypoints.jniExit.getOffset());
    // restore JNIEnv
    asm.emitPOP_Reg(S0);
    // place result in register
    if (returnType.isVoidType()) {
    // Nothing to save
    } else if (returnType.isReferenceType()) {
    // value already in register
    } else if (returnType.isFloatType()) {
        if (SSE2_FULL) {
            asm.emitMOVSS_Reg_RegInd(XMM0, ESP);
        } else {
            asm.emitFLD_Reg_RegInd(FP0, ESP);
        }
        // adjust stack
        asm.emitPOP_Reg(T0);
    } else if (returnType.isDoubleType()) {
        if (SSE2_FULL) {
            asm.emitMOVSD_Reg_RegInd(XMM0, ESP);
        } else {
            asm.emitFLD_Reg_RegInd_Quad(FP0, ESP);
        }
        // adjust stack
        asm.emitPOP_Reg(T0);
        // adjust stack
        asm.emitPOP_Reg(T0);
    } else if (VM.BuildFor32Addr && returnType.isLongType()) {
        asm.emitPOP_Reg(T0);
        asm.emitPOP_Reg(T1);
    } else {
        asm.emitPOP_Reg(T0);
    }
    // saved previous native BP
    asm.emitPOP_Reg(EBX);
    if (VM.BuildFor32Addr) {
        asm.emitMOV_RegDisp_Reg(S0, Entrypoints.JNIEnvBasePointerOnEntryToNative.getOffset(), EBX);
    } else {
        asm.emitMOV_RegDisp_Reg_Quad(S0, Entrypoints.JNIEnvBasePointerOnEntryToNative.getOffset(), EBX);
    }
    // throw away JNI env
    asm.emitPOP_Reg(EBX);
    // restore non-volatile EBP
    asm.emitPOP_Reg(EBP);
    // restore non-volatile EBX
    asm.emitPOP_Reg(EBX);
    // restore non-volatile EDI
    asm.emitPOP_Reg(EDI);
    // throw away cmid
    asm.emitPOP_Reg(S0);
    asm.emitPOP_RegDisp(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset());
    // pop parameters from stack (Note that parameterWords does not include "this")
    if (method.isStatic()) {
        asm.emitRET_Imm(method.getParameterWords() << LG_WORDSIZE);
    } else {
        asm.emitRET_Imm((method.getParameterWords() + 1) << LG_WORDSIZE);
    }
    CodeArray code = asm.getMachineCodes();
    cm.compileComplete(code);
    return cm;
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference) CodeArray(org.jikesrvm.compilers.common.CodeArray) Address(org.vmmagic.unboxed.Address) XMM(org.jikesrvm.ia32.RegisterConstants.XMM) Assembler(org.jikesrvm.compilers.common.assembler.ia32.Assembler) TypeReference(org.jikesrvm.classloader.TypeReference) JNICompiledMethod(org.jikesrvm.jni.JNICompiledMethod) Offset(org.vmmagic.unboxed.Offset)

Example 5 with CodeArray

use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.

the class SpecializedMethodPool method growSpecializedMethods.

/**
 * Increase the capacity of the internal data structures to track
 * specialized methods.
 */
public static void growSpecializedMethods() {
    int org_length = specializedMethods.length;
    int new_length = 2 * org_length;
    CodeArray[] temp = new CodeArray[new_length];
    for (int i = 0; i < org_length; i++) {
        temp[i] = specializedMethods[i];
    }
    specializedMethods = temp;
}
Also used : CodeArray(org.jikesrvm.compilers.common.CodeArray) Entrypoint(org.vmmagic.pragma.Entrypoint)

Aggregations

CodeArray (org.jikesrvm.compilers.common.CodeArray)18 Address (org.vmmagic.unboxed.Address)6 Offset (org.vmmagic.unboxed.Offset)6 RVMClass (org.jikesrvm.classloader.RVMClass)4 RVMMethod (org.jikesrvm.classloader.RVMMethod)4 TIB (org.jikesrvm.objectmodel.TIB)4 Entrypoint (org.vmmagic.pragma.Entrypoint)4 NoInline (org.vmmagic.pragma.NoInline)4 RVMType (org.jikesrvm.classloader.RVMType)3 TypeReference (org.jikesrvm.classloader.TypeReference)3 FileOutputStream (java.io.FileOutputStream)2 IOException (java.io.IOException)2 PrintStream (java.io.PrintStream)2 TreeSet (java.util.TreeSet)2 RVMArray (org.jikesrvm.classloader.RVMArray)2 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)2 Interruptible (org.vmmagic.pragma.Interruptible)2 BufferedOutputStream (java.io.BufferedOutputStream)1 BufferedWriter (java.io.BufferedWriter)1 OutputStreamWriter (java.io.OutputStreamWriter)1