mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 19:23:08 +00:00
stage2: sparc64: Implement SPARCv9 bpr
This commit is contained in:
parent
8f8853cd4f
commit
e057ff2496
@ -51,9 +51,11 @@ const InnerError = error{
|
|||||||
|
|
||||||
const BranchType = enum {
|
const BranchType = enum {
|
||||||
bpcc,
|
bpcc,
|
||||||
|
bpr,
|
||||||
fn default(tag: Mir.Inst.Tag) BranchType {
|
fn default(tag: Mir.Inst.Tag) BranchType {
|
||||||
return switch (tag) {
|
return switch (tag) {
|
||||||
.bpcc => .bpcc,
|
.bpcc => .bpcc,
|
||||||
|
.bpr => .bpr,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -78,6 +80,7 @@ pub fn emitMir(
|
|||||||
|
|
||||||
.add => try emit.mirArithmetic3Op(inst),
|
.add => try emit.mirArithmetic3Op(inst),
|
||||||
|
|
||||||
|
.bpr => try emit.mirConditionalBranch(inst),
|
||||||
.bpcc => try emit.mirConditionalBranch(inst),
|
.bpcc => try emit.mirConditionalBranch(inst),
|
||||||
|
|
||||||
.call => @panic("TODO implement sparc64 call"),
|
.call => @panic("TODO implement sparc64 call"),
|
||||||
@ -232,15 +235,43 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
|
|||||||
|
|
||||||
fn mirConditionalBranch(emit: *Emit, inst: Mir.Inst.Index) !void {
|
fn mirConditionalBranch(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||||
const branch_predict_int = emit.mir.instructions.items(.data)[inst].branch_predict_int;
|
|
||||||
|
|
||||||
const offset = @intCast(i64, emit.code_offset_mapping.get(branch_predict_int.inst).?) - @intCast(i64, emit.code.items.len);
|
|
||||||
const branch_type = emit.branch_types.get(inst).?;
|
const branch_type = emit.branch_types.get(inst).?;
|
||||||
log.debug("mirConditionalBranchImmediate: {} offset={}", .{ inst, offset });
|
|
||||||
|
|
||||||
switch (branch_type) {
|
switch (branch_type) {
|
||||||
.bpcc => switch (tag) {
|
.bpcc => switch (tag) {
|
||||||
.bpcc => try emit.writeInstruction(Instruction.bpcc(branch_predict_int.cond, branch_predict_int.annul, branch_predict_int.pt, branch_predict_int.ccr, @intCast(i21, offset))),
|
.bpcc => {
|
||||||
|
const branch_predict_int = emit.mir.instructions.items(.data)[inst].branch_predict_int;
|
||||||
|
const offset = @intCast(i64, emit.code_offset_mapping.get(branch_predict_int.inst).?) - @intCast(i64, emit.code.items.len);
|
||||||
|
log.debug("mirConditionalBranch: {} offset={}", .{ inst, offset });
|
||||||
|
|
||||||
|
try emit.writeInstruction(
|
||||||
|
Instruction.bpcc(
|
||||||
|
branch_predict_int.cond,
|
||||||
|
branch_predict_int.annul,
|
||||||
|
branch_predict_int.pt,
|
||||||
|
branch_predict_int.ccr,
|
||||||
|
@intCast(i21, offset),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
.bpr => switch (tag) {
|
||||||
|
.bpr => {
|
||||||
|
const branch_predict_reg = emit.mir.instructions.items(.data)[inst].branch_predict_reg;
|
||||||
|
const offset = @intCast(i64, emit.code_offset_mapping.get(branch_predict_reg.inst).?) - @intCast(i64, emit.code.items.len);
|
||||||
|
log.debug("mirConditionalBranch: {} offset={}", .{ inst, offset });
|
||||||
|
|
||||||
|
try emit.writeInstruction(
|
||||||
|
Instruction.bpr(
|
||||||
|
branch_predict_reg.cond,
|
||||||
|
branch_predict_reg.annul,
|
||||||
|
branch_predict_reg.pt,
|
||||||
|
branch_predict_reg.rs1,
|
||||||
|
@intCast(i18, offset),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -291,6 +322,7 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index {
|
|||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.bpcc => return emit.mir.instructions.items(.data)[inst].branch_predict_int.inst,
|
.bpcc => return emit.mir.instructions.items(.data)[inst].branch_predict_int.inst,
|
||||||
|
.bpr => return emit.mir.instructions.items(.data)[inst].branch_predict_reg.inst,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,6 +375,7 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
|
|||||||
fn isBranch(tag: Mir.Inst.Tag) bool {
|
fn isBranch(tag: Mir.Inst.Tag) bool {
|
||||||
return switch (tag) {
|
return switch (tag) {
|
||||||
.bpcc => true,
|
.bpcc => true,
|
||||||
|
.bpr => true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -459,19 +492,27 @@ fn optimalBranchType(emit: *Emit, tag: Mir.Inst.Tag, offset: i64) !BranchType {
|
|||||||
assert(offset & 0b11 == 0);
|
assert(offset & 0b11 == 0);
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
|
// TODO use the following strategy to implement long branches:
|
||||||
|
// - Negate the conditional and target of the original instruction;
|
||||||
|
// - In the space immediately after the branch, load
|
||||||
|
// the address of the original target, preferrably in
|
||||||
|
// a PC-relative way, into %o7; and
|
||||||
|
// - jmpl %o7 + %g0, %g0
|
||||||
|
|
||||||
.bpcc => {
|
.bpcc => {
|
||||||
if (std.math.cast(i21, offset)) |_| {
|
if (std.math.cast(i21, offset)) |_| {
|
||||||
return BranchType.bpcc;
|
return BranchType.bpcc;
|
||||||
} else |_| {
|
} else |_| {
|
||||||
// TODO use the following strategy to implement long branches:
|
|
||||||
// - Negate the conditional and target of the original BPcc;
|
|
||||||
// - In the space immediately after the branch, load
|
|
||||||
// the address of the original target, preferrably in
|
|
||||||
// a PC-relative way, into %o7; and
|
|
||||||
// - jmpl %o7 + %g0, %g0
|
|
||||||
return emit.fail("TODO support BPcc branches larger than +-1 MiB", .{});
|
return emit.fail("TODO support BPcc branches larger than +-1 MiB", .{});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.bpr => {
|
||||||
|
if (std.math.cast(i18, offset)) |_| {
|
||||||
|
return BranchType.bpr;
|
||||||
|
} else |_| {
|
||||||
|
return emit.fail("TODO support BPr branches larger than +-128 KiB", .{});
|
||||||
|
}
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,6 +43,10 @@ pub const Inst = struct {
|
|||||||
// TODO add other operations.
|
// TODO add other operations.
|
||||||
add,
|
add,
|
||||||
|
|
||||||
|
/// A.3 Branch on Integer Register with Prediction (BPr)
|
||||||
|
/// This uses the branch_predict_reg field.
|
||||||
|
bpr,
|
||||||
|
|
||||||
/// A.7 Branch on Integer Condition Codes with Prediction (BPcc)
|
/// A.7 Branch on Integer Condition Codes with Prediction (BPcc)
|
||||||
/// This uses the branch_predict_int field.
|
/// This uses the branch_predict_int field.
|
||||||
bpcc,
|
bpcc,
|
||||||
@ -175,6 +179,16 @@ pub const Inst = struct {
|
|||||||
inst: Index,
|
inst: Index,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Branch with prediction, comparing a register's content with zero
|
||||||
|
/// Used by e.g. bpr
|
||||||
|
branch_predict_reg: struct {
|
||||||
|
annul: bool = false,
|
||||||
|
pt: bool = true,
|
||||||
|
cond: Instruction.RCondition,
|
||||||
|
rs1: Register,
|
||||||
|
inst: Index,
|
||||||
|
},
|
||||||
|
|
||||||
/// No additional data
|
/// No additional data
|
||||||
///
|
///
|
||||||
/// Used by e.g. flushw
|
/// Used by e.g. flushw
|
||||||
|
|||||||
@ -1145,6 +1145,10 @@ pub const Instruction = union(enum) {
|
|||||||
return format2c(0b001, .{ .icond = cond }, annul, pt, ccr, disp);
|
return format2c(0b001, .{ .icond = cond }, annul, pt, ccr, disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bpr(cond: RCondition, annul: bool, pt: bool, rs1: Register, disp: i18) Instruction {
|
||||||
|
return format2d(0b011, cond, annul, pt, rs1, disp);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn jmpl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
|
pub fn jmpl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
|
||||||
return switch (s2) {
|
return switch (s2) {
|
||||||
Register => format3a(0b10, 0b11_1000, rs1, rs2, rd),
|
Register => format3a(0b10, 0b11_1000, rs1, rs2, rd),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user