# X87

x87 - É o nome genérico dado aos co-processadores Intel de ponto flutuante que funcionavam em conjunto com os processadores de dados, cada um com o seu par. Originou-se como uma extensão da instrução set 8086 na forma de co-processadores de ponto flutuante opcional que trabalhou em conjunto com CPUs x86 correspondentes. Estes microchips tinham nomes terminados em "87". Como outras extensões para o conjunto de instruções básicas, as instruções x87 não são estritamente necessárias para a construção de programas de trabalho, mas para fornecer hardware e microcódigo em implementações de tarefas comuns numérica, permitindo que estas tarefas sejam executadas muito mais rapidamente que as rotinas de código normais. O conjunto de instruções x87 inclui instruções para operações básicas de ponto flutuante, como adição, subtração e comparação, mas também para mais complexas operações numéricas, como o cálculo da função tangente e seu inverso.
A maioria dos processadores x86 desde o Intel 80486 tiveram estas instruções x87 implementadas na CPU principal, mas o termo ainda é usado para se referir a essa parte do conjunto de instruções. Antes das instruções x87 serem padrão em PCs, os compiladores ou programadores tinham de usar uma biblioteca bastante lenta para fazer chamadas ou executar operações de ponto flutuante, um método que ainda é comum em (baixo custo) sistemas embarcados.

## Descrição

Os registros da x87 formam uma estrutura de nível 8-deep stack não-rígidas que vão desde ST (0) para ST (7) com registros que podem ser acessados diretamente por qualquer operando, usando um deslocamento em relação ao superior como em uma pilha. Há instruções para deslocar e calcular valores no topo desta pilha, operações monádicas (FSQRT, FPTAN etc), no endereço ST superior (0) enquanto as operações diádicas (FADD, FMUL, FCOM, etc) nos ST (0) e ST (1). O modelo de pilha não-estrita também permite a operações diádicas usarem ST (0) juntamente com um operando de memória direto ou com uma especifica pilha-registro, ST (x), em um papel semelhante a um acumulador tradicional (um destino combinado e operando à esquerda).
Isso também pode ser revertido em uma base de instrução por instrução com ST (0) com o operando modificado e ST (x) como destino. Além disso, o conteúdo de ST (0) pode ser trocado com outro registro pilha usando uma instrução chamada FXCH ST (x).
Isso faz com que as pilhas x87 sejam utilizaveis em 7 registradores de endereço mais um acumulador dedicado (ou até sete acumuladores independentes). Isto é especialmente aplicável em superprocessadores escalares x86 (como o Pentium de 1993 e posteriores), onde estas instruções de troca (códigos D9C8 .. D9CFh) são otimizadas para baixo a zero clock, usando um dos caminhos inteiro para FXCH ST (x) em paralelo com a instrução FPU. Apesar de ser natural e conveniente para os programadores da linguagem assembly, alguns desenvolvedores de compiladores tem encontrado dificuldade para construir geradores de código automático que agendem código de forma eficaz.
O x87 fornece precisão simples, dupla precisão e 80-bit de precisão estendida duplamente binária-aritmética de ponto flutuante de acordo com a IEEE 754-1985 padrão. Por padrão, os processadores x87 usam 80-bit de precisão dupla estendida internamente (para permitir a precisão sustentada durante muitos cálculos). Uma determinada seqüência de operações aritméticas podem se comportar de forma ligeiramente diferente em comparação com uma precisão única ou de precisão dupla IEEE 754 FPU [1]. Isso às vezes pode ser problemático para alguns cálculos semi-numéricos confiando no conhecimento de precisão FPU exato para a operação correta. Para evitar tais problemas, o x87 pode ser configurado através de um status especial de configuração que registra automaticamente a volta para precisão simples ou dupla, após cada operação. Desde a introdução do SSE2, as instruções x87 não são tão essenciais quanto eram uma vez, exceto para alta precisão cálculos exigindo a precisão de 64 bits mantissa disponível no formato 80-bit.

## Desempenho

