| ... | @@ -1541,6 +1541,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1541,6 +1541,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1541 | .union_init => self.airUnionInit(inst), | 1541 | .union_init => self.airUnionInit(inst), |
| 1542 | .prefetch => self.airPrefetch(inst), | 1542 | .prefetch => self.airPrefetch(inst), |
| 1543 | .popcount => self.airPopcount(inst), | 1543 | .popcount => self.airPopcount(inst), |
| | 1544 | .byte_swap => self.airByteSwap(inst), |
| 1544 | | 1545 | |
| 1545 | .slice => self.airSlice(inst), | 1546 | .slice => self.airSlice(inst), |
| 1546 | .slice_len => self.airSliceLen(inst), | 1547 | .slice_len => self.airSliceLen(inst), |
| ... | @@ -1590,7 +1591,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1590,7 +1591,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1590 | .shl_sat, | 1591 | .shl_sat, |
| 1591 | .ret_addr, | 1592 | .ret_addr, |
| 1592 | .frame_addr, | 1593 | .frame_addr, |
| 1593 | .byte_swap, | | |
| 1594 | .bit_reverse, | 1594 | .bit_reverse, |
| 1595 | .is_err_ptr, | 1595 | .is_err_ptr, |
| 1596 | .is_non_err_ptr, | 1596 | .is_non_err_ptr, |
| ... | @@ -4691,3 +4691,50 @@ fn lowerTry( | ... | @@ -4691,3 +4691,50 @@ fn lowerTry( |
| 4691 | } | 4691 | } |
| 4692 | return self.load(err_union, pl_ty, pl_offset); | 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 | } |