mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 11:13: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 {
|
||||
bpcc,
|
||||
bpr,
|
||||
fn default(tag: Mir.Inst.Tag) BranchType {
|
||||
return switch (tag) {
|
||||
.bpcc => .bpcc,
|
||||
.bpr => .bpr,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
@ -78,6 +80,7 @@ pub fn emitMir(
|
||||
|
||||
.add => try emit.mirArithmetic3Op(inst),
|
||||
|
||||
.bpr => try emit.mirConditionalBranch(inst),
|
||||
.bpcc => try emit.mirConditionalBranch(inst),
|
||||
|
||||
.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 {
|
||||
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).?;
|
||||
log.debug("mirConditionalBranchImmediate: {} offset={}", .{ inst, offset });
|
||||
|
||||
switch (branch_type) {
|
||||
.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,
|
||||
},
|
||||
}
|
||||
@ -291,6 +322,7 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index {
|
||||
|
||||
switch (tag) {
|
||||
.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,
|
||||
}
|
||||
}
|
||||
@ -343,6 +375,7 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
|
||||
fn isBranch(tag: Mir.Inst.Tag) bool {
|
||||
return switch (tag) {
|
||||
.bpcc => true,
|
||||
.bpr => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
@ -459,19 +492,27 @@ fn optimalBranchType(emit: *Emit, tag: Mir.Inst.Tag, offset: i64) !BranchType {
|
||||
assert(offset & 0b11 == 0);
|
||||
|
||||
switch (tag) {
|
||||
.bpcc => {
|
||||
if (std.math.cast(i21, offset)) |_| {
|
||||
return BranchType.bpcc;
|
||||
} else |_| {
|
||||
// TODO use the following strategy to implement long branches:
|
||||
// - Negate the conditional and target of the original BPcc;
|
||||
// - 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 => {
|
||||
if (std.math.cast(i21, offset)) |_| {
|
||||
return BranchType.bpcc;
|
||||
} else |_| {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +43,10 @@ pub const Inst = struct {
|
||||
// TODO add other operations.
|
||||
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)
|
||||
/// This uses the branch_predict_int field.
|
||||
bpcc,
|
||||
@ -175,6 +179,16 @@ pub const Inst = struct {
|
||||
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
|
||||
///
|
||||
/// Used by e.g. flushw
|
||||
|
||||
@ -1145,6 +1145,10 @@ pub const Instruction = union(enum) {
|
||||
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 {
|
||||
return switch (s2) {
|
||||
Register => format3a(0b10, 0b11_1000, rs1, rs2, rd),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user