| ... | ... | @@ -185,13 +185,11 @@ fn fixupRelocs(emit: *Emit) InnerError!void { |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | 187 | fn mirBrk(emit: *Emit) InnerError!void { |
| 188 | | const encoder = try Encoder.init(emit.code, 1); |
| 189 | | encoder.opcode_1byte(0xcc); |
| 188 | return lowerToZoEnc(.brk, emit.code); |
| 190 | 189 | } |
| 191 | 190 | |
| 192 | 191 | fn mirNop(emit: *Emit) InnerError!void { |
| 193 | | const encoder = try Encoder.init(emit.code, 1); |
| 194 | | encoder.opcode_1byte(0x90); |
| 192 | return lowerToZoEnc(.nop, emit.code); |
| 195 | 193 | } |
| 196 | 194 | |
| 197 | 195 | fn mirSyscall(emit: *Emit) InnerError!void { |
| ... | ... | @@ -436,7 +434,6 @@ fn mirRet(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 436 | 434 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 437 | 435 | assert(tag == .ret); |
| 438 | 436 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 439 | | const encoder = try Encoder.init(emit.code, 3); |
| 440 | 437 | switch (ops.flags) { |
| 441 | 438 | 0b00 => { |
| 442 | 439 | // RETF imm16 |
| ... | ... | @@ -444,14 +441,14 @@ fn mirRet(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 444 | 441 | const imm = emit.mir.instructions.items(.data)[inst].imm; |
| 445 | 442 | return lowerToIEnc(.ret_far, imm, emit.code); |
| 446 | 443 | }, |
| 447 | | 0b01 => encoder.opcode_1byte(0xcb), // RETF |
| 444 | 0b01 => return lowerToZoEnc(.ret_far, emit.code), |
| 448 | 445 | 0b10 => { |
| 449 | 446 | // RET imm16 |
| 450 | 447 | // I |
| 451 | 448 | const imm = emit.mir.instructions.items(.data)[inst].imm; |
| 452 | 449 | return lowerToIEnc(.ret_near, imm, emit.code); |
| 453 | 450 | }, |
| 454 | | 0b11 => encoder.opcode_1byte(0xc3), // RET |
| 451 | 0b11 => return lowerToZoEnc(.ret_near, emit.code), |
| 455 | 452 | } |
| 456 | 453 | } |
| 457 | 454 | |
| ... | ... | @@ -471,11 +468,16 @@ const Tag = enum { |
| 471 | 468 | push, |
| 472 | 469 | pop, |
| 473 | 470 | @"test", |
| 471 | brk, |
| 472 | nop, |
| 474 | 473 | ret_near, |
| 475 | 474 | ret_far, |
| 476 | 475 | }; |
| 477 | 476 | |
| 478 | 477 | const Encoding = enum { |
| 478 | /// OP |
| 479 | zo, |
| 480 | |
| 479 | 481 | /// OP rel32 |
| 480 | 482 | d, |
| 481 | 483 | |
| ... | ... | @@ -509,6 +511,13 @@ const Encoding = enum { |
| 509 | 511 | |
| 510 | 512 | inline fn getOpCode(tag: Tag, enc: Encoding) ?u8 { |
| 511 | 513 | switch (enc) { |
| 514 | .zo => return switch (tag) { |
| 515 | .ret_near => 0xc3, |
| 516 | .ret_far => 0xcb, |
| 517 | .brk => 0xcc, |
| 518 | .nop => 0x90, |
| 519 | else => null, |
| 520 | }, |
| 512 | 521 | .d => return switch (tag) { |
| 513 | 522 | .jmp_near => 0xe9, |
| 514 | 523 | .call_near => 0xe8, |
| ... | ... | @@ -638,6 +647,12 @@ const RegisterOrMemory = union(enum) { |
| 638 | 647 | } |
| 639 | 648 | }; |
| 640 | 649 | |
| 650 | fn lowerToZoEnc(tag: Tag, code: *std.ArrayList(u8)) InnerError!void { |
| 651 | const opc = getOpCode(tag, .zo).?; |
| 652 | const encoder = try Encoder.init(code, 1); |
| 653 | encoder.opcode_1byte(opc); |
| 654 | } |
| 655 | |
| 641 | 656 | fn lowerToIEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) InnerError!void { |
| 642 | 657 | var opc = getOpCode(tag, .i).?; |
| 643 | 658 | if (tag == .ret_far or tag == .ret_near) { |