Contagem de ciclo de relógio para exemplos de típicos instruções x87 FPU (apenas versões registradas são mostradas).
A notação A ~ B (mínimo ao máximo), abrange variações de tempo dependente do estado da pipeline transitória, bem como a precisão aritmética escolhida (32, 64 ou 80 bits), que também inclui variações devido a casos numéricos (como o número de bits definidos, zeros, etc.) A notação L → H retrata valores correspondentes a mais baixa (L) e o mais alto (H) freqüências de clock máximo que estavam disponíveis. vale a pena ter
| x87 implementation | FADD | FMUL | FDIV | FXCH | FCOM | FSQRT | FPTAN | FPATAN | Max Clock | Peak FMUL/sec | Relative 5 MHz 8087$^§$ FMUL |
| 8087 | 70~100 | 90~145 | 193~203 | 10~15 | 40~50 | 180~186 | 30~540 | 250~800 | 5→10 MHz | 34~55K → 100~111K | 1.0 → 2.0 times as fast |
| 80287 (original) | 70~100 | 90~145 | 193~203 | 10~15 | 40~50 | 180~186 | 30~540 | 250~800 | 6→12 MHz | 41~66K → 83~133K | 1.2 → 2.4 times as fast |
| 80387 (and later 287 models) | 23~34 | 29~57 | 88~91 | 18 | 24 | 122~129 | 191~497 | 314~487 | 16→33 MHz | 280~552K → 579~1100K | approx 10 → 20 × as fast |
| 80486 (or 80487) | 8~20 | 16 | 73 | 4 | 4 | 83~87 | 200~273 | 218~303 | 16→50 MHz | 1.0M → 3.1M | approx 18 → 56 × as fast |
| Cyrix 6x86, Cyrix MII | 4~7 | 4~6 | 24~34 | 2 | 4 | 59~60 | 117~129 | 97~161 | 66→300 MHz | 11~16M → 50~75M | approx 320 → 1400 × |
| AMD K6 (including K6 II/III) | 2 | 2 | todo | 2 | todo | todo | todo | todo | 166→550 MHz | 83M → 275M | approx 1500 → 5000 × |
| Pentium / Pentium MMX | 1~3 | 1~3 | 39 | 1 (0*) | 1~4 | 70 | 17~173 | 19~134 | 60→300 MHz | 20~60M → 100~300M | approx 1100 → 5400 × |
| Pentium Pro | 1~3 | 2~5 | 16~56 | 1 (0*) | 1 | 28~68 | todo | todo | 150→200 MHz | 30~75M → 40~100M | approx 1400 → 1800 × |
| Pentium II / III | 1~3 | 2~5 | 17~38 | 1 (0*) | 1 | 27~50 | todo | todo | 233→1400 MHz | 47~116M → 280~700M | approx 2100 → 13000 × |
| Athlon (K7) | 1~4 | 1~4 | 13~24 | 1 (0*) | 1~2 | 16~35 | todo | todo | 500→2330 MHz | 125~500M → 0.580~2.33G | approx 9000 → 42000 × |
| Pentium 4 | 1~5 | 2~7 | 20~43 | 1 (0*) | todo | 20~43 | todo | todo | 1.3→3.8 GHz | 186~650M → 0.543~1.90G | approx 11000 → 34000 × |
| Athlon 64 (K8) | 1~4 | 1~4 | 13~24 | 1 (0*) | 1~2 | 16~35 | todo | todo | 1.0→3.2 GHz | 250~1000M → 0.800~3.2G | approx 18000 → 58000 × |
* Um atraso de clock efetivo zero é frequentemente possível, via execução superescalar. $^§$ 5 MHz 8087 foi o processador x87 original. Comparando softwares implementados com rotinas de ponto flutuante em um 8086 (sem 8087), os fatores seriam ainda maiores, talvez por um outro fator de 10 (ou seja, uma adição ponto correto flutuante em linguagem assembly pode muito bem consumir mais de 1000 ciclos).

## Fabricantes

Empresas que tenham desenvolvido ou fabricado unidades de ponto flutuante compatível com o Intel 8087 ou modelos mais recentes incluem: AMD (287, 387 486DX, 5x86, K5, K6, K7, K8), Chips and Technologies (o co-processadores MATH Super), Cyrix (o FasMath, Cx87SLC, Cx87DLC, etc, 6x86, Cyrix MII), Fujitsu (início Pentium Mobile, etc), Harris Semiconductor (fabricado 80387 e processadores 486DX), IBM (387 e 486 desenhos diferentes), IDT (o WinChip, C3, C7, Nano, etc), IIT (o 2C87, 3C87, etc), LC Tecnologia (coprocessors MATH Green), National Semiconductor (o Geode GX1, Geode GXM, etc), NexGen (o Nx587), Tecnologia Rise (o MP6), ST Microelectronics (486DX fabricados, 5x86, etc), Texas Instruments (processadores 486DX fabricados, etc), Transmeta (TM5600 e TM5800 a), ULSI (o Math · coprocessors Co), VIA (o C3 , C7 e Nano, etc) e Xtend (o co-processadores 83S87SX-25 e outros).

## Arquiteturas
### 8087

O 8087 foi o primeiro co-processador matemático para processadores 16-bit projetado pela Intel (o I8231 era mais velho, mas projetado para a Intel 8-bit 8080), que foi construído para ser emparelhado com o Intel 8088 ou 8086 microprocessadores.

