AULA 7 - Microprocessadores - Graduação
Estrutura e Funcionamento da CPU
Neste capítulo estudaremos características da maioria das CPUs.
Pilhas
Uma pilha , ou stack é uma estrutura de dados ordenada do tipo LIFO (last-in-first-out), na qual apenas um dos elementos pode ser acessado, em um dado instante - o elemento do topo da pilha.
O tamanho da pilha, ou o número de elementos empilhados, é variável. Normalmente, existe um tamanho máximo de "níveis" da pilha, mas estes podem ser continuamente acrescentados ou removidos.
Quase todas as pilhas são controladas por 3 apontadores/ponteiros (variáveis que armazenam endereços de memória):
- o apontador que endereça o topo da pilha, normalmente chamado de TOP - este valor é incrementado ou decrementado, conforme a pilha aumenta ou diminui (até o limite máximo de LENGHT, e o limite mínimo de BOTTOM);
- o apontador que endereça o limite máximo de tamanho da pilha, muitas vezes chamado de LENGHT, e
- o apontador que endereça a base da pilha, também chamado de BOTTOM.
Normalmente, a instrução que empilha, isto é, coloca um novo dado no topo da pilha é a instrução PUSH. Da mesma forma, a instrução que desempilha, ou seja, remove o item do topo da pilha, normalmente, chama-se POP.
Na grande maioria dos casos, as pilhas são usadas nas CPUs para gerenciar a chamada e retorno de procedimento. Ou seja, é comum que se armazene endereço de retorno nas pilhas, ou status de registradores, etc.
Alguns processadores possuem pilhas para uso interno. Porém estas não estão disponíveis para os programadores.
Quando estiverem, instruções específicas para processamento nas pilhas, além de PUSH e POP, são desejáveis.
Por exemplo:
Note que a última instrução, MUPST, de MUltiPlica STack atuará sobre os dois últimos valores do topo da pilha.
Na imensa maioria dos casos, as operações lógico-aritméticas nas pilhas seguem esta notação pós-fixa, também chamada de notação polonesa reversa. Nesta notação, o operador vem depois dos operandos.
Exemplo:
a + b ⇒ a b + a + (b x c) ⇒ a b c x + (a + b )x c ⇒ a b + c x
A figura abaixo ilustra todos os passos, e comportamento da pilha, se esta estivesse executando a sequência de instruções de pilha abaixo, para efetuar a operação f = (a - b)/(c + d x e):
(I) PUSH A (II) PUSH B (III) SUB (IV) PUSH C (V) PUSH D (VI) PUSH E (VII) MUL (VIII) ADD (IX) DIV (X) POP F
Representações Little-Endian, Big-Endian e Bi-Endian
A partir do momento em que os valores utilizados nas CPUs começaram a ultrapassar o limite de um byte (8 bits), surgiu a dúvida: "como dispor estes bytes componentes de cada palavra na memória?"
Byte menos significativos em endereços mais baixos da memória, ou vice-versa.
Por exemplo:
Seja o valor hexadecimal 12345678h, armazenado em 32 bits, a partir da posição de memória 184, em memória endereçável a cada byte.
No mapeamento mostrado à esquerda, em (a), o byte mais significativo é armazenado no menor endereço de byte. Isto é conhecido como representação big-endian e é equivalente à ordem de escrita ocidental.
No mapeamento mostrado à direita, em (b), o byte menos significativo é armazenado no menor endereço de byte. Isto é conhecido como representação little-endian, e é remanescente da ordem de avaliação das operações aritméticas, da direita para a esquerda.
Modos de Endereçamento
Nas aulas anteriores, focamos o que faz um conjunto de instruções. Em particular, examinamos os tipos de operação e de operandos que podem ser especificados em instruções de máquinas.
Esta aula aborda a questão de como especificar operações e operandos nas instruções:
- como o endereço de um operando é especificado e,
- como são organizados os bits de uma instrução, para definir a operação e os endereços de operandos, em uma instrução.
Em um formato de instrução típico, os campos de endereço são relativamente pequenos. Para viabilizar a referência a uma enorme quantidade de posições de memória principal, ou virtual, várias técnicas de endereçamento têm sido empregadas.
As mais comuns são:
- Endereçamento imediato;
- Endereçamento direto;
- Endereçamento indireto;
- Endereçamento de registrador;
- Endereçamento indireto via registrador;
- Endereçamento por deslocamento;
- Endereçamento a pilha
| MODO | Algoritmo | Principal Vantagem | Principal Desvantagem |
|---|---|---|---|
| Imediato | Operando = A | Nenhuma referência à memória | Limitada magnitude do operando |
| Direto | EA = A | Simples | Espaço de endereçamento limitado |
| Indireto | EA = (A) | Espaço de endereçamento grande | Múltiplas referências à memória |
| Registrador | EA = R | Nenhuma referência à memória | Espaço de endereçamento limitado |
| Indireto via Registrador | EA = (R) | Espaço de endereçamento grande | Referência extra à memória |
| Deslocamento | EA = A + (R) | Flexibilidade | Complexibilidade |
| Pilha | EA = *Top | Nenhuma referência à memória | Aplicabilidade limitada |
Onde:
A = conteúdo de campo de endereço da instrução
R = conteúdo de campo de endereço que referencia um registrador
EA = endereço real (efetivo) da posição que contém o operando
(X) = conteúdo da posição de endereço X
Endereçamento imediato
A forma mais simples é o endereçamento imediato, no qual o valor do operando é especificado diretamente na instrução
OPERANDO = A
Esse modo pode ser usado para definir e usar constantes ou para atribuir valores iniciais em variáveis.
O valor é armazenado em complemento-dois, e o bit de sinal é propagado.
A grande desvantagem é que o tamanho do operando é limitado pelo tamanho do campo de endereço, o qual, na maioria dos conjuntos de instrução, é bem menor que o tamanho de uma palavra.
Exemplo no ARM:
MOV R1, #3
Endereçamento direto
Outra forma simples de endereçamento, na qual o campo de endereço contém o endereço efetivo do operando
EA = A
Também fornece um espaço de endereçamento limitado.
Exemplo no ARM:
LDR R3,=MY_NUMBER ... MY_NUMBER DCD 0x12345678
Endereçamento indireto
No endereçamento indireto, especifica-se o endereço de uma palavra de memória, que, por sua vez, contém o endereço do operando:
EA = (A)
Exemplo:
Este modo não existe no ARM, mas seria algo do tipo
MOV R1, [0x2000]
Endereçamento de registrador
Semelhante ao endereçamento direto, exceto que o campo de endereço se refere a um registrador, não a um endereço de memória.
EA = R
Tipicamente, um campo de endereço que referencia um registrador tem 3 a 4 bits, possibilitando referenciar um total de 8 a 16 registradores de propósito geral.
As vantagens deste modo de endereçamento são:
- O tamanho do campo de endereço requerido na instrução é pequeno;
- Não requer nenhuma referência à memória (tempo menor de acesso).
Exemplo no ARM:
MOV R1, R2
Endereçamento indireto via registrador
Neste modo de endereçamento, o campo de endereço contém um registrador, o qual, por sua vez, contém o endereço do operando.
É um dos mais vantajosos, porque permite que o endereço (de tamanho longo) seja utilizado na própria instrução. Como utiliza um registrador, requer um acesso à memória a menos, tornando o acesso ao operando ainda mais rápido.
Este modo não existe no ARM, mas seria algo do tipo
Exemplo no ARM:
STR R1,[R0]
Endereçamento por deslocamento
É um modo de endereçamento bastante poderoso. Combina as capacidades dos endereçamentos direto e indireto via registrador.
É conhecido por uma variedade de nomes, dependendo do contexto de uso, embora o mecanismo básico seja o mesmo.
EA = A + (R)
O endereçamento por deslocamento requer que a instrução tenha dois campos de endereço, pelo menos um dos quais é explícito.
O outro campo de endereço, ou uma referência implícita baseada no código de operação, especifica um registrador cujo conteúdo é adicionado a A, para produzir o endereço efetivo.
Os três usos mais comuns do endereçamento por deslocamento são:
- Endereçamento relativo
- Endereçamento via registrador-base
- Indexação
Endereçamento Relativo
No modo de endereçamento relativo, o registrador referenciado implicitamente é o contador de programa. Isto é, o endereço da instrução corrente é adicionado ao campo de endereço para produzir o endereço efetivo EA.
Nessa operação, o campo de endereço é tipicamente tratado como um número em complemento dois. Portanto, o endereço efetivo é um deslocamento relativo ao endereço da instrução.
Endereçamento via registrador-base
Neste modo de endereçamento, o registrador referenciado contém um endereço de memória, e o campo de endereço contém um deslocamento em relação a este endereço.
A referência ao registrador pode ser explícita ou implícita.
Exemplo no ARM:
LDR.W R0,[R1, #offset]! ; Read memory[R1+offset], with R1 ; update to R1+offset
LDR.W R0,[R1], #offset ; Read memory[R1], with R1 ; updated to R1+offset
Endereçamento por indexação
No modo indexado, o campo de endereço contém um endereço de memória principal e o registrador especificado conterá um deslocamento positivo, relativo a este endereço.
Endereçamento por deslocamento no ARM
Existem nove formatos utilizados para calcular o endereço para uma instrução LOAD ou STORE, para palavra ou byte sem sinal.
A sintaxe geral é:
LDR|STR{<cond>}{B}{T} <Rd>, <addressing_mode>
onde <addressing_mode> é uma das nove opções listadas abaixo:
1. Offset imediato
[<Rn>, #+/-<offset_12>]
2. Offset por registrador
[<Rn>, +/-<Rm>]
3. Offset escalonado por registrador
[<Rn>, +/-<Rm>, <shift> #<shift_imm>]
4. Pré-indexado imediato
[<Rn>, #+/-<offset_12>]!
5. Registrador pré-indexado
[<Rn>, +/-<Rm>]!
6. Pré-indexado por registrador escalonado
[<Rn>, +/-<Rm>, <shift> #<shift_imm>]!
7. Pós-indexado imediato
[<Rn>], #+/-<offset_12>
8. Registrador pós-indexado
[<Rn>], +/-<Rm>
9. Pós-indexado por registrador escalonado
[<Rn>], +/-<Rm>, <shift> #<shift_imm>
Endereçamento a pilha
É uma forma de endereçamento implícito.
As instruções de máquina não precisam incluir uma referência à memória, operando implicitamente sobre o topo da pilha.
Máquinas CISC x RISC
Paradigma CISC - Complex Instruction Set Computer
- Conjunto de instruções inicialmente simples
- Avanços tecnológicos permitiram a fabricação de computadores com mais transistores e menor custo
- Projetistas optaram por conjuntos de instruções cada vez mais complexos
⇒ Intenção: reduzir a distância semântica entre Assembly e linguagens de alto nível
- Instruções com elevado grau semântico
- Elevado número de modos de endereçamento (ex: endereçamento indireto em memória)
- Elevado número de ciclos de clock por instrução → redução da frequência de clock
- Menor número de instruções por programa → menor uso de memória de código
- Decodificação através de microcódigo → dificulta/impossibilita o uso de pipeline
Paradigma RISC - Reduced Instruction Set Computer
- Instruções simples que executam rápido
- Elevado número de registradores de uso geral
- Decodificação de instruções com lógica combinacional (tabela)
- Execução utilizando pipeline → um ciclo de clock por instrução
- Regularidade de tempo de execução
- Regularidade de tamanho de instrução
- Redução da área de silício e tempo de projeto
- Efeito final: melhor desempenho, apesar do número de instruções por programa ser maior
Processadores ARM
São processadores de 32 bits (alguns 64 bits) de arquitetura RISC.
Algumas famílias ARM: Existem hoje aproximadamente 18 famílias, dentre elas as mais utilizadas são: ARM7, ARM7TDMI, ARM9TDMI, ARM11, Cortex-M, Cortex-A, Cortex-R.
Cada família tem uma especialização.
Exemplo:
O Cortex-A tem foco na área de processadores para computadores e Smartfones poderosos.
O ARM7 abrange uma grande faixa, desde alguns microcontroladores até processadores de videogames portáteis.
A família Cortex-M (em especial os Cortex-M0+) são arquiteturas focadas para microcontroladores.
Arquiteturas de Von Neumann x Harvard
Família Cortex-M: São Von Neumann (Não existe separação entre barramentos de dados e o barramento da memória de programa):
Cortex-M0 -->Microcontroladores mais simples, suportam somente o set de instruções Thumb com algumas instruções do Thumb2 (sempre executam no modo Thumb); Cortex-M0+ -->Apresentam algumas melhorias em relação ao M0, além de ter suporte opcional à proteção de memória (MPU); Cortex-M1 -->São utilizados juntos com FPGAs;
São Harvard (Possuem barramentos separados para dados e instruções):
Cortex-M3 -->São microcontroladores mais poderosos, suportam completamente os sets Thumb e Thumb2, além de multiplicação têm divisão por hardware; Coxtex-M4 -->Têm instruções para processamento de sinais (DSP), têm uma unidade de ponto flutuante opcional (Cortex-M4F).
Pipelines
Pipeline (3 Estágios) 1. Busca (Fetch) – Busca da instrução na memória 2. Decodificação (Decode) – Decodificação dos registradores usados na instrução 3. Execução (Execute) – Leitura de registradores – Operações lógicas, aritméticas e de deslocamento; – Escrita em registradores
Pipeline: Situação Ideal
• Todas as operações realizadas em registradores → 6 instruções em 6 ciclos de clock (ARM Cortex-M3)
Pior caso: salto indireto (instrução BX), 3 ciclos de clock para completar o salto (ARM Cortex-M3)
Arquitetura = documento de especificação – Instruções – Exceções – Registradores – Memória • Ex: ARMv4, ARMv7, etc. • Não tem custo, pode ser obtido diretamente do website da ARM
Organização = implementação física (silício) – Ex: ARM7TDMI, ARM Cortex-M3, etc. • ARM vende a implementação de núcleos em VHDL ou máscara de difusão para empresas licenciadas
18 registradores de 32 bits • Tratamento muito eficiente de interrupções • Gerenciamento de consumo de energia • Projetado para ser programado em C (completamente, até mesmo tratamento de reset, interrupções e exceções) • Permite uso de sistemas operacionais (RTOS) – Modelo Usuário/Supervisor
Arquitetura ARMv7M • Sem memória cache ou Unidade de Gerenciamento de Memória (MMU) • Tabela de vetores contém endereços, não instruções • Instrução DIV • Interrupções salvam e recuperam automaticamente o estado do processador
Controlador de Interrupções é parte da macrocélula Cortex-M3 • Mapa de memória fixo • Registrador único de estado do processador • Núcleo de processamento Thumb-2 – Mistura de instruções de 16 e 32 bits (alta densidade de código), mas não requer alinhamento para instruções de 32 bits
| << Página da disciplina | < Conjunto de Instruções | Aula 7 - Estrutura e Funcionamento da CPU | Arquitetura ARM > |
|---|













