authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-05-02 21:55:57+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-05-16 22:47:53+07:00
log2770f9a03464dee1e11134054598a6e07c30a6e4
treefa85265314e6f1236ba6f9d6e9093ee3810678f3
parentb6de8d2565974318b888f4e93eab6235fcce6419

stage2: sparc64: Implement airBr


1 files changed, 57 insertions(+), 1 deletions(-)

src/arch/sparc64/CodeGen.zig+57-1
...@@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
543 .assembly => try self.airAsm(inst),543 .assembly => try self.airAsm(inst),
544 .bitcast => @panic("TODO try self.airBitCast(inst)"),544 .bitcast => @panic("TODO try self.airBitCast(inst)"),
545 .block => try self.airBlock(inst),545 .block => try self.airBlock(inst),
546 .br => @panic("TODO try self.airBr(inst)"),546 .br => try self.airBr(inst),
547 .breakpoint => try self.airBreakpoint(),547 .breakpoint => try self.airBreakpoint(),
548 .ret_addr => @panic("TODO try self.airRetAddr(inst)"),548 .ret_addr => @panic("TODO try self.airRetAddr(inst)"),
549 .frame_addr => @panic("TODO try self.airFrameAddress(inst)"),549 .frame_addr => @panic("TODO try self.airFrameAddress(inst)"),
...@@ -852,6 +852,12 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -852,6 +852,12 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
852 return self.finishAir(inst, result, .{ .none, .none, .none });852 return self.finishAir(inst, result, .{ .none, .none, .none });
853}853}
854854
855fn airBr(self: *Self, inst: Air.Inst.Index) !void {
856 const branch = self.air.instructions.items(.data)[inst].br;
857 try self.br(branch.block_inst, branch.operand);
858 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });
859}
860
855fn airBreakpoint(self: *Self) !void {861fn airBreakpoint(self: *Self) !void {
856 // ta 0x01862 // ta 0x01
857 _ = try self.addInst(.{863 _ = try self.addInst(.{
...@@ -1365,6 +1371,56 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -1365,6 +1371,56 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
1365 return MCValue{ .stack_offset = stack_offset };1371 return MCValue{ .stack_offset = stack_offset };
1366}1372}
13671373
1374fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
1375 const block_data = self.blocks.getPtr(block).?;
1376
1377 if (self.air.typeOf(operand).hasRuntimeBits()) {
1378 const operand_mcv = try self.resolveInst(operand);
1379 const block_mcv = block_data.mcv;
1380 if (block_mcv == .none) {
1381 block_data.mcv = switch (operand_mcv) {
1382 .none, .dead, .unreach => unreachable,
1383 .register, .stack_offset, .memory => operand_mcv,
1384 .immediate => blk: {
1385 const new_mcv = try self.allocRegOrMem(block, true);
1386 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
1387 break :blk new_mcv;
1388 },
1389 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
1390 };
1391 } else {
1392 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
1393 }
1394 }
1395 return self.brVoid(block);
1396}
1397
1398fn brVoid(self: *Self, block: Air.Inst.Index) !void {
1399 const block_data = self.blocks.getPtr(block).?;
1400
1401 // Emit a jump with a relocation. It will be patched up after the block ends.
1402 try block_data.relocs.ensureUnusedCapacity(self.gpa, 1);
1403
1404 const br_index = try self.addInst(.{
1405 .tag = .bpcc,
1406 .data = .{
1407 .branch_predict_int = .{
1408 .ccr = .xcc,
1409 .cond = .al,
1410 .inst = undefined, // Will be filled by performReloc
1411 },
1412 },
1413 });
1414
1415 // TODO Find a way to fill this delay slot
1416 _ = try self.addInst(.{
1417 .tag = .nop,
1418 .data = .{ .nop = {} },
1419 });
1420
1421 block_data.relocs.appendAssumeCapacity(br_index);
1422}
1423
1368/// Copies a value to a register without tracking the register. The register is not considered1424/// Copies a value to a register without tracking the register. The register is not considered
1369/// allocated. A second call to `copyToTmpRegister` may return the same register.1425/// allocated. A second call to `copyToTmpRegister` may return the same register.
1370/// This can have a side effect of spilling instructions to the stack to free up a register.1426/// This can have a side effect of spilling instructions to the stack to free up a register.