23

The x87 instruction set does not support direct transfers between general purpose registers and floating point registers. This is mainly a consequence of the 8087/80287/80387 being a separate chip attached to the same memory bus of which the CPU is largely (but not entirely) ignorant. So all data transfers between the two have to be passed through memory.

Famously, the FSTSW AX instruction introduced with the 80287 is the main exception to this before the later introduction of the FCOMI family of instructions. Various documents on the internet allude that the instruction is apparently implemented by means of port IO between the CPU and the FPU through the reserved port range F0 to FF, but no details were found.

How exactly is the FSTSW AX instruction implemented on the 80287 (and possibly the 80387) as far as transferring data into AX is concerned? Can the same mechanism be abused by other or custom coprocessors to gain access to the register file?

19
  • @fuz From old memory, the instruction you mentioned is recognized by both the 80286 and 80287 as an 80287 ESC instruction. The 80287 ignores the busy bit (neither changes it nor examines it) in its status word (it doesn't care) and performs the operation exclusively over the BIU. No WAIT instruction is required as the 80286 is held off during the BIU transaction. I'm not sure what more detail you need, though. What's going on? (I also have a vague memory of the processor extension data channel but don't recall much about it and I may be confusing the FSTSW AX and the FSTSW.)
    – jonk
    Commented Jul 16, 2022 at 22:19
  • @fuz (I may be able to track down my old hardware manuals for the 80286 and the 80287. Just not today.)
    – jonk
    Commented Jul 16, 2022 at 22:21
  • @jonk So how does the status word get into the AX register? With FSTSW mem16, it's clear how it works. But FSTSW AX is a special case.
    – fuz
    Commented Jul 16, 2022 at 22:25
  • @fuz My recollection remains fuzzy. But my recollection is that the register transfer takes place directly. Have a look at PEREQ, to start. I think that is part of the exchange. I didn't work at Intel until the Pentium II (BX chipset) and didn't need to unearth 80286 transactions at that late date. (Besides, Intel tightly controlled their internal documents in their vault and since I had no business accessing those documents I would not have been allowed to check them out and read them.)
    – jonk
    Commented Jul 16, 2022 at 22:30
  • @jonk According to various pages, this mechanism seems to be for data transfers from/to memory. It is not clear to me how it is decided what direction the transfer goes. Maybe there are additional cases for from/to AX.
    – fuz
    Commented Jul 16, 2022 at 22:59

1 Answer 1

12

Since this is about low level operation, let's start with the fact that the CPU/FPU does not provide an FSTSW AX instruction, only an FNSTSW AX. When encountering FSTSW AX, the assembler issues two instructions (*1):

9b       for FWAIT and
DF E0    for FNSTSW AX

Addressing

The important difference between the 8087 and 80287 is that the 287 no longer snoops the CPU bus, but acts now as an I/O device (*2) - which in turn can be used by other CPU as well. Addressing is done using chip select and a two bit address via:

  • /NPS1, NPS2 - Numeric Processor Select - essentially the Chip Select signals for the 80286
  • CMD0, CMD1 - Command 0/1 - essentially Port/Register address lines of the FPU