#### Instruções original do 8087

| Instrução | Significado | Notas |
| F2XM1 | 2$^x$ - 1 | maior precisão que 2$^x$ para $x$ perto de zero |
| FABS | Valor absoluto | |
| FADD | Soma | |
| FADDP | Soma e "Pop (ver LIFO)" | |
| FBLD | Carrega BCD | |
| FBSTP | Carrega BCD e "Pop (ver LIFO)" | |
| FCHS | Troca sinal | |
| FCLEX | Limpa execções | |
| FCOM | Compara | |
| FCOMP | Compara e "Pop (ver LIFO)" | |
| FCOMPP | Compara e "Pop (ver LIFO)" duas vezes | |
| FDECSTP | Decrementa o ponteiro da pilha de ponto flutuante | |
| FDISI | Desativa Interrupções | |
| FDIV | Divide | |
| FDIVP | Divide e "Pop (ver LIFO)" | |
| FDIVR | Divide reservado | |
| FDIVRP | Divide reservado e "Pop (ver LIFO)" | |
| FENI | Ativa interrupções | |
| FFREE | Libera registrador | |
| FIADD | Soma de inteiros | |
| FICOM | Comparação de inteiros | |
| FICOMP | Comparação de inteiros e "Pop (ver LIFO)" | |
| FIDIV | Divide inteiros | |
| FIDIVR | Divide inteiros reversamente | |
| FILD | Carrega inteiros | |
| FIMUL | Multiplicação de inteiros | |
| FINCSTP | Incrementa o ponteiro da pilha de ponto flutuante | |
| FINIT | Inicializa processador de ponto flutuante | |
| FIST | Armazena inteiro | |
| FISTP | Armazena inteiro e "Pop (ver LIFO)" | |
| FISUB | Subtração de inteiros | |
| FISUBR | Subtração de inteiros reversamente | |
| FLD | Carrega ponto flutuante | |
| FLD1 | Carrega 1.0 na pilha | |
| FLDCW | Carrega palavra de controle | |
| FLDENV | Carrega estado de ambiente | |
| FLDL2E | Carrega log$_2$(e) na pilha | |
| FLDL2T | Carrega log$_2$(10) na pilha | |
| FLDLG2 | Carrega log$_{10}$(2) na pilha | |
| FLDLN2 | Carrega ln(2) na pilha | |
| FLDPI | Carrega π na pilha | |
| FLDZ | Carrega 0.0 na pilha | |
| FMUL | Multiplica | |
| FMULP | Multiplica e "Pop (ver LIFO)" | |
| FNCLEX | Limpa execções, nenhuma espera | |
| FNDISI | Desativa execções, nenhuma espera | |
| FNENI | Ativa execções, nenhuma espera | |
| FNINIT | Inicializa processador de ponto flutuante, nenhuma espera | |
| FNOP | Nenhuma operação | |
| FNSAVE | Salva o estado da FPU, nenhuma espera, 8-bit | |
| FNSAVEW | Salva o estado da FPU, nenhuma espera, 16-bit | |
| FNSTCW | Armazena palavra de controle, nenhuma espera | |
| FNSTENV | Armazena o ambiente da FPU, nenhuma espera | |
| FNSTENVW | Armazena o ambiente da FPU, nenhuma espera, 16-bit | |
| FNSTSW | Armazena palavra de status, nenhuma espera | |
| FPATAN | Arcotangente parcial | |
| FPREM | Resto parcial | |
| FPTAN | Tangente parcial | |
| FRNDINT | Arredonda para inteiro | |
| FRSTOR | Restaura estado salvo | |
| FSAVE | Salva o estado da FPU | |
| FSAVEW | Salva o estado da FPU, 16-bit | |
| FSCALE | Escala por fator de 2 | |
| FSQRT | Raiz quadrada | |
| FST | Armazena ponto flutuante | |
| FSTCW | Armazena palavra de controle | |
| FSTENV | Armazena ambiente da FPU | |
| FSTENVW | Armazena ambiente da FPU, 16-bit | |
| FSTP | Armazena e "Pop (ver LIFO)" | |
| FSTSW | Armazena palavra de estado | |
| FSUB | Subtração | |
| FSUBP | Subtração e "Pop (ver LIFO)" | |
| FSUBR | Subtrai reversamente | |
| FSUBRP | Subtrai reversamente e "Pop (ver LIFO)" | |
| FTST | Testa por ZERO | |
| FWAIT | Aguarda enquanto a FPU está executando | |
| FXAM | Examina flags de condição | |
| FXCH | Troca registradores | |
| FXTRACT | Extrai expoente e significado | |
| FYL2X | y * log$_2$(x) | se $y={\frac {1}{\log _{2}b}}$, então a base-$b$ logaritmica é computada |
| FYL2XP1 | y * log$_2$(x+1) | mais precisão que $\log _{2}z$ se $x$ está perto de ZERO |

