authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-06 21:20:51+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-11 19:38:00+02:00
logbc499de328f0d0110a8eaf3de7be55e05595f598
tree9201e8aa976df79899c18abad64c14dc7a48d7b3
parentc1eb6c30e84b0b161b634f7410088f44c80caa90

wasm: implement `@byteSwap` for 16/32bit integers


1 files changed, 48 insertions(+), 1 deletions(-)

src/arch/wasm/CodeGen.zig+48-1
......@@ -1541,6 +1541,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
15411541 .union_init => self.airUnionInit(inst),
15421542 .prefetch => self.airPrefetch(inst),
15431543 .popcount => self.airPopcount(inst),
1544 .byte_swap => self.airByteSwap(inst),
15441545
15451546 .slice => self.airSlice(inst),
15461547 .slice_len => self.airSliceLen(inst),
......@@ -1590,7 +1591,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
15901591 .shl_sat,
15911592 .ret_addr,
15921593 .frame_addr,
1593 .byte_swap,
15941594 .bit_reverse,
15951595 .is_err_ptr,
15961596 .is_non_err_ptr,
......@@ -4691,3 +4691,50 @@ fn lowerTry(
46914691 }
46924692 return self.load(err_union, pl_ty, pl_offset);
46934693}
4694
4695fn 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}