1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - asm_defines.c * |
3 | * Mupen64Plus homepage: https://mupen64plus.org/ * |
4 | * Copyright (C) 2016 Bobby Smiles * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | /** |
23 | * This file is to be compiled with the same compilation flags as the |
24 | * mupen64plus-core, but without LTO / Global Optimizations |
25 | * (those tends to inhibit effective creation of required symbols). |
26 | * It's purpose is to help generate asm_defines headers |
27 | * suitable for inclusion in assembly files. |
28 | * This allow to effectively share struct definitions between C and assembly |
29 | * files. |
30 | */ |
31 | |
32 | #include "device/device.h" |
33 | #include "device/r4300/new_dynarec/new_dynarec.h" |
34 | #include "device/r4300/r4300_core.h" |
35 | |
36 | #include <stddef.h> |
37 | |
38 | #define HEX(n) ((n) >= 10 ? ('a' + ((n) - 10)) : ('0' + (n))) |
39 | |
40 | /* Creates a structure whose bytes form a string like |
41 | * "\n@ASM_DEFINE offsetof_blah_blah 0xdeadbeef\n" |
42 | * |
43 | * This should appear somewhere in the object file, and is distinctive enough |
44 | * that it shouldn't appear by chance. Thus we can pipe the object file |
45 | * directly to awk, and extract the values without having to use |
46 | * platform-specific tools (e.g. objdump, dumpbin, nm). |
47 | */ |
48 | #define _DEFINE(str, sym, val) \ |
49 | const struct { \ |
50 | char before[sizeof(str)-1]; \ |
51 | char hexval[8]; \ |
52 | char after; \ |
53 | char ensure_32bit[(val) > UINT64_C(0xffffffff) ? -1 : 1]; \ |
54 | } sym = { \ |
55 | str, \ |
56 | { \ |
57 | HEX(((val) >> 28) & 0xf), \ |
58 | HEX(((val) >> 24) & 0xf), \ |
59 | HEX(((val) >> 20) & 0xf), \ |
60 | HEX(((val) >> 16) & 0xf), \ |
61 | HEX(((val) >> 12) & 0xf), \ |
62 | HEX(((val) >> 8) & 0xf), \ |
63 | HEX(((val) >> 4) & 0xf), \ |
64 | HEX(((val) >> 0) & 0xf) \ |
65 | }, \ |
66 | '\n', \ |
67 | {0} \ |
68 | } |
69 | |
70 | /* Export member m of structure s. |
71 | * Suitable parsing of corresponding object file (with strings) can be used to |
72 | * generate header suitable for inclusion in assembly files. |
73 | */ |
74 | #define DEFINE(s, m) \ |
75 | _DEFINE("\n@ASM_DEFINE offsetof_struct_" #s "_" #m " 0x", \ |
76 | __offsetof_struct_##s##_##m, \ |
77 | offsetof(struct s, m)) |
78 | |
79 | |
80 | /* Structure members definitions */ |
81 | DEFINE(device, r4300); |
82 | |
83 | #ifndef NEW_DYNAREC |
84 | /* New dynarec uses a different memory layout */ |
85 | DEFINE(r4300_core, regs); |
86 | DEFINE(r4300_core, hi); |
87 | DEFINE(r4300_core, lo); |
88 | |
89 | DEFINE(r4300_core, stop); |
90 | #endif |
91 | |
92 | #if !defined(NEW_DYNAREC) |
93 | DEFINE(r4300_core, recomp); |
94 | |
95 | #if defined(__x86_64__) |
96 | DEFINE(recomp, save_rsp); |
97 | DEFINE(recomp, save_rip); |
98 | #else |
99 | DEFINE(recomp, save_ebp); |
100 | DEFINE(recomp, save_esp); |
101 | DEFINE(recomp, save_ebx); |
102 | DEFINE(recomp, save_esi); |
103 | DEFINE(recomp, save_edi); |
104 | DEFINE(recomp, save_eip); |
105 | #endif |
106 | DEFINE(recomp, return_address); |
107 | #endif /* !NEW_DYNAREC */ |
108 | |
109 | DEFINE(r4300_core, cp0); |
110 | #ifndef NEW_DYNAREC |
111 | /* New dynarec uses a different memory layout */ |
112 | DEFINE(cp0, regs); |
113 | DEFINE(cp0, next_interrupt); |
114 | #endif |
115 | DEFINE(cp0, last_addr); |
116 | DEFINE(cp0, count_per_op); |
117 | DEFINE(cp0, tlb); |
118 | |
119 | DEFINE(tlb, entries); |
120 | DEFINE(tlb, LUT_r); |
121 | DEFINE(tlb, LUT_w); |
122 | |
123 | DEFINE(r4300_core, cached_interp); |
124 | DEFINE(cached_interp, invalid_code); |
125 | |
126 | #ifdef NEW_DYNAREC |
127 | DEFINE(r4300_core, new_dynarec_hot_state); |
128 | DEFINE(r4300_core, extra_memory); |
129 | DEFINE(new_dynarec_hot_state, dynarec_local); |
130 | DEFINE(new_dynarec_hot_state, next_interrupt); |
131 | DEFINE(new_dynarec_hot_state, cycle_count); |
132 | DEFINE(new_dynarec_hot_state, pending_exception); |
133 | DEFINE(new_dynarec_hot_state, pcaddr); |
134 | DEFINE(new_dynarec_hot_state, stop); |
135 | DEFINE(new_dynarec_hot_state, invc_ptr); |
136 | DEFINE(new_dynarec_hot_state, fcr0); |
137 | DEFINE(new_dynarec_hot_state, fcr31); |
138 | DEFINE(new_dynarec_hot_state, regs); |
139 | DEFINE(new_dynarec_hot_state, hi); |
140 | DEFINE(new_dynarec_hot_state, lo); |
141 | DEFINE(new_dynarec_hot_state, cp0_regs); |
142 | DEFINE(new_dynarec_hot_state, cp1_regs_simple); |
143 | DEFINE(new_dynarec_hot_state, cp1_regs_double); |
144 | DEFINE(new_dynarec_hot_state, rounding_modes); |
145 | DEFINE(new_dynarec_hot_state, branch_target); |
146 | DEFINE(new_dynarec_hot_state, pc); |
147 | DEFINE(new_dynarec_hot_state, fake_pc); |
148 | DEFINE(new_dynarec_hot_state, rs); |
149 | DEFINE(new_dynarec_hot_state, rt); |
150 | DEFINE(new_dynarec_hot_state, rd); |
151 | DEFINE(new_dynarec_hot_state, mini_ht); |
152 | DEFINE(new_dynarec_hot_state, restore_candidate); |
153 | DEFINE(new_dynarec_hot_state, memory_map); |
154 | #endif |
155 | |