### 80287

Versão 6 MHz da Intel 80287 Intel 80287XL. Intel 80287XLT.

#### 80287(i287)

O 80287 (i287) foi o co-processador matemático para o 80286 Intel série de microprocessadores. Intel (e seus concorrentes) mais tarde introduziu um 80287XL, que era na verdade um 80387SX com uma pinagem 287. O 80287XL continha um multiplicador de 3 / 2 interna, de modo que as placas mãe que corria o co-processador de 2 / 3 da velocidade da CPU pode executar o FPU vez na mesma velocidade da CPU. Outros modelos com 287 387-como o desempenho foram o Intel 80C287, construído usando CHMOS III, eo AMD 80EC287 fabricado em processo da AMD CMOS, usando apenas portas totalmente estática.

#### 80287XL e 80287XLT

O 80287 e 80287XL também trabalhou com o microprocessador 80386, e foram, inicialmente, o co-processadores só está disponível para o 80386 até a introdução dos 80.387 em 1987. Finalmente, eles também foram capazes de trabalhar com o Cx486SLC Cyrix. No entanto, para ambos os chips da 80387 foi o preferido para o seu maior desempenho e maior capacidade de seu conjunto de instruções.Modelos da Intel incluíram i80287 variantes com limites de frequência superior que variam de 6 até 12 MHz. Mais tarde seguiu a i80287XL com 387 micro-arquitetura, o i80287XLT, uma versão especial destinado a laptops, bem como outras variantes.
* 6 MHz version of the Intel 80287
* Intel 80287 die shot
* Intel 80287XL
* Intel 80287XLT

### 80387

O 80387 (387 ou i387) foi o co-processador Intel primeira a ser totalmente compatível com o padrão IEEE 754. Lançado em 1987, um total de dois anos após o chip 386, o i387 incluída velocidade muito melhorado ao longo anteriores da Intel 8087/80287 co-processadores, e melhorou as características das funções trigonométricas. (A faixa de 80.287 a limitada argumento para mais ou para menos 45 graus.)
Sem um co-processador, o 386 normalmente desempenhadas aritmética de ponto flutuante através de rotinas (lento) software, implementado em tempo de execução através de um software manipulador de exceção. Quando um co-processador matemático está emparelhado com o 386, o co-processador executa a aritmética de ponto flutuante em hardware, retornando resultados muito mais rápido do que uma chamada de biblioteca.
O i387 é compatível apenas com o chip padrão i386, que tinha um barramento do processador de 32 bits. O i386SX depois teve custo reduzido, teve um estreito de 16 bits de barramento de dados, não poderia interagir com o bus i387 de 32 bits. O i386SX necessários a sua própria co-processador, o Intel 80387SX, que era compatível com o estreito de SX em barramento de dados 16-bit.
* i387
* i387SX
* i387DX
* i387 microarchitecture with 16-bit barrel shifter and CORDIC unit
* i386DX with i387DX
* Socket for the 80387

### 80187

O 80187 (80C187) foi o co-processador matemático para Intel 80186 e 80188 CPUs. O 80187 não apareceu ao mesmo tempo, como o 80186 e 80188, mas na verdade foi lançado após o 80287 eo 80387. Embora a interface para o processador principal foi o mesmo que o 8087, seu núcleo foi a dos 80.387, e foi, assim, plenamente compatível com IEEE 754, bem como capaz de executar todas as instruções de 80.387 extra. Embora a 8087 era perfeitamente capaz de operar com um 80186 ou 80188, o 80187 não funciona particularmente bem com o 8086 ou 8088. Há diferenças suficientes que o código tem que ser escrito especialmente para permitir uma combinação 80187 e 8086 / 8 a funcionar perfeitamente.

### 80487

O i487SX foi comercializado como um co-processador de ponto flutuante de unidade para Intel i486SX máquinas. Ele realmente continha uma implementação i486DX full-blown. Quando instalado em um sistema i486SX, o i487 desativava o CPU principal e assumia todas as operações da CPU. O i487 tomou medidas para detectar a presença de um i486SX e não funcionar sem a CPU original no lugar.

### 80587

O Nx587 foi o FPU x86 durar a ser fabricado separadamente da CPU, neste caso Nx586 NexGen.

## Ver Também

* MMX
* SSE, SSE2, SSE3, SSSE3, SSE4
* AVX
* 3DNow!
* SIMD