| ... | @@ -66,40 +66,45 @@ pub fn emitMir(emit: *Emit) InnerError!void { | ... | @@ -66,40 +66,45 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 66 | const inst = @intCast(u32, index); | 66 | const inst = @intCast(u32, index); |
| 67 | try emit.code_offset_mapping.putNoClobber(emit.bin_file.allocator, inst, emit.code.items.len); | 67 | try emit.code_offset_mapping.putNoClobber(emit.bin_file.allocator, inst, emit.code.items.len); |
| 68 | switch (tag) { | 68 | switch (tag) { |
| 69 | .adc, .add, .sub, .xor, .@"and", .@"or", .sbb, .cmp, .mov => try emit.mirArith(tag, inst), | 69 | .adc => try emit.mirArith(.adc, inst), |
| 70 | | 70 | .add => try emit.mirArith(.add, inst), |
| 71 | .adc_scale_src, | 71 | .sub => try emit.mirArith(.sub, inst), |
| 72 | .add_scale_src, | 72 | .xor => try emit.mirArith(.xor, inst), |
| 73 | .sub_scale_src, | 73 | .@"and" => try emit.mirArith(.@"and", inst), |
| 74 | .xor_scale_src, | 74 | .@"or" => try emit.mirArith(.@"or", inst), |
| 75 | .and_scale_src, | 75 | .sbb => try emit.mirArith(.sbb, inst), |
| 76 | .or_scale_src, | 76 | .cmp => try emit.mirArith(.cmp, inst), |
| 77 | .sbb_scale_src, | 77 | .mov => try emit.mirArith(.mov, inst), |
| 78 | .cmp_scale_src, | 78 | |
| 79 | .mov_scale_src, | 79 | .adc_scale_src => try emit.mirArithScaleSrc(.adc, inst), |
| 80 | => try emit.mirArithScaleSrc(tag, inst), | 80 | .add_scale_src => try emit.mirArithScaleSrc(.add, inst), |
| 81 | | 81 | .sub_scale_src => try emit.mirArithScaleSrc(.sub, inst), |
| 82 | .adc_scale_dst, | 82 | .xor_scale_src => try emit.mirArithScaleSrc(.xor, inst), |
| 83 | .add_scale_dst, | 83 | .and_scale_src => try emit.mirArithScaleSrc(.@"and", inst), |
| 84 | .sub_scale_dst, | 84 | .or_scale_src => try emit.mirArithScaleSrc(.@"or", inst), |
| 85 | .xor_scale_dst, | 85 | .sbb_scale_src => try emit.mirArithScaleSrc(.sbb, inst), |
| 86 | .and_scale_dst, | 86 | .cmp_scale_src => try emit.mirArithScaleSrc(.cmp, inst), |
| 87 | .or_scale_dst, | 87 | .mov_scale_src => try emit.mirArithScaleSrc(.mov, inst), |
| 88 | .sbb_scale_dst, | 88 | |
| 89 | .cmp_scale_dst, | 89 | .adc_scale_dst => try emit.mirArithScaleDst(.adc, inst), |
| 90 | .mov_scale_dst, | 90 | .add_scale_dst => try emit.mirArithScaleDst(.add, inst), |
| 91 | => try emit.mirArithScaleDst(tag, inst), | 91 | .sub_scale_dst => try emit.mirArithScaleDst(.sub, inst), |
| 92 | | 92 | .xor_scale_dst => try emit.mirArithScaleDst(.xor, inst), |
| 93 | .adc_scale_imm, | 93 | .and_scale_dst => try emit.mirArithScaleDst(.@"and", inst), |
| 94 | .add_scale_imm, | 94 | .or_scale_dst => try emit.mirArithScaleDst(.@"or", inst), |
| 95 | .sub_scale_imm, | 95 | .sbb_scale_dst => try emit.mirArithScaleDst(.sbb, inst), |
| 96 | .xor_scale_imm, | 96 | .cmp_scale_dst => try emit.mirArithScaleDst(.cmp, inst), |
| 97 | .and_scale_imm, | 97 | .mov_scale_dst => try emit.mirArithScaleDst(.mov, inst), |
| 98 | .or_scale_imm, | 98 | |
| 99 | .sbb_scale_imm, | 99 | .adc_scale_imm => try emit.mirArithScaleImm(.adc, inst), |
| 100 | .cmp_scale_imm, | 100 | .add_scale_imm => try emit.mirArithScaleImm(.add, inst), |
| 101 | .mov_scale_imm, | 101 | .sub_scale_imm => try emit.mirArithScaleImm(.sub, inst), |
| 102 | => try emit.mirArithScaleImm(tag, inst), | 102 | .xor_scale_imm => try emit.mirArithScaleImm(.xor, inst), |
| | 103 | .and_scale_imm => try emit.mirArithScaleImm(.@"and", inst), |
| | 104 | .or_scale_imm => try emit.mirArithScaleImm(.@"or", inst), |
| | 105 | .sbb_scale_imm => try emit.mirArithScaleImm(.sbb, inst), |
| | 106 | .cmp_scale_imm => try emit.mirArithScaleImm(.cmp, inst), |
| | 107 | .mov_scale_imm => try emit.mirArithScaleImm(.mov, inst), |
| 103 | | 108 | |
| 104 | .movabs => try emit.mirMovabs(inst), | 109 | .movabs => try emit.mirMovabs(inst), |
| 105 | | 110 | |
| ... | @@ -110,7 +115,8 @@ pub fn emitMir(emit: *Emit) InnerError!void { | ... | @@ -110,7 +115,8 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 110 | | 115 | |
| 111 | .push, .pop => try emit.mirPushPop(tag, inst), | 116 | .push, .pop => try emit.mirPushPop(tag, inst), |
| 112 | | 117 | |
| 113 | .jmp, .call => try emit.mirJmpCall(tag, inst), | 118 | .jmp => try emit.mirJmpCall(.jmp_near, inst), |
| | 119 | .call => try emit.mirJmpCall(.call_near, inst), |
| 114 | | 120 | |
| 115 | .cond_jmp_greater_less, | 121 | .cond_jmp_greater_less, |
| 116 | .cond_jmp_above_below, | 122 | .cond_jmp_above_below, |
| ... | @@ -283,31 +289,24 @@ fn mirPushPopRegsFromCalleePreservedRegs(emit: *Emit, tag: Mir.Inst.Tag, inst: M | ... | @@ -283,31 +289,24 @@ fn mirPushPopRegsFromCalleePreservedRegs(emit: *Emit, tag: Mir.Inst.Tag, inst: M |
| 283 | } | 289 | } |
| 284 | } | 290 | } |
| 285 | | 291 | |
| 286 | fn mirJmpCall(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | 292 | fn mirJmpCall(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 287 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 293 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 288 | const flag = @truncate(u1, ops.flags); | 294 | const flag = @truncate(u1, ops.flags); |
| 289 | if (flag == 0) { | 295 | if (flag == 0) { |
| 290 | const target = emit.mir.instructions.items(.data)[inst].inst; | 296 | const target = emit.mir.instructions.items(.data)[inst].inst; |
| 291 | const opc: u8 = switch (tag) { | | |
| 292 | .jmp => 0xe9, | | |
| 293 | .call => 0xe8, | | |
| 294 | else => unreachable, | | |
| 295 | }; | | |
| 296 | const source = emit.code.items.len; | 297 | const source = emit.code.items.len; |
| 297 | const encoder = try Encoder.init(emit.code, 5); | 298 | try lowerToDEnc(tag, 0, emit.code); |
| 298 | encoder.opcode_1byte(opc); | | |
| 299 | try emit.relocs.append(emit.bin_file.allocator, .{ | 299 | try emit.relocs.append(emit.bin_file.allocator, .{ |
| 300 | .source = source, | 300 | .source = source, |
| 301 | .target = target, | 301 | .target = target, |
| 302 | .offset = emit.code.items.len, | 302 | .offset = emit.code.items.len - 4, |
| 303 | .length = 5, | 303 | .length = 5, |
| 304 | }); | 304 | }); |
| 305 | encoder.imm32(0x0); | | |
| 306 | return; | 305 | return; |
| 307 | } | 306 | } |
| 308 | const modrm_ext: u3 = switch (tag) { | 307 | const modrm_ext: u3 = switch (tag) { |
| 309 | .jmp => 0x4, | 308 | .jmp_near => 0x4, |
| 310 | .call => 0x2, | 309 | .call_near => 0x2, |
| 311 | else => unreachable, | 310 | else => unreachable, |
| 312 | }; | 311 | }; |
| 313 | if (ops.reg1 == .none) { | 312 | if (ops.reg1 == .none) { |
| ... | @@ -532,7 +531,28 @@ fn mirRet(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ... | @@ -532,7 +531,28 @@ fn mirRet(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 532 | } | 531 | } |
| 533 | } | 532 | } |
| 534 | | 533 | |
| | 534 | const Tag = enum { |
| | 535 | adc, |
| | 536 | add, |
| | 537 | sub, |
| | 538 | xor, |
| | 539 | @"and", |
| | 540 | @"or", |
| | 541 | sbb, |
| | 542 | cmp, |
| | 543 | mov, |
| | 544 | lea, |
| | 545 | jmp_near, |
| | 546 | call_near, |
| | 547 | }; |
| | 548 | |
| 535 | const Encoding = enum { | 549 | const Encoding = enum { |
| | 550 | /// OP rel32 |
| | 551 | d, |
| | 552 | |
| | 553 | /// OP r/m64 |
| | 554 | m, |
| | 555 | |
| 536 | /// OP r/m64, imm32 | 556 | /// OP r/m64, imm32 |
| 537 | mi, | 557 | mi, |
| 538 | | 558 | |
| ... | @@ -552,12 +572,21 @@ const Encoding = enum { | ... | @@ -552,12 +572,21 @@ const Encoding = enum { |
| 552 | td, | 572 | td, |
| 553 | }; | 573 | }; |
| 554 | | 574 | |
| 555 | inline fn getOpCode(tag: Mir.Inst.Tag, enc: Encoding) u8 { | 575 | inline fn getOpCode(tag: Tag, enc: Encoding) ?u8 { |
| 556 | switch (enc) { | 576 | switch (enc) { |
| | 577 | .d => return switch (tag) { |
| | 578 | .jmp_near => 0xe9, |
| | 579 | .call_near => 0xe8, |
| | 580 | else => null, |
| | 581 | }, |
| | 582 | .m => return switch (tag) { |
| | 583 | .jmp_near, .call_near => 0xff, |
| | 584 | else => null, |
| | 585 | }, |
| 557 | .mi => return switch (tag) { | 586 | .mi => return switch (tag) { |
| 558 | .adc, .add, .sub, .xor, .@"and", .@"or", .sbb, .cmp => 0x81, | 587 | .adc, .add, .sub, .xor, .@"and", .@"or", .sbb, .cmp => 0x81, |
| 559 | .mov => 0xc7, | 588 | .mov => 0xc7, |
| 560 | else => unreachable, | 589 | else => null, |
| 561 | }, | 590 | }, |
| 562 | .mr => return switch (tag) { | 591 | .mr => return switch (tag) { |
| 563 | .adc => 0x11, | 592 | .adc => 0x11, |
| ... | @@ -569,7 +598,7 @@ inline fn getOpCode(tag: Mir.Inst.Tag, enc: Encoding) u8 { | ... | @@ -569,7 +598,7 @@ inline fn getOpCode(tag: Mir.Inst.Tag, enc: Encoding) u8 { |
| 569 | .sbb => 0x19, | 598 | .sbb => 0x19, |
| 570 | .cmp => 0x39, | 599 | .cmp => 0x39, |
| 571 | .mov => 0x89, | 600 | .mov => 0x89, |
| 572 | else => unreachable, | 601 | else => null, |
| 573 | }, | 602 | }, |
| 574 | .rm => return switch (tag) { | 603 | .rm => return switch (tag) { |
| 575 | .adc => 0x13, | 604 | .adc => 0x13, |
| ... | @@ -582,24 +611,24 @@ inline fn getOpCode(tag: Mir.Inst.Tag, enc: Encoding) u8 { | ... | @@ -582,24 +611,24 @@ inline fn getOpCode(tag: Mir.Inst.Tag, enc: Encoding) u8 { |
| 582 | .cmp => 0x3b, | 611 | .cmp => 0x3b, |
| 583 | .mov => 0x8b, | 612 | .mov => 0x8b, |
| 584 | .lea => 0x8d, | 613 | .lea => 0x8d, |
| 585 | else => unreachable, | 614 | else => null, |
| 586 | }, | 615 | }, |
| 587 | .oi => return switch (tag) { | 616 | .oi => return switch (tag) { |
| 588 | .mov => 0xb8, | 617 | .mov => 0xb8, |
| 589 | else => unreachable, | 618 | else => null, |
| 590 | }, | 619 | }, |
| 591 | .fd => return switch (tag) { | 620 | .fd => return switch (tag) { |
| 592 | .mov => 0xa1, | 621 | .mov => 0xa1, |
| 593 | else => unreachable, | 622 | else => null, |
| 594 | }, | 623 | }, |
| 595 | .td => return switch (tag) { | 624 | .td => return switch (tag) { |
| 596 | .mov => 0xa3, | 625 | .mov => 0xa3, |
| 597 | else => unreachable, | 626 | else => null, |
| 598 | }, | 627 | }, |
| 599 | } | 628 | } |
| 600 | } | 629 | } |
| 601 | | 630 | |
| 602 | inline fn getMiModRmExt(tag: Mir.Inst.Tag) u3 { | 631 | inline fn getModRmExt(tag: Tag) u3 { |
| 603 | return switch (tag) { | 632 | return switch (tag) { |
| 604 | .adc => 0x2, | 633 | .adc => 0x2, |
| 605 | .add => 0x0, | 634 | .add => 0x0, |
| ... | @@ -610,6 +639,7 @@ inline fn getMiModRmExt(tag: Mir.Inst.Tag) u3 { | ... | @@ -610,6 +639,7 @@ inline fn getMiModRmExt(tag: Mir.Inst.Tag) u3 { |
| 610 | .sbb => 0x3, | 639 | .sbb => 0x3, |
| 611 | .cmp => 0x7, | 640 | .cmp => 0x7, |
| 612 | .mov => 0x0, | 641 | .mov => 0x0, |
| | 642 | .call_near => 0x2, |
| 613 | else => unreachable, | 643 | else => unreachable, |
| 614 | }; | 644 | }; |
| 615 | } | 645 | } |
| ... | @@ -655,34 +685,25 @@ const RegisterOrMemory = union(enum) { | ... | @@ -655,34 +685,25 @@ const RegisterOrMemory = union(enum) { |
| 655 | } | 685 | } |
| 656 | }; | 686 | }; |
| 657 | | 687 | |
| 658 | fn lowerToTdEnc( | 688 | fn lowerToDEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) InnerError!void { |
| 659 | tag: Mir.Inst.Tag, | 689 | const opc = getOpCode(tag, .d).?; |
| 660 | moffs: i64, | 690 | const encoder = try Encoder.init(code, 5); |
| 661 | reg: Register, | 691 | encoder.opcode_1byte(opc); |
| 662 | code: *std.ArrayList(u8), | 692 | encoder.imm32(imm); |
| 663 | ) InnerError!void { | 693 | } |
| | 694 | |
| | 695 | fn lowerToTdEnc(tag: Tag, moffs: i64, reg: Register, code: *std.ArrayList(u8)) InnerError!void { |
| 664 | return lowerToTdFdEnc(tag, reg, moffs, code, true); | 696 | return lowerToTdFdEnc(tag, reg, moffs, code, true); |
| 665 | } | 697 | } |
| 666 | | 698 | |
| 667 | fn lowerToFdEnc( | 699 | fn lowerToFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8)) InnerError!void { |
| 668 | tag: Mir.Inst.Tag, | | |
| 669 | reg: Register, | | |
| 670 | moffs: i64, | | |
| 671 | code: *std.ArrayList(u8), | | |
| 672 | ) InnerError!void { | | |
| 673 | return lowerToTdFdEnc(tag, reg, moffs, code, false); | 700 | return lowerToTdFdEnc(tag, reg, moffs, code, false); |
| 674 | } | 701 | } |
| 675 | | 702 | |
| 676 | fn lowerToTdFdEnc( | 703 | fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), td: bool) InnerError!void { |
| 677 | tag: Mir.Inst.Tag, | | |
| 678 | reg: Register, | | |
| 679 | moffs: i64, | | |
| 680 | code: *std.ArrayList(u8), | | |
| 681 | td: bool, | | |
| 682 | ) InnerError!void { | | |
| 683 | if (reg.lowId() != Register.rax.lowId()) return error.EmitFail; | 704 | if (reg.lowId() != Register.rax.lowId()) return error.EmitFail; |
| 684 | if (reg.size() != immOpSize(moffs)) return error.EmitFail; | 705 | if (reg.size() != immOpSize(moffs)) return error.EmitFail; |
| 685 | var opc = if (td) getOpCode(tag, .td) else getOpCode(tag, .fd); | 706 | var opc = if (td) getOpCode(tag, .td).? else getOpCode(tag, .fd).?; |
| 686 | if (reg.size() == 8) { | 707 | if (reg.size() == 8) { |
| 687 | opc -= 1; | 708 | opc -= 1; |
| 688 | } | 709 | } |
| ... | @@ -714,13 +735,8 @@ fn lowerToTdFdEnc( | ... | @@ -714,13 +735,8 @@ fn lowerToTdFdEnc( |
| 714 | } | 735 | } |
| 715 | } | 736 | } |
| 716 | | 737 | |
| 717 | fn lowerToOiEnc( | 738 | fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) InnerError!void { |
| 718 | tag: Mir.Inst.Tag, | 739 | var opc = getOpCode(tag, .oi).?; |
| 719 | reg: Register, | | |
| 720 | imm: i64, | | |
| 721 | code: *std.ArrayList(u8), | | |
| 722 | ) InnerError!void { | | |
| 723 | var opc = getOpCode(tag, .oi); | | |
| 724 | if (reg.size() != immOpSize(imm)) return error.EmitFail; | 740 | if (reg.size() != immOpSize(imm)) return error.EmitFail; |
| 725 | if (reg.size() == 8) { | 741 | if (reg.size() == 8) { |
| 726 | opc -= 8; | 742 | opc -= 8; |
| ... | @@ -754,14 +770,9 @@ fn lowerToOiEnc( | ... | @@ -754,14 +770,9 @@ fn lowerToOiEnc( |
| 754 | } | 770 | } |
| 755 | } | 771 | } |
| 756 | | 772 | |
| 757 | fn lowerToMiEnc( | 773 | fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.ArrayList(u8)) InnerError!void { |
| 758 | tag: Mir.Inst.Tag, | 774 | var opc = getOpCode(tag, .mi).?; |
| 759 | reg_or_mem: RegisterOrMemory, | 775 | const modrm_ext = getModRmExt(tag); |
| 760 | imm: i32, | | |
| 761 | code: *std.ArrayList(u8), | | |
| 762 | ) InnerError!void { | | |
| 763 | var opc = getOpCode(tag, .mi); | | |
| 764 | const modrm_ext = getMiModRmExt(tag); | | |
| 765 | switch (reg_or_mem) { | 776 | switch (reg_or_mem) { |
| 766 | .register => |dst_reg| { | 777 | .register => |dst_reg| { |
| 767 | if (dst_reg.size() == 8) { | 778 | if (dst_reg.size() == 8) { |
| ... | @@ -839,12 +850,12 @@ fn lowerToMiEnc( | ... | @@ -839,12 +850,12 @@ fn lowerToMiEnc( |
| 839 | } | 850 | } |
| 840 | | 851 | |
| 841 | fn lowerToRmEnc( | 852 | fn lowerToRmEnc( |
| 842 | tag: Mir.Inst.Tag, | 853 | tag: Tag, |
| 843 | reg: Register, | 854 | reg: Register, |
| 844 | reg_or_mem: RegisterOrMemory, | 855 | reg_or_mem: RegisterOrMemory, |
| 845 | code: *std.ArrayList(u8), | 856 | code: *std.ArrayList(u8), |
| 846 | ) InnerError!void { | 857 | ) InnerError!void { |
| 847 | var opc = getOpCode(tag, .rm); | 858 | var opc = getOpCode(tag, .rm).?; |
| 848 | if (reg.size() == 8) { | 859 | if (reg.size() == 8) { |
| 849 | opc -= 1; | 860 | opc -= 1; |
| 850 | } | 861 | } |
| ... | @@ -909,7 +920,7 @@ fn lowerToRmEnc( | ... | @@ -909,7 +920,7 @@ fn lowerToRmEnc( |
| 909 | } | 920 | } |
| 910 | | 921 | |
| 911 | fn lowerToMrEnc( | 922 | fn lowerToMrEnc( |
| 912 | tag: Mir.Inst.Tag, | 923 | tag: Tag, |
| 913 | reg_or_mem: RegisterOrMemory, | 924 | reg_or_mem: RegisterOrMemory, |
| 914 | reg: Register, | 925 | reg: Register, |
| 915 | code: *std.ArrayList(u8), | 926 | code: *std.ArrayList(u8), |
| ... | @@ -920,7 +931,7 @@ fn lowerToMrEnc( | ... | @@ -920,7 +931,7 @@ fn lowerToMrEnc( |
| 920 | // * reg is 32bit - dword ptr | 931 | // * reg is 32bit - dword ptr |
| 921 | // * reg is 16bit - word ptr | 932 | // * reg is 16bit - word ptr |
| 922 | // * reg is 8bit - byte ptr | 933 | // * reg is 8bit - byte ptr |
| 923 | var opc = getOpCode(tag, .mr); | 934 | var opc = getOpCode(tag, .mr).?; |
| 924 | if (reg.size() == 8) { | 935 | if (reg.size() == 8) { |
| 925 | opc -= 1; | 936 | opc -= 1; |
| 926 | } | 937 | } |
| ... | @@ -982,7 +993,7 @@ fn lowerToMrEnc( | ... | @@ -982,7 +993,7 @@ fn lowerToMrEnc( |
| 982 | } | 993 | } |
| 983 | } | 994 | } |
| 984 | | 995 | |
| 985 | fn mirArith(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | 996 | fn mirArith(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 986 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 997 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 987 | switch (ops.flags) { | 998 | switch (ops.flags) { |
| 988 | 0b00 => { | 999 | 0b00 => { |
| ... | @@ -1053,11 +1064,11 @@ fn immOpSize(imm: i64) u8 { | ... | @@ -1053,11 +1064,11 @@ fn immOpSize(imm: i64) u8 { |
| 1053 | return 64; | 1064 | return 64; |
| 1054 | } | 1065 | } |
| 1055 | | 1066 | |
| 1056 | fn mirArithScaleSrc(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | 1067 | fn mirArithScaleSrc(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 1057 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 1068 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 1058 | const scale = ops.flags; | 1069 | const scale = ops.flags; |
| 1059 | // OP reg1, [reg2 + scale*rcx + imm32] | 1070 | // OP reg1, [reg2 + scale*rcx + imm32] |
| 1060 | var opc = getOpCode(tag, .rm); | 1071 | var opc = getOpCode(tag, .rm).?; |
| 1061 | if (ops.reg1.size() == 8) { | 1072 | if (ops.reg1.size() == 8) { |
| 1062 | opc -= 1; | 1073 | opc -= 1; |
| 1063 | } | 1074 | } |
| ... | @@ -1080,15 +1091,15 @@ fn mirArithScaleSrc(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE | ... | @@ -1080,15 +1091,15 @@ fn mirArithScaleSrc(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE |
| 1080 | } | 1091 | } |
| 1081 | } | 1092 | } |
| 1082 | | 1093 | |
| 1083 | fn mirArithScaleDst(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | 1094 | fn mirArithScaleDst(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 1084 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 1095 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 1085 | const scale = ops.flags; | 1096 | const scale = ops.flags; |
| 1086 | const imm = emit.mir.instructions.items(.data)[inst].imm; | 1097 | const imm = emit.mir.instructions.items(.data)[inst].imm; |
| 1087 | | 1098 | |
| 1088 | if (ops.reg2 == .none) { | 1099 | if (ops.reg2 == .none) { |
| 1089 | // OP [reg1 + scale*rax + 0], imm32 | 1100 | // OP [reg1 + scale*rax + 0], imm32 |
| 1090 | var opc = getOpCode(tag, .mi); | 1101 | var opc = getOpCode(tag, .mi).?; |
| 1091 | const modrm_ext = getMiModRmExt(tag); | 1102 | const modrm_ext = getModRmExt(tag); |
| 1092 | if (ops.reg1.size() == 8) { | 1103 | if (ops.reg1.size() == 8) { |
| 1093 | opc -= 1; | 1104 | opc -= 1; |
| 1094 | } | 1105 | } |
| ... | @@ -1111,7 +1122,7 @@ fn mirArithScaleDst(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE | ... | @@ -1111,7 +1122,7 @@ fn mirArithScaleDst(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE |
| 1111 | } | 1122 | } |
| 1112 | | 1123 | |
| 1113 | // OP [reg1 + scale*rax + imm32], reg2 | 1124 | // OP [reg1 + scale*rax + imm32], reg2 |
| 1114 | var opc = getOpCode(tag, .mr); | 1125 | var opc = getOpCode(tag, .mr).?; |
| 1115 | if (ops.reg1.size() == 8) { | 1126 | if (ops.reg1.size() == 8) { |
| 1116 | opc -= 1; | 1127 | opc -= 1; |
| 1117 | } | 1128 | } |
| ... | @@ -1133,16 +1144,16 @@ fn mirArithScaleDst(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE | ... | @@ -1133,16 +1144,16 @@ fn mirArithScaleDst(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE |
| 1133 | } | 1144 | } |
| 1134 | } | 1145 | } |
| 1135 | | 1146 | |
| 1136 | fn mirArithScaleImm(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | 1147 | fn mirArithScaleImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 1137 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 1148 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 1138 | const scale = ops.flags; | 1149 | const scale = ops.flags; |
| 1139 | const payload = emit.mir.instructions.items(.data)[inst].payload; | 1150 | const payload = emit.mir.instructions.items(.data)[inst].payload; |
| 1140 | const imm_pair = emit.mir.extraData(Mir.ImmPair, payload).data; | 1151 | const imm_pair = emit.mir.extraData(Mir.ImmPair, payload).data; |
| 1141 | var opc = getOpCode(tag, .mi); | 1152 | var opc = getOpCode(tag, .mi).?; |
| 1142 | if (ops.reg1.size() == 8) { | 1153 | if (ops.reg1.size() == 8) { |
| 1143 | opc -= 1; | 1154 | opc -= 1; |
| 1144 | } | 1155 | } |
| 1145 | const modrm_ext = getMiModRmExt(tag); | 1156 | const modrm_ext = getModRmExt(tag); |
| 1146 | const encoder = try Encoder.init(emit.code, 2); | 1157 | const encoder = try Encoder.init(emit.code, 2); |
| 1147 | encoder.rex(.{ | 1158 | encoder.rex(.{ |
| 1148 | .w = ops.reg1.size() == 64, | 1159 | .w = ops.reg1.size() == 64, |
| ... | @@ -1230,7 +1241,7 @@ fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ... | @@ -1230,7 +1241,7 @@ fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1230 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 1241 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 1231 | assert(ops.flags == 0b01); | 1242 | assert(ops.flags == 0b01); |
| 1232 | const imm = emit.mir.instructions.items(.data)[inst].imm; | 1243 | const imm = emit.mir.instructions.items(.data)[inst].imm; |
| 1233 | return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.mem(ops.reg2, imm), emit.code); | 1244 | return lowerToRmEnc(.lea, ops.reg1, RegisterOrMemory.mem(ops.reg2, imm), emit.code); |
| 1234 | } | 1245 | } |
| 1235 | | 1246 | |
| 1236 | fn mirLeaRip(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | 1247 | fn mirLeaRip(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| ... | @@ -1272,12 +1283,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ... | @@ -1272,12 +1283,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 1272 | assert(tag == .call_extern); | 1283 | assert(tag == .call_extern); |
| 1273 | const n_strx = emit.mir.instructions.items(.data)[inst].extern_fn; | 1284 | const n_strx = emit.mir.instructions.items(.data)[inst].extern_fn; |
| 1274 | const offset = blk: { | 1285 | const offset = blk: { |
| 1275 | const offset = @intCast(u32, emit.code.items.len + 1); | | |
| 1276 | // callq | 1286 | // callq |
| 1277 | const encoder = try Encoder.init(emit.code, 5); | 1287 | try lowerToDEnc(.call_near, 0, emit.code); |
| 1278 | encoder.opcode_1byte(0xe8); | 1288 | break :blk @intCast(u32, emit.code.items.len) - 4; |
| 1279 | encoder.imm32(0x0); | | |
| 1280 | break :blk offset; | | |
| 1281 | }; | 1289 | }; |
| 1282 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | 1290 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 1283 | // Add relocation to the decl. | 1291 | // Add relocation to the decl. |