authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-15 22:58:54+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-19 22:37:56+02:00
logc78daeb642e742af3ac42bac0468776ccc4cd452
tree1f790dbc2142be7b550c488d53760217308f3c96
parent9c2cbe39c2caa9137e1123fcdf2f326282cad1b5
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: add basic assertions to bits.zig for correct codegen

Includes many fixes of errors discovered by adding these assertions

3 files changed, 126 insertions(+), 69 deletions(-)

src/arch/aarch64/CodeGen.zig+47-29
...@@ -376,7 +376,7 @@ fn gen(self: *Self) !void {...@@ -376,7 +376,7 @@ fn gen(self: *Self) !void {
376 // mov fp, sp376 // mov fp, sp
377 _ = try self.addInst(.{377 _ = try self.addInst(.{
378 .tag = .mov_to_from_sp,378 .tag = .mov_to_from_sp,
379 .data = .{ .rr = .{ .rd = .x29, .rn = .xzr } },379 .data = .{ .rr = .{ .rd = .x29, .rn = .sp } },
380 });380 });
381381
382 // sub sp, sp, #reloc382 // sub sp, sp, #reloc
...@@ -421,7 +421,7 @@ fn gen(self: *Self) !void {...@@ -421,7 +421,7 @@ fn gen(self: *Self) !void {
421 if (math.cast(u12, stack_size)) |size| {421 if (math.cast(u12, stack_size)) |size| {
422 self.mir_instructions.set(backpatch_reloc, .{422 self.mir_instructions.set(backpatch_reloc, .{
423 .tag = .sub_immediate,423 .tag = .sub_immediate,
424 .data = .{ .rr_imm12_sh = .{ .rd = .xzr, .rn = .xzr, .imm12 = size } },424 .data = .{ .rr_imm12_sh = .{ .rd = .sp, .rn = .sp, .imm12 = size } },
425 });425 });
426 } else |_| {426 } else |_| {
427 return self.failSymbol("TODO AArch64: allow larger stacks", .{});427 return self.failSymbol("TODO AArch64: allow larger stacks", .{});
...@@ -453,7 +453,7 @@ fn gen(self: *Self) !void {...@@ -453,7 +453,7 @@ fn gen(self: *Self) !void {
453 // add sp, sp, #stack_size453 // add sp, sp, #stack_size
454 _ = try self.addInst(.{454 _ = try self.addInst(.{
455 .tag = .add_immediate,455 .tag = .add_immediate,
456 .data = .{ .rr_imm12_sh = .{ .rd = .xzr, .rn = .xzr, .imm12 = @intCast(u12, stack_size) } },456 .data = .{ .rr_imm12_sh = .{ .rd = .sp, .rn = .sp, .imm12 = @intCast(u12, stack_size) } },
457 });457 });
458458
459 // <load other registers>459 // <load other registers>
...@@ -882,7 +882,8 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -882,7 +882,8 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
882/// allocated. A second call to `copyToTmpRegister` may return the same register.882/// allocated. A second call to `copyToTmpRegister` may return the same register.
883/// This can have a side effect of spilling instructions to the stack to free up a register.883/// This can have a side effect of spilling instructions to the stack to free up a register.
884fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {884fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
885 const reg = try self.register_manager.allocReg(null);885 const raw_reg = try self.register_manager.allocReg(null);
886 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
886 try self.genSetReg(ty, reg, mcv);887 try self.genSetReg(ty, reg, mcv);
887 return reg;888 return reg;
888}889}
...@@ -891,7 +892,9 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {...@@ -891,7 +892,9 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
891/// `reg_owner` is the instruction that gets associated with the register in the register table.892/// `reg_owner` is the instruction that gets associated with the register in the register table.
892/// This can have a side effect of spilling instructions to the stack to free up a register.893/// This can have a side effect of spilling instructions to the stack to free up a register.
893fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {894fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
894 const reg = try self.register_manager.allocReg(reg_owner);895 const raw_reg = try self.register_manager.allocReg(reg_owner);
896 const ty = self.air.typeOfIndex(reg_owner);
897 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
895 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);898 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
896 return MCValue{ .register = reg };899 return MCValue{ .register = reg };
897}900}
...@@ -1003,7 +1006,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1003,7 +1006,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1003 break :blk op_reg;1006 break :blk op_reg;
1004 }1007 }
10051008
1006 break :blk try self.register_manager.allocReg(null);1009 const raw_reg = try self.register_manager.allocReg(null);
1010 break :blk raw_reg.to32();
1007 };1011 };
10081012
1009 _ = try self.addInst(.{1013 _ = try self.addInst(.{
...@@ -1013,7 +1017,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1013,7 +1017,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1013 .rn = op_reg,1017 .rn = op_reg,
1014 .imms = 0b000000,1018 .imms = 0b000000,
1015 .immr = 0b000000,1019 .immr = 0b000000,
1016 .n = 0b1,1020 .n = 0b0,
1017 } },1021 } },
1018 });1022 });
10191023
...@@ -1035,7 +1039,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1035,7 +1039,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1035 break :blk op_reg;1039 break :blk op_reg;
1036 }1040 }
10371041
1038 break :blk try self.register_manager.allocReg(null);1042 const raw_reg = try self.register_manager.allocReg(null);
1043 break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*));
1039 };1044 };
10401045
1041 _ = try self.addInst(.{1046 _ = try self.addInst(.{
...@@ -1124,7 +1129,8 @@ fn binOpRegister(...@@ -1124,7 +1129,8 @@ fn binOpRegister(
1124 break :inst Air.refToIndex(bin_op.lhs).?;1129 break :inst Air.refToIndex(bin_op.lhs).?;
1125 } else null;1130 } else null;
11261131
1127 const reg = try self.register_manager.allocReg(track_inst);1132 const raw_reg = try self.register_manager.allocReg(track_inst);
1133 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1128 self.register_manager.freezeRegs(&.{reg});1134 self.register_manager.freezeRegs(&.{reg});
11291135
1130 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1136 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
...@@ -1139,7 +1145,8 @@ fn binOpRegister(...@@ -1139,7 +1145,8 @@ fn binOpRegister(
1139 break :inst Air.refToIndex(bin_op.rhs).?;1145 break :inst Air.refToIndex(bin_op.rhs).?;
1140 } else null;1146 } else null;
11411147
1142 const reg = try self.register_manager.allocReg(track_inst);1148 const raw_reg = try self.register_manager.allocReg(track_inst);
1149 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
1143 self.register_manager.freezeRegs(&.{reg});1150 self.register_manager.freezeRegs(&.{reg});
11441151
1145 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1152 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
...@@ -1156,7 +1163,8 @@ fn binOpRegister(...@@ -1156,7 +1163,8 @@ fn binOpRegister(
1156 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {1163 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
1157 break :blk rhs_reg;1164 break :blk rhs_reg;
1158 } else {1165 } else {
1159 break :blk try self.register_manager.allocReg(inst);1166 const raw_reg = try self.register_manager.allocReg(inst);
1167 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1160 }1168 }
1161 } else try self.register_manager.allocReg(null);1169 } else try self.register_manager.allocReg(null);
11621170
...@@ -1276,7 +1284,8 @@ fn binOpImmediate(...@@ -1276,7 +1284,8 @@ fn binOpImmediate(
1276 ).?;1284 ).?;
1277 } else null;1285 } else null;
12781286
1279 const reg = try self.register_manager.allocReg(track_inst);1287 const raw_reg = try self.register_manager.allocReg(track_inst);
1288 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1280 self.register_manager.freezeRegs(&.{reg});1289 self.register_manager.freezeRegs(&.{reg});
12811290
1282 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1291 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
...@@ -1298,7 +1307,8 @@ fn binOpImmediate(...@@ -1298,7 +1307,8 @@ fn binOpImmediate(
1298 )) {1307 )) {
1299 break :blk lhs_reg;1308 break :blk lhs_reg;
1300 } else {1309 } else {
1301 break :blk try self.register_manager.allocReg(inst);1310 const raw_reg = try self.register_manager.allocReg(inst);
1311 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1302 }1312 }
1303 } else try self.register_manager.allocReg(null),1313 } else try self.register_manager.allocReg(null),
1304 };1314 };
...@@ -1965,7 +1975,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1965,7 +1975,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1965 },1975 },
1966 .stack_offset => |off| {1976 .stack_offset => |off| {
1967 if (elem_size <= 8) {1977 if (elem_size <= 8) {
1968 const tmp_reg = try self.register_manager.allocReg(null);1978 const raw_tmp_reg = try self.register_manager.allocReg(null);
1979 const tmp_reg = registerAlias(raw_tmp_reg, elem_size);
1969 self.register_manager.freezeRegs(&.{tmp_reg});1980 self.register_manager.freezeRegs(&.{tmp_reg});
1970 defer self.register_manager.unfreezeRegs(&.{tmp_reg});1981 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
19711982
...@@ -2001,12 +2012,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2001,12 +2012,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2001 .got_load,2012 .got_load,
2002 .direct_load,2013 .direct_load,
2003 => {2014 => {
2004 const reg = try self.register_manager.allocReg(null);2015 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
2005 self.register_manager.freezeRegs(&.{reg});2016 try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);
2006 defer self.register_manager.unfreezeRegs(&.{reg});
2007
2008 try self.genSetReg(ptr_ty, reg, ptr);
2009 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
2010 },2017 },
2011 }2018 }
2012}2019}
...@@ -2091,6 +2098,7 @@ fn genInlineMemcpy(...@@ -2091,6 +2098,7 @@ fn genInlineMemcpy(
2091fn airLoad(self: *Self, inst: Air.Inst.Index) !void {2098fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2092 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2099 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2093 const elem_ty = self.air.typeOfIndex(inst);2100 const elem_ty = self.air.typeOfIndex(inst);
2101 const elem_size = elem_ty.abiSize(self.target.*);
2094 const result: MCValue = result: {2102 const result: MCValue = result: {
2095 if (!elem_ty.hasRuntimeBits())2103 if (!elem_ty.hasRuntimeBits())
2096 break :result MCValue.none;2104 break :result MCValue.none;
...@@ -2101,9 +2109,12 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -2101,9 +2109,12 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2101 break :result MCValue.dead;2109 break :result MCValue.dead;
21022110
2103 const dst_mcv: MCValue = blk: {2111 const dst_mcv: MCValue = blk: {
2104 if (self.reuseOperand(inst, ty_op.operand, 0, ptr)) {2112 if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) {
2105 // The MCValue that holds the pointer can be re-used as the value.2113 // The MCValue that holds the pointer can be re-used as the value.
2106 break :blk ptr;2114 break :blk switch (ptr) {
2115 .register => |r| MCValue{ .register = registerAlias(r, elem_size) },
2116 else => ptr,
2117 };
2107 } else {2118 } else {
2108 break :blk try self.allocRegOrMem(inst, true);2119 break :blk try self.allocRegOrMem(inst, true);
2109 }2120 }
...@@ -2209,6 +2220,8 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, abi_size...@@ -2209,6 +2220,8 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, abi_size
2209}2220}
22102221
2211fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {2222fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
2223 const abi_size = value_ty.abiSize(self.target.*);
2224
2212 switch (ptr) {2225 switch (ptr) {
2213 .none => unreachable,2226 .none => unreachable,
2214 .undef => unreachable,2227 .undef => unreachable,
...@@ -2226,14 +2239,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2226,14 +2239,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2226 self.register_manager.freezeRegs(&.{addr_reg});2239 self.register_manager.freezeRegs(&.{addr_reg});
2227 defer self.register_manager.unfreezeRegs(&.{addr_reg});2240 defer self.register_manager.unfreezeRegs(&.{addr_reg});
22282241
2229 const abi_size = value_ty.abiSize(self.target.*);
2230 switch (value) {2242 switch (value) {
2231 .register => |value_reg| {2243 .register => |value_reg| {
2232 try self.genStrRegister(value_reg, addr_reg, abi_size);2244 try self.genStrRegister(value_reg, addr_reg, abi_size);
2233 },2245 },
2234 else => {2246 else => {
2235 if (abi_size <= 8) {2247 if (abi_size <= 8) {
2236 const tmp_reg = try self.register_manager.allocReg(null);2248 const raw_tmp_reg = try self.register_manager.allocReg(null);
2249 const tmp_reg = registerAlias(raw_tmp_reg, abi_size);
2237 self.register_manager.freezeRegs(&.{tmp_reg});2250 self.register_manager.freezeRegs(&.{tmp_reg});
2238 defer self.register_manager.unfreezeRegs(&.{tmp_reg});2251 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
22392252
...@@ -3522,8 +3535,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3522,8 +3535,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3522 .memory => |addr| {3535 .memory => |addr| {
3523 // The value is in memory at a hard-coded address.3536 // The value is in memory at a hard-coded address.
3524 // If the type is a pointer, it means the pointer address is at this memory location.3537 // If the type is a pointer, it means the pointer address is at this memory location.
3525 try self.genSetReg(ty, reg, .{ .immediate = addr });3538 try self.genSetReg(ty, reg.to64(), .{ .immediate = addr });
3526 try self.genLdrRegister(reg, reg, ty.abiSize(self.target.*));3539 try self.genLdrRegister(reg, reg.to64(), ty.abiSize(self.target.*));
3527 },3540 },
3528 .stack_offset => |off| {3541 .stack_offset => |off| {
3529 const abi_size = ty.abiSize(self.target.*);3542 const abi_size = ty.abiSize(self.target.*);
...@@ -3998,6 +4011,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -3998,6 +4011,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
3998 var nsaa: u32 = 0; // Next stacked argument address4011 var nsaa: u32 = 0; // Next stacked argument address
39994012
4000 for (param_types) |ty, i| {4013 for (param_types) |ty, i| {
4014 const param_size = @intCast(u32, ty.abiSize(self.target.*));
4015 if (param_size == 0) {
4016 result.args[i] = .{ .none = {} };
4017 continue;
4018 }
4019
4001 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned4020 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
4002 // values to spread across odd-numbered registers.4021 // values to spread across odd-numbered registers.
4003 if (ty.abiAlignment(self.target.*) == 16 and !self.target.isDarwin()) {4022 if (ty.abiAlignment(self.target.*) == 16 and !self.target.isDarwin()) {
...@@ -4005,10 +4024,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4005,10 +4024,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4005 ncrn += ncrn % 2;4024 ncrn += ncrn % 2;
4006 }4025 }
40074026
4008 const param_size = @intCast(u32, ty.abiSize(self.target.*));
4009 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {4027 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
4010 if (param_size <= 8) {4028 if (param_size <= 8) {
4011 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };4029 result.args[i] = .{ .register = registerAlias(c_abi_int_param_regs[ncrn], param_size) };
4012 ncrn += 1;4030 ncrn += 1;
4013 } else {4031 } else {
4014 return self.fail("TODO MCValues with multiple registers", .{});4032 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -4045,7 +4063,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4045,7 +4063,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4045 .Unspecified, .C => {4063 .Unspecified, .C => {
4046 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));4064 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4047 if (ret_ty_size <= 8) {4065 if (ret_ty_size <= 8) {
4048 result.return_value = .{ .register = c_abi_int_return_regs[0] };4066 result.return_value = .{ .register = registerAlias(c_abi_int_return_regs[0], ret_ty_size) };
4049 } else {4067 } else {
4050 return self.fail("TODO support more return types for ARM backend", .{});4068 return self.fail("TODO support more return types for ARM backend", .{});
4051 }4069 }
src/arch/aarch64/Emit.zig+35-9
...@@ -457,8 +457,13 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -457,8 +457,13 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
457 const rn = r_imm12_sh.rn;457 const rn = r_imm12_sh.rn;
458 const imm12 = r_imm12_sh.imm12;458 const imm12 = r_imm12_sh.imm12;
459 const sh = r_imm12_sh.sh == 1;459 const sh = r_imm12_sh.sh == 1;
460 const zr: Register = switch (rn.size()) {
461 32 => .wzr,
462 64 => .xzr,
463 else => unreachable,
464 };
460465
461 try emit.writeInstruction(Instruction.subs(.xzr, rn, imm12, sh));466 try emit.writeInstruction(Instruction.subs(zr, rn, imm12, sh));
462 },467 },
463 else => unreachable,468 else => unreachable,
464 }469 }
...@@ -674,8 +679,13 @@ fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -674,8 +679,13 @@ fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
674 const rm = rr_imm6_shift.rm;679 const rm = rr_imm6_shift.rm;
675 const shift = rr_imm6_shift.shift;680 const shift = rr_imm6_shift.shift;
676 const imm6 = rr_imm6_shift.imm6;681 const imm6 = rr_imm6_shift.imm6;
682 const zr: Register = switch (rn.size()) {
683 32 => .wzr,
684 64 => .xzr,
685 else => unreachable,
686 };
677687
678 try emit.writeInstruction(Instruction.subsShiftedRegister(.xzr, rn, rm, shift, imm6));688 try emit.writeInstruction(Instruction.subsShiftedRegister(zr, rn, rm, shift, imm6));
679 },689 },
680 else => unreachable,690 else => unreachable,
681 }691 }
...@@ -686,7 +696,12 @@ fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -686,7 +696,12 @@ fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
686 switch (tag) {696 switch (tag) {
687 .cset => {697 .cset => {
688 const r_cond = emit.mir.instructions.items(.data)[inst].r_cond;698 const r_cond = emit.mir.instructions.items(.data)[inst].r_cond;
689 try emit.writeInstruction(Instruction.csinc(r_cond.rd, .xzr, .xzr, r_cond.cond));699 const zr: Register = switch (r_cond.rd.size()) {
700 32 => .wzr,
701 64 => .xzr,
702 else => unreachable,
703 };
704 try emit.writeInstruction(Instruction.csinc(r_cond.rd, zr, zr, r_cond.cond));
690 },705 },
691 else => unreachable,706 else => unreachable,
692 }707 }
...@@ -718,14 +733,14 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -718,14 +733,14 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
718 // PC-relative displacement to the entry in memory.733 // PC-relative displacement to the entry in memory.
719 // adrp734 // adrp
720 const offset = @intCast(u32, emit.code.items.len);735 const offset = @intCast(u32, emit.code.items.len);
721 try emit.writeInstruction(Instruction.adrp(reg, 0));736 try emit.writeInstruction(Instruction.adrp(reg.to64(), 0));
722737
723 switch (tag) {738 switch (tag) {
724 .load_memory_got => {739 .load_memory_got => {
725 // ldr reg, reg, offset740 // ldr reg, reg, offset
726 try emit.writeInstruction(Instruction.ldr(741 try emit.writeInstruction(Instruction.ldr(
727 reg,742 reg,
728 reg,743 reg.to64(),
729 Instruction.LoadStoreOffset.imm(0),744 Instruction.LoadStoreOffset.imm(0),
730 ));745 ));
731 },746 },
...@@ -739,11 +754,11 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -739,11 +754,11 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
739 // Note that this can potentially be optimised out by the codegen/linker if the754 // Note that this can potentially be optimised out by the codegen/linker if the
740 // target address is appropriately aligned.755 // target address is appropriately aligned.
741 // add reg, reg, offset756 // add reg, reg, offset
742 try emit.writeInstruction(Instruction.add(reg, reg, 0, false));757 try emit.writeInstruction(Instruction.add(reg.to64(), reg.to64(), 0, false));
743 // ldr reg, reg, offset758 // ldr reg, reg, offset
744 try emit.writeInstruction(Instruction.ldr(759 try emit.writeInstruction(Instruction.ldr(
745 reg,760 reg,
746 reg,761 reg.to64(),
747 Instruction.LoadStoreOffset.imm(0),762 Instruction.LoadStoreOffset.imm(0),
748 ));763 ));
749 },764 },
...@@ -905,7 +920,13 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -905,7 +920,13 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
905 switch (tag) {920 switch (tag) {
906 .mov_register => {921 .mov_register => {
907 const rr = emit.mir.instructions.items(.data)[inst].rr;922 const rr = emit.mir.instructions.items(.data)[inst].rr;
908 try emit.writeInstruction(Instruction.orrShiftedRegister(rr.rd, .xzr, rr.rn, .lsl, 0));923 const zr: Register = switch (rr.rd.size()) {
924 32 => .wzr,
925 64 => .xzr,
926 else => unreachable,
927 };
928
929 try emit.writeInstruction(Instruction.orrShiftedRegister(rr.rd, zr, rr.rn, .lsl, 0));
909 },930 },
910 .mov_to_from_sp => {931 .mov_to_from_sp => {
911 const rr = emit.mir.instructions.items(.data)[inst].rr;932 const rr = emit.mir.instructions.items(.data)[inst].rr;
...@@ -917,8 +938,13 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -917,8 +938,13 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
917 const rm = rr_imm6_logical_shift.rm;938 const rm = rr_imm6_logical_shift.rm;
918 const shift = rr_imm6_logical_shift.shift;939 const shift = rr_imm6_logical_shift.shift;
919 const imm6 = rr_imm6_logical_shift.imm6;940 const imm6 = rr_imm6_logical_shift.imm6;
941 const zr: Register = switch (rd.size()) {
942 32 => .wzr,
943 64 => .xzr,
944 else => unreachable,
945 };
920946
921 try emit.writeInstruction(Instruction.ornShiftedRegister(rd, .xzr, rm, shift, imm6));947 try emit.writeInstruction(Instruction.ornShiftedRegister(rd, zr, rm, shift, imm6));
922 },948 },
923 else => unreachable,949 else => unreachable,
924 }950 }
src/arch/aarch64/bits.zig+44-31
...@@ -695,6 +695,9 @@ pub const Instruction = union(enum) {...@@ -695,6 +695,9 @@ pub const Instruction = union(enum) {
695 offset: LoadStoreOffset,695 offset: LoadStoreOffset,
696 variant: LoadStoreVariant,696 variant: LoadStoreVariant,
697 ) Instruction {697 ) Instruction {
698 assert(rn.size() == 64);
699 assert(rn.id() != Register.xzr.id());
700
698 const off = offset.toU12();701 const off = offset.toU12();
699 const op1: u2 = blk: {702 const op1: u2 = blk: {
700 switch (offset) {703 switch (offset) {
...@@ -741,6 +744,9 @@ pub const Instruction = union(enum) {...@@ -741,6 +744,9 @@ pub const Instruction = union(enum) {
741 encoding: u2,744 encoding: u2,
742 load: bool,745 load: bool,
743 ) Instruction {746 ) Instruction {
747 assert(rn.size() == 64);
748 assert(rn.id() != Register.xzr.id());
749
744 switch (rt1.size()) {750 switch (rt1.size()) {
745 32 => {751 32 => {
746 assert(-256 <= offset and offset <= 252);752 assert(-256 <= offset and offset <= 252);
...@@ -849,38 +855,26 @@ pub const Instruction = union(enum) {...@@ -849,38 +855,26 @@ pub const Instruction = union(enum) {
849 shift: LogicalShiftedRegisterShift,855 shift: LogicalShiftedRegisterShift,
850 amount: u6,856 amount: u6,
851 ) Instruction {857 ) Instruction {
852 switch (rd.size()) {858 assert(rd.size() == rn.size());
853 32 => {859 assert(rd.size() == rm.size());
854 assert(amount < 32);860 if (rd.size() == 32) assert(amount < 32);
855 return Instruction{861
856 .logical_shifted_register = .{862 return Instruction{
857 .rd = rd.enc(),863 .logical_shifted_register = .{
858 .rn = rn.enc(),864 .rd = rd.enc(),
859 .imm6 = amount,865 .rn = rn.enc(),
860 .rm = rm.enc(),866 .imm6 = amount,
861 .n = n,867 .rm = rm.enc(),
862 .shift = @enumToInt(shift),868 .n = n,
863 .opc = opc,869 .shift = @enumToInt(shift),
864 .sf = 0b0,870 .opc = opc,
865 },871 .sf = switch (rd.size()) {
866 };872 32 => 0b0,
867 },873 64 => 0b1,
868 64 => {874 else => unreachable,
869 return Instruction{875 },
870 .logical_shifted_register = .{
871 .rd = rd.enc(),
872 .rn = rn.enc(),
873 .imm6 = amount,
874 .rm = rm.enc(),
875 .n = n,
876 .shift = @enumToInt(shift),
877 .opc = opc,
878 .sf = 0b1,
879 },
880 };
881 },876 },
882 else => unreachable, // unexpected register size877 };
883 }
884 }878 }
885879
886 fn addSubtractImmediate(880 fn addSubtractImmediate(
...@@ -891,6 +885,9 @@ pub const Instruction = union(enum) {...@@ -891,6 +885,9 @@ pub const Instruction = union(enum) {
891 imm12: u12,885 imm12: u12,
892 shift: bool,886 shift: bool,
893 ) Instruction {887 ) Instruction {
888 assert(rd.size() == rn.size());
889 assert(rn.id() != Register.xzr.id());
890
894 return Instruction{891 return Instruction{
895 .add_subtract_immediate = .{892 .add_subtract_immediate = .{
896 .rd = rd.enc(),893 .rd = rd.enc(),
...@@ -916,6 +913,9 @@ pub const Instruction = union(enum) {...@@ -916,6 +913,9 @@ pub const Instruction = union(enum) {
916 immr: u6,913 immr: u6,
917 n: u1,914 n: u1,
918 ) Instruction {915 ) Instruction {
916 assert(rd.size() == rn.size());
917 assert(!(rd.size() == 32 and n == 1));
918
919 return Instruction{919 return Instruction{
920 .logical_immediate = .{920 .logical_immediate = .{
921 .rd = rd.enc(),921 .rd = rd.enc(),
...@@ -941,6 +941,8 @@ pub const Instruction = union(enum) {...@@ -941,6 +941,8 @@ pub const Instruction = union(enum) {
941 immr: u6,941 immr: u6,
942 imms: u6,942 imms: u6,
943 ) Instruction {943 ) Instruction {
944 assert(rd.size() == rn.size());
945
944 return Instruction{946 return Instruction{
945 .bitfield = .{947 .bitfield = .{
946 .rd = rd.enc(),948 .rd = rd.enc(),
...@@ -969,6 +971,9 @@ pub const Instruction = union(enum) {...@@ -969,6 +971,9 @@ pub const Instruction = union(enum) {
969 rm: Register,971 rm: Register,
970 imm6: u6,972 imm6: u6,
971 ) Instruction {973 ) Instruction {
974 assert(rd.size() == rn.size());
975 assert(rd.size() == rm.size());
976
972 return Instruction{977 return Instruction{
973 .add_subtract_shifted_register = .{978 .add_subtract_shifted_register = .{
974 .rd = rd.enc(),979 .rd = rd.enc(),
...@@ -994,6 +999,7 @@ pub const Instruction = union(enum) {...@@ -994,6 +999,7 @@ pub const Instruction = union(enum) {
994 offset: i21,999 offset: i21,
995 ) Instruction {1000 ) Instruction {
996 assert(offset & 0b11 == 0b00);1001 assert(offset & 0b11 == 0b00);
1002
997 return Instruction{1003 return Instruction{
998 .conditional_branch = .{1004 .conditional_branch = .{
999 .cond = @enumToInt(cond),1005 .cond = @enumToInt(cond),
...@@ -1010,6 +1016,7 @@ pub const Instruction = union(enum) {...@@ -1010,6 +1016,7 @@ pub const Instruction = union(enum) {
1010 offset: i21,1016 offset: i21,
1011 ) Instruction {1017 ) Instruction {
1012 assert(offset & 0b11 == 0b00);1018 assert(offset & 0b11 == 0b00);
1019
1013 return Instruction{1020 return Instruction{
1014 .compare_and_branch = .{1021 .compare_and_branch = .{
1015 .rt = rt.enc(),1022 .rt = rt.enc(),
...@@ -1033,6 +1040,9 @@ pub const Instruction = union(enum) {...@@ -1033,6 +1040,9 @@ pub const Instruction = union(enum) {
1033 rm: Register,1040 rm: Register,
1034 cond: Condition,1041 cond: Condition,
1035 ) Instruction {1042 ) Instruction {
1043 assert(rd.size() == rn.size());
1044 assert(rd.size() == rm.size());
1045
1036 return Instruction{1046 return Instruction{
1037 .conditional_select = .{1047 .conditional_select = .{
1038 .rd = rd.enc(),1048 .rd = rd.enc(),
...@@ -1085,6 +1095,9 @@ pub const Instruction = union(enum) {...@@ -1085,6 +1095,9 @@ pub const Instruction = union(enum) {
1085 rn: Register,1095 rn: Register,
1086 rm: Register,1096 rm: Register,
1087 ) Instruction {1097 ) Instruction {
1098 assert(rd.size() == rn.size());
1099 assert(rd.size() == rm.size());
1100
1088 return Instruction{1101 return Instruction{
1089 .data_processing_2_source = .{1102 .data_processing_2_source = .{
1090 .rd = rd.enc(),1103 .rd = rd.enc(),