Skip to content

Commit ac936c0

Browse files
Merge pull request #11059 from joachimschmidt557/stage2-aarch64
stage2 AArch64: various improvements
2 parents e297860 + a06e9ec commit ac936c0

30 files changed

+330
-262
lines changed

src/arch/aarch64/CodeGen.zig

Lines changed: 217 additions & 77 deletions
Large diffs are not rendered by default.

src/arch/aarch64/Emit.zig

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ pub fn emitMir(
9595

9696
.call_extern => try emit.mirCallExtern(inst),
9797

98+
.eor_immediate => try emit.mirLogicalImmediate(inst),
99+
98100
.add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
99101
.cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
100102
.sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
@@ -106,7 +108,9 @@ pub fn emitMir(
106108
.dbg_prologue_end => try emit.mirDebugPrologueEnd(),
107109
.dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
108110

111+
.and_shifted_register => try emit.mirLogicalShiftedRegister(inst),
109112
.eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
113+
.orr_shifted_register => try emit.mirLogicalShiftedRegister(inst),
110114

111115
.load_memory_got => try emit.mirLoadMemoryPie(inst),
112116
.load_memory_direct => try emit.mirLoadMemoryPie(inst),
@@ -605,6 +609,21 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
605609
}
606610
}
607611

612+
fn mirLogicalImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
613+
const tag = emit.mir.instructions.items(.tag)[inst];
614+
const rr_bitmask = emit.mir.instructions.items(.data)[inst].rr_bitmask;
615+
const rd = rr_bitmask.rd;
616+
const rn = rr_bitmask.rn;
617+
const imms = rr_bitmask.imms;
618+
const immr = rr_bitmask.immr;
619+
const n = rr_bitmask.n;
620+
621+
switch (tag) {
622+
.eor_immediate => try emit.writeInstruction(Instruction.eorImmediate(rd, rn, imms, immr, n)),
623+
else => unreachable,
624+
}
625+
}
626+
608627
fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
609628
const tag = emit.mir.instructions.items(.tag)[inst];
610629
const rrr_imm6_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_shift;
@@ -643,7 +662,9 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
643662
const imm6 = rrr_imm6_logical_shift.imm6;
644663

645664
switch (tag) {
646-
.eor_shifted_register => try emit.writeInstruction(Instruction.eor(rd, rn, rm, shift, imm6)),
665+
.and_shifted_register => try emit.writeInstruction(Instruction.andShiftedRegister(rd, rn, rm, shift, imm6)),
666+
.eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)),
667+
.orr_shifted_register => try emit.writeInstruction(Instruction.orrShiftedRegister(rd, rn, rm, shift, imm6)),
647668
else => unreachable,
648669
}
649670
}
@@ -844,15 +865,15 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
844865
switch (tag) {
845866
.mov_register => {
846867
const rr = emit.mir.instructions.items(.data)[inst].rr;
847-
try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, .lsl, 0));
868+
try emit.writeInstruction(Instruction.orrShiftedRegister(rr.rd, .xzr, rr.rn, .lsl, 0));
848869
},
849870
.mov_to_from_sp => {
850871
const rr = emit.mir.instructions.items(.data)[inst].rr;
851872
try emit.writeInstruction(Instruction.add(rr.rd, rr.rn, 0, false));
852873
},
853874
.mvn => {
854875
const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift;
855-
try emit.writeInstruction(Instruction.orn(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, .lsl, 0));
876+
try emit.writeInstruction(Instruction.ornShiftedRegister(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, rr_imm6_shift.shift, rr_imm6_shift.imm6));
856877
},
857878
else => unreachable,
858879
}

