Commit 66ef630006

mparadinha <miguel.p.paradinha@gmail.com>
2022-03-16 20:15:41
stage2: x86_64: add new `fld` instruction
1 parent 972d923
Changed files (2)
src
arch
src/arch/x86_64/Emit.zig
@@ -132,6 +132,7 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
             .movabs => try emit.mirMovabs(inst),
 
             .fisttp => try emit.mirFisttp(inst),
+            .fld => try emit.mirFld(inst),
 
             .lea => try emit.mirLea(inst),
             .lea_pie => try emit.mirLeaPie(inst),
@@ -710,6 +711,26 @@ fn mirFisttp(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
     return lowerToMEnc(opcode, .{ .memory = mem_or_reg }, emit.code);
 }
 
+fn mirFld(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
+    const tag = emit.mir.instructions.items(.tag)[inst];
+    assert(tag == .fld);
+    const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
+
+    // the selecting between operand sizes for this particular `fisttp` instruction
+    // is done via opcode instead of the usual prefixes.
+
+    const opcode: Tag = switch (ops.flags) {
+        0b01 => .fld32,
+        0b10 => .fld64,
+        else => unreachable,
+    };
+    const mem_or_reg = Memory{
+        .base = ops.reg1,
+        .disp = emit.mir.instructions.items(.data)[inst].imm,
+        .ptr_size = Memory.PtrSize.dword_ptr, // to prevent any prefix from being used
+    };
+    return lowerToMEnc(opcode, .{ .memory = mem_or_reg }, emit.code);
+}
 fn mirShift(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void {
     const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
     switch (ops.flags) {
@@ -1141,6 +1162,8 @@ const Tag = enum {
     fisttp16,
     fisttp32,
     fisttp64,
+    fld32,
+    fld64,
     jo,
     jno,
     jb,
@@ -1382,6 +1405,8 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) ?OpCode {
             .fisttp16 => OpCode.oneByte(0xdf),
             .fisttp32 => OpCode.oneByte(0xdb),
             .fisttp64 => OpCode.oneByte(0xdd),
+            .fld32 => OpCode.oneByte(0xd9),
+            .fld64 => OpCode.oneByte(0xdd),
             else => null,
         },
         .o => return switch (tag) {
@@ -1525,6 +1550,8 @@ inline fn getModRmExt(tag: Tag) ?u3 {
         .fisttp16 => 0x1,
         .fisttp32 => 0x1,
         .fisttp64 => 0x1,
+        .fld32 => 0x0,
+        .fld64 => 0x0,
         else => null,
     };
 }
src/arch/x86_64/Mir.zig
@@ -265,6 +265,11 @@ pub const Inst = struct {
         ///   * only supports memory operands as destination
         fisttp,
 
+        /// ops flags:  form:
+        ///      0b01    dword ptr [reg1 + imm32]
+        ///      0b10    qword ptr [reg1 + imm32]
+        fld,
+
         /// ops flags:  form:
         ///      0b00    inst
         ///      0b01    reg1