/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ // PPCInstructions.h // // Scott M. Silver // Peter Desantis #ifndef _H_PPCINSTRUCTIONS #define _H_PPCINSTRUCTIONS #include "prtypes.h" #include "Instruction.h" #include "ControlNodes.h" typedef Uint8 PPCInsnFlags; enum { pfNil = 0x00, // nothing special pfRc = 0x01, // sets a condition code pfOE = 0x02 // set the overflow flag }; #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊPPCInstructionXY ¥ #endif // PPCInstructionXY // // Base class for all PPC instructions class PPCInstructionXY : public InsnUseXDefineYFromPool { public: inline PPCInstructionXY(DataNode* inPrimitive, Pool& inPool, Uint8 inX, Uint8 inY) : InsnUseXDefineYFromPool(inPrimitive, inPool, inX, inY) { } virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return (4); } }; // Fixed point color to register map. const Uint8 sFixedPointRegisterMap[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, // -> first non-volatile 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14 // 13 // -> last non-volatile, but used as globals }; const Uint8 sFloatingPointRegisterMap[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // -> first non-volatile 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 // -> last non-volatile }; // udToRegisterNumber // // Map colors of registers to real register numbers inline Uint8 udToRegisterNumber(InstructionUseOrDefine& inUse) { Uint32 color = inUse.getVirtualRegister().colorInfo.color; if (inUse.getVirtualRegister().getClass() == vrcInteger) { if (color < sizeof(sFixedPointRegisterMap) / sizeof(Uint8)) return (sFixedPointRegisterMap[color]); #ifdef DEBUG else return 255; #endif } else if (inUse.getVirtualRegister().getClass() == vrcFloatingPoint) { if (color < sizeof(sFloatingPointRegisterMap) / sizeof(Uint8)) return (sFloatingPointRegisterMap[color]); #ifdef DEBUG else return 255; #endif } else assert(false); return 255; // never reached } #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊD-Form ¥ #endif #define MAKE_DFORM_ENUM(inName) df##inName, #define DFORM_ARITH_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DFORM_ARITHCC_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DFORM_LOAD_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DFORM_LOADU_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DFORM_STORE_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DFORM_STOREU_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DFORM_TRAP_DEFINE(inName, inOpcode) MAKE_DFORM_ENUM(inName) #define DO_DFORM enum DFormKind { #include "PPCInstructionTemplates.h" dfLast }; #undef DFORM_ARITH_DEFINE #undef DFORM_ARITHCC_DEFINE #undef DFORM_LOAD_DEFINE #undef DFORM_LOADU_DEFINE #undef DFORM_STORE_DEFINE #undef DFORM_STOREU_DEFINE #undef DFORM_TRAP_DEFINE struct DFormInstructionInfo { Uint16 opcode; char* formatStr; }; #define MAKE_DFORM_INFO(inOpcode, inString) \ { inOpcode, inString }, #define DFORM_ARITH_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName" r%d, r%d, %d") #define DFORM_ARITHCC_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName" r%d, r%d, %d") #define DFORM_LOAD_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName" r%d, %d(r%d)") #define DFORM_LOADU_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName" r%d, %d(r%d)") #define DFORM_STORE_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName" r%d, %d(r%d)") #define DFORM_STOREU_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName" r%d, %d(r%d)") #define DFORM_TRAP_DEFINE(inName, inOpcode) MAKE_DFORM_INFO(inOpcode, #inName"%s r%d, %d") const DFormInstructionInfo sDFormInfos[] = { #include "PPCInstructionTemplates.h" }; #undef DO_DFORM class DFormXY : public PPCInstructionXY { public: inline DFormXY(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint8 inX, Uint8 inY) : PPCInstructionXY(inPrimitive, inPool, inX, inY), mKind(inKind) { } virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/); protected: Uint8 getOPCD() { return (sDFormInfos[mKind].opcode); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionDefineBegin()[0])); } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } virtual Uint16 getIMM() = 0; const Uint16 mKind; #ifdef DEBUG public: virtual void printPretty(FILE* f) {fprintf(f, sDFormInfos[mKind].formatStr, getD(), getA(), getIMM());} #endif }; class DFormXYImmediate : public DFormXY { public: inline DFormXYImmediate(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint8 inX, Uint8 inY, Uint16 inImmediate) : mImmediate(inImmediate), DFormXY(inPrimitive, inPool, inKind, inX, inY) { } virtual Uint16 getIMM() { return mImmediate; } Uint16 mImmediate; // immediate value }; template class LdD : public DFormXYImmediate { public: inline LdD(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate) : DFormXYImmediate(inPrimitive, inPool, inKind, tUses, tDefines, inImmediate) { } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[tAOffset])); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionDefineBegin()[tDOffset])); } }; template class LdD_FixedSource : public LdD<0, 1, 0, 0> { public: inline LdD_FixedSource(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate) : LdD<0, 1, 0, 0>(inPrimitive, inPool, inKind, inImmediate) { assert (tFixedSourceRegister < 32); } virtual Uint8 getA() { return (tFixedSourceRegister); } }; // the formatToMemory routine does a fix-up // based on the real toc offset class LdD_RTOC : public LdD_FixedSource<2> { public: inline LdD_RTOC(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate) : LdD_FixedSource<2>(inPrimitive, inPool, inKind, inImmediate) { } virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& inFormatter); }; typedef LdD<2, 1, 1, 0> LdD_; // Rvalue | mem Raddress typedef LdD<2, 2, 1, 1> LdD_V; // mem Rvalue | mem Raddress // Rvalue | Sstackslot class LdD_SpillRegister : public LdD<1, 1, 0, 0> { public: inline LdD_SpillRegister(DataNode* inPrimitive, Pool& inPool, VirtualRegister& inStackSlot, VirtualRegister& inDefine) : LdD<1, 1, 0, 0>(inPrimitive, inPool, dfLwz, 0) { addUse(0, inStackSlot); addDefine(0, inDefine); } // FIX-ME what about 64 bit fregs. virtual Uint16 getIMM() { return ((Uint16)(getInstructionUseBegin()[0].getVirtualRegister().getColor() * -4) - 4); } virtual Uint8 getA() { return (1); } }; // -- // mem | mem Raddress Rvalue class StD : public DFormXYImmediate { public: inline StD(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Int16 inImmediate, Uint8 inUses = 3, Uint8 inDefines = 1) : DFormXYImmediate(inPrimitive, inPool, inKind, inUses, inDefines, inImmediate) { } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[1])); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionUseBegin()[2])); } #ifdef DEBUG public: virtual void printPretty(FILE* f) {fprintf(f, sDFormInfos[mKind].formatStr, getD(), getA(), getIMM());} #endif }; // Sstackslot | Rvalue class StD_SpillRegister : public StD { public: inline StD_SpillRegister(DataNode* inPrimitive, Pool& inPool, VirtualRegister& inStackSlot, VirtualRegister& inUse) : StD(inPrimitive, inPool, dfStw, 0, 1, 1) { addDefine(0, inStackSlot); addUse(0, inUse); } virtual Uint16 getIMM() { return ((Uint16)(getInstructionUseBegin()[0].getVirtualRegister().getColor() * -4) - 4); } virtual Uint8 getA() { return (1); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } }; // mem | mem value template class StD_FixedDestRegister : public StD { public: inline StD_FixedDestRegister(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate) : StD(inPrimitive, inPool, inKind, inImmediate, 2, 1) { } virtual Uint8 getA() { return (tFixedDestRegister); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionUseBegin()[1])); } }; class ArithID : public DFormXYImmediate { public: inline ArithID(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Int16 inImmediate) : DFormXYImmediate(inPrimitive, inPool, inKind, 1, 1, inImmediate) { } virtual InstructionFlags getFlags() const { return ((mImmediate == 0 && mKind == dfAddi) ? ifCopy : ifNone); } }; class LogicalID : public DFormXYImmediate { public: inline LogicalID(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Int16 inImmediate) : DFormXYImmediate(inPrimitive, inPool, inKind, 1, 1, inImmediate) { } Uint8 getA() { return (udToRegisterNumber(getInstructionDefineBegin()[0])); } Uint8 getD() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } virtual InstructionFlags getFlags() const { return ((mImmediate == 0 && mKind == dfAddi) ? ifCopy : ifNone); } }; class ArithIZeroInputD : public DFormXYImmediate { public: inline ArithIZeroInputD(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate, Uint8 inFakeUses = 0) : DFormXYImmediate(inPrimitive, inPool, inKind, inFakeUses, 1, inImmediate) { } Uint8 getA() { return (0); } }; class LogicalIZeroInputD : public DFormXYImmediate { public: inline LogicalIZeroInputD(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate, Uint8 inFakeUses = 0) : DFormXYImmediate(inPrimitive, inPool, inKind, inFakeUses, 1, inImmediate) { } Uint8 getA() { return (udToRegisterNumber(getInstructionDefineBegin()[0])); } Uint8 getD() { return (0); } }; class Copy_I : public ArithID { public: inline Copy_I(DataNode* inPrimitive, Pool& inPool) : ArithID(inPrimitive, inPool, dfAddi, 0) { } }; class ArithIDSetCC : public DFormXYImmediate { public: inline ArithIDSetCC(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate) : DFormXYImmediate(inPrimitive, inPool, inKind, 2, 2, inImmediate) { } }; class CmpID : public DFormXYImmediate { public: inline CmpID(DataNode* inPrimitive, Pool& inPool, DFormKind inKind, Uint16 inImmediate) : DFormXYImmediate(inPrimitive, inPool, inKind, 1, 1, inImmediate) { } protected: virtual Uint8 getD() { return (0); } // always use cr0, and L=0 #ifdef DEBUG public: virtual void printPretty(FILE* f) { fprintf(f, sDFormInfos[mKind].formatStr, getD() >> 2, getA(), getIMM()); } #endif }; // the bits in order (or offsets into a condition register) // neg (lt) // pos (gt) // zero (eq) // summary overflow (so) // 0010y branch if cond is false // 0110y branch if cond is true struct TrapCondition { char* name; Uint8 to; }; // indexed by Condition2 static TrapCondition sSignedTrapConditions[] = { {"", 31}, {"lt", 16}, {"eq", 4}, {"le", 20}, {"gt", 8}, {"ne", 24}, {"ge", 12} }; // indexed by Condition2 static TrapCondition sUnsignedTrapConditions[] = { {"", 31}, {"llt", 2}, {"eq", 4}, {"lle", 6}, {"lgt", 1}, {"ne", 24}, {"lge", 5} }; class TrapD : public DFormXYImmediate { public: inline TrapD(DataNode* inPrimitive, Pool& inPool, Condition2 inCondition, bool inSigned, Uint16 inImmediate) : DFormXYImmediate(inPrimitive, inPool, dfTwi, 1, 0, inImmediate), mSigned(inSigned), mCond(inCondition) { } protected: virtual Uint8 getD() { return (mSigned ? sSignedTrapConditions[mCond].to : sUnsignedTrapConditions[mCond].to); } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } const bool mSigned; const Condition2 mCond; #ifdef DEBUG public: virtual void printPretty(FILE* f) { fprintf(f, sDFormInfos[mKind].formatStr, mSigned ? sSignedTrapConditions[mCond].name : sUnsignedTrapConditions[mCond].name, getA(), getIMM()); } #endif }; #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊX & XO-Form ¥ #endif #define MAKE_XFORM_ENUM(inName) xf##inName, #define XFORM_ARITH_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_INAONLY_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_CMP_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_LOAD_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_LOADU_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_STORE_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_STOREU_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_TRAP_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define XFORM_INBONLY_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_ENUM(inName) #define DO_XFORM enum XFormKind { #include "PPCInstructionTemplates.h" xfLast }; #undef XFORM_ARITH_DEFINE #undef XFORM_INAONLY_DEFINE #undef XFORM_CMP_DEFINE #undef XFORM_LOAD_DEFINE #undef XFORM_LOADU_DEFINE #undef XFORM_STORE_DEFINE #undef XFORM_STOREU_DEFINE #undef XFORM_TRAP_DEFINE #undef XFORM_INBONLY_DEFINE struct XFormInstructionInfo { Uint16 opcode; Uint16 primary; char* formatStr; }; #define MAKE_XFORM_INFO(inOpcode, inPrimary, inString) \ { inOpcode, inPrimary, inString }, #define XFORM_ARITH_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_INAONLY_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_CMP_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_LOAD_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_LOADU_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_STORE_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_STOREU_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_TRAP_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") #define XFORM_INBONLY_DEFINE(inName, inOpcode, inPrimary) MAKE_XFORM_INFO(inOpcode, inPrimary, #inName" r%d, r%d, r%d") const XFormInstructionInfo sXFormInfos[] = { #include "PPCInstructionTemplates.h" }; #undef DO_XFORM static char* sFlagsExtensionTbl[] = { "", // none ".", // pfRc "o", // pfOE "o." // pfRC | afOE }; class XFormXY : public PPCInstructionXY { public: inline XFormXY(DataNode* inPrimitive, Pool& inPool, Uint8 inX, Uint8 inY, XFormKind inKind, PPCInsnFlags inFlags) : PPCInstructionXY(inPrimitive, inPool, inX, inY), mFlags(inFlags), mKind(inKind) { } virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/); protected: virtual Uint8 getOPCD() { return (31); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionDefineBegin()[0])); } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } virtual Uint8 getB() { return (udToRegisterNumber(getInstructionUseBegin()[1])); } virtual Uint16 getXO() { return (sXFormInfos[mKind].opcode); } PPCInsnFlags mFlags; XFormKind mKind; #ifdef DEBUG public: virtual void printPretty(FILE* f) { fprintf(f, sXFormInfos[mKind].formatStr, flagsToExtension(), getD(), getA(), getB()); } const char* flagsToExtension() { return sFlagsExtensionTbl[mFlags & 3]; } // only look at OE and Rc bits #endif }; class TrapX : public XFormXY { public: inline TrapX(DataNode* inPrimitive, Pool& inPool, Condition2 inCondition, bool inSigned, PPCInsnFlags inFlags) : XFormXY(inPrimitive, inPool, 2, 0, xfTw, inFlags), mSigned(inSigned), mCond(inCondition) { } protected: virtual Uint8 getD() { return (mSigned ? sSignedTrapConditions[mCond].to : sUnsignedTrapConditions[mCond].to); } #ifdef DEBUG public: virtual void printPretty(FILE* f) { fprintf(f, sXFormInfos[mKind].formatStr, mSigned ? sSignedTrapConditions[mCond].name : sUnsignedTrapConditions[mCond].name, getA(), getB()); } #endif protected: bool mSigned; Condition2 mCond; }; template class LdX : public XFormXY { public: inline LdX(DataNode* inPrimitive, Pool& inPool, XFormKind inKind) : XFormXY(inPrimitive, inPool, inX, inY, inKind, pfNil) { assert(inKind >= xfLbzx && inKind <= xfLwzx); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionDefineBegin()[inD])); } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[inA])); } virtual Uint8 getB() { return (udToRegisterNumber(getInstructionUseBegin()[inB])); } }; typedef LdX<2, 1, 0, 0, 1> LdX_C; // Rvalue <- Raddress Radddress typedef LdX<3, 2, 1, 1, 2> LdX_V; // mem Rvalue Raddress <- mem Raddress Raddress typedef LdX<3, 1, 0, 1, 2> LdX_; // Rvalue <- mem Raddress Raddress // mem <- mem Raddress Raddress Value class StX : public XFormXY { public: inline StX(DataNode* inPrimitive, Pool& inPool, XFormKind inKind) : XFormXY(inPrimitive, inPool, 4, 1, inKind, pfNil) { assert(inKind >= xfStbx && inKind <= xfStwx); } virtual Uint8 getD() { return (udToRegisterNumber(getInstructionUseBegin()[3])); } virtual Uint8 getA() { return (udToRegisterNumber(getInstructionUseBegin()[1])); } virtual Uint8 getB() { return (udToRegisterNumber(getInstructionUseBegin()[2])); } }; class ArithX : public XFormXY { public: inline ArithX(DataNode* inPrimitive, Pool& inPool, XFormKind inKind, PPCInsnFlags inFlags) : XFormXY(inPrimitive, inPool, 2, ((inFlags & pfRc) == 0) ? 1 : 2, inKind, inFlags) { } }; class XOInAOnly : public XFormXY { public: // if we want to use the lswi, need to deal with memory edge inline XOInAOnly(DataNode* inPrimitive, Pool& inPool, XFormKind inKind, PPCInsnFlags inFlags) : XFormXY(inPrimitive, inPool, 1, ((inFlags & pfRc) == 0) ? 1 : 2, inKind, inFlags) {} protected: virtual Uint8 getA() { return 0; } }; class XInAOnly : public XFormXY { public: // if we want to use the lswi, need to deal with memory edge inline XInAOnly(DataNode* inPrimitive, Pool& inPool, XFormKind inKind, PPCInsnFlags inFlags, Uint8 inB) : XFormXY(inPrimitive, inPool, 1, ((inFlags & pfRc) == 0) ? 1 : 2, inKind, (inFlags | pfOE)), mB(inB) { } protected: virtual Uint8 getD() { return (XFormXY::getA()); } virtual Uint8 getA() { return (XFormXY::getD()); } virtual Uint8 getB() { assert (mB < (1 << 6)); return mB; } Uint8 mB; }; class XInBOnly : public XFormXY { public: inline XInBOnly(DataNode* inPrimitive, Pool& inPool, XFormKind inKind, PPCInsnFlags inFlags) : XFormXY(inPrimitive, inPool, 1, ((inFlags & pfRc) == 0) ? 1 : 2, inKind, inFlags) { } protected: virtual Uint8 getA() { return (0); } virtual Uint8 getB() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } virtual InstructionFlags getFlags() const { return ((mKind == xfFmr) ? ifCopy : ifNone); } Uint8 mA; }; class CmpIX : public XFormXY { public: inline CmpIX(DataNode* inPrimitive, Pool& inPool, XFormKind inKind, PPCInsnFlags inFlags) : XFormXY(inPrimitive, inPool, 2, 1, inKind, inFlags) { } protected: virtual Uint8 getD() { return (0); } // always use cr0 }; class CmpFX : public XFormXY { public: inline CmpFX(DataNode* inPrimitive, Pool& inPool, XFormKind inKind, PPCInsnFlags inFlags) : XFormXY(inPrimitive, inPool, 2, 1, inKind, inFlags) { } protected: virtual Uint8 getD() { return (0); } // always use cr0 }; #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊIForm ¥ #endif class BranchI : public PPCInstructionXY { public: inline BranchI(DataNode* inPrimitive, Pool& inPool, ControlNode& inTarget, bool inAbsolute = false, bool inLink = false) : PPCInstructionXY(inPrimitive, inPool, 0, 0), mTarget(inTarget) { mIForm.OPCD = 18; mIForm.LI = 0; mIForm.AA = inAbsolute; mIForm.LK = inLink;} virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/); #ifdef DEBUG virtual void printPretty(FILE* f) { fprintf(f, "bxx %d", mTarget.getNativeOffset()); } #endif protected: ControlNode& mTarget; struct { int OPCD:6; int LI:24; int AA:1; int LK:1; } mIForm; }; #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊIForm ¥ #endif // the bits in order (or offsets into a condition register) // neg (lt) // pos (gt) // zero (eq) // summary overflow (so) // 0010y branch if cond is false // 0110y branch if cond is true struct BranchCondition { char* name; Uint8 bo; Uint8 bi; }; // indexed by Condition2 const BranchCondition sBranchConditions[] = { {"always", 0, 0}, {"lt", 12, 0}, {"eq", 12, 2}, {"le", 4, 1}, {"gt", 12, 1}, {"ne", 4, 2}, {"ge", 4, 0} }; #if 0 BO BI cond0, // 0000 Always false condLt, // 0001 arg1 < arg2 0110y 0 lt condEq, // 0010 arg1 = arg2 0110y 2 eq condLe, // 0011 arg1 <= arg2 0010y 1 not gt condGt, // 0100 arg1 > arg2 0110y 1 gt condLgt, // 0101 arg1 <> arg2 0010y 2 not eq condGe, // 0110 arg1 >= arg2 0010y 0 not lt -- only up to these are supported condOrd, // 0111 arg1 <=> arg2 (i.e. arg1 and arg2 are ordered) 0110y 3 so ?? nan condUnord, // 1000 arg1 ? arg2 (i.e. arg1 and arg2 are unordered) 0010y 3 not so condULt, // 1001 arg1 ?< arg2 do we have to deal with these below here?? condUEq, // 1010 arg1 ?= arg2 condULe, // 1011 arg1 ?<= arg2 condUGt, // 1100 arg1 ?> arg2 condNe, // 1101 arg1 != arg2 condUGe, // 1110 arg1 ?>= arg2 cond1 // 1111 Always true #endif class BranchCB : public PPCInstructionXY { public: BranchCB(DataNode* inPrimitive, Pool& inPool, ControlNode& inTarget, Condition2 inCondition, bool inAbsolute = false, bool inLink = false); virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/); protected: ControlNode& mTarget; struct { unsigned int OPCD:6; unsigned int BO:5; // unsigned int Y:1; unsigned int BI:5; unsigned int BD:14; unsigned int AA:1; unsigned int LK:1; } mCForm; #if DEBUG public: virtual void printPretty(FILE* f) { fprintf(f, "b%s %d", sBranchConditions[mCond].name, mTarget.getNativeOffset()); } protected: Condition2 mCond; #endif }; #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊM-Form ¥ #endif #define DO_MFORM struct MFormInstructionInfo { Uint16 opcode; char* formatStr; }; #define MAKE_MFORM_ENUM(inName) mf##inName, #define MFORM_DEFINE(inName, inOpcode) MAKE_MFORM_ENUM(inName) enum MFormKind { #include "PPCInstructionTemplates.h" mfLast }; #undef MFORM_DEFINE #define MAKE_MFORM_INFO(inName, inOpcode) \ { inOpcode, #inName"%s r%d, r%d, r%d, %d, %d"}, #define MFORM_DEFINE(inName, inOpcode) MAKE_MFORM_INFO(inName, inOpcode) const MFormInstructionInfo sMFormInfos[] = { #include "PPCInstructionTemplates.h" }; #undef MFORM_DEFINE #undef DO_MFORM class MForm : public PPCInstructionXY { public: inline MForm(DataNode* inPrimitive, Pool& inPool, Uint8 inUses, MFormKind inKind, Uint8 inMaskBegin, Uint8 inMaskEnd, PPCInsnFlags inFlags) : PPCInstructionXY(inPrimitive, inPool, inUses, 1 + (bool) (inFlags & pfRc)), mFlags(inFlags), mKind(inKind), mMaskBegin(inMaskBegin), mMaskEnd(inMaskEnd) { } virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/); protected: Uint16 getOPCD() { return (sXFormInfos[mKind].opcode); } Uint8 getS() { return (udToRegisterNumber(getInstructionUseBegin()[0])); } Uint8 getA() { return (udToRegisterNumber(getInstructionDefineBegin()[0])); } virtual Uint8 getB() { return (udToRegisterNumber(getInstructionUseBegin()[1])); } Uint8 getMB() { return (mMaskBegin); } Uint8 getME() { return (mMaskEnd); } #ifdef DEBUG public: virtual void printPretty(FILE* f) { fprintf(f, sMFormInfos[mKind].formatStr, flagsToExtension(), getA(), getS(), getB(), getMB(), getME()); } protected: const char* flagsToExtension() { return sFlagsExtensionTbl[mFlags & 1]; /* only look at Rc bit */ } #endif PPCInsnFlags mFlags; MFormKind mKind; Uint8 mMaskBegin; Uint8 mMaskEnd; }; class MFormInAOnly : public MForm { public: inline MFormInAOnly(DataNode* inPrimitive, Pool& inPool, MFormKind inKind, Uint8 inB, Uint8 inMaskBegin, Uint8 inMaskEnd, PPCInsnFlags inFlags) : MForm(inPrimitive, inPool, 1, inKind, inMaskBegin, inMaskEnd, inFlags), mB(inB) { } protected: virtual Uint8 getB() { return (mB); } Uint8 mB; }; #ifdef __MWERKS__ #pragma mark - #pragma mark ¥ÊA-Form ¥ #endif #define DO_AFORM #define MAKE_AFORM_ENUM(inName) af##inName, #define AFORM_DEFINE(inName, inOpcode, inXo, inHasA, inHasB, inHasC, inRc) MAKE_AFORM_ENUM(inName) enum AFormKind { #include "PPCInstructionTemplates.h" afLast }; #undef AFORM_DEFINE template class AForm : public PPCInstructionXY { public: inline AForm(DataNode* inPrimitive, Pool& inPool, AFormKind inKind) : PPCInstructionXY(inPrimitive, inPool, tHasA + tHasB + tHasC, tRc + 1), mKind(inKind) {} protected: Uint16 getOPCD() { return (sAFormInfos[mKind].opcode); } Uint8 getD() { return (udToRegisterNumber(getInstructionDefineBegin()[0])); } Uint8 getA() { return (tHasA ? udToRegisterNumber(getInstructionUseBegin()[0]) : 0); } Uint8 getB() { return (tHasB ? udToRegisterNumber(getInstructionUseBegin()[tHasA]) : 0); } Uint8 getC() { return (tHasC ? udToRegisterNumber(getInstructionUseBegin()[tHasA + tHasB]) : 0); } public: virtual void formatToMemory(void* inStart, Uint32 /*inOffset*/, MdFormatter& /*inFormatter*/) { struct { uint OPCD:6; uint D:5; uint A:5; uint B:5; uint C:5; uint XO:5; uint RC:1; } aForm; aForm.OPCD = sAFormInfos[mKind].opcode; aForm.D = getD(); aForm.A = getA(); aForm.B = getB(); aForm.C = getC(); aForm.XO = sAFormInfos[mKind].xo; aForm.RC = tRc; *(Uint32*) inStart = *(Uint32*) &aForm; } static Instruction& createInstruction(DataNode& inPrimitive, Pool& mPool, AFormKind inKind) { return *new(mPool) AForm(&inPrimitive, mPool, inKind); } protected: const AFormKind mKind; #ifdef DEBUG public: virtual void printPretty(FILE* /*f*/) {} protected: const char* flagsToExtension() { return sFlagsExtensionTbl[tRc]; } // only look at Rc bit #endif }; struct AFormInstructionInfo { Uint16 opcode; Uint16 xo; Instruction& (*creatorFunction)(DataNode&, Pool&, AFormKind); char* formatStr; }; #define MAKE_AFORM_INFO(inName, inOpcode, inXo, inHasA, inHasB, inHasC, inRc) \ { inOpcode, inXo, AForm::createInstruction, #inName"%s r%d, r%d, r%d, %d, %d"}, #define AFORM_DEFINE(inName, inOpcode, inXo, inHasA, inHasB, inHasC, inRc) MAKE_AFORM_INFO(inName, inOpcode, inXo, inHasA, inHasB, inHasC, inRc) const AFormInstructionInfo sAFormInfos[] = { #include "PPCInstructionTemplates.h" }; #undef AFORM_DEFINE #undef DO_AFORM #endif // _H_PPCINSTRUCTIONS