diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 127 | ||||
| -rw-r--r-- | src/arch/riscv64/Encoding.zig | 6 | ||||
| -rw-r--r-- | src/arch/riscv64/Mir.zig | 2 |
3 files changed, 71 insertions, 64 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index de866b7964..7ed1174433 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -11,6 +11,7 @@ const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); const link = @import("../../link.zig"); const Module = @import("../../Module.zig"); +const Package = @import("../../Package.zig"); const InternPool = @import("../../InternPool.zig"); const Compilation = @import("../../Compilation.zig"); const ErrorMsg = Module.ErrorMsg; @@ -54,6 +55,7 @@ const RegisterView = enum(u1) { gpa: Allocator, air: Air, +mod: *Package.Module, liveness: Liveness, bin_file: *link.File, target: *const std.Target, @@ -724,6 +726,7 @@ pub fn generate( var function = Self{ .gpa = gpa, .air = air, + .mod = mod, .liveness = liveness, .target = target, .bin_file = bin_file, @@ -2138,82 +2141,78 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const lhs_ty = self.typeOf(extra.lhs); const rhs_ty = self.typeOf(extra.rhs); - const add_result_mcv = try self.binOp(.add, lhs, lhs_ty, rhs, rhs_ty); - const add_result_lock = self.register_manager.lockRegAssumeUnused(add_result_mcv.register); - defer self.register_manager.unlockReg(add_result_lock); - - const tuple_ty = self.typeOfIndex(inst); const int_info = lhs_ty.intInfo(zcu); - // TODO: optimization, set this to true. needs the other struct access stuff to support - // accessing registers. + const tuple_ty = self.typeOfIndex(inst); const result_mcv = try self.allocRegOrMem(inst, false); const offset = result_mcv.load_frame; - try self.genSetStack( - lhs_ty, - .{ - .index = offset.index, - .off = offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))), - }, - add_result_mcv, - ); - if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { - if (int_info.signedness == .unsigned) { - switch (int_info.bits) { - 1...8 => { - const max_val = std.math.pow(u16, 2, int_info.bits) - 1; + const add_result = try self.binOp(.add, lhs, lhs_ty, rhs, rhs_ty); + const add_result_reg = try self.copyToTmpRegister(lhs_ty, add_result); + const add_result_reg_lock = self.register_manager.lockRegAssumeUnused(add_result_reg); + defer self.register_manager.unlockReg(add_result_reg_lock); - const overflow_reg, const overflow_lock = try self.allocReg(); - defer self.register_manager.unlockReg(overflow_lock); + const shift_amount: u6 = @intCast(Type.usize.bitSize(zcu) - int_info.bits); - const add_reg, const add_lock = blk: { - if (add_result_mcv == .register) break :blk .{ add_result_mcv.register, null }; + const shift_reg, const shift_lock = try self.allocReg(); + defer self.register_manager.unlockReg(shift_lock); - const add_reg, const add_lock = try self.allocReg(); - try self.genSetReg(lhs_ty, add_reg, add_result_mcv); - break :blk .{ add_reg, add_lock }; - }; - defer if (add_lock) |lock| self.register_manager.unlockReg(lock); - - _ = try self.addInst(.{ - .tag = .andi, - .ops = .rri, - .data = .{ .i_type = .{ - .rd = overflow_reg, - .rs1 = add_reg, - .imm12 = Immediate.s(max_val), - } }, - }); - - const overflow_mcv = try self.binOp( - .cmp_neq, - .{ .register = overflow_reg }, - lhs_ty, - .{ .register = add_reg }, - lhs_ty, - ); - - try self.genSetStack( - Type.u1, - .{ - .index = offset.index, - .off = offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))), - }, - overflow_mcv, - ); + _ = try self.addInst(.{ + .tag = .slli, + .ops = .rri, + .data = .{ + .i_type = .{ + .rd = shift_reg, + .rs1 = add_result_reg, + .imm12 = Immediate.s(shift_amount), + }, + }, + }); - break :result result_mcv; + _ = try self.addInst(.{ + .tag = if (int_info.signedness == .unsigned) .srli else .srai, + .ops = .rri, + .data = .{ + .i_type = .{ + .rd = shift_reg, + .rs1 = shift_reg, + .imm12 = Immediate.s(shift_amount), }, + }, + }); - else => return self.fail("TODO: addWithOverflow check for size {d}", .{int_info.bits}), - } - } else { - return self.fail("TODO: airAddWithOverFlow calculate carry for signed addition", .{}); - } + const add_result_frame: FrameAddr = .{ + .index = offset.index, + .off = offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))), + }; + try self.genSetStack( + lhs_ty, + add_result_frame, + add_result, + ); + + const overflow_mcv = try self.binOp( + .cmp_neq, + .{ .register = shift_reg }, + lhs_ty, + .{ .register = add_result_reg }, + lhs_ty, + ); + + const overflow_frame: FrameAddr = .{ + .index = offset.index, + .off = offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))), + }; + try self.genSetStack( + Type.u1, + overflow_frame, + overflow_mcv, + ); + + break :result result_mcv; } else { - return self.fail("TODO: airAddWithOverflow with < 8 bits or non-pow of 2", .{}); + return self.fail("TODO: less than 8 bit or non-pow 2 addition", .{}); } }; @@ -3500,9 +3499,11 @@ fn genCall( if (self.bin_file.cast(link.File.Elf)) |elf_file| { const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); const sym = elf_file.symbol(sym_index); + _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); const got_addr = sym.zigGotAddress(elf_file); try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr }); + _ = try self.addInst(.{ .tag = .jalr, .ops = .rri, diff --git a/src/arch/riscv64/Encoding.zig b/src/arch/riscv64/Encoding.zig index c23ba10d9b..7953bb0cca 100644 --- a/src/arch/riscv64/Encoding.zig +++ b/src/arch/riscv64/Encoding.zig @@ -16,6 +16,7 @@ pub const Mnemonic = enum { andi, slli, srli, + srai, addi, jalr, @@ -69,6 +70,7 @@ pub const Mnemonic = enum { .jalr => .{ .opcode = 0b1100111, .funct3 = 0b000, .funct7 = null }, .slli => .{ .opcode = 0b0010011, .funct3 = 0b001, .funct7 = null }, .srli => .{ .opcode = 0b0010011, .funct3 = 0b101, .funct7 = null }, + .srai => .{ .opcode = 0b0010011, .funct3 = 0b101, .funct7 = null, .offset = 1 << 10 }, .lui => .{ .opcode = 0b0110111, .funct3 = null, .funct7 = null }, @@ -123,6 +125,7 @@ pub const InstEnc = enum { .andi, .slli, .srli, + .srai, => .I, .lui, @@ -299,7 +302,7 @@ pub const Data = union(InstEnc) { .I = .{ .rd = ops[0].reg.id(), .rs1 = ops[1].reg.id(), - .imm0_11 = ops[2].imm.asBits(u12), + .imm0_11 = ops[2].imm.asBits(u12) + enc.offset, .opcode = enc.opcode, .funct3 = enc.funct3.?, @@ -374,6 +377,7 @@ const Enc = struct { opcode: u7, funct3: ?u3, funct7: ?u7, + offset: u12 = 0, }; fn verifyOps(mnem: Mnemonic, ops: []const Operand) bool { diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig index 9ecca44bd8..08bda25de6 100644 --- a/src/arch/riscv64/Mir.zig +++ b/src/arch/riscv64/Mir.zig @@ -53,6 +53,8 @@ pub const Inst = struct { srli, /// Immediate Logical Left Shift, uses i_type payload slli, + /// Immediate Arithmetic Right Shift, uses i_type payload. + srai, /// Register Logical Left Shift, uses r_type payload sllw, /// Register Logical Right Shit, uses r_type payload |
