| ... | ... | @@ -1541,6 +1541,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1541 | 1541 | .union_init => self.airUnionInit(inst), |
| 1542 | 1542 | .prefetch => self.airPrefetch(inst), |
| 1543 | 1543 | .popcount => self.airPopcount(inst), |
| 1544 | .byte_swap => self.airByteSwap(inst), |
| 1544 | 1545 | |
| 1545 | 1546 | .slice => self.airSlice(inst), |
| 1546 | 1547 | .slice_len => self.airSliceLen(inst), |
| ... | ... | @@ -1590,7 +1591,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1590 | 1591 | .shl_sat, |
| 1591 | 1592 | .ret_addr, |
| 1592 | 1593 | .frame_addr, |
| 1593 | | .byte_swap, |
| 1594 | 1594 | .bit_reverse, |
| 1595 | 1595 | .is_err_ptr, |
| 1596 | 1596 | .is_non_err_ptr, |
| ... | ... | @@ -4691,3 +4691,50 @@ fn lowerTry( |
| 4691 | 4691 | } |
| 4692 | 4692 | return self.load(err_union, pl_ty, pl_offset); |
| 4693 | 4693 | } |
| 4694 | |
| 4695 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4696 | if (self.liveness.isUnused(inst)) { |
| 4697 | return WValue{ .none = {} }; |
| 4698 | } |
| 4699 | |
| 4700 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4701 | const ty = self.air.typeOfIndex(inst); |
| 4702 | const operand = try self.resolveInst(ty_op.operand); |
| 4703 | |
| 4704 | if (ty.zigTypeTag() == .Vector) { |
| 4705 | return self.fail("TODO: @byteSwap for vectors", .{}); |
| 4706 | } |
| 4707 | const int_info = ty.intInfo(self.target); |
| 4708 | |
| 4709 | // bytes are no-op |
| 4710 | if (int_info.bits == 8) { |
| 4711 | return operand; |
| 4712 | } |
| 4713 | |
| 4714 | switch (int_info.bits) { |
| 4715 | 16 => { |
| 4716 | const shl_res = try self.binOp(operand, .{ .imm32 = 8 }, ty, .shl); |
| 4717 | const tmp = try self.binOp(operand, .{ .imm32 = 0xFF00 }, ty, .@"and"); |
| 4718 | const shr_res = try self.binOp(tmp, .{ .imm32 = 8 }, ty, .shr); |
| 4719 | const res = if (int_info.signedness == .signed) blk: { |
| 4720 | break :blk try self.wrapOperand(shr_res, Type.u8); |
| 4721 | } else shr_res; |
| 4722 | return self.binOp(shl_res, res, ty, .@"or"); |
| 4723 | }, |
| 4724 | 32 => { |
| 4725 | const shl_tmp = try self.binOp(operand, .{ .imm32 = 8 }, ty, .shl); |
| 4726 | const lhs = try self.binOp(shl_tmp, .{ .imm32 = 0xFF00FF00 }, ty, .@"and"); |
| 4727 | const shr_tmp = try self.binOp(operand, .{ .imm32 = 8 }, ty, .shr); |
| 4728 | const rhs = try self.binOp(shr_tmp, .{ .imm32 = 0xFF00FF }, ty, .@"and"); |
| 4729 | const tmp_or = try self.binOp(lhs, rhs, ty, .@"or"); |
| 4730 | |
| 4731 | const shl = try self.binOp(tmp_or, .{ .imm32 = 16 }, ty, .shl); |
| 4732 | const shr = try self.binOp(tmp_or, .{ .imm32 = 16 }, ty, .shr); |
| 4733 | const res = if (int_info.signedness == .signed) blk: { |
| 4734 | break :blk try self.wrapOperand(shr, Type.u16); |
| 4735 | } else shr; |
| 4736 | return self.binOp(shl, res, ty, .@"or"); |
| 4737 | }, |
| 4738 | else => return self.fail("TODO: @byteSwap for integers with bitsize {d}", .{int_info.bits}), |
| 4739 | } |
| 4740 | } |