Pergunta

Atualmente estou desenvolvendo um emulador para o bom e velho GameBoy e estou enfrentando alguns problemas para entender como alguns códigos básicos de operação devem ser implementados.

No momento estou implementando as operações AND;os primeiros (0xA0 -> 0xA3;0xA6 e 0xA7) são bastante simples, mas as operações AND para os registradores H, L são um pouco diferentes.

Você pode baixar a documentação do z80 neste link:um0080.pdf (página 172)

Aqui estão alguns exemplos para mostrar o que quero dizer (com pseudocódigo) e basicamente o que faço:

AND A,H (observe a mudança de bits)

(read HL register; >> 8) save in cache C
R->C = R->HL >> 8;

perform AND operation with cache
AND_H(R->C);
R->A &= R->C;

AND A,L (observe o mascaramento de bits)

(read HL register; &0xFF) save in cache C
R->C = R->HL &0xFF;

Conheço todas as operações de bits e sei o que elas fazem, mas parece que não consigo entender por que precisa ser feito assim.Tenho algumas teorias (corrija-me se estiver errado :-)):

O que já entendi é que os registradores H e L são basicamente o registrador HL, que é um registrador de 16 bits.Como a CPU/barramento só pode lidar com operações de 8 bits, ela precisa ser dividida;ou a sugestão mais lógica:como é apenas um registro, os valores de H e L ficam mascarados no registro e simplesmente precisam ser separados um do outro (nibble superior/inferior?).

Eu ficaria profundamente grato se alguém pudesse deixar isso mais claro para mim, porque eu só quero ter mais conhecimento prévio (como tudo isso funciona internamente), então é muito importante para mim saber o que estou fazendo.

Foi útil?

Solução

Como os comentários apontaram, o fato de a implementação que você encontrou armazenar os registros H e L juntos como a entidade HL de 16 bits e depois decompô-los em H, deslocando-se para a direita e em L, mascarando-se, é puramente uma implementação específica.

O z80 original tem uma ALU de 4 bits (veja os comentários de Shima começando no final da página 9 em esta transcrição de um painel do Computer History Museum) então seria na verdade (i) AND os quatro bits inferiores de L e o acumulador;então (ii) AND os quatro bits mais altos de L e o acumulador.No entanto, ele expõe seus registradores como entidades discretas de 8 bits, de modo que a implementação interna fica totalmente oculta.

HL é chamado de par de registradores porque são dois registradores reunidos para formar uma quantidade de 16 bits.Ignorando os registros de sombra e de índice, o z80 original possui três deles – HL, BC e DE.BC e DE sobrevivem na CPU do Gameboy como pares alternativos para carregamento indireto (como opcode 0x1a — LD A, (BC)) e para aritmética de 16 bits (por exemplo, 0x09 ADD HL, BC) e têm alguns outros usos em um z80.

SP e PC são geralmente considerados registradores indivisíveis de 16 bits (embora, é claro, você possa dividi-los armazenando-os na memória e lendo os bytes individualmente) e AF existe para empurrar e estourar, mas F é um caso tão especial que AF geralmente não é particularmente útil como um número inteiro de 16 bits.

Breve resumo então:você não está tendo problemas para entender como os opcodes tem que ser implementados, apenas como foram implementados por um determinado autor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top