authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-11 20:27:38+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-14 22:18:06+07:00
logdcb12a7941371cee3b62cc3215d89c1f96577372
treea559c12bda0e647adb623de4c628f2c8cd560bff
parent1467590e402b5b198ce7c81540263a8e08329e3c

stage2: sparcv9: Use regular structs to encode instructions

Currently packed structs still has endian-dependent behavior, so it results in code that is not portable across platforms (see also issue 10113).

3 files changed, 60 insertions(+), 54 deletions(-)

src/arch/sparcv9/Emit.zig+1-1
......@@ -290,7 +290,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
290290
291291fn writeInstruction(emit: *Emit, instruction: Instruction) !void {
292292 // SPARCv9 instructions are always arranged in BE regardless of the
293 // endianness mode the CPU is running in.
293 // endianness mode the CPU is running in (Section 3.1 of the ISA specification).
294294 // This is to ease porting in case someone wants to do a LE SPARCv9 backend.
295295 const endian = Endian.Big;
296296
src/arch/sparcv9/Mir.zig+1-1
......@@ -62,7 +62,7 @@ pub const Inst = struct {
6262
6363 /// A.27 Load Integer
6464 /// Those uses the arithmetic_3op field.
65 /// Note that the ldd variant of this instruction is deprecated, do not emit
65 /// Note that the ldd variant of this instruction is deprecated, so do not emit
6666 /// it unless specifically requested (e.g. by inline assembly).
6767 // TODO add other operations.
6868 ldub,
src/arch/sparcv9/bits.zig+58-52
......@@ -164,27 +164,33 @@ pub const Instruction = union(enum) {
164164 // name them with letters since there's no official naming scheme.
165165 // TODO: need to rename the minor formats to a more descriptive name.
166166
167 // I am using regular structs instead of packed ones to avoid
168 // endianness-dependent behavior when constructing the actual
169 // assembly instructions.
170 // See also: https://github.com/ziglang/zig/issues/10113
171 // TODO: change it back to packed structs once the issue is resolved.
172
167173 // Format 1 (op = 1): CALL
168 format_1: packed struct {
174 format_1: struct {
169175 op: u2 = 0b01,
170176 disp30: u30,
171177 },
172178
173179 // Format 2 (op = 0): SETHI & Branches (Bicc, BPcc, BPr, FBfcc, FBPfcc)
174 format_2a: packed struct {
180 format_2a: struct {
175181 op: u2 = 0b00,
176182 rd: u5,
177183 op2: u3,
178184 imm22: u22,
179185 },
180 format_2b: packed struct {
186 format_2b: struct {
181187 op: u2 = 0b00,
182188 a: u1,
183189 cond: u4,
184190 op2: u3,
185191 disp22: u22,
186192 },
187 format_2c: packed struct {
193 format_2c: struct {
188194 op: u2 = 0b00,
189195 a: u1,
190196 cond: u4,
......@@ -194,7 +200,7 @@ pub const Instruction = union(enum) {
194200 p: u1,
195201 disp19: u19,
196202 },
197 format_2d: packed struct {
203 format_2d: struct {
198204 op: u2 = 0b00,
199205 a: u1,
200206 fixed: u1 = 0b0,
......@@ -207,7 +213,7 @@ pub const Instruction = union(enum) {
207213 },
208214
209215 // Format 3 (op = 2 or 3): Arithmetic, Logical, MOVr, MEMBAR, Load, and Store
210 format_3a: packed struct {
216 format_3a: struct {
211217 op: u2,
212218 rd: u5,
213219 op3: u6,
......@@ -224,7 +230,7 @@ pub const Instruction = union(enum) {
224230 i: u1 = 0b1,
225231 simm13: u13,
226232 },
227 format_3c: packed struct {
233 format_3c: struct {
228234 op: u2,
229235 reserved1: u5 = 0b00000,
230236 op3: u6,
......@@ -241,7 +247,7 @@ pub const Instruction = union(enum) {
241247 i: u1 = 0b1,
242248 simm13: u13,
243249 },
244 format_3e: packed struct {
250 format_3e: struct {
245251 op: u2,
246252 rd: u5,
247253 op3: u6,
......@@ -260,7 +266,7 @@ pub const Instruction = union(enum) {
260266 rcond: u3,
261267 simm10: u10,
262268 },
263 format_3g: packed struct {
269 format_3g: struct {
264270 op: u2,
265271 rd: u5,
266272 op3: u6,
......@@ -269,7 +275,7 @@ pub const Instruction = union(enum) {
269275 reserved: u8 = 0b00000000,
270276 rs2: u5,
271277 },
272 format_3h: packed struct {
278 format_3h: struct {
273279 op: u2 = 0b10,
274280 fixed1: u5 = 0b00000,
275281 op3: u6 = 0b101000,
......@@ -279,7 +285,7 @@ pub const Instruction = union(enum) {
279285 cmask: u3,
280286 mmask: u4,
281287 },
282 format_3i: packed struct {
288 format_3i: struct {
283289 op: u2,
284290 rd: u5,
285291 op3: u6,
......@@ -288,13 +294,13 @@ pub const Instruction = union(enum) {
288294 imm_asi: u8,
289295 rs2: u5,
290296 },
291 format_3j: packed struct {
297 format_3j: struct {
292298 op: u2,
293299 impl_dep1: u5,
294300 op3: u6,
295301 impl_dep2: u19,
296302 },
297 format_3k: packed struct {
303 format_3k: struct {
298304 op: u2,
299305 rd: u5,
300306 op3: u6,
......@@ -304,7 +310,7 @@ pub const Instruction = union(enum) {
304310 reserved: u7 = 0b0000000,
305311 rs2: u5,
306312 },
307 format_3l: packed struct {
313 format_3l: struct {
308314 op: u2,
309315 rd: u5,
310316 op3: u6,
......@@ -314,7 +320,7 @@ pub const Instruction = union(enum) {
314320 reserved: u7 = 0b0000000,
315321 shcnt32: u5,
316322 },
317 format_3m: packed struct {
323 format_3m: struct {
318324 op: u2,
319325 rd: u5,
320326 op3: u6,
......@@ -324,7 +330,7 @@ pub const Instruction = union(enum) {
324330 reserved: u6 = 0b000000,
325331 shcnt64: u6,
326332 },
327 format_3n: packed struct {
333 format_3n: struct {
328334 op: u2,
329335 rd: u5,
330336 op3: u6,
......@@ -332,7 +338,7 @@ pub const Instruction = union(enum) {
332338 opf: u9,
333339 rs2: u5,
334340 },
335 format_3o: packed struct {
341 format_3o: struct {
336342 op: u2,
337343 fixed: u3 = 0b000,
338344 cc1: u1,
......@@ -342,7 +348,7 @@ pub const Instruction = union(enum) {
342348 opf: u9,
343349 rs2: u5,
344350 },
345 format_3p: packed struct {
351 format_3p: struct {
346352 op: u2,
347353 rd: u5,
348354 op3: u6,
......@@ -350,20 +356,20 @@ pub const Instruction = union(enum) {
350356 opf: u9,
351357 rs2: u5,
352358 },
353 format_3q: packed struct {
359 format_3q: struct {
354360 op: u2,
355361 rd: u5,
356362 op3: u6,
357363 rs1: u5,
358364 reserved: u14 = 0b00000000000000,
359365 },
360 format_3r: packed struct {
366 format_3r: struct {
361367 op: u2,
362368 fcn: u5,
363369 op3: u6,
364370 reserved: u19 = 0b0000000000000000000,
365371 },
366 format_3s: packed struct {
372 format_3s: struct {
367373 op: u2,
368374 rd: u5,
369375 op3: u6,
......@@ -371,7 +377,7 @@ pub const Instruction = union(enum) {
371377 },
372378
373379 //Format 4 (op = 2): MOVcc, FMOVr, FMOVcc, and Tcc
374 format_4a: packed struct {
380 format_4a: struct {
375381 op: u2 = 0b10,
376382 rd: u5,
377383 op3: u6,
......@@ -392,7 +398,7 @@ pub const Instruction = union(enum) {
392398 cc0: u1,
393399 simm11: u11,
394400 },
395 format_4c: packed struct {
401 format_4c: struct {
396402 op: u2 = 0b10,
397403 rd: u5,
398404 op3: u6,
......@@ -415,7 +421,7 @@ pub const Instruction = union(enum) {
415421 cc0: u1,
416422 simm11: u11,
417423 },
418 format_4e: packed struct {
424 format_4e: struct {
419425 op: u2 = 0b10,
420426 rd: u5,
421427 op3: u6,
......@@ -426,7 +432,7 @@ pub const Instruction = union(enum) {
426432 reserved: u4 = 0b0000,
427433 sw_trap: u7,
428434 },
429 format_4f: packed struct {
435 format_4f: struct {
430436 op: u2 = 0b10,
431437 rd: u5,
432438 op3: u6,
......@@ -436,7 +442,7 @@ pub const Instruction = union(enum) {
436442 opf_low: u5,
437443 rs2: u5,
438444 },
439 format_4g: packed struct {
445 format_4g: struct {
440446 op: u2 = 0b10,
441447 rd: u5,
442448 op3: u6,
......@@ -512,37 +518,37 @@ pub const Instruction = union(enum) {
512518 pub fn toU32(self: Instruction) u32 {
513519 // TODO: Remove this once packed structs work.
514520 return switch (self) {
515 .format_1 => |v| @bitCast(u32, v),
516 .format_2a => |v| @bitCast(u32, v),
517 .format_2b => |v| @bitCast(u32, v),
518 .format_2c => |v| @bitCast(u32, v),
519 .format_2d => |v| @bitCast(u32, v),
520 .format_3a => |v| @bitCast(u32, v),
521 .format_1 => |v| (@as(u32, v.op) << 30) | @as(u32, v.disp30),
522 .format_2a => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op2) << 22) | @as(u32, v.imm22),
523 .format_2b => |v| (@as(u32, v.op) << 30) | (@as(u32, v.a) << 29) | (@as(u32, v.cond) << 25) | (@as(u32, v.op2) << 22) | @as(u32, v.disp22),
524 .format_2c => |v| (@as(u32, v.op) << 30) | (@as(u32, v.a) << 29) | (@as(u32, v.cond) << 25) | (@as(u32, v.op2) << 22) | (@as(u32, v.cc1) << 21) | (@as(u32, v.cc0) << 20) | (@as(u32, v.p) << 19) | @as(u32, v.disp19),
525 .format_2d => |v| (@as(u32, v.op) << 30) | (@as(u32, v.a) << 29) | (@as(u32, v.fixed) << 28) | (@as(u32, v.rcond) << 25) | (@as(u32, v.op2) << 22) | (@as(u32, v.d16hi) << 20) | (@as(u32, v.p) << 19) | (@as(u32, v.rs1) << 14) | @as(u32, v.d16lo),
526 .format_3a => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.reserved) << 5) | @as(u32, v.rs2),
521527 .format_3b => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | @as(u32, v.simm13),
522 .format_3c => |v| @bitCast(u32, v),
528 .format_3c => |v| (@as(u32, v.op) << 30) | (@as(u32, v.reserved1) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.reserved2) << 5) | @as(u32, v.rs2),
523529 .format_3d => |v| (@as(u32, v.op) << 30) | (@as(u32, v.reserved) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | @as(u32, v.simm13),
524 .format_3e => |v| @bitCast(u32, v),
530 .format_3e => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.rcond) << 10) | (@as(u32, v.reserved) << 5) | @as(u32, v.rs2),
525531 .format_3f => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.rcond) << 10) | @as(u32, v.simm10),
526 .format_3g => |v| @bitCast(u32, v),
527 .format_3h => |v| @bitCast(u32, v),
528 .format_3i => |v| @bitCast(u32, v),
529 .format_3j => |v| @bitCast(u32, v),
530 .format_3k => |v| @bitCast(u32, v),
531 .format_3l => |v| @bitCast(u32, v),
532 .format_3m => |v| @bitCast(u32, v),
533 .format_3n => |v| @bitCast(u32, v),
534 .format_3o => |v| @bitCast(u32, v),
535 .format_3p => |v| @bitCast(u32, v),
536 .format_3q => |v| @bitCast(u32, v),
537 .format_3r => |v| @bitCast(u32, v),
538 .format_3s => |v| @bitCast(u32, v),
539 .format_4a => |v| @bitCast(u32, v),
532 .format_3g => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.reserved) << 5) | @as(u32, v.rs2),
533 .format_3h => |v| (@as(u32, v.op) << 30) | (@as(u32, v.fixed1) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.fixed2) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.reserved) << 7) | (@as(u32, v.cmask) << 4) | @as(u32, v.mmask),
534 .format_3i => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.imm_asi) << 5) | @as(u32, v.rs2),
535 .format_3j => |v| (@as(u32, v.op) << 30) | (@as(u32, v.impl_dep1) << 25) | (@as(u32, v.op3) << 19) | @as(u32, v.impl_dep2),
536 .format_3k => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.x) << 12) | (@as(u32, v.reserved) << 5) | @as(u32, v.rs2),
537 .format_3l => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.x) << 12) | (@as(u32, v.reserved) << 5) | @as(u32, v.shcnt32),
538 .format_3m => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.x) << 12) | (@as(u32, v.reserved) << 6) | @as(u32, v.shcnt64),
539 .format_3n => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.reserved) << 14) | (@as(u32, v.opf) << 5) | @as(u32, v.rs2),
540 .format_3o => |v| (@as(u32, v.op) << 30) | (@as(u32, v.fixed) << 27) | (@as(u32, v.cc1) << 26) | (@as(u32, v.cc0) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.opf) << 5) | @as(u32, v.rs2),
541 .format_3p => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.opf) << 5) | @as(u32, v.rs2),
542 .format_3q => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | @as(u32, v.reserved),
543 .format_3r => |v| (@as(u32, v.op) << 30) | (@as(u32, v.fcn) << 25) | (@as(u32, v.op3) << 19) | @as(u32, v.reserved),
544 .format_3s => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | @as(u32, v.reserved),
545 .format_4a => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | (@as(u32, v.reserved) << 5) | @as(u32, v.rs2),
540546 .format_4b => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | @as(u32, v.simm11),
541 .format_4c => |v| @bitCast(u32, v),
547 .format_4c => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.cc2) << 18) | (@as(u32, v.cond) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | (@as(u32, v.reserved) << 5) | @as(u32, v.rs2),
542548 .format_4d => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.cc2) << 18) | (@as(u32, v.cond) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | @as(u32, v.simm11),
543 .format_4e => |v| @bitCast(u32, v),
544 .format_4f => |v| @bitCast(u32, v),
545 .format_4g => |v| @bitCast(u32, v),
549 .format_4e => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | (@as(u32, v.reserved) << 7) | @as(u32, v.sw_trap),
550 .format_4f => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.fixed) << 13) | (@as(u32, v.rcond) << 10) | (@as(u32, v.opf_low) << 5) | @as(u32, v.rs2),
551 .format_4g => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.fixed) << 18) | (@as(u32, v.cond) << 14) | (@as(u32, v.opf_cc) << 11) | (@as(u32, v.opf_low) << 5) | @as(u32, v.rs2),
546552 };
547553 }
548554