dmose%mozilla.org 2ccab49e6d updating license boilerplate to xPL v1.1
git-svn-id: svn://10.0.0.236/trunk@52526 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 06:38:29 +00:00

960 lines
28 KiB
C++

/* -*- 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<Uint8 tUses, Uint8 tDefines, Uint8 tAOffset, Uint8 tDOffset>
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<Uint8 tFixedSourceRegister>
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<Uint8 tFixedDestRegister>
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<Uint8 inX, Uint8 inY, Uint8 inD, Uint8 inA, Uint8 inB>
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 <bool tHasA, bool tHasB, bool tHasC, bool tRc>
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<tHasA, tHasB, tHasC, tRc>(&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<inHasA, inHasB, inHasC, inRc>::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