src/arch/aarch64/Mir.zig

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub const Inst = struct {
2828
add_immediate,
2929
/// Add (shifted register)
3030
add_shifted_register,
31+
/// Bitwise AND (shifted register)
32+
and_shifted_register,
3133
/// Branch conditionally
3234
b_cond,
3335
/// Branch
@@ -54,6 +56,8 @@ pub const Inst = struct {
5456
dbg_epilogue_begin,
5557
/// Pseudo-instruction: Update debug line
5658
dbg_line,
59+
/// Bitwise Exclusive OR (immediate)
60+
eor_immediate,
5761
/// Bitwise Exclusive OR (shifted register)
5862
eor_shifted_register,
5963
/// Loads the contents into a register
@@ -106,6 +110,8 @@ pub const Inst = struct {
106110
mvn,
107111
/// No Operation
108112
nop,
113+
/// Bitwise inclusive OR (shifted register)
114+
orr_shifted_register,
109115
/// Pseudo-instruction: Pop multiple registers
110116
pop_regs,
111117
/// Psuedo-instruction: Push multiple registers
@@ -231,14 +237,25 @@ pub const Inst = struct {
231237
imm12: u12,
232238
sh: u1 = 0,
233239
},
234-
/// Two registers and a shift (shift type and 6-bit amount)
240+
/// Two registers and a shift (logical instruction version)
241+
/// (shift type and 6-bit amount)
235242
///
236243
/// Used by e.g. mvn
237244
rr_imm6_shift: struct {
238245
rd: Register,
239246
rm: Register,
240247
imm6: u6,
241-
shift: bits.Instruction.AddSubtractShiftedRegisterShift,
248+
shift: bits.Instruction.LogicalShiftedRegisterShift,
249+
},
250+
/// Two registers and a bitmask immediate
251+
///
252+
/// Used by e.g. eor_immediate
253+
rr_bitmask: struct {
254+
rd: Register,
255+
rn: Register,
256+
imms: u6,
257+
immr: u6,
258+
n: u1,
242259
},
243260
/// Two registers
244261
///

src/arch/aarch64/bits.zig

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,16 @@ pub const Instruction = union(enum) {
323323
op: u1,
324324
sf: u1,
325325
},
326+
logical_immediate: packed struct {
327+
rd: u5,
328+
rn: u5,
329+
imms: u6,
330+
immr: u6,
331+
n: u1,
332+
fixed: u6 = 0b100100,
333+
opc: u2,
334+
sf: u1,
335+
},
326336
add_subtract_shifted_register: packed struct {
327337
rd: u5,
328338
rn: u5,
@@ -487,6 +497,7 @@ pub const Instruction = union(enum) {
487497
.no_operation => |v| @bitCast(u32, v),
488498
.logical_shifted_register => |v| @bitCast(u32, v),
489499
.add_subtract_immediate => |v| @bitCast(u32, v),
500+
.logical_immediate => |v| @bitCast(u32, v),
490501
.add_subtract_shifted_register => |v| @bitCast(u32, v),
491502
// TODO once packed structs work, this can be refactored
492503
.conditional_branch => |v| @as(u32, v.cond) | (@as(u32, v.o0) << 4) | (@as(u32, v.imm19) << 5) | (@as(u32, v.o1) << 24) | (@as(u32, v.fixed) << 25),
@@ -900,6 +911,31 @@ pub const Instruction = union(enum) {
900911
};
901912
}
902913

914+
fn logicalImmediate(
915+
opc: u2,
916+
rd: Register,
917+
rn: Register,
918+
imms: u6,
919+
immr: u6,
920+
n: u1,
921+
) Instruction {
922+
return Instruction{
923+
.logical_immediate = .{
924+
.rd = rd.enc(),
925+
.rn = rn.enc(),
926+
.imms = imms,
927+
.immr = immr,
928+
.n = n,
929+
.opc = opc,
930+
.sf = switch (rd.size()) {
931+
32 => 0b0,
932+
64 => 0b1,
933+
else => unreachable, // unexpected register size
934+
},
935+
},
936+
};
937+
}
938+
903939
pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ };
904940

905941
fn addSubtractShiftedRegister(
@@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) {
11731209

11741210
// Logical (shifted register)
11751211

1176-
pub fn @"and"(
1212+
pub fn andShiftedRegister(
11771213
rd: Register,
11781214
rn: Register,
11791215
rm: Register,
@@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) {
11831219
return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount);
11841220
}
11851221

1186-
pub fn bic(
1222+
pub fn bicShiftedRegister(
11871223
rd: Register,
11881224
rn: Register,
11891225
rm: Register,
@@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) {
11931229
return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount);
11941230
}
11951231

1196-
pub fn orr(
1232+
pub fn orrShiftedRegister(
11971233
rd: Register,
11981234
rn: Register,
11991235
rm: Register,
@@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) {
12031239
return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount);
12041240
}
12051241

1206-
pub fn orn(
1242+
pub fn ornShiftedRegister(
12071243
rd: Register,
12081244
rn: Register,
12091245
rm: Register,
@@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) {
12131249
return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount);
12141250
}
12151251

1216-
pub fn eor(
1252+
pub fn eorShiftedRegister(
12171253
rd: Register,
12181254
rn: Register,
12191255
rm: Register,
@@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) {
12231259
return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount);
12241260
}
12251261

1226-
pub fn eon(
1262+
pub fn eonShiftedRegister(
12271263
rd: Register,
12281264
rn: Register,
12291265
rm: Register,
@@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) {
12331269
return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount);
12341270
}
12351271

1236-
pub fn ands(
1272+
pub fn andsShiftedRegister(
12371273
rd: Register,
12381274
rn: Register,
12391275
rm: Register,
@@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) {
12431279
return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount);
12441280
}
12451281

1246-
pub fn bics(
1282+
pub fn bicsShiftedRegister(
12471283
rd: Register,
12481284
rn: Register,
12491285
rm: Register,
@@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) {
12711307
return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift);
12721308
}
12731309

1310+
// Logical (immediate)
1311+
1312+
pub fn andImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1313+
return logicalImmediate(0b00, rd, rn, imms, immr, n);
1314+
}
1315+
1316+
pub fn orrImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1317+
return logicalImmediate(0b01, rd, rn, imms, immr, n);
1318+
}
1319+
1320+
pub fn eorImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1321+
return logicalImmediate(0b10, rd, rn, imms, immr, n);
1322+
}
1323+
1324+
pub fn andsImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1325+
return logicalImmediate(0b11, rd, rn, imms, immr, n);
1326+
}
1327+
12741328
// Add/subtract (shifted register)
12751329

