Skip to content

Commit

Permalink
Merge pull request ziglang#11806 from koachan/sparc64-codegen
Browse files Browse the repository at this point in the history
stage2: sparc64: Some more Air lowerings
  • Loading branch information
kubkon authored Jun 7, 2022
2 parents 523fae4 + 97d35a5 commit 6c59aa9
Show file tree
Hide file tree
Showing 6 changed files with 644 additions and 61 deletions.
592 changes: 532 additions & 60 deletions src/arch/sparc64/CodeGen.zig

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions src/arch/sparc64/Emit.zig
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub fn emitMir(
.dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),

.add => try emit.mirArithmetic3Op(inst),
.addcc => try emit.mirArithmetic3Op(inst),

.bpr => try emit.mirConditionalBranch(inst),
.bpcc => try emit.mirConditionalBranch(inst),
Expand All @@ -93,6 +94,10 @@ pub fn emitMir(
.ldx => try emit.mirArithmetic3Op(inst),

.@"or" => try emit.mirArithmetic3Op(inst),
.xor => try emit.mirArithmetic3Op(inst),
.xnor => try emit.mirArithmetic3Op(inst),

.movcc => try emit.mirConditionalMove(inst),

.mulx => try emit.mirArithmetic3Op(inst),

Expand Down Expand Up @@ -125,6 +130,8 @@ pub fn emitMir(
.cmp => try emit.mirArithmetic2Op(inst),

.mov => try emit.mirArithmetic2Op(inst),

.not => try emit.mirArithmetic2Op(inst),
}
}
}
Expand Down Expand Up @@ -185,6 +192,7 @@ fn mirArithmetic2Op(emit: *Emit, inst: Mir.Inst.Index) !void {
.@"return" => try emit.writeInstruction(Instruction.@"return"(i13, rs1, imm)),
.cmp => try emit.writeInstruction(Instruction.subcc(i13, rs1, imm, .g0)),
.mov => try emit.writeInstruction(Instruction.@"or"(i13, .g0, imm, rs1)),
.not => try emit.writeInstruction(Instruction.xnor(i13, .g0, imm, rs1)),
else => unreachable,
}
} else {
Expand All @@ -193,6 +201,7 @@ fn mirArithmetic2Op(emit: *Emit, inst: Mir.Inst.Index) !void {
.@"return" => try emit.writeInstruction(Instruction.@"return"(Register, rs1, rs2)),
.cmp => try emit.writeInstruction(Instruction.subcc(Register, rs1, rs2, .g0)),
.mov => try emit.writeInstruction(Instruction.@"or"(Register, .g0, rs2, rs1)),
.not => try emit.writeInstruction(Instruction.xnor(Register, .g0, rs2, rs1)),
else => unreachable,
}
}
Expand All @@ -209,12 +218,15 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
const imm = data.rs2_or_imm.imm;
switch (tag) {
.add => try emit.writeInstruction(Instruction.add(i13, rs1, imm, rd)),
.addcc => try emit.writeInstruction(Instruction.addcc(i13, rs1, imm, rd)),
.jmpl => try emit.writeInstruction(Instruction.jmpl(i13, rs1, imm, rd)),
.ldub => try emit.writeInstruction(Instruction.ldub(i13, rs1, imm, rd)),
.lduh => try emit.writeInstruction(Instruction.lduh(i13, rs1, imm, rd)),
.lduw => try emit.writeInstruction(Instruction.lduw(i13, rs1, imm, rd)),
.ldx => try emit.writeInstruction(Instruction.ldx(i13, rs1, imm, rd)),
.@"or" => try emit.writeInstruction(Instruction.@"or"(i13, rs1, imm, rd)),
.xor => try emit.writeInstruction(Instruction.xor(i13, rs1, imm, rd)),
.xnor => try emit.writeInstruction(Instruction.xnor(i13, rs1, imm, rd)),
.mulx => try emit.writeInstruction(Instruction.mulx(i13, rs1, imm, rd)),
.save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)),
.restore => try emit.writeInstruction(Instruction.restore(i13, rs1, imm, rd)),
Expand All @@ -230,12 +242,15 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
const rs2 = data.rs2_or_imm.rs2;
switch (tag) {
.add => try emit.writeInstruction(Instruction.add(Register, rs1, rs2, rd)),
.addcc => try emit.writeInstruction(Instruction.addcc(Register, rs1, rs2, rd)),
.jmpl => try emit.writeInstruction(Instruction.jmpl(Register, rs1, rs2, rd)),
.ldub => try emit.writeInstruction(Instruction.ldub(Register, rs1, rs2, rd)),
.lduh => try emit.writeInstruction(Instruction.lduh(Register, rs1, rs2, rd)),
.lduw => try emit.writeInstruction(Instruction.lduw(Register, rs1, rs2, rd)),
.ldx => try emit.writeInstruction(Instruction.ldx(Register, rs1, rs2, rd)),
.@"or" => try emit.writeInstruction(Instruction.@"or"(Register, rs1, rs2, rd)),
.xor => try emit.writeInstruction(Instruction.xor(Register, rs1, rs2, rd)),
.xnor => try emit.writeInstruction(Instruction.xnor(Register, rs1, rs2, rd)),
.mulx => try emit.writeInstruction(Instruction.mulx(Register, rs1, rs2, rd)),
.save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)),
.restore => try emit.writeInstruction(Instruction.restore(Register, rs1, rs2, rd)),
Expand Down Expand Up @@ -294,6 +309,34 @@ fn mirConditionalBranch(emit: *Emit, inst: Mir.Inst.Index) !void {
}
}

fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];

switch (tag) {
.movcc => {
const data = emit.mir.instructions.items(.data)[inst].conditional_move;
if (data.is_imm) {
try emit.writeInstruction(Instruction.movcc(
i11,
data.cond,
data.ccr,
data.rs2_or_imm.imm,
data.rd,
));
} else {
try emit.writeInstruction(Instruction.movcc(
Register,
data.cond,
data.ccr,
data.rs2_or_imm.rs2,
data.rd,
));
}
},
else => unreachable,
}
}

fn mirNop(emit: *Emit) !void {
try emit.writeInstruction(Instruction.nop());
}
Expand Down
30 changes: 30 additions & 0 deletions src/arch/sparc64/Mir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub const Inst = struct {
/// This uses the arithmetic_3op field.
// TODO add other operations.
add,
addcc,

/// A.3 Branch on Integer Register with Prediction (BPr)
/// This uses the branch_predict_reg field.
Expand Down Expand Up @@ -73,6 +74,12 @@ pub const Inst = struct {
/// This uses the arithmetic_3op field.
// TODO add other operations.
@"or",
xor,
xnor,

/// A.35 Move Integer Register on Condition (MOVcc)
/// This uses the conditional_move field.
movcc,

/// A.37 Multiply and Divide (64-bit)
/// This uses the arithmetic_3op field.
Expand Down Expand Up @@ -142,6 +149,13 @@ pub const Inst = struct {
/// being the *destination* register.
// TODO is it okay to abuse rs1 in this way?
mov, // mov rs2/imm, rs1 -> or %g0, rs2/imm, rs1

/// Bitwise negation
/// This uses the arithmetic_2op field, with rs1
/// being the *destination* register.
// TODO is it okay to abuse rs1 in this way?
// TODO this differs from official encoding for convenience, fix it later
not, // not rs2/imm, rs1 -> xnor %g0, rs2/imm, rs1
};

/// The position of an MIR instruction within the `Mir` instructions array.
Expand Down Expand Up @@ -216,6 +230,22 @@ pub const Inst = struct {
inst: Index,
},

/// Conditional move.
/// if is_imm true then it uses the imm field of rs2_or_imm,
/// otherwise it uses rs2 field.
///
/// Used by e.g. movcc
conditional_move: struct {
is_imm: bool,
ccr: Instruction.CCR,
cond: Instruction.Condition,
rd: Register,
rs2_or_imm: union {
rs2: Register,
imm: i11,
},
},

/// No additional data
///
/// Used by e.g. flushw
Expand Down
5 changes: 5 additions & 0 deletions src/arch/sparc64/abi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ pub const stack_bias = 2047;
// The first 128 bytes of the stack is reserved for register saving purposes.
// The ABI also requires to reserve space in the stack for the first six
// outgoing arguments, even though they are usually passed in registers.
// TODO Don't allocate the argument space in leaf functions
// TODO Save an RO copy of outgoing arguments in reserved area when building in Debug
// TODO Should we also save it in ReleaseSafe? Solaris and OpenBSD binaries seem to ship
// with argument copying enabled and it doesn't seem to give them big slowdowns so
// I guess it would be okay to do in ReleaseSafe?
pub const stack_reserved_area = 128 + 48;

// There are no callee-preserved registers since the windowing
Expand Down
34 changes: 33 additions & 1 deletion src/arch/sparc64/bits.zig
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ pub const Instruction = union(enum) {
.gt => .gu,
.neq => .ne,
.lt => .cs,
.lte => .le,
.lte => .leu,
.eq => .eq,
};
}
Expand Down Expand Up @@ -1141,6 +1141,14 @@ pub const Instruction = union(enum) {
};
}

pub fn addcc(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format3a(0b10, 0b01_0000, rs1, rs2, rd),
i13 => format3b(0b10, 0b01_0000, rs1, rs2, rd),
else => unreachable,
};
}

pub fn bpcc(cond: ICondition, annul: bool, pt: bool, ccr: CCR, disp: i21) Instruction {
return format2c(0b001, .{ .icond = cond }, annul, pt, ccr, disp);
}
Expand Down Expand Up @@ -1197,6 +1205,30 @@ pub const Instruction = union(enum) {
};
}

pub fn xor(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format3a(0b10, 0b00_0011, rs1, rs2, rd),
i13 => format3b(0b10, 0b00_0011, rs1, rs2, rd),
else => unreachable,
};
}

pub fn xnor(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format3a(0b10, 0b00_0111, rs1, rs2, rd),
i13 => format3b(0b10, 0b00_0111, rs1, rs2, rd),
else => unreachable,
};
}

pub fn movcc(comptime s2: type, cond: Condition, ccr: CCR, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format4c(0b10_1100, cond, ccr, rs2, rd),
i11 => format4d(0b10_1100, cond, ccr, rs2, rd),
else => unreachable,
};
}

pub fn mulx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format3a(0b10, 0b00_1001, rs1, rs2, rd),
Expand Down
1 change: 1 addition & 0 deletions test/behavior/align.zig
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ test "align(N) on functions" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO

// function alignment is a compile error on wasm32/wasm64
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
Expand Down

0 comments on commit 6c59aa9

Please sign in to comment.