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 {...@@ -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),
15441545
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
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}