Microprocessador de 32 bits (MC68000)

Ao contrário do que você pode imaginar, os microprocessadores de 32 bits são mais velhos do que os de 16. O primeiro microprocessador comercial (encapsulado em um chip) foi o 4004, da Intel (processador de 4 bits — você leu certo!) em 1969. Dez anos depois surge o MC68000 e somente alguns anos depois surge o 8088/8086. Claro, estou citando apenas os microprocessadores comercialmente relevantes aqui. Somente no final do ano de 1985 a Intel lançou seu processador de 32 bits, o 80386 (e só no iniciozinho dos anos 90 foi usado nos PCs). Ou seja, a Motorola já tinha seu processador de 32 bits sendo usado em alguns (poucos) mainframes, no MacIntosh e depois no Amiga, quando os PCs com arquitetura de 32 bits começaram a aparecer.

Se fôssemos falar de computadores, na época da criação do UNIX, Ken Thompson relata algumas experiências que fazia em máquina com “palavra” de 36 bits e onde 1 “byte” tinha 9 bits (não 8)… Isso, também, no final dos anos 60. E, só para comparar, em 1946 o ENIAC usava “palavras” de 10 bits (o projeto começou em 1943 e terminou em 1956 [coincidência em relação à “invenção” do transístor em 1955?]).

MC68000

AMIGA 500 usava o MC68000.

O 68000 (ou 68k) é um processador interessante: Internamente, todos seus registradores (exceto flags) têm 32 bits de tamanho, mas externamente seu barramento de dados é de 16… Por isso a documentação o trata como um processador de 16/32 bits. Mas, o que chama a atenção para ele não é o conjunto de instruções ou o tamanho da “palavra”. Ele contém um conjunto abrangente de “modos de endereçamento” e um conjunto grande, para a época, de registradores de uso geral.

Existem 16 deles… D0 até D7 são registradores de 32 bits usados para conter e manipular dados (considere que o 8086 tem apenas 4: AX, BX, CX e DX). A0 até A7 são também registradores de 32 bits, mas dedicados a conter e manipular endereços. De fato, A7 é especial, dedicado a conter o endereço do topo da pilha (USP ou User Stack Pointer). Além desses, temos o PC (Program Counter) de 32 bits — o que, em teoria, poderia nos dar um espaço de endereçamento de 4 GiB, já em 1979! Embora o MC68000 tivesse barramento de endereços de 24 bits, possibilitando, no máximo, 16 MiB) e o registrador de 16 bits CCR (Condition Code Register) que contém os flags e alguns bits de controle.

Assembly

Quem já mexeu com o assembler inline do GCC já reparou que, no padrão AT&T, temos que informar ao compilador que a instrução usa “palavras” de tamanho específico e a ordem dos operandos fonte e destino é invertida (em relação aos mnemônicos usados pela Intel), como em:

movl $0,%eax

Aqui temos a movimentação do valor 0 para dentro do registrador EAX. E a redundância de termos que informar um ‘l’ (de long), logo após o mnemônico ‘mov’.

Suspeito que essas notações tiveram origem no MC68000. No Assembly dele a coisa funciona do mesmo jeito, com alguns detalhes diferentes… Ao invés de simplesmente colocarmos um ‘l’, temos que colocar um ‘.l’ e o caracter ‘$’ é usado para denotar um valor hexadecimal. O caracter usado para denotar um valor imediato é ‘#’. Assim, para colocarmos o byte 0xff entro de D0 temos que escrever:

move.b #$ff,d0

Se você esquecer de colocar o ‘#’ na frente o valor é um endereço de memória. E, outra coisa: Somente os registradores D# podem manipular coisas menores que 32 bits.

Outro notação similar ao padrão AT&T é o uso de offsets nos endereçamentos. Por exemplo:

move.l 4(a0),d0  ; ou move.l (4,a0),d0