In case of the 80286 communication these are decoded as the word size I/O Ports 0F8h, 0FAh, and 0FCh (*3/*4). Note, that these addresses are only fixed within the CPU. External decoding is needed to map the 80287 to these addresses:

Address /NPS1 NPS0 CMD1 CMD0
 0F8h     L    H    L    L
 0FAh     L    H    L    H
 0FCh     L    H    H    L
 0FEh     L    H    H    H

Essentially coupling (and buffering) A1 and A2 to CMD0/1. Additionally the 80287 read/write signals (/NPRD, /NPWR) need to be connected to the CPU's /IORD, /IOWR (or better the signals decoded by the 82288).

The three Ports/Registers are used for 5 distinct transfers:

CMD1/0 (Port) R/W
  00   (0F8h)  W   Opcode to 80287
  00   (0F8h)  R   CW or SW from 80287
  01   (0FAh)  W   Exception Pointer to 80287
  10   (0FCh)  W   Data to 80287
  10   (0FCh)  R   Data from 80287

Command Transfer

A command transfer consists of one or more writes to the first port (0F8h) containing the FPU command to be executed. Depending on command the Status (SW) or Control (CW) Word can be read right after from the same port.

Data Transfer

For data transfer the 80286 provides a DMA like mechanism called Processor Extension Data Channel. If an FPU instruction contains a data transfer the CPU sets up the PEDC address, length and direction from the instruction.

When the FPU is ready to transfer, it raises PEREQ (Processor Extension Request). In case of write to the FPU, the CPU will read the data from memory (*5), provide it on the data lines and pull PEACK (Processor Extension Acknowledge) low. With writes from FPU the same sequence happens. End of transfer (and reinitialization of the PEDC) is signalled by /BUSY going high.

These transfers go to and from Port 0FCh.

FSTSW AX

FSTSW is directly done as read of port 0F8h - after writing the FSTSW command to port 0F8h.

(Here it gets a bit fuzzy, as I can't find the code I'm looking for - Many years ago I attached a 287 to a 68k system, I did only find part of the notes so far. I'm still searching for a command table.)


*1 - Which opens Pandora's Box of Definitions:

  • Is FSTSW an instruction?
  • Is it a macro?
  • Is it something else?

Or - dogmatics behold - is Assembler maybe not a 1:1 representation of machine code?

*2 - The 8087 is really a second processor as it takes over the bus to perform its own read/write cycles - although, not completely independent, as it relies on the CPU to do read on the operand address first, but discards the data. The FPU captures the address for further use and, if a read is to be done, also the first data byte/word. After that it takes over the bus and does all follow up ready or write on its own.

The 287 in turn does not handle the bus but relies on the 286 to feed it with nice aligned 16 bit words. This is also the reason why a 287 can not operate with an 8088. It simply lacks a way to access memory in general and bytewise memory in particular.

*3 - The 386/387 change data size to 32-bit access using only addresses 0F8h and 0FCh.

*4 - The 386 added A31 to the address as selector for simply systems (noone will need 4 Gi address space), do 0F8/0FCh becomes 0800000F8h/FCh

*5 - One cycle when reading word aligned data, two if byte aligned - that's why word alignment does speed up a 80287 a tiny bit.

13
  • According to the datasheet I found, CMD0 and CMD1 are A1 and A2, not A2 and A3. Note that bus snooping is still done to decode the instruction stream (see S1 and S2 pins). This i287XL datasheet has some more explanation! So this all looks like the 80286 does in fact have a vague notion of the 80286 instruction set that goes further than just “d8 to to df are coprocessor escapes.”
    – fuz
    Commented Jul 16, 2022 at 23:56
  • 2
    @fuz Note that the 287XL is a 387 with 287 pinout. Also, while the 286 does not 'understand' what 287 instructions do, it does decode all 287 instructions to setup PEDC operation (data address, data length and transfer direction).
    – Raffzahn
    Commented Jul 17, 2022 at 0:12
  • Interesting, I was not aware of the 286 knowing anything about 287 instructions! The pinout thing is correct, which is why a documentation of these signals on the i287XL will also apply to the 80287.
    – fuz
    Commented Jul 17, 2022 at 0:23
  • @fuz Erm, I'm no aware that the 287 does snoop the bus in any way. Also, what these S1/S2 should be? Are you referring to NPS1/2? Sies are the chip selects from address decoding.
    – Raffzahn
    Commented Jul 17, 2022 at 0:58
  • Sorry, meant S0 and S1 (pins 1 and 2). These are connected to the same pins on the 80286, allowing the 80287 to snoop and decode the instruction stream in parallel as on the 80286. It seems like only memory operands (and AX?) are passed through the special port I/O transaction. Curiously, the i287XL does not use these bits according to the datasheet.
    – fuz
    Commented Jul 17, 2022 at 1:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .