| ... | @@ -131,6 +131,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void { | ... | @@ -131,6 +131,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 131 | | 131 | |
| 132 | .movabs => try emit.mirMovabs(inst), | 132 | .movabs => try emit.mirMovabs(inst), |
| 133 | | 133 | |
| | 134 | .fisttp => try emit.mirFisttp(inst), |
| | 135 | |
| 134 | .lea => try emit.mirLea(inst), | 136 | .lea => try emit.mirLea(inst), |
| 135 | .lea_pie => try emit.mirLeaPie(inst), | 137 | .lea_pie => try emit.mirLeaPie(inst), |
| 136 | | 138 | |
| ... | @@ -686,6 +688,28 @@ fn mirMovabs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ... | @@ -686,6 +688,28 @@ fn mirMovabs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 686 | return lowerToFdEnc(.mov, ops.reg1, imm, emit.code); | 688 | return lowerToFdEnc(.mov, ops.reg1, imm, emit.code); |
| 687 | } | 689 | } |
| 688 | | 690 | |
| | 691 | fn mirFisttp(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| | 692 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| | 693 | assert(tag == .fisttp); |
| | 694 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| | 695 | |
| | 696 | // the selecting between operand sizes for this particular `fisttp` instruction |
| | 697 | // is done via opcode instead of the usual prefixes. |
| | 698 | |
| | 699 | const opcode: Tag = switch (ops.flags) { |
| | 700 | 0b00 => .fisttp16, |
| | 701 | 0b01 => .fisttp32, |
| | 702 | 0b10 => .fisttp64, |
| | 703 | else => unreachable, |
| | 704 | }; |
| | 705 | const mem_or_reg = Memory{ |
| | 706 | .base = ops.reg1, |
| | 707 | .disp = emit.mir.instructions.items(.data)[inst].imm, |
| | 708 | .ptr_size = Memory.PtrSize.dword_ptr, // to prevent any prefix from being used |
| | 709 | }; |
| | 710 | return lowerToMEnc(opcode, .{ .memory = mem_or_reg }, emit.code); |
| | 711 | } |
| | 712 | |
| 689 | fn mirShift(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { | 713 | fn mirShift(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 690 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); | 714 | const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]); |
| 691 | switch (ops.flags) { | 715 | switch (ops.flags) { |
| ... | @@ -1114,6 +1138,9 @@ const Tag = enum { | ... | @@ -1114,6 +1138,9 @@ const Tag = enum { |
| 1114 | syscall, | 1138 | syscall, |
| 1115 | ret_near, | 1139 | ret_near, |
| 1116 | ret_far, | 1140 | ret_far, |
| | 1141 | fisttp16, |
| | 1142 | fisttp32, |
| | 1143 | fisttp64, |
| 1117 | jo, | 1144 | jo, |
| 1118 | jno, | 1145 | jno, |
| 1119 | jb, | 1146 | jb, |
| ... | @@ -1352,6 +1379,9 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) ?OpCode { | ... | @@ -1352,6 +1379,9 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) ?OpCode { |
| 1352 | .setle, .setng => OpCode.twoByte(0x0f, 0x9e), | 1379 | .setle, .setng => OpCode.twoByte(0x0f, 0x9e), |
| 1353 | .setnle, .setg => OpCode.twoByte(0x0f, 0x9f), | 1380 | .setnle, .setg => OpCode.twoByte(0x0f, 0x9f), |
| 1354 | .idiv, .div, .imul => OpCode.oneByte(if (is_one_byte) 0xf6 else 0xf7), | 1381 | .idiv, .div, .imul => OpCode.oneByte(if (is_one_byte) 0xf6 else 0xf7), |
| | 1382 | .fisttp16 => OpCode.oneByte(0xdf), |
| | 1383 | .fisttp32 => OpCode.oneByte(0xdb), |
| | 1384 | .fisttp64 => OpCode.oneByte(0xdd), |
| 1355 | else => null, | 1385 | else => null, |
| 1356 | }, | 1386 | }, |
| 1357 | .o => return switch (tag) { | 1387 | .o => return switch (tag) { |
| ... | @@ -1492,6 +1522,9 @@ inline fn getModRmExt(tag: Tag) ?u3 { | ... | @@ -1492,6 +1522,9 @@ inline fn getModRmExt(tag: Tag) ?u3 { |
| 1492 | .imul => 0x5, | 1522 | .imul => 0x5, |
| 1493 | .idiv => 0x7, | 1523 | .idiv => 0x7, |
| 1494 | .div => 0x6, | 1524 | .div => 0x6, |
| | 1525 | .fisttp16 => 0x1, |
| | 1526 | .fisttp32 => 0x1, |
| | 1527 | .fisttp64 => 0x1, |
| 1495 | else => null, | 1528 | else => null, |
| 1496 | }; | 1529 | }; |
| 1497 | } | 1530 | } |