authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-22 01:30:49-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-22 01:30:49-05:00
log6dc5ce931cbd208221be8588115e6d5e2fcb6eae
tree7176ce4247ac44aad5e5b0e37dbc058e1e2723f2
parent74303a3d9591f188fb4dda96bf689c00ebbd24ca
parent25f73224f7f9921633e67d4b5ef12c6ec10406eb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10959 from joachimschmidt557/stage2-aarch64

stage2 AArch64: misc improvements

12 files changed, 331 insertions(+), 184 deletions(-)

src/arch/aarch64/CodeGen.zig+241-114
...@@ -372,7 +372,7 @@ fn gen(self: *Self) !void {...@@ -372,7 +372,7 @@ fn gen(self: *Self) !void {
372 .data = .{ .load_store_register_pair = .{372 .data = .{ .load_store_register_pair = .{
373 .rt = .x29,373 .rt = .x29,
374 .rt2 = .x30,374 .rt2 = .x30,
375 .rn = Register.sp,375 .rn = .sp,
376 .offset = Instruction.LoadStorePairOffset.pre_index(-16),376 .offset = Instruction.LoadStorePairOffset.pre_index(-16),
377 } },377 } },
378 });378 });
...@@ -407,7 +407,7 @@ fn gen(self: *Self) !void {...@@ -407,7 +407,7 @@ fn gen(self: *Self) !void {
407 self.saved_regs_stack_space = 16;407 self.saved_regs_stack_space = 16;
408 inline for (callee_preserved_regs) |reg| {408 inline for (callee_preserved_regs) |reg| {
409 if (self.register_manager.isRegAllocated(reg)) {409 if (self.register_manager.isRegAllocated(reg)) {
410 saved_regs |= @as(u32, 1) << reg.id();410 saved_regs |= @as(u32, 1) << @intCast(u5, reg.id());
411 self.saved_regs_stack_space += 8;411 self.saved_regs_stack_space += 8;
412 }412 }
413 }413 }
...@@ -449,7 +449,7 @@ fn gen(self: *Self) !void {...@@ -449,7 +449,7 @@ fn gen(self: *Self) !void {
449 // the code. Therefore, we can just delete449 // the code. Therefore, we can just delete
450 // the space initially reserved for the450 // the space initially reserved for the
451 // jump451 // jump
452 self.mir_instructions.len -= 1;452 self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.items[0]);
453 } else for (self.exitlude_jump_relocs.items) |jmp_reloc| {453 } else for (self.exitlude_jump_relocs.items) |jmp_reloc| {
454 self.mir_instructions.set(jmp_reloc, .{454 self.mir_instructions.set(jmp_reloc, .{
455 .tag = .b,455 .tag = .b,
...@@ -475,7 +475,7 @@ fn gen(self: *Self) !void {...@@ -475,7 +475,7 @@ fn gen(self: *Self) !void {
475 .data = .{ .load_store_register_pair = .{475 .data = .{ .load_store_register_pair = .{
476 .rt = .x29,476 .rt = .x29,
477 .rt2 = .x30,477 .rt2 = .x30,
478 .rn = Register.sp,478 .rn = .sp,
479 .offset = Instruction.LoadStorePairOffset.post_index(16),479 .offset = Instruction.LoadStorePairOffset.post_index(16),
480 } },480 } },
481 });481 });
...@@ -1041,6 +1041,7 @@ fn binOpRegister(...@@ -1041,6 +1041,7 @@ fn binOpRegister(
1041 const mir_tag: Mir.Inst.Tag = switch (tag) {1041 const mir_tag: Mir.Inst.Tag = switch (tag) {
1042 .add, .ptr_add => .add_shifted_register,1042 .add, .ptr_add => .add_shifted_register,
1043 .sub, .ptr_sub => .sub_shifted_register,1043 .sub, .ptr_sub => .sub_shifted_register,
1044 .mul => .mul,
1044 .xor => .eor_shifted_register,1045 .xor => .eor_shifted_register,
1045 else => unreachable,1046 else => unreachable,
1046 };1047 };
...@@ -1056,6 +1057,11 @@ fn binOpRegister(...@@ -1056,6 +1057,11 @@ fn binOpRegister(
1056 .imm6 = 0,1057 .imm6 = 0,
1057 .shift = .lsl,1058 .shift = .lsl,
1058 } },1059 } },
1060 .mul => .{ .rrr = .{
1061 .rd = dest_reg,
1062 .rn = lhs_reg,
1063 .rm = rhs_reg,
1064 } },
1059 .xor => .{ .rrr_imm6_logical_shift = .{1065 .xor => .{ .rrr_imm6_logical_shift = .{
1060 .rd = dest_reg,1066 .rd = dest_reg,
1061 .rn = lhs_reg,1067 .rn = lhs_reg,
...@@ -1222,6 +1228,24 @@ fn binOp(...@@ -1222,6 +1228,24 @@ fn binOp(
1222 else => unreachable,1228 else => unreachable,
1223 }1229 }
1224 },1230 },
1231 .mul => {
1232 switch (lhs_ty.zigTypeTag()) {
1233 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1234 .Int => {
1235 assert(lhs_ty.eql(rhs_ty));
1236 const int_info = lhs_ty.intInfo(self.target.*);
1237 if (int_info.bits <= 64) {
1238 // TODO add optimisations for multiplication
1239 // with immediates, for example a * 2 can be
1240 // lowered to a << 1
1241 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1242 } else {
1243 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
1244 }
1245 },
1246 else => unreachable,
1247 }
1248 },
1225 // Bitwise operations on integers1249 // Bitwise operations on integers
1226 .xor => {1250 .xor => {
1227 switch (lhs_ty.zigTypeTag()) {1251 switch (lhs_ty.zigTypeTag()) {
...@@ -1551,88 +1575,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1551,88 +1575,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1551 };1575 };
1552 self.register_manager.freezeRegs(&.{base_mcv.register});1576 self.register_manager.freezeRegs(&.{base_mcv.register});
15531577
1554 // TODO implement optimized ldr for airSliceElemVal1578 switch (elem_size) {
1555 const dst_mcv = try self.allocRegOrMem(inst, true);1579 else => {
15561580 const dst_mcv = try self.allocRegOrMem(inst, true);
1557 const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));
1558 assert(offset_mcv == .register); // result of multiplication should always be register
1559 self.register_manager.freezeRegs(&.{offset_mcv.register});
15601581
1561 const addr_reg = try self.register_manager.allocReg(null);1582 const offset_mcv = try self.binOp(
1562 self.register_manager.freezeRegs(&.{addr_reg});1583 .mul,
1563 defer self.register_manager.unfreezeRegs(&.{addr_reg});1584 null,
1585 index_mcv,
1586 .{ .immediate = elem_size },
1587 Type.usize,
1588 Type.usize,
1589 );
1590 assert(offset_mcv == .register); // result of multiplication should always be register
1591 self.register_manager.freezeRegs(&.{offset_mcv.register});
15641592
1565 _ = try self.addInst(.{1593 const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize);
1566 .tag = .add_shifted_register,
1567 .data = .{ .rrr_imm6_shift = .{
1568 .rd = addr_reg,
1569 .rn = base_mcv.register,
1570 .rm = offset_mcv.register,
1571 .imm6 = 0,
1572 .shift = .lsl,
1573 } },
1574 });
15751594
1576 // At this point in time, neither the base register1595 // At this point in time, neither the base register
1577 // nor the offset register contains any valuable data1596 // nor the offset register contains any valuable data
1578 // anymore.1597 // anymore.
1579 self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });1598 self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });
15801599
1581 try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type);1600 try self.load(dst_mcv, addr_mcv, slice_ptr_field_type);
15821601
1583 break :result dst_mcv;1602 break :result dst_mcv;
1603 },
1604 }
1584 };1605 };
1585 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1606 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1586}1607}
15871608
1588fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
1589 const lhs = try self.resolveInst(op);
1590 const rhs = MCValue{ .immediate = imm };
1591
1592 const lhs_is_register = lhs == .register;
1593
1594 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
1595 defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register});
1596
1597 // Destination must be a register
1598 // LHS must be a register
1599 // RHS must be a register
1600 var dst_mcv: MCValue = undefined;
1601 var lhs_mcv: MCValue = lhs;
1602 var rhs_mcv: MCValue = rhs;
1603
1604 // Allocate registers for operands and/or destination
1605 // Allocate 1 or 2 registers
1606 if (lhs_is_register) {
1607 // Move RHS to register
1608 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) };
1609 rhs_mcv = dst_mcv;
1610 } else {
1611 // Move LHS and RHS to register
1612 const regs = try self.register_manager.allocRegs(2, .{ null, null });
1613 lhs_mcv = MCValue{ .register = regs[0] };
1614 rhs_mcv = MCValue{ .register = regs[1] };
1615 dst_mcv = lhs_mcv;
1616 }
1617
1618 // Move the operands to the newly allocated registers
1619 if (!lhs_is_register) {
1620 try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs);
1621 }
1622 try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs);
1623
1624 _ = try self.addInst(.{
1625 .tag = .mul,
1626 .data = .{ .rrr = .{
1627 .rd = dst_mcv.register,
1628 .rn = lhs_mcv.register,
1629 .rm = rhs_mcv.register,
1630 } },
1631 });
1632
1633 return dst_mcv;
1634}
1635
1636fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {1609fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1637 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1610 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1638 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1611 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -1763,23 +1736,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1763,23 +1736,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1763 self.register_manager.freezeRegs(&.{addr_reg});1736 self.register_manager.freezeRegs(&.{addr_reg});
1764 defer self.register_manager.unfreezeRegs(&.{addr_reg});1737 defer self.register_manager.unfreezeRegs(&.{addr_reg});
17651738
1739 const abi_size = elem_ty.abiSize(self.target.*);
1766 switch (dst_mcv) {1740 switch (dst_mcv) {
1767 .dead => unreachable,1741 .dead => unreachable,
1768 .undef => unreachable,1742 .undef => unreachable,
1769 .compare_flags_signed, .compare_flags_unsigned => unreachable,1743 .compare_flags_signed, .compare_flags_unsigned => unreachable,
1770 .embedded_in_code => unreachable,1744 .embedded_in_code => unreachable,
1771 .register => |dst_reg| {1745 .register => |dst_reg| {
1772 _ = try self.addInst(.{1746 try self.genLdrRegister(dst_reg, addr_reg, abi_size);
1773 .tag = .ldr_immediate,
1774 .data = .{ .load_store_register_immediate = .{
1775 .rt = dst_reg,
1776 .rn = addr_reg,
1777 .offset = Instruction.LoadStoreOffset.none.immediate,
1778 } },
1779 });
1780 },1747 },
1781 .stack_offset => |off| {1748 .stack_offset => |off| {
1782 if (elem_ty.abiSize(self.target.*) <= 8) {1749 if (abi_size <= 8) {
1783 const tmp_reg = try self.register_manager.allocReg(null);1750 const tmp_reg = try self.register_manager.allocReg(null);
1784 self.register_manager.freezeRegs(&.{tmp_reg});1751 self.register_manager.freezeRegs(&.{tmp_reg});
1785 defer self.register_manager.unfreezeRegs(&.{tmp_reg});1752 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
...@@ -1940,6 +1907,100 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1940,6 +1907,100 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1940 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1907 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1941}1908}
19421909
1910fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, abi_size: u64) !void {
1911 switch (abi_size) {
1912 1 => {
1913 _ = try self.addInst(.{
1914 .tag = .ldrb_immediate,
1915 .data = .{ .load_store_register_immediate = .{
1916 .rt = value_reg.to32(),
1917 .rn = addr_reg,
1918 .offset = Instruction.LoadStoreOffset.none.immediate,
1919 } },
1920 });
1921 },
1922 2 => {
1923 _ = try self.addInst(.{
1924 .tag = .ldrh_immediate,
1925 .data = .{ .load_store_register_immediate = .{
1926 .rt = value_reg.to32(),
1927 .rn = addr_reg,
1928 .offset = Instruction.LoadStoreOffset.none.immediate,
1929 } },
1930 });
1931 },
1932 4 => {
1933 _ = try self.addInst(.{
1934 .tag = .ldr_immediate,
1935 .data = .{ .load_store_register_immediate = .{
1936 .rt = value_reg.to32(),
1937 .rn = addr_reg,
1938 .offset = Instruction.LoadStoreOffset.none.immediate,
1939 } },
1940 });
1941 },
1942 8 => {
1943 _ = try self.addInst(.{
1944 .tag = .ldr_immediate,
1945 .data = .{ .load_store_register_immediate = .{
1946 .rt = value_reg.to64(),
1947 .rn = addr_reg,
1948 .offset = Instruction.LoadStoreOffset.none.immediate,
1949 } },
1950 });
1951 },
1952 3, 5, 6, 7 => return self.fail("TODO: genLdrRegister for more abi_sizes", .{}),
1953 else => unreachable,
1954 }
1955}
1956
1957fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, abi_size: u64) !void {
1958 switch (abi_size) {
1959 1 => {
1960 _ = try self.addInst(.{
1961 .tag = .strb_immediate,
1962 .data = .{ .load_store_register_immediate = .{
1963 .rt = value_reg.to32(),
1964 .rn = addr_reg,
1965 .offset = Instruction.LoadStoreOffset.none.immediate,
1966 } },
1967 });
1968 },
1969 2 => {
1970 _ = try self.addInst(.{
1971 .tag = .strh_immediate,
1972 .data = .{ .load_store_register_immediate = .{
1973 .rt = value_reg.to32(),
1974 .rn = addr_reg,
1975 .offset = Instruction.LoadStoreOffset.none.immediate,
1976 } },
1977 });
1978 },
1979 4 => {
1980 _ = try self.addInst(.{
1981 .tag = .str_immediate,
1982 .data = .{ .load_store_register_immediate = .{
1983 .rt = value_reg.to32(),
1984 .rn = addr_reg,
1985 .offset = Instruction.LoadStoreOffset.none.immediate,
1986 } },
1987 });
1988 },
1989 8 => {
1990 _ = try self.addInst(.{
1991 .tag = .str_immediate,
1992 .data = .{ .load_store_register_immediate = .{
1993 .rt = value_reg.to64(),
1994 .rn = addr_reg,
1995 .offset = Instruction.LoadStoreOffset.none.immediate,
1996 } },
1997 });
1998 },
1999 3, 5, 6, 7 => return self.fail("TODO: genStrRegister for more abi_sizes", .{}),
2000 else => unreachable,
2001 }
2002}
2003
1943fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {2004fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
1944 switch (ptr) {2005 switch (ptr) {
1945 .none => unreachable,2006 .none => unreachable,
...@@ -1960,8 +2021,28 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -1960,8 +2021,28 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
1960 .embedded_in_code => {2021 .embedded_in_code => {
1961 return self.fail("TODO implement storing to MCValue.embedded_in_code", .{});2022 return self.fail("TODO implement storing to MCValue.embedded_in_code", .{});
1962 },2023 },
1963 .register => {2024 .register => |addr_reg| {
1964 return self.fail("TODO implement storing to MCValue.register", .{});2025 self.register_manager.freezeRegs(&.{addr_reg});
2026 defer self.register_manager.unfreezeRegs(&.{addr_reg});
2027
2028 const abi_size = value_ty.abiSize(self.target.*);
2029 switch (value) {
2030 .register => |value_reg| {
2031 try self.genStrRegister(value_reg, addr_reg, abi_size);
2032 },
2033 else => {
2034 if (abi_size <= 8) {
2035 const tmp_reg = try self.register_manager.allocReg(null);
2036 self.register_manager.freezeRegs(&.{tmp_reg});
2037 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
2038
2039 try self.genSetReg(value_ty, tmp_reg, value);
2040 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
2041 } else {
2042 return self.fail("TODO implement memcpy", .{});
2043 }
2044 },
2045 }
1965 },2046 },
1966 .memory,2047 .memory,
1967 .stack_offset,2048 .stack_offset,
...@@ -2005,7 +2086,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {...@@ -2005,7 +2086,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
2005fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {2086fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
2006 return if (self.liveness.isUnused(inst)) .dead else result: {2087 return if (self.liveness.isUnused(inst)) .dead else result: {
2007 const mcv = try self.resolveInst(operand);2088 const mcv = try self.resolveInst(operand);
2008 const struct_ty = self.air.typeOf(operand).childType();2089 const ptr_ty = self.air.typeOf(operand);
2090 const struct_ty = ptr_ty.childType();
2009 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));2091 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
2010 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));2092 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
2011 const struct_field_ty = struct_ty.structFieldType(index);2093 const struct_field_ty = struct_ty.structFieldType(index);
...@@ -2014,7 +2096,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -2014,7 +2096,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
2014 .ptr_stack_offset => |off| {2096 .ptr_stack_offset => |off| {
2015 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };2097 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
2016 },2098 },
2017 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),2099 else => {
2100 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
2101 .immediate = struct_field_offset,
2102 });
2103 self.register_manager.freezeRegs(&.{offset_reg});
2104 defer self.register_manager.unfreezeRegs(&.{offset_reg});
2105
2106 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);
2107 self.register_manager.freezeRegs(&.{addr_reg});
2108 defer self.register_manager.unfreezeRegs(&.{addr_reg});
2109
2110 const dest = try self.binOp(
2111 .add,
2112 null,
2113 .{ .register = addr_reg },
2114 .{ .register = offset_reg },
2115 Type.usize,
2116 Type.usize,
2117 );
2118
2119 break :result dest;
2120 },
2018 }2121 }
2019 };2122 };
2020}2123}
...@@ -2983,8 +3086,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -2983,8 +3086,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
2983 const abi_size = ty.abiSize(self.target.*);3086 const abi_size = ty.abiSize(self.target.*);
2984 switch (mcv) {3087 switch (mcv) {
2985 .dead => unreachable,3088 .dead => unreachable,
2986 .ptr_stack_offset => unreachable,
2987 .ptr_embedded_in_code => unreachable,
2988 .unreach, .none => return, // Nothing to do.3089 .unreach, .none => return, // Nothing to do.
2989 .undef => {3090 .undef => {
2990 if (!self.wantSafety())3091 if (!self.wantSafety())
...@@ -3001,6 +3102,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3001,6 +3102,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3001 .compare_flags_unsigned,3102 .compare_flags_unsigned,
3002 .compare_flags_signed,3103 .compare_flags_signed,
3003 .immediate,3104 .immediate,
3105 .ptr_stack_offset,
3106 .ptr_embedded_in_code,
3004 => {3107 => {
3005 const reg = try self.copyToTmpRegister(ty, mcv);3108 const reg = try self.copyToTmpRegister(ty, mcv);
3006 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3109 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
...@@ -3043,17 +3146,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3043,17 +3146,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3043 _ = sym_index;3146 _ = sym_index;
3044 return self.fail("TODO implement set stack variable from {}", .{mcv});3147 return self.fail("TODO implement set stack variable from {}", .{mcv});
3045 },3148 },
3046 .memory => |vaddr| {3149 .memory,
3047 _ = vaddr;3150 .stack_offset,
3048 return self.fail("TODO implement set stack variable from memory vaddr", .{});3151 => {
3049 },3152 switch (mcv) {
3050 .stack_offset => |off| {3153 .stack_offset => |off| {
3051 if (stack_offset == off)3154 if (stack_offset == off)
3052 return; // Copy stack variable to itself; nothing to do.3155 return; // Copy stack variable to itself; nothing to do.
3156 },
3157 else => {},
3158 }
30533159
3054 const ptr_bits = self.target.cpu.arch.ptrBitWidth();3160 if (abi_size <= 8) {
3055 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3056 if (abi_size <= ptr_bytes) {
3057 const reg = try self.copyToTmpRegister(ty, mcv);3161 const reg = try self.copyToTmpRegister(ty, mcv);
3058 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3162 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3059 } else {3163 } else {
...@@ -3068,17 +3172,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3068,17 +3172,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3068 const count_reg = regs[3];3172 const count_reg = regs[3];
3069 const tmp_reg = regs[4];3173 const tmp_reg = regs[4];
30703174
3071 // sub src_reg, fp, #off3175 switch (mcv) {
3072 const adj_src_offset = off + abi_size;3176 .stack_offset => |off| {
3073 const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{});3177 // sub src_reg, fp, #off
3074 _ = try self.addInst(.{3178 const adj_src_offset = off + abi_size;
3075 .tag = .sub_immediate,3179 const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{});
3076 .data = .{ .rr_imm12_sh = .{3180 _ = try self.addInst(.{
3077 .rd = src_reg,3181 .tag = .sub_immediate,
3078 .rn = .x29,3182 .data = .{ .rr_imm12_sh = .{
3079 .imm12 = src_offset,3183 .rd = src_reg,
3080 } },3184 .rn = .x29,
3081 });3185 .imm12 = src_offset,
3186 } },
3187 });
3188 },
3189 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),
3190 else => unreachable,
3191 }
30823192
3083 // sub dst_reg, fp, #stack_offset3193 // sub dst_reg, fp, #stack_offset
3084 const adj_dst_off = stack_offset + abi_size;3194 const adj_dst_off = stack_offset + abi_size;
...@@ -3105,7 +3215,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3105,7 +3215,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3105fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {3215fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
3106 switch (mcv) {3216 switch (mcv) {
3107 .dead => unreachable,3217 .dead => unreachable,
3108 .ptr_stack_offset => unreachable,
3109 .ptr_embedded_in_code => unreachable,3218 .ptr_embedded_in_code => unreachable,
3110 .unreach, .none => return, // Nothing to do.3219 .unreach, .none => return, // Nothing to do.
3111 .undef => {3220 .undef => {
...@@ -3118,6 +3227,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3118,6 +3227,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3118 else => unreachable, // unexpected register size3227 else => unreachable, // unexpected register size
3119 }3228 }
3120 },3229 },
3230 .ptr_stack_offset => |unadjusted_off| {
3231 // TODO: maybe addressing from sp instead of fp
3232 const elem_ty = ty.childType();
3233 const abi_size = elem_ty.abiSize(self.target.*);
3234 const adj_off = unadjusted_off + abi_size;
3235
3236 const imm12 = math.cast(u12, adj_off) catch
3237 return self.fail("TODO larger stack offsets", .{});
3238
3239 _ = try self.addInst(.{
3240 .tag = .sub_immediate,
3241 .data = .{ .rr_imm12_sh = .{
3242 .rd = reg,
3243 .rn = .x29,
3244 .imm12 = imm12,
3245 } },
3246 });
3247 },
3121 .compare_flags_unsigned,3248 .compare_flags_unsigned,
3122 .compare_flags_signed,3249 .compare_flags_signed,
3123 => |op| {3250 => |op| {
src/arch/aarch64/Emit.zig+2-2
...@@ -909,7 +909,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -909,7 +909,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
909 var other_reg: Register = undefined;909 var other_reg: Register = undefined;
910 while (i > 0) : (i -= 1) {910 while (i > 0) : (i -= 1) {
911 const reg = @intToEnum(Register, i - 1);911 const reg = @intToEnum(Register, i - 1);
912 if (reg_list & @as(u32, 1) << reg.id() != 0) {912 if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {
913 if (count % 2 == 0) {913 if (count % 2 == 0) {
914 if (count == number_of_regs - 1) {914 if (count == number_of_regs - 1) {
915 try emit.writeInstruction(Instruction.ldr(915 try emit.writeInstruction(Instruction.ldr(
...@@ -939,7 +939,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -939,7 +939,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
939 var other_reg: Register = undefined;939 var other_reg: Register = undefined;
940 while (i < 32) : (i += 1) {940 while (i < 32) : (i += 1) {
941 const reg = @intToEnum(Register, i);941 const reg = @intToEnum(Register, i);
942 if (reg_list & @as(u32, 1) << reg.id() != 0) {942 if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {
943 if (count % 2 == 0) {943 if (count % 2 == 0) {
944 if (count == number_of_regs - 1) {944 if (count == number_of_regs - 1) {
945 try emit.writeInstruction(Instruction.str(945 try emit.writeInstruction(Instruction.str(
src/arch/aarch64/bits.zig+79-51
...@@ -7,7 +7,7 @@ const testing = std.testing;...@@ -7,7 +7,7 @@ const testing = std.testing;
7// zig fmt: off7// zig fmt: off
88
9/// General purpose registers in the AArch64 instruction set9/// General purpose registers in the AArch64 instruction set
10pub const Register = enum(u6) {10pub const Register = enum(u7) {
11 // 64-bit registers11 // 64-bit registers
12 x0, x1, x2, x3, x4, x5, x6, x7,12 x0, x1, x2, x3, x4, x5, x6, x7,
13 x8, x9, x10, x11, x12, x13, x14, x15,13 x8, x9, x10, x11, x12, x13, x14, x15,
...@@ -20,10 +20,23 @@ pub const Register = enum(u6) {...@@ -20,10 +20,23 @@ pub const Register = enum(u6) {
20 w16, w17, w18, w19, w20, w21, w22, w23,20 w16, w17, w18, w19, w20, w21, w22, w23,
21 w24, w25, w26, w27, w28, w29, w30, wzr,21 w24, w25, w26, w27, w28, w29, w30, wzr,
2222
23 pub const sp = Register.xzr;23 // Stack pointer
24 sp, wsp,
2425
25 pub fn id(self: Register) u5 {26 pub fn id(self: Register) u6 {
26 return @truncate(u5, @enumToInt(self));27 return switch (@enumToInt(self)) {
28 0...63 => return @as(u6, @truncate(u5, @enumToInt(self))),
29 64...65 => 32,
30 else => unreachable,
31 };
32 }
33
34 pub fn enc(self: Register) u5 {
35 return switch (@enumToInt(self)) {
36 0...63 => return @truncate(u5, @enumToInt(self)),
37 64...65 => 31,
38 else => unreachable,
39 };
27 }40 }
2841
29 /// Returns the bit-width of the register.42 /// Returns the bit-width of the register.
...@@ -31,17 +44,32 @@ pub const Register = enum(u6) {...@@ -31,17 +44,32 @@ pub const Register = enum(u6) {
31 return switch (@enumToInt(self)) {44 return switch (@enumToInt(self)) {
32 0...31 => 64,45 0...31 => 64,
33 32...63 => 32,46 32...63 => 32,
47 64 => 64,
48 65 => 32,
49 else => unreachable,
34 };50 };
35 }51 }
3652
37 /// Convert from any register to its 64 bit alias.53 /// Convert from any register to its 64 bit alias.
38 pub fn to64(self: Register) Register {54 pub fn to64(self: Register) Register {
39 return @intToEnum(Register, self.id());55 return switch (@enumToInt(self)) {
56 0...31 => self,
57 32...63 => @intToEnum(Register, @enumToInt(self) - 32),
58 64 => .sp,
59 65 => .sp,
60 else => unreachable,
61 };
40 }62 }
4163
42 /// Convert from any register to its 32 bit alias.64 /// Convert from any register to its 32 bit alias.
43 pub fn to32(self: Register) Register {65 pub fn to32(self: Register) Register {
44 return @intToEnum(Register, @as(u6, self.id()) + 32);66 return switch (@enumToInt(self)) {
67 0...31 => @intToEnum(Register, @enumToInt(self) + 32),
68 32...63 => self,
69 64 => .wsp,
70 65 => .wsp,
71 else => unreachable,
72 };
45 }73 }
4674
47 /// Returns the index into `callee_preserved_regs`.75 /// Returns the index into `callee_preserved_regs`.
...@@ -53,7 +81,7 @@ pub const Register = enum(u6) {...@@ -53,7 +81,7 @@ pub const Register = enum(u6) {
53 }81 }
5482
55 pub fn dwarfLocOp(self: Register) u8 {83 pub fn dwarfLocOp(self: Register) u8 {
56 return @as(u8, self.id()) + DW.OP.reg0;84 return @as(u8, self.enc()) + DW.OP.reg0;
57 }85 }
58};86};
5987
...@@ -76,15 +104,15 @@ pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_re...@@ -76,15 +104,15 @@ pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_re
76pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };104pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
77pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };105pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
78106
79test "Register.id" {107test "Register.enc" {
80 try testing.expectEqual(@as(u5, 0), Register.x0.id());108 try testing.expectEqual(@as(u5, 0), Register.x0.enc());
81 try testing.expectEqual(@as(u5, 0), Register.w0.id());109 try testing.expectEqual(@as(u5, 0), Register.w0.enc());
82110
83 try testing.expectEqual(@as(u5, 31), Register.xzr.id());111 try testing.expectEqual(@as(u5, 31), Register.xzr.enc());
84 try testing.expectEqual(@as(u5, 31), Register.wzr.id());112 try testing.expectEqual(@as(u5, 31), Register.wzr.enc());
85113
86 try testing.expectEqual(@as(u5, 31), Register.sp.id());114 try testing.expectEqual(@as(u5, 31), Register.sp.enc());
87 try testing.expectEqual(@as(u5, 31), Register.sp.id());115 try testing.expectEqual(@as(u5, 31), Register.sp.enc());
88}116}
89117
90test "Register.size" {118test "Register.size" {
...@@ -479,7 +507,7 @@ pub const Instruction = union(enum) {...@@ -479,7 +507,7 @@ pub const Instruction = union(enum) {
479 assert(shift % 16 == 0 and shift <= 16);507 assert(shift % 16 == 0 and shift <= 16);
480 return Instruction{508 return Instruction{
481 .move_wide_immediate = .{509 .move_wide_immediate = .{
482 .rd = rd.id(),510 .rd = rd.enc(),
483 .imm16 = imm16,511 .imm16 = imm16,
484 .hw = @intCast(u2, shift / 16),512 .hw = @intCast(u2, shift / 16),
485 .opc = opc,513 .opc = opc,
...@@ -491,7 +519,7 @@ pub const Instruction = union(enum) {...@@ -491,7 +519,7 @@ pub const Instruction = union(enum) {
491 assert(shift % 16 == 0 and shift <= 48);519 assert(shift % 16 == 0 and shift <= 48);
492 return Instruction{520 return Instruction{
493 .move_wide_immediate = .{521 .move_wide_immediate = .{
494 .rd = rd.id(),522 .rd = rd.enc(),
495 .imm16 = imm16,523 .imm16 = imm16,
496 .hw = @intCast(u2, shift / 16),524 .hw = @intCast(u2, shift / 16),
497 .opc = opc,525 .opc = opc,
...@@ -508,7 +536,7 @@ pub const Instruction = union(enum) {...@@ -508,7 +536,7 @@ pub const Instruction = union(enum) {
508 const imm21_u = @bitCast(u21, imm21);536 const imm21_u = @bitCast(u21, imm21);
509 return Instruction{537 return Instruction{
510 .pc_relative_address = .{538 .pc_relative_address = .{
511 .rd = rd.id(),539 .rd = rd.enc(),
512 .immlo = @truncate(u2, imm21_u),540 .immlo = @truncate(u2, imm21_u),
513 .immhi = @truncate(u19, imm21_u >> 2),541 .immhi = @truncate(u19, imm21_u >> 2),
514 .op = op,542 .op = op,
...@@ -580,7 +608,7 @@ pub const Instruction = union(enum) {...@@ -580,7 +608,7 @@ pub const Instruction = union(enum) {
580 pub fn reg(rm: Register) LoadStoreOffset {608 pub fn reg(rm: Register) LoadStoreOffset {
581 return .{609 return .{
582 .register = .{610 .register = .{
583 .rm = rm.id(),611 .rm = rm.enc(),
584 .shift = .{612 .shift = .{
585 .lsl = 0,613 .lsl = 0,
586 },614 },
...@@ -592,7 +620,7 @@ pub const Instruction = union(enum) {...@@ -592,7 +620,7 @@ pub const Instruction = union(enum) {
592 assert(rm.size() == 32 and (shift == 0 or shift == 2));620 assert(rm.size() == 32 and (shift == 0 or shift == 2));
593 return .{621 return .{
594 .register = .{622 .register = .{
595 .rm = rm.id(),623 .rm = rm.enc(),
596 .shift = .{624 .shift = .{
597 .uxtw = shift,625 .uxtw = shift,
598 },626 },
...@@ -604,7 +632,7 @@ pub const Instruction = union(enum) {...@@ -604,7 +632,7 @@ pub const Instruction = union(enum) {
604 assert(rm.size() == 64 and (shift == 0 or shift == 3));632 assert(rm.size() == 64 and (shift == 0 or shift == 3));
605 return .{633 return .{
606 .register = .{634 .register = .{
607 .rm = rm.id(),635 .rm = rm.enc(),
608 .shift = .{636 .shift = .{
609 .lsl = shift,637 .lsl = shift,
610 },638 },
...@@ -616,7 +644,7 @@ pub const Instruction = union(enum) {...@@ -616,7 +644,7 @@ pub const Instruction = union(enum) {
616 assert(rm.size() == 32 and (shift == 0 or shift == 2));644 assert(rm.size() == 32 and (shift == 0 or shift == 2));
617 return .{645 return .{
618 .register = .{646 .register = .{
619 .rm = rm.id(),647 .rm = rm.enc(),
620 .shift = .{648 .shift = .{
621 .sxtw = shift,649 .sxtw = shift,
622 },650 },
...@@ -628,7 +656,7 @@ pub const Instruction = union(enum) {...@@ -628,7 +656,7 @@ pub const Instruction = union(enum) {
628 assert(rm.size() == 64 and (shift == 0 or shift == 3));656 assert(rm.size() == 64 and (shift == 0 or shift == 3));
629 return .{657 return .{
630 .register = .{658 .register = .{
631 .rm = rm.id(),659 .rm = rm.enc(),
632 .shift = .{660 .shift = .{
633 .sxtx = shift,661 .sxtx = shift,
634 },662 },
...@@ -676,8 +704,8 @@ pub const Instruction = union(enum) {...@@ -676,8 +704,8 @@ pub const Instruction = union(enum) {
676 };704 };
677 return Instruction{705 return Instruction{
678 .load_store_register = .{706 .load_store_register = .{
679 .rt = rt.id(),707 .rt = rt.enc(),
680 .rn = rn.id(),708 .rn = rn.enc(),
681 .offset = off,709 .offset = off,
682 .opc = opc,710 .opc = opc,
683 .op1 = op1,711 .op1 = op1,
...@@ -711,9 +739,9 @@ pub const Instruction = union(enum) {...@@ -711,9 +739,9 @@ pub const Instruction = union(enum) {
711 const imm7 = @truncate(u7, @bitCast(u9, offset >> 2));739 const imm7 = @truncate(u7, @bitCast(u9, offset >> 2));
712 return Instruction{740 return Instruction{
713 .load_store_register_pair = .{741 .load_store_register_pair = .{
714 .rt1 = rt1.id(),742 .rt1 = rt1.enc(),
715 .rn = rn.id(),743 .rn = rn.enc(),
716 .rt2 = rt2.id(),744 .rt2 = rt2.enc(),
717 .imm7 = imm7,745 .imm7 = imm7,
718 .load = @boolToInt(load),746 .load = @boolToInt(load),
719 .encoding = encoding,747 .encoding = encoding,
...@@ -726,9 +754,9 @@ pub const Instruction = union(enum) {...@@ -726,9 +754,9 @@ pub const Instruction = union(enum) {
726 const imm7 = @truncate(u7, @bitCast(u9, offset >> 3));754 const imm7 = @truncate(u7, @bitCast(u9, offset >> 3));
727 return Instruction{755 return Instruction{
728 .load_store_register_pair = .{756 .load_store_register_pair = .{
729 .rt1 = rt1.id(),757 .rt1 = rt1.enc(),
730 .rn = rn.id(),758 .rn = rn.enc(),
731 .rt2 = rt2.id(),759 .rt2 = rt2.enc(),
732 .imm7 = imm7,760 .imm7 = imm7,
733 .load = @boolToInt(load),761 .load = @boolToInt(load),
734 .encoding = encoding,762 .encoding = encoding,
...@@ -743,7 +771,7 @@ pub const Instruction = union(enum) {...@@ -743,7 +771,7 @@ pub const Instruction = union(enum) {
743 fn loadLiteral(rt: Register, imm19: u19) Instruction {771 fn loadLiteral(rt: Register, imm19: u19) Instruction {
744 return Instruction{772 return Instruction{
745 .load_literal = .{773 .load_literal = .{
746 .rt = rt.id(),774 .rt = rt.enc(),
747 .imm19 = imm19,775 .imm19 = imm19,
748 .opc = switch (rt.size()) {776 .opc = switch (rt.size()) {
749 32 => 0b00,777 32 => 0b00,
...@@ -782,7 +810,7 @@ pub const Instruction = union(enum) {...@@ -782,7 +810,7 @@ pub const Instruction = union(enum) {
782 return Instruction{810 return Instruction{
783 .unconditional_branch_register = .{811 .unconditional_branch_register = .{
784 .op4 = op4,812 .op4 = op4,
785 .rn = rn.id(),813 .rn = rn.enc(),
786 .op3 = op3,814 .op3 = op3,
787 .op2 = op2,815 .op2 = op2,
788 .opc = opc,816 .opc = opc,
...@@ -818,10 +846,10 @@ pub const Instruction = union(enum) {...@@ -818,10 +846,10 @@ pub const Instruction = union(enum) {
818 assert(amount < 32);846 assert(amount < 32);
819 return Instruction{847 return Instruction{
820 .logical_shifted_register = .{848 .logical_shifted_register = .{
821 .rd = rd.id(),849 .rd = rd.enc(),
822 .rn = rn.id(),850 .rn = rn.enc(),
823 .imm6 = amount,851 .imm6 = amount,
824 .rm = rm.id(),852 .rm = rm.enc(),
825 .n = n,853 .n = n,
826 .shift = @enumToInt(shift),854 .shift = @enumToInt(shift),
827 .opc = opc,855 .opc = opc,
...@@ -832,10 +860,10 @@ pub const Instruction = union(enum) {...@@ -832,10 +860,10 @@ pub const Instruction = union(enum) {
832 64 => {860 64 => {
833 return Instruction{861 return Instruction{
834 .logical_shifted_register = .{862 .logical_shifted_register = .{
835 .rd = rd.id(),863 .rd = rd.enc(),
836 .rn = rn.id(),864 .rn = rn.enc(),
837 .imm6 = amount,865 .imm6 = amount,
838 .rm = rm.id(),866 .rm = rm.enc(),
839 .n = n,867 .n = n,
840 .shift = @enumToInt(shift),868 .shift = @enumToInt(shift),
841 .opc = opc,869 .opc = opc,
...@@ -857,8 +885,8 @@ pub const Instruction = union(enum) {...@@ -857,8 +885,8 @@ pub const Instruction = union(enum) {
857 ) Instruction {885 ) Instruction {
858 return Instruction{886 return Instruction{
859 .add_subtract_immediate = .{887 .add_subtract_immediate = .{
860 .rd = rd.id(),888 .rd = rd.enc(),
861 .rn = rn.id(),889 .rn = rn.enc(),
862 .imm12 = imm12,890 .imm12 = imm12,
863 .sh = @boolToInt(shift),891 .sh = @boolToInt(shift),
864 .s = s,892 .s = s,
...@@ -885,10 +913,10 @@ pub const Instruction = union(enum) {...@@ -885,10 +913,10 @@ pub const Instruction = union(enum) {
885 ) Instruction {913 ) Instruction {
886 return Instruction{914 return Instruction{
887 .add_subtract_shifted_register = .{915 .add_subtract_shifted_register = .{
888 .rd = rd.id(),916 .rd = rd.enc(),
889 .rn = rn.id(),917 .rn = rn.enc(),
890 .imm6 = imm6,918 .imm6 = imm6,
891 .rm = rm.id(),919 .rm = rm.enc(),
892 .shift = @enumToInt(shift),920 .shift = @enumToInt(shift),
893 .s = s,921 .s = s,
894 .op = op,922 .op = op,
...@@ -926,7 +954,7 @@ pub const Instruction = union(enum) {...@@ -926,7 +954,7 @@ pub const Instruction = union(enum) {
926 assert(offset & 0b11 == 0b00);954 assert(offset & 0b11 == 0b00);
927 return Instruction{955 return Instruction{
928 .compare_and_branch = .{956 .compare_and_branch = .{
929 .rt = rt.id(),957 .rt = rt.enc(),
930 .imm19 = @bitCast(u19, @intCast(i19, offset >> 2)),958 .imm19 = @bitCast(u19, @intCast(i19, offset >> 2)),
931 .op = op,959 .op = op,
932 .sf = switch (rt.size()) {960 .sf = switch (rt.size()) {
...@@ -949,11 +977,11 @@ pub const Instruction = union(enum) {...@@ -949,11 +977,11 @@ pub const Instruction = union(enum) {
949 ) Instruction {977 ) Instruction {
950 return Instruction{978 return Instruction{
951 .conditional_select = .{979 .conditional_select = .{
952 .rd = rd.id(),980 .rd = rd.enc(),
953 .rn = rn.id(),981 .rn = rn.enc(),
954 .op2 = op2,982 .op2 = op2,
955 .cond = @enumToInt(cond),983 .cond = @enumToInt(cond),
956 .rm = rm.id(),984 .rm = rm.enc(),
957 .s = s,985 .s = s,
958 .op = op,986 .op = op,
959 .sf = switch (rd.size()) {987 .sf = switch (rd.size()) {
...@@ -976,11 +1004,11 @@ pub const Instruction = union(enum) {...@@ -976,11 +1004,11 @@ pub const Instruction = union(enum) {
976 ) Instruction {1004 ) Instruction {
977 return Instruction{1005 return Instruction{
978 .data_processing_3_source = .{1006 .data_processing_3_source = .{
979 .rd = rd.id(),1007 .rd = rd.enc(),
980 .rn = rn.id(),1008 .rn = rn.enc(),
981 .ra = ra.id(),1009 .ra = ra.enc(),
982 .o0 = o0,1010 .o0 = o0,
983 .rm = rm.id(),1011 .rm = rm.enc(),
984 .op31 = op31,1012 .op31 = op31,
985 .op54 = op54,1013 .op54 = op54,
986 .sf = switch (rd.size()) {1014 .sf = switch (rd.size()) {
test/behavior/align.zig+1-3
...@@ -27,7 +27,6 @@ test "default alignment allows unspecified in type syntax" {...@@ -27,7 +27,6 @@ test "default alignment allows unspecified in type syntax" {
27}27}
2828
29test "implicitly decreasing pointer alignment" {29test "implicitly decreasing pointer alignment" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 const a: u32 align(4) = 3;30 const a: u32 align(4) = 3;
32 const b: u32 align(8) = 4;31 const b: u32 align(8) = 4;
33 try expect(addUnaligned(&a, &b) == 7);32 try expect(addUnaligned(&a, &b) == 7);
...@@ -38,7 +37,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {...@@ -38,7 +37,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
38}37}
3938
40test "@alignCast pointers" {39test "@alignCast pointers" {
41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
42 var x: u32 align(4) = 1;40 var x: u32 align(4) = 1;
43 expectsOnly1(&x);41 expectsOnly1(&x);
44 try expect(x == 2);42 try expect(x == 2);
...@@ -313,7 +311,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {...@@ -313,7 +311,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
313}311}
314312
315test "alignment of function with c calling convention" {313test "alignment of function with c calling convention" {
316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;314 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
317 if (builtin.zig_backend == .stage1) return error.SkipZigTest;315 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
318316
319 var runtime_nothing = &nothing;317 var runtime_nothing = &nothing;
test/behavior/basic.zig+3-4
...@@ -48,7 +48,7 @@ const g1: i32 = 1233 + 1;...@@ -48,7 +48,7 @@ const g1: i32 = 1233 + 1;
48var g2: i32 = 0;48var g2: i32 = 0;
4949
50test "global variables" {50test "global variables" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
52 try expect(g2 == 0);52 try expect(g2 == 0);
53 g2 = g1;53 g2 = g1;
54 try expect(g2 == 1234);54 try expect(g2 == 1234);
...@@ -327,7 +327,6 @@ const FnPtrWrapper = struct {...@@ -327,7 +327,6 @@ const FnPtrWrapper = struct {
327};327};
328328
329test "const ptr from var variable" {329test "const ptr from var variable" {
330 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
331 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
332331
333 var x: u64 = undefined;332 var x: u64 = undefined;
...@@ -611,7 +610,7 @@ test "comptime cast fn to ptr" {...@@ -611,7 +610,7 @@ test "comptime cast fn to ptr" {
611}610}
612611
613test "equality compare fn ptrs" {612test "equality compare fn ptrs" {
614 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;613 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
615 if (builtin.zig_backend == .stage1) return error.SkipZigTest;614 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
616615
617 var a = &emptyFn;616 var a = &emptyFn;
...@@ -619,7 +618,7 @@ test "equality compare fn ptrs" {...@@ -619,7 +618,7 @@ test "equality compare fn ptrs" {
619}618}
620619
621test "self reference through fn ptr field" {620test "self reference through fn ptr field" {
622 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;621 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
623 if (builtin.zig_backend == .stage1) return error.SkipZigTest;622 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
624 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;623 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
625624
test/behavior/bitreverse.zig-1
...@@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" {...@@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" {
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12 // Currently failing on stage1 for big-endian targets11 // Currently failing on stage1 for big-endian targets
13 if (builtin.zig_backend == .stage1) return error.SkipZigTest;12 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1413
test/behavior/bugs/1486.zig+1-1
...@@ -6,7 +6,7 @@ const ptr = &global;...@@ -6,7 +6,7 @@ const ptr = &global;
6var global: usize = 123;6var global: usize = 123;
77
8test "constant pointer to global variable causes runtime load" {8test "constant pointer to global variable causes runtime load" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
10 global = 1234;10 global = 1234;
11 try expect(&global == ptr);11 try expect(&global == ptr);
12 try expect(ptr.* == 1234);12 try expect(ptr.* == 1234);
test/behavior/bugs/2006.zig+1-1
...@@ -6,7 +6,7 @@ const S = struct {...@@ -6,7 +6,7 @@ const S = struct {
6 p: *S,6 p: *S,
7};7};
8test "bug 2006" {8test "bug 2006" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11 var a: S = undefined;11 var a: S = undefined;
12 a = S{ .p = undefined };12 a = S{ .p = undefined };
test/behavior/cast.zig+1-2
...@@ -211,7 +211,6 @@ test "implicit cast from *[N]T to [*c]T" {...@@ -211,7 +211,6 @@ test "implicit cast from *[N]T to [*c]T" {
211}211}
212212
213test "*usize to *void" {213test "*usize to *void" {
214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
215 var i = @as(usize, 0);214 var i = @as(usize, 0);
216 var v = @ptrCast(*void, &i);215 var v = @ptrCast(*void, &i);
217 v.* = {};216 v.* = {};
...@@ -1014,7 +1013,7 @@ test "cast from array reference to fn: comptime fn ptr" {...@@ -1014,7 +1013,7 @@ test "cast from array reference to fn: comptime fn ptr" {
1014 try expect(@ptrToInt(f) == @ptrToInt(&global_array));1013 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
1015}1014}
1016test "cast from array reference to fn: runtime fn ptr" {1015test "cast from array reference to fn: runtime fn ptr" {
1017 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1016 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
1018 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1017 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1018 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1020 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1019 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/optional.zig-1
...@@ -36,7 +36,6 @@ test "optional pointer to size zero struct" {...@@ -36,7 +36,6 @@ test "optional pointer to size zero struct" {
36}36}
3737
38test "equality compare optional pointers" {38test "equality compare optional pointers" {
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO39 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
41 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4241
test/behavior/slice.zig+1-1
...@@ -81,7 +81,7 @@ fn assertLenIsZero(msg: []const u8) !void {...@@ -81,7 +81,7 @@ fn assertLenIsZero(msg: []const u8) !void {
81}81}
8282
83test "access len index of sentinel-terminated slice" {83test "access len index of sentinel-terminated slice" {
84 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;84 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO85 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
8686
87 const S = struct {87 const S = struct {
test/behavior/struct.zig+1-3
...@@ -43,7 +43,6 @@ const StructWithFields = struct {...@@ -43,7 +43,6 @@ const StructWithFields = struct {
43};43};
4444
45test "non-packed struct has fields padded out to the required alignment" {45test "non-packed struct has fields padded out to the required alignment" {
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
4847
49 const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 };48 const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 };
...@@ -67,7 +66,7 @@ const SmallStruct = struct {...@@ -67,7 +66,7 @@ const SmallStruct = struct {
67};66};
6867
69test "lower unnamed constants" {68test "lower unnamed constants" {
70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;69 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
71 var foo = SmallStruct{ .a = 1, .b = 255 };70 var foo = SmallStruct{ .a = 1, .b = 255 };
72 try expect(foo.first() == 1);71 try expect(foo.first() == 1);
73 try expect(foo.second() == 255);72 try expect(foo.second() == 255);
...@@ -186,7 +185,6 @@ test "store member function in variable" {...@@ -186,7 +185,6 @@ test "store member function in variable" {
186}185}
187186
188test "member functions" {187test "member functions" {
189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
190 const r = MemberFnRand{ .seed = 1234 };188 const r = MemberFnRand{ .seed = 1234 };
191 try expect(r.getSeed() == 1234);189 try expect(r.getSeed() == 1234);
192}190}