authorgravatar for miguel.p.paradinha@gmail.commparadinha <miguel.p.paradinha@gmail.com> 2022-03-14 15:00:45+00:00
committergravatar for miguel.p.paradinha@gmail.commparadinha <miguel.p.paradinha@gmail.com> 2022-03-16 21:24:09+00:00
log972d923f09f90ac15a2f2b13863598b268022d88
tree23ee986650da8b66e4879c974758b26a00f5a987
parent94672dfb1941289eb65fdeab2e1dcc39ca70c3b7

stage2: x86_64: add new `fisttp` instruction

this instruction does truncating conversion from floating point values to signed integers.

2 files changed, 42 insertions(+), 0 deletions(-)

src/arch/x86_64/Emit.zig+33
...@@ -131,6 +131,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void {...@@ -131,6 +131,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
131131
132 .movabs => try emit.mirMovabs(inst),132 .movabs => try emit.mirMovabs(inst),
133133
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),
136138
...@@ -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}
688690
691fn 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
689fn mirShift(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {713fn 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}
src/arch/x86_64/Mir.zig+9
...@@ -256,6 +256,15 @@ pub const Inst = struct {...@@ -256,6 +256,15 @@ pub const Inst = struct {
256 /// TODO handle scaling256 /// TODO handle scaling
257 movabs,257 movabs,
258258
259 /// ops flags: form:
260 /// 0b00 word ptr [reg1 + imm32]
261 /// 0b01 dword ptr [reg1 + imm32]
262 /// 0b10 qword ptr [reg1 + imm32]
263 /// Notes:
264 /// * source is always ST(0)
265 /// * only supports memory operands as destination
266 fisttp,
267
259 /// ops flags: form:268 /// ops flags: form:
260 /// 0b00 inst269 /// 0b00 inst
261 /// 0b01 reg1270 /// 0b01 reg1