FIXME: following is very similar to FADDF64
| 158 | |
| 159 | // FIXME: following is very similar to FADDF64 |
| 160 | void OpDispatchBuilder::FMULF64(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispatchBuilder::OpResult ResInST0) { |
| 161 | if (Op->Src[0].IsNone()) { // Implicit argument case |
| 162 | auto offset = Op->OP & 7; |
| 163 | auto st0 = 0; |
| 164 | if (ResInST0 == OpResult::RES_STI) { |
| 165 | _F80MulStack(offset, st0); |
| 166 | } else { |
| 167 | _F80MulStack(st0, offset); |
| 168 | } |
| 169 | if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) { |
| 170 | _PopStackDestroy(); |
| 171 | } |
| 172 | return; |
| 173 | } |
| 174 | |
| 175 | // We have one memory argument |
| 176 | Ref arg {}; |
| 177 | |
| 178 | if (Integer) { |
| 179 | arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); |
| 180 | if (Width == OpSize::i16Bit) { |
| 181 | arg = _Sbfe(OpSize::i64Bit, 16, 0, arg); |
| 182 | } |
| 183 | arg = _Float_FromGPR_S(OpSize::i64Bit, Width == OpSize::i64Bit ? OpSize::i64Bit : OpSize::i32Bit, arg); |
| 184 | } else if (Width == OpSize::i32Bit) { |
| 185 | arg = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); |
| 186 | arg = _Float_FToF(OpSize::i64Bit, OpSize::i32Bit, arg); |
| 187 | } else if (Width == OpSize::i64Bit) { |
| 188 | arg = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); |
| 189 | } else { |
| 190 | FEX_UNREACHABLE; |
| 191 | } |
| 192 | |
| 193 | // top of stack is at offset zero |
| 194 | _F80MulValue(0, arg); |
| 195 | |
| 196 | if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) { |
| 197 | _PopStackDestroy(); |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | void OpDispatchBuilder::FDIVF64(OpcodeArgs, IR::OpSize Width, bool Integer, bool Reverse, OpDispatchBuilder::OpResult ResInST0) { |
| 202 | if (Op->Src[0].IsNone()) { |