mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
srl/srlv rotate when the low bit of their unused field (rs or sa) is set and shift when it's clear, whatever the other bits hold (cpu/cpu_alu/shift_encodings). The interpreter treated values above 1 as invalid and the other cores shifted. The Allegrex bit ops decode only some bits of sa, so all 32 values are one of wsbh, wsbw, seb, seh and bitrev (cpu/cpu_alu/allegrex_encodings). AllegrexBitOp() gives the canonical one for every core. Special3 function 0x18 does nothing on the PSP, where it was decoded as an alias of 0x20. The interpreter dispatch is regenerated, and its generator now lists each instruction name once. CPUEquivalence no longer skips the srl/srlv encodings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102 lines
3.6 KiB
C++
102 lines
3.6 KiB
C++
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/Data/Convert/SmallDataConvert.h"
|
|
#include "Core/MIPS/MIPS.h"
|
|
|
|
// Invalid branch target address
|
|
#define INVALIDTARGET 0xFFFFFFFF
|
|
|
|
#define MIPS_MAKE_B(offs) (0x10000000 | ((offs) & 0xFFFF))
|
|
#define MIPS_MAKE_J(addr) (0x08000000 | ((addr)>>2))
|
|
#define MIPS_MAKE_JAL(addr) (0x0C000000 | ((addr)>>2))
|
|
#define MIPS_MAKE_JR_RA() (0x03e00008)
|
|
#define MIPS_MAKE_NOP() (0)
|
|
#define MIPS_MAKE_BNEZ(pc, addr, rs) (0x14000000 | (rs << 21) | (u32)(((int)(addr - (pc + 4)) >> 2) & 0xFFFF))
|
|
|
|
#define MIPS_MAKE_ADDIU(dreg, sreg, immval) ((9 << 26) | ((dreg) << 16) | ((sreg) << 21) | (immval))
|
|
#define MIPS_MAKE_LUI(reg, immval) (0x3c000000 | ((reg) << 16) | (immval))
|
|
#define MIPS_MAKE_ORI(rt, rs, immval) (0x34000000 | ((rs) << 21) | ((rt) << 16) | (immval))
|
|
#define MIPS_MAKE_LW(rt, rs, immval) (0x8c000000 | ((rs) << 21) | ((rt) << 16) | (immval))
|
|
#define MIPS_MAKE_SYSCALL(module, function) GetSyscallOp(module, GetNibByName(module, function))
|
|
#define MIPS_MAKE_BREAK(n) (((n) << 6) | 13) // ! :)
|
|
|
|
#define MIPS_GET_OP(op) ((op>>26) & 0x3F)
|
|
#define MIPS_GET_FUNC(op) (op & 0x3F)
|
|
#define MIPS_GET_SA(op) ((op>>6) & 0x1F)
|
|
|
|
#define MIPS_GET_RS(op) MIPSGPReg((op>>21) & 0x1F)
|
|
#define MIPS_GET_RT(op) MIPSGPReg((op>>16) & 0x1F)
|
|
#define MIPS_GET_RD(op) MIPSGPReg((op>>11) & 0x1F)
|
|
|
|
#define MIPS_GET_FS(op) ((op>>11) & 0x1F)
|
|
#define MIPS_GET_FT(op) ((op>>16) & 0x1F)
|
|
#define MIPS_GET_FD(op) ((op>>6 ) & 0x1F)
|
|
|
|
#define MIPS_GET_VD(op) (op & 0x7F)
|
|
#define MIPS_GET_VS(op) ((op>>8) & 0x7F)
|
|
#define MIPS_GET_VT(op) ((op>>16) & 0x7F)
|
|
|
|
// ctc1 to fcr31, the only instruction that changes the guest's rounding mode and flush-to-zero.
|
|
#define MIPS_IS_CTC1_FCR31(op) (((op) & 0xFFE0F800) == 0x44C0F800)
|
|
|
|
inline int32_t SignExtend8ToS32(MIPSOpcode op) {
|
|
return SignExtend8ToS32(op.encoding);
|
|
}
|
|
|
|
inline uint32_t SignExtend8ToU32(MIPSOpcode op) {
|
|
return SignExtend8ToU32(op.encoding);
|
|
}
|
|
|
|
inline int32_t SignExtend16ToS32(MIPSOpcode op) {
|
|
return SignExtend16ToS32(op.encoding);
|
|
}
|
|
|
|
inline uint32_t SignExtend16ToU32(MIPSOpcode op) {
|
|
return SignExtend16ToU32(op.encoding);
|
|
}
|
|
|
|
// The Allegrex bit ops (special3, function 0x20) only decode some bits of the sa field, so every
|
|
// value is one of them (cpu/cpu_alu/allegrex_encodings). Returns the canonical sa: 2 wsbh, 3 wsbw,
|
|
// 16 seb, 20 bitrev, 24 seh.
|
|
inline int AllegrexBitOp(MIPSOpcode op) {
|
|
int sa = (op >> 6) & 31;
|
|
if (!(sa & 0x10)) {
|
|
return 2 | (sa & 1);
|
|
}
|
|
if (sa & 4) {
|
|
return 20;
|
|
}
|
|
return (sa & 8) ? 24 : 16;
|
|
}
|
|
|
|
namespace MIPSCodeUtils
|
|
{
|
|
u32 GetCallTarget(u32 addr);
|
|
u32 GetBranchTarget(u32 addr);
|
|
// Ignores bltzal/etc. instructions that change RA.
|
|
u32 GetBranchTargetNoRA(u32 addr);
|
|
u32 GetBranchTargetNoRA(u32 addr, MIPSOpcode op);
|
|
u32 GetJumpTarget(u32 addr);
|
|
u32 GetSureBranchTarget(u32 addr);
|
|
bool IsVFPUBranch(MIPSOpcode op);
|
|
bool IsBranch(MIPSOpcode op);
|
|
}
|