Skip to content

Commit b302b4f

Browse files
SME & SME+I16I64 support
1 parent 59c6a7e commit b302b4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+3498
-23
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ CFLAGS=-std=c++11 -DNDEBUG -g -I ./xbyak_aarch64 -Wall -Wextra -fPIC
2121
ifneq ($(DEBUG),1)
2222
CFLAGS+=-O2
2323
endif
24+
ifeq ($(STRICT_CONCAT),1) # allows to check collisions during test comparison
25+
CFLAGS+=-DSTRICT_CONCAT
26+
endif
2427

2528
LIB_OBJ=obj/xbyak_aarch64_impl.o obj/util_impl.o
2629

src/xbyak_aarch64_impl.h

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ inline uint64_t lsb(uint64_t v) { return v & 0x1; }
2020
uint32_t concat(const std::initializer_list<uint32_t> list) {
2121
uint32_t result = 0;
2222
for (auto f : list) {
23+
#ifdef STRICT_CONCAT
24+
uint32_t saved = result;
2325
result |= f;
26+
if (saved != ((~f) & result)) return saved;
27+
#else
28+
result |= f;
29+
#endif
2430
}
2531
return result;
2632
}
@@ -582,6 +588,12 @@ void CodeGenerator::PState(PStateField psfield, uint32_t imm) {
582588
op1 = 3;
583589
op2 = 2;
584590
break;
591+
case SVCRSM:
592+
case SVCRZA:
593+
case SVCRSMZA:
594+
op1 = 3;
595+
op2 = 3;
596+
break;
585597
default:
586598
op1 = 0;
587599
op2 = 0;
@@ -4298,3 +4310,235 @@ void CodeGenerator::clearCache(void *begin, void *end) {
42984310
__builtin___clear_cache((char *)begin, (char *)end);
42994311
#endif
43004312
}
4313+
4314+
void CodeGenerator::SmeAddPredVec(bool isVertical, const _ZAReg &za, const _PReg &pn, const _PReg &pm, const _ZReg &zn) {
4315+
bool isDouble = za.getBit() == 64;
4316+
verifyIncRange(pn.getIdx() | pm.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4317+
verifyIncRange(za.getIdx(), 0, isDouble?7:3, ERR_ILLEGAL_REG_IDX);
4318+
uint32_t code = concat({F(0x181, 23), F(isDouble, 22), F(1, 20), F(isVertical, 16), F(pm.getIdx(), 13), F(pn.getIdx(), 10), F(zn.getIdx(), 5), F(za.getIdx(), 0)});
4319+
dd(code);
4320+
}
4321+
4322+
// Add multiply of Streaming SVE <predicate|vector> register size
4323+
void CodeGenerator::SmeAddMultiplySSRegSize(bool isPredicate, const XReg &rd, const XReg &rn, const int32_t imm6) {
4324+
uint32_t masked_imm = (uint32_t)imm6 & 0x3F;
4325+
verifyIncRange(imm6, -32, 31, ERR_ILLEGAL_IMM_RANGE, true);
4326+
uint32_t code = concat({F(isPredicate, 22), F(0x21, 21), F(rn.getIdx(), 16), F(0xB, 11), F(masked_imm, 5), F(rd.getIdx(), 0)});
4327+
dd(code);
4328+
}
4329+
4330+
// Half-float/BFloat16 sum of outer products to single-precision
4331+
void CodeGenerator::SmeHalfFloatOuterProd(bool isBfloat16, bool isSubtract, const ZARegS &za, const _PReg &pn, const _PReg &pm, const ZRegH &zn, const ZRegH &zm) {
4332+
verifyIncRange(pn.getIdx() | pm.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4333+
verifyIncRange(za.getIdx(), 0, 3, ERR_ILLEGAL_REG_IDX);
4334+
uint32_t code = concat({F(0x103, 23), F(!isBfloat16, 21), F(zm.getIdx(), 16), F(pm.getIdx(), 13), F(pn.getIdx(), 10), F(zn.getIdx(), 5), F(isSubtract, 4), F(za.getIdx(), 0)});
4335+
dd(code);
4336+
}
4337+
4338+
void CodeGenerator::SmeZahvContiLdStB(bool isStore, const _ZAHVReg &za0hv, const _PReg &pg, const XReg &xm, const XReg &xn) {
4339+
int32_t wsIdxPacked = za0hv.getWsIdx()-12;
4340+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4341+
verifyIncRange(za0hv.getIdx(), 0, 0, ERR_ILLEGAL_REG_IDX);
4342+
verifyIncRange(za0hv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4343+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4344+
if(8u != za0hv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4345+
uint32_t code = concat({F(0x7, 29), F(isStore, 21), F(xm.getIdx(), 16), F(za0hv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(xn.getIdx(), 5), F(za0hv.getOffs(), 0)});
4346+
dd(code);
4347+
}
4348+
4349+
void CodeGenerator::SmeZahvContiLdStH(bool isStore, const _ZAHVReg &zahv, const _PReg &pg, const XReg &xm, const XReg &xn) {
4350+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4351+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4352+
verifyIncRange(zahv.getIdx(), 0, 1, ERR_ILLEGAL_REG_IDX);
4353+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4354+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4355+
if(16u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4356+
uint32_t code = concat({F(0x7, 29), F(1, 22), F(isStore, 21), F(xm.getIdx(), 16), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(xn.getIdx(), 5), F(zahv.getIdx(), 3), F(zahv.getOffs(), 0)});
4357+
dd(code);
4358+
}
4359+
4360+
void CodeGenerator::SmeZahvContiLdStW(bool isStore, const _ZAHVReg &zahv, const _PReg &pg, const XReg &xm, const XReg &xn) {
4361+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4362+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4363+
verifyIncRange(zahv.getIdx(), 0, 3, ERR_ILLEGAL_REG_IDX);
4364+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4365+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4366+
if(32u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4367+
uint32_t code = concat({F(0x7, 29), F(1, 23), F(isStore, 21), F(xm.getIdx(), 16), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(xn.getIdx(), 5), F(zahv.getIdx(), 2), F(zahv.getOffs(), 0)});
4368+
dd(code);
4369+
}
4370+
4371+
void CodeGenerator::SmeZahvContiLdStD(bool isStore, const _ZAHVReg &zahv, const _PReg &pg, const XReg &xm, const XReg &xn) {
4372+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4373+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4374+
verifyIncRange(zahv.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4375+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4376+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4377+
if(64u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4378+
uint32_t code = concat({F(0x7, 29), F(0x3, 22), F(isStore, 21), F(xm.getIdx(), 16), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(xn.getIdx(), 5), F(zahv.getIdx(), 1), F(zahv.getOffs(), 0)});
4379+
dd(code);
4380+
}
4381+
4382+
void CodeGenerator::SmeZahvContiLdStQ(bool isStore, const _ZAHVReg &zahv, const _PReg &pg, const XReg &xm, const XReg &xn) {
4383+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4384+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4385+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4386+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4387+
if(128u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4388+
uint32_t code = concat({F(0x7, 29), F(0x7, 22), F(isStore, 21), F(xm.getIdx(), 16), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(xn.getIdx(), 5), F(zahv.getIdx(), 0), F(zahv.getOffs(), 0)});
4389+
dd(code);
4390+
}
4391+
4392+
void CodeGenerator::SmeZaContiLdSt(bool isStore, const ZAReg &za, const XReg &xn, const uint32_t offs) {
4393+
int32_t wsIdxPacked = za.getWvIdx()-12;
4394+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4395+
verifyIncRange(za.getOffs() | offs, 0, 15, ERR_ILLEGAL_REG_IDX);
4396+
if(offs != za.getOffs()) throw Error(ERR_ILLEGAL_REG_IDX); // must be equal
4397+
uint32_t code = concat({F(0x7, 29), F(0x4, 22), F(isStore, 21), F(wsIdxPacked, 13), F(xn.getIdx(), 5), F(offs, 0)});
4398+
dd(code);
4399+
}
4400+
4401+
void CodeGenerator::SmeMovTileToVectB(const ZRegB &zd, const _PReg &pg, const _ZAHVReg &za0hv) {
4402+
int32_t wsIdxPacked = za0hv.getWsIdx()-12;
4403+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4404+
verifyIncRange(za0hv.getIdx(), 0, 0, ERR_ILLEGAL_REG_IDX);
4405+
verifyIncRange(za0hv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4406+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4407+
if(8u != za0hv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4408+
uint32_t code = concat({F(0x6, 29), F(1, 17), F(za0hv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(za0hv.getOffs(), 5), F(zd.getIdx(), 0)});
4409+
dd(code);
4410+
}
4411+
4412+
void CodeGenerator::SmeMovTileToVectH(const ZRegH &zd, const _PReg &pg, const _ZAHVReg &zahv) {
4413+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4414+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4415+
verifyIncRange(zahv.getIdx(), 0, 1, ERR_ILLEGAL_REG_IDX);
4416+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4417+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4418+
if(16u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4419+
uint32_t code = concat({F(0x6, 29), F(1, 22), F(1, 17), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zahv.getIdx(), 8), F(zahv.getOffs(), 5), F(zd.getIdx(), 0)});
4420+
dd(code);
4421+
}
4422+
4423+
void CodeGenerator::SmeMovTileToVectS(const ZRegS &zd, const _PReg &pg, const _ZAHVReg &zahv) {
4424+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4425+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4426+
verifyIncRange(zahv.getIdx(), 0, 3, ERR_ILLEGAL_REG_IDX);
4427+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4428+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4429+
if(32u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4430+
uint32_t code = concat({F(0x6, 29), F(2, 22), F(1, 17), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zahv.getIdx(), 7), F(zahv.getOffs(), 5), F(zd.getIdx(), 0)});
4431+
dd(code);
4432+
}
4433+
4434+
void CodeGenerator::SmeMovTileToVectD(const ZRegD &zd, const _PReg &pg, const _ZAHVReg &zahv) {
4435+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4436+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4437+
verifyIncRange(zahv.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4438+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4439+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4440+
if(64u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4441+
uint32_t code = concat({F(0x6, 29), F(3, 22), F(1, 17), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zahv.getIdx(), 6), F(zahv.getOffs(), 5), F(zd.getIdx(), 0)});
4442+
dd(code);
4443+
}
4444+
4445+
void CodeGenerator::SmeMovTileToVectQ(const ZRegQ &zd, const _PReg &pg, const _ZAHVReg &zahv) {
4446+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4447+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4448+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4449+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4450+
if(128u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4451+
uint32_t code = concat({F(0x6, 29), F(3, 22), F(1, 17), F(1, 16), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zahv.getIdx(), 5), F(zahv.getOffs(), 5), F(zd.getIdx(), 0)});
4452+
dd(code);
4453+
}
4454+
4455+
void CodeGenerator::SmeMovVectToTileB(const _ZAHVReg &za0hv, const _PReg &pg, const ZRegB &zn) {
4456+
int32_t wsIdxPacked = za0hv.getWsIdx()-12;
4457+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4458+
verifyIncRange(za0hv.getIdx(), 0, 0, ERR_ILLEGAL_REG_IDX);
4459+
verifyIncRange(za0hv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4460+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4461+
if(8u != za0hv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4462+
uint32_t code = concat({F(0x6, 29), F(za0hv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zn.getIdx(), 5), F(za0hv.getOffs(), 0)});
4463+
dd(code);
4464+
}
4465+
4466+
void CodeGenerator::SmeMovVectToTileH(const _ZAHVReg &zahv, const _PReg &pg, const ZRegH &zn) {
4467+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4468+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4469+
verifyIncRange(zahv.getIdx(), 0, 1, ERR_ILLEGAL_REG_IDX);
4470+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4471+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4472+
if(16u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4473+
uint32_t code = concat({F(0x6, 29), F(1, 22), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zn.getIdx(), 5), F(zahv.getIdx(), 3), F(zahv.getOffs(), 0)});
4474+
dd(code);
4475+
}
4476+
4477+
void CodeGenerator::SmeMovVectToTileS(const _ZAHVReg &zahv, const _PReg &pg, const ZRegS &zn) {
4478+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4479+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4480+
verifyIncRange(zahv.getIdx(), 0, 3, ERR_ILLEGAL_REG_IDX);
4481+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4482+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4483+
if(32u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4484+
uint32_t code = concat({F(0x6, 29), F(2, 22), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zn.getIdx(), 5), F(zahv.getIdx(), 2), F(zahv.getOffs(), 0)});
4485+
dd(code);
4486+
}
4487+
4488+
void CodeGenerator::SmeMovVectToTileD(const _ZAHVReg &zahv, const _PReg &pg, const ZRegD &zn) {
4489+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4490+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4491+
verifyIncRange(zahv.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4492+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4493+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4494+
if(64u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4495+
uint32_t code = concat({F(0x6, 29), F(3, 22), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zn.getIdx(), 5), F(zahv.getIdx(), 1), F(zahv.getOffs(), 0)});
4496+
dd(code);
4497+
}
4498+
4499+
void CodeGenerator::SmeMovVectToTileQ(const _ZAHVReg &zahv, const _PReg &pg, const ZRegQ &zn) {
4500+
int32_t wsIdxPacked = zahv.getWsIdx()-12;
4501+
verifyIncRange(wsIdxPacked, 0, 3, ERR_ILLEGAL_REG_IDX);
4502+
verifyIncRange(zahv.getOffs(), 0, 15, ERR_ILLEGAL_REG_IDX);
4503+
verifyIncRange(pg.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4504+
if(128u != zahv.getBit()) throw Error(ERR_ILLEGAL_TYPE);
4505+
uint32_t code = concat({F(0x6, 29), F(3, 22), F(1, 16), F(zahv.isV(), 15), F(wsIdxPacked, 13), F(pg.getIdx(), 10), F(zn.getIdx(), 5), F(zahv.getIdx(), 0), F(zahv.getOffs(), 0)});
4506+
dd(code);
4507+
}
4508+
4509+
void CodeGenerator::SmeReadMultiplySSRegSize(const XReg &rd, const int32_t imm6) {
4510+
uint32_t masked_imm = (uint32_t)imm6 & 0x3F;
4511+
verifyIncRange(imm6, -32, 31, ERR_ILLEGAL_IMM_RANGE, true);
4512+
uint32_t code = concat({F(0x97EB, 11), F(masked_imm, 5), F(rd.getIdx(), 0)});
4513+
dd(code);
4514+
}
4515+
4516+
// 8 bit sum of outer products to 32-bit
4517+
void CodeGenerator::Sme8bitTo32bitOuterProd(bool isU0, bool isU1, bool isSubtract, const ZARegS &zaS, const _PReg &pn, const _PReg &pm, const ZRegB &zn, const ZRegB &zm) {
4518+
verifyIncRange(pn.getIdx() | pm.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4519+
verifyIncRange(zaS.getIdx(), 0, 3, ERR_ILLEGAL_REG_IDX);
4520+
uint32_t code = concat({F(0x5, 29), F(isU0, 24), F(2, 22), F(isU1, 21), F(zm.getIdx(), 16), F(pm.getIdx(), 13), F(pn.getIdx(), 10), F(zn.getIdx(), 5), F(isSubtract, 4), F(zaS.getIdx(), 0)});
4521+
dd(code);
4522+
}
4523+
4524+
// 16 bit sum of outer products to 64-bit
4525+
void CodeGenerator::Sme16bitTo64bitOuterProd(bool isU0, bool isU1, bool isSubtract, const ZARegD &zaD, const _PReg &pn, const _PReg &pm, const ZRegH &zn, const ZRegH &zm) {
4526+
verifyIncRange(pn.getIdx() | pm.getIdx(), 0, 7, ERR_ILLEGAL_REG_IDX);
4527+
uint32_t code = concat({F(0x5, 29), F(isU0, 24), F(3, 22), F(isU1, 21), F(zm.getIdx(), 16), F(pm.getIdx(), 13), F(pn.getIdx(), 10), F(zn.getIdx(), 5), F(isSubtract, 4), F(zaD.getIdx(), 0)});
4528+
dd(code);
4529+
}
4530+
4531+
void CodeGenerator::SmeZero(std::initializer_list<ZARegD> list) {
4532+
uint32_t imm8 = 0;
4533+
for (auto e : list) {
4534+
imm8 |= 1 << e.getIdx();
4535+
}
4536+
uint32_t code = concat({F(0x3,30), F(1,19), F(imm8,0)});
4537+
dd(code);
4538+
}
4539+
4540+
void CodeGenerator::SmeZero(const ZAReg &za) {
4541+
(void)za;
4542+
uint32_t code = concat({F(0x3,30), F(1,19), F(0xFF,0)});
4543+
dd(code);
4544+
}

0 commit comments

Comments
 (0)