| author | |
| committer | |
| log | 94a84e783e32169268809e4aa4bdbfdff92d81e9 |
| tree | 058f39b3608d1fbc0e360d45d6eaccf53a02067d |
| parent | 927706e6d0cf289be979bb6f12be6636c0e07f59 |
3 files changed, 162 insertions(+), 3 deletions(-)
src/arch/sparcv9/CodeGen.zig+101-1| ... | ... | @@ -382,9 +382,109 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, is_caller: bool) !Ca |
| 382 | 382 | |
| 383 | 383 | /// Caller must call `CallMCValues.deinit`. |
| 384 | 384 | fn gen(self: *Self) !void { |
| 385 | const cc = self.fn_type.fnCallingConvention(); | |
| 386 | if (cc != .Naked) { | |
| 387 | // TODO Finish function prologue and epilogue for sparcv9. | |
| 388 | ||
| 389 | // TODO Backpatch stack offset | |
| 390 | // save %sp, -176, %sp | |
| 391 | _ = try self.addInst(.{ | |
| 392 | .tag = .save, | |
| 393 | .data = .{ | |
| 394 | .arithmetic_3op = .{ | |
| 395 | .is_imm = true, | |
| 396 | .rd = .sp, | |
| 397 | .rs1 = .sp, | |
| 398 | .rs2_or_imm = .{ .imm = -176 }, | |
| 399 | }, | |
| 400 | }, | |
| 401 | }); | |
| 402 | ||
| 403 | _ = try self.addInst(.{ | |
| 404 | .tag = .dbg_prologue_end, | |
| 405 | .data = .{ .nop = {} }, | |
| 406 | }); | |
| 407 | ||
| 408 | try self.genBody(self.air.getMainBody()); | |
| 409 | ||
| 410 | _ = try self.addInst(.{ | |
| 411 | .tag = .dbg_epilogue_begin, | |
| 412 | .data = .{ .nop = {} }, | |
| 413 | }); | |
| 414 | ||
| 415 | // exitlude jumps | |
| 416 | if (self.exitlude_jump_relocs.items.len > 0 and | |
| 417 | self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2) | |
| 418 | { | |
| 419 | // If the last Mir instruction (apart from the | |
| 420 | // dbg_epilogue_begin) is the last exitlude jump | |
| 421 | // relocation (which would just jump one instruction | |
| 422 | // further), it can be safely removed | |
| 423 | self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop()); | |
| 424 | } | |
| 425 | ||
| 426 | for (self.exitlude_jump_relocs.items) |jmp_reloc| { | |
| 427 | _ = jmp_reloc; | |
| 428 | return self.fail("TODO add branches in sparcv9", .{}); | |
| 429 | } | |
| 430 | ||
| 431 | // return %i7 + 8 | |
| 432 | _ = try self.addInst(.{ | |
| 433 | .tag = .@"return", | |
| 434 | .data = .{ | |
| 435 | .arithmetic_2op = .{ | |
| 436 | .is_imm = true, | |
| 437 | .rs1 = .@"i7", | |
| 438 | .rs2_or_imm = .{ .imm = 8 }, | |
| 439 | }, | |
| 440 | }, | |
| 441 | }); | |
| 442 | ||
| 443 | // TODO Find a way to fill this slot | |
| 444 | // nop | |
| 445 | _ = try self.addInst(.{ | |
| 446 | .tag = .nop, | |
| 447 | .data = .{ .nop = {} }, | |
| 448 | }); | |
| 449 | } else { | |
| 450 | _ = try self.addInst(.{ | |
| 451 | .tag = .dbg_prologue_end, | |
| 452 | .data = .{ .nop = {} }, | |
| 453 | }); | |
| 454 | ||
| 455 | try self.genBody(self.air.getMainBody()); | |
| 456 | ||
| 457 | _ = try self.addInst(.{ | |
| 458 | .tag = .dbg_epilogue_begin, | |
| 459 | .data = .{ .nop = {} }, | |
| 460 | }); | |
| 461 | } | |
| 462 | ||
| 463 | // Drop them off at the rbrace. | |
| 464 | _ = try self.addInst(.{ | |
| 465 | .tag = .dbg_line, | |
| 466 | .data = .{ .dbg_line_column = .{ | |
| 467 | .line = self.end_di_line, | |
| 468 | .column = self.end_di_column, | |
| 469 | } }, | |
| 470 | }); | |
| 471 | } | |
| 472 | ||
| 473 | fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | |
| 385 | 474 | _ = self; |
| 475 | _ = body; | |
| 476 | ||
| 477 | @panic("TODO implement genBody"); | |
| 478 | } | |
| 479 | ||
| 480 | fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { | |
| 481 | const gpa = self.gpa; | |
| 482 | ||
| 483 | try self.mir_instructions.ensureUnusedCapacity(gpa, 1); | |
| 386 | 484 | |
| 387 | @panic("TODO implement gen"); | |
| 485 | const result_index = @intCast(Air.Inst.Index, self.mir_instructions.len); | |
| 486 | self.mir_instructions.appendAssumeCapacity(inst); | |
| 487 | return result_index; | |
| 388 | 488 | } |
| 389 | 489 | |
| 390 | 490 | fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { |
src/arch/sparcv9/Emit.zig+15-1| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | //! machine code |
| 3 | 3 | |
| 4 | 4 | const std = @import("std"); |
| 5 | const assert = std.debug.assert; | |
| 5 | 6 | const link = @import("../../link.zig"); |
| 6 | 7 | const Module = @import("../../Module.zig"); |
| 7 | 8 | const ErrorMsg = Module.ErrorMsg; |
| ... | ... | @@ -41,9 +42,15 @@ pub fn emitMir( |
| 41 | 42 | const inst = @intCast(u32, index); |
| 42 | 43 | switch (tag) { |
| 43 | 44 | .dbg_line => try emit.mirDbgLine(inst), |
| 44 | ||
| 45 | 45 | .dbg_prologue_end => try emit.mirDebugPrologueEnd(), |
| 46 | 46 | .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(), |
| 47 | ||
| 48 | .nop => @panic("TODO implement nop"), | |
| 49 | ||
| 50 | .save => @panic("TODO implement save"), | |
| 51 | .restore => @panic("TODO implement restore"), | |
| 52 | ||
| 53 | .@"return" => @panic("TODO implement return"), | |
| 47 | 54 | } |
| 48 | 55 | } |
| 49 | 56 | } |
| ... | ... | @@ -91,3 +98,10 @@ fn mirDebugEpilogueBegin(self: *Emit) !void { |
| 91 | 98 | .none => {}, |
| 92 | 99 | } |
| 93 | 100 | } |
| 101 | ||
| 102 | fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { | |
| 103 | @setCold(true); | |
| 104 | assert(emit.err_msg == null); | |
| 105 | emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args); | |
| 106 | return error.EmitFail; | |
| 107 | } |
src/arch/sparcv9/Mir.zig+46-1| ... | ... | @@ -29,6 +29,22 @@ pub const Inst = struct { |
| 29 | 29 | dbg_epilogue_begin, |
| 30 | 30 | /// Pseudo-instruction: Update debug line |
| 31 | 31 | dbg_line, |
| 32 | ||
| 33 | // All the real instructions are ordered by their section number | |
| 34 | // in The SPARC Architecture Manual, Version 9. | |
| 35 | ||
| 36 | /// A.40 No Operation | |
| 37 | /// It uses the nop field. | |
| 38 | nop, | |
| 39 | ||
| 40 | /// A.46 SAVE and RESTORE | |
| 41 | /// Those uses the arithmetic_3op field. | |
| 42 | save, | |
| 43 | restore, | |
| 44 | ||
| 45 | /// A.45 RETURN | |
| 46 | /// It uses the arithmetic_2op field. | |
| 47 | @"return", | |
| 32 | 48 | }; |
| 33 | 49 | |
| 34 | 50 | /// The position of an MIR instruction within the `Mir` instructions array. |
| ... | ... | @@ -42,6 +58,36 @@ pub const Inst = struct { |
| 42 | 58 | /// |
| 43 | 59 | /// Used by e.g. flushw |
| 44 | 60 | nop: void, |
| 61 | ||
| 62 | /// Three operand arithmetic. | |
| 63 | /// if is_imm true then it uses the imm field of rs2_or_imm, | |
| 64 | /// otherwise it uses rs2 field. | |
| 65 | /// | |
| 66 | /// Used by e.g. add, sub | |
| 67 | arithmetic_3op: struct { | |
| 68 | is_imm: bool, | |
| 69 | rd: Register, | |
| 70 | rs1: Register, | |
| 71 | rs2_or_imm: union { | |
| 72 | rs2: Register, | |
| 73 | imm: i13, | |
| 74 | }, | |
| 75 | }, | |
| 76 | ||
| 77 | /// Two operand arithmetic. | |
| 78 | /// if is_imm true then it uses the imm field of rs2_or_imm, | |
| 79 | /// otherwise it uses rs2 field. | |
| 80 | /// | |
| 81 | /// Used by e.g. return | |
| 82 | arithmetic_2op: struct { | |
| 83 | is_imm: bool, | |
| 84 | rs1: Register, | |
| 85 | rs2_or_imm: union { | |
| 86 | rs2: Register, | |
| 87 | imm: i13, | |
| 88 | }, | |
| 89 | }, | |
| 90 | ||
| 45 | 91 | /// Debug info: line and column |
| 46 | 92 | /// |
| 47 | 93 | /// Used by e.g. dbg_line |
| ... | ... | @@ -77,4 +123,3 @@ pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end |
| 77 | 123 | .end = i, |
| 78 | 124 | }; |
| 79 | 125 | } |
| 80 |