12761330
pub fn addShiftedRegister(
@@ -1378,11 +1432,11 @@ test "serialize instructions" {
13781432

13791433
const testcases = [_]Testcase{
13801434
.{ // orr x0, xzr, x1
1381-
.inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0),
1435+
.inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0),
13821436
.expected = 0b1_01_01010_00_0_00001_000000_11111_00000,
13831437
},
13841438
.{ // orn x0, xzr, x1
1385-
.inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0),
1439+
.inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0),
13861440
.expected = 0b1_01_01010_00_1_00001_000000_11111_00000,
13871441
},
13881442
.{ // movz x1, #4
@@ -1502,11 +1556,11 @@ test "serialize instructions" {
15021556
.expected = 0b10_101_0_001_1_0000010_00010_11111_00001,
15031557
},
15041558
.{ // and x0, x4, x2
1505-
.inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0),
1559+
.inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0),
15061560
.expected = 0b1_00_01010_00_0_00010_000000_00100_00000,
15071561
},
15081562
.{ // and x0, x4, x2, lsl #0x8
1509-
.inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8),
1563+
.inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0x8),
15101564
.expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
15111565
},
15121566
.{ // add x0, x10, #10
@@ -1537,6 +1591,10 @@ test "serialize instructions" {
15371591
.inst = Instruction.mul(.x1, .x4, .x9),
15381592
.expected = 0b1_00_11011_000_01001_0_11111_00100_00001,
15391593
},
1594+
.{ // eor x3, x5, #1
1595+
.inst = Instruction.eorImmediate(.x3, .x5, 0b000000, 0b000000, 0b1),
1596+
.expected = 0b1_10_100100_1_000000_000000_00101_00011,
1597+
},
15401598
};
15411599

15421600
for (testcases) |case| {

test/behavior/align.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,6 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
269269

270270
test "runtime known array index has best alignment possible" {
271271
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
272-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
273272
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
274273

275274
// take full advantage of over-alignment

test/behavior/array.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,6 @@ test "array with sentinels" {
142142
}
143143

144144
test "void arrays" {
145-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
146-
147145
var array: [4]void = undefined;
148146
array[0] = void{};
149147
array[1] = array[2];

test/behavior/bitcast.zig

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
7575
}
7676

7777
test "nested bitcast" {
78-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
79-
8078
const S = struct {
8179
fn moo(x: isize) !void {
8280
try expect(@intCast(isize, 42) == x);
@@ -94,8 +92,6 @@ test "nested bitcast" {
9492
}
9593

9694
test "@bitCast enum to its integer type" {
97-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98-
9995
const SOCK = enum(c_int) {
10096
A,
10197
B,
@@ -113,15 +109,11 @@ test "@bitCast enum to its integer type" {
113109

114110
// issue #3010: compiler segfault
115111
test "bitcast literal [4]u8 param to u32" {
116-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
117-
118112
const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
119113
try expect(ip == maxInt(u32));
120114
}
121115

122116
test "bitcast generates a temporary value" {
123-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
124-
125117
var y = @as(u16, 0x55AA);
126118
const x = @bitCast(u16, @bitCast([2]u8, y));
127119
try expect(y == x);
@@ -240,7 +232,6 @@ test "implicit cast to error union by returning" {
240232
test "bitcast packed struct literal to byte" {
241233
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
242234
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
243-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
244235

245236
const Foo = packed struct {
246237
value: u8,
@@ -252,7 +243,6 @@ test "bitcast packed struct literal to byte" {
252243
test "comptime bitcast used in expression has the correct type" {
253244
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
254245
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
255-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
256246

257247
const Foo = packed struct {
258248
value: u8,

test/behavior/bugs/3367.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const Mixin = struct {
1010
};
1111

1212
test "container member access usingnamespace decls" {
13-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1413
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1514
var foo = Foo{};
1615
foo.two();

0 commit comments

Comments
 (0)