Skip to content

Commit e8e7b60

Browse files
committed
extended corpus
1 parent dc36145 commit e8e7b60

4 files changed

Lines changed: 387 additions & 1 deletion

File tree

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
- [ ] Compare against a reference runner (choose one):
5656
- [x] WASM path: `zrun` (behavioral oracle for ABI-visible semantics)
5757
- [ ] Interpreter path: `zem` (only where it matches runtime semantics; do not treat as VM design source)
58-
- [x] Run over example corpus (hello/cat/upper/alloc/isa_smoke/log) + selected fixtures (currently: ret_only + hello + cat + upper + alloc + isa_smoke + log)
58+
- [x] Run over example corpus (hello/cat/upper/alloc/isa_smoke/log/bytes/loop/arithmetic) + selected fixtures (currently: ret_only + hello + cat + upper + alloc + isa_smoke + log + bytes + loop + arithmetic)
5959
- [ ] Add minimization hook (optional) for shrinking divergent cases
6060

6161
- [x] Fix arm64 bounds-check trailer (was trapping unconditionally due to `b +1; brk` sequence)

src/common/zasm_verify.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ zasm_verify_result_t zasm_verify_decode(const uint8_t* code, size_t code_len,
287287
case 0x17: case 0x18: case 0x19:
288288
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
289289
case 0x27: case 0x28: case 0x29:
290+
case 0x35: case 0x36: case 0x37:
291+
case 0x45: case 0x46: case 0x47:
290292
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55:
291293
case 0x56: case 0x57: case 0x58: case 0x59:
292294
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65:

src/zxc/arm64.c

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ static uint32_t enc_cmp_reg(int is64, uint8_t rn, uint8_t rm) {
222222
((uint32_t)rm << 16) | ((uint32_t)rn << 5);
223223
}
224224

225+
static uint32_t enc_clz(int is64, uint8_t rd, uint8_t rn) {
226+
return (is64 ? 0xDAC01000u : 0x5AC01000u) | ((uint32_t)rn << 5) | rd;
227+
}
228+
229+
static uint32_t enc_rbit(int is64, uint8_t rd, uint8_t rn) {
230+
return (is64 ? 0xDAC00000u : 0x5AC00000u) | ((uint32_t)rn << 5) | rd;
231+
}
232+
225233
static uint32_t enc_cset(int is64, uint8_t rd, uint8_t cond) {
226234
uint32_t base = is64 ? 0x9A9F07E0u : 0x1A9F07E0u;
227235
uint8_t inv = (uint8_t)(cond ^ 1u);
@@ -507,6 +515,31 @@ static int zxc_arm64_size_at(const uint8_t* in, size_t in_len, size_t off,
507515
size_t n_off = off + 4;
508516

509517
switch (op) {
518+
case 0x35: /* CLZ */
519+
case 0x45: /* CLZ64 */
520+
sz = 4;
521+
break;
522+
case 0x36: /* CTZ */
523+
case 0x46: /* CTZ64 */
524+
sz = 8;
525+
break;
526+
case 0x37: /* POPC */
527+
case 0x47: /* POPC64 */
528+
{
529+
int is64p = (op == 0x47);
530+
uint64_t mask1 = is64p ? 0x5555555555555555ull : 0x55555555ull;
531+
uint64_t mask2 = is64p ? 0x3333333333333333ull : 0x33333333ull;
532+
uint64_t mask3 = is64p ? 0x0F0F0F0F0F0F0F0Full : 0x0F0F0F0Full;
533+
uint64_t maskf = is64p ? 0x7Full : 0x3Full;
534+
535+
/* POPC emission uses 4 constant materializations (mask1, mask2, mask3, final mask)
536+
plus a fixed number of ALU/shift instructions. Keep in sync with translate(). */
537+
size_t mov_sz = mov_imm64_size(mask1) + mov_imm64_size(mask2) +
538+
mov_imm64_size(mask3) + mov_imm64_size(maskf);
539+
size_t fixed_insn = is64p ? 23u : 20u;
540+
sz = mov_sz + fixed_insn * 4u;
541+
}
542+
break;
510543
case ZOP_DIVS:
511544
case ZOP_DIVU:
512545
case ZOP_DIVS64:
@@ -751,6 +784,225 @@ zxc_result_t zxc_arm64_translate(const uint8_t* in, size_t in_len,
751784
/* Read the dropped register but discard the value (matches WASM local.get + drop). */
752785
enc = enc_orr_reg(1, 31, rd_m, 31);
753786
break;
787+
case 0x35: /* CLZ */
788+
enc = enc_clz(0, rd_m, rd_m);
789+
break;
790+
case 0x45: /* CLZ64 */
791+
enc = enc_clz(1, rd_m, rd_m);
792+
break;
793+
case 0x36: /* CTZ */
794+
if (!emit_u32(out, out_cap, &out_len, enc_rbit(0, ZXC_SCRATCH, rd_m))) {
795+
res.err = ZXC_ERR_OUTBUF;
796+
res.in_off = insn_off;
797+
res.out_len = out_len;
798+
return res;
799+
}
800+
enc = enc_clz(0, rd_m, ZXC_SCRATCH);
801+
break;
802+
case 0x46: /* CTZ64 */
803+
if (!emit_u32(out, out_cap, &out_len, enc_rbit(1, ZXC_SCRATCH, rd_m))) {
804+
res.err = ZXC_ERR_OUTBUF;
805+
res.in_off = insn_off;
806+
res.out_len = out_len;
807+
return res;
808+
}
809+
enc = enc_clz(1, rd_m, ZXC_SCRATCH);
810+
break;
811+
case 0x37: /* POPC */
812+
case 0x47: /* POPC64 */
813+
{
814+
int is64p = (op == 0x47);
815+
uint8_t x = rd_m;
816+
uint8_t t = ZXC_SCRATCH;
817+
uint8_t sh = ZXC_SCRATCH2;
818+
uint8_t m1 = ZXC_SCRATCH3;
819+
uint8_t m2 = ZXC_SCRATCH4;
820+
821+
uint64_t mask1 = is64p ? 0x5555555555555555ull : 0x55555555ull;
822+
uint64_t mask2 = is64p ? 0x3333333333333333ull : 0x33333333ull;
823+
uint64_t mask3 = is64p ? 0x0F0F0F0F0F0F0F0Full : 0x0F0F0F0Full;
824+
uint64_t maskf = is64p ? 0x7Full : 0x3Full;
825+
826+
if (!emit_mov_imm64(out, out_cap, &out_len, m1, mask1)) {
827+
res.err = ZXC_ERR_OUTBUF;
828+
res.in_off = insn_off;
829+
res.out_len = out_len;
830+
return res;
831+
}
832+
if (!emit_mov_imm64(out, out_cap, &out_len, m2, mask2)) {
833+
res.err = ZXC_ERR_OUTBUF;
834+
res.in_off = insn_off;
835+
res.out_len = out_len;
836+
return res;
837+
}
838+
839+
/* x = x - ((x >> 1) & mask1) */
840+
if (!emit_u32(out, out_cap, &out_len, enc_add_imm(is64p, sh, 31, 1))) {
841+
res.err = ZXC_ERR_OUTBUF;
842+
res.in_off = insn_off;
843+
res.out_len = out_len;
844+
return res;
845+
}
846+
if (!emit_u32(out, out_cap, &out_len, enc_lsrv(is64p, t, x, sh))) {
847+
res.err = ZXC_ERR_OUTBUF;
848+
res.in_off = insn_off;
849+
res.out_len = out_len;
850+
return res;
851+
}
852+
if (!emit_u32(out, out_cap, &out_len, enc_and_reg(is64p, t, t, m1))) {
853+
res.err = ZXC_ERR_OUTBUF;
854+
res.in_off = insn_off;
855+
res.out_len = out_len;
856+
return res;
857+
}
858+
if (!emit_u32(out, out_cap, &out_len, enc_sub_reg(is64p, x, x, t))) {
859+
res.err = ZXC_ERR_OUTBUF;
860+
res.in_off = insn_off;
861+
res.out_len = out_len;
862+
return res;
863+
}
864+
865+
/* x = (x & mask2) + ((x >> 2) & mask2) */
866+
if (!emit_u32(out, out_cap, &out_len, enc_add_imm(is64p, sh, 31, 2))) {
867+
res.err = ZXC_ERR_OUTBUF;
868+
res.in_off = insn_off;
869+
res.out_len = out_len;
870+
return res;
871+
}
872+
if (!emit_u32(out, out_cap, &out_len, enc_lsrv(is64p, t, x, sh))) {
873+
res.err = ZXC_ERR_OUTBUF;
874+
res.in_off = insn_off;
875+
res.out_len = out_len;
876+
return res;
877+
}
878+
if (!emit_u32(out, out_cap, &out_len, enc_and_reg(is64p, t, t, m2))) {
879+
res.err = ZXC_ERR_OUTBUF;
880+
res.in_off = insn_off;
881+
res.out_len = out_len;
882+
return res;
883+
}
884+
if (!emit_u32(out, out_cap, &out_len, enc_and_reg(is64p, sh, x, m2))) {
885+
res.err = ZXC_ERR_OUTBUF;
886+
res.in_off = insn_off;
887+
res.out_len = out_len;
888+
return res;
889+
}
890+
if (!emit_u32(out, out_cap, &out_len, enc_add_reg(is64p, x, sh, t))) {
891+
res.err = ZXC_ERR_OUTBUF;
892+
res.in_off = insn_off;
893+
res.out_len = out_len;
894+
return res;
895+
}
896+
897+
/* x = (x + (x >> 4)) & mask3 */
898+
if (!emit_u32(out, out_cap, &out_len, enc_add_imm(is64p, sh, 31, 4))) {
899+
res.err = ZXC_ERR_OUTBUF;
900+
res.in_off = insn_off;
901+
res.out_len = out_len;
902+
return res;
903+
}
904+
if (!emit_u32(out, out_cap, &out_len, enc_lsrv(is64p, t, x, sh))) {
905+
res.err = ZXC_ERR_OUTBUF;
906+
res.in_off = insn_off;
907+
res.out_len = out_len;
908+
return res;
909+
}
910+
if (!emit_u32(out, out_cap, &out_len, enc_add_reg(is64p, x, x, t))) {
911+
res.err = ZXC_ERR_OUTBUF;
912+
res.in_off = insn_off;
913+
res.out_len = out_len;
914+
return res;
915+
}
916+
if (!emit_mov_imm64(out, out_cap, &out_len, m1, mask3)) {
917+
res.err = ZXC_ERR_OUTBUF;
918+
res.in_off = insn_off;
919+
res.out_len = out_len;
920+
return res;
921+
}
922+
if (!emit_u32(out, out_cap, &out_len, enc_and_reg(is64p, x, x, m1))) {
923+
res.err = ZXC_ERR_OUTBUF;
924+
res.in_off = insn_off;
925+
res.out_len = out_len;
926+
return res;
927+
}
928+
929+
/* x += x>>8; x += x>>16; (x += x>>32 for 64-bit) */
930+
if (!emit_u32(out, out_cap, &out_len, enc_add_imm(is64p, sh, 31, 8))) {
931+
res.err = ZXC_ERR_OUTBUF;
932+
res.in_off = insn_off;
933+
res.out_len = out_len;
934+
return res;
935+
}
936+
if (!emit_u32(out, out_cap, &out_len, enc_lsrv(is64p, t, x, sh))) {
937+
res.err = ZXC_ERR_OUTBUF;
938+
res.in_off = insn_off;
939+
res.out_len = out_len;
940+
return res;
941+
}
942+
if (!emit_u32(out, out_cap, &out_len, enc_add_reg(is64p, x, x, t))) {
943+
res.err = ZXC_ERR_OUTBUF;
944+
res.in_off = insn_off;
945+
res.out_len = out_len;
946+
return res;
947+
}
948+
949+
if (!emit_u32(out, out_cap, &out_len, enc_add_imm(is64p, sh, 31, 16))) {
950+
res.err = ZXC_ERR_OUTBUF;
951+
res.in_off = insn_off;
952+
res.out_len = out_len;
953+
return res;
954+
}
955+
if (!emit_u32(out, out_cap, &out_len, enc_lsrv(is64p, t, x, sh))) {
956+
res.err = ZXC_ERR_OUTBUF;
957+
res.in_off = insn_off;
958+
res.out_len = out_len;
959+
return res;
960+
}
961+
if (!emit_u32(out, out_cap, &out_len, enc_add_reg(is64p, x, x, t))) {
962+
res.err = ZXC_ERR_OUTBUF;
963+
res.in_off = insn_off;
964+
res.out_len = out_len;
965+
return res;
966+
}
967+
968+
if (is64p) {
969+
if (!emit_u32(out, out_cap, &out_len, enc_add_imm(is64p, sh, 31, 32))) {
970+
res.err = ZXC_ERR_OUTBUF;
971+
res.in_off = insn_off;
972+
res.out_len = out_len;
973+
return res;
974+
}
975+
if (!emit_u32(out, out_cap, &out_len, enc_lsrv(is64p, t, x, sh))) {
976+
res.err = ZXC_ERR_OUTBUF;
977+
res.in_off = insn_off;
978+
res.out_len = out_len;
979+
return res;
980+
}
981+
if (!emit_u32(out, out_cap, &out_len, enc_add_reg(is64p, x, x, t))) {
982+
res.err = ZXC_ERR_OUTBUF;
983+
res.in_off = insn_off;
984+
res.out_len = out_len;
985+
return res;
986+
}
987+
}
988+
989+
if (!emit_mov_imm64(out, out_cap, &out_len, m2, maskf)) {
990+
res.err = ZXC_ERR_OUTBUF;
991+
res.in_off = insn_off;
992+
res.out_len = out_len;
993+
return res;
994+
}
995+
if (!emit_u32(out, out_cap, &out_len, enc_and_reg(is64p, x, x, m2))) {
996+
res.err = ZXC_ERR_OUTBUF;
997+
res.in_off = insn_off;
998+
res.out_len = out_len;
999+
return res;
1000+
}
1001+
1002+
enc = 0;
1003+
off += 4;
1004+
continue;
1005+
}
7541006
case ZOP_ADD: is64 = 0; enc = enc_add_reg(is64, rd_m, rs1_m, rs2_m); break;
7551007
case ZOP_SUB: is64 = 0; enc = enc_sub_reg(is64, rd_m, rs1_m, rs2_m); break;
7561008
case ZOP_MUL: is64 = 0; enc = enc_madd(is64, rd_m, rs1_m, rs2_m, 31); break;

0 commit comments

Comments
 (0)