authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-06-16 01:32:02+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-06-24 21:19:33+07:00
log36bfe4b7efedd1b030c335151b2d6a61bbeab1eb
tree026c5e3204905780be6984bd5e372c17d8493b9f
parent18d61d691c0c28405a521422a590e6ea84d13c61

stage2: sparc64: Implement airFence + SPARCv9 membar


4 files changed, 52 insertions(+), 1 deletions(-)

src/arch/sparc64/CodeGen.zig+24-1
...@@ -578,7 +578,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -578,7 +578,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
578 .breakpoint => try self.airBreakpoint(),578 .breakpoint => try self.airBreakpoint(),
579 .ret_addr => @panic("TODO try self.airRetAddr(inst)"),579 .ret_addr => @panic("TODO try self.airRetAddr(inst)"),
580 .frame_addr => @panic("TODO try self.airFrameAddress(inst)"),580 .frame_addr => @panic("TODO try self.airFrameAddress(inst)"),
581 .fence => @panic("TODO try self.airFence()"),581 .fence => try self.airFence(inst),
582 .cond_br => try self.airCondBr(inst),582 .cond_br => try self.airCondBr(inst),
583 .dbg_stmt => try self.airDbgStmt(inst),583 .dbg_stmt => try self.airDbgStmt(inst),
584 .fptrunc => @panic("TODO try self.airFptrunc(inst)"),584 .fptrunc => @panic("TODO try self.airFptrunc(inst)"),
...@@ -1442,6 +1442,29 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {...@@ -1442,6 +1442,29 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
1442 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1442 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1443}1443}
14441444
1445fn airFence(self: *Self, inst: Air.Inst.Index) !void {
1446 // TODO weaken this as needed, currently this implements the strongest membar form
1447 const fence = self.air.instructions.items(.data)[inst].fence;
1448 _ = fence;
1449
1450 // membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad
1451 _ = try self.addInst(.{
1452 .tag = .membar,
1453 .data = .{
1454 .membar_mask = .{
1455 .mmask = .{
1456 .store_store = true,
1457 .store_load = true,
1458 .load_store = true,
1459 .load_load = true,
1460 },
1461 },
1462 },
1463 });
1464
1465 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1466}
1467
1445fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {1468fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
1446 const un_op = self.air.instructions.items(.data)[inst].un_op;1469 const un_op = self.air.instructions.items(.data)[inst].un_op;
1447 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1470 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
src/arch/sparc64/Emit.zig+13
...@@ -98,6 +98,8 @@ pub fn emitMir(...@@ -98,6 +98,8 @@ pub fn emitMir(
98 .xor => try emit.mirArithmetic3Op(inst),98 .xor => try emit.mirArithmetic3Op(inst),
99 .xnor => try emit.mirArithmetic3Op(inst),99 .xnor => try emit.mirArithmetic3Op(inst),
100100
101 .membar => try emit.mirMembar(inst),
102
101 .movcc => try emit.mirConditionalMove(inst),103 .movcc => try emit.mirConditionalMove(inst),
102104
103 .movr => @panic("TODO implement sparc64 movr"),105 .movr => @panic("TODO implement sparc64 movr"),
...@@ -342,6 +344,17 @@ fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -342,6 +344,17 @@ fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {
342 }344 }
343}345}
344346
347fn mirMembar(emit: *Emit, inst: Mir.Inst.Index) !void {
348 const tag = emit.mir.instructions.items(.tag)[inst];
349 const mask = emit.mir.instructions.items(.data)[inst].membar_mask;
350 assert(tag == .membar);
351
352 try emit.writeInstruction(Instruction.membar(
353 mask.cmask,
354 mask.mmask,
355 ));
356}
357
345fn mirNop(emit: *Emit) !void {358fn mirNop(emit: *Emit) !void {
346 try emit.writeInstruction(Instruction.nop());359 try emit.writeInstruction(Instruction.nop());
347}360}
src/arch/sparc64/Mir.zig+11
...@@ -78,6 +78,10 @@ pub const Inst = struct {...@@ -78,6 +78,10 @@ pub const Inst = struct {
78 xor,78 xor,
79 xnor,79 xnor,
8080
81 /// A.32 Memory Barrier
82 /// This uses the membar_mask field.
83 membar,
84
81 /// A.35 Move Integer Register on Condition (MOVcc)85 /// A.35 Move Integer Register on Condition (MOVcc)
82 /// This uses the conditional_move_int field.86 /// This uses the conditional_move_int field.
83 movcc,87 movcc,
...@@ -236,6 +240,13 @@ pub const Inst = struct {...@@ -236,6 +240,13 @@ pub const Inst = struct {
236 inst: Index,240 inst: Index,
237 },241 },
238242
243 /// Membar mask, controls the barrier behavior
244 /// Used by e.g. membar
245 membar_mask: struct {
246 mmask: Instruction.MemOrderingConstraint = .{},
247 cmask: Instruction.MemCompletionConstraint = .{},
248 },
249
239 /// Conditional move, checking the integer status code250 /// Conditional move, checking the integer status code
240 /// if is_imm true then it uses the imm field of rs2_or_imm,251 /// if is_imm true then it uses the imm field of rs2_or_imm,
241 /// otherwise it uses rs2 field.252 /// otherwise it uses rs2 field.
src/arch/sparc64/bits.zig+4
...@@ -1261,6 +1261,10 @@ pub const Instruction = union(enum) {...@@ -1261,6 +1261,10 @@ pub const Instruction = union(enum) {
1261 };1261 };
1262 }1262 }
12631263
1264 pub fn membar(cmask: MemCompletionConstraint, mmask: MemOrderingConstraint) Instruction {
1265 return format3h(cmask, mmask);
1266 }
1267
1264 pub fn movcc(comptime s2: type, cond: Condition, ccr: CCR, rs2: s2, rd: Register) Instruction {1268 pub fn movcc(comptime s2: type, cond: Condition, ccr: CCR, rs2: s2, rd: Register) Instruction {
1265 return switch (s2) {1269 return switch (s2) {
1266 Register => format4c(0b10_1100, cond, ccr, rs2, rd),1270 Register => format4c(0b10_1100, cond, ccr, rs2, rd),