/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.common.assembler.cellspu; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Random; import org.jikesrvm.SubordinateArchitecture; import org.jikesrvm.VM; import org.jikesrvm.VM_Services; import org.jikesrvm.SubordinateArchitecture.VM_TrapConstants; import org.jikesrvm.compilers.baseline.VM_BaselineCompiler; import org.jikesrvm.compilers.baseline.cellspu.VM_Compiler; import org.jikesrvm.compilers.common.assembler.VM_AbstractAssembler; import org.jikesrvm.compilers.common.assembler.VM_ForwardReference; import org.jikesrvm.compilers.common.assembler.cellspu.VM_AssemblerShortBranch; import org.jikesrvm.cellspu.VM_BaselineConstants; import org.jikesrvm.cellspu.VM_MachineCode; import org.jikesrvm.cellspu.VM_Disassembler; import org.vmmagic.pragma.NoInline; import org.vmmagic.unboxed.Offset; /** * Machine code generators: * * Corresponding to a Cell SPU assembler instruction of the form * xx A,B,C * there will be a method * void emitXX (int A, int B, int C). * * The emitXX method appends this instruction to an VM_MachineCode object. * * mIP will be incremented to point to the next machine instruction. * * Machine code generators: */ public abstract class VM_Assembler extends VM_AbstractAssembler implements VM_BaselineConstants, VM_AssemblerConstants { /** Machine code being assembled */ private final VM_MachineCode mc; /** Debug output? */ private final boolean shouldPrint; /** // VM_Baseline compiler instance for this assembler. May be null. */ final VM_Compiler compiler; /** current machine code instruction */ private int mIP; public VM_Assembler(int length) { this(length, false, null); } public VM_Assembler(int length, boolean sp, VM_Compiler comp) { if (VM.VerifyAssertions) VM._assert(S3 <= LAST_SCRATCH_GPR); // need 4 scratch mc = new SubordinateArchitecture.VM_MachineCode(); shouldPrint = sp; compiler = comp; mIP = 0; } public VM_Assembler(int length, boolean sp) { this(length, sp, null); } public static boolean fits(int val, int bits) { val = val >> (bits - 1); return (val == 0 || val == -1); } public static boolean fitsU(int val, int bits) { val = val >> (bits); return (val == 0); } @NoInline public void noteBytecode(int i, String bcode) { String s1 = VM_Services.getHexString(mIP << LG_INSTRUCTION_WIDTH, true); VM.sysWrite(s1 + ": [" + i + "] " + bcode + "\n"); } @NoInline public void noteBytecode(int i, String bcode, int x) { noteBytecode(i, bcode + " " + x); } @NoInline public void noteBytecode(int i, String bcode, long x) { noteBytecode(i, bcode + " " + x); } @NoInline public void noteBytecode(int i, String bcode, Object o) { noteBytecode(i, bcode + " " + o); } @NoInline public void noteBytecode(int i, String bcode, int x, int y) { noteBytecode(i, bcode + " " + x + " " + y); } @NoInline public void noteBranchBytecode(int i, String bcode, int off, int bt) { noteBytecode(i, bcode + " " + off + " [" + bt + "] "); } @NoInline public void noteTableswitchBytecode(int i, int l, int h, int d) { noteBytecode(i, "tableswitch [" + l + "--" + h + "] " + d); } @NoInline public void noteLookupswitchBytecode(int i, int n, int d) { noteBytecode(i, "lookupswitch [<" + n + ">]" + d); } /* Handling backward branch references */ public int getMachineCodeIndex() { return mIP; } /* Handling forward branch references */ VM_ForwardReference forwardRefs = null; /* call before emiting code for the branch */ final void reserveForwardBranch(int where) { VM_ForwardReference fr = new VM_ForwardReference.UnconditionalBranch(mIP, where); forwardRefs = VM_ForwardReference.enqueue(forwardRefs, fr); } /* call before emiting code for the branch */ final void reserveForwardConditionalBranch(int where) { emitNOP(); VM_ForwardReference fr = new VM_ForwardReference.ConditionalBranch(mIP, where); forwardRefs = VM_ForwardReference.enqueue(forwardRefs, fr); } /* call before emiting code for the branch */ final void reserveShortForwardConditionalBranch(int where) { VM_ForwardReference fr = new VM_ForwardReference.ConditionalBranch(mIP, where); forwardRefs = VM_ForwardReference.enqueue(forwardRefs, fr); } /* call before emiting data for the case branch */ final void reserveForwardCase(int where) { VM_ForwardReference fr = new VM_ForwardReference.SwitchCase(mIP, where); forwardRefs = VM_ForwardReference.enqueue(forwardRefs, fr); } /* call before emiting code for the target */ public final void resolveForwardReferences(int label) { if (forwardRefs == null) return; forwardRefs = VM_ForwardReference.resolveMatching(this, forwardRefs, label); } public final void patchShortBranch(int sourceMachinecodeIndex) { int delta = mIP - sourceMachinecodeIndex; int instr = mc.getInstruction(sourceMachinecodeIndex); if ((delta >>> 15) == 0) { // delta (positive) fits in 16 bits instr |= (delta << 7); mc.putInstruction(sourceMachinecodeIndex, instr); } else { throw new InternalError("Long offset doesn't fit in short branch\n"); } } public final void patchConditionalBranch(int sourceMachinecodeIndex) { patchShortBranch(sourceMachinecodeIndex); } public final void patchUnconditionalBranch(int sourceMachinecodeIndex) { patchShortBranch(sourceMachinecodeIndex); } public final void registerLoadReturnAddress(int bReturn) { VM_ForwardReference r = new VM_ForwardReference.LoadReturnAddress(mIP, bReturn); forwardRefs = VM_ForwardReference.enqueue(forwardRefs, r); } public final VM_ForwardReference generatePendingJMP(int bTarget) { return this.emitForwardBR(); } public final void patchSwitchCase(int sourceMachinecodeIndex) { int delta = (mIP - sourceMachinecodeIndex) << 2; // correction is number of bytes of source off switch base int correction = (int) mc.getInstruction(sourceMachinecodeIndex); int offset = delta + correction; mc.putInstruction(sourceMachinecodeIndex, offset); } public final void patchLoadReturnAddress(int sourceIndex) { // TODO - patchLoadReturnAddress VM._assert(NOT_REACHED); } /* =============================================================== * machine instructions * =============================================================== */ /* * Load / Store Instructions * ________________________________ */ /** Load QuadWord */ static final int LQDtemplate = 0x34 << 24; /** Load QuadWord */ public final void emitLQD(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = LQDtemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Load QuadWord (x-form) */ static final int LQXtemplate = 0x1c4 << 21; /** Load QuadWord (x-form) */ public final void emitLQX(int RT, int RA, int RB) { int mi = LQXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Load QuadWord (a-form) */ static final int LQAtemplate = 0x61 << 23; /** Load QuadWord (a-form) */ public final void emitLQA(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 16)); int mi = LQAtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Load QuadWord Instruction Relative (a-form) */ static final int LQRtemplate = 0x67 << 23; /** Load QuadWord Instruction Relative (a-form) */ public final void emitLQR(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 16)); int mi = LQRtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Store QuadWord */ static final int STQDtemplate = 0x24 << 24; /** Store QuadWord */ public final void emitSTQD(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = STQDtemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Store QuadWord (x-form) */ static final int STQXtemplate = 0x144 << 21; /** Store QuadWord (x-form) */ public final void emitSTQX(int RT, int RA, int RB) { int mi = STQXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Store QuadWord (a-form) */ static final int STQAtemplate = 0x41 << 23; /** Store QuadWord (a-form) */ public final void emitSTQA(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 16)); int mi = STQAtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Store QuadWord Instruction Relative (a-form) */ static final int STQRtemplate = 0x47 << 23; /** Store QuadWord Instruction Relative (a-form) */ public final void emitSTQR(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 16)); int mi = STQRtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Byte Insertion (d-form) */ static final int CBDtemplate = 0x1f4 << 21; /** Generate Controls for Byte Insertion (d-form) */ public final void emitCBD(int RT, int RA, int immed) { int mi = CBDtemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Byte Insertion (x-form) */ static final int CBXtemplate = 0x1d4 << 21; /** Generate Controls for Byte Insertion (x-form) */ public final void emitCBX(int RT, int RA, int RB) { int mi = CBXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Halfword Insertion (d-form) */ static final int CHDtemplate = 0x1f5 << 21; /** Generate Controls for Halfword Insertion (d-form) */ public final void emitCHD(int RT, int RA, int immed) { int mi = CHDtemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Halfword Insertion (x-form) */ static final int CHXtemplate = 0x1d5 << 21; /** Generate Controls for Halfword Insertion (x-form) */ public final void emitCHX(int RT, int RA, int RB) { int mi = CHXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Word Insertion (d-form) */ static final int CWDtemplate = 0x1f6 << 21; /** Generate Controls for Word Insertion (d-form) */ public final void emitCWD(int RT, int RA, int immed) { int mi = CWDtemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Word Insertion (x-form) */ static final int CWXtemplate = 0x1d6 << 21; /** Generate Controls for Word Insertion (x-form) */ public final void emitCWX(int RT, int RA, int RB) { int mi = CWXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Doubleword Insertion (d-form) */ static final int CDDtemplate = 0x1f7 << 21; /** Generate Controls for Doubleword Insertion (d-form) */ public final void emitCDD(int RT, int RA, int immed) { int mi = CDDtemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Generate Controls for Doubleword Insertion (x-form) */ static final int CDXtemplate = 0x1d7 << 21; /** Generate Controls for Doubleword Insertion (x-form) */ public final void emitCDX(int RT, int RA, int RB) { int mi = CDXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** * Generate a set of instructions which load the byte at the address in * addrReg (aligned to 16 Bytes) + offsetReg into the preferred slot of the target * register. * Destroys S0 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadByte(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && offsetReg != S0); if (VM.VerifyAssertions) VM._assert(destReg != offsetReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, offsetReg); // rotate back to preferred byte slot emitROTQBYI(destReg, destReg, 13); // sign extend emitXSBH(S0, destReg); emitXSHW(destReg, S0); } /** * Generate a set of instructions which load the byte at the address in * addrReg + offsetReg into the preferred slot of the target register. * Destroys S0 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadByteUnaligned(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg && destReg != addrReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, offsetReg); emitROTQBY(destReg, destReg, addrReg); // rotate back to preferred byte slot emitROTQBYI(destReg, destReg, 13); // sign extend emitXSBH(S0, destReg); emitXSHW(destReg, S0); } /** * Generate a set of instructions which load the byte at the address in * addrReg into the preferred slot of the target register. * Destroys S0 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) */ public final void emitLoadByteUnaligned(int destReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(destReg != addrReg); emitLQD(destReg, addrReg, 0); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); // rotate back to preferred byte slot emitROTQBYI(destReg, destReg, 13); // sign extend emitXSBH(S0, destReg); emitXSHW(destReg, S0); } /** * Generate a set of instructions which load the byte at the address in * addrReg (aligned to 16 Bytes) + offsetReg into the preferred slot of the target * register. * Destroys S0 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadByte(int destReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { emitLQD(destReg, addrReg, offsetI >> 4); // rotate to preferred slot emitROTQBYI(destReg, destReg, offsetI - 3); // sign extend emitXSBH(S0, destReg); emitXSHW(destReg, S0); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offsetI); emitLoadByte(destReg, addrReg, S0); } } /** * Generate a set of instructions which load the byte at the address in * addrReg + offsetReg into the preferred slot of the target * register. * Destroys S0 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadByteUnaligned(int destReg, int addrReg, Offset offset) { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offset.toInt()); emitLoadByteUnaligned(destReg, addrReg, S0); } /** * Generate a set of instructions which load the unsigned char at the address in * addrReg (aligned to 16 Bytes) + offsetReg into the preferred slot of the target * register. * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadChar(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, offsetReg); // rotate back to preferred char slot and mask emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); } /** * Generate a set of instructions which load the unsigned char at the address in * addrReg + offsetReg into the preferred slot of the target * register. * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadCharUnaligned(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg && destReg != addrReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); emitROTQBY(destReg, destReg, offsetReg); // rotate back to preferred char slot and mask emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); } /** * Generate a set of instructions which load the unsigned char at the address in * addrReg into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadCharUnaligned(int destReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(destReg != addrReg); emitLQD(destReg, addrReg, 0); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); // rotate back to preferred char slot and mask emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); } /** * Generate a set of instructions which load the unsigned char at the address in * addrReg (aligned to 16 Bytes) + offsetReg into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadChar(int destReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { emitLQD(destReg, addrReg, offsetI >> 4); // rotate to preferred slot emitROTQBYI(destReg, destReg, offsetI); // rotate back to preferred char slot and mask emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offsetI); emitLoadChar(destReg, addrReg, S0); } } /** * Generate a set of instructions which load the unsigned char at the address in * addrReg + offsetReg into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadCharUnaligned(int destReg, int addrReg, Offset offset) { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offset.toInt()); emitLoadCharUnaligned(destReg, addrReg, S0); } /** * Generate a set of instructions which load the short at the address in * addrReg (aligned to 16 Bytes) + offsetReg into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadShort(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, offsetReg); emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); // sign extend emitXSHW(destReg, destReg); } /** * Generate a set of instructions which load the short at the address in * addrReg + offsetReg into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * Destroys S3 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadShortUnaligned(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg && destReg != addrReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); emitROTQBY(destReg, destReg, offsetReg); emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); // sign extend emitXSHW(destReg, destReg); } /** * Generate a set of instructions which load the short at the address in * addrReg into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * Destroys S3 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadShortUnaligned(int destReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(destReg != addrReg); emitLQD(destReg, addrReg, 0); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); emitROTMI(destReg, destReg, -(2 * BITS_IN_BYTE)); // sign extend emitXSHW(destReg, destReg); } /** * Generate a set of instructions which load the short at the address in * addrReg (aligned to 16 Bytes) + offsetReg into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * Destroys S3 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadShort(int destReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { emitLQD(destReg, addrReg, offsetI >> 4); if (offsetI != 0) { emitROTQBYI(destReg, destReg, offsetI - 2); } else { emitROTQBYI(destReg, destReg, 14); } // sign extend emitXSHW(destReg, destReg); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offsetI); emitLoadShort(destReg, addrReg, S0); } } /** * Generate a set of instructions which load the short at the address in * addrReg + offsetReg into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * Destroys S3 * * @param destReg Register into which the word will be loaded (as an int word) * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadShortUnaligned(int destReg, int addrReg, Offset offset) { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offset.toInt()); emitLoadShortUnaligned(destReg, addrReg, S0); } /** * Generate a set of instructions which load the word at the address in * addrReg into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes */ public final void emitLoad(int destReg, int addrReg) { emitLQD(destReg, addrReg, 0); } /** * Generate a set of instructions which load the word at the address in * addrReg + offsetReg into the preferred slot of the target * register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadUnaligned(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg && destReg != addrReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); emitROTQBY(destReg, destReg, offsetReg); } /** * Generate a set of instructions which load the word at the address in * addrReg into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoadUnaligned(int destReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(destReg != addrReg); emitLQD(destReg, addrReg, 0); // rotate to preferred slot emitROTQBY(destReg, destReg, addrReg); } /** * Generate a set of instructions which load the word/double word at the address in * addrReg (aligned to 16 Bytes) + offsetReg (aligned to word) into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes */ public final void emitLoad(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(destReg != offsetReg); emitLQX(destReg, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, destReg, offsetReg); } /** * Generate a set of instructions which load the word/double word at the address in * addrReg (aligned to 16 Bytes) + offsetReg (aligned to word) into the preferred slot of the target * register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offsetReg Register which contains offset of address being loaded in bytes * @param origQuad Register which will contain the orignal Quad for a later store a */ public final void emitLoad(int destReg, int addrReg, int offsetReg, int origQuad) { if (VM.VerifyAssertions) VM._assert(offsetReg != origQuad); emitLQX(origQuad, addrReg, offsetReg); // rotate to preferred slot emitROTQBY(destReg, origQuad, offsetReg); } /** * Generate a set of instructions which load the word at the address in * addrReg + offset (aligned to 16 bytes) into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offset Immediate offset of address being loaded in bytes */ public final void emitLoad(int destReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { emitLQD(destReg, addrReg, offsetI >> 4); // check whether offset is non-aligned if ((offsetI & (BYTES_IN_QUAD - 1)) != 0) { emitROTQBYI(destReg, destReg, offsetI); } } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offsetI); emitLoad(destReg, addrReg, S0); } } /** * Generate a set of instructions which load the word at the address in * addrReg + offset into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offset Immediate offset of address being loaded in bytes */ public final void emitLoadUnaligned(int destReg, int addrReg, Offset offset) { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offset.toInt()); emitLoadUnaligned(destReg, addrReg, S0); } /** * Generate a set of instructions which load the word at the address in * addrReg + offset (aligned to 16 bytes) into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param offset Immediate offset of address being loaded in bytes * @param origQuad Used to store the orignal quad word for a later store */ public final void emitLoad(int destReg, int addrReg, Offset offset, int origQuad) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { emitLQD(origQuad, addrReg, offsetI >> 4); emitROTQBYI(destReg, origQuad, offsetI); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && origQuad != S0); emitILW(S0, offsetI); emitLoad(destReg, addrReg, S0, origQuad); } } /** * Generate a set of instructions which load the word at the address in * addrReg (aligned to 16 bytes) + offset (aligned to double) into the preferred slot * of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Immediate offset of address being loaded in bytes */ public final void emitLoadDouble(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(offsetReg != destReg); emitLQX(destReg, addrReg, offsetReg); // rotate to correct offset emitROTQBY(destReg, destReg, offsetReg); } /** * Generate a set of instructions which load the word at the address in * addrReg + offset into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Immediate offset of address being loaded in bytes */ public final void emitLoadDoubleUnaligned(int destReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(offsetReg != destReg && addrReg != destReg); emitLQX(destReg, addrReg, offsetReg); // rotate to correct offset emitROTQBY(destReg, destReg, addrReg); emitROTQBY(destReg, destReg, offsetReg); } /** * Generate a set of instructions which load the word at the address in * addrReg into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offsetReg Immediate offset of address being loaded in bytes */ public final void emitLoadDoubleUnaligned(int destReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(addrReg != destReg); emitLQD(destReg, addrReg, 0); // rotate to correct offset emitROTQBY(destReg, destReg, addrReg); } /** * Generate a set of instructions which load the word at the address in * addrReg (aligned to 16 bytes) + offset into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offset Immediate offset of address being loaded in bytes */ public final void emitLoadDouble(int destReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (VM.VerifyAssertions) VM._assert((offsetI & (BYTES_IN_DOUBLE - 1)) == 0); if (fits((offsetI >> 4), 10)) { emitLQD(destReg, addrReg, offsetI >> 4); // check whether offset is non-aligned if ((offsetI & (BYTES_IN_QUAD - 1)) != 0) { emitROTQBYI(destReg, destReg, offsetI); } } else { if (VM.VerifyAssertions) VM._assert(addrReg != S5); emitILW(S5, offsetI); emitLoadDouble(destReg, addrReg, S5); } } /** * Generate a set of instructions which load the word at the address in * addrReg (aligned to 16 bytes) + offset into the preferred slot of the target register. * Note: This only rotates word based upon offset alignment into preferred slot, * so ensure addrReg is aligned or you want the full quadword. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes * @param offset Immediate offset of address being loaded in bytes */ public final void emitLoadDoubleUnaligned(int destReg, int addrReg, Offset offset) { if (VM.VerifyAssertions) VM._assert(addrReg != S5); emitILW(S5, offset.toInt()); emitLoadDoubleUnaligned(destReg, addrReg, S5); } /** * Generate a set of instructions which load the quadword at the address in * addrReg (aligned to 16 bytes) into the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) */ public final void emitLoadQuad(int destReg, int addrReg) { emitLQD(destReg, addrReg, 0); } /** * Generate a set of instructions which load the word at the address in * addrReg + offsetReg (aligned to 16 bytes) into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param addrReg Register which contains the offset of address to be loaded in bytes (aligned to 16 bytes) */ public final void emitLoadQuad(int destReg, int addrReg, int offsetReg) { emitLQX(destReg, addrReg, offsetReg); } /** * Generate a set of instructions which load the word at the address in * addrReg + offsetReg (aligned to 16 bytes) into the preferred slot of the target register. * * @param destReg Register into which the word will be loaded * @param addrReg Register which contains the address to be loaded in bytes (aligned to 16 bytes) * @param addrReg Register which contains the offset of address to be loaded in bytes (aligned to 16 bytes) */ public final void emitLoadQuad(int destReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (VM.VerifyAssertions) VM._assert((offsetI & (BYTES_IN_QUAD - 1)) == 0); if (fits((offsetI >> 4), 10)) { emitLQD(destReg, addrReg, offsetI); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0); emitILW(S0, offsetI); emitLQX(destReg, addrReg, S0); } } /** * Generate a set of instructions which stores the byte in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offsetReg Register which contains offset of address being stored in bytes */ public final void emitStoreByte(int sourceReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2 && offsetReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3 && offsetReg != S3); emitLQX(S2, addrReg, offsetReg); emitCBX(S3, addrReg, offsetReg); emitSHUFB(S2, sourceReg, S2, S3); emitSTQX(S2, addrReg, offsetReg); } /** * Generate a set of instructions which stores the byte in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offsetReg Register which contains offset of address being stored in bytes */ public final void emitStoreByte(int sourceReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3); emitLQD(S2, addrReg, offsetI >> 4); emitCBD(S3, addrReg, offsetI); emitSHUFB(S2, sourceReg, S2, S3); emitSTQD(S2, addrReg, offsetI >> 4); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && sourceReg != S0); emitILW(S0, offsetI); emitStoreByte(sourceReg, addrReg, S0); } } /** * Generate a set of instructions which stores the short in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offsetReg Register which contains offset of address being stored in bytes */ public final void emitStoreShort(int sourceReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2 && offsetReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3 && offsetReg != S3); emitLQX(S2, addrReg, offsetReg); emitCHX(S3, addrReg, offsetReg); emitSHUFB(S2, sourceReg, S2, S3); emitSTQX(S2, addrReg, offsetReg); } /** * Generate a set of instructions which stores the short in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offsetReg Register which contains offset of address being stored in bytes */ public final void emitStoreShort(int sourceReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3); emitLQD(S2, addrReg, offsetI >> 4); emitCHD(S3, addrReg, offsetI); emitSHUFB(S2, sourceReg, S2, S3); emitSTQD(S2, addrReg, offsetI >> 4); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && sourceReg != S0); emitILW(S0, offsetI); emitStoreShort(sourceReg, addrReg, S0); } } /** * Generate a set of instructions which stores the word in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offset Immediate offset of address being loaded in bytes */ public final void emitStore(int sourceReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3); emitLQD(S2, addrReg, 0); emitCWD(S3, addrReg, 0); emitSHUFB(S2, sourceReg, S2, S3); emitSTQD(S2, addrReg, 0); } /** * Generate a set of instructions which stores the word in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offsetReg Register which contains offset of address being stored in bytes */ public final void emitStore(int sourceReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2 && offsetReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3 && offsetReg != S3); emitLQX(S2, addrReg, offsetReg); emitCWX(S3, addrReg, offsetReg); emitSHUFB(S2, sourceReg, S2, S3); emitSTQX(S2, addrReg, offsetReg); } /** * Generate a set of instructions which stores the word in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offsetReg Register which contains offset of address being stored in bytes * @param origQuad Register containing the original quad word */ public final void emitStore(int sourceReg, int addrReg, int offsetReg, int origQuad) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2 && offsetReg != S2 && origQuad != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3 && offsetReg != S3 && origQuad != S2); emitCWX(S3, addrReg, offsetReg); emitSHUFB(S2, sourceReg, origQuad, S3); emitSTQX(S2, addrReg, offsetReg); } /** * Generate a set of instructions which stores the word in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offset Immediate offset of address being stored in bytes */ public final void emitStore(int sourceReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3); emitLQD(S2, addrReg, (offsetI >> 4)); emitCWD(S3, addrReg, offsetI); emitSHUFB(S2, sourceReg, S2, S3); emitSTQD(S2, addrReg, (offsetI >> 4)); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && sourceReg != S0); emitILW(S0, offsetI); emitStore(sourceReg, addrReg, S0); } } /** * Generate a set of instructions which stores the word in the preferred slot of * the source register at the address in addrReg. * Note: Destroys S2 and S3 and perhaps S0 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes * @param offset Immediate offset of address being stored in bytes * @param origQuad Register storing the original quad word */ public final void emitStore(int sourceReg, int addrReg, Offset offset, int origQuad) { int offsetI = offset.toInt(); if (fits((offsetI >> 4), 10)) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2 && origQuad != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3 && origQuad != S2); emitCWD(S3, addrReg, offsetI); emitSHUFB(S2, sourceReg, origQuad, S3); emitSTQD(S2, addrReg, (offsetI >> 4)); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && sourceReg != S0 && origQuad != S0); emitILW(S0, offsetI); emitStore(sourceReg, addrReg, S0, origQuad); } } /** * Generate a set of instructions which stores the DoubleWord in the preferred slot of * the source register at the address in addrReg. Note: addrReg must be aligned to * double word * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes (must be aligned) */ public final void emitStoreDouble(int sourceReg, int addrReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3); emitLQD(S2, addrReg, 0); emitCDD(S3, addrReg, 0); emitSHUFB(S2, sourceReg, S2, S3); emitSTQD(S2, addrReg, 0); } /** * Generate a set of instructions which stores the DoubleWord in the preferred slot of * the source register at the address in addrReg. Note: addrReg must be aligned to * to quadword and offsetReg must be aligned double word * Note: Destroys S2 and S3 * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes (must be aligned) * @param offsetReg Register which contains offset of address being stored in bytes (must be aligned) */ public final void emitStoreDouble(int sourceReg, int addrReg, int offsetReg) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2 && offsetReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3 && offsetReg != S3); emitLQX(S2, addrReg, offsetReg); emitCDX(S3, addrReg, offsetReg); emitSHUFB(S2, sourceReg, S2, S3); emitSTQX(S2, addrReg, offsetReg); } /** * Generate a set of instructions which stores the DoubleWord in the preferred slot of * the source register at the address in addrReg. Note: addrReg and offset must be aligned to * double word. * * @param sourceReg Register which contains data to be written * @param addrReg Register which contains the address to be stored in bytes (must be aligned) * @param offset Immediate offset of address being stored in bytes */ public final void emitStoreDouble(int sourceReg, int addrReg, Offset offset) { int offsetI = offset.toInt(); if (VM.VerifyAssertions) VM._assert((offsetI & (BYTES_IN_DOUBLE - 1)) == 0); if (fits((offsetI >> 4), 10)) { if (VM.VerifyAssertions) VM._assert(addrReg != S2 && sourceReg != S2); if (VM.VerifyAssertions) VM._assert(addrReg != S3 && sourceReg != S3); emitLQD(S2, addrReg, (offsetI >> 4)); emitCDD(S3, addrReg, offsetI); emitSHUFB(S2, sourceReg, S2, S3); emitSTQD(S2, addrReg, (offsetI >> 4)); } else { if (VM.VerifyAssertions) VM._assert(addrReg != S0 && sourceReg != S0); emitILW(S0, offsetI); emitStoreDouble(sourceReg, addrReg, S0); } } /* * Constant-Formation Instructions * ________________________________ */ /** Emit a constant quad word into the datastream for loading in code */ public final void emitConstantQuad(int w1, int w2, int w3, int w4) { if (VM.VerifyAssertions) VM._assert((mIP % 4) == 0); mc.addInstruction(w1); mc.addInstruction(w2); mc.addInstruction(w3); mc.addInstruction(w4); mIP += 4; } public final void emitILW(int RT, int val) { if (fits(val, 16)) { emitIL(RT, val); } else { emitILHU(RT, (val >>> 16)); emitIOHL(RT, val & 0xFFFF); } } /** immediate load halfword */ static final int ILHtemplate = 0x83 << 23; /** immediate load halfword */ public final void emitILH(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 16)); int mi = ILHtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** immediate load halfword upper */ static final int ILHUtemplate = 0x82 << 23; /** immediate load halfword upper */ public final void emitILHU(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 16)); int mi = ILHUtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** immediate load word */ static final int ILtemplate = 0x81 << 23; /** immediate load word */ public final void emitIL(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 16)); int mi = ILtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** immediate load address */ static final int ILAtemplate = 0x21 << 25; /** immediate load address */ public final void emitILA(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 18)); int mi = ILAtemplate | (0x3ffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitILA(int RT, int relative_address, int label) { if (relative_address == 0) { reserveForwardBranch(label); } else { relative_address -= mIP; } emitILA(RT, relative_address); } /** immediate Or Halfword Lower */ static final int IOHLtemplate = 0xc1 << 23; /** immediate Or Halfword Lower */ public final void emitIOHL(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 16)); int mi = IOHLtemplate | (0xffff & immed) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /* * Integer and Logical Instructions * ________________________________ */ /** add halfword */ static final int AHtemplate = 0xc8 << 21; /** add halfword */ public final void emitAH(int RT, int RA, int RB) { int mi = AHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** add halfword immediate */ static final int AHItemplate = 0x1d << 24; /** add halfword immediate */ public final void emitAHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = AHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** add word */ static final int Atemplate = 0xc0 << 21; /** add word */ public final void emitA(int RT, int RA, int RB) { int mi = Atemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** add word immediate */ static final int AItemplate = 0x1c << 24; /** add word immediate */ public final void emitAI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = AItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** subtract halfword */ static final int SFHtemplate = 0x48 << 21; /** subtract halfword */ public final void emitSFH(int RT, int RA, int RB) { int mi = SFHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // subtract halfword immediate static final int SFHItemplate = 0xd << 24; public final void emitSFHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = SFHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // subtract word static final int SFtemplate = 0x40 << 21; public final void emitSF(int RT, int RA, int RB) { int mi = SFtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // subtract word immediate static final int SFItemplate = 0xc << 24; public final void emitSFI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = SFItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** add word extended */ static final int ADDXtemplate = 0x340 << 21; /** add word extended */ public final void emitADDX(int RT, int RA, int RB) { int mi = ADDXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** carry generate */ static final int CGtemplate = 0xc2 << 21; /** carry generate */ public final void emitCG(int RT, int RA, int RB) { int mi = CGtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** subtract from extended */ static final int SFXtemplate = 0x341 << 21; /** subtract from extended */ public final void emitSFX(int RT, int RA, int RB) { int mi = SFXtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** borrow generate */ static final int BGtemplate = 0x42 << 21; /** carry generate */ public final void emitBG(int RT, int RA, int RB) { int mi = BGtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Multiply static final int MPYtemplate = 0x3c4 << 21; public final void emitMPY(int RT, int RA, int RB) { int mi = MPYtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Unsigned Multiply */ static final int MPYUtemplate = 0x3cc << 21; /** Unsigned Multiply */ public final void emitMPYU(int RT, int RA, int RB) { int mi = MPYUtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Multiply High */ static final int MPYHtemplate = 0x3c5 << 21; /** Multiply High */ public final void emitMPYH(int RT, int RA, int RB) { int mi = MPYHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Multiply Immediate */ static final int MPYItemplate = 0x74 << 24; /** Multiply Immediate */ public final void emitMPYI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = MPYItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Unsigned Multiply Immediate */ static final int MPYUItemplate = 0x75 << 24; /** Unsigned Multiply Immediate */ public final void emitMPYUI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = MPYUItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Count Leading Zero's */ static final int CLZtemplate = 0x2a5 << 21; /** Count Leading Zero's */ public final void emitCLZ(int RT, int RA) { int mi = CLZtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Form Selection Mask for Words */ static final int FSMtemplate = 0x1b4 << 21; /** Form Selection Mask for Words */ public final void emitFSM(int RT, int RA) { int mi = FSMtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Form Selection Mask for Bytes Immediate */ static final int FSMBItemplate = 0x65 << 23; /** Form Selection Mask for Words */ public final void emitFSMBI(int RT, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 16)); int mi = FSMBItemplate | (immed & 0xffff) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Extend Sign Byte to Halfword */ static final int XSBHtemplate = 0x2b6 << 21; /** Extend Sign Byte to Halfword */ public final void emitXSBH(int RT, int RA) { int mi = XSBHtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Extend Sign Halfword to Word */ static final int XSHWtemplate = 0x2ae << 21; /** Extend Sign Halfword to Word */ public final void emitXSHW(int RT, int RA) { int mi = XSHWtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Extend Sign Word to DoubleWord */ static final int XSWDtemplate = 0x2a6 << 21; /** Extend Sign Word to DoubleWord */ public final void emitXSWD(int RT, int RA) { int mi = XSWDtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** And */ static final int ANDtemplate = 0xc1 << 21; /** And */ public final void emitAND(int RT, int RA, int RB) { int mi = ANDtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** And with Compliment */ static final int ANDCtemplate = 0x2c1 << 21; /** And with Compliment */ public final void emitANDC(int RT, int RA, int RB) { int mi = ANDCtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** And Byte Immediate */ static final int ANDBItemplate = 0x16 << 24; /** And Byte Immediate */ public final void emitANDBI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = ANDBItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** And Halfword Immediate */ static final int ANDHItemplate = 0x15 << 24; /** And Halfword Immediate */ public final void emitANDHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = ANDHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** And Word Immediate */ static final int ANDItemplate = 0x14 << 24; /** And Word Immediate */ public final void emitANDI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = ANDItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Or */ static final int ORtemplate = 0x41 << 21; /** Or */ public final void emitOR(int RT, int RA, int RB) { int mi = ORtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Or with Compliment */ static final int ORCtemplate = 0x2c9 << 21; /** Or with Compliment */ public final void emitORC(int RT, int RA, int RB) { int mi = ORCtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Or Byte Immediate */ static final int ORBItemplate = 0x6 << 24; /** Or Byte Immediate */ public final void emitORBI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = ORBItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Or Halfword Immediate */ static final int ORHItemplate = 0x5 << 24; /** Or Halfword Immediate */ public final void emitORHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = ORHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Or Word Immediate */ static final int ORItemplate = 0x4 << 24; /** Or Word Immediate */ public final void emitORI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = ORItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Xor */ static final int XORtemplate = 0x241 << 21; /** Xor */ public final void emitXOR(int RT, int RA, int RB) { int mi = XORtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Xor Byte Immediate */ static final int XORBItemplate = 0x46 << 24; /** Xor Byte Immediate */ public final void emitXORBI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = XORBItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Xor Halfword Immediate */ static final int XORHItemplate = 0x45 << 24; /** Xor Halfword Immediate */ public final void emitXORHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = XORHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Xor Word Immediate */ static final int XORItemplate = 0x44 << 24; /** Xor Word Immediate */ public final void emitXORI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = XORItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Nand */ static final int NANDtemplate = 0xc9 << 21; /** Nand */ public final void emitNAND(int RT, int RA, int RB) { int mi = NANDtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Nor */ static final int NORtemplate = 0x49 << 21; /** Nor */ public final void emitNOR(int RT, int RA, int RB) { int mi = NORtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Equivalent */ static final int EQVtemplate = 0x249 << 21; /** Equivalent */ public final void emitEQV(int RT, int RA, int RB) { int mi = EQVtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Select Bits */ static final int SELBtemplate = 0x8 << 28; /** Select Bits */ public final void emitSELB(int RT, int RA, int RB, int RC) { int mi = SELBtemplate | RT << 21 | RB << 14 | RA << 7 | RC << 0; mIP++; mc.addInstruction(mi); } /** Shuffle Bytes */ static final int SHUFBtemplate = 0xB << 28; /** Shuffle Bytes */ public final void emitSHUFB(int RT, int RA, int RB, int RC) { int mi = SHUFBtemplate | RT << 21 | RB << 14 | RA << 7 | RC << 0; mIP++; mc.addInstruction(mi); } /* * Shift and Rotate Instructions * ________________________________ */ /** Shift Left Halfword */ static final int SHLHtemplate = 0x5f << 21; /** Shift Left Halfword */ public final void emitSHLH(int RT, int RA, int RB) { int mi = SHLHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left Halfword Immediate */ static final int SHLHItemplate = 0x7f << 21; /** Shift Left Halfword Immediate */ public final void emitSHLHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 7)); int mi = SHLHItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left Word */ static final int SHLtemplate = 0x5b << 21; /** Shift Left Word */ public final void emitSHL(int RT, int RA, int RB) { int mi = SHLtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left Word Immediate */ static final int SHLItemplate = 0x7b << 21; /** Shift Left Word Immediate */ public final void emitSHLI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 7)); int mi = SHLItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left QuadWord by Bytes */ static final int SHLQBYtemplate = 0x1df << 21; /** Shift Left QuadWord by Bytes */ public final void emitSHLQBY(int RT, int RA, int RB) { int mi = SHLQBYtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left QuadWord by Bytes Immediate */ static final int SHLQBYItemplate = 0x1ff << 21; /** Shift Left QuadWord by Bytes Immediate */ public final void emitSHLQBYI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 7)); int mi = SHLQBYItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left QuadWord by Bytes from Bit Shift Count */ static final int SHLQBYBItemplate = 0x1cf << 21; /** Shift Left QuadWord by Bytes from Bit Shift Count */ public final void emitSHLQBYBI(int RT, int RA, int RB) { int mi = SHLQBYBItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left QuadWord by Bits */ static final int SHLQBItemplate = 0x1db << 21; /** Shift Left QuadWord by Bits */ public final void emitSHLQBI(int RT, int RA, int RB) { int mi = SHLQBItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Shift Left QuadWord by Bits Immediate */ static final int SHLQBIItemplate = 0x1fb << 21; /** Shift Left QuadWord by Bits Immediate */ public final void emitSHLQBII(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 7)); int mi = SHLQBIItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Halfword */ static final int ROTHtemplate = 0x5c << 21; /** Rotate Left Halfword */ public final void emitROTH(int RT, int RA, int RB) { int mi = ROTHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Halfword Immediate */ static final int ROTHItemplate = 0x7c << 21; /** Rotate Left Halfword Immediate */ public final void emitROTHI(int RT, int RA, int immed) { int mi = ROTHItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Word */ static final int ROTtemplate = 0x58 << 21; /** Rotate Left Word */ public final void emitROT(int RT, int RA, int RB) { int mi = ROTtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Word Immediate */ static final int ROTItemplate = 0x78 << 21; /** Rotate Left Word Immediate */ public final void emitROTI(int RT, int RA, int immed) { int mi = ROTItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Word and Mask */ static final int ROTMtemplate = 0x59 << 21; /** Rotate Left Word and Mask */ public final void emitROTM(int RT, int RA, int RB) { int mi = ROTMtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Word and Mask Immediate */ static final int ROTMItemplate = 0x79 << 21; /** Rotate Left Word and Mask Immediate */ public final void emitROTMI(int RT, int RA, int immed) { int mi = ROTMItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Word and Mask Algebraic */ static final int ROTMAtemplate = 0x5a << 21; /** Rotate Left Word and Mask Algebraic */ public final void emitROTMA(int RT, int RA, int RB) { int mi = ROTMAtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Word and Mask Algebraic Immediate */ static final int ROTMAItemplate = 0x7a << 21; /** Rotate Left Word and Mask Algebraic Immediate */ public final void emitROTMAI(int RT, int RA, int immed) { int mi = ROTMAItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bytes */ static final int ROTQBYtemplate = 0x1dc << 21; /** Rotate Left Quadword by Bytes */ public final void emitROTQBY(int RT, int RA, int RB) { int mi = ROTQBYtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bytes Immediate */ static final int ROTQBYItemplate = 0x1fc << 21; /** Rotate Left Quadword by Bytes Immediate */ public final void emitROTQBYI(int RT, int RA, int immed) { int mi = ROTQBYItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bytes and Mask */ static final int ROTQMBYtemplate = 0x1dd << 21; /** Rotate Left Quadword by Bytes and Mask */ public final void emitROTQMBY(int RT, int RA, int RB) { int mi = ROTQMBYtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bytes and Mask Immediate */ static final int ROTQMBYItemplate = 0x1fd << 21; /** Rotate Left Quadword by Bytes and Mask Immediate */ public final void emitROTQMBYI(int RT, int RA, int immed) { int mi = ROTQMBYItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword Bytes by Bit Shift Count */ static final int ROTQBYBItemplate = 0x1cc << 21; /** Rotate Left Quadword Bytes by Bit Shift Count */ public final void emitROTQBYBI(int RT, int RA, int RB) { int mi = ROTQBYBItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bits */ static final int ROTQBItemplate = 0x1d8 << 21; /** Rotate Left Quadword by Bits */ public final void emitROTQBI(int RT, int RA, int RB) { int mi = ROTQBItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bits and Mask */ static final int ROTQMBItemplate = 0x1d9 << 21; /** Rotate Left Quadword by Bytes and Mask */ public final void emitROTQMBI(int RT, int RA, int RB) { int mi = ROTQMBItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left Quadword by Bits and Mask Immediate */ static final int ROTQMBIItemplate = 0x1f9 << 21; /** Rotate Left Quadword by Bytes and Mask Immediate */ public final void emitROTQMBII(int RT, int RA, int immed) { int mi = ROTQMBIItemplate | (0x7f & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Rotate Left and Mask Quadword Bytes by Bit Shift Count */ static final int ROTQMBYBItemplate = 0x1cd << 21; /** Rotate Left and Mask Quadword Bytes by Bit Shift Count */ public final void emitROTQMBYBI(int RT, int RA, int RB) { int mi = ROTQMBYBItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /* * Branch and Compare Instructions * ________________________________ */ /** Compare Equal Byte */ static final int CEQBtemplate = 0x3d0 << 21; /** Compare Equal Byte */ public final void emitCEQB(int RT, int RA, int RB) { int mi = CEQBtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Equal Byte Immediate */ static final int CEQBItemplate = 0x7e << 24; /** Compare Equal Byte Immediate */ public final void emitCEQBI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CEQBItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Equal Halfword */ static final int CEQHtemplate = 0x3c8 << 21; /** Compare Equal Halfword */ public final void emitCEQH(int RT, int RA, int RB) { int mi = CEQHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Equal Halfword Immediate */ static final int CEQHItemplate = 0x7d << 24; /** Compare Equal Halfword Immediate */ public final void emitCEQHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CEQHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Equal Word */ static final int CEQtemplate = 0x3c0 << 21; /** Compare Equal Word */ public final void emitCEQ(int RT, int RA, int RB) { int mi = CEQtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Equal Word Immediate */ static final int CEQItemplate = 0x7c << 24; /** Compare Equal Word Immediate */ public final void emitCEQI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CEQItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Greater Than Byte */ static final int CGTBtemplate = 0x250 << 21; /** Compare Greater Than Byte */ public final void emitCGTB(int RT, int RA, int RB) { int mi = CGTBtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Greater Than Byte Immediate */ static final int CGTBItemplate = 0x4e << 24; /** Compare Greater Than Byte Immediate */ public final void emitCGTBI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CGTBItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Greater Than Halfword */ static final int CGTHtemplate = 0x248 << 21; /** Compare Greater Than Halfword */ public final void emitCGTH(int RT, int RA, int RB) { int mi = CGTHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Greater Than Halfword Immediate */ static final int CGTHItemplate = 0x4d << 24; /** Compare Greater Than Halfword Immediate */ public final void emitCGTHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CGTHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Greater Than Word */ static final int CGTtemplate = 0x240 << 21; /** Compare Greater Than Word (RA > RB) */ public final void emitCGT(int RT, int RA, int RB) { int mi = CGTtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Greater Than Word Immediate */ static final int CGTItemplate = 0x4c << 24; /** Compare Greater Than Word Immediate */ public final void emitCGTI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CGTItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Logical Greater Than Byte */ static final int CLGTBtemplate = 0x2d0 << 21; /** Compare Logical Greater Than Byte */ public final void emitCLGTB(int RT, int RA, int RB) { int mi = CLGTBtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Logical Greater Than Byte Immediate */ static final int CLGTBItemplate = 0x5e << 24; /** Compare Logical Greater Than Byte Immediate */ public final void emitCLGTBI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CLGTBItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Logical Greater Than Halfword */ static final int CLGTHtemplate = 0x2c8 << 21; /** Compare Logical Greater Than Halfword */ public final void emitCLGTH(int RT, int RA, int RB) { int mi = CLGTHtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Logical Greater Than Halfword Immediate */ static final int CLGTHItemplate = 0x5d << 24; /** Compare Logical Greater Than Halfword Immediate */ public final void emitCLGTHI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CLGTHItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Logical Greater Than Word */ static final int CLGTtemplate = 0x2c0 << 21; /** Compare Logical Greater Than Word */ public final void emitCLGT(int RT, int RA, int RB) { int mi = CLGTtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Compare Logical Greater Than Word Immediate */ static final int CLGTItemplate = 0x5c << 24; /** Compare Logical Greater Than Word Immediate */ public final void emitCLGTI(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fits(immed, 10)); int mi = CLGTItemplate | (0x3ff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Branch Relative static final int BRtemplate = 0x64 << 23; public void _emitBR(int relative_address) { if (VM.VerifyAssertions) VM._assert(fits(relative_address, 16)); int mi = BRtemplate | (relative_address & 0xFFFF) << 7; mIP++; mc.addInstruction(mi); } public final void emitBR(int relative_address, int label) { if (relative_address == 0) { reserveForwardBranch(label); } else { relative_address -= mIP; } _emitBR(relative_address); } public final void emitBR(int relative_address) { relative_address -= mIP; if (VM.VerifyAssertions) VM._assert(relative_address < 0); _emitBR(relative_address); } public final VM_ForwardReference emitForwardBR() { VM_ForwardReference fr; if (compiler != null) { fr = new VM_AssemblerShortBranch(mIP, compiler.spTopOffset); } else { fr = new VM_ForwardReference.ShortBranch(mIP); } _emitBR(0); return fr; } // Branch Absolute static final int BRAtemplate = 0x60 << 23; public final void emitBRA(int address) { // convert branch from byte to word address = address >> LG_INSTRUCTION_WIDTH; if (VM.VerifyAssertions) VM._assert(fits(address, 16)); int mi = BRAtemplate | (address & 0xFFFF) << 7; mIP++; mc.addInstruction(mi); } // Branch Relative and Set Link static final int BRSLtemplate = 0x66 << 23; public void _emitBRSL(int RT, int relative_address) { if (VM.VerifyAssertions) VM._assert(fits(relative_address, 16)); int mi = BRSLtemplate | (relative_address & 0xFFFF) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitBRSL(int RT, int relative_address, int label) { if (relative_address == 0) { reserveForwardBranch(label); } else { relative_address -= mIP; } _emitBRSL(RT, relative_address); } public final VM_ForwardReference emitForwardBRSL(int RT) { VM_ForwardReference fr; if (compiler != null) { fr = new VM_AssemblerShortBranch(mIP, compiler.spTopOffset); } else { fr = new VM_ForwardReference.ShortBranch(mIP); } _emitBRSL(RT, 0); return fr; } // Branch Absolute and Set Link static final int BRASLtemplate = 0x62 << 23; public final void emitBRASL(int RT, int address) { address = address >> LG_INSTRUCTION_WIDTH; if (VM.VerifyAssertions) VM._assert(fits(address, 16)); int mi = BRASLtemplate | (address & 0xFFFF) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Branch Indirect static final int BItemplate = 0x1a8 << 21; public final void _emitBI(int RA, int itr_change) { if (VM.VerifyAssertions) VM._assert((itr_change >= NO_CHANGE_INT) && (itr_change <= DISABLE_INT)); int mi = BItemplate | itr_change << 18 | RA << 7; mIP++; mc.addInstruction(mi); } public final void emitBI(int RA) { _emitBI(RA, NO_CHANGE_INT); } public final void emitBIE(int RA) { _emitBI(RA, ENABLE_INT); } public final void emitBID(int RA) { _emitBI(RA, DISABLE_INT); } // Branch Indirect and Set Link static final int BISLtemplate = 0x1a9 << 21; public final void _emitBISL(int RT, int RA, int itr_change) { if (VM.VerifyAssertions) VM._assert((itr_change >= NO_CHANGE_INT) && (itr_change <= DISABLE_INT)); int mi = BISLtemplate | itr_change << 18 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitBISL(int RT, int RA) { _emitBISL(RT, RA, NO_CHANGE_INT); } public final void emitBISLE(int RT, int RA) { _emitBISL(RT, RA, ENABLE_INT); } public final void emitBISLD(int RT, int RA) { _emitBISL(RT, RA, DISABLE_INT); } // Branch Relative If Not Zero Word static final int BRNZtemplate = 0x42 << 23; private void _emitBRNZ(int RT, int relative_address) { if (VM.VerifyAssertions) VM._assert(fits(relative_address, 16)); int mi = BRNZtemplate | (relative_address & 0xFFFF) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitBRNZ(int RT, int relative_address, int label) { if (relative_address == 0) { reserveForwardBranch(label); } else { relative_address -= mIP; } _emitBRNZ(RT, relative_address); } public final void emitBRNZ(int RT, int relative_address) { relative_address -= mIP; if (VM.VerifyAssertions) VM._assert(relative_address < 0); _emitBRNZ(RT, relative_address); } public final VM_ForwardReference emitForwardBRNZ(int RT) { VM_ForwardReference fr; if (compiler != null) { fr = new VM_AssemblerShortBranch(mIP, compiler.spTopOffset); } else { fr = new VM_ForwardReference.ShortBranch(mIP); } _emitBRNZ(RT, 0); return fr; } // Branch Relative If Zero Word static final int BRZtemplate = 0x40 << 23; private void _emitBRZ(int RT, int relative_address) { if (VM.VerifyAssertions) VM._assert(fits(relative_address, 16)); int mi = BRZtemplate | (relative_address & 0xFFFF) << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitBRZ(int RT, int relative_address, int label) { if (relative_address == 0) { reserveForwardBranch(label); } else { relative_address -= mIP; } _emitBRZ(RT, relative_address); } public final void emitBRZ(int RT, int relative_address) { relative_address -= mIP; if (VM.VerifyAssertions) VM._assert(relative_address < 0); _emitBRZ(RT, relative_address); } public final VM_ForwardReference emitForwardBRZ(int RT) { VM_ForwardReference fr; if (compiler != null) { fr = new VM_AssemblerShortBranch(mIP, compiler.spTopOffset); } else { fr = new VM_ForwardReference.ShortBranch(mIP); } _emitBRZ(RT, 0); return fr; } // Branch Indirect If Zero static final int BIZtemplate = 0x128 << 21; public final void _emitBIZ(int RT, int RA, int itr_change) { if (VM.VerifyAssertions) VM._assert((itr_change >= NO_CHANGE_INT) && (itr_change <= DISABLE_INT)); int mi = BIZtemplate | itr_change << 18 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitBIZ(int RT, int RA) { _emitBIZ(RT, RA, NO_CHANGE_INT); } public final void emitBIZE(int RT, int RA) { _emitBIZ(RT, RA, ENABLE_INT); } public final void emitBIZD(int RT, int RA) { _emitBIZ(RT, RA, DISABLE_INT); } // Branch Indirect If Not Zero static final int BINZtemplate = 0x129 << 21; public final void _emitBINZ(int RT, int RA, int itr_change) { if (VM.VerifyAssertions) VM._assert((itr_change >= NO_CHANGE_INT) && (itr_change <= DISABLE_INT)); int mi = BINZtemplate | itr_change << 18 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } public final void emitBINZ(int RT, int RA) { _emitBINZ(RT, RA, NO_CHANGE_INT); } public final void emitBINZE(int RT, int RA) { _emitBINZ(RT, RA, ENABLE_INT); } public final void emitBINZD(int RT, int RA) { _emitBINZ(RT, RA, DISABLE_INT); } // Switch Case Address public final void emitSwitchCase(int i, int relative_address, int bTarget) { //delta i: difference between address of case i and of delta 0 int data = i << 2; if (relative_address == 0) { reserveForwardCase(bTarget); } else { data += ((relative_address - mIP) << 2); } mIP++; mc.addInstruction(data); } /* * Floating Point Instructions * ________________________________ */ // Floating Add static final int FAtemplate = 0x2c4 << 21; public final void emitFA(int RT, int RA, int RB) { int mi = FAtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Double Floating Add static final int DFAtemplate = 0x2cc << 21; public final void emitDFA(int RT, int RA, int RB) { int mi = DFAtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Floating Subtract static final int FStemplate = 0x2c5 << 21; public final void emitFS(int RT, int RA, int RB) { int mi = FStemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Double Floating Subtract static final int DFStemplate = 0x2cd << 21; public final void emitDFS(int RT, int RA, int RB) { int mi = DFStemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Floating Multiply static final int FMtemplate = 0x2c6 << 21; public final void emitFM(int RT, int RA, int RB) { int mi = FMtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Double Floating Multiply static final int DFMtemplate = 0x2ce << 21; public final void emitDFM(int RT, int RA, int RB) { int mi = DFMtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Convert Signed Integer to Floating static final int CSFLTtemplate = 0x1da << 22; public final void emitCSFLT(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = CSFLTtemplate | (0xff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Convert Floating to Signed Integer static final int CFLTStemplate = 0x1d8 << 22; public final void emitCFLTS(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = CFLTStemplate | (0xff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Convert Unsigned Integer to Floating static final int CUFLTtemplate = 0x1db << 22; public final void emitCUFLT(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = CUFLTtemplate | (0xff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Convert Floating to Unsigned Integer static final int CFLTUtemplate = 0x1d9 << 22; public final void emitCFLTU(int RT, int RA, int immed) { if (VM.VerifyAssertions) VM._assert(fitsU(immed, 8)); int mi = CFLTUtemplate | (0xff & immed) << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Floating Round Double to Single static final int FRDStemplate = 0x3b9 << 21; public final void emitFRDS(int RT, int RA) { int mi = FRDStemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Floating Sign Extend Single to Double static final int FESDtemplate = 0x3b8 << 21; public final void emitFESD(int RT, int RA) { int mi = FESDtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Floating Compare Equal static final int FCEQtemplate = 0x3c2 << 21; public final void emitFCEQ(int RT, int RA, int RB) { int mi = FCEQtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Floating Compare Greater Than static final int FCGTtemplate = 0x2c2 << 21; public final void emitFCGT(int RT, int RA, int RB) { int mi = FCGTtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Double Floating Compare Equal static final int DFCEQtemplate = 0x3c3 << 21; public final void emitDFCEQ(int RT, int RA, int RB) { int mi = DFCEQtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } // Double Floating Compare Greater Than static final int DFCGTtemplate = 0x2c3 << 21; public final void emitDFCGT(int RT, int RA, int RB) { int mi = DFCGTtemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Floating Multiply and Add */ static final int FMAtemplate = 0xe << 28; /** Floating Multiply and Add */ public final void emitFMA(int RT, int RA, int RB, int RC) { int mi = FMAtemplate | RT << 21 | RB << 14 | RA << 7 | RC << 0; mIP++; mc.addInstruction(mi); } /** Floating Multiply and Subtract */ static final int FMStemplate = 0xf << 28; /** Floating Multiply and Subtract */ public final void emitFMS(int RT, int RA, int RB, int RC) { int mi = FMStemplate | RT << 21 | RB << 14 | RA << 7 | RC << 0; mIP++; mc.addInstruction(mi); } /** Floating Negative Multiply and Subtract */ static final int FNMStemplate = 0xd << 28; /** Floating Negative Multiply and Subtract */ public final void emitFNMS(int RT, int RA, int RB, int RC) { int mi = FNMStemplate | RT << 21 | RB << 14 | RA << 7 | RC << 0; mIP++; mc.addInstruction(mi); } /** Floating Reciprocal Estimate */ static final int FRESTtemplate = 0x1b8 << 21; /** Floating Reciprocal Estimate */ public final void emitFREST(int RT, int RA) { int mi = FRESTtemplate | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /** Floating Interpolate */ static final int FItemplate = 0x3d4 << 21; /** Floating Interpolate */ public final void emitFI(int RT, int RA, int RB) { int mi = FItemplate | RB << 14 | RA << 7 | RT << 0; mIP++; mc.addInstruction(mi); } /* * Control Instructions * ________________________________ */ // nop static final int NOPtemplate = 0x201 << 21; public final void emitNOP() { int mi = NOPtemplate; mIP++; mc.addInstruction(mi); } // Syncronize static final int SYNCtemplate = 0x2 << 21; public final void emitSYNC() { int mi = SYNCtemplate; mIP++; mc.addInstruction(mi); } public final void emitSYNCC() { int mi = SYNCtemplate | 0x1 << 20; mIP++; mc.addInstruction(mi); } // Syncronize Data static final int DSYNCtemplate = 0x3 << 21; public final void emitDSYNC() { int mi = DSYNCtemplate; mIP++; mc.addInstruction(mi); } /** stop and signal */ static final int STOPtemplate = 0x0 << 21; /** stop and signal */ public final void emitSTOP(int signal) { if (VM.VerifyAssertions) VM._assert(fitsU(signal, 14)); int mi = STOPtemplate | (0x3fff & signal) << 0; mIP++; mc.addInstruction(mi); } /** Load link reg with PC */ public final void emitLoadLR(int RT) { _emitBRSL(RT, 1); } /** Read Channel */ static final int RDCHtemplate = 0xD << 21; /** Read Channel */ public final void emitRDCH(int CA, int RT) { if (VM.VerifyAssertions) VM._assert(fitsU(CA, 7)); int mi = RDCHtemplate | (0x7f & CA) << 7 | (0x7f & RT) << 0; mIP++; mc.addInstruction(mi); } /** Read Channel Count */ static final int RCHCNTtemplate = 0xF << 21; /** Read Channel Count */ public final void emitRCHCNT(int CA, int RT) { if (VM.VerifyAssertions) VM._assert(fitsU(CA, 7)); int mi = RCHCNTtemplate | (0x7f & CA) << 7 | (0x7f & RT) << 0; mIP++; mc.addInstruction(mi); } /** Write Channel */ static final int WRCHtemplate = 0x10D << 21; /** Write Channel */ public final void emitWRCH(int CA, int RT) { if (VM.VerifyAssertions) VM._assert(fitsU(CA, 7)); int mi = WRCHtemplate | (0x7f & CA) << 7 | (0x7f & RT) << 0; mIP++; mc.addInstruction(mi); } /** * Perform a read from main memory to local memory * * @param mainAddressReg Register holding main memory address where data should be read * @param lengthReg Register holding the length of data to be transferred * @param localAddressReg Register holding the local address where data should be written * @param tagGroup Tag group to perform right under */ public final void emitGET(int mainAddressReg, int lengthReg, int localAddressReg, int tagGroup) { emitIL(S0, tagGroup); emitIL(S1, MFC_GET_OPCODE); emitWRCH(MFC_LOCAL_ADDR_CHAN, localAddressReg); emitWRCH(MFC_LO_MAIN_ADDR_CHAN, mainAddressReg); emitWRCH(MFC_TRANSFER_SIZE_CHAN, lengthReg); emitWRCH(MFC_TAG_ID_CHAN, S0); emitWRCH(MFC_CMD_CHAN, S1); } /** * Perform a write to main memory from local memory * * @param mainAddressReg Register holding main memory address where data should be written * @param lengthReg Register holding the length of data to be transferred * @param localAddressReg Register holding the local address where data should be read * @param tagGroup Tag group to perform right under */ public final void emitPUT(int mainAddressReg, int lengthReg, int localAddressReg, int tagGroup) { emitIL(S0, tagGroup); emitIL(S1, MFC_PUT_OPCODE); emitWRCH(MFC_LOCAL_ADDR_CHAN, localAddressReg); emitWRCH(MFC_LO_MAIN_ADDR_CHAN, mainAddressReg); emitWRCH(MFC_TRANSFER_SIZE_CHAN, lengthReg); emitWRCH(MFC_TAG_ID_CHAN, S0); emitWRCH(MFC_CMD_CHAN, S1); } /** * Perform a read from main memory to local memory * * @param mainAddressReg Register holding main memory address where data should be read * @param lengthReg Register holding the length of data to be transferred * @param localAddressReg Register holding the local address where data should be written * @param tagGroup Tag group to perform right under */ public final void emitGETL(int listAddrReg, int listSizeReg, int localAddrStartReg, int tagGroup) { emitIL(S0, tagGroup); emitIL(S1, MFC_GETL_OPCODE); emitWRCH(MFC_LOCAL_ADDR_CHAN, localAddrStartReg); emitWRCH(MFC_LIST_ADDR_CHAN, listAddrReg); emitWRCH(MFC_LIST_SIZE_CHAN, listSizeReg); emitWRCH(MFC_TAG_ID_CHAN, S0); emitWRCH(MFC_CMD_CHAN, S1); } /** * Perform a getllar MFC atomic command * * @param mainAddressReg Register holding main memory address where data should be read * @param localAddressReg Register holding the local address where data should be written */ public final void emitGETLLAR(int mainAddressReg, int localAddrStartReg) { emitIL(S1, MFC_GETLLAR_OPCODE); emitWRCH(MFC_LOCAL_ADDR_CHAN, localAddrStartReg); emitWRCH(MFC_LIST_ADDR_CHAN, mainAddressReg); emitWRCH(MFC_CMD_CHAN, S1); } /** * Perform a putllc MFC atomic command * * @param mainAddressReg Register holding main memory address where data should be read * @param localAddressReg Register holding the local address where data should be written */ public final void emitPUTLLC(int mainAddressReg, int localAddrStartReg) { emitIL(S1, MFC_PUTLLC_OPCODE); emitWRCH(MFC_LOCAL_ADDR_CHAN, localAddrStartReg); emitWRCH(MFC_LIST_ADDR_CHAN, mainAddressReg); emitWRCH(MFC_CMD_CHAN, S1); } /** * Wait for the previous atomic instruction to complete */ public final void emitATOMIC_WAIT(int statReg) { emitRDCH(MFC_READ_ATOMIC_STAT, statReg); // TODO - check result } /** * Blocks execution until the MFC updates to the specified tag group are complete * Note: Tag group should be in S0 */ public final void emitBlockUntilComplete() { emitIL(S1, 0); emitWRCH(MFC_WRITE_TAG_UPDATE, S1); int readChnCntLoop = mIP; emitRCHCNT(MFC_WRITE_TAG_UPDATE, S2); emitBRZ(S2, readChnCntLoop); emitRDCH(MFC_READ_TAG_STATUS, S2); emitWRCH(MFC_WRITE_TAG_MASK, S0); // TODO - don't poll, do something else instead int blockLoop = mIP; emitWRCH(MFC_WRITE_TAG_UPDATE, S1); emitRDCH(MFC_READ_TAG_STATUS, S2); emitBRZ(S2, blockLoop); } /** * Blocks execution until the MFC updates to the specified tag group are complete * * @param tagGroup tag group of requests to block on */ public final void emitBlockUntilComplete(int tagGroup) { emitIL(S0, (0x1<<tagGroup)); emitBlockUntilComplete(); } // -----------------------------------------------------------// // The following section contains assembler "macros" used by: // // VM_Compiler // // VM_Barriers // // -----------------------------------------------------------// /** * Destroys S2 and possibly S6 */ public void emitTRAP(int source, boolean cc, int trapCode) { // TODO: Check if trap returns here // load return value to trap return register // _emitBRSL(S6, 4); // Note, this does not flush pipeline as it branches to next instruction emitIL(S2, trapCode); if (cc) { emitBINZ(source, TRAP_ENTRY_REG); // Traps to interrupt handler } else { emitBIZ(source, TRAP_ENTRY_REG); // Traps to interrupt handler } } public void emitFakeTrap(int source) { emitIL(source, FAKE_TRAP_MESSAGE); emitWRCH(SPU_WR_OUT_INTR_MBOX, source); } public void emitFakeTrapStr(int source, int bytesAddr) { emitIL(source, FAKE_TRAP_MESSAGE_STR); emitWRCH(SPU_WR_OUT_MBOX, bytesAddr); emitWRCH(SPU_WR_OUT_INTR_MBOX, source); // wait for ACK emitRDCH(SPU_RD_IN_MBOX, source); } public void emitFakeTrapInt(int source, int intReg) { emitIL(source, FAKE_TRAP_MESSAGE_INT); emitWRCH(SPU_WR_OUT_MBOX, intReg); emitWRCH(SPU_WR_OUT_INTR_MBOX, source); // wait for ACK emitRDCH(SPU_RD_IN_MBOX, source); } // Emit baseline stack overflow instruction sequence. // Before: FP is current (calling) frame // PR is the current VM_Processor, which contains a pointer to the active thread. // After: R0, S2, S3 destroyed // public void emitStackOverflowCheck(int frameSize) { //emitLoad(0, VM_RegisterConstants.PROCESSOR_REGISTER, // VM_Entrypoints.activeThreadStackLimitField.getSubArchOffset()); // TODO - Make this dynamic emitILW(0, STACK_END); emitAI(S2, FP, -frameSize); // S2 := &new frame emitCLGT(S3, 0, S2); // Trap if new frame below guard page emitTRAP(S3, true, VM_TrapConstants.TRAP_STACK_OVERFLOW); } /** * emit a trap on null check. * @param RA The register number containing the ptr to null check */ public void emitNullCheck(int RA) { emitTRAP(RA, false, VM_TrapConstants.TRAP_NULL_POINTER); } public static int getTargetOffset(int instr) { // TODO - Check for opcodes which can be retargeted // FIXME - retarget 4 reg instructions (e.g. selb etc.) return 0; } public boolean retargetInstruction(int mcIndex, int newRegister) { int instr = mc.getInstruction(mcIndex); int offset = getTargetOffset(instr); if (offset < 0) { VM.sysWrite("Failed to retarget index="); VM.sysWrite(mcIndex); VM.sysWrite(", instr="); VM.sysWriteHex(instr); VM.sysWriteln(); if (VM.VerifyAssertions) VM._assert(NOT_REACHED); return false; } instr = (instr & ~(0x3F << offset)) | (newRegister << offset); mc.putInstruction(mcIndex, instr); return true; } // Convert generated machine code into final form. // public SubordinateArchitecture.VM_MachineCode finalizeMachineCode(int[] bytecodeMap) { mc.setBytecodeMap(bytecodeMap); return makeMachineCode(); } public SubordinateArchitecture.VM_MachineCode makeMachineCode() { mc.finish(); if (shouldPrint) { VM.sysWriteln(); SubordinateArchitecture.VM_CodeArray instructions = mc.getInstructions(); boolean saved = VM_BaselineCompiler.options.PRINT_MACHINECODE; try { VM_BaselineCompiler.options.PRINT_MACHINECODE = false; for (int i = 0; i < instructions.length(); i++) { VM.sysWrite(VM_Services.getHexString(i << LG_INSTRUCTION_WIDTH, true)); VM.sysWrite(" : "); VM.sysWrite(VM_Services.getHexString(instructions.get(i), false)); VM.sysWrite(" "); VM.sysWrite(VM_Disassembler.disasm(instructions.get(i), i << LG_INSTRUCTION_WIDTH)); VM.sysWrite("\n"); } } finally { VM_BaselineCompiler.options.PRINT_MACHINECODE = saved; } } return (SubordinateArchitecture.VM_MachineCode) mc; } public static String getOpcodeName(int opcode) { String s; switch (opcode) { // TODO - Generate correct opcode names default: s = "UNKNOWN"; break; } return s; } /************************************************************************ * Stub/s added for IA32 compatability */ public static void patchCode(SubordinateArchitecture.VM_CodeArray code, int indexa, int indexb) { if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /************************************************************************ * Test assembler */ private static final int D_FORM = 0x1; private static final int SHFT_IMMED_4 = 0x2; private static final int IMMED_NEG = 0x4; private static final int IMMED_HEX = 0x8; private static final int SHFT_IMMED_2 = 0x10; private static final int IMMED_REL = 0x20; private static final int DONT_CHECK_ARG = 0x40; private static final int FROM_155 = 0x80; private static final int FROM_173 = 0x100; private static final int CHAN_READ_FORM = 0x200; private static final int CHAN_WRITE_FORM = 0x400; private static class Instruction { private static int inst_count = 0; public String name; public int [] arg_ranges; public int [] arg_vals; public Object [] arg_vals_o; public String [] arg_results; public boolean [] arg_is_reg; public Class[] arg_types; private int inst_numb; private boolean dont_check_arg = false; public String argsErrors = ""; public String methodPrefix = ""; private static Random rand; public Instruction (String name, int [] arg_ranges, boolean [] arg_is_reg) { if (rand == null) { rand = new Random(); } this.name = name; this.arg_ranges = arg_ranges; this.arg_is_reg = arg_is_reg; this.inst_numb = inst_count; inst_count++; this.arg_vals = new int [arg_ranges.length]; this.arg_vals_o = new Object[arg_ranges.length]; this.arg_results = new String[arg_ranges.length]; for (int i=0; i<arg_vals.length; i++) { this.arg_vals[i] = rand.nextInt(1 << this.arg_ranges[i]); this.arg_vals_o[i] = new Integer(this.arg_vals[i]); if (this.arg_is_reg[i]) { this.arg_results[i] = "$" + this.arg_vals[i]; } else { this.arg_results[i] = "" + this.arg_vals[i]; } } this.arg_types = new Class[arg_ranges.length]; for (int i=0; i<this.arg_types.length; i++) { this.arg_types[i] = int.class; } } public Instruction (String name, int [] arg_ranges, boolean [] arg_is_reg, int options) { this(name, arg_ranges, arg_is_reg); if ((options & IMMED_NEG) != 0) { int last_val = this.arg_vals.length - 1; if ((this.arg_vals[last_val] & (1 << (this.arg_ranges[last_val] - 1))) != 0) { // sign extend value this.arg_vals[last_val] = this.arg_vals[last_val] | 0xffffffff & ~((1 << this.arg_ranges[last_val]) - 1); this.arg_vals_o[last_val] = new Integer(arg_vals[last_val]); this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + (this.arg_vals[last_val]); } } if ((options & SHFT_IMMED_4) != 0) { int last_val = this.arg_vals.length - 1; this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + (this.arg_vals[last_val] << 4); } if ((options & SHFT_IMMED_2) != 0) { int last_val = this.arg_vals.length - 1; this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + (this.arg_vals[last_val] << 2); } if ((options & FROM_155) != 0) { int last_val = this.arg_vals.length - 1; while (this.arg_vals[last_val] > 155 || this.arg_vals[last_val] < 28) this.arg_vals[last_val] = rand.nextInt(1 << 8); this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + (155 - (Integer.parseInt(this.arg_results[last_val]))); } if ((options & FROM_173) != 0) { int last_val = this.arg_vals.length - 1; while (this.arg_vals[last_val] > 173 || this.arg_vals[last_val] < 46) this.arg_vals[last_val] = rand.nextInt(1 << 8); this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + (173 - (Integer.parseInt(this.arg_results[last_val]))); } if ((options & IMMED_REL) != 0) { int last_val = this.arg_vals.length - 1; this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + ((Integer.parseInt(this.arg_results[last_val])) + (4 * this.inst_numb)); } if ((options & IMMED_HEX) != 0) { int last_val = this.arg_vals.length - 1; int range = this.arg_ranges[last_val]; if ((options & SHFT_IMMED_4) != 0) range += 4; if ((options & SHFT_IMMED_2) != 0) range += 2; int prev_val = Integer.parseInt(this.arg_results[last_val]) & ((1 << range) - 1); this.arg_results[last_val] = (arg_is_reg[last_val] ? "$" : "") + (Integer.toHexString(prev_val)); } // do any swaps at the end if ((options & D_FORM) != 0) { // swap last two values for result int last_val = this.arg_results.length - 1; String tmp = this.arg_results[last_val]; this.arg_results[last_val] = this.arg_results[last_val - 1]; this.arg_results[last_val - 1] = tmp; } if ((options & CHAN_READ_FORM) != 0) { // swap last two values for result, and make second one a channel int last_val = this.arg_results.length - 1; String tmp = this.arg_results[last_val]; this.arg_results[last_val] = "$ch" + this.arg_results[last_val - 1]; this.arg_results[last_val - 1] = tmp; } if ((options & CHAN_WRITE_FORM) != 0) { // make first result a channel int last_val = this.arg_results.length - 1; this.arg_results[last_val - 1] = "$ch" + this.arg_results[last_val - 1]; } // do any swaps at the end if ((options & DONT_CHECK_ARG) != 0) { this.dont_check_arg = true; } } public Instruction (String name, int [] arg_ranges, boolean [] arg_is_reg, String prefixStr) { this(name, arg_ranges, arg_is_reg); this.methodPrefix = prefixStr; } public Instruction (String name, int [] arg_ranges, boolean [] arg_is_reg, String prefixStr, int options) { this(name, arg_ranges, arg_is_reg, options); this.methodPrefix = prefixStr; } public boolean checkArgs(String[] args) { if (this.dont_check_arg) return true; if (args.length < arg_results.length) return false; boolean success = true; for(int i=0; i<arg_results.length; i++) { if (!arg_results[i].equals(args[i])) { success = false; argsErrors = argsErrors + " : Arg " + (i + 1) + " should have been " + arg_results[i] + " but was instead " + args[i] + "\n"; } } return success; } } public static void main (String args[]) { System.out.println("Testing assembly of instructions"); VM_Assembler asm = new org.jikesrvm.SubordinateArchitecture.VM_Assembler(1024); int [] none_r = {}; boolean [] none_b = {}; int [] reg1_r = {7}; boolean [] reg1_b = {true}; int [] reg2_r = {7, 7}; boolean [] reg2_b = {true, true}; boolean [] chan_b = {false, true}; int [] reg3_r = {7, 7, 7}; boolean [] reg3_b = {true, true, true}; int [] reg4_r = {7, 7, 7, 7}; boolean [] reg4_b = {true, true, true, true}; int [] immed16_r = {16}; boolean [] immed16_b = {false}; int [] immed14_r = {14}; boolean [] immed14_b = {false}; int [] reg_immed16_r = {7, 16}; boolean [] reg_immed16_b = {true, false}; int [] reg_immed18_r = {7, 18}; boolean [] reg_immed18_b = {true, false}; int [] reg2_immed10_r = {7, 7, 10}; boolean [] reg2_immed10_b = {true, true, false}; int [] reg2_immed8_r = {7, 7, 8}; boolean [] reg2_immed8_b = {true, true, false}; int [] reg2_immed7_r = {7, 7, 7}; boolean [] reg2_immed7_b = {true, true, false}; Instruction [] instructions = { new Instruction("LQD", reg2_immed10_r, reg2_immed10_b, D_FORM | SHFT_IMMED_4 | IMMED_NEG), new Instruction("LQX", reg3_r, reg3_b), new Instruction("LQA", reg_immed16_r, reg_immed16_b, IMMED_NEG | IMMED_HEX | SHFT_IMMED_2), new Instruction("LQR", reg_immed16_r, reg_immed16_b, IMMED_NEG | IMMED_HEX | SHFT_IMMED_2 | IMMED_REL), new Instruction("STQD", reg2_immed10_r, reg2_immed10_b, D_FORM | SHFT_IMMED_4 | IMMED_NEG), new Instruction("STQX", reg3_r, reg3_b), new Instruction("STQA", reg_immed16_r, reg_immed16_b, IMMED_NEG | IMMED_HEX | SHFT_IMMED_2), new Instruction("STQR", reg_immed16_r, reg_immed16_b, IMMED_NEG | IMMED_HEX | SHFT_IMMED_2 | IMMED_REL), new Instruction("CBD", reg2_immed7_r, reg2_immed7_b, D_FORM | IMMED_NEG), new Instruction("CBX", reg3_r, reg3_b), new Instruction("CHD", reg2_immed7_r, reg2_immed7_b, D_FORM | IMMED_NEG), new Instruction("CHX", reg3_r, reg3_b), new Instruction("CWD", reg2_immed7_r, reg2_immed7_b, D_FORM | IMMED_NEG), new Instruction("CWX", reg3_r, reg3_b), new Instruction("CDD", reg2_immed7_r, reg2_immed7_b, D_FORM | IMMED_NEG), new Instruction("CDX", reg3_r, reg3_b), new Instruction("ILH", reg_immed16_r, reg_immed16_b), new Instruction("ILHU", reg_immed16_r, reg_immed16_b), new Instruction("IL", reg_immed16_r, reg_immed16_b, IMMED_NEG), new Instruction("ILA", reg_immed18_r, reg_immed18_b, IMMED_HEX), new Instruction("IOHL", reg_immed16_r, reg_immed16_b), new Instruction("AH", reg3_r, reg3_b), new Instruction("AHI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("A", reg3_r, reg3_b), new Instruction("AI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("SFH", reg3_r, reg3_b), new Instruction("SFHI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("SF", reg3_r, reg3_b), new Instruction("SFI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("MPY", reg3_r, reg3_b), new Instruction("MPYU", reg3_r, reg3_b), new Instruction("MPYI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("MPYUI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CLZ", reg2_r, reg2_b), new Instruction("FSM", reg2_r, reg2_b), new Instruction("FSMBI", reg_immed16_r, reg_immed16_b), new Instruction("XSBH", reg2_r, reg2_b), new Instruction("XSHW", reg2_r, reg2_b), new Instruction("XSWD", reg2_r, reg2_b), new Instruction("AND", reg3_r, reg3_b), new Instruction("ANDC", reg3_r, reg3_b), new Instruction("ANDBI",reg2_immed8_r, reg2_immed8_b), new Instruction("ANDHI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("ANDI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("OR", reg3_r, reg3_b), new Instruction("ORC", reg3_r, reg3_b), new Instruction("ORBI", reg2_immed8_r, reg2_immed8_b), new Instruction("ORHI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("ORI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("XOR", reg3_r, reg3_b), new Instruction("XORBI",reg2_immed8_r, reg2_immed8_b), new Instruction("XORHI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("XORI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("NAND", reg3_r, reg3_b), new Instruction("NOR", reg3_r, reg3_b), new Instruction("EQV", reg3_r, reg3_b), new Instruction("SELB", reg4_r, reg4_b), new Instruction("SHUFB",reg4_r, reg4_b), new Instruction("SHLH", reg3_r, reg3_b), new Instruction("SHLHI",reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("SHL", reg3_r, reg3_b), new Instruction("SHLI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("SHLQBY", reg3_r, reg3_b), new Instruction("SHLQBYI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("SHLQBI", reg3_r, reg3_b), new Instruction("SHLQBYBI", reg3_r, reg3_b), new Instruction("SHLQBII", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROTH", reg3_r, reg3_b), new Instruction("ROTHI",reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROT", reg3_r, reg3_b), new Instruction("ROTI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROTM", reg3_r, reg3_b), new Instruction("ROTMI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROTMA", reg3_r, reg3_b), new Instruction("ROTMAI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROTQBY", reg3_r, reg3_b), new Instruction("ROTQBYI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROTQBYBI", reg3_r, reg3_b), new Instruction("ROTQBI", reg3_r, reg3_b), new Instruction("ROTQMBY", reg3_r, reg3_b), new Instruction("ROTQMBYI", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("ROTQMBYBI", reg3_r, reg3_b), new Instruction("ROTQMBI", reg3_r, reg3_b), new Instruction("ROTQMBII", reg2_immed7_r, reg2_immed7_b, IMMED_NEG), new Instruction("CEQB", reg3_r, reg3_b), new Instruction("CEQBI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CEQH", reg3_r, reg3_b), new Instruction("CEQHI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CEQ", reg3_r, reg3_b), new Instruction("CEQI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CGTB", reg3_r, reg3_b), new Instruction("CGTBI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CGTH", reg3_r, reg3_b), new Instruction("CGTHI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CGT", reg3_r, reg3_b), new Instruction("CGTI", reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CLGTB",reg3_r, reg3_b), new Instruction("CLGTBI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CLGTH",reg3_r, reg3_b), new Instruction("CLGTHI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("CLGT", reg3_r, reg3_b), new Instruction("CLGTI",reg2_immed10_r, reg2_immed10_b, IMMED_NEG), new Instruction("BR", immed16_r, immed16_b, "_", IMMED_NEG | IMMED_HEX | SHFT_IMMED_2 | IMMED_REL), new Instruction("BRA", immed16_r, immed16_b, IMMED_NEG | IMMED_HEX | SHFT_IMMED_2), new Instruction("BRSL", reg_immed16_r, reg_immed16_b, "_",IMMED_NEG | IMMED_HEX | SHFT_IMMED_2 | IMMED_REL), new Instruction("BRASL",reg_immed16_r, reg_immed16_b, IMMED_NEG | IMMED_HEX | SHFT_IMMED_2), new Instruction("BI", reg1_r, reg1_b), new Instruction("BIE", reg1_r, reg1_b), new Instruction("BID", reg1_r, reg1_b), new Instruction("BISL", reg2_r, reg2_b), new Instruction("BISLE",reg2_r, reg2_b), new Instruction("BISLD",reg2_r, reg2_b), new Instruction("BRNZ", reg_immed16_r, reg_immed16_b, "_", IMMED_NEG | IMMED_HEX | SHFT_IMMED_2 | IMMED_REL), new Instruction("BRZ", reg_immed16_r, reg_immed16_b, "_", IMMED_NEG | IMMED_HEX | SHFT_IMMED_2 | IMMED_REL), new Instruction("BIZ", reg2_r, reg2_b), new Instruction("BIZE", reg2_r, reg2_b), new Instruction("BIZD", reg2_r, reg2_b), new Instruction("BINZ", reg2_r, reg2_b), new Instruction("BINZE",reg2_r, reg2_b), new Instruction("BINZD",reg2_r, reg2_b), new Instruction("FA", reg3_r, reg3_b), new Instruction("DFA", reg3_r, reg3_b), new Instruction("FS", reg3_r, reg3_b), new Instruction("DFS", reg3_r, reg3_b), new Instruction("FM", reg3_r, reg3_b), new Instruction("DFM", reg3_r, reg3_b), new Instruction("CSFLT",reg2_immed8_r, reg2_immed8_b, FROM_155), new Instruction("CFLTS",reg2_immed8_r, reg2_immed8_b, FROM_173), new Instruction("CUFLT",reg2_immed8_r, reg2_immed8_b, FROM_155), new Instruction("CFLTU",reg2_immed8_r, reg2_immed8_b, FROM_173), new Instruction("FMA", reg4_r, reg4_b), new Instruction("FMS", reg4_r, reg4_b), new Instruction("FNMS", reg4_r, reg4_b), new Instruction("FRDS", reg2_r, reg2_b), new Instruction("FI", reg3_r, reg3_b), new Instruction("FESD", reg2_r, reg2_b), new Instruction("FCEQ", reg3_r, reg3_b), new Instruction("FCGT", reg3_r, reg3_b), new Instruction("DFCEQ", reg3_r, reg3_b), new Instruction("DFCGT", reg3_r, reg3_b), new Instruction("FREST",reg2_r, reg2_b), new Instruction("NOP", none_r, none_b), new Instruction("SYNC", none_r, none_b), new Instruction("SYNCC",none_r, none_b), new Instruction("DSYNC",none_r, none_b), new Instruction("STOP", immed14_r, immed14_b, DONT_CHECK_ARG), new Instruction("RDCH",reg2_r, chan_b, CHAN_READ_FORM), new Instruction("RCHCNT",reg2_r, chan_b, CHAN_READ_FORM), new Instruction("WRCH",reg2_r, chan_b, CHAN_WRITE_FORM) }; try { for (int i=0; i<instructions.length; i++) { Instruction inst = instructions[i]; Class<VM_Assembler> asmClass = VM_Assembler.class; Method emitMethod = asmClass.getDeclaredMethod(inst.methodPrefix + "emit" + inst.name, inst.arg_types); emitMethod.invoke(asm, inst.arg_vals_o); } } catch (Exception e) { System.out.println(e); e.printStackTrace(); } asm.dumpInstructions(new File("dump_cell_spu.bin")); asm.finalizeMachineCode(new int[2]); try { String line; boolean startedDump = false; boolean success = true; int i = 0; // wrap assembly into elf format Process ldProc = Runtime.getRuntime().exec("spu-ld -r -b binary -o dump_cell_spu.o dump_cell_spu.bin"); ldProc.waitFor(); // dissasemble assembly Process objdumpProc = Runtime.getRuntime().exec("/opt/cell/toolchain/bin/spu-objdump -D dump_cell_spu.o"); BufferedReader input = new BufferedReader(new InputStreamReader(objdumpProc.getInputStream())); while ((line = input.readLine()) != null) { if (startedDump) { String paddingStr = " "; System.out.print(instructions[i].name + " : " + paddingStr.substring(instructions[i].name.length(), paddingStr.length())); String [] lineTokens = line.split("\\s+|:|,|\\(|\\)"); if (!lineTokens[7].equalsIgnoreCase(instructions[i].name)) { System.out.println("[Fail]"); System.out.println(" : Instruction emitted - " + lineTokens[7] + " should have been - " + instructions[i].name); success = false; } else if (!instructions[i].checkArgs(Arrays.copyOfRange(lineTokens, 8, lineTokens.length))) { System.out.println("[Fail]"); System.out.println(instructions[i].argsErrors); success = false; } else { System.out.println("[Pass]"); } i++; } else { if (line.contains("_binary_dump_cell_spu_bin_start")) { startedDump = true; } } } input.close(); // emit null check test System.out.println("\nCreating null check test"); asm = new org.jikesrvm.SubordinateArchitecture.VM_Assembler(1024); asm.emitILA(TRAP_ENTRY_REG, 0x1000); asm.emitIL(3, 0x1234); asm.emitNullCheck(3); asm.emitIL(3, 0); asm.emitNullCheck(3); asm.dumpInstructions(new File("null_check.bin")); //mc = asm.finalizeMachineCode(new int[0]); Process objCpyProc = Runtime.getRuntime().exec("spu-objcopy -I binary -O elf32-spu null_check.bin null_check.o"); objCpyProc.waitFor(); ldProc = Runtime.getRuntime().exec("spu-ld null_check.o -o null_check"); ldProc.waitFor(); // emit stack overflow check System.out.println("\nCreating stack overflow check test"); asm = new org.jikesrvm.SubordinateArchitecture.VM_Assembler(1024); asm.emitILA(TRAP_ENTRY_REG, 0x1000); asm.emitILA(FP, 0x3080); asm.emitILA(3, 0x3000); asm.emitStackOverflowCheck(0x40); asm.emitStackOverflowCheck(0x80); asm.emitStackOverflowCheck(0x100); asm.dumpInstructions(new File("stack_check.bin")); //mc = asm.finalizeMachineCode(new int[0]); objCpyProc = Runtime.getRuntime().exec("spu-objcopy -I binary -O elf32-spu stack_check.bin stack_check.o"); objCpyProc.waitFor(); ldProc = Runtime.getRuntime().exec("spu-ld stack_check.o -o stack_check"); ldProc.waitFor(); if (success) { System.out.println("\nOverall - [Pass]"); } else { System.out.println("\nOverall - [Fail]"); } } catch (Exception err) { err.printStackTrace(); } } private void dumpInstructions(File file) { mc.dumpInstructions(file); } }