aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorDavid Rubin <daviru007@icloud.com>2024-04-16 16:39:31 -0700
committerDavid Rubin <daviru007@icloud.com>2024-05-11 02:17:24 -0700
commita30af172e8dc360cb0a71a5c4dfd904120555715 (patch)
treee43bb564776492b6fa18187b4a379a82be5cdbb1 /src/arch
parenta615fbc1f8330e455d02fdda5c6de257b0cde7f4 (diff)
downloadzig-a30af172e8dc360cb0a71a5c4dfd904120555715.tar.gz
zig-a30af172e8dc360cb0a71a5c4dfd904120555715.zip
riscv: math progress
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/riscv64/CodeGen.zig127
-rw-r--r--src/arch/riscv64/Encoding.zig6
-rw-r--r--src/arch/riscv64/Mir.zig2
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