authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-06-01 19:13:43+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-06-06 20:34:53+07:00
log23150de9c41330351bc5f7b62418617d5714203d
treec681de9dd01f948e452c0e1e8e26ddc099e51850
parent9ad74b60874447b81747651e28246d3f2168940a

stage2: sparc64: Implement airNot


3 files changed, 134 insertions(+), 1 deletions(-)

src/arch/sparc64/CodeGen.zig+121-1
...@@ -586,7 +586,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -586,7 +586,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
586 .is_err_ptr => @panic("TODO try self.airIsErrPtr(inst)"),586 .is_err_ptr => @panic("TODO try self.airIsErrPtr(inst)"),
587 .load => try self.airLoad(inst),587 .load => try self.airLoad(inst),
588 .loop => try self.airLoop(inst),588 .loop => try self.airLoop(inst),
589 .not => @panic("TODO try self.airNot(inst)"),589 .not => try self.airNot(inst),
590 .ptrtoint => @panic("TODO try self.airPtrToInt(inst)"),590 .ptrtoint => @panic("TODO try self.airPtrToInt(inst)"),
591 .ret => try self.airRet(inst),591 .ret => try self.airRet(inst),
592 .ret_load => try self.airRetLoad(inst),592 .ret_load => try self.airRetLoad(inst),
...@@ -1507,6 +1507,126 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {...@@ -1507,6 +1507,126 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {
1507 return self.finishAirBookkeeping();1507 return self.finishAirBookkeeping();
1508}1508}
15091509
1510fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1511 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1512 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1513 const operand = try self.resolveInst(ty_op.operand);
1514 const operand_ty = self.air.typeOf(ty_op.operand);
1515 switch (operand) {
1516 .dead => unreachable,
1517 .unreach => unreachable,
1518 .compare_flags_unsigned => |op| {
1519 const r = MCValue{
1520 .compare_flags_unsigned = .{
1521 .cmp = switch (op.cmp) {
1522 .gte => .lt,
1523 .gt => .lte,
1524 .neq => .eq,
1525 .lt => .gte,
1526 .lte => .gt,
1527 .eq => .neq,
1528 },
1529 .ccr = op.ccr,
1530 },
1531 };
1532 break :result r;
1533 },
1534 .compare_flags_signed => |op| {
1535 const r = MCValue{
1536 .compare_flags_signed = .{
1537 .cmp = switch (op.cmp) {
1538 .gte => .lt,
1539 .gt => .lte,
1540 .neq => .eq,
1541 .lt => .gte,
1542 .lte => .gt,
1543 .eq => .neq,
1544 },
1545 .ccr = op.ccr,
1546 },
1547 };
1548 break :result r;
1549 },
1550 else => {
1551 switch (operand_ty.zigTypeTag()) {
1552 .Bool => {
1553 // TODO convert this to mvn + and
1554 const op_reg = switch (operand) {
1555 .register => |r| r,
1556 else => try self.copyToTmpRegister(operand_ty, operand),
1557 };
1558 const reg_lock = self.register_manager.lockRegAssumeUnused(op_reg);
1559 defer self.register_manager.unlockReg(reg_lock);
1560
1561 const dest_reg = blk: {
1562 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1563 break :blk op_reg;
1564 }
1565
1566 const reg = try self.register_manager.allocReg(null, gp);
1567 break :blk reg;
1568 };
1569
1570 _ = try self.addInst(.{
1571 .tag = .xor,
1572 .data = .{
1573 .arithmetic_3op = .{
1574 .is_imm = true,
1575 .rd = dest_reg,
1576 .rs1 = op_reg,
1577 .rs2_or_imm = .{ .imm = 1 },
1578 },
1579 },
1580 });
1581
1582 break :result MCValue{ .register = dest_reg };
1583 },
1584 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
1585 .Int => {
1586 const int_info = operand_ty.intInfo(self.target.*);
1587 if (int_info.bits <= 64) {
1588 const op_reg = switch (operand) {
1589 .register => |r| r,
1590 else => try self.copyToTmpRegister(operand_ty, operand),
1591 };
1592 const reg_lock = self.register_manager.lockRegAssumeUnused(op_reg);
1593 defer self.register_manager.unlockReg(reg_lock);
1594
1595 const dest_reg = blk: {
1596 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1597 break :blk op_reg;
1598 }
1599
1600 const reg = try self.register_manager.allocReg(null, gp);
1601 break :blk reg;
1602 };
1603
1604 _ = try self.addInst(.{
1605 .tag = .not,
1606 .data = .{
1607 .arithmetic_2op = .{
1608 .is_imm = false,
1609 .rs1 = dest_reg,
1610 .rs2_or_imm = .{ .rs2 = op_reg },
1611 },
1612 },
1613 });
1614
1615 try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
1616
1617 break :result MCValue{ .register = dest_reg };
1618 } else {
1619 return self.fail("TODO AArch64 not on integers > u64/i64", .{});
1620 }
1621 },
1622 else => unreachable,
1623 }
1624 },
1625 }
1626 };
1627 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1628}
1629
1510fn airRet(self: *Self, inst: Air.Inst.Index) !void {1630fn airRet(self: *Self, inst: Air.Inst.Index) !void {
1511 const un_op = self.air.instructions.items(.data)[inst].un_op;1631 const un_op = self.air.instructions.items(.data)[inst].un_op;
1512 const operand = try self.resolveInst(un_op);1632 const operand = try self.resolveInst(un_op);
src/arch/sparc64/Emit.zig+4
...@@ -94,6 +94,8 @@ pub fn emitMir(...@@ -94,6 +94,8 @@ pub fn emitMir(
94 .ldx => try emit.mirArithmetic3Op(inst),94 .ldx => try emit.mirArithmetic3Op(inst),
9595
96 .@"or" => try emit.mirArithmetic3Op(inst),96 .@"or" => try emit.mirArithmetic3Op(inst),
97 .xor => @panic("TODO implement sparc64 xor"),
98 .xnor => @panic("TODO implement sparc64 xnor"),
9799
98 .movcc => try emit.mirConditionalMove(inst),100 .movcc => try emit.mirConditionalMove(inst),
99101
...@@ -128,6 +130,8 @@ pub fn emitMir(...@@ -128,6 +130,8 @@ pub fn emitMir(
128 .cmp => try emit.mirArithmetic2Op(inst),130 .cmp => try emit.mirArithmetic2Op(inst),
129131
130 .mov => try emit.mirArithmetic2Op(inst),132 .mov => try emit.mirArithmetic2Op(inst),
133
134 .not => @panic("TODO implement sparc64 not"),
131 }135 }
132 }136 }
133}137}
src/arch/sparc64/Mir.zig+9
...@@ -74,6 +74,8 @@ pub const Inst = struct {...@@ -74,6 +74,8 @@ pub const Inst = struct {
74 /// This uses the arithmetic_3op field.74 /// This uses the arithmetic_3op field.
75 // TODO add other operations.75 // TODO add other operations.
76 @"or",76 @"or",
77 xor,
78 xnor,
7779
78 /// A.35 Move Integer Register on Condition (MOVcc)80 /// A.35 Move Integer Register on Condition (MOVcc)
79 /// This uses the conditional_move field.81 /// This uses the conditional_move field.
...@@ -147,6 +149,13 @@ pub const Inst = struct {...@@ -147,6 +149,13 @@ pub const Inst = struct {
147 /// being the *destination* register.149 /// being the *destination* register.
148 // TODO is it okay to abuse rs1 in this way?150 // TODO is it okay to abuse rs1 in this way?
149 mov, // mov rs2/imm, rs1 -> or %g0, rs2/imm, rs1151 mov, // mov rs2/imm, rs1 -> or %g0, rs2/imm, rs1
152
153 /// Bitwise negation
154 /// This uses the arithmetic_2op field, with rs1
155 /// being the *destination* register.
156 // TODO is it okay to abuse rs1 in this way?
157 // TODO this differs from official encoding for convenience, fix it later
158 not, // not rs2/imm, rs1 -> xnor %g0, rs2/imm, rs1
150 };159 };
151160
152 /// The position of an MIR instruction within the `Mir` instructions array.161 /// The position of an MIR instruction within the `Mir` instructions array.