1 /*
2  * Copyright (C) 2016-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 #ifndef __LIGHTREC_PRIVATE_H__
16 #define __LIGHTREC_PRIVATE_H__
17 
18 #include "config.h"
19 #include "disassembler.h"
20 #include "lightrec.h"
21 
22 #if ENABLE_THREADED_COMPILER
23 #include <stdatomic.h>
24 #endif
25 
26 #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0)
27 #define BIT(x) (1 << (x))
28 
29 #ifdef __GNUC__
30 #	define likely(x)       __builtin_expect(!!(x),1)
31 #	define unlikely(x)     __builtin_expect(!!(x),0)
32 #else
33 #	define likely(x)       (x)
34 #	define unlikely(x)     (x)
35 #endif
36 
37 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
38 #	define LE32TOH(x)	__builtin_bswap32(x)
39 #	define HTOLE32(x)	__builtin_bswap32(x)
40 #	define LE16TOH(x)	__builtin_bswap16(x)
41 #	define HTOLE16(x)	__builtin_bswap16(x)
42 #else
43 #	define LE32TOH(x)	(x)
44 #	define HTOLE32(x)	(x)
45 #	define LE16TOH(x)	(x)
46 #	define HTOLE16(x)	(x)
47 #endif
48 
49 /* Flags for (struct block *)->flags */
50 #define BLOCK_NEVER_COMPILE	BIT(0)
51 #define BLOCK_SHOULD_RECOMPILE	BIT(1)
52 #define BLOCK_FULLY_TAGGED	BIT(2)
53 #define BLOCK_IS_DEAD		BIT(3)
54 
55 #define RAM_SIZE	0x200000
56 #define BIOS_SIZE	0x80000
57 
58 #define CODE_LUT_SIZE	((RAM_SIZE + BIOS_SIZE) >> 2)
59 
60 /* Definition of jit_state_t (avoids inclusion of <lightning.h>) */
61 struct jit_node;
62 struct jit_state;
63 typedef struct jit_state jit_state_t;
64 
65 struct blockcache;
66 struct recompiler;
67 struct regcache;
68 struct opcode;
69 struct tinymm;
70 struct reaper;
71 
72 struct block {
73 	jit_state_t *_jit;
74 	struct lightrec_state *state;
75 	struct opcode *opcode_list;
76 	void (*function)(void);
77 	u32 pc;
78 	u32 hash;
79 #if ENABLE_THREADED_COMPILER
80 	atomic_flag op_list_freed;
81 #endif
82 	unsigned int code_size;
83 	u16 flags;
84 	u16 nb_ops;
85 	const struct lightrec_mem_map *map;
86 	struct block *next;
87 };
88 
89 struct lightrec_branch {
90 	struct jit_node *branch;
91 	u32 target;
92 };
93 
94 struct lightrec_branch_target {
95 	struct jit_node *label;
96 	u32 offset;
97 };
98 
99 struct lightrec_state {
100 	u32 native_reg_cache[34];
101 	u32 next_pc;
102 	u32 current_cycle;
103 	u32 target_cycle;
104 	u32 exit_flags;
105 	struct block *dispatcher, *rw_wrapper, *rw_generic_wrapper,
106 		     *mfc_wrapper, *mtc_wrapper, *rfe_wrapper, *cp_wrapper,
107 		     *syscall_wrapper, *break_wrapper;
108 	void *rw_func, *rw_generic_func, *mfc_func, *mtc_func, *rfe_func,
109 	     *cp_func, *syscall_func, *break_func;
110 	struct jit_node *branches[512];
111 	struct lightrec_branch local_branches[512];
112 	struct lightrec_branch_target targets[512];
113 	unsigned int nb_branches;
114 	unsigned int nb_local_branches;
115 	unsigned int nb_targets;
116 	struct tinymm *tinymm;
117 	struct blockcache *block_cache;
118 	struct regcache *reg_cache;
119 	struct recompiler *rec;
120 	struct reaper *reaper;
121 	void (*eob_wrapper_func)(void);
122 	void (*get_next_block)(void);
123 	struct lightrec_ops ops;
124 	unsigned int nb_precompile;
125 	unsigned int cycles;
126 	unsigned int nb_maps;
127 	const struct lightrec_mem_map *maps;
128 	uintptr_t offset_ram, offset_bios, offset_scratch;
129 	_Bool mirrors_mapped;
130 	_Bool invalidate_from_dma_only;
131 	void *code_lut[];
132 };
133 
134 u32 lightrec_rw(struct lightrec_state *state, union code op,
135 		u32 addr, u32 data, u16 *flags);
136 
137 void lightrec_free_block(struct block *block);
138 
139 void remove_from_code_lut(struct blockcache *cache, struct block *block);
140 
kunseg(u32 addr)141 static inline u32 kunseg(u32 addr)
142 {
143 	if (unlikely(addr >= 0xa0000000))
144 		return addr - 0xa0000000;
145 	else
146 		return addr &~ 0x80000000;
147 }
148 
lut_offset(u32 pc)149 static inline u32 lut_offset(u32 pc)
150 {
151 	if (pc & BIT(28))
152 		return ((pc & (BIOS_SIZE - 1)) + RAM_SIZE) >> 2; // BIOS
153 	else
154 		return (pc & (RAM_SIZE - 1)) >> 2; // RAM
155 }
156 
157 void lightrec_mtc(struct lightrec_state *state, union code op, u32 data);
158 u32 lightrec_mfc(struct lightrec_state *state, union code op);
159 
160 union code lightrec_read_opcode(struct lightrec_state *state, u32 pc);
161 
162 struct block * lightrec_get_block(struct lightrec_state *state, u32 pc);
163 int lightrec_compile_block(struct block *block);
164 
165 #endif /* __LIGHTREC_PRIVATE_H__ */
166