CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/MIPS/IR/IRInst.h
Views: 1401
#pragma once12#include <cstdint>3#include <vector>4#include <utility>56#include "Common/CommonTypes.h"7#include "Core/MIPS/MIPS.h"89// Basic IR10//11// This IR refers implicitly to the MIPS register set and is simple to interpret.12// To do real compiler things with it and do full-function compilation, it probably13// needs to be lifted to a higher IR first, before being lowered onto each target.14// But this gets rid of a lot of MIPS idiosyncrasies that makes it tricky, like15// delay slots, and is very suitable for translation into other IRs. Can of course16// even be directly JIT-ed, but the gains will probably be tiny over our older direct17// MIPS->target JITs.1819// Ops beginning with "OI" are specialized for IR Interpreter use. These will not be produced20// for the IR JITs.2122enum class IROp : uint8_t {23SetConst,24SetConstF,2526Mov,2728Add,29Sub,30Neg,31Not,3233And,34Or,35Xor,3637AddConst,38OptAddConst,39SubConst,4041AndConst,42OrConst,43XorConst,44OptAndConst,45OptOrConst,4647Shl,48Shr,49Sar,50Ror,5152// The shift is stored directly, not in the const table, so Imm instead of Const53ShlImm,54ShrImm,55SarImm,56RorImm,5758Slt,59SltConst,60SltU,61SltUConst,6263Clz,6465// Conditional moves66MovZ,67MovNZ,6869Max,70Min,7172// Byte swaps. All CPUs have native ones so worth keeping.73BSwap16, // Swaps both the high and low byte pairs.74BSwap32,7576// Weird Hi/Lo semantics preserved. Too annoying to do something more generic.77MtLo,78MtHi,79MfLo,80MfHi,81Mult,82MultU,83Madd,84MaddU,85Msub,86MsubU,87Div,88DivU,8990// These take a constant from the pool as an offset.91// Loads from a constant address can be represented by using r0.92Load8,93Load8Ext,94Load16,95Load16Ext,96Load32,97Load32Left,98Load32Right,99Load32Linked,100LoadFloat,101LoadVec4,102103Store8,104Store16,105Store32,106Store32Left,107Store32Right,108Store32Conditional,109StoreFloat,110StoreVec4,111112Ext8to32,113Ext16to32,114ReverseBits,115116FAdd,117FSub,118FMul,119FDiv,120FMin,121FMax,122123FMov,124FSqrt,125FNeg,126FAbs,127FSign,128129FRound,130FTrunc,131FCeil,132FFloor,133134FCvtWS,135FCvtSW,136FCvtScaledWS,137FCvtScaledSW,138139FMovFromGPR,140OptFCvtSWFromGPR,141FMovToGPR,142OptFMovToGPRShr8,143144FSat0_1,145FSatMinus1_1,146147FpCondFromReg,148FpCondToReg,149FpCtrlFromReg,150FpCtrlToReg,151VfpuCtrlToReg,152153FCmp,154155FCmovVfpuCC,156FCmpVfpuBit,157FCmpVfpuAggregate,158159// Rounding Mode160RestoreRoundingMode,161ApplyRoundingMode,162UpdateRoundingMode,163164SetCtrlVFPU,165SetCtrlVFPUReg,166SetCtrlVFPUFReg,167168// 4-wide instructions to assist SIMD.169// Can of course add a pass to break them up if a target does not170// support SIMD.171Vec4Init,172Vec4Shuffle,173Vec4Blend,174Vec4Mov,175Vec4Add,176Vec4Sub,177Vec4Mul,178Vec4Div,179Vec4Scale,180Vec4Dot,181Vec4Neg,182Vec4Abs,183184// vx2i185Vec2Unpack16To31, // Note that the result is shifted down by 1, hence 31186Vec2Unpack16To32,187Vec4Unpack8To32,188Vec4DuplicateUpperBitsAndShift1, // Bizarro vuc2i behaviour, in an instruction. Split?189Vec4ClampToZero,190Vec2ClampToZero,191Vec4Pack31To8,192Vec4Pack32To8,193Vec2Pack31To16,194Vec2Pack32To16,195196// Slow special functions. Used on singles.197FSin,198FCos,199FRSqrt,200FRecip,201FAsin,202203// Fake/System instructions204Interpret,205206// Emit this before you exit. Semantic is to set the downcount207// that will be used at the actual exit.208Downcount, // src1 + (src2<<8)209210// End-of-basic-block.211ExitToConst, // 0, const, downcount212ExitToReg,213ExitToConstIfEq, // const, reg1, reg2214ExitToConstIfNeq, // const, reg1, reg2215ExitToConstIfGtZ, // const, reg1, 0216ExitToConstIfGeZ, // const, reg1, 0217ExitToConstIfLtZ, // const, reg1, 0218ExitToConstIfLeZ, // const, reg1, 0219220ExitToConstIfFpTrue,221ExitToConstIfFpFalse,222ExitToPC, // Used after a syscall to give us a way to do things before returning.223224Syscall,225SetPC, // hack to make syscall returns work226SetPCConst, // hack to make replacement know PC227CallReplacement,228Break,229230// Debugging breakpoints.231Breakpoint,232MemoryCheck,233234ValidateAddress8,235ValidateAddress16,236ValidateAddress32,237ValidateAddress128,238239// Tracing support.240LogIRBlock,241242Nop,243Bad,244};245246enum IRComparison {247Greater,248GreaterEqual,249Less,250LessEqual,251Equal,252NotEqual,253Bad,254};255256// Some common vec4 constants.257enum class Vec4Init {258AllZERO,259AllONE,260AllMinusONE,261Set_1000,262Set_0100,263Set_0010,264Set_0001,265};266267enum class IRRoundMode : uint8_t {268RINT_0 = 0,269CAST_1 = 1,270CEIL_2 = 2,271FLOOR_3 = 3,272};273274// Hm, unused275inline IRComparison Invert(IRComparison comp) {276switch (comp) {277case IRComparison::Equal: return IRComparison::NotEqual;278case IRComparison::NotEqual: return IRComparison::Equal;279case IRComparison::Greater: return IRComparison::LessEqual;280case IRComparison::GreaterEqual: return IRComparison::Less;281case IRComparison::Less: return IRComparison::GreaterEqual;282case IRComparison::LessEqual: return IRComparison::Greater;283default:284return IRComparison::Bad;285}286}287288inline IROp ComparisonToExit(IRComparison comp) {289switch (comp) {290case IRComparison::Equal: return IROp::ExitToConstIfEq;291case IRComparison::NotEqual: return IROp::ExitToConstIfNeq;292case IRComparison::Greater: return IROp::ExitToConstIfGtZ;293case IRComparison::GreaterEqual: return IROp::ExitToConstIfGeZ;294case IRComparison::Less: return IROp::ExitToConstIfLtZ;295case IRComparison::LessEqual: return IROp::ExitToConstIfLeZ;296default:297return IROp::Break;298}299}300301enum IRFpCompareMode {302False = 0,303EitherUnordered,304EqualOrdered, // eq, seq (equal, ordered)305EqualUnordered, // ueq, ngl (equal, unordered)306LessOrdered, // olt, lt (less than, ordered)307LessUnordered, // ult, nge (less than, unordered)308LessEqualOrdered, // ole, le (less equal, ordered)309LessEqualUnordered, // ule, ngt (less equal, unordered)310};311312typedef u8 IRReg;313314enum : IRReg {315IRTEMP_0 = 192,316IRTEMP_1,317IRTEMP_2,318IRTEMP_3,319IRTEMP_LHS, // Reserved for use in branches320IRTEMP_RHS, // Reserved for use in branches321IRTEMP_LR_ADDR, // Reserved for left/right loads and stores.322IRTEMP_LR_VALUE, // Reserved for left/right loads and stores.323IRTEMP_LR_MASK, // Reserved for left/right loads and stores.324IRTEMP_LR_SHIFT, // Reserved for left/right loads and stores.325326IRVTEMP_PFX_S = 224 - 32, // Relative to the FP regs327IRVTEMP_PFX_T = 228 - 32,328IRVTEMP_PFX_D = 232 - 32,329IRVTEMP_0 = 236 - 32,330331// Hacky way to get to other state332IRREG_VFPU_CTRL_BASE = 208,333IRREG_VFPU_CC = 211,334IRREG_LO = 242, // offset of lo in MIPSState / 4335IRREG_HI = 243,336IRREG_FCR31 = 244,337IRREG_FPCOND = 245,338IRREG_LLBIT = 250,339};340341enum IRFlags {342// Uses src3, not dest.343IRFLAG_SRC3 = 0x0001,344// Uses src3 AND dest (i.e. mutates dest.)345IRFLAG_SRC3DST = 0x0002,346// Exit instruction (maybe conditional.)347IRFLAG_EXIT = 0x0004,348// Instruction like Interpret which may read anything, but not an exit.349IRFLAG_BARRIER = 0x0008,350};351352struct IRMeta {353IROp op;354const char *name;355char types[5]; // GGG356u32 flags;357};358359// 64 bits.360struct IRInst {361IROp op;362union {363IRReg dest;364IRReg src3;365};366IRReg src1;367IRReg src2;368u32 constant;369};370371// Returns the new PC.372u32 IRInterpret(MIPSState *ms, const IRInst *inst);373374// Each IR block gets a constant pool.375class IRWriter {376public:377IRWriter &operator =(const IRWriter &w) {378insts_ = w.insts_;379return *this;380}381IRWriter &operator =(IRWriter &&w) {382insts_ = std::move(w.insts_);383return *this;384}385386void Write(IROp op, u8 dst = 0, u8 src1 = 0, u8 src2 = 0);387void Write(IROp op, IRReg dst, IRReg src1, IRReg src2, uint32_t c) {388AddConstant(c);389Write(op, dst, src1, src2);390}391void Write(IRInst inst) {392insts_.push_back(inst);393}394void WriteSetConstant(u8 dst, u32 value);395396int AddConstant(u32 value);397int AddConstantFloat(float value);398399void Reserve(size_t s) {400insts_.reserve(s);401}402void Clear() {403insts_.clear();404}405void ReplaceConstant(size_t instNumber, u32 newConstant);406407const std::vector<IRInst> &GetInstructions() const { return insts_; }408409private:410std::vector<IRInst> insts_;411u32 nextConst_ = 0;412};413414struct IROptions {415uint32_t disableFlags;416bool unalignedLoadStore;417bool unalignedLoadStoreVec4;418bool preferVec4;419bool preferVec4Dot;420bool optimizeForInterpreter;421};422423const IRMeta *GetIRMeta(IROp op);424void DisassembleIR(char *buf, size_t bufsize, IRInst inst);425void InitIR();426427428