14

The 8087 and 287 FPUs were designed before the IEEE 754 standard was released. Because of this, they contain some instructions which are not compliant with it. When the 387 was released in 1987, it addressed these problems by adding some new instructions (notably, FPREM1) and also by changing a lot of rules and quirks about rounding, infinities and denormal numbers (the main differences are listed in the 80387 Programmer's Reference Manual, Appendix C and D).

While some 387 programs may lose precision by being run on a 287, and some may even miss some important overflow/underflow/denormal exceptions, a 387 program is guaranteed to not work correctly if it tries a new instruction like FSIN or FUCOM.

Since the 387 was released 2 years after the 386, the first 386 systems were built with a 287 socket. Is it possible for such a system to emulate the new 387 instructions (without swapping the 287 with a 287XL)? By that, I mean to trap only the 387 opcodes, not every FPU opcode (which is trivial by setting CR0.EM).

Current x86 CPUs seem to trap invalid FPU opcodes (in the D8DF range). However, the 80386 CPU has no idea which FPU opcodes are valid and which aren't, because the FPU is external.

user3840170
  • 23,072
  • 4
  • 91
  • 150
DarkAtom
  • 2,337
  • 8
  • 31
  • So trap on the new 387 codes and replace with a set of 287 codes that at least roughly emulate them? With or without messing with the 287 state (much)? – Jon Custer May 31 '23 at 20:41
  • Yes, trap and emulate them, and modify the correct registers (for example, fsin does computation on st0). – DarkAtom May 31 '23 at 20:43
  • You could probably use the CR0.EM flag and manually decode each instruction, then for the common ones temporarily enable the FPU, trace that instruction, then disable the FPU again. – ecm May 31 '23 at 21:41
  • 2
    @ecm Wouldn't that create a performance penalty almost as bad as software emulation? The point is to utilize the 287 at its best, otherwise software emulation would be a much better and more robust solution, as it would create a true 387 environment. – DarkAtom May 31 '23 at 22:08
  • 3
    So to begin. what does a 287 generally do when it encounters an unknown opcode? I skimmed the 287 manual and didn't see this addressed. If it doesn't trap in some fashion, then it seems that this effort is dead in the water. – Nate Eldredge Jun 01 '23 at 05:02
  • @DarkAtom Most of the work would still run on the FPU, just with tracing. I expect that this would be much faster than software emulation, depending on how many 387 instructions you get that do have to be done in software – ecm Jun 01 '23 at 06:11
  • 1
    @ecm In Protected Mode, those context switches can be pretty expensive. In a standard DOS environment you're probably right and it shouldn't be that big of a problem. – DarkAtom Jun 01 '23 at 10:24
  • 1
    @NateEldredge I see...I was hoping someone here would know more about this matter, because I also didn't find anything in the manual. I guess ecm's idea is probably the best, if there is no way to trap unknown x87 opcodes. – DarkAtom Jun 01 '23 at 10:35
  • Do you have a specific combination of hardware and software you want to run? A more concrete problem might be easier to solve. – John Dallman Jun 01 '23 at 15:53
  • Yes, it might be possible, I just don't know. All I'm saying is that "what does a 287 do with undefined opcodes" might be a better question to start with, as it should have a more well-defined answer. – Nate Eldredge Jun 01 '23 at 21:17
  • Well, the reference manual (http://bitsavers.trailing-edge.com/components/intel/80286/210498-005_80286_and_80287_Programmers_Reference_Manual_1987.pdf) is not explicit on what the 80287 will do if presented with an illegal instruction that I could find. – Jon Custer Jun 02 '23 at 14:44
  • 1
    Wouldn’t people just use a 386/287 combo as a super-speed 287/287? IOW, you might be assuming too much. – RonJohn Jun 02 '23 at 17:23
  • @RonJohn I probably am assuming waay to much I guess :P Though I'm not sure the ability to run Win32s applications under Windows 3.1, or Protected Mode DOS games using a DOS extender counts as "super-speed 286+287". – DarkAtom Jun 02 '23 at 18:39
  • @DarkAtom since the 387 didn't exist yet, and 386/287 systems were created at this time, why would compilers emit 387 code? Why would users expect to run 387 code? – RonJohn Jun 02 '23 at 22:59
  • @RonJohn Because nobody keeps a computer for 2-3 years only. If you buy a system, you probably expect to be able to run most software that will be released 3 years later (maybe with terrible performance, but at least able to run). – DarkAtom Jun 03 '23 at 01:12
  • @DarkAtom things were different back then. Now, you can get good performance out of a 3 year old computer. Not so back then: if you needed performance, your company actually was buying you a new computer or workstation every few years. – RonJohn Jun 03 '23 at 01:18
  • 2
    Update: It seems that the CPU might actually know about invalid FPU opcodes. In this article about 80386 errata, it is mentioned that one of the bugs for the A1 stepping is: "Bad Floating-Point Instructions: The execution of certain undefined floating-point instructions causes the 80386 to hang rather than reporting an invalid instruction fault.". I guess this means that the 80386 is supposed to be able detect undefined x87 opcodes. – DarkAtom Jun 05 '23 at 08:18
  • @DarkAtom Indeed, the 286 and later do know about one floating point instruction, which is "FSTSW AX". This instruction transfers coprocessor state into a CPU register - something that can not be done without the CPU recognizing this instruction. I consider it likely that this erratum is related to incomplete decoding of FSTSW AX. – Michael Karcher Nov 26 '23 at 19:01
  • I was watching the new (29th Feb '24) Adrian's Digital Basement where he's going through a very early 16Mhz 386 (a Tandy 4000 PC) and the documentation + Motherboard sockets make it clear that it takes a 287 - perhaps this might open up another rabbit whole? Good luck and please keep up posted! – Russ Clarke Mar 01 '24 at 03:15

0 Answers0