| author | |
| committer | |
| log | 28df64cba45595a201f8c2312656922a8c28a67c |
| tree | 13679895113da1e2fa0199e1b117060bbed880cf |
| parent | 060c475fcd358eb9d05d14ec9f1bb7bfc47e4423 |
- add the `abs` MIR instruction
- implement `@abs` by shifting to the right by `bits - 1`, and xoring.6 files changed, 54 insertions(+), 12 deletions(-)
lib/std/builtin.zig+1-3| ... | @@ -760,9 +760,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr | ... | @@ -760,9 +760,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr |
| 760 | @setCold(true); | 760 | @setCold(true); |
| 761 | 761 | ||
| 762 | // stage2_riscv64 backend doesn't support loops yet. | 762 | // stage2_riscv64 backend doesn't support loops yet. |
| 763 | if (builtin.zig_backend == .stage2_riscv64 or | 763 | if (builtin.zig_backend == .stage2_riscv64) { |
| 764 | builtin.cpu.arch == .riscv64) | ||
| 765 | { | ||
| 766 | unreachable; | 764 | unreachable; |
| 767 | } | 765 | } |
| 768 | 766 |
src/arch/riscv64/CodeGen.zig+37-3| ... | @@ -1385,8 +1385,44 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1385,8 +1385,44 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1385 | } | 1385 | } |
| 1386 | 1386 | ||
| 1387 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | 1387 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 1388 | const mod = self.bin_file.comp.module.?; | ||
| 1388 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 1389 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 1389 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch}); | 1390 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1391 | const ty = self.typeOf(ty_op.operand); | ||
| 1392 | const scalar_ty = ty.scalarType(mod); | ||
| 1393 | const operand = try self.resolveInst(ty_op.operand); | ||
| 1394 | |||
| 1395 | switch (scalar_ty.zigTypeTag(mod)) { | ||
| 1396 | .Int => if (ty.zigTypeTag(mod) == .Vector) { | ||
| 1397 | return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)}); | ||
| 1398 | } else { | ||
| 1399 | const int_bits = ty.intInfo(mod).bits; | ||
| 1400 | |||
| 1401 | if (int_bits > 32) { | ||
| 1402 | return self.fail("TODO: airAbs for larger than 32 bits", .{}); | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | // promote the src into a register | ||
| 1406 | const src_mcv = try self.copyToNewRegister(inst, operand); | ||
| 1407 | // temp register for shift | ||
| 1408 | const temp_reg = try self.register_manager.allocReg(inst, gp); | ||
| 1409 | |||
| 1410 | _ = try self.addInst(.{ | ||
| 1411 | .tag = .abs, | ||
| 1412 | .data = .{ | ||
| 1413 | .i_type = .{ | ||
| 1414 | .rs1 = src_mcv.register, | ||
| 1415 | .rd = temp_reg, | ||
| 1416 | .imm12 = @intCast(int_bits - 1), | ||
| 1417 | }, | ||
| 1418 | }, | ||
| 1419 | }); | ||
| 1420 | |||
| 1421 | break :result src_mcv; | ||
| 1422 | }, | ||
| 1423 | else => return self.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(mod)}), | ||
| 1424 | } | ||
| 1425 | }; | ||
| 1390 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1426 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1391 | } | 1427 | } |
| 1392 | 1428 | ||
| ... | @@ -1603,8 +1639,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1603,8 +1639,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1603 | self.register_manager.getRegAssumeFree(src_reg, inst); | 1639 | self.register_manager.getRegAssumeFree(src_reg, inst); |
| 1604 | break :dst src_mcv; | 1640 | break :dst src_mcv; |
| 1605 | }, | 1641 | }, |
| 1606 | // don't need to allocate anything, can just be used immediately. | ||
| 1607 | .stack_offset => src_mcv, | ||
| 1608 | else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), | 1642 | else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), |
| 1609 | }; | 1643 | }; |
| 1610 | 1644 |
src/arch/riscv64/Emit.zig+7| ... | @@ -58,6 +58,7 @@ pub fn emitMir( | ... | @@ -58,6 +58,7 @@ pub fn emitMir( |
| 58 | 58 | ||
| 59 | .addi => try emit.mirIType(inst), | 59 | .addi => try emit.mirIType(inst), |
| 60 | .jalr => try emit.mirIType(inst), | 60 | .jalr => try emit.mirIType(inst), |
| 61 | .abs => try emit.mirIType(inst), | ||
| 61 | 62 | ||
| 62 | .jal => try emit.mirJType(inst), | 63 | .jal => try emit.mirJType(inst), |
| 63 | 64 | ||
| ... | @@ -200,6 +201,12 @@ fn mirIType(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -200,6 +201,12 @@ fn mirIType(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 200 | 201 | ||
| 201 | .ldr_ptr_stack => try emit.writeInstruction(Instruction.add(i_type.rd, i_type.rs1, .sp)), | 202 | .ldr_ptr_stack => try emit.writeInstruction(Instruction.add(i_type.rd, i_type.rs1, .sp)), |
| 202 | 203 | ||
| 204 | .abs => { | ||
| 205 | try emit.writeInstruction(Instruction.sraiw(i_type.rd, i_type.rs1, @intCast(i_type.imm12))); | ||
| 206 | try emit.writeInstruction(Instruction.xor(i_type.rs1, i_type.rs1, i_type.rd)); | ||
| 207 | try emit.writeInstruction(Instruction.subw(i_type.rs1, i_type.rs1, i_type.rd)); | ||
| 208 | }, | ||
| 209 | |||
| 203 | else => unreachable, | 210 | else => unreachable, |
| 204 | } | 211 | } |
| 205 | } | 212 | } |
src/arch/riscv64/Mir.zig+3| ... | @@ -38,6 +38,9 @@ pub const Inst = struct { | ... | @@ -38,6 +38,9 @@ pub const Inst = struct { |
| 38 | /// Subtraction | 38 | /// Subtraction |
| 39 | sub, | 39 | sub, |
| 40 | 40 | ||
| 41 | /// Absolute Value, uses i_type payload. | ||
| 42 | abs, | ||
| 43 | |||
| 41 | jal, | 44 | jal, |
| 42 | /// Jumps. Uses `inst` payload. | 45 | /// Jumps. Uses `inst` payload. |
| 43 | j, | 46 | j, |
src/arch/riscv64/bits.zig+5-5| ... | @@ -250,7 +250,7 @@ pub const Instruction = union(enum) { | ... | @@ -250,7 +250,7 @@ pub const Instruction = union(enum) { |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | pub fn srai(rd: Register, r1: Register, shamt: u6) Instruction { | 252 | pub fn srai(rd: Register, r1: Register, shamt: u6) Instruction { |
| 253 | return iType(0b0010011, 0b101, rd, r1, (1 << 10) + shamt); | 253 | return iType(0b0010011, 0b101, rd, r1, (@as(i12, 1) << 10) + shamt); |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | pub fn slti(rd: Register, r1: Register, imm: i12) Instruction { | 256 | pub fn slti(rd: Register, r1: Register, imm: i12) Instruction { |
| ... | @@ -267,16 +267,16 @@ pub const Instruction = union(enum) { | ... | @@ -267,16 +267,16 @@ pub const Instruction = union(enum) { |
| 267 | return iType(0b0011011, 0b000, rd, r1, imm); | 267 | return iType(0b0011011, 0b000, rd, r1, imm); |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | pub fn slliw(rd: Register, r1: Register, shamt: u5) Instruction { | 270 | pub fn slliw(rd: Register, r1: Register, shamt: u6) Instruction { |
| 271 | return iType(0b0011011, 0b001, rd, r1, shamt); | 271 | return iType(0b0011011, 0b001, rd, r1, shamt); |
| 272 | } | 272 | } |
| 273 | 273 | ||
| 274 | pub fn srliw(rd: Register, r1: Register, shamt: u5) Instruction { | 274 | pub fn srliw(rd: Register, r1: Register, shamt: u6) Instruction { |
| 275 | return iType(0b0011011, 0b101, rd, r1, shamt); | 275 | return iType(0b0011011, 0b101, rd, r1, shamt); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | pub fn sraiw(rd: Register, r1: Register, shamt: u5) Instruction { | 278 | pub fn sraiw(rd: Register, r1: Register, shamt: u6) Instruction { |
| 279 | return iType(0b0011011, 0b101, rd, r1, (1 << 10) + shamt); | 279 | return iType(0b0011011, 0b101, rd, r1, (@as(i12, 1) << 10) + shamt); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | // Upper Immediate | 282 | // Upper Immediate |
src/target.zig+1-1| ... | @@ -507,7 +507,7 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken | ... | @@ -507,7 +507,7 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken |
| 507 | if (use_llvm) return .stage2_llvm; | 507 | if (use_llvm) return .stage2_llvm; |
| 508 | if (target.ofmt == .c) return .stage2_c; | 508 | if (target.ofmt == .c) return .stage2_c; |
| 509 | return switch (target.cpu.arch) { | 509 | return switch (target.cpu.arch) { |
| 510 | .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm, | 510 | .wasm32, .wasm64 => .stage2_wasm, |
| 511 | .arm, .armeb, .thumb, .thumbeb => .stage2_arm, | 511 | .arm, .armeb, .thumb, .thumbeb => .stage2_arm, |
| 512 | .x86_64 => .stage2_x86_64, | 512 | .x86_64 => .stage2_x86_64, |
| 513 | .x86 => .stage2_x86, | 513 | .x86 => .stage2_x86, |