1 /*
2  * Copyright (C) 2014-2020 Paul Cercueil <paul@crapouillou.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  */
14 
15 #include "blockcache.h"
16 #include "config.h"
17 #include "debug.h"
18 #include "disassembler.h"
19 #include "emitter.h"
20 #include "interpreter.h"
21 #include "lightrec.h"
22 #include "memmanager.h"
23 #include "reaper.h"
24 #include "recompiler.h"
25 #include "regcache.h"
26 #include "optimizer.h"
27 
28 #include <errno.h>
29 #include <lightning.h>
30 #include <limits.h>
31 #if ENABLE_THREADED_COMPILER
32 #include <stdatomic.h>
33 #endif
34 #include <stdbool.h>
35 #include <stddef.h>
36 #include <string.h>
37 #if ENABLE_TINYMM
38 #include <tinymm.h>
39 #endif
40 
41 #define GENMASK(h, l) \
42 	(((uintptr_t)-1 << (l)) & ((uintptr_t)-1 >> (__WORDSIZE - 1 - (h))))
43 
44 static struct block * lightrec_precompile_block(struct lightrec_state *state,
45 						u32 pc);
46 
lightrec_default_sb(struct lightrec_state * state,u32 opcode,void * host,u32 addr,u8 data)47 static void lightrec_default_sb(struct lightrec_state *state, u32 opcode,
48 				void *host, u32 addr, u8 data)
49 {
50 	*(u8 *)host = data;
51 
52 	if (!state->invalidate_from_dma_only)
53 		lightrec_invalidate(state, addr, 1);
54 }
55 
lightrec_default_sh(struct lightrec_state * state,u32 opcode,void * host,u32 addr,u16 data)56 static void lightrec_default_sh(struct lightrec_state *state, u32 opcode,
57 				void *host, u32 addr, u16 data)
58 {
59 	*(u16 *)host = HTOLE16(data);
60 
61 	if (!state->invalidate_from_dma_only)
62 		lightrec_invalidate(state, addr, 2);
63 }
64 
lightrec_default_sw(struct lightrec_state * state,u32 opcode,void * host,u32 addr,u32 data)65 static void lightrec_default_sw(struct lightrec_state *state, u32 opcode,
66 				void *host, u32 addr, u32 data)
67 {
68 	*(u32 *)host = HTOLE32(data);
69 
70 	if (!state->invalidate_from_dma_only)
71 		lightrec_invalidate(state, addr, 4);
72 }
73 
lightrec_default_lb(struct lightrec_state * state,u32 opcode,void * host,u32 addr)74 static u8 lightrec_default_lb(struct lightrec_state *state,
75 			      u32 opcode, void *host, u32 addr)
76 {
77 	return *(u8 *)host;
78 }
79 
lightrec_default_lh(struct lightrec_state * state,u32 opcode,void * host,u32 addr)80 static u16 lightrec_default_lh(struct lightrec_state *state,
81 			       u32 opcode, void *host, u32 addr)
82 {
83 	return LE16TOH(*(u16 *)host);
84 }
85 
lightrec_default_lw(struct lightrec_state * state,u32 opcode,void * host,u32 addr)86 static u32 lightrec_default_lw(struct lightrec_state *state,
87 			       u32 opcode, void *host, u32 addr)
88 {
89 	return LE32TOH(*(u32 *)host);
90 }
91 
92 static const struct lightrec_mem_map_ops lightrec_default_ops = {
93 	.sb = lightrec_default_sb,
94 	.sh = lightrec_default_sh,
95 	.sw = lightrec_default_sw,
96 	.lb = lightrec_default_lb,
97 	.lh = lightrec_default_lh,
98 	.lw = lightrec_default_lw,
99 };
100 
__segfault_cb(struct lightrec_state * state,u32 addr)101 static void __segfault_cb(struct lightrec_state *state, u32 addr)
102 {
103 	lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT);
104 	pr_err("Segmentation fault in recompiled code: invalid "
105 	       "load/store at address 0x%08x\n", addr);
106 }
107 
lightrec_swl(struct lightrec_state * state,const struct lightrec_mem_map_ops * ops,u32 opcode,void * host,u32 addr,u32 data)108 static void lightrec_swl(struct lightrec_state *state,
109 			 const struct lightrec_mem_map_ops *ops,
110 			 u32 opcode, void *host, u32 addr, u32 data)
111 {
112 	unsigned int shift = addr & 0x3;
113 	unsigned int mask = GENMASK(31, (shift + 1) * 8);
114 	u32 old_data;
115 
116 	/* Align to 32 bits */
117 	addr &= ~3;
118 	host = (void *)((uintptr_t)host & ~3);
119 
120 	old_data = ops->lw(state, opcode, host, addr);
121 
122 	data = (data >> ((3 - shift) * 8)) | (old_data & mask);
123 
124 	ops->sw(state, opcode, host, addr, data);
125 }
126 
lightrec_swr(struct lightrec_state * state,const struct lightrec_mem_map_ops * ops,u32 opcode,void * host,u32 addr,u32 data)127 static void lightrec_swr(struct lightrec_state *state,
128 			 const struct lightrec_mem_map_ops *ops,
129 			 u32 opcode, void *host, u32 addr, u32 data)
130 {
131 	unsigned int shift = addr & 0x3;
132 	unsigned int mask = (1 << (shift * 8)) - 1;
133 	u32 old_data;
134 
135 	/* Align to 32 bits */
136 	addr &= ~3;
137 	host = (void *)((uintptr_t)host & ~3);
138 
139 	old_data = ops->lw(state, opcode, host, addr);
140 
141 	data = (data << (shift * 8)) | (old_data & mask);
142 
143 	ops->sw(state, opcode, host, addr, data);
144 }
145 
lightrec_swc2(struct lightrec_state * state,union code op,const struct lightrec_mem_map_ops * ops,void * host,u32 addr)146 static void lightrec_swc2(struct lightrec_state *state, union code op,
147 			  const struct lightrec_mem_map_ops *ops,
148 			  void *host, u32 addr)
149 {
150 	u32 data = state->ops.cop2_ops.mfc(state, op.opcode, op.i.rt);
151 
152 	ops->sw(state, op.opcode, host, addr, data);
153 }
154 
lightrec_lwl(struct lightrec_state * state,const struct lightrec_mem_map_ops * ops,u32 opcode,void * host,u32 addr,u32 data)155 static u32 lightrec_lwl(struct lightrec_state *state,
156 			const struct lightrec_mem_map_ops *ops,
157 			u32 opcode, void *host, u32 addr, u32 data)
158 {
159 	unsigned int shift = addr & 0x3;
160 	unsigned int mask = (1 << (24 - shift * 8)) - 1;
161 	u32 old_data;
162 
163 	/* Align to 32 bits */
164 	addr &= ~3;
165 	host = (void *)((uintptr_t)host & ~3);
166 
167 	old_data = ops->lw(state, opcode, host, addr);
168 
169 	return (data & mask) | (old_data << (24 - shift * 8));
170 }
171 
lightrec_lwr(struct lightrec_state * state,const struct lightrec_mem_map_ops * ops,u32 opcode,void * host,u32 addr,u32 data)172 static u32 lightrec_lwr(struct lightrec_state *state,
173 			const struct lightrec_mem_map_ops *ops,
174 			u32 opcode, void *host, u32 addr, u32 data)
175 {
176 	unsigned int shift = addr & 0x3;
177 	unsigned int mask = GENMASK(31, 32 - shift * 8);
178 	u32 old_data;
179 
180 	/* Align to 32 bits */
181 	addr &= ~3;
182 	host = (void *)((uintptr_t)host & ~3);
183 
184 	old_data = ops->lw(state, opcode, host, addr);
185 
186 	return (data & mask) | (old_data >> (shift * 8));
187 }
188 
lightrec_lwc2(struct lightrec_state * state,union code op,const struct lightrec_mem_map_ops * ops,void * host,u32 addr)189 static void lightrec_lwc2(struct lightrec_state *state, union code op,
190 			  const struct lightrec_mem_map_ops *ops,
191 			  void *host, u32 addr)
192 {
193 	u32 data = ops->lw(state, op.opcode, host, addr);
194 
195 	state->ops.cop2_ops.mtc(state, op.opcode, op.i.rt, data);
196 }
197 
lightrec_invalidate_map(struct lightrec_state * state,const struct lightrec_mem_map * map,u32 addr)198 static void lightrec_invalidate_map(struct lightrec_state *state,
199 		const struct lightrec_mem_map *map, u32 addr)
200 {
201 	if (map == &state->maps[PSX_MAP_KERNEL_USER_RAM])
202 		state->code_lut[lut_offset(addr)] = NULL;
203 }
204 
205 static const struct lightrec_mem_map *
lightrec_get_map(struct lightrec_state * state,u32 kaddr)206 lightrec_get_map(struct lightrec_state *state, u32 kaddr)
207 {
208 	unsigned int i;
209 
210 	for (i = 0; i < state->nb_maps; i++) {
211 		const struct lightrec_mem_map *map = &state->maps[i];
212 
213 		if (kaddr >= map->pc && kaddr < map->pc + map->length)
214 			return map;
215 	}
216 
217 	return NULL;
218 }
219 
lightrec_rw(struct lightrec_state * state,union code op,u32 addr,u32 data,u16 * flags)220 u32 lightrec_rw(struct lightrec_state *state, union code op,
221 		u32 addr, u32 data, u16 *flags)
222 {
223 	const struct lightrec_mem_map *map;
224 	const struct lightrec_mem_map_ops *ops;
225 	u32 kaddr, pc, opcode = op.opcode;
226 	void *host;
227 
228 	addr += (s16) op.i.imm;
229 	kaddr = kunseg(addr);
230 
231 	map = lightrec_get_map(state, kaddr);
232 	if (!map) {
233 		__segfault_cb(state, addr);
234 		return 0;
235 	}
236 
237 	pc = map->pc;
238 
239 	while (map->mirror_of)
240 		map = map->mirror_of;
241 
242 	host = (void *)((uintptr_t)map->address + kaddr - pc);
243 
244 	if (unlikely(map->ops)) {
245 		if (flags)
246 			*flags |= LIGHTREC_HW_IO;
247 
248 		ops = map->ops;
249 	} else {
250 		if (flags)
251 			*flags |= LIGHTREC_DIRECT_IO;
252 
253 		ops = &lightrec_default_ops;
254 	}
255 
256 	switch (op.i.op) {
257 	case OP_SB:
258 		ops->sb(state, opcode, host, addr, (u8) data);
259 		return 0;
260 	case OP_SH:
261 		ops->sh(state, opcode, host, addr, (u16) data);
262 		return 0;
263 	case OP_SWL:
264 		lightrec_swl(state, ops, opcode, host, addr, data);
265 		return 0;
266 	case OP_SWR:
267 		lightrec_swr(state, ops, opcode, host, addr, data);
268 		return 0;
269 	case OP_SW:
270 		ops->sw(state, opcode, host, addr, data);
271 		return 0;
272 	case OP_SWC2:
273 		lightrec_swc2(state, op, ops, host, addr);
274 		return 0;
275 	case OP_LB:
276 		return (s32) (s8) ops->lb(state, opcode, host, addr);
277 	case OP_LBU:
278 		return ops->lb(state, opcode, host, addr);
279 	case OP_LH:
280 		return (s32) (s16) ops->lh(state, opcode, host, addr);
281 	case OP_LHU:
282 		return ops->lh(state, opcode, host, addr);
283 	case OP_LWC2:
284 		lightrec_lwc2(state, op, ops, host, addr);
285 		return 0;
286 	case OP_LWL:
287 		return lightrec_lwl(state, ops, opcode, host, addr, data);
288 	case OP_LWR:
289 		return lightrec_lwr(state, ops, opcode, host, addr, data);
290 	case OP_LW:
291 	default:
292 		return ops->lw(state, opcode, host, addr);
293 	}
294 }
295 
lightrec_rw_helper(struct lightrec_state * state,union code op,u16 * flags)296 static void lightrec_rw_helper(struct lightrec_state *state,
297 			       union code op, u16 *flags)
298 {
299 	u32 ret = lightrec_rw(state, op,
300 			  state->native_reg_cache[op.i.rs],
301 			  state->native_reg_cache[op.i.rt], flags);
302 
303 	switch (op.i.op) {
304 	case OP_LB:
305 	case OP_LBU:
306 	case OP_LH:
307 	case OP_LHU:
308 	case OP_LWL:
309 	case OP_LWR:
310 	case OP_LW:
311 		if (op.i.rt)
312 			state->native_reg_cache[op.i.rt] = ret;
313 	default: /* fall-through */
314 		break;
315 	}
316 }
317 
lightrec_rw_cb(struct lightrec_state * state,union code op)318 static void lightrec_rw_cb(struct lightrec_state *state, union code op)
319 {
320 	lightrec_rw_helper(state, op, NULL);
321 }
322 
lightrec_rw_generic_cb(struct lightrec_state * state,struct opcode * op,struct block * block)323 static void lightrec_rw_generic_cb(struct lightrec_state *state,
324 				   struct opcode *op, struct block *block)
325 {
326 	bool was_tagged = op->flags & (LIGHTREC_HW_IO | LIGHTREC_DIRECT_IO);
327 
328 	lightrec_rw_helper(state, op->c, &op->flags);
329 
330 	if (!was_tagged) {
331 		pr_debug("Opcode of block at PC 0x%08x offset 0x%x has been "
332 			 "tagged - flag for recompilation\n",
333 			 block->pc, op->offset << 2);
334 
335 		block->flags |= BLOCK_SHOULD_RECOMPILE;
336 	}
337 }
338 
lightrec_mfc(struct lightrec_state * state,union code op)339 u32 lightrec_mfc(struct lightrec_state *state, union code op)
340 {
341 	bool is_cfc = (op.i.op == OP_CP0 && op.r.rs == OP_CP0_CFC0) ||
342 		      (op.i.op == OP_CP2 && op.r.rs == OP_CP2_BASIC_CFC2);
343 	u32 (*func)(struct lightrec_state *, u32, u8);
344 	const struct lightrec_cop_ops *ops;
345 
346 	if (op.i.op == OP_CP0)
347 		ops = &state->ops.cop0_ops;
348 	else
349 		ops = &state->ops.cop2_ops;
350 
351 	if (is_cfc)
352 		func = ops->cfc;
353 	else
354 		func = ops->mfc;
355 
356 	return (*func)(state, op.opcode, op.r.rd);
357 }
358 
lightrec_mfc_cb(struct lightrec_state * state,union code op)359 static void lightrec_mfc_cb(struct lightrec_state *state, union code op)
360 {
361 	u32 rt = lightrec_mfc(state, op);
362 
363 	if (op.r.rt)
364 		state->native_reg_cache[op.r.rt] = rt;
365 }
366 
lightrec_mtc(struct lightrec_state * state,union code op,u32 data)367 void lightrec_mtc(struct lightrec_state *state, union code op, u32 data)
368 {
369 	bool is_ctc = (op.i.op == OP_CP0 && op.r.rs == OP_CP0_CTC0) ||
370 		      (op.i.op == OP_CP2 && op.r.rs == OP_CP2_BASIC_CTC2);
371 	void (*func)(struct lightrec_state *, u32, u8, u32);
372 	const struct lightrec_cop_ops *ops;
373 
374 	if (op.i.op == OP_CP0)
375 		ops = &state->ops.cop0_ops;
376 	else
377 		ops = &state->ops.cop2_ops;
378 
379 	if (is_ctc)
380 		func = ops->ctc;
381 	else
382 		func = ops->mtc;
383 
384 	(*func)(state, op.opcode, op.r.rd, data);
385 }
386 
lightrec_mtc_cb(struct lightrec_state * state,union code op)387 static void lightrec_mtc_cb(struct lightrec_state *state, union code op)
388 {
389 	lightrec_mtc(state, op, state->native_reg_cache[op.r.rt]);
390 }
391 
lightrec_rfe_cb(struct lightrec_state * state,union code op)392 static void lightrec_rfe_cb(struct lightrec_state *state, union code op)
393 {
394 	u32 status;
395 
396 	/* Read CP0 Status register (r12) */
397 	status = state->ops.cop0_ops.mfc(state, op.opcode, 12);
398 
399 	/* Switch the bits */
400 	status = ((status & 0x3c) >> 2) | (status & ~0xf);
401 
402 	/* Write it back */
403 	state->ops.cop0_ops.ctc(state, op.opcode, 12, status);
404 }
405 
lightrec_cp_cb(struct lightrec_state * state,union code op)406 static void lightrec_cp_cb(struct lightrec_state *state, union code op)
407 {
408 	void (*func)(struct lightrec_state *, u32);
409 
410 	if ((op.opcode >> 25) & 1)
411 		func = state->ops.cop2_ops.op;
412 	else
413 		func = state->ops.cop0_ops.op;
414 
415 	(*func)(state, op.opcode);
416 }
417 
lightrec_syscall_cb(struct lightrec_state * state,union code op)418 static void lightrec_syscall_cb(struct lightrec_state *state, union code op)
419 {
420 	lightrec_set_exit_flags(state, LIGHTREC_EXIT_SYSCALL);
421 }
422 
lightrec_break_cb(struct lightrec_state * state,union code op)423 static void lightrec_break_cb(struct lightrec_state *state, union code op)
424 {
425 	lightrec_set_exit_flags(state, LIGHTREC_EXIT_BREAK);
426 }
427 
lightrec_get_block(struct lightrec_state * state,u32 pc)428 struct block * lightrec_get_block(struct lightrec_state *state, u32 pc)
429 {
430 	struct block *block = lightrec_find_block(state->block_cache, pc);
431 
432 	if (block && lightrec_block_is_outdated(block)) {
433 		pr_debug("Block at PC 0x%08x is outdated!\n", block->pc);
434 
435 		/* Make sure the recompiler isn't processing the block we'll
436 		 * destroy */
437 		if (ENABLE_THREADED_COMPILER)
438 			lightrec_recompiler_remove(state->rec, block);
439 
440 		lightrec_unregister_block(state->block_cache, block);
441 		remove_from_code_lut(state->block_cache, block);
442 		lightrec_free_block(block);
443 		block = NULL;
444 	}
445 
446 	if (!block) {
447 		block = lightrec_precompile_block(state, pc);
448 		if (!block) {
449 			pr_err("Unable to recompile block at PC 0x%x\n", pc);
450 			lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT);
451 			return NULL;
452 		}
453 
454 		lightrec_register_block(state->block_cache, block);
455 	}
456 
457 	return block;
458 }
459 
get_next_block_func(struct lightrec_state * state,u32 pc)460 static void * get_next_block_func(struct lightrec_state *state, u32 pc)
461 {
462 	struct block *block;
463 	bool should_recompile;
464 	void *func;
465 
466 	for (;;) {
467 		func = state->code_lut[lut_offset(pc)];
468 		if (func && func != state->get_next_block)
469 			return func;
470 
471 		block = lightrec_get_block(state, pc);
472 
473 		if (unlikely(!block))
474 			return NULL;
475 
476 		should_recompile = block->flags & BLOCK_SHOULD_RECOMPILE &&
477 			!(block->flags & BLOCK_IS_DEAD);
478 
479 		if (unlikely(should_recompile)) {
480 			pr_debug("Block at PC 0x%08x should recompile\n", pc);
481 
482 			lightrec_unregister(MEM_FOR_CODE, block->code_size);
483 
484 			if (ENABLE_THREADED_COMPILER)
485 				lightrec_recompiler_add(state->rec, block);
486 			else
487 				lightrec_compile_block(block);
488 		}
489 
490 		if (ENABLE_THREADED_COMPILER && likely(!should_recompile))
491 			func = lightrec_recompiler_run_first_pass(block, &pc);
492 		else
493 			func = block->function;
494 
495 		if (likely(func))
496 			return func;
497 
498 		/* Block wasn't compiled yet - run the interpreter */
499 		if (!ENABLE_THREADED_COMPILER &&
500 		    ((ENABLE_FIRST_PASS && likely(!should_recompile)) ||
501 		     unlikely(block->flags & BLOCK_NEVER_COMPILE)))
502 			pc = lightrec_emulate_block(block, pc);
503 
504 		if (likely(!(block->flags & BLOCK_NEVER_COMPILE))) {
505 			/* Then compile it using the profiled data */
506 			if (ENABLE_THREADED_COMPILER)
507 				lightrec_recompiler_add(state->rec, block);
508 			else
509 				lightrec_compile_block(block);
510 		}
511 
512 		if (state->exit_flags != LIGHTREC_EXIT_NORMAL ||
513 		    state->current_cycle >= state->target_cycle) {
514 			state->next_pc = pc;
515 			return NULL;
516 		}
517 	}
518 }
519 
c_generic_function_wrapper(struct lightrec_state * state,s32 cycles_delta,void (* f)(struct lightrec_state *,struct opcode *,struct block *),struct opcode * op,struct block * block)520 static s32 c_generic_function_wrapper(struct lightrec_state *state,
521 				      s32 cycles_delta,
522 				      void (*f)(struct lightrec_state *,
523 						struct opcode *,
524 						struct block *),
525 				      struct opcode *op, struct block *block)
526 {
527 	state->current_cycle = state->target_cycle - cycles_delta;
528 
529 	(*f)(state, op, block);
530 
531 	return state->target_cycle - state->current_cycle;
532 }
533 
c_function_wrapper(struct lightrec_state * state,s32 cycles_delta,void (* f)(struct lightrec_state *,union code),union code op)534 static s32 c_function_wrapper(struct lightrec_state *state, s32 cycles_delta,
535 			      void (*f)(struct lightrec_state *, union code),
536 			      union code op)
537 {
538 	state->current_cycle = state->target_cycle - cycles_delta;
539 
540 	(*f)(state, op);
541 
542 	return state->target_cycle - state->current_cycle;
543 }
544 
generate_wrapper(struct lightrec_state * state,void * f,bool generic)545 static struct block * generate_wrapper(struct lightrec_state *state,
546 				       void *f, bool generic)
547 {
548 	struct block *block;
549 	jit_state_t *_jit;
550 	unsigned int i;
551 	int stack_ptr;
552 	jit_word_t code_size;
553 	jit_node_t *to_tramp, *to_fn_epilog;
554 
555 	block = lightrec_malloc(state, MEM_FOR_IR, sizeof(*block));
556 	if (!block)
557 		goto err_no_mem;
558 
559 	_jit = jit_new_state();
560 	if (!_jit)
561 		goto err_free_block;
562 
563 	jit_name("RW wrapper");
564 	jit_note(__FILE__, __LINE__);
565 
566 	/* Wrapper entry point */
567 	jit_prolog();
568 
569 	stack_ptr = jit_allocai(sizeof(uintptr_t) * NUM_TEMPS);
570 
571 	for (i = 0; i < NUM_TEMPS; i++)
572 		jit_stxi(stack_ptr + i * sizeof(uintptr_t), JIT_FP, JIT_R(i));
573 
574 	/* Jump to the trampoline */
575 	to_tramp = jit_jmpi();
576 
577 	/* The trampoline will jump back here */
578 	to_fn_epilog = jit_label();
579 
580 	for (i = 0; i < NUM_TEMPS; i++)
581 		jit_ldxi(JIT_R(i), JIT_FP, stack_ptr + i * sizeof(uintptr_t));
582 
583 	jit_ret();
584 	jit_epilog();
585 
586 	/* Trampoline entry point.
587 	 * The sole purpose of the trampoline is to cheese Lightning not to
588 	 * save/restore the callee-saved register LIGHTREC_REG_CYCLE, since we
589 	 * do want to return to the caller with this register modified. */
590 	jit_prolog();
591 	jit_tramp(256);
592 	jit_patch(to_tramp);
593 
594 	jit_prepare();
595 	jit_pushargr(LIGHTREC_REG_STATE);
596 	jit_pushargr(LIGHTREC_REG_CYCLE);
597 	jit_pushargi((uintptr_t)f);
598 	jit_pushargr(JIT_R0);
599 	if (generic) {
600 		jit_pushargr(JIT_R1);
601 		jit_finishi(c_generic_function_wrapper);
602 	} else {
603 		jit_finishi(c_function_wrapper);
604 	}
605 
606 #if __WORDSIZE == 64
607 	jit_retval_i(LIGHTREC_REG_CYCLE);
608 #else
609 	jit_retval(LIGHTREC_REG_CYCLE);
610 #endif
611 
612 	jit_patch_at(jit_jmpi(), to_fn_epilog);
613 	jit_epilog();
614 
615 	block->state = state;
616 	block->_jit = _jit;
617 	block->function = jit_emit();
618 	block->opcode_list = NULL;
619 	block->flags = 0;
620 	block->nb_ops = 0;
621 
622 	jit_get_code(&code_size);
623 	lightrec_register(MEM_FOR_CODE, code_size);
624 
625 	block->code_size = code_size;
626 
627 	if (ENABLE_DISASSEMBLER) {
628 		pr_debug("Wrapper block:\n");
629 		jit_disassemble();
630 	}
631 
632 	jit_clear_state();
633 	return block;
634 
635 err_free_block:
636 	lightrec_free(state, MEM_FOR_IR, sizeof(*block), block);
637 err_no_mem:
638 	pr_err("Unable to compile wrapper: Out of memory\n");
639 	return NULL;
640 }
641 
generate_dispatcher(struct lightrec_state * state)642 static struct block * generate_dispatcher(struct lightrec_state *state)
643 {
644 	struct block *block;
645 	jit_state_t *_jit;
646 	jit_node_t *to_end, *to_end2, *to_c, *loop, *addr, *addr2;
647 	unsigned int i;
648 	u32 offset, ram_len;
649 	jit_word_t code_size;
650 
651 	block = lightrec_malloc(state, MEM_FOR_IR, sizeof(*block));
652 	if (!block)
653 		goto err_no_mem;
654 
655 	_jit = jit_new_state();
656 	if (!_jit)
657 		goto err_free_block;
658 
659 	jit_name("dispatcher");
660 	jit_note(__FILE__, __LINE__);
661 
662 	jit_prolog();
663 	jit_frame(256);
664 
665 	jit_getarg(JIT_R0, jit_arg());
666 #if __WORDSIZE == 64
667 	jit_getarg_i(LIGHTREC_REG_CYCLE, jit_arg());
668 #else
669 	jit_getarg(LIGHTREC_REG_CYCLE, jit_arg());
670 #endif
671 
672 	/* Force all callee-saved registers to be pushed on the stack */
673 	for (i = 0; i < NUM_REGS; i++)
674 		jit_movr(JIT_V(i), JIT_V(i));
675 
676 	/* Pass lightrec_state structure to blocks, using the last callee-saved
677 	 * register that Lightning provides */
678 	jit_movi(LIGHTREC_REG_STATE, (intptr_t) state);
679 
680 	loop = jit_label();
681 
682 	/* Call the block's code */
683 	jit_jmpr(JIT_R0);
684 
685 	/* The block will jump here, with the number of cycles remaining in
686 	 * LIGHTREC_REG_CYCLE */
687 	addr2 = jit_indirect();
688 
689 	/* Jump to end if state->target_cycle < state->current_cycle */
690 	to_end = jit_blei(LIGHTREC_REG_CYCLE, 0);
691 
692 	/* Convert next PC to KUNSEG and avoid mirrors */
693 	ram_len = state->maps[PSX_MAP_KERNEL_USER_RAM].length;
694 	jit_andi(JIT_R0, JIT_V0, 0x10000000 | (ram_len - 1));
695 	to_c = jit_bgei(JIT_R0, ram_len);
696 
697 	/* Fast path: code is running from RAM, use the code LUT */
698 #if __WORDSIZE == 64
699 	jit_lshi(JIT_R0, JIT_R0, 1);
700 #endif
701 	jit_addr(JIT_R0, JIT_R0, LIGHTREC_REG_STATE);
702 	jit_ldxi(JIT_R0, JIT_R0, offsetof(struct lightrec_state, code_lut));
703 
704 	/* If we get non-NULL, loop */
705 	jit_patch_at(jit_bnei(JIT_R0, 0), loop);
706 
707 	/* Slow path: call C function get_next_block_func() */
708 	jit_patch(to_c);
709 
710 	if (ENABLE_FIRST_PASS) {
711 		/* We may call the interpreter - update state->current_cycle */
712 		jit_ldxi_i(JIT_R2, LIGHTREC_REG_STATE,
713 			   offsetof(struct lightrec_state, target_cycle));
714 		jit_subr(JIT_R1, JIT_R2, LIGHTREC_REG_CYCLE);
715 		jit_stxi_i(offsetof(struct lightrec_state, current_cycle),
716 			   LIGHTREC_REG_STATE, JIT_R1);
717 	}
718 
719 	/* The code LUT will be set to this address when the block at the target
720 	 * PC has been preprocessed but not yet compiled by the threaded
721 	 * recompiler */
722 	addr = jit_indirect();
723 
724 	/* Get the next block */
725 	jit_prepare();
726 	jit_pushargr(LIGHTREC_REG_STATE);
727 	jit_pushargr(JIT_V0);
728 	jit_finishi(&get_next_block_func);
729 	jit_retval(JIT_R0);
730 
731 	if (ENABLE_FIRST_PASS) {
732 		/* The interpreter may have updated state->current_cycle and
733 		 * state->target_cycle - recalc the delta */
734 		jit_ldxi_i(JIT_R1, LIGHTREC_REG_STATE,
735 			   offsetof(struct lightrec_state, current_cycle));
736 		jit_ldxi_i(JIT_R2, LIGHTREC_REG_STATE,
737 			   offsetof(struct lightrec_state, target_cycle));
738 		jit_subr(LIGHTREC_REG_CYCLE, JIT_R2, JIT_R1);
739 	}
740 
741 	/* If we get non-NULL, loop */
742 	jit_patch_at(jit_bnei(JIT_R0, 0), loop);
743 
744 	to_end2 = jit_jmpi();
745 
746 	/* When exiting, the recompiled code will jump to that address */
747 	jit_note(__FILE__, __LINE__);
748 	jit_patch(to_end);
749 
750 	/* Store back the next_pc to the lightrec_state structure */
751 	offset = offsetof(struct lightrec_state, next_pc);
752 	jit_stxi_i(offset, LIGHTREC_REG_STATE, JIT_V0);
753 
754 	jit_patch(to_end2);
755 
756 	jit_retr(LIGHTREC_REG_CYCLE);
757 	jit_epilog();
758 
759 	block->state = state;
760 	block->_jit = _jit;
761 	block->function = jit_emit();
762 	block->opcode_list = NULL;
763 	block->flags = 0;
764 	block->nb_ops = 0;
765 
766 	jit_get_code(&code_size);
767 	lightrec_register(MEM_FOR_CODE, code_size);
768 
769 	block->code_size = code_size;
770 
771 	state->eob_wrapper_func = jit_address(addr2);
772 	state->get_next_block = jit_address(addr);
773 
774 	if (ENABLE_DISASSEMBLER) {
775 		pr_debug("Dispatcher block:\n");
776 		jit_disassemble();
777 	}
778 
779 	/* We're done! */
780 	jit_clear_state();
781 	return block;
782 
783 err_free_block:
784 	lightrec_free(state, MEM_FOR_IR, sizeof(*block), block);
785 err_no_mem:
786 	pr_err("Unable to compile dispatcher: Out of memory\n");
787 	return NULL;
788 }
789 
lightrec_read_opcode(struct lightrec_state * state,u32 pc)790 union code lightrec_read_opcode(struct lightrec_state *state, u32 pc)
791 {
792 	u32 addr, kunseg_pc = kunseg(pc);
793 	const u32 *code;
794 	const struct lightrec_mem_map *map = lightrec_get_map(state, kunseg_pc);
795 
796 	addr = kunseg_pc - map->pc;
797 
798 	while (map->mirror_of)
799 		map = map->mirror_of;
800 
801 	code = map->address + addr;
802 
803 	return (union code) *code;
804 }
805 
lightrec_precompile_block(struct lightrec_state * state,u32 pc)806 static struct block * lightrec_precompile_block(struct lightrec_state *state,
807 						u32 pc)
808 {
809 	struct opcode *list;
810 	struct block *block;
811 	const u32 *code;
812 	u32 addr, kunseg_pc = kunseg(pc);
813 	const struct lightrec_mem_map *map = lightrec_get_map(state, kunseg_pc);
814 	unsigned int length;
815 
816 	if (!map)
817 		return NULL;
818 
819 	addr = kunseg_pc - map->pc;
820 
821 	while (map->mirror_of)
822 		map = map->mirror_of;
823 
824 	code = map->address + addr;
825 
826 	block = lightrec_malloc(state, MEM_FOR_IR, sizeof(*block));
827 	if (!block) {
828 		pr_err("Unable to recompile block: Out of memory\n");
829 		return NULL;
830 	}
831 
832 	list = lightrec_disassemble(state, code, &length);
833 	if (!list) {
834 		lightrec_free(state, MEM_FOR_IR, sizeof(*block), block);
835 		return NULL;
836 	}
837 
838 	block->pc = pc;
839 	block->state = state;
840 	block->_jit = NULL;
841 	block->function = NULL;
842 	block->opcode_list = list;
843 	block->map = map;
844 	block->next = NULL;
845 	block->flags = 0;
846 	block->code_size = 0;
847 #if ENABLE_THREADED_COMPILER
848 	block->op_list_freed = (atomic_flag)ATOMIC_FLAG_INIT;
849 #endif
850 	block->nb_ops = length / sizeof(u32);
851 
852 	lightrec_optimize(block);
853 
854 	length = block->nb_ops * sizeof(u32);
855 
856 	lightrec_register(MEM_FOR_MIPS_CODE, length);
857 
858 	if (ENABLE_DISASSEMBLER) {
859 		pr_debug("Disassembled block at PC: 0x%x\n", block->pc);
860 		lightrec_print_disassembly(block, code, length);
861 	}
862 
863 	pr_debug("Block size: %lu opcodes\n", block->nb_ops);
864 
865 	/* If the first opcode is an 'impossible' branch, never compile the
866 	 * block */
867 	if (list->flags & LIGHTREC_EMULATE_BRANCH)
868 		block->flags |= BLOCK_NEVER_COMPILE;
869 
870 	block->hash = lightrec_calculate_block_hash(block);
871 
872 	pr_debug("Recompile count: %u\n", state->nb_precompile++);
873 
874 	return block;
875 }
876 
lightrec_block_is_fully_tagged(struct block * block)877 static bool lightrec_block_is_fully_tagged(struct block *block)
878 {
879 	struct opcode *op;
880 
881 	for (op = block->opcode_list; op; op = op->next) {
882 		/* Verify that all load/stores of the opcode list
883 		 * Check all loads/stores of the opcode list and mark the
884 		 * block as fully compiled if they all have been tagged. */
885 		switch (op->c.i.op) {
886 		case OP_LB:
887 		case OP_LH:
888 		case OP_LWL:
889 		case OP_LW:
890 		case OP_LBU:
891 		case OP_LHU:
892 		case OP_LWR:
893 		case OP_SB:
894 		case OP_SH:
895 		case OP_SWL:
896 		case OP_SW:
897 		case OP_SWR:
898 		case OP_LWC2:
899 		case OP_SWC2:
900 			if (!(op->flags & (LIGHTREC_DIRECT_IO |
901 					   LIGHTREC_HW_IO)))
902 				return false;
903 		default: /* fall-through */
904 			continue;
905 		}
906 	}
907 
908 	return true;
909 }
910 
lightrec_reap_block(void * data)911 static void lightrec_reap_block(void *data)
912 {
913 	struct block *block = data;
914 
915 	pr_debug("Reap dead block at PC 0x%08x\n", block->pc);
916 	lightrec_free_block(block);
917 }
918 
lightrec_reap_jit(void * data)919 static void lightrec_reap_jit(void *data)
920 {
921 	_jit_destroy_state(data);
922 }
923 
lightrec_compile_block(struct block * block)924 int lightrec_compile_block(struct block *block)
925 {
926 	struct lightrec_state *state = block->state;
927 	struct lightrec_branch_target *target;
928 	bool op_list_freed = false, fully_tagged = false;
929 	struct block *block2;
930 	struct opcode *elm;
931 	jit_state_t *_jit, *oldjit;
932 	jit_node_t *start_of_block;
933 	bool skip_next = false;
934 	jit_word_t code_size;
935 	unsigned int i, j;
936 	u32 next_pc, offset;
937 
938 	fully_tagged = lightrec_block_is_fully_tagged(block);
939 	if (fully_tagged)
940 		block->flags |= BLOCK_FULLY_TAGGED;
941 
942 	_jit = jit_new_state();
943 	if (!_jit)
944 		return -ENOMEM;
945 
946 	oldjit = block->_jit;
947 	block->_jit = _jit;
948 
949 	lightrec_regcache_reset(state->reg_cache);
950 	state->cycles = 0;
951 	state->nb_branches = 0;
952 	state->nb_local_branches = 0;
953 	state->nb_targets = 0;
954 
955 	jit_prolog();
956 	jit_tramp(256);
957 
958 	start_of_block = jit_label();
959 
960 	for (elm = block->opcode_list; elm; elm = elm->next) {
961 		next_pc = block->pc + elm->offset * sizeof(u32);
962 
963 		if (skip_next) {
964 			skip_next = false;
965 			continue;
966 		}
967 
968 		state->cycles += lightrec_cycles_of_opcode(elm->c);
969 
970 		if (elm->flags & LIGHTREC_EMULATE_BRANCH) {
971 			pr_debug("Branch at offset 0x%x will be emulated\n",
972 				 elm->offset << 2);
973 			lightrec_emit_eob(block, elm, next_pc);
974 			skip_next = !(elm->flags & LIGHTREC_NO_DS);
975 		} else if (elm->opcode) {
976 			lightrec_rec_opcode(block, elm, next_pc);
977 			skip_next = has_delay_slot(elm->c) &&
978 				!(elm->flags & LIGHTREC_NO_DS);
979 #if _WIN32
980 			/* FIXME: GNU Lightning on Windows seems to use our
981 			 * mapped registers as temporaries. Until the actual bug
982 			 * is found and fixed, unconditionally mark our
983 			 * registers as live here. */
984 			lightrec_regcache_mark_live(state->reg_cache, _jit);
985 #endif
986 		}
987 	}
988 
989 	for (i = 0; i < state->nb_branches; i++)
990 		jit_patch(state->branches[i]);
991 
992 	for (i = 0; i < state->nb_local_branches; i++) {
993 		struct lightrec_branch *branch = &state->local_branches[i];
994 
995 		pr_debug("Patch local branch to offset 0x%x\n",
996 			 branch->target << 2);
997 
998 		if (branch->target == 0) {
999 			jit_patch_at(branch->branch, start_of_block);
1000 			continue;
1001 		}
1002 
1003 		for (j = 0; j < state->nb_targets; j++) {
1004 			if (state->targets[j].offset == branch->target) {
1005 				jit_patch_at(branch->branch,
1006 					     state->targets[j].label);
1007 				break;
1008 			}
1009 		}
1010 
1011 		if (j == state->nb_targets)
1012 			pr_err("Unable to find branch target\n");
1013 	}
1014 
1015 	jit_ldxi(JIT_R0, LIGHTREC_REG_STATE,
1016 		 offsetof(struct lightrec_state, eob_wrapper_func));
1017 
1018 	jit_jmpr(JIT_R0);
1019 
1020 	jit_ret();
1021 	jit_epilog();
1022 
1023 	block->function = jit_emit();
1024 	block->flags &= ~BLOCK_SHOULD_RECOMPILE;
1025 
1026 	/* Add compiled function to the LUT */
1027 	state->code_lut[lut_offset(block->pc)] = block->function;
1028 
1029 	/* Fill code LUT with the block's entry points */
1030 	for (i = 0; i < state->nb_targets; i++) {
1031 		target = &state->targets[i];
1032 
1033 		if (target->offset) {
1034 			offset = lut_offset(block->pc) + target->offset;
1035 			state->code_lut[offset] = jit_address(target->label);
1036 		}
1037 	}
1038 
1039 	/* Detect old blocks that have been covered by the new one */
1040 	for (i = 0; i < state->nb_targets; i++) {
1041 		target = &state->targets[i];
1042 
1043 		if (!target->offset)
1044 			continue;
1045 
1046 		offset = block->pc + target->offset * sizeof(u32);
1047 		block2 = lightrec_find_block(state->block_cache, offset);
1048 		if (block2) {
1049 			/* No need to check if block2 is compilable - it must
1050 			 * be, otherwise block wouldn't be compilable either */
1051 
1052 			block2->flags |= BLOCK_IS_DEAD;
1053 
1054 			pr_debug("Reap block 0x%08x as it's covered by block "
1055 				 "0x%08x\n", block2->pc, block->pc);
1056 
1057 			lightrec_unregister_block(state->block_cache, block2);
1058 
1059 			if (ENABLE_THREADED_COMPILER) {
1060 				lightrec_recompiler_remove(state->rec, block2);
1061 				lightrec_reaper_add(state->reaper,
1062 						    lightrec_reap_block,
1063 						    block2);
1064 			} else {
1065 				lightrec_free_block(block2);
1066 			}
1067 		}
1068 	}
1069 
1070 	jit_get_code(&code_size);
1071 	lightrec_register(MEM_FOR_CODE, code_size);
1072 
1073 	block->code_size = code_size;
1074 
1075 	if (ENABLE_DISASSEMBLER) {
1076 		pr_debug("Compiling block at PC: 0x%x\n", block->pc);
1077 		jit_disassemble();
1078 	}
1079 
1080 	jit_clear_state();
1081 
1082 #if ENABLE_THREADED_COMPILER
1083 	if (fully_tagged)
1084 		op_list_freed = atomic_flag_test_and_set(&block->op_list_freed);
1085 #endif
1086 	if (fully_tagged && !op_list_freed) {
1087 		pr_debug("Block PC 0x%08x is fully tagged"
1088 			 " - free opcode list\n", block->pc);
1089 		lightrec_free_opcode_list(state, block->opcode_list);
1090 		block->opcode_list = NULL;
1091 	}
1092 
1093 	if (oldjit) {
1094 		pr_debug("Block 0x%08x recompiled, reaping old jit context.\n",
1095 			 block->pc);
1096 
1097 		if (ENABLE_THREADED_COMPILER)
1098 			lightrec_reaper_add(state->reaper,
1099 					    lightrec_reap_jit, oldjit);
1100 		else
1101 			_jit_destroy_state(oldjit);
1102 	}
1103 
1104 	return 0;
1105 }
1106 
lightrec_execute(struct lightrec_state * state,u32 pc,u32 target_cycle)1107 u32 lightrec_execute(struct lightrec_state *state, u32 pc, u32 target_cycle)
1108 {
1109 	s32 (*func)(void *, s32) = (void *)state->dispatcher->function;
1110 	void *block_trace;
1111 	s32 cycles_delta;
1112 
1113 	state->exit_flags = LIGHTREC_EXIT_NORMAL;
1114 
1115 	/* Handle the cycle counter overflowing */
1116 	if (unlikely(target_cycle < state->current_cycle))
1117 		target_cycle = UINT_MAX;
1118 
1119 	state->target_cycle = target_cycle;
1120 
1121 	block_trace = get_next_block_func(state, pc);
1122 	if (block_trace) {
1123 		cycles_delta = state->target_cycle - state->current_cycle;
1124 
1125 		cycles_delta = (*func)(block_trace, cycles_delta);
1126 
1127 		state->current_cycle = state->target_cycle - cycles_delta;
1128 	}
1129 
1130 	if (ENABLE_THREADED_COMPILER)
1131 		lightrec_reaper_reap(state->reaper);
1132 
1133 	return state->next_pc;
1134 }
1135 
lightrec_execute_one(struct lightrec_state * state,u32 pc)1136 u32 lightrec_execute_one(struct lightrec_state *state, u32 pc)
1137 {
1138 	return lightrec_execute(state, pc, state->current_cycle);
1139 }
1140 
lightrec_run_interpreter(struct lightrec_state * state,u32 pc)1141 u32 lightrec_run_interpreter(struct lightrec_state *state, u32 pc)
1142 {
1143 	struct block *block = lightrec_get_block(state, pc);
1144 	if (!block)
1145 		return 0;
1146 
1147 	state->exit_flags = LIGHTREC_EXIT_NORMAL;
1148 
1149 	return lightrec_emulate_block(block, pc);
1150 }
1151 
lightrec_free_block(struct block * block)1152 void lightrec_free_block(struct block *block)
1153 {
1154 	lightrec_unregister(MEM_FOR_MIPS_CODE, block->nb_ops * sizeof(u32));
1155 	if (block->opcode_list)
1156 		lightrec_free_opcode_list(block->state, block->opcode_list);
1157 	if (block->_jit)
1158 		_jit_destroy_state(block->_jit);
1159 	lightrec_unregister(MEM_FOR_CODE, block->code_size);
1160 	lightrec_free(block->state, MEM_FOR_IR, sizeof(*block), block);
1161 }
1162 
lightrec_init(char * argv0,const struct lightrec_mem_map * map,size_t nb,const struct lightrec_ops * ops)1163 struct lightrec_state * lightrec_init(char *argv0,
1164 				      const struct lightrec_mem_map *map,
1165 				      size_t nb,
1166 				      const struct lightrec_ops *ops)
1167 {
1168 	struct lightrec_state *state;
1169 
1170 	/* Sanity-check ops */
1171 	if (!ops ||
1172 	    !ops->cop0_ops.mfc || !ops->cop0_ops.cfc || !ops->cop0_ops.mtc ||
1173 	    !ops->cop0_ops.ctc || !ops->cop0_ops.op ||
1174 	    !ops->cop2_ops.mfc || !ops->cop2_ops.cfc || !ops->cop2_ops.mtc ||
1175 	    !ops->cop2_ops.ctc || !ops->cop2_ops.op) {
1176 		pr_err("Missing callbacks in lightrec_ops structure\n");
1177 		return NULL;
1178 	}
1179 
1180 	init_jit(argv0);
1181 
1182 	state = calloc(1, sizeof(*state) +
1183 		       sizeof(*state->code_lut) * CODE_LUT_SIZE);
1184 	if (!state)
1185 		goto err_finish_jit;
1186 
1187 	lightrec_register(MEM_FOR_LIGHTREC, sizeof(*state) +
1188 			  sizeof(*state->code_lut) * CODE_LUT_SIZE);
1189 
1190 #if ENABLE_TINYMM
1191 	state->tinymm = tinymm_init(malloc, free, 4096);
1192 	if (!state->tinymm)
1193 		goto err_free_state;
1194 #endif
1195 
1196 	state->block_cache = lightrec_blockcache_init(state);
1197 	if (!state->block_cache)
1198 		goto err_free_tinymm;
1199 
1200 	state->reg_cache = lightrec_regcache_init(state);
1201 	if (!state->reg_cache)
1202 		goto err_free_block_cache;
1203 
1204 	if (ENABLE_THREADED_COMPILER) {
1205 		state->rec = lightrec_recompiler_init(state);
1206 		if (!state->rec)
1207 			goto err_free_reg_cache;
1208 
1209 		state->reaper = lightrec_reaper_init(state);
1210 		if (!state->reaper)
1211 			goto err_free_recompiler;
1212 	}
1213 
1214 	state->nb_maps = nb;
1215 	state->maps = map;
1216 
1217 	memcpy(&state->ops, ops, sizeof(*ops));
1218 
1219 	state->dispatcher = generate_dispatcher(state);
1220 	if (!state->dispatcher)
1221 		goto err_free_reaper;
1222 
1223 	state->rw_generic_wrapper = generate_wrapper(state,
1224 						     lightrec_rw_generic_cb,
1225 						     true);
1226 	if (!state->rw_generic_wrapper)
1227 		goto err_free_dispatcher;
1228 
1229 	state->rw_wrapper = generate_wrapper(state, lightrec_rw_cb, false);
1230 	if (!state->rw_wrapper)
1231 		goto err_free_generic_rw_wrapper;
1232 
1233 	state->mfc_wrapper = generate_wrapper(state, lightrec_mfc_cb, false);
1234 	if (!state->mfc_wrapper)
1235 		goto err_free_rw_wrapper;
1236 
1237 	state->mtc_wrapper = generate_wrapper(state, lightrec_mtc_cb, false);
1238 	if (!state->mtc_wrapper)
1239 		goto err_free_mfc_wrapper;
1240 
1241 	state->rfe_wrapper = generate_wrapper(state, lightrec_rfe_cb, false);
1242 	if (!state->rfe_wrapper)
1243 		goto err_free_mtc_wrapper;
1244 
1245 	state->cp_wrapper = generate_wrapper(state, lightrec_cp_cb, false);
1246 	if (!state->cp_wrapper)
1247 		goto err_free_rfe_wrapper;
1248 
1249 	state->syscall_wrapper = generate_wrapper(state, lightrec_syscall_cb,
1250 						  false);
1251 	if (!state->syscall_wrapper)
1252 		goto err_free_cp_wrapper;
1253 
1254 	state->break_wrapper = generate_wrapper(state, lightrec_break_cb,
1255 						false);
1256 	if (!state->break_wrapper)
1257 		goto err_free_syscall_wrapper;
1258 
1259 	state->rw_generic_func = state->rw_generic_wrapper->function;
1260 	state->rw_func = state->rw_wrapper->function;
1261 	state->mfc_func = state->mfc_wrapper->function;
1262 	state->mtc_func = state->mtc_wrapper->function;
1263 	state->rfe_func = state->rfe_wrapper->function;
1264 	state->cp_func = state->cp_wrapper->function;
1265 	state->syscall_func = state->syscall_wrapper->function;
1266 	state->break_func = state->break_wrapper->function;
1267 
1268 	map = &state->maps[PSX_MAP_BIOS];
1269 	state->offset_bios = (uintptr_t)map->address - map->pc;
1270 
1271 	map = &state->maps[PSX_MAP_SCRATCH_PAD];
1272 	state->offset_scratch = (uintptr_t)map->address - map->pc;
1273 
1274 	map = &state->maps[PSX_MAP_KERNEL_USER_RAM];
1275 	state->offset_ram = (uintptr_t)map->address - map->pc;
1276 
1277 	if (state->maps[PSX_MAP_MIRROR1].address == map->address + 0x200000 &&
1278 	    state->maps[PSX_MAP_MIRROR2].address == map->address + 0x400000 &&
1279 	    state->maps[PSX_MAP_MIRROR3].address == map->address + 0x600000)
1280 		state->mirrors_mapped = true;
1281 
1282 	return state;
1283 
1284 err_free_syscall_wrapper:
1285 	lightrec_free_block(state->syscall_wrapper);
1286 err_free_cp_wrapper:
1287 	lightrec_free_block(state->cp_wrapper);
1288 err_free_rfe_wrapper:
1289 	lightrec_free_block(state->rfe_wrapper);
1290 err_free_mtc_wrapper:
1291 	lightrec_free_block(state->mtc_wrapper);
1292 err_free_mfc_wrapper:
1293 	lightrec_free_block(state->mfc_wrapper);
1294 err_free_rw_wrapper:
1295 	lightrec_free_block(state->rw_wrapper);
1296 err_free_generic_rw_wrapper:
1297 	lightrec_free_block(state->rw_generic_wrapper);
1298 err_free_dispatcher:
1299 	lightrec_free_block(state->dispatcher);
1300 err_free_reaper:
1301 	if (ENABLE_THREADED_COMPILER)
1302 		lightrec_reaper_destroy(state->reaper);
1303 err_free_recompiler:
1304 	if (ENABLE_THREADED_COMPILER)
1305 		lightrec_free_recompiler(state->rec);
1306 err_free_reg_cache:
1307 	lightrec_free_regcache(state->reg_cache);
1308 err_free_block_cache:
1309 	lightrec_free_block_cache(state->block_cache);
1310 err_free_tinymm:
1311 #if ENABLE_TINYMM
1312 	tinymm_shutdown(state->tinymm);
1313 err_free_state:
1314 #endif
1315 	lightrec_unregister(MEM_FOR_LIGHTREC, sizeof(*state) +
1316 			    sizeof(*state->code_lut) * CODE_LUT_SIZE);
1317 	free(state);
1318 err_finish_jit:
1319 	finish_jit();
1320 	return NULL;
1321 }
1322 
lightrec_destroy(struct lightrec_state * state)1323 void lightrec_destroy(struct lightrec_state *state)
1324 {
1325 	if (ENABLE_THREADED_COMPILER) {
1326 		lightrec_free_recompiler(state->rec);
1327 		lightrec_reaper_destroy(state->reaper);
1328 	}
1329 
1330 	lightrec_free_regcache(state->reg_cache);
1331 	lightrec_free_block_cache(state->block_cache);
1332 	lightrec_free_block(state->dispatcher);
1333 	lightrec_free_block(state->rw_generic_wrapper);
1334 	lightrec_free_block(state->rw_wrapper);
1335 	lightrec_free_block(state->mfc_wrapper);
1336 	lightrec_free_block(state->mtc_wrapper);
1337 	lightrec_free_block(state->rfe_wrapper);
1338 	lightrec_free_block(state->cp_wrapper);
1339 	lightrec_free_block(state->syscall_wrapper);
1340 	lightrec_free_block(state->break_wrapper);
1341 	finish_jit();
1342 
1343 #if ENABLE_TINYMM
1344 	tinymm_shutdown(state->tinymm);
1345 #endif
1346 	lightrec_unregister(MEM_FOR_LIGHTREC, sizeof(*state) +
1347 			    sizeof(*state->code_lut) * CODE_LUT_SIZE);
1348 	free(state);
1349 }
1350 
lightrec_invalidate(struct lightrec_state * state,u32 addr,u32 len)1351 void lightrec_invalidate(struct lightrec_state *state, u32 addr, u32 len)
1352 {
1353 	u32 kaddr = kunseg(addr & ~0x3);
1354 	const struct lightrec_mem_map *map = lightrec_get_map(state, kaddr);
1355 
1356 	if (map) {
1357 		while (map->mirror_of)
1358 			map = map->mirror_of;
1359 
1360 		if (map != &state->maps[PSX_MAP_KERNEL_USER_RAM])
1361 			return;
1362 
1363 		/* Handle mirrors */
1364 		kaddr &= (state->maps[PSX_MAP_KERNEL_USER_RAM].length - 1);
1365 
1366 		for (; len > 4; len -= 4, kaddr += 4)
1367 			lightrec_invalidate_map(state, map, kaddr);
1368 
1369 		lightrec_invalidate_map(state, map, kaddr);
1370 	}
1371 }
1372 
lightrec_invalidate_all(struct lightrec_state * state)1373 void lightrec_invalidate_all(struct lightrec_state *state)
1374 {
1375 	memset(state->code_lut, 0, sizeof(*state->code_lut) * CODE_LUT_SIZE);
1376 }
1377 
lightrec_set_invalidate_mode(struct lightrec_state * state,bool dma_only)1378 void lightrec_set_invalidate_mode(struct lightrec_state *state, bool dma_only)
1379 {
1380 	if (state->invalidate_from_dma_only != dma_only)
1381 		lightrec_invalidate_all(state);
1382 
1383 	state->invalidate_from_dma_only = dma_only;
1384 }
1385 
lightrec_set_exit_flags(struct lightrec_state * state,u32 flags)1386 void lightrec_set_exit_flags(struct lightrec_state *state, u32 flags)
1387 {
1388 	if (flags != LIGHTREC_EXIT_NORMAL) {
1389 		state->exit_flags |= flags;
1390 		state->target_cycle = state->current_cycle;
1391 	}
1392 }
1393 
lightrec_exit_flags(struct lightrec_state * state)1394 u32 lightrec_exit_flags(struct lightrec_state *state)
1395 {
1396 	return state->exit_flags;
1397 }
1398 
lightrec_dump_registers(struct lightrec_state * state,u32 regs[34])1399 void lightrec_dump_registers(struct lightrec_state *state, u32 regs[34])
1400 {
1401 	memcpy(regs, state->native_reg_cache, sizeof(state->native_reg_cache));
1402 }
1403 
lightrec_restore_registers(struct lightrec_state * state,u32 regs[34])1404 void lightrec_restore_registers(struct lightrec_state *state, u32 regs[34])
1405 {
1406 	memcpy(state->native_reg_cache, regs, sizeof(state->native_reg_cache));
1407 }
1408 
lightrec_current_cycle_count(const struct lightrec_state * state)1409 u32 lightrec_current_cycle_count(const struct lightrec_state *state)
1410 {
1411 	return state->current_cycle;
1412 }
1413 
lightrec_reset_cycle_count(struct lightrec_state * state,u32 cycles)1414 void lightrec_reset_cycle_count(struct lightrec_state *state, u32 cycles)
1415 {
1416 	state->current_cycle = cycles;
1417 
1418 	if (state->target_cycle < cycles)
1419 		state->target_cycle = cycles;
1420 }
1421 
lightrec_set_target_cycle_count(struct lightrec_state * state,u32 cycles)1422 void lightrec_set_target_cycle_count(struct lightrec_state *state, u32 cycles)
1423 {
1424 	if (state->exit_flags == LIGHTREC_EXIT_NORMAL) {
1425 		if (cycles < state->current_cycle)
1426 			cycles = state->current_cycle;
1427 
1428 		state->target_cycle = cycles;
1429 	}
1430 }
1431