#ifndef COMPILER_PCODE_H #define COMPILER_PCODE_H #include "compiler/common.h" #include "compiler/PCodeInfo.h" #ifdef __MWERKS__ #pragma options align=mac68k #endif #define FLAG_SET_T(flags) (((flags) & (fPCodeFlag1 | fPCodeFlag8)) ? (flags) : 0) #define FLAG_SET_F(flags) (((flags) & (fPCodeFlag1 | fPCodeFlag8)) ? 0 : (flags)) #define PCODE_FLAG_SET_T(pcode) (((pcode)->flags & (fPCodeFlag1 | fPCodeFlag8)) ? (pcode)->flags : 0) #define PCODE_FLAG_SET_F(pcode) (((pcode)->flags & (fPCodeFlag1 | fPCodeFlag8)) ? 0 : (pcode)->flags) enum { EffectRead = 1, EffectWrite = 2, Effect4 = 4, Effect8 = 8, Effect40 = 0x40 // spilled register? }; /*typedef enum { PCOp_REGISTER, PCOp_SYSREG, PCOp_IMMEDIATE, PCOp_MEMORY, PCOp_LABEL, PCOp_LABELDIFF, PCOp_PLACEHOLDEROPERAND } PCOpKind;*/ typedef enum { RefType_0, RefType_1, // like D, but 32-bit? RefType_2, // matches MW_RELOC_3? RefType_3, // matches MW_RELOC_4? RefType_4, RefType_5, RefType_6, // LO16? RefType_7, // HI16? RefType_8, // HA16? RefType_9, RefType_A, // another LO RefType_B, // another HA RefType_C, // another HA RefType_D // another LO } PCRefType; struct PCodeArg { PCOpKind kind; RegClass arg; union { struct { unsigned short effect; short reg; } reg; struct { SInt32 value; Object *obj; } imm; struct { SInt32 offset; Object *obj; } mem; struct { PCodeLabel *label; } label; struct { SInt16 offset; PCodeLabel *labelA; PCodeLabel *labelB; } labeldiff; unsigned char placeholder[10]; // keep the size } data; }; #define PC_OP_IS_REGISTER(_op, _rclass, _reg) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass) && \ (_op)->data.reg.reg == (_reg)) #define PC_OP_IS_READ_REGISTER(_op, _rclass, _reg) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass) && \ (_op)->data.reg.reg == (_reg) && \ ((_op)->data.reg.effect & EffectRead)) #define PC_OP_IS_WRITE_REGISTER(_op, _rclass, _reg) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass) && \ (_op)->data.reg.reg == (_reg) && \ ((_op)->data.reg.effect & EffectWrite)) #define PC_OP_IS_R_OR_W_REGISTER(_op, _rclass, _reg) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass) && \ (_op)->data.reg.reg == (_reg) && \ ((_op)->data.reg.effect & (EffectRead | EffectWrite))) #define PC_OP_IS_ANY_REGISTER(_op, _rclass) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass)) #define PC_OP_IS_READ_ANY_REGISTER(_op, _rclass) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass) && \ ((_op)->data.reg.effect & EffectRead)) #define PC_OP_IS_WRITE_ANY_REGISTER(_op, _rclass) \ ((_op)->kind == PCOp_REGISTER && \ (_op)->arg == (_rclass) && \ ((_op)->data.reg.effect & EffectWrite)) struct PCode { PCode *nextPCode; PCode *prevPCode; PCodeBlock *block; int useID; int defID; UInt32 flags; struct Alias *alias; SInt32 sourceoffset; short op; short argCount; PCodeArg args[0]; }; struct PCodeLabel { PCodeLabel *nextLabel; PCodeBlock *block; short resolved; unsigned short index; }; typedef struct _PCLink { struct _PCLink *nextLink; struct PCodeBlock *block; } PCLink; struct PCodeBlock { struct PCodeBlock *nextBlock; struct PCodeBlock *prevBlock; PCodeLabel *labels; PCLink *predecessors; PCLink *successors; PCode *firstPCode; PCode *lastPCode; int blockIndex; int codeOffset; // in bytes int loopWeight; short pcodeCount; unsigned short flags; }; /* PCode Flags */ enum { fPCodeFlag1 = 1, // some kinds of branches fPCodeFlag2 = 2, // read from memory fPCodeFlag4 = 4, // write to memory fPCodeFlag8 = 8, // other kinds of branches fPCodeFlag10 = 0x10, // moves fPCodeFlag20 = 0x20, // indexed operations // Always valid fIsConst = 0x40, fIsVolatile = 0x80, fSideEffects = 0x100, // instructions that do weird stuff with PPC state fPCodeFlag200 = 0x200, // ? fPCodeFlag400 = 0x400, // ? fPCodeFlag800 = 0x800, // ? fPCodeFlag1000 = 0x1000, // ? fCommutative = 0x2000, fIsCSE = 0x4000, fPCodeFlag8000 = 0x8000, fPCodeFlag20000 = 0x20000, // some kinda load? fPCodeFlag40000 = 0x40000, // some kinda store? // Set 1 (branches) only fLink = 0x1000000, fBranchNotTaken = 0x4000000, fBranchTaken = 0x8000000, fAbsolute = 0x10000000, // Set 2 (non-branches) only fIsPtrOp = 0x20, fOverflow = 0x800000, fSetsCarry = 0x10000000, fPCodeFlag20000000 = 0x20000000, // record bit? // ?? fPCodeFlag2000000 = 0x2000000, fPCodeFlag4000000 = 0x4000000, fPCodeFlag8000000 = 0x8000000, fPCodeFlag10000000 = 0x10000000, fPCodeFlag40000000 = 0x40000000, fPCodeFlag80000000 = 0x80000000, fPCodeFlagC0000000 = 0xC0000000 }; enum { fPCBlockFlag1 = 1, // fIsProlog fPCBlockFlag2 = 2, // fIsEpilogue fPCBlockFlag4 = 4, // fVisited fPCBlockFlag8 = 8, // fScheduled fPCBlockFlag10 = 0x10, // maybe fIsSwitch based off v3? fPCBlockFlag20 = 0x20, // fDeleted fPCBlockFlag2000 = 0x2000, fPCBlockFlag4000 = 0x4000, fPCBlockFlag6000 = 0x6000, fPCBlockFlag8000 = 0x8000 }; // v3 has fCCisLiveOnExit, fUnrolled, fAlignBlock extern PCodeBlock *pcbasicblocks; extern PCodeBlock *pclastblock; extern PCodeBlock *prologue; extern PCodeBlock *epilogue; extern PCodeBlock **depthfirstordering; extern int pcblockcount; extern int pcloopweight; extern void initpcode(void); extern PCode *makepcode(Opcode op, ...); extern void emitpcode(Opcode op, ...); extern PCode *copypcode(PCode *pcode); extern PCodeLabel *makepclabel(void); extern PCodeBlock *makepcblock(void); extern void pclabel(PCodeBlock *block, PCodeLabel *label); extern void pcbranch(PCodeBlock *block, PCodeLabel *label); extern void pccomputepredecessors(void); extern void deleteblock(PCodeBlock *block); extern void deleteunreachableblocks(void); extern void appendpcode(PCodeBlock *block, PCode *pcode); extern void deletepcode(PCode *pcode); extern void insertpcodebefore(PCode *anchor, PCode *newpcode); extern void insertpcodeafter(PCode *anchor, PCode *newpcode); extern void setpcodeflags(int flags); extern void clearpcodeflags(int flags); extern int pccomputeoffsets(void); extern void computedepthfirstordering(void); #ifdef __MWERKS__ #pragma options align=reset #endif #endif