authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-27 12:44:58-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-10 02:04:52-04:00
log7a2963efabfed7cf7e356b698a425cd30aa5620a
tree818f6e79bfd834ec89699172a1638998c91aca3c
parentbbf8abf5d3eb6870b2235f5c18e23239872cda69

x86_64: add avx512 registers


3 files changed, 82 insertions(+), 64 deletions(-)

src/arch/x86_64/Encoding.zig+1-1
...@@ -50,7 +50,7 @@ pub fn findByMnemonic(...@@ -50,7 +50,7 @@ pub fn findByMnemonic(
50 else => {},50 else => {},
51 } else false;51 } else false;
52 const rex_extended = for (ops) |op| {52 const rex_extended = for (ops) |op| {
53 if (op.isBaseExtended() or op.isIndexExtended()) break true;53 if (op.baseExtEnc() != 0b00 or op.indexExtEnc() != 0b00) break true;
54 } else false;54 } else false;
5555
56 if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode;56 if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode;
src/arch/x86_64/bits.zig+33-30
...@@ -360,11 +360,20 @@ pub const Register = enum(u8) {...@@ -360,11 +360,20 @@ pub const Register = enum(u8) {
360360
361 ah, ch, dh, bh,361 ah, ch, dh, bh,
362362
363 ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7,363 zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7,
364 ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15,364 zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15,
365 zmm16, zmm17,zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
366 zmm24, zmm25,zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
365367
366 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,368 ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7,
367 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,369 ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15,
370 ymm16, ymm17,ymm18, ymm19, ymm20, ymm21, ymm22, ymm23,
371 ymm24, ymm25,ymm26, ymm27, ymm28, ymm29, ymm30, ymm31,
372
373 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
374 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
375 xmm16, xmm17,xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
376 xmm24, xmm25,xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
368377
369 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,378 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
370379
...@@ -404,8 +413,9 @@ pub const Register = enum(u8) {...@@ -404,8 +413,9 @@ pub const Register = enum(u8) {
404 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => .general_purpose,413 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => .general_purpose,
405 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => .gphi,414 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => .gphi,
406415
407 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => .sse,416 @intFromEnum(Register.zmm0) ... @intFromEnum(Register.zmm31) => .sse,
408 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => .sse,417 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm31) => .sse,
418 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm31) => .sse,
409 @intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => .mmx,419 @intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => .mmx,
410 @intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => .x87,420 @intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => .x87,
411421
...@@ -428,13 +438,14 @@ pub const Register = enum(u8) {...@@ -428,13 +438,14 @@ pub const Register = enum(u8) {
428 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => @intFromEnum(Register.al),438 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => @intFromEnum(Register.al),
429 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah),439 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah),
430440
431 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => @intFromEnum(Register.ymm0) - 16,441 @intFromEnum(Register.zmm0) ... @intFromEnum(Register.zmm31) => @intFromEnum(Register.zmm0) - 16,
432 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => @intFromEnum(Register.xmm0) - 16,442 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm31) => @intFromEnum(Register.ymm0) - 16,
433 @intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => @intFromEnum(Register.mm0) - 32,443 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm31) => @intFromEnum(Register.xmm0) - 16,
434 @intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => @intFromEnum(Register.st0) - 40,444 @intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => @intFromEnum(Register.mm0) - 48,
435 @intFromEnum(Register.es) ... @intFromEnum(Register.gs) => @intFromEnum(Register.es) - 48,445 @intFromEnum(Register.st0) ... @intFromEnum(Register.st7) => @intFromEnum(Register.st0) - 56,
436 @intFromEnum(Register.cr0) ... @intFromEnum(Register.cr15) => @intFromEnum(Register.cr0) - 54,446 @intFromEnum(Register.es) ... @intFromEnum(Register.gs) => @intFromEnum(Register.es) - 64,
437 @intFromEnum(Register.dr0) ... @intFromEnum(Register.dr15) => @intFromEnum(Register.dr0) - 70,447 @intFromEnum(Register.cr0) ... @intFromEnum(Register.cr15) => @intFromEnum(Register.cr0) - 70,
448 @intFromEnum(Register.dr0) ... @intFromEnum(Register.dr15) => @intFromEnum(Register.dr0) - 86,
438449
439 else => unreachable,450 else => unreachable,
440 // zig fmt: on451 // zig fmt: on
...@@ -451,6 +462,7 @@ pub const Register = enum(u8) {...@@ -451,6 +462,7 @@ pub const Register = enum(u8) {
451 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => 8,462 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => 8,
452 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => 8,463 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => 8,
453464
465 @intFromEnum(Register.zmm0) ... @intFromEnum(Register.zmm15) => 512,
454 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => 256,466 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => 256,
455 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => 128,467 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => 128,
456 @intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => 64,468 @intFromEnum(Register.mm0) ... @intFromEnum(Register.mm7) => 64,
...@@ -474,8 +486,9 @@ pub const Register = enum(u8) {...@@ -474,8 +486,9 @@ pub const Register = enum(u8) {
474 @intFromEnum(Register.r8w) ... @intFromEnum(Register.r15w) => true,486 @intFromEnum(Register.r8w) ... @intFromEnum(Register.r15w) => true,
475 @intFromEnum(Register.r8b) ... @intFromEnum(Register.r15b) => true,487 @intFromEnum(Register.r8b) ... @intFromEnum(Register.r15b) => true,
476488
477 @intFromEnum(Register.ymm8) ... @intFromEnum(Register.ymm15) => true,489 @intFromEnum(Register.zmm8) ... @intFromEnum(Register.zmm31) => true,
478 @intFromEnum(Register.xmm8) ... @intFromEnum(Register.xmm15) => true,490 @intFromEnum(Register.ymm8) ... @intFromEnum(Register.ymm31) => true,
491 @intFromEnum(Register.xmm8) ... @intFromEnum(Register.xmm31) => true,
479492
480 @intFromEnum(Register.cr8) ... @intFromEnum(Register.cr15) => true,493 @intFromEnum(Register.cr8) ... @intFromEnum(Register.cr15) => true,
481 @intFromEnum(Register.dr8) ... @intFromEnum(Register.dr15) => true,494 @intFromEnum(Register.dr8) ... @intFromEnum(Register.dr15) => true,
...@@ -485,7 +498,7 @@ pub const Register = enum(u8) {...@@ -485,7 +498,7 @@ pub const Register = enum(u8) {
485 };498 };
486 }499 }
487500
488 pub fn enc(reg: Register) u4 {501 pub fn enc(reg: Register) u5 {
489 const base = switch (@intFromEnum(reg)) {502 const base = switch (@intFromEnum(reg)) {
490 // zig fmt: off503 // zig fmt: off
491 @intFromEnum(Register.rax) ... @intFromEnum(Register.r15) => @intFromEnum(Register.rax),504 @intFromEnum(Register.rax) ... @intFromEnum(Register.r15) => @intFromEnum(Register.rax),
...@@ -510,10 +523,6 @@ pub const Register = enum(u8) {...@@ -510,10 +523,6 @@ pub const Register = enum(u8) {
510 return @truncate(@intFromEnum(reg) - base);523 return @truncate(@intFromEnum(reg) - base);
511 }524 }
512525
513 pub fn lowEnc(reg: Register) u3 {
514 return @truncate(reg.enc());
515 }
516
517 pub fn toBitSize(reg: Register, bit_size: u64) Register {526 pub fn toBitSize(reg: Register, bit_size: u64) Register {
518 return switch (bit_size) {527 return switch (bit_size) {
519 8 => reg.to8(),528 8 => reg.to8(),
...@@ -558,11 +567,12 @@ pub const Register = enum(u8) {...@@ -558,11 +567,12 @@ pub const Register = enum(u8) {
558 };567 };
559 }568 }
560569
561 fn sseBase(reg: Register) u7 {570 fn sseBase(reg: Register) u8 {
562 assert(reg.class() == .sse);571 assert(reg.class() == .sse);
563 return switch (@intFromEnum(reg)) {572 return switch (@intFromEnum(reg)) {
564 @intFromEnum(Register.ymm0)...@intFromEnum(Register.ymm15) => @intFromEnum(Register.ymm0),573 @intFromEnum(Register.zmm0)...@intFromEnum(Register.zmm31) => @intFromEnum(Register.zmm0),
565 @intFromEnum(Register.xmm0)...@intFromEnum(Register.xmm15) => @intFromEnum(Register.xmm0),574 @intFromEnum(Register.ymm0)...@intFromEnum(Register.ymm31) => @intFromEnum(Register.ymm0),
575 @intFromEnum(Register.xmm0)...@intFromEnum(Register.xmm31) => @intFromEnum(Register.xmm0),
566 else => unreachable,576 else => unreachable,
567 };577 };
568 }578 }
...@@ -682,13 +692,6 @@ pub const Memory = struct {...@@ -682,13 +692,6 @@ pub const Memory = struct {
682 rip_inst: Mir.Inst.Index,692 rip_inst: Mir.Inst.Index,
683693
684 pub const Tag = @typeInfo(Base).@"union".tag_type.?;694 pub const Tag = @typeInfo(Base).@"union".tag_type.?;
685
686 pub fn isExtended(self: Base) bool {
687 return switch (self) {
688 .none, .frame, .table, .reloc, .rip_inst => false, // rsp, rbp, and rip are not extended
689 .reg => |reg| reg.isExtended(),
690 };
691 }
692 };695 };
693696
694 pub const Mod = union(enum(u1)) {697 pub const Mod = union(enum(u1)) {
src/arch/x86_64/encoder.zig+48-33
...@@ -206,19 +206,22 @@ pub const Instruction = struct {...@@ -206,19 +206,22 @@ pub const Instruction = struct {
206 };206 };
207 }207 }
208208
209 pub fn isBaseExtended(op: Operand) bool {209 pub fn baseExtEnc(op: Operand) u2 {
210 return switch (op) {210 return switch (op) {
211 .none, .imm => false,211 .none, .imm => 0b00,
212 .reg => |reg| reg.isExtended(),212 .reg => |reg| @truncate(reg.enc() >> 3),
213 .mem => |mem| mem.base().isExtended(),213 .mem => |mem| switch (mem.base()) {
214 .none, .frame, .table, .reloc, .rip_inst => 0b00, // rsp, rbp, and rip are not extended
215 .reg => |reg| @truncate(reg.enc() >> 3),
216 },
214 .bytes => unreachable,217 .bytes => unreachable,
215 };218 };
216 }219 }
217220
218 pub fn isIndexExtended(op: Operand) bool {221 pub fn indexExtEnc(op: Operand) u2 {
219 return switch (op) {222 return switch (op) {
220 .none, .reg, .imm => false,223 .none, .reg, .imm => 0b00,
221 .mem => |mem| if (mem.scaleIndex()) |si| si.index.isExtended() else false,224 .mem => |mem| if (mem.scaleIndex()) |si| @truncate(si.index.enc() >> 3) else 0b00,
222 .bytes => unreachable,225 .bytes => unreachable,
223 };226 };
224 }227 }
...@@ -422,14 +425,14 @@ pub const Instruction = struct {...@@ -422,14 +425,14 @@ pub const Instruction = struct {
422 };425 };
423 switch (mem_op) {426 switch (mem_op) {
424 .reg => |reg| {427 .reg => |reg| {
425 const rm = switch (data.op_en) {428 const rm: u3 = switch (data.op_en) {
426 .ia, .m, .mi, .m1, .mc, .vm, .vmi => enc.modRmExt(),429 .ia, .m, .mi, .m1, .mc, .vm, .vmi => enc.modRmExt(),
427 .mr, .mri, .mrc => inst.ops[1].reg.lowEnc(),430 .mr, .mri, .mrc => @truncate(inst.ops[1].reg.enc()),
428 .rm, .rmi, .rm0, .rvm, .rvmr, .rvmi, .rmv => inst.ops[0].reg.lowEnc(),431 .rm, .rmi, .rm0, .rvm, .rvmr, .rvmi, .rmv => @truncate(inst.ops[0].reg.enc()),
429 .mvr => inst.ops[2].reg.lowEnc(),432 .mvr => @truncate(inst.ops[2].reg.enc()),
430 else => unreachable,433 else => unreachable,
431 };434 };
432 try encoder.modRm_direct(rm, reg.lowEnc());435 try encoder.modRm_direct(rm, @truncate(reg.enc()));
433 },436 },
434 .mem => |mem| {437 .mem => |mem| {
435 const op = switch (data.op_en) {438 const op = switch (data.op_en) {
...@@ -448,7 +451,7 @@ pub const Instruction = struct {...@@ -448,7 +451,7 @@ pub const Instruction = struct {
448 .ia => try encodeImm(inst.ops[0].imm, data.ops[0], encoder),451 .ia => try encodeImm(inst.ops[0].imm, data.ops[0], encoder),
449 .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),452 .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
450 .rmi, .mri, .vmi => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),453 .rmi, .mri, .vmi => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),
451 .rvmr => try encoder.imm8(@as(u8, inst.ops[3].reg.enc()) << 4),454 .rvmr => try encoder.imm8(@as(u8, @as(u4, @intCast(inst.ops[3].reg.enc()))) << 4),
452 .rvmi => try encodeImm(inst.ops[3].imm, data.ops[3], encoder),455 .rvmi => try encodeImm(inst.ops[3].imm, data.ops[3], encoder),
453 else => {},456 else => {},
454 }457 }
...@@ -462,8 +465,8 @@ pub const Instruction = struct {...@@ -462,8 +465,8 @@ pub const Instruction = struct {
462 const final = opcode.len - 1;465 const final = opcode.len - 1;
463 for (opcode[first..final]) |byte| try encoder.opcode_1byte(byte);466 for (opcode[first..final]) |byte| try encoder.opcode_1byte(byte);
464 switch (inst.encoding.data.op_en) {467 switch (inst.encoding.data.op_en) {
465 .o, .oz, .oi => try encoder.opcode_withReg(opcode[final], inst.ops[0].reg.lowEnc()),468 .o, .oz, .oi => try encoder.opcode_withReg(opcode[final], @truncate(inst.ops[0].reg.enc())),
466 .zo => try encoder.opcode_withReg(opcode[final], inst.ops[1].reg.lowEnc()),469 .zo => try encoder.opcode_withReg(opcode[final], @truncate(inst.ops[1].reg.enc())),
467 else => try encoder.opcode_1byte(opcode[final]),470 else => try encoder.opcode_1byte(opcode[final]),
468 }471 }
469 }472 }
...@@ -533,23 +536,29 @@ pub const Instruction = struct {...@@ -533,23 +536,29 @@ pub const Instruction = struct {
533536
534 switch (op_en) {537 switch (op_en) {
535 .z, .i, .zi, .ii, .ia, .fd, .td, .d => {},538 .z, .i, .zi, .ii, .ia, .fd, .td, .d => {},
536 .o, .oz, .oi => rex.b = inst.ops[0].reg.isExtended(),539 .o, .oz, .oi => rex.b = inst.ops[0].reg.enc() & 0b01000 != 0,
537 .zo => rex.b = inst.ops[1].reg.isExtended(),540 .zo => rex.b = inst.ops[1].reg.enc() & 0b01000 != 0,
538 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0, .rmv => {541 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0, .rmv => {
539 const r_op = switch (op_en) {542 const r_op = switch (op_en) {
540 .rm, .rmi, .rm0, .rmv => inst.ops[0],543 .rm, .rmi, .rm0, .rmv => inst.ops[0],
541 .mr, .mri, .mrc => inst.ops[1],544 .mr, .mri, .mrc => inst.ops[1],
542 else => .none,545 else => .none,
543 };546 };
544 rex.r = r_op.isBaseExtended();547 const r_op_base_ext_enc = r_op.baseExtEnc();
548 rex.r = r_op_base_ext_enc & 0b01 != 0;
549 assert(r_op_base_ext_enc & 0b10 == 0);
545550
546 const b_x_op = switch (op_en) {551 const b_x_op = switch (op_en) {
547 .rm, .rmi, .rm0 => inst.ops[1],552 .rm, .rmi, .rm0 => inst.ops[1],
548 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],553 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
549 else => unreachable,554 else => unreachable,
550 };555 };
551 rex.b = b_x_op.isBaseExtended();556 const b_x_op_base_ext_enc = b_x_op.baseExtEnc();
552 rex.x = b_x_op.isIndexExtended();557 rex.b = b_x_op_base_ext_enc & 0b01 != 0;
558 assert(b_x_op_base_ext_enc & 0b10 == 0);
559 const b_x_op_index_ext_enc = b_x_op.indexExtEnc();
560 rex.x = b_x_op_index_ext_enc & 0b01 != 0;
561 assert(b_x_op_index_ext_enc & 0b10 == 0);
553 },562 },
554 .vm, .vmi, .rvm, .rvmr, .rvmi, .mvr => unreachable,563 .vm, .vmi, .rvm, .rvmr, .rvmi, .mvr => unreachable,
555 }564 }
...@@ -576,7 +585,9 @@ pub const Instruction = struct {...@@ -576,7 +585,9 @@ pub const Instruction = struct {
576 .m, .mi, .m1, .mc, .vm, .vmi => .none,585 .m, .mi, .m1, .mc, .vm, .vmi => .none,
577 else => unreachable,586 else => unreachable,
578 };587 };
579 vex.r = r_op.isBaseExtended();588 const r_op_base_ext_enc = r_op.baseExtEnc();
589 vex.r = r_op_base_ext_enc & 0b01 != 0;
590 assert(r_op_base_ext_enc & 0b10 == 0);
580591
581 const b_x_op = switch (op_en) {592 const b_x_op = switch (op_en) {
582 .rm, .rmi, .rm0, .vm, .vmi, .rmv => inst.ops[1],593 .rm, .rmi, .rm0, .vm, .vmi, .rmv => inst.ops[1],
...@@ -584,8 +595,12 @@ pub const Instruction = struct {...@@ -584,8 +595,12 @@ pub const Instruction = struct {
584 .rvm, .rvmr, .rvmi => inst.ops[2],595 .rvm, .rvmr, .rvmi => inst.ops[2],
585 else => unreachable,596 else => unreachable,
586 };597 };
587 vex.b = b_x_op.isBaseExtended();598 const b_x_op_base_ext_enc = b_x_op.baseExtEnc();
588 vex.x = b_x_op.isIndexExtended();599 vex.b = b_x_op_base_ext_enc & 0b01 != 0;
600 assert(b_x_op_base_ext_enc & 0b10 == 0);
601 const b_x_op_index_ext_enc = b_x_op.indexExtEnc();
602 vex.x = b_x_op_index_ext_enc & 0b01 != 0;
603 assert(b_x_op_index_ext_enc & 0b10 == 0);
589 },604 },
590 }605 }
591606
...@@ -622,8 +637,8 @@ pub const Instruction = struct {...@@ -622,8 +637,8 @@ pub const Instruction = struct {
622 }637 }
623638
624 fn encodeMemory(encoding: Encoding, mem: Memory, operand: Operand, encoder: anytype) !void {639 fn encodeMemory(encoding: Encoding, mem: Memory, operand: Operand, encoder: anytype) !void {
625 const operand_enc = switch (operand) {640 const operand_enc: u3 = switch (operand) {
626 .reg => |reg| reg.lowEnc(),641 .reg => |reg| @truncate(reg.enc()),
627 .none => encoding.modRmExt(),642 .none => encoding.modRmExt(),
628 else => unreachable,643 else => unreachable,
629 };644 };
...@@ -635,7 +650,7 @@ pub const Instruction = struct {...@@ -635,7 +650,7 @@ pub const Instruction = struct {
635 try encoder.modRm_SIBDisp0(operand_enc);650 try encoder.modRm_SIBDisp0(operand_enc);
636 if (mem.scaleIndex()) |si| {651 if (mem.scaleIndex()) |si| {
637 const scale = math.log2_int(u4, si.scale);652 const scale = math.log2_int(u4, si.scale);
638 try encoder.sib_scaleIndexDisp32(scale, si.index.lowEnc());653 try encoder.sib_scaleIndexDisp32(scale, @truncate(si.index.enc()));
639 } else {654 } else {
640 try encoder.sib_disp32();655 try encoder.sib_disp32();
641 }656 }
...@@ -647,21 +662,21 @@ pub const Instruction = struct {...@@ -647,21 +662,21 @@ pub const Instruction = struct {
647 try encoder.modRm_SIBDisp0(operand_enc);662 try encoder.modRm_SIBDisp0(operand_enc);
648 if (mem.scaleIndex()) |si| {663 if (mem.scaleIndex()) |si| {
649 const scale = math.log2_int(u4, si.scale);664 const scale = math.log2_int(u4, si.scale);
650 try encoder.sib_scaleIndexDisp32(scale, si.index.lowEnc());665 try encoder.sib_scaleIndexDisp32(scale, @truncate(si.index.enc()));
651 } else {666 } else {
652 try encoder.sib_disp32();667 try encoder.sib_disp32();
653 }668 }
654 try encoder.disp32(sib.disp);669 try encoder.disp32(sib.disp);
655 },670 },
656 .general_purpose => {671 .general_purpose => {
657 const dst = base.lowEnc();672 const dst: u3 = @truncate(base.enc());
658 const src = operand_enc;673 const src = operand_enc;
659 if (dst == 4 or mem.scaleIndex() != null) {674 if (dst == 4 or mem.scaleIndex() != null) {
660 if (sib.disp == 0 and dst != 5) {675 if (sib.disp == 0 and dst != 5) {
661 try encoder.modRm_SIBDisp0(src);676 try encoder.modRm_SIBDisp0(src);
662 if (mem.scaleIndex()) |si| {677 if (mem.scaleIndex()) |si| {
663 const scale = math.log2_int(u4, si.scale);678 const scale = math.log2_int(u4, si.scale);
664 try encoder.sib_scaleIndexBase(scale, si.index.lowEnc(), dst);679 try encoder.sib_scaleIndexBase(scale, @truncate(si.index.enc()), dst);
665 } else {680 } else {
666 try encoder.sib_base(dst);681 try encoder.sib_base(dst);
667 }682 }
...@@ -669,7 +684,7 @@ pub const Instruction = struct {...@@ -669,7 +684,7 @@ pub const Instruction = struct {
669 try encoder.modRm_SIBDisp8(src);684 try encoder.modRm_SIBDisp8(src);
670 if (mem.scaleIndex()) |si| {685 if (mem.scaleIndex()) |si| {
671 const scale = math.log2_int(u4, si.scale);686 const scale = math.log2_int(u4, si.scale);
672 try encoder.sib_scaleIndexBaseDisp8(scale, si.index.lowEnc(), dst);687 try encoder.sib_scaleIndexBaseDisp8(scale, @truncate(si.index.enc()), dst);
673 } else {688 } else {
674 try encoder.sib_baseDisp8(dst);689 try encoder.sib_baseDisp8(dst);
675 }690 }
...@@ -678,7 +693,7 @@ pub const Instruction = struct {...@@ -678,7 +693,7 @@ pub const Instruction = struct {
678 try encoder.modRm_SIBDisp32(src);693 try encoder.modRm_SIBDisp32(src);
679 if (mem.scaleIndex()) |si| {694 if (mem.scaleIndex()) |si| {
680 const scale = math.log2_int(u4, si.scale);695 const scale = math.log2_int(u4, si.scale);
681 try encoder.sib_scaleIndexBaseDisp32(scale, si.index.lowEnc(), dst);696 try encoder.sib_scaleIndexBaseDisp32(scale, @truncate(si.index.enc()), dst);
682 } else {697 } else {
683 try encoder.sib_baseDisp32(dst);698 try encoder.sib_baseDisp32(dst);
684 }699 }
...@@ -867,7 +882,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -867,7 +882,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
867882
868 try self.writer.writeByte(883 try self.writer.writeByte(
869 @as(u8, @intFromBool(fields.w)) << 7 |884 @as(u8, @intFromBool(fields.w)) << 7 |
870 @as(u8, ~fields.v.enc()) << 3 |885 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |
871 @as(u8, @intFromBool(fields.l)) << 2 |886 @as(u8, @intFromBool(fields.l)) << 2 |
872 @as(u8, @intFromEnum(fields.p)) << 0,887 @as(u8, @intFromEnum(fields.p)) << 0,
873 );888 );
...@@ -875,7 +890,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -875,7 +890,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
875 try self.writer.writeByte(0b1100_0101);890 try self.writer.writeByte(0b1100_0101);
876 try self.writer.writeByte(891 try self.writer.writeByte(
877 @as(u8, ~@intFromBool(fields.r)) << 7 |892 @as(u8, ~@intFromBool(fields.r)) << 7 |
878 @as(u8, ~fields.v.enc()) << 3 |893 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |
879 @as(u8, @intFromBool(fields.l)) << 2 |894 @as(u8, @intFromBool(fields.l)) << 2 |
880 @as(u8, @intFromEnum(fields.p)) << 0,895 @as(u8, @intFromEnum(fields.p)) << 0,
881 );896 );