| 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 | 760 | @setCold(true); |
| 761 | 761 | |
| 762 | 762 | // stage2_riscv64 backend doesn't support loops yet. |
| 763 | if (builtin.zig_backend == .stage2_riscv64 or | |
| 764 | builtin.cpu.arch == .riscv64) | |
| 765 | { | |
| 763 | if (builtin.zig_backend == .stage2_riscv64) { | |
| 766 | 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 | 1385 | } |
| 1386 | 1386 | |
| 1387 | 1387 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 1388 | const mod = self.bin_file.comp.module.?; | |
| 1388 | 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 | 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 | 1639 | self.register_manager.getRegAssumeFree(src_reg, inst); |
| 1604 | 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 | 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 | 58 | |
| 59 | 59 | .addi => try emit.mirIType(inst), |
| 60 | 60 | .jalr => try emit.mirIType(inst), |
| 61 | .abs => try emit.mirIType(inst), | |
| 61 | 62 | |
| 62 | 63 | .jal => try emit.mirJType(inst), |
| 63 | 64 | |
| ... | ... | @@ -200,6 +201,12 @@ fn mirIType(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 200 | 201 | |
| 201 | 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 | 210 | else => unreachable, |
| 204 | 211 | } |
| 205 | 212 | } |
src/arch/riscv64/Mir.zig+3| ... | ... | @@ -38,6 +38,9 @@ pub const Inst = struct { |
| 38 | 38 | /// Subtraction |
| 39 | 39 | sub, |
| 40 | 40 | |
| 41 | /// Absolute Value, uses i_type payload. | |
| 42 | abs, | |
| 43 | ||
| 41 | 44 | jal, |
| 42 | 45 | /// Jumps. Uses `inst` payload. |
| 43 | 46 | j, |
src/arch/riscv64/bits.zig+5-5| ... | ... | @@ -250,7 +250,7 @@ pub const Instruction = union(enum) { |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 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 | 256 | pub fn slti(rd: Register, r1: Register, imm: i12) Instruction { |
| ... | ... | @@ -267,16 +267,16 @@ pub const Instruction = union(enum) { |
| 267 | 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 | 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 | 275 | return iType(0b0011011, 0b101, rd, r1, shamt); |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | pub fn sraiw(rd: Register, r1: Register, shamt: u5) Instruction { | |
| 279 | return iType(0b0011011, 0b101, rd, r1, (1 << 10) + shamt); | |
| 278 | pub fn sraiw(rd: Register, r1: Register, shamt: u6) Instruction { | |
| 279 | return iType(0b0011011, 0b101, rd, r1, (@as(i12, 1) << 10) + shamt); | |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | 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 | 507 | if (use_llvm) return .stage2_llvm; |
| 508 | 508 | if (target.ofmt == .c) return .stage2_c; |
| 509 | 509 | return switch (target.cpu.arch) { |
| 510 | .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm, | |
| 510 | .wasm32, .wasm64 => .stage2_wasm, | |
| 511 | 511 | .arm, .armeb, .thumb, .thumbeb => .stage2_arm, |
| 512 | 512 | .x86_64 => .stage2_x86_64, |
| 513 | 513 | .x86 => .stage2_x86, |