Aqui temos o valor 4 adicionado a A0 antes de ler o DWORD da memória…

Outra coisa à frente de nosso tempo, que já tinha nos 68000 e só veio a aparecer na arquitetura da família 80×86 com o surgimento do modo amd64 (ou x86-64), é o endereçamento relativo ao PC.

O 68k não é RISC

RISC significa somente “Reduced Instruction Set Computer“. Ou seja, se o processador tem poucas (mas, poderosas, instruções) é RISC… O 68000 é CISC (C de Complex) porque possui algumas instruções interessantes. Por exemplo, MOVEM pode mover múltiplos operandos para dentro de vários registradores. Literalmente uma lista de dados/registradores para outros dados/registradores. Em C, uma expressão como “a = b = *p = 0” pode ser feita com uma única instrução em linguagem de máquina!

Alguns fazem confusão a respeito do 68000, como se ele fosse RISC, pelo grande número de modos de endereçamento. Por exemplo, existem dois tipos de endereçamento indiretos que fazem, automaticamente, pós incrementos e pré-decrementos. Por exemplo:

move.l -(a0),d0
move.l d0,(a1)+

O que é incrementado ou decrementado aqui não é o conteúdo da memória endereçada, mas o registrador A#. Agora, dê uma olhada no código padrão da rotina strcpy:

# char *strcpy(char *d, char *s)
# {
#   char *p = d;
#   while (*d++ = *s++);
#   return p;
# }
strcpy:
  link.w %fp,#0        # A6 = SP (não reserva espaço local).

  move.l %a2,-(%sp)    # O compilador preferiu reservar
                       # temporário local aqui!

  move.l 8(%fp),%a0    # A0 = d
  move.l 12(%fp),%a2   # A2 = s
  move.l %a0,%a1

.L2:
  move.b (%a2)+,%d0
  move.b %d0,(%a1)+
  jne .L2

  move.l %a0,%d0       # Retorna p em D0.

  move.l (%sp)+,%a2

  unlk %fp             # Restaura a pilha...
  rts

Observe, particularmente, o loop… Em primeiro lugar, MOVE, assim como no 6502, afeta o flag Z. Em segundo lugar, o próprio modo de endereçamento incrementa os ponteiros que foram passados como argumentos para a função! (Não sei o suficiente da convenção de chamada do GCC para o 68000 para te dizer porque ele precisa salvar A2 na pilha!). Outra coisa: FP (de Frame Pointer) é apenas um apelido para A6.

Modo “protegido”, memória virtual e ponto-flutuante

Desde o começo, em 1979, o 68000 possui modos de operação distintos. Dentre eles o modo Supervisor e o modo User, sendo o primeiro “mais privilegiado” do que o segundo… Somente com o 68020 é que o recurso de “paginação” foi introduzido, por hardware, no microprocessador e, somente com o 68030 as instruções de ponto flutuante foram incorporadas (antes, era necessário o uso de um co-processador matemático: o 68881/68882 (em meados dos anos 80) — o mesmo ocorreu com a Intel e seu 8087).

Com o 68010 a Motorola introduziu o 68851, Um chip dedicado a MMU (Memory Management Unit), que permitia a virtualização de memória (em 1982!).

O maior “erro” da IBM, em minha opinião…

… foi não criar o PC com base no 68000. Pensem como seria o avanço de 8 para 32 bits de uma só tacada e, em pouco tempo, o uso de memória virtual!!! Isso era perfeitamente factível, na época, tanto é que a Apple logo lançou o MacIntosh, com interface gráfica… O fato do Mac ser caro, na época, foi mais devido a ganância (ou ao alto custo do investimento feito por uma empresa pequena, em comparação à IBM) do que qualquer outra coisa.

Diz a “lenda” que a IBM queria o PC no 68000, mas não encontrou uma empreiteira que desenvolvesse o DOS para eles. Entra em cena a Microsoft e a sugestão de uso de processadores Intel…