next up previous contents
Next: Processador Estrutura e Função Up: Arquitectura e Organização Interna Previous: Jogos de instruções: Características


Jogos de Instruções: Modos de Endereçamento e Formatos

No capítulo 9, pusemos a ênfase em, o jogo de instrução faz o o quê. Em particular, examinamos os tipos de operandos e as operações que podem ser especificadas pelas instruções máquina. Este capítulo regressa à questão de como especificar os operandos e as operações das instruções. Emergem dois tópicos. Em primeiro lugar, como é especificado o endereço de um operando e, em segundo lugar, como é que são organizados os bits de uma instrução para definir os endereços dos operandos e a operação da instrução.

Endereçamento

Como tínhamos mencionado, o endereço do campo, ou campos, do formato de uma instrução típica são bastante limitados. Gostaríamos de ser capazes de referenciar uma vasta gama de localizações da memória principal ou, para alguns sistemas, da memória virtual. Para atingir este objectivo, uma variedade de técnicas de endereçamento têm vindo a ser empregadas. Todas envolvem algum compromisso entre, por um lado, a gama de endereços e, ou a flexibilidade do endereçamento e, por outro lado, o número de referências à memória e, ou a complexidade do cálculo dos endereços. Nesta secção, examinamos as técnicas de endereçamento mais habituais.

Figura 10.1: Modos de Endereçamento.
\begin{figure}
\end{figure}

Aqueles modos estão ilustrados pela figura 10.1. Nesta secção, usamos a seguinte notação:
A = conteúdo do(s) campo(s) de endereço(s) da instrução
EA = endereço efectivo da posição que contém o operando referenciado
(X) = conteúdo da posição

A tabela 10.1 mostra os cálculo de endereços efectuado para cada modo de endereçamento.

Tabela 10.1: Modos básicos de Endereçamento.
\begin{table}
\end{table}


Endereçamento Imediato

A forma mais simples de endereçamento é o endereçamento imediato, no qual o operando está efectivamente presente na instrução:
OPERANDO = A
Este modo pode ser usado para definir e usar constantes ou atribuir o valores iniciais às variáveis. Tipicamente, o número é guardado em complemento para dois; o bit mais à esquerda do campo do operando é usado como bit de sinal. Quando o operando é carregado num registo de dados, o bit de sinal estende-se para a esquerda até ao máximo tamanho da palavra de dados.

A vantagem do endereçamento imediato é que não há nenhuma referência à memória para além da extracção da instrução necessária para obter o operando, dessa forma, poupando o ciclo de memória ou de cache no ciclo de instrução. A desvantagem é que o tamanho do campo de endereçamento é restringido ao tamanho do campo de endereço, o qual, em grande parte dos jogos de instruções é pequeno quando comparado com o tamanho da palavra.

Endereçamento Directo

Uma forma muito simples de endereçamento é o endereçamento directo, no qual o campo de endereço contém o endereço efectivo do operando:
EA = A

Esta técnica era habitual nas primeiras gerações de computadores e ainda pode ser encontrada num certo número de pequenos sistemas de computadores. A limitação óbvia, mencionada antes, é que esta apenas permite um campo de endereçamento limitado.

Endereçamento Indirecto

O problema que se põe com o endereçamento directo é que o comprimento do campo de endereço é habitualmente inferior ao comprimento da palavra, desta forma, limitando a gama de endereços. Uma solução é ter o campo de endereço a referenciar o endereço de uma palavra na memória, a qual, por sua vez, contém o endereço completo do operando. Isto é conhecido como endereçamento indirecto:
EA = (A)
(tal como foi, atrás, definido, os parêntesis devem ser interpretados como querendo significar conteúdo de. A vantagem, óbvia, desta abordagem é que, para a palavra de tamanho N passa a estar disponível um espaço de endereçamento de $2^N$. A desvantagem é que a execução da instrução necessita de duas referências à memória para extrair o operando, uma para obter o, respectivo, endereço e uma segunda para obter o valor.

O leitor notará que embora o número de palavras que podem ser endereçadas ser agora igual a $2^N$, o número de diferentes endereços efectivos que podem ser referenciados de uma só vez está limitado a $2^K$, sendo $K$ o comprimento do campo de endereço. No geral, isto não constitui, uma restrição de peso e pode tornar-se numa habilidade. Num ambiente de memória virtual, todos as localizações dos endereços efectivos de um processo, podem ser confinadas à página 0. (A única restrição é que o tamanho da página deve ser maior ou igual a $2^K$). Quando um processo está activo, haverá repetidas referências à página 0, o que tem como efeito que esta se mantenha permanentemente na memória real. Assim, uma referência indirecta à memória irá envolver, no máximo, uma falta de página em vez de duas.

Uma variante, raramente utilizada, do endereçamento indirecto é o endereçamento multi-nível ou em cascata:
EA = (... (A) ...)

Neste caso, um bit de endereço duma palavra-completa é uma agulha indirecta (I). Se o bit I é 0, então a palavra contém o EA. Se o bit é 1, então, é evocado um novo nível de via indirecta. Não parece existir nenhuma vantagem especial nesta abordagem, e a desvantagem é que podem ser necessárias três ou mais referências à memória para extrair um operando.

Endereçamento por Registo

O endereçamento por registo é semelhante ao endereçamento directo. A única diferença é que o campo de endereçamento referencia um registo em vez de um endereço na memória principal:
EA = R

Tipicamente, um campo de endereçamento que referencia registos terá 3 ou 4 bits, pelo que um total de 8 ou 16 registos de uso geral podem ser referenciados.

As vantagens do endereçamento de registos são que (1) na instrução é necessário, apenas, um campo pequeno de endereço e (2) não são requeridas referências à memória. Tal como foi discutido no capítulo 4, o tempo de acesso à memória é muito menor para um registo interno ao processador do que para um endereço na memória principal. A desvantagem do endereçamento de registos é que o espaço de endereçamento é muito limitado.

Se o endereçamento de registos é intensamente usado num jogo de instruções, isto implica que os registos do processador terão uma uso intensivo. Por causa do limite severo do número de registos (comparado com as posições da memória principal) o seu uso para este efeito só faz sentido se estes forem empregados com eficiência. Se todo o operando for trazido da memória principal para um registo, operado de uma vez, e retornado para a memória principal, então foi adicionado um passo intermédio desnecessário. Pelo contrário, se o operando no registo permanecer em uso durante múltiplas operações, então é obtida uma poupança real. Um exemplo é o resultado intermédio de um cálculo. Em particular, suponhamos que o algoritmo para multiplicação em complemento para dois era para ser implementado em software. A posição rotulada A no fluxograma (Figura 8.11) é referenciada muitas vezes e deveria ser implementada num registo em vez de numa posição da memória.

Compete ao programador decidir quais os valores que devem permanecer nos registos e os que devem ser guardados em memória. A maior parte dos processadores actuais empregam múltiplos registos de uso-geral, entregando ao programador da linguagem de montagem a responsabilidade pela eficiência da execução (e.g. programador de compiladores).

Endereçamento Indirecto por Registo

Tal como o endereçamento por registo é análogo ao endereçamento directo, o endereçamento indirecto de registos é análogo ao endereçamento indirecto. Em ambos os casos, a única diferença é se o campo de endereço referencia uma posição de memória ou um registo. Assim, para endereçamento indirecto de registo,
EA = ( R)

As vantagens e limitações do endereçamento indirecto de registo são basicamente as mesmas que as para o endereçamento indirecto. Em ambos os casos, a limitação do espaço de endereçamento é ultrapassada se fizermos com que aquele campo refira uma localização que contenha um endereço com o comprimento da palavra. Adicionalmente, o endereçamento indirecto de registos usa menos uma referência à memória do que o endereçamento indirecto.

Endereçamento por Deslocamento

Um modo poderoso de endereçamento combina as capacidades do endereçamento directo e de endereçamento indirecto de registo. É conhecido por uma variedade de nomes dependendo do contexto de utilização, mas o mecanismo básico é o mesmo. Referirmo-nos-emos-lhe como endereçamento por deslocamento.
EA = A + ( R)

O endereçamento por deslocamento requer que a instrução tenha dois campos de endereços, um dos quais, pelo menos, explícito. O valor contido num dos campos de endereço (valor = A) é usado directamente. O outro campo de endereço, ou uma referência implícita baseada no código de operação refere-se a um registo cujo conteúdo é adicionado a A para produzir o endereço efectivo.

Descreveremos três das mais comuns utilizações do endereçamento por deslocamento:

Endereçamento Relativo

Para o endereçamento relativo, o registo implicitamente referenciado é o apontador de programa (PC). Isto é, o endereço da instrução corrente é adicionado ao campo de endereço para produzir o EA. Tipicamente, o campo de endereço, para esta operação, é tratado como um número em complemento para dois.

O endereçamento relativo explora o conceito de localidade que foi discutido no capítulo 4 e 7. Se a maioria da referências à memória estiverem relativamente perto da instrução que está a ser executada, então a utilização do endereçamento relativo poupa bits de endereços da instrução.

Endereçamento por Registo-Base

Para o endereçamento por registo base, a interpretação é a seguinte: O registo referenciado contém um endereço de memória e o campo de endereço contém um deslocamento (habitualmente um inteiro em representação sem sinal) desde aquele endereço. O registo pode ser referido explícita ou implicitamente.

O endereçamento por registo base também explora a localidade das referências à memória. É uma maneira apropriada de implementar segmentação, que foi discutida no capítulo 7. Em algumas implementações, um único registo base de segmento é empregado e usado implicitamente. Em outros, o programador pode escolher um registo para conter o endereço base de um segmento e a instrução tem de referenciá-lo explicitamente. Neste último caso, se o comprimento do campo de endereço é $K$ e o número de possíveis registos é $N$, então, uma instrução pode referenciar qualquer uma das $N$ áreas de $2^K$ palavras.

Indexação

Para a indexação, a interpretação é tipicamente a seguinte: O campo de endereço referencia um endereço na memória principal e o registo referenciado contém um deslocamento positivo desde aquele endereço. É de notar que esta utilização é exactamente a oposta da interpretação para o endereçamento registo-base. Claro que é mais do que, apenas, uma questão de interpretação do utilizador. Uma vez que em indexação, o campo de endereço é considerado como sendo um endereço na memória, este contém mais bits do que o campo de endereço numa instrução comparável de registo-base. Também veremos que há alguns refinamentos à indexação que não seriam úteis no contexto de registo-base. Seja como for, o método de cálculo do EA para o endereçamento por registo-base e indexação é o mesmo para ambos e em ambos os casos a referência ao registo é umas vezes implícita e outras vezes explícita (para diferentes tipos de processadores).

Uma importante utilização da indexação é fornecer um mecanismo eficiente para efectuar operações iterativas. Consideremos, por exemplo, uma lista de números guardados a partir da posição A. Suponhamos que gostaríamos de somar 1 a cada elemento da lista. Nós necessitamos de extrair cada valor, somar-lhe 1 e guardá-lo de novo. A sequência de endereços efectivos de que necessitamos é A; A +1, A+2, ..., até à última posição da lista. Com a indexação, isto é feito facilmente. O valor de A é guardado no campo de endereço da instrução e o registo escolhido, chamado de registo índice é iniciado a zero. Depois de cada operação o registo índice é incrementado de 1.

Porque os registos de índice são habitualmente utilizados para tais tarefas iterativas, é típico que haja necessidade de incrementar ou decrementar o registo índice depois de cada referência a este. Uma vez que isto é operação habitual, alguns sistemas farão isso automaticamente como parte do mesmo ciclo de instrução. Isto é conhecido como auto-indexação. Se certos registos forem devotados exclusivamente à indexação, então a auto-indexação pode ser evocada implicitamente e automaticamente. Se forem usados registos de uso-geral, a operação de auto-indexação pode necessitar de ser sinalizada por um bit na instrução. A auto-indexação com incremento pode ser descrita como segue:
EA = A + R
R $\leftarrow$ (R) + 1

Em algumas máquinas, é suprido tanto o endereçamento indirecto como a indexação e é possível empregar ambas na mesma instrução. Há duas possibilidades: a indexação é efectuada depois ou antes do endereçamento indirecto. Se a indexação é efectuada depois de endereçamento indirecto é designada por pós-indexação:

EA = (A) + (R)

Em primeiro lugar o conteúdo do campo de endereço é usados para o acesso à posição de memória que contém o endereço directo. Este endereço é depois indexado pelo valor do registo. Esta técnica é útil para o acesso a um certo número de blocos de dados de formato fixo. Por exemplo, tal como foi descrito no capítulo 7, o sistema de operação necessita de empregar um bloco de controlo de processos para cada processo. As operações efectuadas são a mesmas independentemente do bloco que está a ser manipulado. Assim o endereço na instrução que referência o bloco pode apontar para uma posição (valor = A) que contém um apontador variável para o início do bloco de controlo de processo. O registo índice contém o deslocamento dentro do bloco.

Com pré-indexação a indexação é efectuada antes do endereçamento indirecto:
EA = (A + (R))

Um endereço é calculado tal como uma indexação simples. Nesta caso, contudo, o endereço calculado contém não o operando, mas o endereço do operando. Um exemplo do uso desta técnica é a construção de uma tabela de derivação por múltiplas vias. Num determinado ponto de um programa, pode existir uma derivação para uma de um certo número de porções dependendo das condições. Uma tabela de endereços pode ser construída com inicio na posição A. A localização pretendida pode ser obtida por indexação desta tabela.

Normalmente, um jogo de instrução não deverá incluir pré-indexação e pós-indexação.

Endereçamento de Pilha

O último modo de endereçamento que consideramos é o endereçamento de pilha. Tal como é definido no Apêndice 9A, uma pilha é uma lista linear de posições. É algumas vezes referida como uma lista empurra para baixo ou fila último-a-chegar primeiro-a-sair. A pilha é um bloco reservado de posições. Os itens são adicionados ao topo da pilha de forma a que, a qualquer momento, o bloco possa ser preenchido. Associado com a pilha está um apontador cujo valor é o endereço do topo da pilha. Em alternativa os dois elementos do topo da pilha podem estar em registos do processador, neste caso o apontador de pilha referencia o terceiro elemento da pilha (fig. 9.14). O apontador de pilha é mantido num registo. Assim, as referências a posições da pilha na memória são na verdade endereços indirectos por registo.

O modo de endereçamento de pilha é uma forma de endereço implícito. As instruções máquina não necessitam de incluir uma referência à memória, mas operam implicitamente no topo da pilha. As pilhas não têm sido, tradicionalmente, muito comuns mas estão a tornar-se extremamente comuns em micro-processadores.

Modos de Endereçamento no Pentium

Recordemos da figura 7.25 que o mecanismo de tradução de endereços no Pentium produz um endereço, chamado endereço virtual ou endereço efectivo que é um desvio num segmento. A soma do endereço de partida do segmento com o endereço efectivo produz um endereço linear. Se estiver a ser usada paginação, este endereço linear tem de passar através de um mecanismo de translação para produzir um endereço físico. No que segue, ignoramos este último passo, uma vez que este é transparente para o jogo de instruções e para o programador.

O Pentium está equipado com uma variedade de modos de endereçamentos desenhados para permitir a execução eficiente de linguagens de alto-nível tais como o C e o Fortran. A figura 10.2 mostra o hardware envolvido.

Figura 10.2: Cálculo dos modos de endereçamento no Pentium.
\begin{figure}
\end{figure}

O segmento que é sujeito à referência é determinado pelo registo de segmento. Há seis registos de segmento; o que está a ser usado para uma determinada referência depende do contexto de execução e da instrução. Cada registo de segmento contém o endereço do segmento correspondente. Associado com cada registo de segmento visível ao utilizador está um registo descritor de segmento (não visível ao programador) o qual regista os direitos de acesso ao segmento, assim como o endereço inicial e o comprimento do segmento. Adicionalmente, há dois registos que podem ser usados para construir um endereço: o registo base e o registo índice.

A tabela 10.2 lista os 12 modos de endereçamento do Pentium. Consideremos cada uma destes à vez.

Para o modo imediato o operando está incluído na instrução. O operando pode ser um octeto, palavra, ou dupla palavra.

Para o modo operando em registo, o operando está localizado num registo. Para as instruções gerais tais como transferência de dados, aritméticas e lógicas, o operando pode ser um dos registos gerais de 32-bits (EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP), um dos registos gerais de 16-bits (AX, BX, CX, DX, SI, DI, SP, BP) ou um dos registos gerais de 8-bits (AH, BH, CH, DH, AL, BL, CL, DL). Para operações em vírgula flutuante, os operandos de 64-bits são formados usando dois registos de 32-bits como um par.

Tabela 10.2: Modos de endereçamento no Pentium.
\begin{table}
\end{table}


Há, também, algumas instruções que referenciam os registos de segmentos (CS, DS, ES, SS; FS, GS).

Os modos de endereçamento restantes referenciam posições da memória. A posição de memória tem de ser especificada em termos de segmentos contendo a posição e o desvio do início do segmento. Em alguns casos, o segmento é especificado explicitamente; em outros casos, o segmento é especificado através de regras simples que atribuem um segmento por omissão.

No modo deslocamento, o desvio do operando (o endereço efectivo da figura 10.2) faz parte da instrução como um deslocamento de 8, 16, ou 32-bits. Com segmentação, todos os endereços na instrução referem-se meramente a um balancear dentro do segmento. O modo de endereçamento por deslocamento encontra-se em poucas máquinas, porque, como foi mencionado antes, dá lugar a instruções longas. No caso do Pentium, o valor de deslocamento pode ser tão extenso como 32 bits, dando lugar a instruções de 6-octetos. O endereçamento por deslocamento pode ser útil para referenciar variáveis globais.

Os restantes modos de endereçamento são indirectos, no sentido que a porção de endereço da instrução diz ao processador onde procurar o endereço. O modo base especifica que o registo de 8-, 16, ou 32-bits contém o endereço efectivo. Isto é equivalente ao que foi referenciado como endereçamento indirecto por registo.

No modo base com deslocamento, a instrução inclui o deslocamento a ser adicionado ao registo base, que pode ser qualquer um dos registos de uso-geral. Exemplos do uso deste modo:

  1. Usado pelo compilador para apontar para o início de uma área local de variavéis . Por exemplo, o registo base podia apontar para o princípio do caixilho da pilha, que contém as variáveis locais para o procedimento correspondente.
  2. Usado para indexar um vector quando o tamanho do elemento não é 2, 4 ou 8 octetos e por isso não pode ser indexado usando um registo de índice. Neste caso, o deslocamento aponta para aponta para o princípio da pilha e o registo base contém o resultado de um cálculo para determinar o desvio até um elemento específico dentro do vector.
  3. Usado para acesso a um campo do registo. O registo base aponta para o princípio do registo, enquanto o deslocamento é um desvio do campo.
No modo índice com escala e deslocamento a instrução inclui um deslocamento a ser adicionado a um registo, neste caso um registo índice. O registo índice pode ser qualquer registo de uso-geral excepto o designado por ESP, que é habitualmente usado para processamento da pilha. No cálculo do endereçamento efectivo, o conteúdo do registo de índice é multiplicado por um factor de escala de 1, 2, 4, ou de 8, e depois adicionado deslocamento. Este modo é muito conveniente para indexar vectores. Um factor de escala de 2 pode ser usado para um vector de inteiros de 16-bits. Um factor de escala de 8 pode ser usado para um vector de inteiros de 32-bits ou números em vírgula flutuante. Finalmente, um factor de escala de 8 pode ser usado para um vector números em vírgula flutuante de dupla precisão.

O modo base com índice e deslocamento soma o conteúdo do registo base, do registo índice e um deslocamento para formar o endereço efectivo. De novo, o registo base pode ser qualquer registo de uso-geral o registo índice pode ser qualquer registo de uso-geral excepto ESP. Como um exemplo, este modo de endereçamento pode ser usado para o acesso a um vector local no caixilho da pilha. Este modo pode também ser usado para suportar um vector a duas dimensões; neste caso, o deslocamento aponta para o princípio do vector e cada registo trata de uma dimensão do vector.

O modo base e índice com escala e deslocamento soma o conteúdo do registo índice multiplicado por um factor de escala, o conteúdo do registo base e o deslocamento. Isto é útil se um vector é guardado num caixilho da pilha; neste caso, os elementos do vector seriam de 2, 4 ou 8 octetos cada em comprimento. Este modo também fornece uma indexação eficiente de vectores de duas-dimensões quando os elementos do vector são de 2, 4 ou 8 octetos em comprimento.

Finalmente, endereçamento relativo pode ser usado em instruções de transferência de controlo. Um deslocamento é adicionado ao valor do contador de programa, que aponta para a próxima instrução. Neste caso o deslocamento é tratado como um valor com sinal, octeto, palavra, ou dupla palavra e aquele valor aumenta ou diminui o endereço no apontador de programa.

Modos de endereçamento no PowerPc

Em conjunção com a maioria das máquinas RISC e ao contrário do Pentium e da maioria das máquinas CISC, o PowerPc usa um simples e relativamente directo . Tal como indica a tabela 10.3, estes modos são convenientemente classificados com respeito ao tipo de instrução.

Tabela 10.3: Modos de endereçamento no PowerPc.
\begin{table}
\end{table}


Endereçamento Guarda/Carrega

O PowerPc fornece dois modos de endereçamento alternativos para instruções de carregar/guardar (Figura 10.3). Com endereçamento indirecto, a instrução inclui um deslocamento de 16-bits para ser adicionado a um registo base, que pode ser qualquer um dos registos de uso-geral. Adicionalmente, a instrução pode especificar que o novo endereço efectivo calculado é para ser reinjectado no registo base, actualizando o conteúdo corrente. A opção de actualização é útil para indexação progressiva de vectores em laços.

A outra técnica de instruções com endereçamento carrega/guarda é o endereçamento indirecto indexado. Neste caso, a instrução referencia um registo base e um registo índice, ambos os quais podem ser quaisquer registos de uso-geral. O endereçamento efectivo é a soma do conteúdo destes dois registos. De novo, a opção de actualização tem como efeito a actualização do registo base com o novo endereço efectivo.

Figura 10.3: Modos de endereçamento dos operandos em memória no PowerPc
\begin{figure}
\end{figure}

Endereçamento de Derivação

São fornecidos três modos de endereçamento de derivação. Quando é usado endereçamento absoluto com instruções de derivação não-condicionais, o endereço efectivo da próxima instrução é derivada de um valor imediato de 24-bits dentro da instrução. O valor de 24-bits é estendido para um valor de 32-bits adicionando dois zeros à extremidade menos significativa (isto é admissível uma vez que todas as instruções devem ocorrer em limites de 32-bits) feita a estensão do sinal. Para instruções de derivação condicionais, o endereço efectivo da próxima instrução é derivada de um valor imediato de 16-bits na própria instrução. O valor de 16-bits é estendido para um valor de 32-bits adicionando dois zeros à extremidade menos significativa e fazendo a estensão do sinal.

Com o endereçamento relativo o valor imediato de 24-bits (instrução de derivação não-condicional) ou valor imediato de 14-bits (instrução de derivação condicional) é estendido como antes. O valor resultante é então somado ao contador de programa para definir a posição relativa à instrução corrente. O outro modo de endereçamento de derivação condicional é endereçamento indirecto. Este modo obtém o endereçamento efectivo da próxima instrução, quer do registo ligação, quer do registo contador. É de notar que neste caso o registo contador é usado para conter o endereço de uma instrução de derivação. Este registo pode também ser usado para guardar a contagem para as voltas do laços, tal como foi explicado atrás.

Instruções Aritméticas

Para instruções aritméticas, todos os operandos tem de estar contidos quer em registos quer como parte da instrução. Com o endereçamento de registo um operando de origem ou de destino é especificado como um dos registos de uso-geral. Com o endereçamento indirecto, um operando na origem aparece como uma quantidade de 16-bits com sinal na instrução.

Para a aritmética em vírgula flutuante, todos os operandos são registos de vírgula flutuante; isto é, usado apenas o endereçamento de registo.

Formatos de Instrução

Um formato de instrução define o esquema dos bits de uma instrução, em termos das suas partes constituintes. Um formato de instrução tem de incluir um código de operação e, implícita ou explicitamente, zero, ou mais operandos. Cada operando explícito é referenciado usando um dos modos de endereçamento descritos na secção 10.1. O formato tem de, implícita ou explicitamente, indicar o modo de endereçamento para cada operando. Para a maioria dos jogos de instruções, é usado mais do que um formato de instrução.

O desenho do formato de uma instrução é uma arte complexa, e uma incrível variedade de desenhos foram implementados. Nesta secção, examinamos os tópicos chave do projecto, olhando brevemente para alguns projectos para ilustrar alguns aspectos e, seguidamente, examinamos em detalhe as soluções Pentium e PowerPC.

Comprimento da instrução

O tópico de desenho mais básico para ser revelado é o comprimento do formato de instrução. Esta decisão afecta, e é afectada pelo tamanho da memória, a organização da memória, a estrutura do barramento, a complexidade do processador e a velocidade do processador. Esta decisão determina a riqueza e flexibilidade da máquina tal como é vista pelo programador da linguagem de montagem.

Aqui o compromisso mais óbvio é entre o desejo de um repertório de instruções poderosas e a necessidade de poupar espaço. Os programadores querem mais código de operação, mais operandos, mais modos de endereçamento e uma gama maior de endereços. Mais códigos de operação e mais operandos facilitam a vida aos programadores, uma vez que podem escrever-se programas mais curtos para cumprir as tarefas atribuídas. Similarmente, mais modos de endereçamento dão ao programador uma maior facilidade na implementação de certas funções, tais como, para a manipulação de tabelas e para múltiplas vias de derivação. E, claro, com o crescimento do tamanho da memória principal e o uso crescente da memória virtual, os programadores querem ser capazes de endereçar maiores gamas de endereços. Todas estas coisas, (códigos de operação, operandos, modos de endereçamento e gama de endereços) requerem bits e empurram na direcção de instruções mais longas em comprimento. Mas instruções com tamanhos maiores podem ser um desperdício. Uma instrução de 32-bits ocupa duas vezes o espaço de uma instrução de 16-bits mas tem, provavelmente, uma utilidade inferior a duas vezes.

Para além deste compromisso básico, há outras considerações. Ou o comprimento da instrução deveria ser igual ao tamanho do canal para a memória (num sistema de barramento , barramento de dados) ou um deveria ser múltiplo do outro. Doutra forma, não obteremos um valor inteiro de instruções durante um ciclo de extracção. Uma consideração relacionada é a taxa de transferência. Esta taxa não tem vindo a acompanhar o crescimento da velocidade do processador. Em concordância, a memória pode tornar-se um gargalo se o processador poder executar instruções mais depressa do que pode extraí-las. Uma solução para este problema é o uso de memória cache (ver secção 4.3); uma outra é usar instruções mais curtas. De novo, as instruções de 16-bits podem ser extraída a duas vezes a taxa das instruções de 32-bits mas, provavelmente, podem ser executadas menos do que duas vezes mais depressa.

Uma talvez mundana mas de qualquer forma importante característica é que o tamanho da instrução deveria ser um múltiplo do tamanho do carácter, que é comummente 8-bits e do tamanho dos números de ponto fixo. Para ver isto, necessitamos de recorrer à infelizmente mal-denominada palavra "palavracite. O tamanho da palavra em memória e, de alguma forma, a unidade ``natural" de organização. O tamanho de uma palavra determina habitualmente o tamanho dos números em ponto fixo (habitualmente os dois são iguais). O tamanho da palavra é tipicamente, também, tipicamente, igual a, ou pelo menos integralmente relacionado com o tamanho do canal de memória. Uma vez que um formato comum de dados é o carácter, gostaríamos de poder guardar uma palavra num número inteiro de caracteres. Doutra forma, há bits desperdiçados em cada palavra quando guardamos múltiplos caracteres, ou um carácter terá de vagar entre os limites da palavra. A importância deste ponto é tal que a IBM, quando introduziu o Sistema/360 e quis empregar caracteres de 8-bits, tomou uma abrupta decisão de passar de uma arquitectura de 36-bits para os membros científicos da série 700/7000 para uma arquitectura de 32-bits.

Alocação de Bits

Demos uma espreitada a alguns dos factores que condicionam o tamanho do formato da instrução. Um tópico igualmente difícil é, como alocar os bits naquele formato. Os compromissos são complexos.

Para um determinado comprimento de instrução, há claramente um compromisso entre os número de códigos de operação e a potência das capacidades de endereçamento. Mais códigos de operação significam, obviamente, mais bits no campo do código. Para um formato de instruções de um determinado comprimento isto reduz o número de bits disponíveis para endereçamento. Há um interessante refinamento deste compromisso que é o uso de códigos de tamanho variável. Nesta abordagem, há um tamanho de código mínimo mas, para alguns códigos, operações adicionais podem ser especificadas para usar bits adicionais na instrução. Para uma instrução de tamanho fixo, isto deixa menos bits para endereçamento, Assim esta característica é usada para aquelas instruções que necessitam de menos operandos e/ou menor poder de endereçamento. Veremos exemplos, actuais, desta estratégia.

Os seguintes factores inter-relacionados condicionam o uso de bits de endereçamento:

Posto isto, o projectista é confrontado com inúmeros factores a considerar e a equilibrar. Não está claro quão críticas são as várias escolhas. Como um exemplo, citamos um estudo que compara várias abordagens a formatos de instrução, incluindo o uso da pilha, registos de uso geral, acumulador, e memória para registo. Quando se usa um conjunto consistente de pressupostos, não é observada uma diferença significativa, em espaço para o código ou em tempo de execução.

Damos agora uma espreitadela a como dois projectos de máquinas equilibram estes vários factores.

Figura 10.4: Formatos de Instrução do PDP-8.
\begin{figure}
\end{figure}

Figura 10.5: Formatos de Instrução do PDP-10.
\begin{figure}
\end{figure}

Formatos de Instrução do Pentium

O Pentium está equipado com uma variedade de formatos de instruções. Dos elementos descritos, abaixo, apenas o campo do código está sempre presente. A figura 10.7 ilustra o formato geral de instrução. As instruções podem ter desde zero a quatro prefixos opcionais de instrução, um ou dois octetos para o código de operação, um campo opcional para especificar o endereço que consiste do octeto Mod r/m e do octeto de Escala do Índice, um deslocamento opcional e um campo imediato opcional.

Consideremos os octetos de prefixo.

Figura 10.6: Formatos de Instrução usados pelo PDP-10; os números indicam o comprimento dos campos.
\begin{figure}
\end{figure}

A instrução, ela própria, inclui os seguintes campos:

Figura 10.7: Formatos de Instrução do Pentium.
\begin{figure}
\end{figure}

Diversas comparações podem ser úteis aqui. No formato Pentium, o modo de endereçamento é fornecido como uma parte da sequência do código de operação em vez de com cada operando. Uma vez que apenas um operando pode ter informação de modo de operação, apenas um operando em memória pode ser referenciado na instrução. Em contraste o VAX transporta o modo de endereçamento em cada operando, permitindo operações de memória para memória. As instruções do Pentium são assim mais compactas. Contudo, se for requerida uma operação de memória para memória o VAX pode realizá-la numa simples instrução.

O formato Pentium permite o uso de não apenas 1-octeto, mas de 2-octetos e 4-octetos de deslocamento para indexação. Embora o uso de maiores deslocamento para indexação resultem em instruções mais longas, esta característica fornece a necessária flexibilidade. Por exemplo, é útil no endereçamento de grandes vectores ou grandes de caixilhos de pilha. Em contraste, o formato de instrução do IBM s/370 não permite deslocamentos superiores a 4K octetos (12 bits de informação de deslocamento) e o deslocamento tem de ser positivo. Quando uma localização não alcançável com este deslocamento, o compilador tem de gerar código extra para gerar o endereço necessário. Este problema é especialmente aparente quando se trata com caixilhos de pilha que possuem variáveis locais com ocupações superiores a 4K octetos. Tal como afirma ``gerar código para o 370 é tão penoso como resultado daquela restrição que têm havido compiladores para o 370 que limitam, simplesmente, o tamanho da pilha a 4K octetos.''

Tal como pode ser ver visto, a codificação do jogo de instruções do Pentium é muito complexa. Isto tem a ver, parcialmente, com a necessidade de manter a compatibilidade com a máquina 8086 e parcialmente com o desejo de parte dos projectistas de fornecer toda a possível assistência ao programador de compiladores para produzir código eficiente. É assunto para algum debate sobre um jogo de instruções tão complexo como este é preferível à posição extrema do jogo de instruções RISC.

Formatos de Instrução do PowerPc.

Todas as instruções do PowerPc têm 32bits de extensão e seguem um formato regular. Os primeiros 6 bits da instrução especificam a operação a efectuar. Em alguns casos, há uma extensão ao código de operação algures na instrução que especifica um sub-caso particular de uma operação. Na figura 10.8 os bits de código são representados pela porção sombreada de cada formato.

Notar a estrutura regular dos formatos, os quais facilitam o trabalho das unidades de execução. Para todos as operações de carregar/guardar, aritméticas e lógicas o código de operação é seguido de 2 referências de 5-bits a registos, habilitando o uso de 32 registos de uso-geral.

As instruções de derivação incluem um bit (L) de ligação que indica que o endereço efectivo da instrução contígua a instrução de derivação deverá ser colocada no registo de ligação. Duas formas da instrução também incluem um bit (A) que indica se o modo de endereçamento é absoluto ou relativo ao valor do PC. Para as instruções de derivação condicional o campo de bit CR a ser testado especifica o bit a ser testado no registo de condição. O campo de opções especificam as condições debaixo das quais a derivação pode ser tomada.

As seguintes condições podem ser especificadas:

Muitas instruções que produzem resultados (aritméticas, vírgula flutuante, lógicas) incluem um bit que indica se o resultado de uma operação deverá ser registado no registo de condição. Tal como será mostrado, esta característica é útil para o processo de predição de derivação.

As instruções de vírgula flutuante têm campos para três registos de entrada. Em muitos casos, apenas dois registos são usados. Umas poucas instruções envolvem a multiplicação de dois registos e depois a adição ou subtracção de um terceiro registo de entrada. Estas operações compostas foram incluídas porque causa da frequência do seu uso. Por exemplo, o produto interno que é parte de muitas operações sobre matrizes pode ser implementado usando múltiplas adições.

Figura 10.8: Formatos de Instrução do PowerPc.
\begin{figure}
\end{figure}


next up previous contents
Next: Processador Estrutura e Função Up: Arquitectura e Organização Interna Previous: Jogos de instruções: Características

2000-05-10