1 // Copyright (c) 2014- 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 "ppsspp_config.h"
19 #include <stdarg.h>
20 #include <stddef.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "Common/Log.h"
26 #include "Common/MemoryUtil.h"
27 #include "Common/MipsEmitter.h"
28 #include "Common/CPUDetect.h"
29 
30 namespace MIPSGen {
SetCodePointer(const u8 * ptr,u8 * writePtr)31 void MIPSEmitter::SetCodePointer(const u8 *ptr, u8 *writePtr) {
32 	code_ = writePtr;
33 	lastCacheFlushEnd_ = writePtr;
34 }
35 
GetCodePointer() const36 const u8 *MIPSEmitter::GetCodePointer() const {
37 	return code_;
38 }
39 
ReserveCodeSpace(u32 bytes)40 void MIPSEmitter::ReserveCodeSpace(u32 bytes) {
41 	for (u32 i = 0; i < bytes / 4; ++i) {
42 		BREAK(0);
43 	}
44 }
45 
AlignCode16()46 const u8 *MIPSEmitter::AlignCode16() {
47 	ReserveCodeSpace((-(intptr_t)code_) & 15);
48 	return code_;
49 }
50 
AlignCodePage()51 const u8 *MIPSEmitter::AlignCodePage() {
52 	// TODO: Assuming code pages ought to be 4K?
53 	ReserveCodeSpace((-(intptr_t)code_) & 4095);
54 	return code_;
55 }
56 
GetCodePtr() const57 const u8 *MIPSEmitter::GetCodePtr() const {
58 	return code_;
59 }
60 
GetWritableCodePtr()61 u8 *MIPSEmitter::GetWritableCodePtr() {
62 	return code_;
63 }
64 
FlushIcache()65 void MIPSEmitter::FlushIcache() {
66 	FlushIcacheSection(lastCacheFlushEnd_, code_);
67 	lastCacheFlushEnd_ = code_;
68 }
69 
FlushIcacheSection(u8 * start,u8 * end)70 void MIPSEmitter::FlushIcacheSection(u8 *start, u8 *end) {
71 #if PPSSPP_ARCH(MIPS)
72 #ifdef __clang__
73 	__clear_cache(start, end);
74 #else
75 	__builtin___clear_cache(start, end);
76 #endif
77 #endif
78 }
79 
BREAK(u32 code)80 void MIPSEmitter::BREAK(u32 code) {
81 	// 000000 iiiiiiiiiiiiiiiiiiii 001101
82 	_dbg_assert_msg_(code <= 0xfffff, "Bad emitter arguments");
83 	Write32Fields(26, 0x00, 6, code & 0xfffff, 0, 0x0d);
84 }
85 
J(std::function<void ()> delaySlot)86 FixupBranch MIPSEmitter::J(std::function<void ()> delaySlot) {
87 	// 000010 iiiiiiiiiiiiiiiiiiiiiiiiii (fix up)
88 	FixupBranch b = MakeFixupBranch(BRANCH_26);
89 	Write32Fields(26, 0x02);
90 	ApplyDelaySlot(delaySlot);
91 	return b;
92 }
93 
J(const void * func,std::function<void ()> delaySlot)94 void MIPSEmitter::J(const void *func, std::function<void ()> delaySlot) {
95 	SetJumpTarget(J(delaySlot), func);
96 }
97 
JAL(std::function<void ()> delaySlot)98 FixupBranch MIPSEmitter::JAL(std::function<void ()> delaySlot) {
99 	// 000011 iiiiiiiiiiiiiiiiiiiiiiiiii (fix up)
100 	FixupBranch b = MakeFixupBranch(BRANCH_26);
101 	Write32Fields(26, 0x03);
102 	ApplyDelaySlot(delaySlot);
103 	return b;
104 }
105 
JAL(const void * func,std::function<void ()> delaySlot)106 void MIPSEmitter::JAL(const void *func, std::function<void ()> delaySlot) {
107 	SetJumpTarget(JAL(delaySlot), func);
108 }
109 
JR(MIPSReg rs,std::function<void ()> delaySlot)110 void MIPSEmitter::JR(MIPSReg rs, std::function<void ()> delaySlot) {
111 	// 000000 sssss xxxxxxxxxx hint- 001000 (hint must be 0.)
112 	_dbg_assert_msg_(rs < F_BASE, "Bad emitter arguments");
113 	Write32Fields(26, 0x00, 21, rs, 0, 0x08);
114 	ApplyDelaySlot(delaySlot);
115 }
116 
JALR(MIPSReg rd,MIPSReg rs,std::function<void ()> delaySlot)117 void MIPSEmitter::JALR(MIPSReg rd, MIPSReg rs, std::function<void ()> delaySlot) {
118 	// 000000 sssss xxxxx ddddd hint- 001001 (hint must be 0.)
119 	_dbg_assert_msg_(rs < F_BASE, "Bad emitter arguments");
120 	Write32Fields(26, 0x00, 21, rs, 11, rd, 0, 0x09);
121 	ApplyDelaySlot(delaySlot);
122 }
123 
BLTZ(MIPSReg rs,std::function<void ()> delaySlot)124 FixupBranch MIPSEmitter::BLTZ(MIPSReg rs, std::function<void ()> delaySlot) {
125 	// 000001 sssss xxxxx iiiiiiiiiiiiiii (fix up)
126 	_dbg_assert_msg_(rs < F_BASE, "Bad emitter arguments");
127 	FixupBranch b = MakeFixupBranch(BRANCH_16);
128 	Write32Fields(26, 0x01, 21, rs);
129 	ApplyDelaySlot(delaySlot);
130 	return b;
131 }
132 
BLTZ(MIPSReg rs,const void * func,std::function<void ()> delaySlot)133 void MIPSEmitter::BLTZ(MIPSReg rs, const void *func, std::function<void ()> delaySlot) {
134 	SetJumpTarget(BLTZ(rs, delaySlot), func);
135 }
136 
BEQ(MIPSReg rs,MIPSReg rt,std::function<void ()> delaySlot)137 FixupBranch MIPSEmitter::BEQ(MIPSReg rs, MIPSReg rt, std::function<void ()> delaySlot) {
138 	// 000100 sssss ttttt iiiiiiiiiiiiiii (fix up)
139 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
140 	FixupBranch b = MakeFixupBranch(BRANCH_16);
141 	Write32Fields(26, 0x04, 21, rs, 16, rt);
142 	ApplyDelaySlot(delaySlot);
143 	return b;
144 }
145 
BEQ(MIPSReg rs,MIPSReg rt,const void * func,std::function<void ()> delaySlot)146 void MIPSEmitter::BEQ(MIPSReg rs, MIPSReg rt, const void *func, std::function<void ()> delaySlot) {
147 	SetJumpTarget(BEQ(rs, rt, delaySlot), func);
148 }
149 
BNE(MIPSReg rs,MIPSReg rt,std::function<void ()> delaySlot)150 FixupBranch MIPSEmitter::BNE(MIPSReg rs, MIPSReg rt, std::function<void ()> delaySlot) {
151 	// 000101 sssss ttttt iiiiiiiiiiiiiii (fix up)
152 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
153 	FixupBranch b = MakeFixupBranch(BRANCH_16);
154 	Write32Fields(26, 0x05, 21, rs, 16, rt);
155 	ApplyDelaySlot(delaySlot);
156 	return b;
157 }
158 
BNE(MIPSReg rs,MIPSReg rt,const void * func,std::function<void ()> delaySlot)159 void MIPSEmitter::BNE(MIPSReg rs, MIPSReg rt, const void *func, std::function<void ()> delaySlot) {
160 	SetJumpTarget(BNE(rs, rt, delaySlot), func);
161 }
162 
BLEZ(MIPSReg rs,std::function<void ()> delaySlot)163 FixupBranch MIPSEmitter::BLEZ(MIPSReg rs, std::function<void ()> delaySlot) {
164 	// 000110 sssss xxxxx iiiiiiiiiiiiiii (fix up)
165 	_dbg_assert_msg_(rs < F_BASE, "Bad emitter arguments");
166 	FixupBranch b = MakeFixupBranch(BRANCH_16);
167 	Write32Fields(26, 0x06, 21, rs);
168 	ApplyDelaySlot(delaySlot);
169 	return b;
170 }
171 
BLEZ(MIPSReg rs,const void * func,std::function<void ()> delaySlot)172 void MIPSEmitter::BLEZ(MIPSReg rs, const void *func, std::function<void ()> delaySlot) {
173 	SetJumpTarget(BLEZ(rs, delaySlot), func);
174 }
175 
BGTZ(MIPSReg rs,std::function<void ()> delaySlot)176 FixupBranch MIPSEmitter::BGTZ(MIPSReg rs, std::function<void ()> delaySlot) {
177 	// 000111 sssss xxxxx iiiiiiiiiiiiiii (fix up)
178 	_dbg_assert_msg_(rs < F_BASE, "Bad emitter arguments");
179 	FixupBranch b = MakeFixupBranch(BRANCH_16);
180 	Write32Fields(26, 0x07, 21, rs);
181 	ApplyDelaySlot(delaySlot);
182 	return b;
183 }
184 
BGTZ(MIPSReg rs,const void * func,std::function<void ()> delaySlot)185 void MIPSEmitter::BGTZ(MIPSReg rs, const void *func, std::function<void ()> delaySlot) {
186 	SetJumpTarget(BGTZ(rs, delaySlot), func);
187 }
188 
SetJumpTarget(const FixupBranch & branch)189 void MIPSEmitter::SetJumpTarget(const FixupBranch &branch) {
190 	SetJumpTarget(branch, code_);
191 }
192 
BInRange(const void * func)193 bool MIPSEmitter::BInRange(const void *func) {
194 	return BInRange(code_, func);
195 }
196 
JInRange(const void * func)197 bool MIPSEmitter::JInRange(const void *func) {
198 	return JInRange(code_, func);
199 }
200 
SetJumpTarget(const FixupBranch & branch,const void * dst)201 void MIPSEmitter::SetJumpTarget(const FixupBranch &branch, const void *dst) {
202 	const intptr_t srcp = (intptr_t)branch.ptr;
203 	const intptr_t dstp = (intptr_t)dst;
204 	u32 *fixup = (u32 *)branch.ptr;
205 
206 	_dbg_assert_msg_((dstp & 3) == 0, "Destination should be aligned");
207 
208 	if (branch.type == BRANCH_16) {
209 		// The distance is encoded as words from the delay slot.
210 		ptrdiff_t distance = (dstp - srcp - 4) >> 2;
211 		_dbg_assert_msg_(BInRange(branch.ptr, dst), "Destination is too far away (%p -> %p)", branch.ptr, dst);
212 		*fixup = (*fixup & 0xffff0000) | (distance & 0x0000ffff);
213 	} else {
214 		// Absolute, easy.
215 		_dbg_assert_msg_(JInRange(branch.ptr, dst), "Destination is too far away (%p -> %p)", branch.ptr, dst);
216 		*fixup = (*fixup & 0xfc000000) | ((dstp >> 2) & 0x03ffffff);
217 	}
218 }
219 
BInRange(const void * src,const void * dst)220 bool MIPSEmitter::BInRange(const void *src, const void *dst) {
221 	const intptr_t srcp = (intptr_t)src;
222 	const intptr_t dstp = (intptr_t)dst;
223 
224 	// The distance is encoded as words from the delay slot.
225 	ptrdiff_t distance = (dstp - srcp - 4) >> 2;
226 	return distance >= -0x8000 && distance < 0x8000;
227 }
228 
JInRange(const void * src,const void * dst)229 bool MIPSEmitter::JInRange(const void *src, const void *dst) {
230 	const intptr_t srcp = (intptr_t)src;
231 	const intptr_t dstp = (intptr_t)dst;
232 
233 	return (srcp - (srcp & 0x0fffffff)) == (dstp - (dstp & 0x0fffffff));
234 }
235 
ApplyDelaySlot(std::function<void ()> delaySlot)236 void MIPSEmitter::ApplyDelaySlot(std::function<void ()> delaySlot) {
237 	if (delaySlot) {
238 		delaySlot();
239 	} else {
240 		// We just insert a NOP if there's no delay slot provided.  Safer.
241 		NOP();
242 	}
243 }
244 
QuickCallFunction(MIPSReg scratchreg,const void * func)245 void MIPSEmitter::QuickCallFunction(MIPSReg scratchreg, const void *func) {
246 	_dbg_assert_msg_(scratchreg < F_BASE, "Bad emitter arguments");
247 	if (JInRange(func)) {
248 		JAL(func);
249 	} else {
250 		// This may never happen.
251 		MOVP2R(scratchreg, func);
252 		JALR(scratchreg);
253 	}
254 }
255 
MakeFixupBranch(FixupBranchType type)256 FixupBranch MIPSEmitter::MakeFixupBranch(FixupBranchType type) {
257 	FixupBranch b;
258 	b.ptr = code_;
259 	b.type = type;
260 	return b;
261 }
262 
LB(MIPSReg value,MIPSReg base,s16 offset)263 void MIPSEmitter::LB(MIPSReg value, MIPSReg base, s16 offset) {
264 	// 100000 sssss ttttt iiiiiiiiiiiiiiii - rs = base, rt = value
265 	_dbg_assert_msg_(value < F_BASE && base < F_BASE, "Bad emitter arguments");
266 	Write32Fields(26, 0x20, 21, base, 16, value, 0, (u16)offset);
267 }
268 
LH(MIPSReg value,MIPSReg base,s16 offset)269 void MIPSEmitter::LH(MIPSReg value, MIPSReg base, s16 offset) {
270 	// 100001 sssss ttttt iiiiiiiiiiiiiiii - rs = base, rt = value
271 	_dbg_assert_msg_(value < F_BASE && base < F_BASE, "Bad emitter arguments");
272 	Write32Fields(26, 0x21, 21, base, 16, value, 0, (u16)offset);
273 }
274 
LW(MIPSReg value,MIPSReg base,s16 offset)275 void MIPSEmitter::LW(MIPSReg value, MIPSReg base, s16 offset) {
276 	// 100011 sssss ttttt iiiiiiiiiiiiiiii - rs = base, rt = value
277 	_dbg_assert_msg_(value < F_BASE && base < F_BASE, "Bad emitter arguments");
278 	Write32Fields(26, 0x23, 21, base, 16, value, 0, (u16)offset);
279 }
280 
SB(MIPSReg value,MIPSReg base,s16 offset)281 void MIPSEmitter::SB(MIPSReg value, MIPSReg base, s16 offset) {
282 	// 101000 sssss ttttt iiiiiiiiiiiiiiii - rs = base, rt = value
283 	_dbg_assert_msg_(value < F_BASE && base < F_BASE, "Bad emitter arguments");
284 	Write32Fields(26, 0x28, 21, base, 16, value, 0, (u16)offset);
285 }
286 
SH(MIPSReg value,MIPSReg base,s16 offset)287 void MIPSEmitter::SH(MIPSReg value, MIPSReg base, s16 offset) {
288 	// 101001 sssss ttttt iiiiiiiiiiiiiiii - rs = base, rt = value
289 	_dbg_assert_msg_(value < F_BASE && base < F_BASE, "Bad emitter arguments");
290 	Write32Fields(26, 0x29, 21, base, 16, value, 0, (u16)offset);
291 }
292 
SW(MIPSReg value,MIPSReg base,s16 offset)293 void MIPSEmitter::SW(MIPSReg value, MIPSReg base, s16 offset) {
294 	// 101011 sssss ttttt iiiiiiiiiiiiiiii - rs = base, rt = value
295 	_dbg_assert_msg_(value < F_BASE && base < F_BASE, "Bad emitter arguments");
296 	Write32Fields(26, 0x2b, 21, base, 16, value, 0, (u16)offset);
297 }
298 
SLL(MIPSReg rd,MIPSReg rt,u8 sa)299 void MIPSEmitter::SLL(MIPSReg rd, MIPSReg rt, u8 sa) {
300 	// 000000 xxxxx ttttt ddddd aaaaa 000000
301 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && sa <= 0x1f, "Bad emitter arguments");
302 	Write32Fields(26, 0x00, 16, rt, 11, rd, 6, sa & 0x1f, 0, 0x00);
303 }
304 
SRL(MIPSReg rd,MIPSReg rt,u8 sa)305 void MIPSEmitter::SRL(MIPSReg rd, MIPSReg rt, u8 sa) {
306 	// 000000 xxxxx ttttt ddddd aaaaa 000010
307 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && sa <= 0x1f, "Bad emitter arguments");
308 	Write32Fields(26, 0x00, 16, rt, 11, rd, 6, sa & 0x1f, 0, 0x02);
309 }
310 
SRA(MIPSReg rd,MIPSReg rt,u8 sa)311 void MIPSEmitter::SRA(MIPSReg rd, MIPSReg rt, u8 sa) {
312 	// 000000 xxxxx ttttt ddddd aaaaa 000011
313 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && sa <= 0x1f, "Bad emitter arguments");
314 	Write32Fields(26, 0x00, 16, rt, 11, rd, 6, sa & 0x1f, 0, 0x03);
315 }
316 
SLLV(MIPSReg rd,MIPSReg rt,MIPSReg rs)317 void MIPSEmitter::SLLV(MIPSReg rd, MIPSReg rt, MIPSReg rs) {
318 	// 000000 sssss ttttt ddddd xxxxx 000100
319 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
320 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x04);
321 }
322 
SRLV(MIPSReg rd,MIPSReg rt,MIPSReg rs)323 void MIPSEmitter::SRLV(MIPSReg rd, MIPSReg rt, MIPSReg rs) {
324 	// 000000 sssss ttttt ddddd xxxxx 000110
325 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
326 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x06);
327 }
328 
SRAV(MIPSReg rd,MIPSReg rt,MIPSReg rs)329 void MIPSEmitter::SRAV(MIPSReg rd, MIPSReg rt, MIPSReg rs) {
330 	// 000000 sssss ttttt ddddd xxxxx 000111
331 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
332 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x07);
333 }
334 
SLT(MIPSReg rd,MIPSReg rs,MIPSReg rt)335 void MIPSEmitter::SLT(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
336 	// 000000 sssss ttttt ddddd xxxxx 101010
337 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
338 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x2a);
339 }
340 
SLTU(MIPSReg rd,MIPSReg rs,MIPSReg rt)341 void MIPSEmitter::SLTU(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
342 	// 000000 sssss ttttt ddddd xxxxx 101011
343 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
344 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x2b);
345 }
346 
SLTI(MIPSReg rt,MIPSReg rs,s16 imm)347 void MIPSEmitter::SLTI(MIPSReg rt, MIPSReg rs, s16 imm) {
348 	// 001010 sssss ttttt iiiiiiiiiiiiiiii
349 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
350 	Write32Fields(26, 0x0a, 21, rs, 16, rt, 0, (u16)imm);
351 }
352 
SLTIU(MIPSReg rt,MIPSReg rs,s16 imm)353 void MIPSEmitter::SLTIU(MIPSReg rt, MIPSReg rs, s16 imm) {
354 	// 001011 sssss ttttt iiiiiiiiiiiiiiii
355 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
356 	Write32Fields(26, 0x0b, 21, rs, 16, rt, 0, (u16)imm);
357 }
358 
ADDU(MIPSReg rd,MIPSReg rs,MIPSReg rt)359 void MIPSEmitter::ADDU(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
360 	// 000000 sssss ttttt ddddd 00000100001
361 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
362 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x21);
363 }
364 
SUBU(MIPSReg rd,MIPSReg rs,MIPSReg rt)365 void MIPSEmitter::SUBU(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
366 	// 000000 sssss ttttt ddddd 00000100011
367 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
368 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x23);
369 }
370 
ADDIU(MIPSReg rt,MIPSReg rs,s16 imm)371 void MIPSEmitter::ADDIU(MIPSReg rt, MIPSReg rs, s16 imm) {
372 	// 001001 sssss ttttt iiiiiiiiiiiiiiii
373 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
374 	Write32Fields(26, 0x09, 21, rs, 16, rt, 0, (u16)imm);
375 }
376 
AND(MIPSReg rd,MIPSReg rs,MIPSReg rt)377 void MIPSEmitter::AND(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
378 	// 000000 sssss ttttt ddddd 00000100100
379 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
380 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x24);
381 }
382 
OR(MIPSReg rd,MIPSReg rs,MIPSReg rt)383 void MIPSEmitter::OR(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
384 	// 000000 sssss ttttt ddddd 00000100101
385 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
386 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x25);
387 }
388 
XOR(MIPSReg rd,MIPSReg rs,MIPSReg rt)389 void MIPSEmitter::XOR(MIPSReg rd, MIPSReg rs, MIPSReg rt) {
390 	// 000000 sssss ttttt ddddd 00000100110
391 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && rs < F_BASE, "Bad emitter arguments");
392 	Write32Fields(26, 0x00, 21, rs, 16, rt, 11, rd, 0, 0x26);
393 }
394 
ANDI(MIPSReg rt,MIPSReg rs,s16 imm)395 void MIPSEmitter::ANDI(MIPSReg rt, MIPSReg rs, s16 imm) {
396 	// 001100 sssss ttttt iiiiiiiiiiiiiiii
397 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
398 	Write32Fields(26, 0x0c, 21, rs, 16, rt, 0, (u16)imm);
399 }
400 
ORI(MIPSReg rt,MIPSReg rs,s16 imm)401 void MIPSEmitter::ORI(MIPSReg rt, MIPSReg rs, s16 imm) {
402 	// 001101 sssss ttttt iiiiiiiiiiiiiiii
403 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
404 	Write32Fields(26, 0x0d, 21, rs, 16, rt, 0, (u16)imm);
405 }
406 
XORI(MIPSReg rt,MIPSReg rs,s16 imm)407 void MIPSEmitter::XORI(MIPSReg rt, MIPSReg rs, s16 imm) {
408 	// 001110 sssss ttttt iiiiiiiiiiiiiiii
409 	_dbg_assert_msg_(rs < F_BASE && rt < F_BASE, "Bad emitter arguments");
410 	Write32Fields(26, 0x0e, 21, rs, 16, rt, 0, (u16)imm);
411 }
412 
LUI(MIPSReg rt,s16 imm)413 void MIPSEmitter::LUI(MIPSReg rt, s16 imm) {
414 	// 001111 00000 ttttt iiiiiiiiiiiiiiii
415 	_dbg_assert_msg_(rt < F_BASE, "Bad emitter arguments");
416 	Write32Fields(26, 0x0f, 16, rt, 0, (u16)imm);
417 }
418 
INS(MIPSReg rt,MIPSReg rs,s8 pos,s8 size)419 void MIPSEmitter::INS(MIPSReg rt, MIPSReg rs, s8 pos, s8 size) {
420 	// 011111 sssss ttttt xxxxx yyyyy 000100
421 	_dbg_assert_msg_(rt < F_BASE && rs < F_BASE && pos <= 0x1f && (size+pos+1) <= 0x1f, "Bad emitter arguments");
422 	Write32Fields(26, 0x1f, 21, rt, 16, rs, 11, (size+pos+1) & 0x1f, 6, pos & 0x1f, 0, 0x04);
423 }
424 
EXT(MIPSReg rt,MIPSReg rs,s8 pos,s8 size)425 void MIPSEmitter::EXT(MIPSReg rt, MIPSReg rs, s8 pos, s8 size) {
426 	// 111111 sssss ttttt xxxxx yyyyy 000000
427 	_dbg_assert_msg_(rt < F_BASE && rs < F_BASE && pos <= 0x1f && size >= 1, "Bad emitter arguments");
428 	Write32Fields(26, 0x3f, 21, rt, 16, rs, 11, (size-1) & 0x1f, 6, pos & 0x1f, 0, 0x00);
429 }
430 
DSLL(MIPSReg rd,MIPSReg rt,u8 sa)431 void MIPSEmitter::DSLL(MIPSReg rd, MIPSReg rt, u8 sa) {
432 	// 000000 xxxxx ttttt ddddd aaaaa 111000 DSLL
433 	// 000000 xxxxx ttttt ddddd aaaaa 111100 DSLL32
434 	_dbg_assert_msg_(rd < F_BASE && rt < F_BASE && sa <= 0x3f, "Bad emitter arguments");
435 	// TODO: Assert MIPS64.
436 	if (sa >= 32) {
437 		Write32Fields(26, 0x00, 16, rt, 11, rd, 6, (sa - 32) & 0x1f, 0, 0x3c);
438 	} else {
439 		Write32Fields(26, 0x00, 16, rt, 11, rd, 6, sa & 0x1f, 0, 0x38);
440 	}
441 }
442 
MOVI2R(MIPSReg reg,u64 imm)443 void MIPSEmitter::MOVI2R(MIPSReg reg, u64 imm) {
444 	_dbg_assert_msg_(reg < F_BASE, "Bad emitter arguments");
445 	// TODO: Assert MIPS64.
446 
447 	// Probably better to use a literal pool and load.
448 	LUI(reg, imm >> 48);
449 	ORI(reg, reg, (imm >> 32) & 0x0000ffff);
450 	DSLL(reg, reg, 16);
451 	ORI(reg, reg, (imm >> 16) & 0x0000ffff);
452 	DSLL(reg, reg, 16);
453 	ORI(reg, reg, (imm >> 0) & 0x0000ffff);
454 }
455 
MOVI2R(MIPSReg reg,u32 imm)456 void MIPSEmitter::MOVI2R(MIPSReg reg, u32 imm) {
457 	_dbg_assert_msg_(reg < F_BASE, "Bad emitter arguments");
458 
459 	if ((imm & 0xffff0000) != 0) {
460 #if 0
461 		// TODO: CPUDetect MIPS64.  Ideally allow emitter to emit MIPS32 on x64.
462 		ORI(reg, R_ZERO, imm >> 16);
463 		DSLL(reg, reg, 16);
464 		ORI(reg, reg, imm & 0x0000ffff);
465 #else
466 		LUI(reg, imm >> 16);
467 		ORI(reg, reg, imm & 0x0000ffff);
468 #endif
469 	} else {
470 		ORI(reg, R_ZERO, imm & 0x0000ffff);
471 	}
472 }
473 
PoisonMemory(int offset)474 void MIPSCodeBlock::PoisonMemory(int offset) {
475 	u32 *ptr = (u32 *)(region + offset);
476 	u32 *maxptr = (u32 *)(region + region_size - offset);
477 	// If our memory isn't a multiple of u32 then this won't write the last remaining bytes with anything
478 	// Less than optimal, but there would be nothing we could do but throw a runtime warning anyway.
479 	// AArch64: 0x0000000d = break 0
480 	while (ptr < maxptr)
481 		*ptr++ = 0x0000000d;
482 }
483 
484 }
485