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/MIPS.h
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819#include "ppsspp_config.h"2021#include <cstddef>2223#include "Common/CommonTypes.h"24#include "Core/Opcode.h"2526class PointerWrap;2728typedef Memory::Opcode MIPSOpcode;2930// Unlike on the PPC, opcode 0 is not unused and thus we have to choose another fake31// opcode to represent JIT blocks and other emu hacks.32// I've chosen 0x68000000.33#define MIPS_EMUHACK_OPCODE 0x6800000034#define MIPS_EMUHACK_MASK 0xFC00000035#define MIPS_JITBLOCK_MASK 0xFF00000036#define MIPS_EMUHACK_VALUE_MASK 0x00FFFFFF3738// There are 2 bits available for sub-opcodes, 0x03000000.39#define EMUOP_RUNBLOCK 0 // Runs a JIT block40#define EMUOP_RETKERNEL 1 // Returns to the simulated PSP kernel from a thread41#define EMUOP_CALL_REPLACEMENT 24243#define MIPS_IS_EMUHACK(op) (((op) & 0xFC000000) == MIPS_EMUHACK_OPCODE) // masks away the subop44#define MIPS_IS_RUNBLOCK(op) (((op) & 0xFF000000) == MIPS_EMUHACK_OPCODE) // masks away the subop45#define MIPS_IS_REPLACEMENT(op) (((op) & 0xFF000000) == (MIPS_EMUHACK_OPCODE | (EMUOP_CALL_REPLACEMENT << 24))) // masks away the subop4647#define MIPS_EMUHACK_CALL_REPLACEMENT (MIPS_EMUHACK_OPCODE | (EMUOP_CALL_REPLACEMENT << 24))4849enum MIPSGPReg {50MIPS_REG_ZERO=0,51MIPS_REG_COMPILER_SCRATCH=1,5253MIPS_REG_V0=2,54MIPS_REG_V1=3,5556MIPS_REG_A0=4,57MIPS_REG_A1=5,58MIPS_REG_A2=6,59MIPS_REG_A3=7,60MIPS_REG_A4=8,61MIPS_REG_A5=9,6263MIPS_REG_T0=8, //alternate names for A4/A564MIPS_REG_T1=9,65MIPS_REG_T2=10,66MIPS_REG_T3=11,67MIPS_REG_T4=12,68MIPS_REG_T5=13,69MIPS_REG_T6=14,70MIPS_REG_T7=15,7172MIPS_REG_S0=16,73MIPS_REG_S1=17,74MIPS_REG_S2=18,75MIPS_REG_S3=19,76MIPS_REG_S4=20,77MIPS_REG_S5=21,78MIPS_REG_S6=22,79MIPS_REG_S7=23,80MIPS_REG_T8=24,81MIPS_REG_T9=25,82MIPS_REG_K0=26,83MIPS_REG_K1=27,84MIPS_REG_GP=28,85MIPS_REG_SP=29,86MIPS_REG_FP=30,87MIPS_REG_RA=31,8889// Not real regs, just for convenience/jit mapping.90// NOTE: These are not the same as the offsets the IR has to use!91MIPS_REG_HI = 32,92MIPS_REG_LO = 33,93MIPS_REG_FPCOND = 34,94MIPS_REG_VFPUCC = 35,9596MIPS_REG_INVALID=-1,97};9899enum {100VFPU_CTRL_SPREFIX,101VFPU_CTRL_TPREFIX,102VFPU_CTRL_DPREFIX,103VFPU_CTRL_CC,104VFPU_CTRL_INF4,105VFPU_CTRL_RSV5,106VFPU_CTRL_RSV6,107VFPU_CTRL_REV,108VFPU_CTRL_RCX0,109VFPU_CTRL_RCX1,110VFPU_CTRL_RCX2,111VFPU_CTRL_RCX3,112VFPU_CTRL_RCX4,113VFPU_CTRL_RCX5,114VFPU_CTRL_RCX6,115VFPU_CTRL_RCX7,116117VFPU_CTRL_MAX,118//unknown....119};120121enum VCondition122{123VC_FL,124VC_EQ,125VC_LT,126VC_LE,127VC_TR,128VC_NE,129VC_GE,130VC_GT,131VC_EZ,132VC_EN,133VC_EI,134VC_ES,135VC_NZ,136VC_NN,137VC_NI,138VC_NS139};140141// In memory, we order the VFPU registers differently.142// Games use columns a whole lot more than rows, and it would thus be good if columns143// were contiguous in memory. Also, matrices aren't but should be.144extern u8 voffset[128];145extern u8 fromvoffset[128];146147enum class CPUCore;148149#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)150151// Note that CTXREG is offset to point at the first floating point register, intentionally. This is so that a byte offset152// can reach both GPR and FPR regs.153#define MIPSSTATE_VAR(x) MDisp(X64JitConstants::CTXREG, \154(int)(offsetof(MIPSState, x) - offsetof(MIPSState, f[0])))155156// Workaround for compilers that don't like dynamic indexing in offsetof157#define MIPSSTATE_VAR_ELEM32(x, i) MDisp(X64JitConstants::CTXREG, \158(int)(offsetof(MIPSState, x) - offsetof(MIPSState, f[0]) + (i) * 4))159160// To get RIP/relative addressing (requires tight memory control so generated code isn't too far from the binary, and a reachable variable called mips):161// #define MIPSSTATE_VAR(x) M(&mips_->x)162163#endif164165enum {166NUM_X86_FPU_TEMPS = 16,167};168169class MIPSState170{171public:172MIPSState();173~MIPSState();174175void Init();176void Shutdown();177void Reset();178void UpdateCore(CPUCore desired);179180void DoState(PointerWrap &p);181182// MUST start with r and be followed by f, v, and t!183u32 r[32];184union {185float f[32];186u32 fi[32];187int fs[32];188};189union {190float v[128];191u32 vi[128];192};193194// Register-allocated JIT Temps don't get flushed so we don't reserve space for them.195// However, the IR interpreter needs some temps that can stick around between ops.196// Can be indexed through r[] using indices 192+, thanks to predictable struct layout.197// Unfortunately, UBSAN isn't too happy about these.198u32 t[16]; //192199200// If vfpuCtrl (prefixes) get mysterious values, check the VFPU regcache code.201u32 vfpuCtrl[16]; // 208202203float vt[16]; //224 TODO: VFPU temp204205// ARM64 wants lo/hi to be aligned to 64 bits from the base of this struct.206u32 padLoHi; // 240207208union {209struct {210u32 pc; //241211212u32 lo; //242213u32 hi; //243214215u32 fcr31; //244 fpu control register216u32 fpcond; //245 cache the cond flag of fcr31 (& 1 << 23)217};218u32 other[6];219};220221u32 nextPC;222int downcount; // This really doesn't belong here, it belongs in CoreTiming. But you gotta do what you gotta do, this needs to be reachable in the JITs without additional pointers.223224bool inDelaySlot;225int llBit; // ll/sc226u32 temp; // can be used to save temporaries during calculations when we need more than R0 and R1227u32 mxcsrTemp;228// Temporary used around delay slots and similar.229u64 saved_flags;230231// Debug stuff232u32 debugCount; // can be used to count basic blocks before crashes, etc.233234// Temps needed for JitBranch.cpp experiments235u32 intBranchExit;236u32 jitBranchExit;237238u32 savedPC;239240alignas(16) u32 vcmpResult[4];241242float sincostemp[2];243244static const u32 FCR0_VALUE = 0x00003351;245246#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)247// FPU TEMP0, etc. are swapped in here if necessary (e.g. on x86.)248float tempValues[NUM_X86_FPU_TEMPS];249#endif250251u8 VfpuWriteMask() const {252return (vfpuCtrl[VFPU_CTRL_DPREFIX] >> 8) & 0xF;253}254bool VfpuWriteMask(int i) const {255return (vfpuCtrl[VFPU_CTRL_DPREFIX] >> (8 + i)) & 1;256}257258bool HasDefaultPrefix() const;259260void SingleStep();261int RunLoopUntil(u64 globalTicks);262// To clear jit caches, etc.263void InvalidateICache(u32 address, int length = 4);264void ClearJitCache();265266void ProcessPendingClears();267268// Doesn't need save stating.269volatile bool insideJit = false;270volatile bool hasPendingClears = false;271};272273class MIPSDebugInterface;274275//The one we are compiling or running currently276extern MIPSState *currentMIPS;277extern MIPSDebugInterface *currentDebugMIPS;278extern MIPSState mipsr4k;279280extern const float cst_constants[32];281282283