| ... | ... | @@ -647,11 +647,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 647 | 647 | } |
| 648 | 648 | } |
| 649 | 649 | |
| 650 | | fn 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 | 650 | /// Asserts there is already capacity to insert into top branch inst_table. |
| 656 | 651 | fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 657 | 652 | const air_tags = self.air.instructions.items(.tag); |
| ... | ... | @@ -906,7 +901,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 906 | 901 | break :result r; |
| 907 | 902 | }, |
| 908 | 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 | 929 | |
| 935 | 930 | fn airAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 936 | 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 | 933 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 939 | 934 | } |
| 940 | 935 | |
| ... | ... | @@ -952,7 +947,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 952 | 947 | |
| 953 | 948 | fn airSub(self: *Self, inst: Air.Inst.Index) !void { |
| 954 | 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 | 951 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 957 | 952 | } |
| 958 | 953 | |
| ... | ... | @@ -970,7 +965,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 970 | 965 | |
| 971 | 966 | fn airMul(self: *Self, inst: Air.Inst.Index) !void { |
| 972 | 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 | 969 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 975 | 970 | } |
| 976 | 971 | |
| ... | ... | @@ -1026,25 +1021,25 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1026 | 1021 | |
| 1027 | 1022 | fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { |
| 1028 | 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 | 1025 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1031 | 1026 | } |
| 1032 | 1027 | |
| 1033 | 1028 | fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { |
| 1034 | 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 | 1031 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1037 | 1032 | } |
| 1038 | 1033 | |
| 1039 | 1034 | fn airXor(self: *Self, inst: Air.Inst.Index) !void { |
| 1040 | 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 | 1037 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1043 | 1038 | } |
| 1044 | 1039 | |
| 1045 | 1040 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { |
| 1046 | 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 | 1043 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1049 | 1044 | } |
| 1050 | 1045 | |
| ... | ... | @@ -1056,7 +1051,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1056 | 1051 | |
| 1057 | 1052 | fn airShr(self: *Self, inst: Air.Inst.Index) !void { |
| 1058 | 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 | 1055 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1061 | 1056 | } |
| 1062 | 1057 | |
| ... | ... | @@ -1296,7 +1291,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1296 | 1291 | else => { |
| 1297 | 1292 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 1298 | 1293 | |
| 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 | 1295 | assert(offset_mcv == .register); // result of multiplication should always be register |
| 1301 | 1296 | self.register_manager.freezeRegs(&.{offset_mcv.register}); |
| 1302 | 1297 | |
| ... | ... | @@ -1304,7 +1299,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1304 | 1299 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1305 | 1300 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1306 | 1301 | |
| 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); |
| 1308 | 1303 | |
| 1309 | 1304 | // At this point in time, neither the base register |
| 1310 | 1305 | // 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 | 1410 | |
| 1416 | 1411 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1417 | 1412 | const elem_ty = ptr_ty.elemType(); |
| 1413 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 1414 | |
| 1418 | 1415 | switch (ptr) { |
| 1419 | 1416 | .none => unreachable, |
| 1420 | 1417 | .undef => unreachable, |
| ... | ... | @@ -1440,24 +1437,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1440 | 1437 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| 1441 | 1438 | .embedded_in_code => unreachable, |
| 1442 | 1439 | .register => |dst_reg| { |
| 1443 | | _ = try self.addInst(.{ |
| 1444 | | .tag = .ldr, |
| 1445 | | .data = .{ .rr_offset = .{ |
| 1446 | | .rt = dst_reg, |
| 1447 | | .rn = reg, |
| 1448 | | .offset = .{ .offset = Instruction.Offset.none }, |
| 1449 | | } }, |
| 1450 | | }); |
| 1440 | try self.genLdrRegister(dst_reg, reg, elem_size); |
| 1451 | 1441 | }, |
| 1452 | 1442 | .stack_offset => |off| { |
| 1453 | | if (elem_ty.abiSize(self.target.*) <= 4) { |
| 1443 | if (elem_size <= 4) { |
| 1454 | 1444 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1455 | 1445 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1456 | 1446 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| 1457 | 1447 | |
| 1458 | 1448 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 1459 | 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 | 1451 | // TODO generalize this: maybe add a |
| 1462 | 1452 | // genArmMemcpy function which manually copies |
| 1463 | 1453 | // 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 | 1490 | const tmp_reg = regs[3]; |
| 1501 | 1491 | |
| 1502 | 1492 | // sub dst_reg, fp, #off |
| 1503 | | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 1504 | 1493 | const adj_off = off + elem_size; |
| 1505 | 1494 | const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else { |
| 1506 | 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 | 1517 | }); |
| 1529 | 1518 | |
| 1530 | 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 | 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 | 1589 | |
| 1601 | 1590 | switch (value) { |
| 1602 | 1591 | .register => |value_reg| { |
| 1603 | | _ = try self.addInst(.{ |
| 1604 | | .tag = .str, |
| 1605 | | .data = .{ .rr_offset = .{ |
| 1606 | | .rt = value_reg, |
| 1607 | | .rn = addr_reg, |
| 1608 | | .offset = .{ .offset = Instruction.Offset.none }, |
| 1609 | | } }, |
| 1610 | | }); |
| 1592 | try self.genStrRegister(value_reg, addr_reg, @intCast(u32, value_ty.abiSize(self.target.*))); |
| 1611 | 1593 | }, |
| 1612 | 1594 | else => { |
| 1613 | 1595 | if (value_ty.abiSize(self.target.*) <= 4) { |
| ... | ... | @@ -1723,7 +1705,7 @@ fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool { |
| 1723 | 1705 | }; |
| 1724 | 1706 | } |
| 1725 | 1707 | |
| 1726 | | fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue { |
| 1708 | fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue { |
| 1727 | 1709 | // In the case of bitshifts, the type of rhs is different |
| 1728 | 1710 | // from the resulting type |
| 1729 | 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 | 1714 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 1733 | 1715 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 1734 | 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 | 1719 | .Int => { |
| 1738 | 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 | 1723 | else => unreachable, |
| 1742 | 1724 | } |
| 1743 | 1725 | } |
| 1744 | 1726 | |
| 1745 | | fn genArmBinIntOp( |
| 1727 | fn genBinIntOp( |
| 1746 | 1728 | self: *Self, |
| 1747 | 1729 | inst: Air.Inst.Index, |
| 1748 | 1730 | op_lhs: Air.Inst.Ref, |
| ... | ... | @@ -1852,7 +1834,7 @@ fn genArmBinIntOp( |
| 1852 | 1834 | try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs); |
| 1853 | 1835 | } |
| 1854 | 1836 | |
| 1855 | | try self.genArmBinOpCode( |
| 1837 | try self.genBinOpCode( |
| 1856 | 1838 | dst_mcv.register, |
| 1857 | 1839 | lhs_mcv, |
| 1858 | 1840 | rhs_mcv, |
| ... | ... | @@ -1863,7 +1845,7 @@ fn genArmBinIntOp( |
| 1863 | 1845 | return dst_mcv; |
| 1864 | 1846 | } |
| 1865 | 1847 | |
| 1866 | | fn genArmBinOpCode( |
| 1848 | fn genBinOpCode( |
| 1867 | 1849 | self: *Self, |
| 1868 | 1850 | dst_reg: Register, |
| 1869 | 1851 | lhs_mcv: MCValue, |
| ... | ... | @@ -1971,7 +1953,7 @@ fn genArmBinOpCode( |
| 1971 | 1953 | } |
| 1972 | 1954 | } |
| 1973 | 1955 | |
| 1974 | | fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 1956 | fn genMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 1975 | 1957 | const lhs = try self.resolveInst(op_lhs); |
| 1976 | 1958 | const rhs = try self.resolveInst(op_rhs); |
| 1977 | 1959 | |
| ... | ... | @@ -2050,7 +2032,7 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai |
| 2050 | 2032 | return dst_mcv; |
| 2051 | 2033 | } |
| 2052 | 2034 | |
| 2053 | | fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { |
| 2035 | fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { |
| 2054 | 2036 | const lhs = try self.resolveInst(op); |
| 2055 | 2037 | const rhs = MCValue{ .immediate = imm }; |
| 2056 | 2038 | |
| ... | ... | @@ -2097,7 +2079,71 @@ fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { |
| 2097 | 2079 | return dst_mcv; |
| 2098 | 2080 | } |
| 2099 | 2081 | |
| 2100 | | fn genArmInlineMemcpy( |
| 2082 | fn 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 | |
| 2114 | fn 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 | |
| 2146 | fn genInlineMemcpy( |
| 2101 | 2147 | self: *Self, |
| 2102 | 2148 | src: Register, |
| 2103 | 2149 | dst: Register, |
| ... | ... | @@ -2469,7 +2515,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2469 | 2515 | |
| 2470 | 2516 | // The destination register is not present in the cmp instruction |
| 2471 | 2517 | // 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); |
| 2473 | 2519 | |
| 2474 | 2520 | break :result switch (signedness) { |
| 2475 | 2521 | .signed => MCValue{ .compare_flags_signed = op }, |
| ... | ... | @@ -2701,7 +2747,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2701 | 2747 | else => .{ .register = try self.copyToTmpRegister(ty, operand) }, |
| 2702 | 2748 | }; |
| 2703 | 2749 | |
| 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); |
| 2705 | 2751 | |
| 2706 | 2752 | return MCValue{ .compare_flags_unsigned = .eq }; |
| 2707 | 2753 | } else { |
| ... | ... | @@ -2731,7 +2777,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2731 | 2777 | else => .{ .register = try self.copyToTmpRegister(error_type, operand) }, |
| 2732 | 2778 | }; |
| 2733 | 2779 | |
| 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); |
| 2735 | 2781 | |
| 2736 | 2782 | return MCValue{ .compare_flags_unsigned = .gt }; |
| 2737 | 2783 | } else { |
| ... | ... | @@ -2946,8 +2992,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { |
| 2946 | 2992 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2947 | 2993 | const air_tags = self.air.instructions.items(.tag); |
| 2948 | 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), |
| 2950 | | .bool_or => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or), |
| 2995 | .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and), |
| 2996 | .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or), |
| 2951 | 2997 | else => unreachable, // Not a boolean operation |
| 2952 | 2998 | }; |
| 2953 | 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 | 3288 | }); |
| 3243 | 3289 | |
| 3244 | 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 | 3485 | // The value is in memory at a hard-coded address. |
| 3440 | 3486 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3441 | 3487 | try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) }); |
| 3442 | | _ = try self.addInst(.{ |
| 3443 | | .tag = .ldr, |
| 3444 | | .data = .{ .rr_offset = .{ |
| 3445 | | .rt = reg, |
| 3446 | | .rn = reg, |
| 3447 | | .offset = .{ .offset = Instruction.Offset.none }, |
| 3448 | | } }, |
| 3449 | | }); |
| 3488 | try self.genLdrRegister(reg, reg, @intCast(u32, ty.abiSize(self.target.*))); |
| 3450 | 3489 | }, |
| 3451 | 3490 | .stack_offset => |unadjusted_off| { |
| 3452 | 3491 | // TODO: maybe addressing from sp instead of fp |