authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-13 20:23:20+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-16 20:20:07+01:00
log0eebdfcad38e1348ca5fb8a26e722803664a3ebb
treebe6c08c8a398f2646de426a52a4bf1a041b37465
parentca1ffb0951a0bd039ac435435a5c396f26c6d141
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: fix bitwise negation of ints with bits < 32


2 files changed, 76 insertions(+), 51 deletions(-)

src/arch/arm/CodeGen.zig+76-50
...@@ -939,63 +939,85 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -939,63 +939,85 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
939 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });939 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
940}940}
941941
942fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {942fn truncRegister(
943 const ty_op = self.air.instructions.items(.data)[inst].ty_op;943 self: *Self,
944 if (self.liveness.isUnused(inst))944 operand_reg: Register,
945 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });945 dest_reg: Register,
946 int_signedness: std.builtin.Signedness,
947 int_bits: u16,
948) !void {
949 // TODO check if sxtb/uxtb/sxth/uxth are more efficient
950 _ = try self.addInst(.{
951 .tag = switch (int_signedness) {
952 .signed => .sbfx,
953 .unsigned => .ubfx,
954 },
955 .data = .{ .rr_lsb_width = .{
956 .rd = dest_reg,
957 .rn = operand_reg,
958 .lsb = 0,
959 .width = @intCast(u6, int_bits),
960 } },
961 });
962}
946963
947 const operand_ty = self.air.typeOf(ty_op.operand);964fn trunc(
948 const operand = try self.resolveInst(ty_op.operand);965 self: *Self,
966 maybe_inst: ?Air.Inst.Index,
967 operand: MCValue,
968 operand_ty: Type,
969 dest_ty: Type,
970) !MCValue {
949 const info_a = operand_ty.intInfo(self.target.*);971 const info_a = operand_ty.intInfo(self.target.*);
950 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);972 const info_b = dest_ty.intInfo(self.target.*);
951973
952 const result: MCValue = blk: {974 if (info_b.bits <= 32) {
953 if (info_b.bits <= 32) {975 const operand_reg = switch (operand) {
954 const operand_reg = switch (operand) {976 .register => |r| r,
955 .register => |r| r,977 else => operand_reg: {
956 else => operand_reg: {978 if (info_a.bits <= 32) {
957 if (info_a.bits <= 32) {979 break :operand_reg try self.copyToTmpRegister(operand_ty, operand);
958 break :operand_reg try self.copyToTmpRegister(operand_ty, operand);980 } else {
959 } else {981 return self.fail("TODO load least significant word into register", .{});
960 return self.fail("TODO load least significant word into register", .{});
961 }
962 },
963 };
964 self.register_manager.freezeRegs(&.{operand_reg});
965 defer self.register_manager.unfreezeRegs(&.{operand_reg});
966
967 const dest_reg = dest_reg: {
968 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
969 break :dest_reg operand_reg;
970 }982 }
983 },
984 };
985 self.register_manager.freezeRegs(&.{operand_reg});
986 defer self.register_manager.unfreezeRegs(&.{operand_reg});
971987
972 break :dest_reg try self.register_manager.allocReg(null);988 const dest_reg = if (maybe_inst) |inst| blk: {
973 };989 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
974990
975 switch (info_b.bits) {991 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
976 32 => {992 break :blk operand_reg;
977 try self.genSetReg(operand_ty, dest_reg, .{ .register = operand_reg });993 } else {
978 break :blk MCValue{ .register = dest_reg };994 break :blk try self.register_manager.allocReg(inst);
979 },
980 else => {
981 _ = try self.addInst(.{
982 .tag = switch (info_b.signedness) {
983 .signed => .sbfx,
984 .unsigned => .ubfx,
985 },
986 .data = .{ .rr_lsb_width = .{
987 .rd = dest_reg,
988 .rn = operand_reg,
989 .lsb = 0,
990 .width = @intCast(u6, info_b.bits),
991 } },
992 });
993 break :blk MCValue{ .register = dest_reg };
994 },
995 }995 }
996 } else {996 } else try self.register_manager.allocReg(null);
997 return self.fail("TODO: truncate to ints > 32 bits", .{});997
998 switch (info_b.bits) {
999 32 => {
1000 try self.genSetReg(operand_ty, dest_reg, .{ .register = operand_reg });
1001 return MCValue{ .register = dest_reg };
1002 },
1003 else => {
1004 try self.truncRegister(operand_reg, dest_reg, info_b.signedness, info_b.bits);
1005 return MCValue{ .register = dest_reg };
1006 },
998 }1007 }
1008 } else {
1009 return self.fail("TODO: truncate to ints > 32 bits", .{});
1010 }
1011}
1012
1013fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
1014 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1015 const operand = try self.resolveInst(ty_op.operand);
1016 const operand_ty = self.air.typeOf(ty_op.operand);
1017 const dest_ty = self.air.typeOfIndex(inst);
1018
1019 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
1020 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);
999 };1021 };
10001022
1001 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1023 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -1099,6 +1121,10 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1099,6 +1121,10 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1099 } },1121 } },
1100 });1122 });
11011123
1124 if (int_info.bits < 32) {
1125 try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
1126 }
1127
1102 break :result MCValue{ .register = dest_reg };1128 break :result MCValue{ .register = dest_reg };
1103 } else {1129 } else {
1104 return self.fail("TODO ARM not on integers > u32/i32", .{});1130 return self.fail("TODO ARM not on integers > u32/i32", .{});
test/behavior/math.zig-1
...@@ -367,7 +367,6 @@ test "binary not" {...@@ -367,7 +367,6 @@ test "binary not" {
367 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO367 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
368 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO368 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
370 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
371370
372 try expect(comptime x: {371 try expect(comptime x: {
373 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;372 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;