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();
}
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");
}
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;
}
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;
}
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;
}
Aggregations