diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 0822d1775f..a215764142 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -1983,8 +1983,8 @@ fn binOpRegister( if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); const mir_tag: Mir.Inst.Tag = switch (tag) { - .add, .ptr_add => .add, - .sub, .ptr_sub => .sub, + .add => .add, + .sub => .sub, .cmp_eq => .cmp, .mul => .mul, .bit_and, @@ -1993,12 +1993,8 @@ fn binOpRegister( .bit_or, .bool_or, => .orr, - .shl, - .shl_exact, - => .lsl, - .shr, - .shr_exact, - => switch (lhs_ty.intInfo(self.target.*).signedness) { + .shl_exact => .lsl, + .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) { .signed => Mir.Inst.Tag.asr, .unsigned => Mir.Inst.Tag.lsr, }, @@ -2014,16 +2010,12 @@ fn binOpRegister( .bit_or, .bool_or, .xor, - .ptr_add, - .ptr_sub, => .{ .rr_op = .{ .rd = dest_reg, .rn = lhs_reg, .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none), } }, - .shl, .shl_exact, - .shr, .shr_exact, => .{ .rr_shift = .{ .rd = dest_reg, @@ -2120,12 +2112,8 @@ fn binOpImmediate( .bit_or, .bool_or, => .orr, - .shl, - .shl_exact, - => .lsl, - .shr, - .shr_exact, - => switch (lhs_ty.intInfo(self.target.*).signedness) { + .shl_exact => .lsl, + .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) { .signed => Mir.Inst.Tag.asr, .unsigned => Mir.Inst.Tag.lsr, }, @@ -2146,9 +2134,7 @@ fn binOpImmediate( .rn = lhs_reg, .op = Instruction.Operand.fromU32(rhs.immediate).?, } }, - .shl, .shl_exact, - .shr, .shr_exact, => .{ .rr_shift = .{ .rd = dest_reg, @@ -2279,8 +2265,8 @@ fn binOp( else => unreachable, } }, - .shl, - .shr, + .shl_exact, + .shr_exact, => { switch (lhs_ty.zigTypeTag()) { .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -2301,6 +2287,41 @@ fn binOp( else => unreachable, } }, + .shl, + .shr, + => { + const base_tag: Air.Inst.Tag = switch (tag) { + .shl => .shl_exact, + .shr => .shr_exact, + else => unreachable, + }; + + // Generate a shl_exact/shr_exact + const result = try self.binOp(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); + + // Truncate if necessary + switch (tag) { + .shr => return result, + .shl => switch (lhs_ty.zigTypeTag()) { + .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), + .Int => { + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 32) { + const result_reg = result.register; + + if (int_info.bits < 32) { + try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); + return result; + } else return result; + } else { + return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); + } + }, + else => unreachable, + }, + else => unreachable, + } + }, .bool_and, .bool_or, => { @@ -2334,7 +2355,13 @@ fn binOp( const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); if (elem_size == 1) { - return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); + const base_tag: Air.Inst.Tag = switch (tag) { + .ptr_add => .add, + .ptr_sub => .sub, + else => unreachable, + }; + + return try self.binOpRegister(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); } else { // convert the offset into a byte offset by // multiplying it with elem_size diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 21eb53e497..f6f342ec13 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -864,7 +864,6 @@ test "quad hex float literal parsing accurate" { test "truncating shift left" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try testShlTrunc(maxInt(u16)); @@ -877,7 +876,6 @@ fn testShlTrunc(x: u16) !void { test "exact shift left" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try testShlExact(0b00110101); @@ -890,7 +888,6 @@ fn testShlExact(x: u8) !void { test "exact shift right" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try testShrExact(0b10110100);