diff options
| author | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-08-04 21:05:11 +0200 |
|---|---|---|
| committer | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-08-05 20:30:51 +0200 |
| commit | 8b24c783c5bd417f84beeb2f3736a78c3f595d22 (patch) | |
| tree | 460fd5b85032a6a71c60f3bf7fa2056b0c83c86c /src | |
| parent | dcb236acf432c1d772b2f7d65074735eeae4c4c2 (diff) | |
| download | zig-8b24c783c5bd417f84beeb2f3736a78c3f595d22.tar.gz zig-8b24c783c5bd417f84beeb2f3736a78c3f595d22.zip | |
stage2 AArch64: implement basic integer division
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 132 | ||||
| -rw-r--r-- | src/arch/aarch64/Emit.zig | 12 | ||||
| -rw-r--r-- | src/arch/aarch64/Mir.zig | 4 | ||||
| -rw-r--r-- | src/arch/aarch64/bits.zig | 8 |
4 files changed, 110 insertions, 46 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index c30b8d97b3..37c3721709 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -561,33 +561,38 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { switch (air_tags[inst]) { // zig fmt: off - .add => try self.airBinOp(inst, .add), - .addwrap => try self.airBinOp(inst, .addwrap), - .sub => try self.airBinOp(inst, .sub), - .subwrap => try self.airBinOp(inst, .subwrap), - .mul => try self.airBinOp(inst, .mul), - .mulwrap => try self.airBinOp(inst, .mulwrap), - .shl => try self.airBinOp(inst, .shl), - .shl_exact => try self.airBinOp(inst, .shl_exact), - .bool_and => try self.airBinOp(inst, .bool_and), - .bool_or => try self.airBinOp(inst, .bool_or), - .bit_and => try self.airBinOp(inst, .bit_and), - .bit_or => try self.airBinOp(inst, .bit_or), - .xor => try self.airBinOp(inst, .xor), - .shr => try self.airBinOp(inst, .shr), - .shr_exact => try self.airBinOp(inst, .shr_exact), - - .ptr_add => try self.airPtrArithmetic(inst, .ptr_add), - .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub), + .add => try self.airBinOp(inst, .add), + .addwrap => try self.airBinOp(inst, .addwrap), + .sub => try self.airBinOp(inst, .sub), + .subwrap => try self.airBinOp(inst, .subwrap), + .mul => try self.airBinOp(inst, .mul), + .mulwrap => try self.airBinOp(inst, .mulwrap), + .shl => try self.airBinOp(inst, .shl), + .shl_exact => try self.airBinOp(inst, .shl_exact), + .bool_and => try self.airBinOp(inst, .bool_and), + .bool_or => try self.airBinOp(inst, .bool_or), + .bit_and => try self.airBinOp(inst, .bit_and), + .bit_or => try self.airBinOp(inst, .bit_or), + .xor => try self.airBinOp(inst, .xor), + .shr => try self.airBinOp(inst, .shr), + .shr_exact => try self.airBinOp(inst, .shr_exact), + .div_float => try self.airBinOp(inst, .div_float), + .div_trunc => try self.airBinOp(inst, .div_trunc), + .div_floor => try self.airBinOp(inst, .div_floor), + .div_exact => try self.airBinOp(inst, .div_exact), + .rem => try self.airBinOp(inst, .rem), + .mod => try self.airBinOp(inst, .mod), + + .ptr_add => try self.airPtrArithmetic(inst, .ptr_add), + .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub), + + .min => try self.airMin(inst), + .max => try self.airMax(inst), .add_sat => try self.airAddSat(inst), .sub_sat => try self.airSubSat(inst), .mul_sat => try self.airMulSat(inst), - .rem => try self.airRem(inst), - .mod => try self.airMod(inst), .shl_sat => try self.airShlSat(inst), - .min => try self.airMin(inst), - .max => try self.airMax(inst), .slice => try self.airSlice(inst), .sqrt, @@ -612,8 +617,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .mul_with_overflow => try self.airMulWithOverflow(inst), .shl_with_overflow => try self.airShlWithOverflow(inst), - .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst), - .cmp_lt => try self.airCmp(inst, .lt), .cmp_lte => try self.airCmp(inst, .lte), .cmp_eq => try self.airCmp(inst, .eq), @@ -1391,6 +1394,8 @@ fn binOpRegister( .lsl_register, .asr_register, .lsr_register, + .sdiv, + .udiv, => .{ .rrr = .{ .rd = dest_reg, .rn = lhs_reg, @@ -1629,6 +1634,67 @@ fn binOp( else => unreachable, } }, + .div_float => { + switch (lhs_ty.zigTypeTag()) { + .Float => return self.fail("TODO div_float", .{}), + .Vector => return self.fail("TODO div_float on vectors", .{}), + else => unreachable, + } + }, + .div_trunc, .div_floor, .div_exact => { + switch (lhs_ty.zigTypeTag()) { + .Float => return self.fail("TODO div on floats", .{}), + .Vector => return self.fail("TODO div on vectors", .{}), + .Int => { + assert(lhs_ty.eql(rhs_ty, mod)); + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 64) { + switch (int_info.signedness) { + .signed => { + switch (tag) { + .div_trunc, .div_exact => { + // TODO optimize integer division by constants + return try self.binOpRegister(.sdiv, lhs, rhs, lhs_ty, rhs_ty, metadata); + }, + .div_floor => return self.fail("TODO div_floor on signed integers", .{}), + else => unreachable, + } + }, + .unsigned => { + // TODO optimize integer division by constants + return try self.binOpRegister(.udiv, lhs, rhs, lhs_ty, rhs_ty, metadata); + }, + } + } else { + return self.fail("TODO integer division for ints with bits > 64", .{}); + } + }, + else => unreachable, + } + }, + .rem, .mod => { + switch (lhs_ty.zigTypeTag()) { + .Float => return self.fail("TODO rem/mod on floats", .{}), + .Vector => return self.fail("TODO rem/mod on vectors", .{}), + .Int => { + assert(lhs_ty.eql(rhs_ty, mod)); + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 32) { + switch (int_info.signedness) { + .signed => { + return self.fail("TODO rem/mod on signed integers", .{}); + }, + .unsigned => { + return self.fail("TODO rem/mod on unsigned integers", .{}); + }, + } + } else { + return self.fail("TODO rem/mod for integers with bits > 64", .{}); + } + }, + else => unreachable, + } + }, .addwrap, .subwrap, .mulwrap, @@ -2300,24 +2366,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); } -fn airDiv(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement div for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - -fn airRem(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - -fn airMod(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mod for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 1ca198ccd8..ba85730276 100644 --- a/src/arch/aarch64/Emit.zig +++ b/src/arch/aarch64/Emit.zig @@ -91,9 +91,11 @@ pub fn emitMir( .sub_immediate => try emit.mirAddSubtractImmediate(inst), .subs_immediate => try emit.mirAddSubtractImmediate(inst), - .asr_register => try emit.mirShiftRegister(inst), - .lsl_register => try emit.mirShiftRegister(inst), - .lsr_register => try emit.mirShiftRegister(inst), + .asr_register => try emit.mirDataProcessing2Source(inst), + .lsl_register => try emit.mirDataProcessing2Source(inst), + .lsr_register => try emit.mirDataProcessing2Source(inst), + .sdiv => try emit.mirDataProcessing2Source(inst), + .udiv => try emit.mirDataProcessing2Source(inst), .asr_immediate => try emit.mirShiftImmediate(inst), .lsl_immediate => try emit.mirShiftImmediate(inst), @@ -520,7 +522,7 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void { } } -fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void { +fn mirDataProcessing2Source(emit: *Emit, inst: Mir.Inst.Index) !void { const tag = emit.mir.instructions.items(.tag)[inst]; const rrr = emit.mir.instructions.items(.data)[inst].rrr; const rd = rrr.rd; @@ -531,6 +533,8 @@ fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void { .asr_register => try emit.writeInstruction(Instruction.asrRegister(rd, rn, rm)), .lsl_register => try emit.writeInstruction(Instruction.lslRegister(rd, rn, rm)), .lsr_register => try emit.writeInstruction(Instruction.lsrRegister(rd, rn, rm)), + .sdiv => try emit.writeInstruction(Instruction.sdiv(rd, rn, rm)), + .udiv => try emit.writeInstruction(Instruction.udiv(rd, rn, rm)), else => unreachable, } } diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig index c4d6af9db4..d1ba38a779 100644 --- a/src/arch/aarch64/Mir.zig +++ b/src/arch/aarch64/Mir.zig @@ -164,6 +164,8 @@ pub const Inst = struct { ret, /// Signed bitfield extract sbfx, + /// Signed divide + sdiv, /// Signed multiply high smulh, /// Signed multiply long @@ -212,6 +214,8 @@ pub const Inst = struct { tst_immediate, /// Unsigned bitfield extract ubfx, + /// Unsigned divide + udiv, /// Unsigned multiply high umulh, /// Unsigned multiply long diff --git a/src/arch/aarch64/bits.zig b/src/arch/aarch64/bits.zig index a3f5fbac51..ad45661b70 100644 --- a/src/arch/aarch64/bits.zig +++ b/src/arch/aarch64/bits.zig @@ -1698,6 +1698,14 @@ pub const Instruction = union(enum) { // Data processing (2 source) + pub fn udiv(rd: Register, rn: Register, rm: Register) Instruction { + return dataProcessing2Source(0b0, 0b000010, rd, rn, rm); + } + + pub fn sdiv(rd: Register, rn: Register, rm: Register) Instruction { + return dataProcessing2Source(0b0, 0b000011, rd, rn, rm); + } + pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction { return dataProcessing2Source(0b0, 0b001000, rd, rn, rm); } |
