CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/MIPS/MIPSCodeUtils.cpp
Views: 1401
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include "Core/MIPS/MIPS.h"
19
#include "Core/MIPS/MIPSTables.h"
20
#include "Core/MIPS/MIPSCodeUtils.h"
21
#include "Core/MemMap.h"
22
23
namespace MIPSCodeUtils
24
{
25
26
#define OP_SYSCALL 0x0000000c
27
#define OP_SYSCALL_MASK 0xFC00003F
28
#define _RS ((op>>21) & 0x1F)
29
#define _RT ((op>>16) & 0x1F)
30
#define _IMM26 (op & 0x03FFFFFF)
31
#define TARGET16 ((int)(SignExtend16ToU32(op) << 2))
32
#define TARGET26 (_IMM26 << 2)
33
34
u32 GetJumpTarget(u32 addr) {
35
MIPSOpcode op = Memory::Read_Instruction(addr, true);
36
if (op != 0) {
37
MIPSInfo info = MIPSGetInfo(op);
38
if ((info & IS_JUMP) && (info & IN_IMM26))
39
return (addr & 0xF0000000) | TARGET26;
40
else
41
return INVALIDTARGET;
42
} else {
43
return INVALIDTARGET;
44
}
45
}
46
47
u32 GetBranchTarget(u32 addr) {
48
MIPSOpcode op = Memory::Read_Instruction(addr, true);
49
if (op != 0) {
50
MIPSInfo info = MIPSGetInfo(op);
51
if (info & IS_CONDBRANCH)
52
return addr + 4 + TARGET16;
53
else
54
return INVALIDTARGET;
55
} else {
56
return INVALIDTARGET;
57
}
58
}
59
60
u32 GetBranchTargetNoRA(u32 addr) {
61
MIPSOpcode op = Memory::Read_Instruction(addr, true);
62
return GetBranchTargetNoRA(addr, op);
63
}
64
65
u32 GetBranchTargetNoRA(u32 addr, MIPSOpcode op) {
66
if (op != 0) {
67
MIPSInfo info = MIPSGetInfo(op);
68
if ((info & IS_CONDBRANCH) && !(info & OUT_RA))
69
return addr + 4 + TARGET16;
70
else
71
return INVALIDTARGET;
72
} else {
73
return INVALIDTARGET;
74
}
75
}
76
77
u32 GetSureBranchTarget(u32 addr) {
78
MIPSOpcode op = Memory::Read_Instruction(addr, true);
79
if (op != 0) {
80
MIPSInfo info = MIPSGetInfo(op);
81
if ((info & IS_CONDBRANCH) && !(info & (IN_FPUFLAG | IS_VFPU))) {
82
bool sure;
83
bool takeBranch;
84
switch (info & CONDTYPE_MASK)
85
{
86
case CONDTYPE_EQ:
87
sure = _RS == _RT;
88
takeBranch = true;
89
break;
90
91
case CONDTYPE_NE:
92
sure = _RS == _RT;
93
takeBranch = false;
94
break;
95
96
case CONDTYPE_LEZ:
97
case CONDTYPE_GEZ:
98
sure = _RS == 0;
99
takeBranch = true;
100
break;
101
102
case CONDTYPE_LTZ:
103
case CONDTYPE_GTZ:
104
sure = _RS == 0;
105
takeBranch = false;
106
break;
107
108
default:
109
sure = false;
110
}
111
112
if (sure && takeBranch)
113
return addr + 4 + TARGET16;
114
else if (sure && !takeBranch)
115
return addr + 8;
116
else
117
return INVALIDTARGET;
118
} else {
119
return INVALIDTARGET;
120
}
121
} else {
122
return INVALIDTARGET;
123
}
124
}
125
126
bool IsVFPUBranch(MIPSOpcode op) {
127
return (MIPSGetInfo(op) & (IS_VFPU | IS_CONDBRANCH)) == (IS_VFPU | IS_CONDBRANCH);
128
}
129
130
bool IsBranch(MIPSOpcode op) {
131
return (MIPSGetInfo(op) & IS_CONDBRANCH) == IS_CONDBRANCH;
132
}
133
134
135
}
136
137