Bom dia
Há muito tempo, havia um desejo de escrever um emulador de algum processador.
E o que poderia ser melhor do que inventar uma bicicleta?
O nome da bicicleta é V16, colando a palavra Virtual e, de fato, profundidade de bits.
Por onde começar?
E você precisa começar, é claro, com uma descrição do processador.
No começo, planejei escrever um emulador de DCPU-16, mas existem muitos milagres na Internet, então decidi me concentrar apenas em "lamber" o mais básico do DCPU-16 1.1.
Arquitetura
Memória e portas
- A V16 endereça 128 KB (65536 palavras) de RAM, que também podem ser usados como buffers de dispositivo e a pilha.
- A pilha começa com o endereço FFFF, portanto, o RSP possui um valor padrão de 0xFFFF
- As portas de E / S V16 têm 256, todas com 16 bits. A leitura e escrita a partir deles é realizada através das instruções
IN b, a
AND OUT b, a
.
Registros
O V16 possui dois conjuntos de registros de uso geral: primário e alternativo.
Um processador pode funcionar com apenas um conjunto, para que você possa alternar entre os conjuntos usando a instrução XCR
.
Instruções
Todas as instruções têm um comprimento máximo de três palavras e são totalmente definidas primeiro
A primeira palavra é dividida em três valores: o byte baixo é o código de operação, o byte alto na forma de dois valores de 4 bits é a descrição dos operandos.
Interrupções
As interrupções aqui nada mais são do que uma tabela com endereços para os quais o processador duplica a instrução CALL
. Se o valor do endereço for zero, a interrupção não faz nada, simplesmente redefine o sinalizador HF.
Um exemplo de pseudocódigo e palavras nas quais tudo isso deve ser traduzido:
MOV RAX, 0xABCD ; 350D ABCD MOV [RAX], 0x1234 ; 354D 1234
Ciclos
O V16 pode executar uma instrução em 1, 2 ou 3 compassos. Cada acesso à memória é um ciclo de relógio separado. Instrução não é tato!
Vamos começar a escrever!
Implementação de estruturas básicas de processador
Um conjunto de registros. Existem apenas quatro registros, mas a situação melhora, pois existem dois desses conjuntos no processador. A troca ocorre usando a instrução XCR
.
typedef struct Regs { uint16_t rax, rbx;
Bandeiras Ao contrário do DCPU-16, o V16 possui saltos condicionais, chamadas de sub-rotina e retorna do mesmo. No momento, o processador possui 8 sinalizadores, 5 dos quais são sinalizadores de condição.
Na verdade, o próprio processador. Também descreve a tabela de endereços de interrupção, que pode ser chamada de descritores e encontra outra referência ao x86.
typedef struct CPU {
Operando. Ao obter os valores, precisamos primeiro ler, depois alterar e, em seguida, escrever o valor de volta para onde conseguimos.
typedef struct Opd { uint8_t code : 4; uint16_t value; uint16_t nextw; } opd_t;
Funções para trabalhar com estruturas
Quando todas as estruturas são descritas, surge a necessidade de funções que dotarão essas estruturas com o poder mágico do código extinto.
cpu_t * cpu_create(void);
Além disso, não mencionei uma grande enumeração com códigos de operação, mas isso não é necessário e é necessário apenas para entender o que está acontecendo em toda essa bagunça.
Função Tick ()
Além disso, há chamadas para funções estáticas destinadas apenas a chamadas de tick()
.
void cpu_tick(cpu_t *cpu) {
O que fazer depois?
Na tentativa de encontrar a resposta para essa pergunta, reescrevi o emulador cinco vezes de C para C ++ e vice-versa.
No entanto, os principais objetivos podem ser identificados agora:
- Prenda interrupções normais (em vez de apenas chamar uma função e proibir o recebimento de outras interrupções, faça uma chamada de função e adicione novas interrupções à fila).
- Parafusos de dispositivos, bem como maneiras de se comunicar com eles, o benefício dos códigos de operação pode ser de 256.
- Ensinar
Não escreva qualquer heresia em Habr O processador opera a uma velocidade de clock específica de 200 MHz.
Conclusão
Espero que este "artigo" seja útil para alguém, alguém os solicite a escrever algo semelhante.
Minhas tortas podem ser visualizadas no github .
Além disso, sobre o horror, eu tenho o assembler para a versão antiga deste emulador (não, nem tente, o emulador pelo menos reclamará do formato errado da ROM)