| ... | ... | @@ -1537,9 +1537,47 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 1537 | 1537 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 1538 | 1538 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 1539 | 1539 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1540 | | if (true) |
| 1541 | | return self.fail("TODO: airByteSwap", .{}); |
| 1542 | | break :result undefined; |
| 1540 | const mod = self.bin_file.comp.module.?; |
| 1541 | const ty = self.typeOf(ty_op.operand); |
| 1542 | const operand = try self.resolveInst(ty_op.operand); |
| 1543 | |
| 1544 | const int_bits = ty.intInfo(mod).bits; |
| 1545 | |
| 1546 | // bytes are no-op |
| 1547 | if (int_bits == 8 and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1548 | return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none }); |
| 1549 | } |
| 1550 | |
| 1551 | const dest_reg = try self.register_manager.allocReg(null, gp); |
| 1552 | try self.genSetReg(ty, dest_reg, operand); |
| 1553 | |
| 1554 | const dest_mcv: MCValue = .{ .register = dest_reg }; |
| 1555 | |
| 1556 | switch (int_bits) { |
| 1557 | 16 => { |
| 1558 | const temp = try self.binOp(.shr, null, dest_mcv, .{ .immediate = 8 }, ty, Type.u8); |
| 1559 | assert(temp == .register); |
| 1560 | _ = try self.addInst(.{ |
| 1561 | .tag = .slli, |
| 1562 | .data = .{ .i_type = .{ |
| 1563 | .imm12 = 8, |
| 1564 | .rd = dest_reg, |
| 1565 | .rs1 = dest_reg, |
| 1566 | } }, |
| 1567 | }); |
| 1568 | _ = try self.addInst(.{ |
| 1569 | .tag = .@"or", |
| 1570 | .data = .{ .r_type = .{ |
| 1571 | .rd = dest_reg, |
| 1572 | .rs1 = dest_reg, |
| 1573 | .rs2 = temp.register, |
| 1574 | } }, |
| 1575 | }); |
| 1576 | }, |
| 1577 | else => return self.fail("TODO: {d} bits for airByteSwap", .{int_bits}), |
| 1578 | } |
| 1579 | |
| 1580 | break :result dest_mcv; |
| 1543 | 1581 | }; |
| 1544 | 1582 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1545 | 1583 | } |