authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-10 11:06:29+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-14 22:18:06+07:00
log5e2045cbe549c9020ebbbecc763699fc4a68c818
tree41740ad177f355899d1517bbc8f549b5805c676a
parent42f4bd34216ae1ae03df0a56502919109e030136

stage2: sparcv9: Implement basic asm codegen


1 files changed, 113 insertions(+), 9 deletions(-)

src/arch/sparcv9/CodeGen.zig+113-9
......@@ -521,8 +521,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
521521 => try self.airDbgBlock(inst),
522522
523523 .call => try self.airCall(inst, .auto),
524 .call_always_tail => @panic("TODO try self.airCall(inst, .always_tail)"),
525 .call_never_tail => @panic("TODO try self.airCall(inst, .never_tail)"),
524 .call_always_tail => try self.airCall(inst, .always_tail),
525 .call_never_tail => try self.airCall(inst, .never_tail),
526526 .call_never_inline => try self.airCall(inst, .never_inline),
527527
528528 .atomic_store_unordered => @panic("TODO try self.airAtomicStore(inst, .Unordered)"),
......@@ -586,16 +586,106 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
586586 const is_volatile = (extra.data.flags & 0x80000000) != 0;
587587 const clobbers_len = @truncate(u31, extra.data.flags);
588588 var extra_i: usize = extra.end;
589 const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.outputs_len]);
589 const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[extra_i..extra_i+extra.data.outputs_len]);
590590 extra_i += outputs.len;
591 const inputs = @bitCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.inputs_len]);
591 const inputs = @bitCast([]const Air.Inst.Ref, self.air.extra[extra_i..extra_i+extra.data.inputs_len]);
592592 extra_i += inputs.len;
593593
594594 const dead = !is_volatile and self.liveness.isUnused(inst);
595 _ = dead;
596 _ = clobbers_len;
595 const result: MCValue = if (dead) .dead else result: {
596 if (outputs.len > 1) {
597 return self.fail("TODO implement codegen for asm with more than 1 output", .{});
598 }
599
600 const output_constraint: ?[]const u8 = for (outputs) |output| {
601 if (output != .none) {
602 return self.fail("TODO implement codegen for non-expr asm", .{});
603 }
604 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
605 // This equation accounts for the fact that even if we have exactly 4 bytes
606 // for the string, we still use the next u32 for the null terminator.
607 extra_i += constraint.len / 4 + 1;
608
609 break constraint;
610 } else null;
611
612 for (inputs) |input| {
613 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
614 // This equation accounts for the fact that even if we have exactly 4 bytes
615 // for the string, we still use the next u32 for the null terminator.
616 extra_i += constraint.len / 4 + 1;
617
618 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
619 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
620 }
621 const reg_name = constraint[1 .. constraint.len - 1];
622 const reg = parseRegName(reg_name) orelse
623 return self.fail("unrecognized register: '{s}'", .{reg_name});
624
625 const arg_mcv = try self.resolveInst(input);
626 try self.register_manager.getReg(reg, null);
627 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
628 }
629
630 {
631 var clobber_i: u32 = 0;
632 while (clobber_i < clobbers_len) : (clobber_i += 1) {
633 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
634 // This equation accounts for the fact that even if we have exactly 4 bytes
635 // for the string, we still use the next u32 for the null terminator.
636 extra_i += clobber.len / 4 + 1;
637
638 // TODO honor these
639 }
640 }
641
642 const asm_source = std.mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];
643
644 if (mem.eql(u8, asm_source, "ta 0x6d")) {
645 _ = try self.addInst(.{
646 .tag = .tcc,
647 .data = .{
648 .trap = .{
649 .is_imm = true,
650 .cond = 0b1000, // TODO need to look into changing this into an enum
651 .rs2_or_imm = .{ .imm = 0x6d },
652 },
653 },
654 });
655 } else {
656 return self.fail("TODO implement a full SPARCv9 assembly parsing", .{});
657 }
658
659 if (output_constraint) |output| {
660 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
661 return self.fail("unrecognized asm output constraint: '{s}'", .{output});
662 }
663 const reg_name = output[2 .. output.len - 1];
664 const reg = parseRegName(reg_name) orelse
665 return self.fail("unrecognized register: '{s}'", .{reg_name});
666 break :result MCValue{ .register = reg };
667 } else {
668 break :result MCValue{ .none = {} };
669 }
670 };
671
672 simple: {
673 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
674 var buf_index: usize = 0;
675 for (outputs) |output| {
676 if (output == .none) continue;
597677
598 return self.fail("TODO implement asm for {}", .{self.target.cpu.arch});
678 if (buf_index >= buf.len) break :simple;
679 buf[buf_index] = output;
680 buf_index += 1;
681 }
682 if (buf_index + inputs.len > buf.len) break :simple;
683 std.mem.copy(Air.Inst.Ref, buf[buf_index..], inputs);
684 return self.finishAir(inst, result, buf);
685 }
686
687 @panic("TODO implement asm return");
688 //return self.fail("TODO implement asm return for {}", .{self.target.cpu.arch});
599689}
600690
601691fn airArg(self: *Self, inst: Air.Inst.Index) !void {
......@@ -759,9 +849,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
759849 });
760850 }
761851
762 // TODO handle return value
852 const result = info.return_value;
853
854 if (args.len + 1 <= Liveness.bpi - 1) {
855 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
856 buf[0] = callee;
857 std.mem.copy(Air.Inst.Ref, buf[1..], args);
858 return self.finishAir(inst, result, buf);
859 }
763860
764 return self.fail("TODO implement call for {}", .{self.target.cpu.arch});
861 @panic("TODO handle return value with BigTomb");
765862}
766863
767864fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
......@@ -1218,6 +1315,13 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
12181315 }
12191316}
12201317
1318fn parseRegName(name: []const u8) ?Register {
1319 if (@hasDecl(Register, "parseRegName")) {
1320 return Register.parseRegName(name);
1321 }
1322 return std.meta.stringToEnum(Register, name);
1323}
1324
12211325fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
12221326 const tag = self.mir_instructions.items(.tag)[inst];
12231327 switch (tag) {