Telkin
Loading...
Searching...
No Matches
Assembly.h
Go to the documentation of this file.
1#pragma once
2
3#include <telkin/Preprocessor.h>
4#include <cafe.h>
5
6// thx to mkwcat/nsmbw-project for some of these
7
8#ifdef TELKIN_NO_REGISTERS
9 #define TELKIN_REGISTERS_WARNING()
10#else
11 #define TELKIN_REGISTERS_WARNING() _Pragma("message \"WARNING: TELKIN_REGISTERS was not defined. It is recommended to globally define TELKIN_NO_REGISTERS if this was intentional\"")
12#endif
13
14#ifdef TELKIN_REGISTERS
15 #define tAssembly(...) __attribute__((naked)) __attribute__((__noinline__)) { __asm__ volatile (PP_STR_VAL(__VA_ARGS__)); }
16#else
17 #define tAssembly(...)
19 __attribute__((naked)) __attribute__((__noinline__)) { __asm__ volatile (PP_STR_VAL(__VA_ARGS__)); }
20#endif
21
22#ifdef __clangd__
23 #define tRegSave __attribute__(())
24#else
25 #define tRegSave __attribute__((preserve_all)) // red hills compiler magic for ppc
26#endif
27
28namespace tk::ppc {
29
30 enum class GPR : u8 {
31 r0, r1, r2, r3, r4,
32 r5, r6, r7, r8, r9,
38
40 };
41
42 enum class FPR : u8 {
43 f0, f1, f2, f3, f4,
44 f5, f6, f7, f8, f9,
50 };
51
52 enum class CR : u8 {
54 };
55
56 using R = GPR;
57
58 namespace internal {
59 // I-form: [ op:6 | LI:24 | AA:1 | LK:1 ]
60 consteval u32 I_form(u8 op, s32 li, bool aa, bool lk) {
61 return (u32(op) << 26)
62 | (u32(li & 0xFF'FF'FF) << 2)
63 | (u32(aa) << 1)
64 | u32(lk);
65 }
66
67 // B-form: [ op:6 | BO:5 | BI:5 | BD:14 | AA:1 | LK:1 ]
68 consteval u32 B_form(u8 op, u8 bo, u8 bi, s16 bd, bool aa, bool lk) {
69 return (u32(op) << 26)
70 | (u32(bo & 0x1F) << 21)
71 | (u32(bi & 0x1F) << 16)
72 | (u32(bd & 0x3FFF) << 2)
73 | (u32(aa) << 1)
74 | u32(lk);
75 }
76
77 // D-form: [ op:6 | RT/RS:5 | RA:5 | D:16 ]
78 consteval u32 D_form(u8 op, u8 rsd, u8 ra, s16 d) {
79 return (u32(op) << 26)
80 | (u32(rsd & 0x1F) << 21)
81 | (u32(ra & 0x1F) << 16)
82 | u16(d);
83 }
84
85 // X-form: [ op:6 | RT/RS:5 | RA:5 | RB:5 | XO:10 | Rc:1 ]
86 consteval u32 X_form(u8 op, u8 rsd, u8 ra, u8 rb, u16 xo, bool rc) {
87 return (u32(op) << 26)
88 | (u32(rsd & 0x1F) << 21)
89 | (u32(ra & 0x1F) << 16)
90 | (u32(rb & 0x1F) << 11)
91 | (u32(xo & 0x3FF) << 1)
92 | u32(rc);
93 }
94
95 // XO-form: [ op:6 | RT:5 | RA:5 | RB:5 | OE:1 | XO:9 | Rc:1 ]
96 consteval u32 XO_form(u8 op, u8 rt, u8 ra, u8 rb, bool oe, u16 xo, bool rc) {
97 return (u32(op) << 26)
98 | (u32(rt & 0x1F) << 21)
99 | (u32(ra & 0x1F) << 16)
100 | (u32(rb & 0x1F) << 11)
101 | (u32(oe) << 10)
102 | (u32(xo & 0x1FF) << 1)
103 | u32(rc);
104 }
105
106 // A-form: [ op:6 | FRT:5 | FRA:5 | FRB:5 | FRC:5 | XO:5 | Rc:1 ]
107 consteval u32 A_form(u8 op, u8 frt, u8 fra, u8 frb, u8 frc, u8 xo, bool rc) {
108 return (u32(op) << 26)
109 | (u32(frt & 0x1F) << 21)
110 | (u32(fra & 0x1F) << 16)
111 | (u32(frb & 0x1F) << 11)
112 | (u32(frc & 0x1F) << 6)
113 | (u32(xo & 0x1F) << 1)
114 | u32(rc);
115 }
116
117 // M-form: [ op:6 | RS:5 | RA:5 | SH:5 | MB:5 | ME:5 | Rc:1 ]
118 consteval u32 M_form(u8 op, u8 rs, u8 ra, u8 sh, u8 mb, u8 me, bool rc) {
119 return (u32(op) << 26)
120 | (u32(rs & 0x1F) << 21)
121 | (u32(ra & 0x1F) << 16)
122 | (u32(sh & 0x1F) << 11)
123 | (u32(mb & 0x1F) << 6)
124 | (u32(me & 0x1F) << 1)
125 | u32(rc);
126 }
127
128 consteval u8 cr_field(CR cr) { return u8(cr) << 2; }
129 }
130
131 // Instructions:
132
133 consteval u32 addi(R rt, R ra, s16 si) { return internal::D_form(14, u8(rt), u8(ra), si); }
134 consteval u32 addis(R rt, R ra, s16 si) { return internal::D_form(15, u8(rt), u8(ra), si); }
135 consteval u32 add(R rt, R ra, R rb, bool rc = false) { return internal::XO_form(31, u8(rt), u8(ra), u8(rb), false, 266, rc); }
136 consteval u32 mullw(R rt, R ra, R rb, bool rc = false) { return internal::XO_form(31, u8(rt), u8(ra), u8(rb), false, 235, rc); }
137
138 consteval u32 lwz(R rt, R ra, s16 d) { return internal::D_form(32, u8(rt), u8(ra), d); }
139 consteval u32 stw(R rs, R ra, s16 d) { return internal::D_form(36, u8(rs), u8(ra), d); }
140 consteval u32 stwu(R rs, R ra, s16 d) { return internal::D_form(37, u8(rs), u8(ra), d); }
141 consteval u32 lbz(R rt, R ra, s16 d) { return internal::D_form(34, u8(rt), u8(ra), d); }
142 consteval u32 stb(R rs, R ra, s16 d) { return internal::D_form(38, u8(rs), u8(ra), d); }
143
144 consteval u32 ori(R ra, R rs, u16 ui) { return internal::D_form(24, u8(rs), u8(ra), s16(ui)); }
145 consteval u32 oris(R ra, R rs, u16 ui) { return internal::D_form(25, u8(rs), u8(ra), s16(ui)); }
146 consteval u32 xori(R ra, R rs, u16 ui) { return internal::D_form(26, u8(rs), u8(ra), s16(ui)); }
147 consteval u32 andi(R ra, R rs, u16 ui) { return internal::D_form(28, u8(rs), u8(ra), s16(ui)); }
148
149 consteval u32 andr(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 28, rc); }
150 consteval u32 orr(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 444, rc); }
151 consteval u32 xorr(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 316, rc); }
152 consteval u32 norr(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 124, rc); }
153
154 consteval u32 mr(R ra, R rb) { return orr(ra, rb, rb); }
155
156 consteval u32 cmpw(R ra, R rb, CR cr = CR::cr0) { return internal::X_form(31, internal::cr_field(cr), u8(ra), u8(rb), 0, false); }
157 consteval u32 cmpwi(R ra, s16 simm, CR cr = CR::cr0) { return internal::D_form(11, internal::cr_field(cr), u8(ra), simm); }
158 consteval u32 cmplw(R ra, R rb, CR cr = CR::cr0) { return internal::X_form(31, internal::cr_field(cr), u8(ra), u8(rb), 32, false); }
159 consteval u32 cmplwi(R ra, u16 uimm, CR cr = CR::cr0) { return internal::D_form(10, internal::cr_field(cr), u8(ra), s16(uimm)); }
160
161 consteval u32 li(R rt, s16 si) { return addi(rt, R::r0, si); }
162 consteval u32 lis(R rt, s16 si) { return addis(rt, R::r0, si); }
163
164 consteval u32 bc(u8 bo, u8 bi, s16 byte_offset) { return internal::B_form(16, bo, bi, byte_offset >> 2, false, false); }
165 consteval u32 blt(s16 offset) { return bc(12, 0, offset); }
166 consteval u32 bgt(s16 offset) { return bc(12, 1, offset); }
167 consteval u32 beq(s16 offset) { return bc(12, 2, offset); }
168 consteval u32 bne(s16 offset) { return bc( 4, 2, offset); }
169
170 consteval u32 rlwinm(R ra, R rs, u8 sh, u8 mb, u8 me, bool rc = false) { return internal::M_form(21, u8(rs), u8(ra), sh, mb, me, rc); }
171
172 consteval u32 slw(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 24, rc); }
173 consteval u32 srw(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 536, rc); }
174 consteval u32 sraw(R ra, R rs, R rb, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), u8(rb), 792, rc); }
175 consteval u32 srawi(R ra, R rs, u8 sh, bool rc=false) { return internal::X_form(31, u8(rs), u8(ra), sh, 824, rc); }
176
177 consteval u32 b(s32 relative) { return internal::I_form(18, relative >> 2, false, false); }
178 consteval u32 bl(s32 relative) { return internal::I_form(18, relative >> 2, false, true); }
179 consteval u32 blr() { return internal::X_form(19, 20, 0, 0, 16, false); }
180 consteval u32 nop() { return ori(R::r0, R::r0, 0); }
181
182 consteval u32 mfspr(R rt, u16 spr) { return internal::X_form(31, u8(rt), spr & 0x1F, (spr >> 5) & 0x1F, 339, false); }
183 consteval u32 mtspr(u16 spr, R rs) { return internal::X_form(31, u8(rs), spr & 0x1F, (spr >> 5) & 0x1F, 467, false); }
184
185 consteval u32 mflr(R rt) { return mfspr(rt, 8); }
186 consteval u32 mtlr(R rs) { return mtspr(8, rs); }
187
188}
189
190#ifdef TELKIN_REGISTERS
191#include <telkin/DefineRegisters.h>
192#endif
193
194// It's recommended to use the tRegSave attribute directly in C++ instead of the below macros
195#define tSaveVolatileRegisters
196 stwu r1, -0x3C(r1);
197 stw r0, 0x08(r1);
198 stw r3, 0x0C(r1);
199 stw r4, 0x10(r1);
200 stw r5, 0x14(r1);
201 stw r6, 0x18(r1);
202 stw r7, 0x1C(r1);
203 stw r8, 0x20(r1);
204 stw r9, 0x24(r1);
205 stw r10, 0x28(r1);
206 stw r11, 0x2C(r1);
207 stw r12, 0x30(r1);
208 mfcr r0;
209 stw r0, 0x34(r1);
210 mfctr r0;
211 stw r0, 0x38(r1);
212 mflr r0;
213 stw r0, 0x40(r1)
214
215#define tRestoreVolatileRegisters
216 lwz r0, 0x38(r1);
217 mtctr r0;
218 lwz r0, 0x34(r1);
219 mtcr r0;
220 lwz r0, 0x40(r1);
221 mtlr r0;
222 lwz r0, 0x08(r1);
223 lwz r3, 0x0C(r1);
224 lwz r4, 0x10(r1);
225 lwz r5, 0x14(r1);
226 lwz r6, 0x18(r1);
227 lwz r7, 0x1C(r1);
228 lwz r8, 0x20(r1);
229 lwz r9, 0x24(r1);
230 lwz r10, 0x28(r1);
231 lwz r11, 0x2C(r1);
232 lwz r12, 0x30(r1);
233 addi r1, r1, 0x3C
234
235#define tSaveLR
236 stwu r1, -0x10(r1);
237 mflr r2;
238 stw r2, 0x14(r1)
239
240#define tRestoreLR
241 lwz r2, 0x14(r1);
242 mtlr r2;
243 addi r1, r1, 0x10
#define TELKIN_REGISTERS_WARNING()
Definition Assembly.h:11
Definition Assembly.h:58
GPR
Definition Assembly.h:30
@ r15
Definition Assembly.h:34
@ r25
Definition Assembly.h:36
@ r13
Definition Assembly.h:33
@ sp
Definition Assembly.h:39
@ r9
Definition Assembly.h:32
@ r14
Definition Assembly.h:33
@ r21
Definition Assembly.h:35
@ r7
Definition Assembly.h:32
@ r4
Definition Assembly.h:31
@ r11
Definition Assembly.h:33
@ r27
Definition Assembly.h:36
@ r18
Definition Assembly.h:34
@ r16
Definition Assembly.h:34
@ r26
Definition Assembly.h:36
@ r1
Definition Assembly.h:31
@ r19
Definition Assembly.h:34
@ r31
Definition Assembly.h:37
@ r8
Definition Assembly.h:32
@ r29
Definition Assembly.h:36
@ r20
Definition Assembly.h:35
@ r3
Definition Assembly.h:31
@ r10
Definition Assembly.h:33
@ r22
Definition Assembly.h:35
@ r24
Definition Assembly.h:35
@ r6
Definition Assembly.h:32
@ r30
Definition Assembly.h:37
@ r0
Definition Assembly.h:31
@ r2
Definition Assembly.h:31
@ r17
Definition Assembly.h:34
@ r12
Definition Assembly.h:33
@ r28
Definition Assembly.h:36
@ r5
Definition Assembly.h:32
@ r23
Definition Assembly.h:35
GPR R
Definition Assembly.h:56
FPR
Definition Assembly.h:42
@ f14
Definition Assembly.h:45
@ f3
Definition Assembly.h:43
@ f22
Definition Assembly.h:47
@ f27
Definition Assembly.h:48
@ f2
Definition Assembly.h:43
@ f20
Definition Assembly.h:47
@ f29
Definition Assembly.h:48
@ f25
Definition Assembly.h:48
@ f8
Definition Assembly.h:44
@ f19
Definition Assembly.h:46
@ f30
Definition Assembly.h:49
@ f6
Definition Assembly.h:44
@ f9
Definition Assembly.h:44
@ f7
Definition Assembly.h:44
@ f4
Definition Assembly.h:43
@ f5
Definition Assembly.h:44
@ f12
Definition Assembly.h:45
@ f10
Definition Assembly.h:45
@ f13
Definition Assembly.h:45
@ f23
Definition Assembly.h:47
@ f28
Definition Assembly.h:48
@ f16
Definition Assembly.h:46
@ f1
Definition Assembly.h:43
@ f0
Definition Assembly.h:43
@ f31
Definition Assembly.h:49
@ f15
Definition Assembly.h:46
@ f18
Definition Assembly.h:46
@ f26
Definition Assembly.h:48
@ f11
Definition Assembly.h:45
@ f21
Definition Assembly.h:47
@ f17
Definition Assembly.h:46
@ f24
Definition Assembly.h:47
CR
Definition Assembly.h:52
@ cr3
Definition Assembly.h:53
@ cr5
Definition Assembly.h:53
@ cr6
Definition Assembly.h:53
@ cr7
Definition Assembly.h:53
@ cr1
Definition Assembly.h:53
@ cr0
Definition Assembly.h:53
@ cr4
Definition Assembly.h:53
@ cr2
Definition Assembly.h:53
Definition Assembly.h:28
u64(*)() getTitleID_t
Definition Mod.h:16