Skip to content

Commit 1cccfe4

Browse files
committed
loongarch64: implement not
1 parent 738c12a commit 1cccfe4

File tree

1 file changed

+64
-3
lines changed

1 file changed

+64
-3
lines changed

src/arch/loongarch64/CodeGen.zig

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
18581858
.bit_and => try cg.airLogicBinOp(inst, .@"and"),
18591859
.bit_or => try cg.airLogicBinOp(inst, .@"or"),
18601860
.xor => try cg.airLogicBinOp(inst, .xor),
1861+
.not => try cg.airNot(inst),
18611862

18621863
.bitcast => try cg.airBitCast(inst),
18631864
.intcast => try cg.airIntCast(inst),
@@ -2666,6 +2667,7 @@ const Select = struct {
26662667
pub const Src = union(enum) {
26672668
none,
26682669
any,
2670+
zero,
26692671
imm,
26702672
imm_val: i32,
26712673
imm_fit: u5,
@@ -2682,6 +2684,7 @@ const Select = struct {
26822684

26832685
pub const imm12: Src = .{ .imm_fit = 12 };
26842686
pub const imm20: Src = .{ .imm_fit = 20 };
2687+
/// Immediate 0, see also zero
26852688
pub const imm_zero: Src = .{ .imm_val = 0 };
26862689
pub const imm_one: Src = .{ .imm_val = 1 };
26872690
pub const int_reg: Src = .{ .reg = .int };
@@ -2693,6 +2696,11 @@ const Select = struct {
26932696
return switch (pat) {
26942697
.none => temp.tracking(cg).short == .none,
26952698
.any => true,
2699+
.zero => switch (temp.tracking(cg).short) {
2700+
.immediate => |imm| imm == 0,
2701+
.register => |reg| reg == Register.zero,
2702+
else => false,
2703+
},
26962704
.imm => temp.tracking(cg).short == .immediate,
26972705
.imm_val => |val| switch (temp.tracking(cg).short) {
26982706
.immediate => |imm| @as(i32, @intCast(imm)) == val,
@@ -2716,7 +2724,7 @@ const Select = struct {
27162724

27172725
fn convert(pat: Src, temp: *Temp, cg: *CodeGen) InnerError!bool {
27182726
return switch (pat) {
2719-
.none, .any, .imm, .imm_val, .imm_fit, .regs, .reg_frame => false,
2727+
.none, .any, .zero, .imm, .imm_val, .imm_fit, .regs, .reg_frame => false,
27202728
.mem, .to_mem => try temp.moveToMemory(cg, false),
27212729
.mut_mem, .to_mut_mem => try temp.moveToMemory(cg, true),
27222730
.reg, .to_reg => |rc| try temp.moveToRegister(cg, rc, false),
@@ -2926,6 +2934,7 @@ fn airLogicBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: LogicBinOpKind) !void {
29262934
const ty = sel.ops[0].typeOf(cg);
29272935
assert(ty.isAbiInt(zcu));
29282936

2937+
// case 1: RI
29292938
if (try sel.match(.{
29302939
.patterns = &.{
29312940
.{ .srcs = &.{ .to_int_reg, .imm12 } },
@@ -2938,7 +2947,9 @@ fn airLogicBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: LogicBinOpKind) !void {
29382947
const dst_limb = dst.toLimbValue(0, cg);
29392948
try asmIntLogicBinOpRRI(cg, op, dst_limb.getReg().?, lhs_limb.getReg().?, @intCast(rhs.getUnsignedImm(cg)));
29402949
try sel.finish(dst);
2941-
} else if (try sel.match(.{
2950+
}
2951+
// case 2: RR
2952+
else if (try sel.match(.{
29422953
.patterns = &.{.{ .srcs = &.{ .to_int_reg, .to_int_reg } }},
29432954
})) {
29442955
const lhs, const rhs = sel.ops[0..2].*;
@@ -2950,7 +2961,9 @@ fn airLogicBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: LogicBinOpKind) !void {
29502961
try asmIntLogicBinOpRRR(cg, op, dst_limb.getReg().?, lhs_limb.getReg().?, rhs_limb.getReg().?);
29512962
}
29522963
try sel.finish(dst);
2953-
} else if (try sel.match(.{
2964+
}
2965+
// case 3: limbs
2966+
else if (try sel.match(.{
29542967
.patterns = &.{.{ .srcs = &.{ .any, .any } }},
29552968
.temps = &.{ .any_usize_reg, .any_usize_reg },
29562969
})) {
@@ -2967,6 +2980,54 @@ fn airLogicBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: LogicBinOpKind) !void {
29672980
} else return sel.fail();
29682981
}
29692982

2983+
fn airNot(cg: *CodeGen, inst: Air.Inst.Index) !void {
2984+
const pt = cg.pt;
2985+
const zcu = pt.zcu;
2986+
2987+
const ty_op = cg.getAirData(inst).ty_op;
2988+
const ty = ty_op.ty.toType();
2989+
var sel = Select.init(cg, inst, &try cg.tempsFromOperands(inst, .{ty_op.operand}));
2990+
2991+
// case 1: booleans
2992+
if (try sel.match(.{
2993+
.requirement = ty.zigTypeTag(zcu) == .bool,
2994+
.patterns = &.{
2995+
.{ .srcs = &.{.to_int_reg} },
2996+
},
2997+
})) {
2998+
const op = sel.ops[0];
2999+
const dst, _ = try cg.tempReuseOrAlloc(inst, op, 0, ty, .{ .use_frame = false });
3000+
try cg.asmInst(.xori(dst.getReg(cg), op.getReg(cg), 1));
3001+
try sel.finish(dst);
3002+
}
3003+
// case 2: integers, fit in one register
3004+
else if (try sel.match(.{
3005+
.requirement = ty.isInt(zcu),
3006+
.patterns = &.{.{ .srcs = &.{.to_int_reg} }},
3007+
})) {
3008+
const op = sel.ops[0];
3009+
const dst, _ = try cg.tempReuseOrAlloc(inst, op, 0, ty, .{ .use_frame = false });
3010+
try cg.asmInst(.nor(dst.getReg(cg), op.getReg(cg), .zero));
3011+
try sel.finish(dst);
3012+
}
3013+
// case 3: integers, per-limb
3014+
else if (try sel.match(.{
3015+
.requirement = ty.isInt(zcu),
3016+
.patterns = &.{.{ .srcs = &.{.any} }},
3017+
.temps = &.{.any_usize_reg},
3018+
})) {
3019+
const op = sel.ops[0];
3020+
const tmp = sel.temps[0];
3021+
const dst, _ = try cg.tempReuseOrAlloc(inst, op, 0, ty, .{ .use_frame = false });
3022+
for (0..op.getLimbCount(cg)) |limb_i| {
3023+
const op_limb = try tmp.ensureReg(cg, op.toLimbValue(limb_i, cg));
3024+
const dst_limb = dst.toLimbValue(limb_i, cg);
3025+
try cg.asmInst(.nor(dst_limb.getReg().?, op_limb.getReg().?, .zero));
3026+
}
3027+
try sel.finish(dst);
3028+
} else return sel.fail();
3029+
}
3030+
29703031
fn airRetAddr(cg: *CodeGen, inst: Air.Inst.Index) !void {
29713032
// do not mark $ra as allocated
29723033
const index = RegisterManager.indexOfKnownRegIntoTracked(.ra).?;

0 commit comments

Comments
 (0)