authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-06 18:18:53+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-06 23:29:36+01:00
logadc9a282d8b3cbe58e07c965fe40fb1dd8666bd7
treec5af1be6addc7065ab278f48511155fd3a9c6f71
parent4468abfc424ba645413ee076e5e2e370aa807bcc

stage2 ARM: fix load and store for abi_size < 4

Previously, in these cases, we would emit the ldr instruction even though ldrb oder ldrh are the correct instructions.

1 files changed, 98 insertions(+), 59 deletions(-)

src/arch/arm/CodeGen.zig+98-59
...@@ -647,11 +647,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -647,11 +647,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
647 }647 }
648}648}
649649
650fn writeInt(self: *Self, comptime T: type, buf: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T) void {
651 const endian = self.target.cpu.arch.endian();
652 std.mem.writeInt(T, buf, value, endian);
653}
654
655/// Asserts there is already capacity to insert into top branch inst_table.650/// Asserts there is already capacity to insert into top branch inst_table.
656fn processDeath(self: *Self, inst: Air.Inst.Index) void {651fn processDeath(self: *Self, inst: Air.Inst.Index) void {
657 const air_tags = self.air.instructions.items(.tag);652 const air_tags = self.air.instructions.items(.tag);
...@@ -906,7 +901,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -906,7 +901,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
906 break :result r;901 break :result r;
907 },902 },
908 else => {903 else => {
909 break :result try self.genArmBinOp(inst, ty_op.operand, .bool_true, .not);904 break :result try self.genBinOp(inst, ty_op.operand, .bool_true, .not);
910 },905 },
911 }906 }
912 };907 };
...@@ -934,7 +929,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -934,7 +929,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
934929
935fn airAdd(self: *Self, inst: Air.Inst.Index) !void {930fn airAdd(self: *Self, inst: Air.Inst.Index) !void {
936 const bin_op = self.air.instructions.items(.data)[inst].bin_op;931 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
937 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .add);932 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .add);
938 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });933 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
939}934}
940935
...@@ -952,7 +947,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -952,7 +947,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
952947
953fn airSub(self: *Self, inst: Air.Inst.Index) !void {948fn airSub(self: *Self, inst: Air.Inst.Index) !void {
954 const bin_op = self.air.instructions.items(.data)[inst].bin_op;949 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
955 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .sub);950 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .sub);
956 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });951 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
957}952}
958953
...@@ -970,7 +965,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -970,7 +965,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
970965
971fn airMul(self: *Self, inst: Air.Inst.Index) !void {966fn airMul(self: *Self, inst: Air.Inst.Index) !void {
972 const bin_op = self.air.instructions.items(.data)[inst].bin_op;967 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
973 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmMul(inst, bin_op.lhs, bin_op.rhs);968 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genMul(inst, bin_op.lhs, bin_op.rhs);
974 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });969 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
975}970}
976971
...@@ -1026,25 +1021,25 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1026,25 +1021,25 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
10261021
1027fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {1022fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
1028 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1023 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1029 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and);1024 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and);
1030 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1025 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1031}1026}
10321027
1033fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {1028fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
1034 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1029 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1035 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or);1030 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or);
1036 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1031 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1037}1032}
10381033
1039fn airXor(self: *Self, inst: Air.Inst.Index) !void {1034fn airXor(self: *Self, inst: Air.Inst.Index) !void {
1040 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1035 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1041 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .xor);1036 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .xor);
1042 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1037 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1043}1038}
10441039
1045fn airShl(self: *Self, inst: Air.Inst.Index) !void {1040fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1046 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1041 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1047 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .shl);1042 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shl);
1048 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1043 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1049}1044}
10501045
...@@ -1056,7 +1051,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -1056,7 +1051,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
10561051
1057fn airShr(self: *Self, inst: Air.Inst.Index) !void {1052fn airShr(self: *Self, inst: Air.Inst.Index) !void {
1058 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1053 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1059 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .shr);1054 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shr);
1060 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1055 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1061}1056}
10621057
...@@ -1296,7 +1291,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1296,7 +1291,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1296 else => {1291 else => {
1297 const dst_mcv = try self.allocRegOrMem(inst, true);1292 const dst_mcv = try self.allocRegOrMem(inst, true);
12981293
1299 const offset_mcv = try self.genArmMulConstant(bin_op.rhs, @intCast(u32, elem_size));1294 const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));
1300 assert(offset_mcv == .register); // result of multiplication should always be register1295 assert(offset_mcv == .register); // result of multiplication should always be register
1301 self.register_manager.freezeRegs(&.{offset_mcv.register});1296 self.register_manager.freezeRegs(&.{offset_mcv.register});
13021297
...@@ -1304,7 +1299,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1304,7 +1299,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1304 self.register_manager.freezeRegs(&.{addr_reg});1299 self.register_manager.freezeRegs(&.{addr_reg});
1305 defer self.register_manager.unfreezeRegs(&.{addr_reg});1300 defer self.register_manager.unfreezeRegs(&.{addr_reg});
13061301
1307 try self.genArmBinOpCode(addr_reg, base_mcv, offset_mcv, false, .add, .unsigned);1302 try self.genBinOpCode(addr_reg, base_mcv, offset_mcv, false, .add, .unsigned);
13081303
1309 // At this point in time, neither the base register1304 // At this point in time, neither the base register
1310 // nor the offset register contains any valuable data1305 // nor the offset register contains any valuable data
...@@ -1415,6 +1410,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind...@@ -1415,6 +1410,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
14151410
1416fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {1411fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
1417 const elem_ty = ptr_ty.elemType();1412 const elem_ty = ptr_ty.elemType();
1413 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
1414
1418 switch (ptr) {1415 switch (ptr) {
1419 .none => unreachable,1416 .none => unreachable,
1420 .undef => unreachable,1417 .undef => unreachable,
...@@ -1440,24 +1437,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1440,24 +1437,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1440 .compare_flags_signed, .compare_flags_unsigned => unreachable,1437 .compare_flags_signed, .compare_flags_unsigned => unreachable,
1441 .embedded_in_code => unreachable,1438 .embedded_in_code => unreachable,
1442 .register => |dst_reg| {1439 .register => |dst_reg| {
1443 _ = try self.addInst(.{1440 try self.genLdrRegister(dst_reg, reg, elem_size);
1444 .tag = .ldr,
1445 .data = .{ .rr_offset = .{
1446 .rt = dst_reg,
1447 .rn = reg,
1448 .offset = .{ .offset = Instruction.Offset.none },
1449 } },
1450 });
1451 },1441 },
1452 .stack_offset => |off| {1442 .stack_offset => |off| {
1453 if (elem_ty.abiSize(self.target.*) <= 4) {1443 if (elem_size <= 4) {
1454 const tmp_reg = try self.register_manager.allocReg(null);1444 const tmp_reg = try self.register_manager.allocReg(null);
1455 self.register_manager.freezeRegs(&.{tmp_reg});1445 self.register_manager.freezeRegs(&.{tmp_reg});
1456 defer self.register_manager.unfreezeRegs(&.{tmp_reg});1446 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
14571447
1458 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);1448 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1459 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });1449 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1460 } else if (elem_ty.abiSize(self.target.*) == 8) {1450 } else if (elem_size == 8) {
1461 // TODO generalize this: maybe add a1451 // TODO generalize this: maybe add a
1462 // genArmMemcpy function which manually copies1452 // genArmMemcpy function which manually copies
1463 // data if the size is below a certain1453 // data if the size is below a certain
...@@ -1500,7 +1490,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1500,7 +1490,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1500 const tmp_reg = regs[3];1490 const tmp_reg = regs[3];
15011491
1502 // sub dst_reg, fp, #off1492 // sub dst_reg, fp, #off
1503 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
1504 const adj_off = off + elem_size;1493 const adj_off = off + elem_size;
1505 const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else {1494 const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else {
1506 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});1495 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
...@@ -1528,7 +1517,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1528,7 +1517,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1528 });1517 });
15291518
1530 // memcpy(src, dst, len)1519 // memcpy(src, dst, len)
1531 try self.genArmInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);1520 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
1532 }1521 }
1533 },1522 },
1534 else => return self.fail("TODO load from register into {}", .{dst_mcv}),1523 else => return self.fail("TODO load from register into {}", .{dst_mcv}),
...@@ -1600,14 +1589,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -1600,14 +1589,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
16001589
1601 switch (value) {1590 switch (value) {
1602 .register => |value_reg| {1591 .register => |value_reg| {
1603 _ = try self.addInst(.{1592 try self.genStrRegister(value_reg, addr_reg, @intCast(u32, value_ty.abiSize(self.target.*)));
1604 .tag = .str,
1605 .data = .{ .rr_offset = .{
1606 .rt = value_reg,
1607 .rn = addr_reg,
1608 .offset = .{ .offset = Instruction.Offset.none },
1609 } },
1610 });
1611 },1593 },
1612 else => {1594 else => {
1613 if (value_ty.abiSize(self.target.*) <= 4) {1595 if (value_ty.abiSize(self.target.*) <= 4) {
...@@ -1723,7 +1705,7 @@ fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool {...@@ -1723,7 +1705,7 @@ fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool {
1723 };1705 };
1724}1706}
17251707
1726fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue {1708fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue {
1727 // In the case of bitshifts, the type of rhs is different1709 // In the case of bitshifts, the type of rhs is different
1728 // from the resulting type1710 // from the resulting type
1729 const ty = self.air.typeOf(op_lhs);1711 const ty = self.air.typeOf(op_lhs);
...@@ -1732,17 +1714,17 @@ fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -1732,17 +1714,17 @@ fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
1732 .Float => return self.fail("TODO ARM binary operations on floats", .{}),1714 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
1733 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),1715 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
1734 .Bool => {1716 .Bool => {
1735 return self.genArmBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned);1717 return self.genBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned);
1736 },1718 },
1737 .Int => {1719 .Int => {
1738 const int_info = ty.intInfo(self.target.*);1720 const int_info = ty.intInfo(self.target.*);
1739 return self.genArmBinIntOp(inst, op_lhs, op_rhs, op, int_info.bits, int_info.signedness);1721 return self.genBinIntOp(inst, op_lhs, op_rhs, op, int_info.bits, int_info.signedness);
1740 },1722 },
1741 else => unreachable,1723 else => unreachable,
1742 }1724 }
1743}1725}
17441726
1745fn genArmBinIntOp(1727fn genBinIntOp(
1746 self: *Self,1728 self: *Self,
1747 inst: Air.Inst.Index,1729 inst: Air.Inst.Index,
1748 op_lhs: Air.Inst.Ref,1730 op_lhs: Air.Inst.Ref,
...@@ -1852,7 +1834,7 @@ fn genArmBinIntOp(...@@ -1852,7 +1834,7 @@ fn genArmBinIntOp(
1852 try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs);1834 try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs);
1853 }1835 }
18541836
1855 try self.genArmBinOpCode(1837 try self.genBinOpCode(
1856 dst_mcv.register,1838 dst_mcv.register,
1857 lhs_mcv,1839 lhs_mcv,
1858 rhs_mcv,1840 rhs_mcv,
...@@ -1863,7 +1845,7 @@ fn genArmBinIntOp(...@@ -1863,7 +1845,7 @@ fn genArmBinIntOp(
1863 return dst_mcv;1845 return dst_mcv;
1864}1846}
18651847
1866fn genArmBinOpCode(1848fn genBinOpCode(
1867 self: *Self,1849 self: *Self,
1868 dst_reg: Register,1850 dst_reg: Register,
1869 lhs_mcv: MCValue,1851 lhs_mcv: MCValue,
...@@ -1971,7 +1953,7 @@ fn genArmBinOpCode(...@@ -1971,7 +1953,7 @@ fn genArmBinOpCode(
1971 }1953 }
1972}1954}
19731955
1974fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {1956fn genMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
1975 const lhs = try self.resolveInst(op_lhs);1957 const lhs = try self.resolveInst(op_lhs);
1976 const rhs = try self.resolveInst(op_rhs);1958 const rhs = try self.resolveInst(op_rhs);
19771959
...@@ -2050,7 +2032,7 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai...@@ -2050,7 +2032,7 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai
2050 return dst_mcv;2032 return dst_mcv;
2051}2033}
20522034
2053fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {2035fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
2054 const lhs = try self.resolveInst(op);2036 const lhs = try self.resolveInst(op);
2055 const rhs = MCValue{ .immediate = imm };2037 const rhs = MCValue{ .immediate = imm };
20562038
...@@ -2097,7 +2079,71 @@ fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {...@@ -2097,7 +2079,71 @@ fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
2097 return dst_mcv;2079 return dst_mcv;
2098}2080}
20992081
2100fn genArmInlineMemcpy(2082fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, abi_size: u32) !void {
2083 switch (abi_size) {
2084 1, 3, 4 => {
2085 const tag: Mir.Inst.Tag = switch (abi_size) {
2086 1 => .ldrb,
2087 3, 4 => .ldr,
2088 else => unreachable,
2089 };
2090
2091 _ = try self.addInst(.{
2092 .tag = tag,
2093 .data = .{ .rr_offset = .{
2094 .rt = dest_reg,
2095 .rn = addr_reg,
2096 .offset = .{ .offset = Instruction.Offset.none },
2097 } },
2098 });
2099 },
2100 2 => {
2101 _ = try self.addInst(.{
2102 .tag = .ldrh,
2103 .data = .{ .rr_extra_offset = .{
2104 .rt = dest_reg,
2105 .rn = addr_reg,
2106 .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
2107 } },
2108 });
2109 },
2110 else => unreachable, // invalid abi_size for a register
2111 }
2112}
2113
2114fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, abi_size: u32) !void {
2115 switch (abi_size) {
2116 1, 3, 4 => {
2117 const tag: Mir.Inst.Tag = switch (abi_size) {
2118 1 => .strb,
2119 3, 4 => .str,
2120 else => unreachable,
2121 };
2122
2123 _ = try self.addInst(.{
2124 .tag = tag,
2125 .data = .{ .rr_offset = .{
2126 .rt = source_reg,
2127 .rn = addr_reg,
2128 .offset = .{ .offset = Instruction.Offset.none },
2129 } },
2130 });
2131 },
2132 2 => {
2133 _ = try self.addInst(.{
2134 .tag = .strh,
2135 .data = .{ .rr_extra_offset = .{
2136 .rt = source_reg,
2137 .rn = addr_reg,
2138 .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
2139 } },
2140 });
2141 },
2142 else => unreachable, // invalid abi_size for a register
2143 }
2144}
2145
2146fn genInlineMemcpy(
2101 self: *Self,2147 self: *Self,
2102 src: Register,2148 src: Register,
2103 dst: Register,2149 dst: Register,
...@@ -2469,7 +2515,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -2469,7 +2515,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24692515
2470 // The destination register is not present in the cmp instruction2516 // The destination register is not present in the cmp instruction
2471 // The signedness of the integer does not matter for the cmp instruction2517 // The signedness of the integer does not matter for the cmp instruction
2472 try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined);2518 try self.genBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined);
24732519
2474 break :result switch (signedness) {2520 break :result switch (signedness) {
2475 .signed => MCValue{ .compare_flags_signed = op },2521 .signed => MCValue{ .compare_flags_signed = op },
...@@ -2701,7 +2747,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -2701,7 +2747,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
2701 else => .{ .register = try self.copyToTmpRegister(ty, operand) },2747 else => .{ .register = try self.copyToTmpRegister(ty, operand) },
2702 };2748 };
27032749
2704 try self.genArmBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);2750 try self.genBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);
27052751
2706 return MCValue{ .compare_flags_unsigned = .eq };2752 return MCValue{ .compare_flags_unsigned = .eq };
2707 } else {2753 } else {
...@@ -2731,7 +2777,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -2731,7 +2777,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
2731 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },2777 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
2732 };2778 };
27332779
2734 try self.genArmBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);2780 try self.genBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);
27352781
2736 return MCValue{ .compare_flags_unsigned = .gt };2782 return MCValue{ .compare_flags_unsigned = .gt };
2737 } else {2783 } else {
...@@ -2946,8 +2992,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -2946,8 +2992,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
2946 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2992 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2947 const air_tags = self.air.instructions.items(.tag);2993 const air_tags = self.air.instructions.items(.tag);
2948 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) {2994 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) {
2949 .bool_and => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and),2995 .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and),
2950 .bool_or => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or),2996 .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or),
2951 else => unreachable, // Not a boolean operation2997 else => unreachable, // Not a boolean operation
2952 };2998 };
2953 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2999 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
...@@ -3242,7 +3288,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3242,7 +3288,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3242 });3288 });
32433289
3244 // memcpy(src, dst, len)3290 // memcpy(src, dst, len)
3245 try self.genArmInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);3291 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
3246 }3292 }
3247 },3293 },
3248 }3294 }
...@@ -3439,14 +3485,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3439,14 +3485,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3439 // The value is in memory at a hard-coded address.3485 // The value is in memory at a hard-coded address.
3440 // If the type is a pointer, it means the pointer address is at this memory location.3486 // If the type is a pointer, it means the pointer address is at this memory location.
3441 try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) });3487 try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) });
3442 _ = try self.addInst(.{3488 try self.genLdrRegister(reg, reg, @intCast(u32, ty.abiSize(self.target.*)));
3443 .tag = .ldr,
3444 .data = .{ .rr_offset = .{
3445 .rt = reg,
3446 .rn = reg,
3447 .offset = .{ .offset = Instruction.Offset.none },
3448 } },
3449 });
3450 },3489 },
3451 .stack_offset => |unadjusted_off| {3490 .stack_offset => |unadjusted_off| {
3452 // TODO: maybe addressing from sp instead of fp3491 // TODO: maybe addressing from sp instead of fp