aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/aarch64/CodeGen.zig157
1 files changed, 75 insertions, 82 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 049d8af572..b328c70f06 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -1193,7 +1193,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
/// Asserts that generating an instruction of that form is possible.
fn binOpRegister(
self: *Self,
- tag: Air.Inst.Tag,
+ mir_tag: Mir.Inst.Tag,
maybe_inst: ?Air.Inst.Index,
lhs: MCValue,
rhs: MCValue,
@@ -1256,38 +1256,9 @@ fn binOpRegister(
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
- const mir_tag: Mir.Inst.Tag = switch (tag) {
- .add,
- .ptr_add,
- => .add_shifted_register,
- .sub,
- .ptr_sub,
- => .sub_shifted_register,
- .cmp_eq => .cmp_shifted_register,
- .mul => .mul,
- .bit_and,
- .bool_and,
- => .and_shifted_register,
- .bit_or,
- .bool_or,
- => .orr_shifted_register,
- .shl,
- .shl_exact,
- => .lsl_register,
- .shr,
- .shr_exact,
- => switch (lhs_ty.intInfo(self.target.*).signedness) {
- .signed => Mir.Inst.Tag.asr_register,
- .unsigned => Mir.Inst.Tag.lsr_register,
- },
- .xor => .eor_shifted_register,
- else => unreachable,
- };
- const mir_data: Mir.Inst.Data = switch (tag) {
- .add,
- .sub,
- .ptr_add,
- .ptr_sub,
+ const mir_data: Mir.Inst.Data = switch (mir_tag) {
+ .add_shifted_register,
+ .sub_shifted_register,
=> .{ .rrr_imm6_shift = .{
.rd = dest_reg,
.rn = lhs_reg,
@@ -1295,27 +1266,24 @@ fn binOpRegister(
.imm6 = 0,
.shift = .lsl,
} },
- .cmp_eq => .{ .rr_imm6_shift = .{
+ .cmp_shifted_register => .{ .rr_imm6_shift = .{
.rn = lhs_reg,
.rm = rhs_reg,
.imm6 = 0,
.shift = .lsl,
} },
.mul,
- .shl,
- .shl_exact,
- .shr,
- .shr_exact,
+ .lsl_register,
+ .asr_register,
+ .lsr_register,
=> .{ .rrr = .{
.rd = dest_reg,
.rn = lhs_reg,
.rm = rhs_reg,
} },
- .bit_and,
- .bool_and,
- .bit_or,
- .bool_or,
- .xor,
+ .and_shifted_register,
+ .orr_shifted_register,
+ .eor_shifted_register,
=> .{ .rrr_imm6_logical_shift = .{
.rd = dest_reg,
.rn = lhs_reg,
@@ -1348,7 +1316,7 @@ fn binOpRegister(
/// Asserts that generating an instruction of that form is possible.
fn binOpImmediate(
self: *Self,
- tag: Air.Inst.Tag,
+ mir_tag: Mir.Inst.Tag,
maybe_inst: ?Air.Inst.Index,
lhs: MCValue,
rhs: MCValue,
@@ -1379,8 +1347,8 @@ fn binOpImmediate(
};
defer self.register_manager.unfreezeRegs(&.{lhs_reg});
- const dest_reg = switch (tag) {
- .cmp_eq => undefined, // cmp has no destination register
+ const dest_reg = switch (mir_tag) {
+ .cmp_immediate => undefined, // cmp has no destination register
else => if (maybe_inst) |inst| blk: {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
@@ -1400,39 +1368,23 @@ fn binOpImmediate(
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
- const mir_tag: Mir.Inst.Tag = switch (tag) {
- .add => .add_immediate,
- .sub => .sub_immediate,
- .shl,
- .shl_exact,
- => .lsl_immediate,
- .shr,
- .shr_exact,
- => switch (lhs_ty.intInfo(self.target.*).signedness) {
- .signed => Mir.Inst.Tag.asr_immediate,
- .unsigned => Mir.Inst.Tag.lsr_immediate,
- },
- .cmp_eq => .cmp_immediate,
- else => unreachable,
- };
- const mir_data: Mir.Inst.Data = switch (tag) {
- .add,
- .sub,
+ const mir_data: Mir.Inst.Data = switch (mir_tag) {
+ .add_immediate,
+ .sub_immediate,
=> .{ .rr_imm12_sh = .{
.rd = dest_reg,
.rn = lhs_reg,
.imm12 = @intCast(u12, rhs.immediate),
} },
- .shl,
- .shl_exact,
- .shr,
- .shr_exact,
+ .lsl_immediate,
+ .asr_immediate,
+ .lsr_immediate,
=> .{ .rr_shift = .{
.rd = dest_reg,
.rn = lhs_reg,
.shift = @intCast(u6, rhs.immediate),
} },
- .cmp_eq => .{ .r_imm12_sh = .{
+ .cmp_immediate => .{ .r_imm12_sh = .{
.rn = lhs_reg,
.imm12 = @intCast(u12, rhs.immediate),
} },
@@ -1470,7 +1422,6 @@ fn binOp(
) InnerError!MCValue {
const target = self.target.*;
switch (tag) {
- // Arithmetic operations on integers and floats
.add,
.sub,
.cmp_eq,
@@ -1498,13 +1449,26 @@ fn binOp(
else => unreachable,
};
+ const mir_tag_register: Mir.Inst.Tag = switch (tag) {
+ .add => .add_shifted_register,
+ .sub => .sub_shifted_register,
+ .cmp_eq => .cmp_shifted_register,
+ else => unreachable,
+ };
+ const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
+ .add => .add_immediate,
+ .sub => .sub_immediate,
+ .cmp_eq => .cmp_immediate,
+ else => unreachable,
+ };
+
if (rhs_immediate_ok) {
- return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
+ return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false);
} else if (lhs_immediate_ok) {
// swap lhs and rhs
- return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true);
+ return try self.binOpImmediate(mir_tag_immediate, maybe_inst, rhs, lhs, rhs_ty, true);
} else {
- return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+ return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
}
} else {
return self.fail("TODO binary operations on int with bits > 64", .{});
@@ -1523,7 +1487,7 @@ fn binOp(
// TODO add optimisations for multiplication
// with immediates, for example a * 2 can be
// lowered to a << 1
- return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+ return try self.binOpRegister(.mul, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
} else {
return self.fail("TODO binary operations on int with bits > 64", .{});
}
@@ -1564,7 +1528,6 @@ fn binOp(
else => unreachable,
}
},
- // Bitwise operations on integers
.bit_and,
.bit_or,
.xor,
@@ -1576,7 +1539,14 @@ fn binOp(
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 64) {
// TODO implement bitwise operations with immediates
- return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+ const mir_tag: Mir.Inst.Tag = switch (tag) {
+ .bit_and => .and_shifted_register,
+ .bit_or => .orr_shifted_register,
+ .xor => .eor_shifted_register,
+ else => unreachable,
+ };
+
+ return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
} else {
return self.fail("TODO binary operations on int with bits > 64", .{});
}
@@ -1594,10 +1564,27 @@ fn binOp(
if (int_info.bits <= 64) {
const rhs_immediate_ok = rhs == .immediate;
+ const mir_tag_register: Mir.Inst.Tag = switch (tag) {
+ .shl => .lsl_register,
+ .shr => switch (lhs_ty.intInfo(self.target.*).signedness) {
+ .signed => Mir.Inst.Tag.asr_register,
+ .unsigned => Mir.Inst.Tag.lsr_register,
+ },
+ else => unreachable,
+ };
+ const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
+ .shl => .lsl_immediate,
+ .shr => switch (lhs_ty.intInfo(self.target.*).signedness) {
+ .signed => Mir.Inst.Tag.asr_immediate,
+ .unsigned => Mir.Inst.Tag.lsr_immediate,
+ },
+ else => unreachable,
+ };
+
if (rhs_immediate_ok) {
- return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false);
+ return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false);
} else {
- return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+ return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
}
} else {
return self.fail("TODO binary operations on int with bits > 64", .{});
@@ -1614,7 +1601,13 @@ fn binOp(
assert(lhs != .immediate); // should have been handled by Sema
assert(rhs != .immediate); // should have been handled by Sema
- return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+ const mir_tag_register: Mir.Inst.Tag = switch (tag) {
+ .bool_and => .and_shifted_register,
+ .bool_or => .orr_shifted_register,
+ else => unreachable,
+ };
+
+ return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
},
else => unreachable,
}
@@ -1632,9 +1625,9 @@ fn binOp(
const elem_size = elem_ty.abiSize(self.target.*);
if (elem_size == 1) {
- const base_tag: Air.Inst.Tag = switch (tag) {
- .ptr_add => .add,
- .ptr_sub => .sub,
+ const base_tag: Mir.Inst.Tag = switch (tag) {
+ .ptr_add => .add_shifted_register,
+ .ptr_sub => .sub_shifted_register,
else => unreachable,
};