| author | |
| committer | |
| log | d19b77d63f0d02ab9c0a0928391891ae4a77744c |
| tree | f32cd14c27295517503576ccb16caa46bccaf141 |
| parent | cc204e2365547c19f7c9e1a836a3ea8c18e3a6ea |
9 files changed, 179 insertions(+), 28 deletions(-)
lib/std/builtin.zig+9-1| ... | @@ -775,7 +775,15 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr | ... | @@ -775,7 +775,15 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr |
| 775 | } | 775 | } |
| 776 | 776 | ||
| 777 | if (builtin.zig_backend == .stage2_riscv64) { | 777 | if (builtin.zig_backend == .stage2_riscv64) { |
| 778 | unreachable; | 778 | asm volatile ("ecall" |
| 779 | : | ||
| 780 | : [number] "{a7}" (64), | ||
| 781 | [arg1] "{a0}" (1), | ||
| 782 | [arg2] "{a1}" (@intFromPtr(msg.ptr)), | ||
| 783 | [arg3] "{a2}" (msg.len), | ||
| 784 | : "memory" | ||
| 785 | ); | ||
| 786 | std.posix.exit(127); | ||
| 779 | } | 787 | } |
| 780 | 788 | ||
| 781 | switch (builtin.os.tag) { | 789 | switch (builtin.os.tag) { |
src/arch/riscv64/CodeGen.zig+25-5| ... | @@ -1513,7 +1513,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { | ... | @@ -1513,7 +1513,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { |
| 1513 | }, | 1513 | }, |
| 1514 | else => unreachable, | 1514 | else => unreachable, |
| 1515 | }, | 1515 | }, |
| 1516 | else => break, | 1516 | else => return self.fail("TODO: splitType class {}", .{class}), |
| 1517 | }; | 1517 | }; |
| 1518 | } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts; | 1518 | } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts; |
| 1519 | return self.fail("TODO implement splitType for {}", .{ty.fmt(zcu)}); | 1519 | return self.fail("TODO implement splitType for {}", .{ty.fmt(zcu)}); |
| ... | @@ -3434,6 +3434,8 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3434,6 +3434,8 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3434 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { | 3434 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 3435 | const src_mcv = self.args[arg_index]; | 3435 | const src_mcv = self.args[arg_index]; |
| 3436 | 3436 | ||
| 3437 | const arg_ty = self.typeOfIndex(inst); | ||
| 3438 | |||
| 3437 | const dst_mcv = switch (src_mcv) { | 3439 | const dst_mcv = switch (src_mcv) { |
| 3438 | .register => dst: { | 3440 | .register => dst: { |
| 3439 | const frame = try self.allocFrameIndex(FrameAlloc.init(.{ | 3441 | const frame = try self.allocFrameIndex(FrameAlloc.init(.{ |
| ... | @@ -3441,9 +3443,16 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3441,9 +3443,16 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3441 | .alignment = Type.usize.abiAlignment(zcu), | 3443 | .alignment = Type.usize.abiAlignment(zcu), |
| 3442 | })); | 3444 | })); |
| 3443 | const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } }; | 3445 | const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } }; |
| 3444 | |||
| 3445 | try self.genCopy(Type.usize, dst_mcv, src_mcv); | 3446 | try self.genCopy(Type.usize, dst_mcv, src_mcv); |
| 3446 | 3447 | break :dst dst_mcv; | |
| 3448 | }, | ||
| 3449 | .register_pair => dst: { | ||
| 3450 | const frame = try self.allocFrameIndex(FrameAlloc.init(.{ | ||
| 3451 | .size = Type.usize.abiSize(zcu) * 2, | ||
| 3452 | .alignment = Type.usize.abiAlignment(zcu), | ||
| 3453 | })); | ||
| 3454 | const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } }; | ||
| 3455 | try self.genCopy(arg_ty, dst_mcv, src_mcv); | ||
| 3447 | break :dst dst_mcv; | 3456 | break :dst dst_mcv; |
| 3448 | }, | 3457 | }, |
| 3449 | .load_frame => src_mcv, | 3458 | .load_frame => src_mcv, |
| ... | @@ -4506,6 +4515,17 @@ fn genSetStack( | ... | @@ -4506,6 +4515,17 @@ fn genSetStack( |
| 4506 | else => unreachable, // register can hold a max of 8 bytes | 4515 | else => unreachable, // register can hold a max of 8 bytes |
| 4507 | } | 4516 | } |
| 4508 | }, | 4517 | }, |
| 4518 | .register_pair => |pair| { | ||
| 4519 | var part_disp: i32 = frame.off; | ||
| 4520 | for (try self.splitType(ty), pair) |src_ty, src_reg| { | ||
| 4521 | try self.genSetStack( | ||
| 4522 | src_ty, | ||
| 4523 | .{ .index = frame.index, .off = part_disp }, | ||
| 4524 | .{ .register = src_reg }, | ||
| 4525 | ); | ||
| 4526 | part_disp += @intCast(src_ty.abiSize(zcu)); | ||
| 4527 | } | ||
| 4528 | }, | ||
| 4509 | .load_frame, | 4529 | .load_frame, |
| 4510 | .indirect, | 4530 | .indirect, |
| 4511 | .load_symbol, | 4531 | .load_symbol, |
| ... | @@ -4564,8 +4584,8 @@ fn genInlineMemcpy( | ... | @@ -4564,8 +4584,8 @@ fn genInlineMemcpy( |
| 4564 | .ops = .rri, | 4584 | .ops = .rri, |
| 4565 | .data = .{ | 4585 | .data = .{ |
| 4566 | .i_type = .{ | 4586 | .i_type = .{ |
| 4567 | .rd = tmp, | 4587 | .rd = dst, |
| 4568 | .rs1 = dst, | 4588 | .rs1 = tmp, |
| 4569 | .imm12 = Immediate.s(0), | 4589 | .imm12 = Immediate.s(0), |
| 4570 | }, | 4590 | }, |
| 4571 | }, | 4591 | }, |
src/arch/riscv64/Emit.zig+31-1| ... | @@ -41,7 +41,35 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -41,7 +41,35 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 41 | .offset = 0, | 41 | .offset = 0, |
| 42 | .enc = std.meta.activeTag(lowered_inst.encoding.data), | 42 | .enc = std.meta.activeTag(lowered_inst.encoding.data), |
| 43 | }), | 43 | }), |
| 44 | else => |x| return emit.fail("TODO: emitMir {s}", .{@tagName(x)}), | 44 | .load_symbol_reloc => |symbol| { |
| 45 | if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { | ||
| 46 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | ||
| 47 | const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index); | ||
| 48 | const sym = elf_file.symbol(sym_index); | ||
| 49 | |||
| 50 | var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20); | ||
| 51 | var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I); | ||
| 52 | |||
| 53 | if (sym.flags.needs_zig_got) { | ||
| 54 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | ||
| 55 | |||
| 56 | hi_r_type = Elf.R_ZIG_GOT_HI20; | ||
| 57 | lo_r_type = Elf.R_ZIG_GOT_LO12; | ||
| 58 | } | ||
| 59 | |||
| 60 | try atom_ptr.addReloc(elf_file, .{ | ||
| 61 | .r_offset = start_offset, | ||
| 62 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type, | ||
| 63 | .r_addend = 0, | ||
| 64 | }); | ||
| 65 | |||
| 66 | try atom_ptr.addReloc(elf_file, .{ | ||
| 67 | .r_offset = start_offset + 4, | ||
| 68 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type, | ||
| 69 | .r_addend = 0, | ||
| 70 | }); | ||
| 71 | } else return emit.fail("TODO: load_symbol_reloc non-ELF", .{}); | ||
| 72 | }, | ||
| 45 | }; | 73 | }; |
| 46 | } | 74 | } |
| 47 | std.debug.assert(lowered_relocs.len == 0); | 75 | std.debug.assert(lowered_relocs.len == 0); |
| ... | @@ -120,6 +148,7 @@ fn fixupRelocs(emit: *Emit) Error!void { | ... | @@ -120,6 +148,7 @@ fn fixupRelocs(emit: *Emit) Error!void { |
| 120 | 148 | ||
| 121 | switch (reloc.enc) { | 149 | switch (reloc.enc) { |
| 122 | .J => riscv_util.writeInstJ(code, @bitCast(disp)), | 150 | .J => riscv_util.writeInstJ(code, @bitCast(disp)), |
| 151 | .B => riscv_util.writeInstB(code, @bitCast(disp)), | ||
| 123 | else => return emit.fail("tried to reloc encoding type {s}", .{@tagName(reloc.enc)}), | 152 | else => return emit.fail("tried to reloc encoding type {s}", .{@tagName(reloc.enc)}), |
| 124 | } | 153 | } |
| 125 | } | 154 | } |
| ... | @@ -161,3 +190,4 @@ const Lower = @import("Lower.zig"); | ... | @@ -161,3 +190,4 @@ const Lower = @import("Lower.zig"); |
| 161 | const Mir = @import("Mir.zig"); | 190 | const Mir = @import("Mir.zig"); |
| 162 | const riscv_util = @import("../../link/riscv.zig"); | 191 | const riscv_util = @import("../../link/riscv.zig"); |
| 163 | const Encoding = @import("Encoding.zig"); | 192 | const Encoding = @import("Encoding.zig"); |
| 193 | const Elf = @import("../../link/Elf.zig"); |
src/arch/riscv64/Encoding.zig+39-9| ... | @@ -29,6 +29,9 @@ pub const Mnemonic = enum { | ... | @@ -29,6 +29,9 @@ pub const Mnemonic = enum { |
| 29 | // J Type | 29 | // J Type |
| 30 | jal, | 30 | jal, |
| 31 | 31 | ||
| 32 | // B Type | ||
| 33 | beq, | ||
| 34 | |||
| 32 | // System | 35 | // System |
| 33 | ecall, | 36 | ecall, |
| 34 | ebreak, | 37 | ebreak, |
| ... | @@ -58,7 +61,9 @@ pub const Mnemonic = enum { | ... | @@ -58,7 +61,9 @@ pub const Mnemonic = enum { |
| 58 | .sh => .{ .opcode = 0b0100011, .funct3 = 0b001, .funct7 = null }, | 61 | .sh => .{ .opcode = 0b0100011, .funct3 = 0b001, .funct7 = null }, |
| 59 | .sb => .{ .opcode = 0b0100011, .funct3 = 0b000, .funct7 = null }, | 62 | .sb => .{ .opcode = 0b0100011, .funct3 = 0b000, .funct7 = null }, |
| 60 | 63 | ||
| 61 | .jal => .{ .opcode = 0b1101111, .funct3 = null, .funct7 = null }, | 64 | .jal => .{ .opcode = 0b1101111, .funct3 = null, .funct7 = null }, |
| 65 | |||
| 66 | .beq => .{ .opcode = 0b1100011, .funct3 = 0b000, .funct7 = null }, | ||
| 62 | 67 | ||
| 63 | .ecall => .{ .opcode = 0b1110011, .funct3 = 0b000, .funct7 = null }, | 68 | .ecall => .{ .opcode = 0b1110011, .funct3 = 0b000, .funct7 = null }, |
| 64 | .ebreak => .{ .opcode = 0b1110011, .funct3 = 0b000, .funct7 = null }, | 69 | .ebreak => .{ .opcode = 0b1110011, .funct3 = 0b000, .funct7 = null }, |
| ... | @@ -107,6 +112,9 @@ pub const InstEnc = enum { | ... | @@ -107,6 +112,9 @@ pub const InstEnc = enum { |
| 107 | .jal, | 112 | .jal, |
| 108 | => .J, | 113 | => .J, |
| 109 | 114 | ||
| 115 | .beq, | ||
| 116 | => .B, | ||
| 117 | |||
| 110 | .ecall, | 118 | .ecall, |
| 111 | .ebreak, | 119 | .ebreak, |
| 112 | .unimp, | 120 | .unimp, |
| ... | @@ -114,15 +122,17 @@ pub const InstEnc = enum { | ... | @@ -114,15 +122,17 @@ pub const InstEnc = enum { |
| 114 | }; | 122 | }; |
| 115 | } | 123 | } |
| 116 | 124 | ||
| 117 | pub fn opsList(enc: InstEnc) [4]std.meta.FieldEnum(Operand) { | 125 | pub fn opsList(enc: InstEnc) [3]std.meta.FieldEnum(Operand) { |
| 118 | return switch (enc) { | 126 | return switch (enc) { |
| 119 | .R => .{ .reg, .reg, .reg, .none }, | 127 | // zig fmt: off |
| 120 | .I => .{ .reg, .reg, .imm, .none }, | 128 | .R => .{ .reg, .reg, .reg, }, |
| 121 | .S => .{ .reg, .reg, .imm, .none }, | 129 | .I => .{ .reg, .reg, .imm, }, |
| 122 | .B => .{ .imm, .reg, .reg, .imm }, | 130 | .S => .{ .reg, .reg, .imm, }, |
| 123 | .U => .{ .reg, .imm, .none, .none }, | 131 | .B => .{ .reg, .reg, .imm, }, |
| 124 | .J => .{ .reg, .imm, .none, .none }, | 132 | .U => .{ .reg, .imm, .none, }, |
| 125 | .system => .{ .none, .none, .none, .none }, | 133 | .J => .{ .reg, .imm, .none, }, |
| 134 | .system => .{ .none, .none, .none, }, | ||
| 135 | // zig fmt: on | ||
| 126 | }; | 136 | }; |
| 127 | } | 137 | } |
| 128 | }; | 138 | }; |
| ... | @@ -292,6 +302,26 @@ pub const Data = union(InstEnc) { | ... | @@ -292,6 +302,26 @@ pub const Data = union(InstEnc) { |
| 292 | }, | 302 | }, |
| 293 | }; | 303 | }; |
| 294 | }, | 304 | }, |
| 305 | .B => { | ||
| 306 | assert(ops.len == 3); | ||
| 307 | |||
| 308 | const umm = ops[2].imm.asBits(u13); | ||
| 309 | assert(umm % 4 == 0); // misaligned branch target | ||
| 310 | |||
| 311 | return .{ | ||
| 312 | .B = .{ | ||
| 313 | .rs1 = ops[0].reg.id(), | ||
| 314 | .rs2 = ops[1].reg.id(), | ||
| 315 | .imm1_4 = @truncate(umm >> 1), | ||
| 316 | .imm5_10 = @truncate(umm >> 5), | ||
| 317 | .imm11 = @truncate(umm >> 11), | ||
| 318 | .imm12 = @truncate(umm >> 12), | ||
| 319 | |||
| 320 | .opcode = enc.opcode, | ||
| 321 | .funct3 = enc.funct3.?, | ||
| 322 | }, | ||
| 323 | }; | ||
| 324 | }, | ||
| 295 | 325 | ||
| 296 | else => std.debug.panic("TODO: construct {s}", .{@tagName(inst_enc)}), | 326 | else => std.debug.panic("TODO: construct {s}", .{@tagName(inst_enc)}), |
| 297 | } | 327 | } |
src/arch/riscv64/Lower.zig+44-3| ... | @@ -31,7 +31,9 @@ pub const Reloc = struct { | ... | @@ -31,7 +31,9 @@ pub const Reloc = struct { |
| 31 | 31 | ||
| 32 | const Target = union(enum) { | 32 | const Target = union(enum) { |
| 33 | inst: Mir.Inst.Index, | 33 | inst: Mir.Inst.Index, |
| 34 | linker_reloc: bits.Symbol, | 34 | |
| 35 | /// Relocs the lowered_inst_index and the next one. | ||
| 36 | load_symbol_reloc: bits.Symbol, | ||
| 35 | }; | 37 | }; |
| 36 | }; | 38 | }; |
| 37 | 39 | ||
| ... | @@ -59,6 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -59,6 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 59 | .pseudo_dbg_prologue_end, | 61 | .pseudo_dbg_prologue_end, |
| 60 | .pseudo_dead, | 62 | .pseudo_dead, |
| 61 | => {}, | 63 | => {}, |
| 64 | |||
| 62 | .pseudo_load_rm, .pseudo_store_rm => { | 65 | .pseudo_load_rm, .pseudo_store_rm => { |
| 63 | const rm = inst.data.rm; | 66 | const rm = inst.data.rm; |
| 64 | 67 | ||
| ... | @@ -106,6 +109,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -106,6 +109,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 106 | .{ .imm = Immediate.s(0) }, | 109 | .{ .imm = Immediate.s(0) }, |
| 107 | }); | 110 | }); |
| 108 | }, | 111 | }, |
| 112 | |||
| 109 | .pseudo_ret => { | 113 | .pseudo_ret => { |
| 110 | try lower.emit(.jalr, &.{ | 114 | try lower.emit(.jalr, &.{ |
| 111 | .{ .reg = .zero }, | 115 | .{ .reg = .zero }, |
| ... | @@ -113,6 +117,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -113,6 +117,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 113 | .{ .imm = Immediate.s(0) }, | 117 | .{ .imm = Immediate.s(0) }, |
| 114 | }); | 118 | }); |
| 115 | }, | 119 | }, |
| 120 | |||
| 116 | .pseudo_j => { | 121 | .pseudo_j => { |
| 117 | try lower.emit(.jal, &.{ | 122 | try lower.emit(.jal, &.{ |
| 118 | .{ .reg = .zero }, | 123 | .{ .reg = .zero }, |
| ... | @@ -123,7 +128,38 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -123,7 +128,38 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 123 | .pseudo_spill_regs => try lower.pushPopRegList(true, inst.data.reg_list), | 128 | .pseudo_spill_regs => try lower.pushPopRegList(true, inst.data.reg_list), |
| 124 | .pseudo_restore_regs => try lower.pushPopRegList(false, inst.data.reg_list), | 129 | .pseudo_restore_regs => try lower.pushPopRegList(false, inst.data.reg_list), |
| 125 | 130 | ||
| 126 | else => return lower.fail("TODO: psuedo {s}", .{@tagName(inst.ops)}), | 131 | .pseudo_load_symbol => { |
| 132 | const payload = inst.data.payload; | ||
| 133 | const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data; | ||
| 134 | |||
| 135 | try lower.emit(.lui, &.{ | ||
| 136 | .{ .reg = @enumFromInt(data.register) }, | ||
| 137 | .{ .imm = lower.reloc(.{ .load_symbol_reloc = .{ | ||
| 138 | .atom_index = data.atom_index, | ||
| 139 | .sym_index = data.sym_index, | ||
| 140 | } }) }, | ||
| 141 | }); | ||
| 142 | |||
| 143 | // the above reloc implies this one | ||
| 144 | try lower.emit(.addi, &.{ | ||
| 145 | .{ .reg = @enumFromInt(data.register) }, | ||
| 146 | .{ .reg = @enumFromInt(data.register) }, | ||
| 147 | .{ .imm = Immediate.s(0) }, | ||
| 148 | }); | ||
| 149 | }, | ||
| 150 | |||
| 151 | .pseudo_lea_rm => { | ||
| 152 | const rm = inst.data.rm; | ||
| 153 | const frame = rm.m.toFrameLoc(lower.mir); | ||
| 154 | |||
| 155 | try lower.emit(.addi, &.{ | ||
| 156 | .{ .reg = rm.r }, | ||
| 157 | .{ .reg = frame.base }, | ||
| 158 | .{ .imm = Immediate.s(frame.disp) }, | ||
| 159 | }); | ||
| 160 | }, | ||
| 161 | |||
| 162 | else => return lower.fail("TODO Lower: psuedo {s}", .{@tagName(inst.ops)}), | ||
| 127 | }, | 163 | }, |
| 128 | } | 164 | } |
| 129 | 165 | ||
| ... | @@ -135,7 +171,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -135,7 +171,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 135 | 171 | ||
| 136 | fn generic(lower: *Lower, inst: Mir.Inst) Error!void { | 172 | fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 137 | const mnemonic = std.meta.stringToEnum(Encoding.Mnemonic, @tagName(inst.tag)) orelse { | 173 | const mnemonic = std.meta.stringToEnum(Encoding.Mnemonic, @tagName(inst.tag)) orelse { |
| 138 | return lower.fail("generic inst name {s}-{s} doesn't match with a mnemonic", .{ | 174 | return lower.fail("generic inst name '{s}' with op {s} doesn't match with a mnemonic", .{ |
| 139 | @tagName(inst.tag), | 175 | @tagName(inst.tag), |
| 140 | @tagName(inst.ops), | 176 | @tagName(inst.ops), |
| 141 | }); | 177 | }); |
| ... | @@ -151,6 +187,11 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { | ... | @@ -151,6 +187,11 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 151 | .{ .reg = inst.data.i_type.rs1 }, | 187 | .{ .reg = inst.data.i_type.rs1 }, |
| 152 | .{ .imm = inst.data.i_type.imm12 }, | 188 | .{ .imm = inst.data.i_type.imm12 }, |
| 153 | }, | 189 | }, |
| 190 | .rr_inst => &.{ | ||
| 191 | .{ .reg = inst.data.b_type.rs1 }, | ||
| 192 | .{ .reg = inst.data.b_type.rs2 }, | ||
| 193 | .{ .imm = lower.reloc(.{ .inst = inst.data.b_type.inst }) }, | ||
| 194 | }, | ||
| 154 | else => return lower.fail("TODO: generic lower ops {s}", .{@tagName(inst.ops)}), | 195 | else => return lower.fail("TODO: generic lower ops {s}", .{@tagName(inst.ops)}), |
| 155 | }); | 196 | }); |
| 156 | } | 197 | } |
src/arch/riscv64/bits.zig+13-5| ... | @@ -65,17 +65,25 @@ pub const Memory = struct { | ... | @@ -65,17 +65,25 @@ pub const Memory = struct { |
| 65 | 65 | ||
| 66 | /// Asserts `mem` can be represented as a `FrameLoc`. | 66 | /// Asserts `mem` can be represented as a `FrameLoc`. |
| 67 | pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc { | 67 | pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc { |
| 68 | const offset: i32 = switch (mem.mod) { | ||
| 69 | .off => |off| @intCast(off), | ||
| 70 | .rm => |rm| rm.disp, | ||
| 71 | }; | ||
| 72 | |||
| 68 | switch (mem.base) { | 73 | switch (mem.base) { |
| 69 | .reg => |reg| { | 74 | .reg => |reg| { |
| 70 | return .{ | 75 | return .{ |
| 71 | .base = reg, | 76 | .base = reg, |
| 72 | .disp = switch (mem.mod) { | 77 | .disp = offset, |
| 73 | .off => unreachable, // TODO: toFrameLoc disp.off | 78 | }; |
| 74 | .rm => |rm| rm.disp, | 79 | }, |
| 75 | }, | 80 | .frame => |index| { |
| 81 | const base_loc = mir.frame_locs.get(@intFromEnum(index)); | ||
| 82 | return .{ | ||
| 83 | .base = base_loc.base, | ||
| 84 | .disp = base_loc.disp + offset, | ||
| 76 | }; | 85 | }; |
| 77 | }, | 86 | }, |
| 78 | .frame => |index| return mir.frame_locs.get(@intFromEnum(index)), | ||
| 79 | .reloc => unreachable, | 87 | .reloc => unreachable, |
| 80 | } | 88 | } |
| 81 | } | 89 | } |
src/arch/riscv64/encoder.zig+3-3| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | pub const Instruction = struct { | 1 | pub const Instruction = struct { |
| 2 | encoding: Encoding, | 2 | encoding: Encoding, |
| 3 | ops: [4]Operand = .{.none} ** 4, | 3 | ops: [3]Operand = .{.none} ** 3, |
| 4 | 4 | ||
| 5 | pub const Operand = union(enum) { | 5 | pub const Operand = union(enum) { |
| 6 | none, | 6 | none, |
| ... | @@ -11,7 +11,7 @@ pub const Instruction = struct { | ... | @@ -11,7 +11,7 @@ pub const Instruction = struct { |
| 11 | 11 | ||
| 12 | pub fn new(mnemonic: Encoding.Mnemonic, ops: []const Operand) !Instruction { | 12 | pub fn new(mnemonic: Encoding.Mnemonic, ops: []const Operand) !Instruction { |
| 13 | const encoding = (try Encoding.findByMnemonic(mnemonic, ops)) orelse { | 13 | const encoding = (try Encoding.findByMnemonic(mnemonic, ops)) orelse { |
| 14 | log.err("no encoding found for: {s} {s} {s} {s} {s}", .{ | 14 | std.log.err("no encoding found for: {s} {s} {s} {s} {s}", .{ |
| 15 | @tagName(mnemonic), | 15 | @tagName(mnemonic), |
| 16 | @tagName(if (ops.len > 0) ops[0] else .none), | 16 | @tagName(if (ops.len > 0) ops[0] else .none), |
| 17 | @tagName(if (ops.len > 1) ops[1] else .none), | 17 | @tagName(if (ops.len > 1) ops[1] else .none), |
| ... | @@ -21,7 +21,7 @@ pub const Instruction = struct { | ... | @@ -21,7 +21,7 @@ pub const Instruction = struct { |
| 21 | return error.InvalidInstruction; | 21 | return error.InvalidInstruction; |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | var result_ops: [4]Operand = .{.none} ** 4; | 24 | var result_ops: [3]Operand = .{.none} ** 3; |
| 25 | @memcpy(result_ops[0..ops.len], ops); | 25 | @memcpy(result_ops[0..ops.len], ops); |
| 26 | 26 | ||
| 27 | return .{ | 27 | return .{ |
src/link/riscv.zig+14| ... | @@ -73,6 +73,20 @@ pub fn writeInstJ(code: *[4]u8, value: u32) void { | ... | @@ -73,6 +73,20 @@ pub fn writeInstJ(code: *[4]u8, value: u32) void { |
| 73 | mem.writeInt(u32, code, data.toU32(), .little); | 73 | mem.writeInt(u32, code, data.toU32(), .little); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | pub fn writeInstB(code: *[4]u8, value: u32) void { | ||
| 77 | var data = Encoding.Data{ | ||
| 78 | .B = mem.bytesToValue(std.meta.TagPayload( | ||
| 79 | Encoding.Data, | ||
| 80 | Encoding.Data.B, | ||
| 81 | ), code), | ||
| 82 | }; | ||
| 83 | data.B.imm1_4 = bitSlice(value, 4, 1); | ||
| 84 | data.B.imm5_10 = bitSlice(value, 10, 5); | ||
| 85 | data.B.imm11 = bitSlice(value, 11, 11); | ||
| 86 | data.B.imm12 = bitSlice(value, 12, 12); | ||
| 87 | mem.writeInt(u32, code, data.toU32(), .little); | ||
| 88 | } | ||
| 89 | |||
| 76 | fn bitSlice( | 90 | fn bitSlice( |
| 77 | value: anytype, | 91 | value: anytype, |
| 78 | comptime high: comptime_int, | 92 | comptime high: comptime_int, |
src/target.zig+1-1| ... | @@ -526,7 +526,7 @@ pub fn backendSupportsFeature( | ... | @@ -526,7 +526,7 @@ pub fn backendSupportsFeature( |
| 526 | feature: Feature, | 526 | feature: Feature, |
| 527 | ) bool { | 527 | ) bool { |
| 528 | return switch (feature) { | 528 | return switch (feature) { |
| 529 | .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64, | 529 | .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64 or cpu_arch == .riscv64, |
| 530 | .panic_unwrap_error => ofmt == .c or use_llvm, | 530 | .panic_unwrap_error => ofmt == .c or use_llvm, |
| 531 | .safety_check_formatted => ofmt == .c or use_llvm, | 531 | .safety_check_formatted => ofmt == .c or use_llvm, |
| 532 | .error_return_trace => use_llvm, | 532 | .error_return_trace => use_llvm, |