diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-15 19:32:16 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-15 19:32:16 +0100 |
| commit | 3af4e28dda7e4537255516fd1d575c2a34d904e7 (patch) | |
| tree | 526e491b538bdbff894ae27050f01de8f23be2f8 /src | |
| parent | 6315bcb32aa48858c43373542d9c50a366913f7c (diff) | |
| download | zig-3af4e28dda7e4537255516fd1d575c2a34d904e7.tar.gz zig-3af4e28dda7e4537255516fd1d575c2a34d904e7.zip | |
stage2: implement signed compare
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 36 | ||||
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 20 |
2 files changed, 20 insertions, 36 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 0aef4e1392..f4ecc001e8 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1821,11 +1821,11 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: const dst_ty = self.air.typeOfIndex(inst); const air_tags = self.air.instructions.items(.tag); switch (air_tags[inst]) { - .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), - .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, dst_mcv, src_mcv), - .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, src_mcv), - .sub, .subwrap => try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, src_mcv), - .xor, .not => try self.genBinMathOpMir(.xor, dst_ty, dst_mcv, src_mcv), + .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, .unsigned, dst_mcv, src_mcv), + .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, .unsigned, dst_mcv, src_mcv), + .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, .unsigned, dst_mcv, src_mcv), + .sub, .subwrap => try self.genBinMathOpMir(.sub, dst_ty, .unsigned, dst_mcv, src_mcv), + .xor, .not => try self.genBinMathOpMir(.xor, dst_ty, .unsigned, dst_mcv, src_mcv), .mul, .mulwrap => try self.genIMulOpMir(dst_ty, dst_mcv, src_mcv), else => unreachable, } @@ -1837,6 +1837,7 @@ fn genBinMathOpMir( self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, + signedness: std.builtin.Signedness, dst_mcv: MCValue, src_mcv: MCValue, ) !void { @@ -1856,11 +1857,16 @@ fn genBinMathOpMir( .ptr_stack_offset => unreachable, .ptr_embedded_in_code => unreachable, .register => |src_reg| { + // TODO think more carefully about this: is this actually correct? + const reg_size = if (mir_tag == .cmp and signedness == .signed) + @divExact(dst_reg.size(), 8) + else + @divExact(src_reg.size(), 8); _ = try self.addInst(.{ .tag = mir_tag, .ops = (Mir.Ops{ - .reg1 = registerAlias(dst_reg, @divExact(src_reg.size(), 8)), - .reg2 = src_reg, + .reg1 = registerAlias(dst_reg, reg_size), + .reg2 = registerAlias(src_reg, reg_size), }).encode(), .data = undefined, }); @@ -2446,7 +2452,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { // This instruction supports only signed 32-bit immediates at most. const src_mcv = try self.limitImmediateType(bin_op.rhs, i32); - try self.genBinMathOpMir(.cmp, ty, dst_mcv, src_mcv); + try self.genBinMathOpMir(.cmp, ty, signedness, dst_mcv, src_mcv); break :result switch (signedness) { .signed => MCValue{ .compare_flags_signed = op }, .unsigned => MCValue{ .compare_flags_unsigned = op }, @@ -2669,7 +2675,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { } fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { - try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 }); + try self.genBinMathOpMir(.cmp, ty, .unsigned, operand, MCValue{ .immediate = 0 }); return MCValue{ .compare_flags_unsigned = .eq }; } @@ -2686,7 +2692,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { return MCValue{ .immediate = 0 }; // always false } else if (!payload_type.hasCodeGenBits()) { if (err_type.abiSize(self.target.*) <= 8) { - try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 }); + try self.genBinMathOpMir(.cmp, err_type, .unsigned, operand, MCValue{ .immediate = 0 }); return MCValue{ .compare_flags_unsigned = .gt }; } else { return self.fail("TODO isErr for errors with size larger than register size", .{}); @@ -3378,7 +3384,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void else => unreachable, } }, - .compare_flags_unsigned => |op| { + .compare_flags_unsigned, + .compare_flags_signed, + => |op| { const tag: Mir.Inst.Tag = switch (op) { .gte, .gt, .lt, .lte => .cond_set_byte_above_below, .eq, .neq => .cond_set_byte_eq_ne, @@ -3400,10 +3408,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .data = undefined, }); }, - .compare_flags_signed => |op| { - _ = op; - return self.fail("TODO set register with compare flags value (signed)", .{}); - }, .immediate => |x| { // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit // register is the fastest way to zero a register. @@ -3441,7 +3445,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void _ = try self.addInst(.{ .tag = .movabs, .ops = (Mir.Ops{ - .reg1 = reg, + .reg1 = reg.to64(), }).encode(), .data = .{ .payload = payload }, }); diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index fba57424fe..d192288dc4 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -492,20 +492,6 @@ inline fn immOpSize(u_imm: u32) u8 { return 32; } -inline fn imm64OpSize(u_imm: u64) u8 { - const imm = @bitCast(i64, u_imm); - if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) { - return 8; - } - if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) { - return 16; - } - if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) { - return 32; - } - return 64; -} - fn mirArithScaleSrc(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); const scale = ops.flags; @@ -1485,9 +1471,6 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8), if (reg.lowId() != Register.rax.lowId()) { return error.RaxOperandExpected; } - if (reg.size() != imm64OpSize(moffs)) { - return error.OperandSizeMismatch; - } const opc = if (td) getOpCode(tag, .td, reg.size() == 8).? else @@ -1510,9 +1493,6 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8), } fn lowerToOiEnc(tag: Tag, reg: Register, imm: u64, code: *std.ArrayList(u8)) LoweringError!void { - if (reg.size() != imm64OpSize(imm)) { - return error.OperandSizeMismatch; - } const opc = getOpCode(tag, .oi, reg.size() == 8).?; const encoder = try Encoder.init(code, 10); if (reg.size() == 16) { |
