Some improvements for FOOTBALL, including support for the 386 LOADALL instruction

This commit is contained in:
Jeff Parsons 2016-01-28 22:22:36 -08:00
commit a5b9e0cae7
27 changed files with 4431 additions and 3981 deletions

View file

@ -9,6 +9,6 @@ PC Reference Manuals
An assortment of PC reference manuals, including:
* [IBM PC References](ibm/)
* [IBM PC Manuals](ibm/)
* [Intel CPU Documents](intel/)
* [Microsoft Specifications](microsoft/)

View file

@ -9,6 +9,7 @@ Intel 80286 CPU Information
### 80286 Errata
* [Early 80286 Errata of Interest](early_errata/#early-80286-errata-of-interest)
* [ARPL Behavior](arpl/)
* [Coprocessor Operand Beyond Segment Limit](b2_b3_info/#coprocessor-operand-partially-beyond-limit-of-erc-segment)
* [Instructions Longer than 10 Bytes](extra_prefixes/)
@ -16,9 +17,8 @@ Intel 80286 CPU Information
* [Non-Restartable Protection Violations](b2_b3_info/#non-restartable-protection-violations)
* [POPF Behavior](b2_b3_info/#popf-behavior)
* [REP MOVS and REP INS Restartability](rep_restart/)
* [Early 80286 Errata of Interest](early_errata/#early-80286-errata-of-interest)
### 80286 Undocumented Opcodes
### 80286 Undocumented Instructions
* [LOADALL](loadall/)

View file

@ -1,12 +1,14 @@
---
layout: page
title: "Intel 80286 CPU Documentation: ARPL"
title: "Intel 80286 CPU Errata: ARPL"
permalink: /pubs/pc/reference/intel/80286/arpl/
---
Intel 80286 CPU Documentation
Intel 80286 CPU Errata: ARPL
---
[The following information is from an Intel document titled "80286 ARPL and Overlength Instructions, 15 October 1984"]
### ARPL (63H)
When the second operand of the ARPL instruction (as described in the iAPX286 Programmer's Reference Manual) is a null
@ -15,5 +17,3 @@ but will be described in future revisions of the "iAPX286 Programmer's Reference
This functionality of the ARPL is not believed not to be a problem, and there are no plans to change this functionality
of the ARPL instruction.
[This information is from an Intel document titled "80286 ARPL and Overlength Instructions, 15 October 1984"]

View file

@ -1,12 +1,14 @@
---
layout: page
title: "Intel 80286 CPU Documentation: B-2/B-3 Steppings"
title: "Intel 80286 CPU Errata: B-2/B-3 Steppings"
permalink: /pubs/pc/reference/intel/80286/b2_b3_info/
---
Intel 80286 CPU Documentation
Intel 80286 CPU Errata: B-2/B-3 Steppings
---
[The following information is from a 7-page Intel document titled "80286(B-2/B-3) Information Sheet, 21 November 1984"]
### 80286 B-2/B-3 Steppings
This applies to S-spec #40093 and to S-spec #54012 of the 80286, since they contain a (B-2/B-3) stepping of the 80286.
@ -197,5 +199,3 @@ handled if the 80286 interrupts are always disabled before programming the inter
is performed no unmasked interrupt is active. The interrupt handler for IR7 can read ISR7 of the 8259A to tell if this was a real
interrupt on IR7. The ISR7 bit will be 0 if at the time the interrupt was acknowledged, no unmasked IR inputs of the 8259A were
active ("phantom" interrupt).
[This information is from a 7-page Intel document titled "80286(B-2/B-3) Information Sheet, 21 November 1984"]

View file

@ -1,12 +1,16 @@
---
layout: page
title: "Intel 80286 CPU Documentation: Early Errata"
title: "Intel 80286 CPU Errata: Early Problems"
permalink: /pubs/pc/reference/intel/80286/early_errata/
---
Intel 80286 CPU Documentation
Intel 80286 CPU Errata: Early Problems
---
[The following information is from an undated 15-page Intel document titled "Undocumented iAPX 286 Test Instruction".
NOTE: The initial reference to LOADALL as "opcode 0F04H" and the subsequent references to the "0F05H opcode" are exactly
as they appear in the original document. Whether or not they were mistakes is unknown.]
### Exceptions from Undefined Opcodes and String Instructions
The exception 13 handler will probably use a lookup table for the opcode byte of the instruction causing exception
@ -101,5 +105,3 @@ steppings of the 80286 and are fixed in later steppings of the 80286.
0-wait memory for the data values or be sure bit 0 of memory location 804H is zero. HOLD requests and processor
extension data transfers should be inhibited while [LOADALL](../loadall/) is running. Later steppings of the 80286 will correctly
load the MSW during [LOADALL](../loadall/) with HOLD and processor extension transfers.
[This information is from an undated 15-page Intel document titled "Undocumented iAPX 286 Test Instruction"]

View file

@ -1,12 +1,14 @@
---
layout: page
title: "Intel 80286 CPU Documentation: Extra Prefixes"
title: "Intel 80286 CPU Errata: Extra Prefixes"
permalink: /pubs/pc/reference/intel/80286/extra_prefixes/
---
Intel 80286 CPU Documentation
Intel 80286 CPU Errata: Extra Prefixes
---
[The following information is from an Intel document titled "80286 ARPL and Overlength Instructions, 15 October 1984"]
### Instructions Longer than 10 Bytes
When the CPU detects an instruction that is illegal due to being greater than 10 bytes in length, it generates an
@ -16,5 +18,3 @@ greater than ten bytes can occur is by using the assembler to intentionally plac
There are no plans to change this functionality of the 80286 and future editions of the "iAPX286 Programmer's Reference
Manual" and 80286 datasheet will accurately describe how 80286 reacts to instructions greater than 10 bytes in length.
[This information is from an Intel document titled "80286 ARPL and Overlength Instructions, 15 October 1984"]

View file

@ -1,12 +1,14 @@
---
layout: page
title: "Intel 80286 CPU Documentation: LOADALL"
title: "Intel 80286 LOADALL Instruction"
permalink: /pubs/pc/reference/intel/80286/loadall/
---
Intel 80286 CPU Documentation
Intel 80286 LOADALL Instruction
---
[The following information is from an undated 15-page Intel document titled "Undocumented iAPX 286 Test Instruction"]
### LOADALL (0F05H)
The iAPX 286 microprocessor (part number 80286) has an undocumented instruction used by Intel test programs to
@ -154,5 +156,3 @@ For proper protected mode operation, the following is required:
4. The DPL fields of the ES and DS descriptors should be 3 to prevent their being zeroed by RET or IRET
instructions.
[This information is from an undated 15-page Intel document titled "Undocumented iAPX 286 Test Instruction"]

View file

@ -4,9 +4,11 @@ title: "Intel 80286 CPU Documentation: Real Mode"
permalink: /pubs/pc/reference/intel/80286/real_mode/
---
Intel 80286 CPU Documentation
Intel 80286 CPU Documentation: Real Mode
---
[The following information is from an undated 15-page Intel document titled "Undocumented iAPX 286 Test Instruction"]
### Executing Real Mode Programs in Protected Mode
An iAPX 86/88 program using real mode addressing can be executed in protected mode with full protection between
@ -300,5 +302,3 @@ Interrupts must be handled specially. Interrupt handlers for both real mode and
times. If an interrupt handler needs to access a data area, that data area must be addressable from both real and
protected mode. The real mode interrupt table would be would be kept at location 000000H. The protected mode IDT could
be anywhere. [LOADALL](../loadall/) will switch to the protected interrupt table.
[This information is from an undated 15-page Intel document titled "Undocumented iAPX 286 Test Instruction"]

View file

@ -1,12 +1,14 @@
---
layout: page
title: "Intel 80286 CPU Documentation: REP Restart"
title: "Intel 80286 CPU Errata: REP Restart"
permalink: /pubs/pc/reference/intel/80286/rep_restart/
---
Intel 80286 CPU Documentation
Intel 80286 CPU Errata: REP Restart
---
[The following information is from an Intel document titled "80286 REP MOVS and REP INS Restartability, 15 October 1984"]
### 80286 REP MOVS and REP INS Restartability
The repeated string instructions on 80286 were made restartable after protection violations on the (B-2/B-3) and
@ -46,5 +48,3 @@ The above three problems are being corrected in all future steppings of the 8028
register will hold 0ffffH when the CPU detects a violation due to the conditions above. Note that even when REP MOVS and
REP INS restartability is corrected, CX will correctly continue to be 0000H when these instructions complete without generating
a protection violation.
[This information is from an Intel document titled "80286 REP MOVS and REP INS Restartability, 15 October 1984"]

View file

@ -4,26 +4,27 @@ title: Intel 80386 CPU Information
permalink: /pubs/pc/reference/intel/80386/
---
Intel 80386 CPU Information
---
* [A0 Stepping](#a0-stepping)
* [A1 Stepping](#a1-stepping)
* [A2 Stepping](#a2-stepping)
* [B0 Stepping](#b0-stepping)
* [B1 Stepping](#b1-stepping)
* [C0 Stepping](#c0-stepping)
* [D0 Stepping](#d0-stepping)
* [D1 Stepping](#d1-stepping)
* [D2 Stepping](#d2-stepping)
80386 Instructions
80386 Errata
---
* [IBTS and XBTS](ibts_xbts/)
* [A0 Stepping](#a0-stepping)
* [A1 Stepping](#a1-stepping)
* [A2 Stepping](#a2-stepping)
* [B0 Stepping](#b0-stepping)
* [B1 Stepping](#b1-stepping)
* [C0 Stepping](#c0-stepping)
* [D0 Stepping](#d0-stepping)
* [D1 Stepping](#d1-stepping)
* [D2 Stepping](#d2-stepping)
80386 Undocumented Instructions
---
* [LOADALL](loadall/)
* [IBTS and XBTS](ibts_xbts/)
80386 Steppings
---

View file

@ -0,0 +1,277 @@
---
layout: page
title: "Intel 80386 LOADALL Instruction"
permalink: /pubs/pc/reference/intel/80386/loadall/
---
Intel 80386 LOADALL Instruction
---
[The following information is from an undated 6-page Intel "Internal Correspondence" document]
### LOADALL (0F07H)
### 1. 386 LOADALL Instruction
The 80386 implements a LOADALL instruction capable of loading all visible machine state from an area in memory.
The function of this instruction is the same as the [80286 LOADALL](/pubs/pc/reference/intel/80286/loadall/)
instruction [RASH]. Due to the architecture, and implementation of the 386, the format of the memory area
used by the two processors is different. Conversion between these formats is possible, requiring an algorithm
to 'map' between the two formats, and compensate for the architectural differences.
The attached tables illustrate the memory area used by LOADALL. The location of this area in memory is dynamic,
not fixed at 800H as in the 80286. The LOADALL instruction uses ES:EDI for the base of the LOADALL memory image.
Note that the normal address computation scheme applies to LOADALL; if protection is enabled (CR0.PE), and possibly
paging is enabled (CR0.PG), the physical address of the memory area will be computed by both segment, and page
relocation. A typical sequence to perform the LOADALL would be:
MOV AX,Dump_Area_Selector
MOV ES,AX
MOV EDI,offset Dump_Area
LOADALL
### 1.1 Background
As part of marketing the 286, most of the details of one of the 286 test instructions were published to selected
customers and ISVs in a note entitled "[[Undocumented] iAPX 286 LOADALL Instruction](/pubs/pc/reference/intel/80286/loadall/)",
by Bill Rash. The test instruction was named LOADALL for public consumption. The instruction was published to provide
two functions: to allow REAL mode code to access memory above 1 Meg, and to allow a protected mode OS to simulate 8086
semantics for segment register loads as a key part of implementing a "virtual 8086 mode" on the 286. When the details
of the "LOADALL" instruction were released, we made it quite clear that the instruction would not be supported on the
386. However, regardless of our warnings, by publishing the details of the 286 LOADALL we effectively made it a part
of the 286 architecture. People will use the instruction anyway, and we must support the 286 LOADALL instruction on
the 386.
The 386 has similar test instructions, which are "culturally compatible" with the 286 test instructions. The
instructions on both machines reload internal machine state from a block of memory. However, the format of the memory
area is quite different, and the 386 LOADALL loads more state. Things that were 16-bits on the 286 were stretched
to 32 bits on the 386.
### 1.2 Emulating 286 LOADALL with 386 LOADALL
As noted above, the 386 LOADALL function is pretty close the the 286 LOADALL instruction, and it is possible to
reformat the 286 image to a 386 image and use the 386 instruction to provide emulation capability. This requires the
following:
+ The 386 must trap the 286 LOADALL opcode.
+ Need code to translate 286 LOADALL format to 386 format.
The 386 traps the 286 LOADALL opcode, since the 286 LOADALL opcode (0F05) an illegal opcode on the 386. The 386
LOADALL has a different opcode (0F07). A 386 OS that wishes to emulate the 286 LOADALL can include an interrupt 6
(invalid opcode fault) handler to emulate the 286 LOADALL. The invalid opcode fault handler will be invoked whenever
the 286 LOADALL instruction occurs in the instruction stream. The fault handler can decode the invalid instruction,
and if it is the 286 LOADALL, can reformat the memory image in a new area, and execute a 386 LOADALL. Because the
386 LOADALL can load from an arbitrary address, the block at 800H can be left undisturbed, with the reformatting done
in a part of the address space not accessible on the 286 (above 16 Meg. for example).
The information loaded by the 286 LOADALL falls into 3 categories: programmer visible registers, 286 specific temp
registers, and "invisible" descriptor cache registers. There is no problem with emulating the loading of the programmer
visible registers, as these are compatibly implemented on the 386 (and the 486, 586, ...). The 286 also loads a number
of temp registers, but the values in these registers are "dead" when the next instruction (other than STOREALL)
begins execution. Consequently, the values loaded into the temp registers can have no effecton 286 program execution,
so these can be ignored. As long as the 386 temps are also "dead" when the next instruction begins (except for STOREALL),
there will be no problems with 386-specific temp registers.
In order to ease the burden of supporting LOADALL on future processors, the temp register dump/load area is at the
top of the LOADALL block, so it can grow and shrink as required for future implementations. Several difficulties occur
when attempting to emulate the loading of the invisible descriptor cache registers. Unfortunately, this is the main
reason why the 286 loadall is an interesting instruction....
To verify that the 386 LOADALL can emulate the 286 LOADALL, we need to verify that all of the invisible 286 descriptor
cache entries modified by the 286 LOADALL are also modified by the 386 LOADALL. Any extra state can just be loaded with
the 286 compatible values. Some "don't care" values on the 286 are now recognized by the 386, and so these may need to
be parsed and reformatted.
### 1.2.1 Translating 286 LOADALL format to 386 LOADALL
This section sketches the algorithm for translating the 286 LOADALL format to the format
required for 386 LOADALL. Special considerations for each field in the 286 descriptor cache are given below:
**MSW**
> Only the lower 4 bits are defined on the 286. Bit 0 is sticky on the 286 LOADALL, so software must OR in the
current setting of bit 0 of CR0 with the 286 LOADALL image to get the CR0 image for the 386 LOADALL. The ET bit is
new on the 386, as is the PG bit. Both of these bits should remain unchanged, and so should be copied from the
current CR0 value. This can be done with the following code sequence:
MOV EAX,CR0
AND EAX,80000011H
MOV CX,LD286MSW ; Load 286 MSW image AND ECX. OFh ; mask low bits
OR EAX,ECX
MOV LD386,CR0 ; value for 386 LOADALL
**TR, LDT, DS, SS, CS, ES Selectors**
> These can be copied directly.
**FLAGS**
> The 386 defines two new flags. The 286 flags can be copied directly to the low order 16 bits of the 386 flags.
The RF bit can be set to 0, and the VM bit set if the emulated program is in Virtual 8086 mode (if the LOADALL was
trapped in a Virtual 8086 program), and cleared otherwise. The VM bit can be copied from the EFLAGS image pushed
when the invalid opcode trap is taken.
**IP**
> The 286 IP register is copied to the low order 16 bits of the 386 EIP image, and the upper 16 bits of the EIP
image cleared.
**AX...SI**
> The 286 register images are copied to the lower 16 bits of the 386 32-bit registers. The upper 16 bits can be
random trash, or could be set to 0 for tidyness. Only EIP needs to have its upper bits cleared.
**ES...DS Descriptor Cache Entries**
> These can be reformatted to 386 descriptor cache entries. The base and limit values translate directly to the 386,
with extra high-order zeros. However, the AR values may not translate.
> The 286 uses only bit 1, bit 2, bit 3, and bit 7 of the AR byte to do protection checks. The 386 uses these bits,
plus the "G" and "B" bits to perform checks. If the "G" and "B" bits are 0, the checks are 100% compatible. The 286
and 386 may behave differently if the DPL field of the SS and CS descriptor entries are not equal, or if the RPL
fields of the SS and CS selectors do not match the DPL field of the SS and CS descriptors. The 286 action in this
case is described as "undefined" in the LOADALL description. CPL is loaded from the AR byte for the SS register
(SS, not CS). If LOADALL is executed in protected mode, errors may occur in subsequent instructions if the RPL field
of SS or CS selectors, or the DPL of the CS descriptor, do not match the DPL field of the SS descriptor.
**GDTR, IDTR Registers**
> These translate directly. The low 5 bytes of the 286 LOADALL image are moved to the 3S6 image, and the upper byte
is set to 0.
**LDT Descriptor Cache**
> Similar to other descriptor cache entries, except that only a subset of the AR bits are on the 286 and 386.
Only the P bit is supported on both machines, so this descriptor entry should translate directly.
**TSS Descriptor Cache**
> Similar to other descriptor cache entries, except for the treatment of AR bits again. The 286 recognizes none
of the AR bits. The 386 recognizes bit 3 to distinguish 286 TSS types from 386 TSS types. The 286 descriptor can
be copied to the 386 LOADALL image directly, with bit 3 of the AR field set to 0.
To summarize, the 386 LOADALL instruction can be used to emulate the 286 LOADALL except for some questionable areas
involving the Access Rights bvtes in the "hidden" descriptor entries. The 286 LOADALL can be used to load these AR
fields with inconsistent values, in which case we don't know what the 286 will do, let alone whether the 386 matches
the 286 semantics. The 286 LOADALL can be emulated by the 386 LOADALL provided that the DPL and RPL values of CS and
SS are all equal. Other cases are undefined by the 286 (and cannot be induced by executing normal instructions).
### 1.3 LOADALL used to switch Modes
Any of the 80386 operating modes may be selected with LOADALL. The PE (Protection Enabled) bit is not 'Sticky' as in
the 286. By setting the appropriate bits in the memory area, the processor will resume execution in the selected mode
after LOADALL. For example, a LOADALL could be performed to a page protected VM86 task by setting the following
conditions in the memory image:
* PE and PG bits set to 1
* VM bit set in the extended flags register
* 8086 style segment register values into the memory image
* Descriptor bases to (Segment Reg SHL 4)
* Access rights (Present, ByteGranular, etc.)
* LIMIT set to 0000FFFFH.
As another example, RESET can be emulated with LOADALL, by loading the processor's initial values into the memory
image as follows:
* All registers=0
* GS,FS,DS,ES,SS=0
* CS=F000, EIP=FFF0, CS-Base-FFFF0000
* GS,FS,DS,ES,SS-Base=0
* GS,FS,DS,ES,SS-AR=Present
* GS,FS,DS,ES,SS-Limit=FFFF
* CR0=0
* All other control registers=0
* Debug Registers=0
* EFLAGS=0
After the LOADALL instruction, the processor state will be identical to reset, could be set to run at a CPL <> 0
while in real mode. Combinations such as these are possible, but may have unexpected results. Placing the processor
into other than a 'Natural' state should be avoided.
### 1.4 Caveats
Note that LOADALL provides no error checking. It is important that the descriptor entries match the selector entries
(Unless the intent is that they do not; for example to give a REAL mode program access to the extended address space).
After LOADALL. the CPL of the processor will be set to the DPL of the SS Descriptor entry. This is necessary to
accomodate conforming segments. The IOPL will be set from the IOPL value in the EFLAGS image.
LOADALL is not restartable. If a page or segment fault occurs during execution of LOADALL, the processor will be left
in an undefined state. LOADALL is a privileged instruction, so it can be executed only at level 0. It is assumed that
the OS kernel will restrict use of this instruction, and will check for addressability and for consistent semantics
before executing the LOADALL.
### 1.5 386 LOADALL Memory Format
The following tables define the LOADALL memory format. The LOADALL instruction uses a 512-byte block of memory,
where the lowest addressed byte is given in ES:[(E)DI]. The area above offset CC hex is used for processor dependent
registers (temporaries, invisible registers). These are loaded into the processor, but will not affect normal program
execution. All values in the memory area are read from a four byte field, to keep the memory format DWORD aligned,
but it is possible to locate memory area at a non-aligned address. In this case, the execution time of LOADALL will
DOUBLE. For this reason, the memory dump area should always be DWORD aligned.
Each descriptor entry consists of 3 pieces:
* AR
* Base
* Limit
The AR part has the same format as the second dword of a segment descriptor except that only the AR byte (bits 8-15)
and the G and B/D bits (bits 23 and 22) are used. All other bits in the AR field are ignored. The Base and Limit parts
contain full 32-bit values, fully expanded and unscrambled from the 386 descriptor. In particular, the Limit field
loaded for a page granular segment gives a byte granular limit, so should contain the page limit*4096 plus 4095.
**80386 LOADALL Memory Format**
Offset | Register
:--------: | :--------:
000 | CR0
004 | EFLAGS
008 | EIP
00C | EDI
010 | ESI
014 | EBP
018 | ESP
01C | EBX
020 | EDX
024 | ECX
028 | EAX
02C | DR6
030 | DR7
034 | TSSR(TSSSelector-Word)
038 | LDTR(LDTSelector-Word)
03C | GS
040 | FS
044 | DS
048 | SS
04C | CS
050 | ES
054 | TSS(AR)
058 | TSS(BASE)
05C | TSS(LIMIT)
060 | IDT(AR)
064 | IDT(BASE)
068 | IDT(LIMIT)
06C | GDT(AR)
070 | GDT(BASE)
074 | GDT(LIMIT)
078 | LDT(AR)
07C | LDT(BASE)
080 | LDT(LIMIT)
084 | GS(AR)
088 | GS(BASE)
08C | GS(LIMIT)
090 | FS(AR)
094 | FS(BASE)
098 | FS(LIMIT)
09C | DS(AR)
0A0 | DS(BASE)
0A4 | DS(LIMIT)
0A8 | SS(AR)
0AC | SS(BASE)
0B0 | SS(LIMIT)
0B4 | CS(AR)
0B8 | CS(BASE)
0BC | CS(LIMIT)
0C0 | ES(AR)
0C4 | ES(BASE)
0C8 | ES(LIMIT)