( 0,5 pontos) Por que o MIPS não tem uma instrução que subtraia imediato?

Passo 1

O enunciado pergunta por que o conjunto de instruções MIPS não inclui uma instrução específica para “subtrair imediato” (ou seja, uma instrução do tipo subi que faria \text{registro} \leftarrow \text{registro} - \text{imediato}).
Informações relevantes que temos (implícitas na pergunta e úteis para resolver):
  • MIPS já tem instruções para soma imediata ( \text{addi} e \text{addiu}) e para subtração entre registradores ( \text{sub} e \text{subu}).
  • O campo imediato nas instruções do tipo I em MIPS tem 16 bits e é interpretado com sinal (sign-extended) quando usado por \text{addi}.
  • Em arquiteturas que usam complemento de dois, subtração pode ser realizada como adição do negativo.

Passo 2

Conceito chave: subtração como adição do complemento de dois.
Expliquei isso porque é o fundamento que justifica a ausência de uma instrução “subi”. A identidade aritmética é:
a - b = a + (-b).
Em sistemas que usam representação em complemento de dois, representar -b é natural — basta inverter os bits de b e somar 1, ou, visto do ponto de vista da ALU, tratar -b como um valor inteiro comum e usar a mesma unidade de soma. Portanto, do ponto de vista lógico e físico, subtrair é a mesma operação da adição, apenas com o segundo operando negado.

Passo 3

Como isso se aplica ao MIPS na prática: usar \text{addi} com imediato negativo.
  • A instrução \text{addi}\; \$t, \$s, \text{imm} faz \$t \leftarrow \$s + \text{imm}, onde \text{imm} é um imediato de 16 bits com sinal (é sign-extended para 32 bits antes da soma).
  • Se você quer fazer \$t \leftarrow \$s - 7, basta escrever:
    addi $t, $s, -7
    (ou seja, usar -7 como imediato).
    Isto realiza exatamente a subtração imediata, porque \$s + (-7) = \$s - 7. Portanto, a funcionalidade que uma hipotética instrução \text{subi} daria já está disponível com \text{addi}.

Passo 4

Por que não colocar uma instrução separada então? — motivação de projeto do ISA (RISC) e economia de recursos:
  • Economia de espaço de codificação: campos de opcode são limitados (por exemplo, 6 bits em MIPS clássico). Incluir instruções redundantes desperdiça esse espaço que pode ser usado para instruções realmente novas.
  • Simplicidade e regularidade: arquiteturas RISC (como MIPS) preferem poucas instruções “orthogonais” e simples. Ter várias instruções que fazem a mesma coisa com pequena variação aumenta complexidade do decodificador e do manual, sem ganho real de funcionalidade.
  • Implementação física: a ALU já realiza adição; para subtração a mesma ALU pode receber o operando negado. Não há ganho hardware significativo em ter um novo opcode que só difere pelo sinal do imediato.
  • Manutenção do conjunto mínimo e previsível de instruções facilita otimizações, pipeline e verificação formal.

Passo 5

Comportamento de overflow e instruções relacionadas ( \text{addi} vs \text{addiu}):
  • \text{addi} detecta overflow aritmético e gera exceção em caso de estouro em aritmética com sinal. Se você usá-la com imediato negativo para fazer subtração, o tratamento de overflow é o mesmo que a hipotética \text{subi} teria.
  • \text{addiu} não gera exceção de overflow (a operação é realizada modulo 2^{32}). Se você quer evitar exceção, pode usar \text{addiu} com imediato negativo.
    Isso mostra que, além de redundância funcional, já existem variantes que cobrem comportamento com/sem exceção.

Passo 6

Assembler e pseudo-instruções: como usuários acabam tendo uma instrução “subi” sem que o hardware a suporte.
  • Muitos montadores aceitam pseudo-instruções como \text{subi}\; \$t,\$s,\text{imm} e simplesmente as traduzem para \text{addi}\; \$t,\$s,-\text{imm} (ou para uma sequência de instruções se o imediato não couber em 16 bits).
  • Se o imediato não cabe em 16 bits (por exemplo, você quer subtrair 100000), o montador gera uma sequência: carrega o imediato em um registrador com \text{lui} / \text{ori} ou usa \text{li} (pseudo-instrução) e então usa \text{sub} entre registradores. Assim, a sintaxe amigável não exige instrução nova no hardware.

Passo 7

Um exemplo numérico simples para fixar:
Queremos \$a \leftarrow \$b - 3. Em MIPS escrevemos:
addi $a, $b, -3
No nível aritmético, isso executa
\$a = \$b + (-3) = \$b - 3,
usando o imediato de 16 bits com sign-extension. Se fosse \$b - 70000 (imediato maior que 16 bits), o montador gera código para carregar 70000 num registrador e faz uma subtração registrador-registrador.

Passo 8

Resumo didático e motivacional (curto e direto): a instrução de subtrair imediato seria redundante porque a adição com imediato negativo faz o mesmo trabalho; por razões de economia de codificação, simplicidade do ISA e da implementação, o MIPS prefere não duplicar instruções e deixa o montador fornecer uma pseudo-instrução se for conveniente. Você já sabe fazer isso na prova: basta lembrar que subtração = adição do negativo e que o imediato em MIPS é sign-extended de 16 bits.

Resposta

Porque é desnecessária: a subtração com imediato é realizada usando \text{addi} com imediato negativo (ou \text{addiu} quando não se quer exceção de overflow), poupando espaço de opcode e mantendo o ISA simples; montadores fornecem uma pseudo-instrução \text{subi} que é expandida para essa sequência quando conveniente.

Exercícios relacionados