< [Voltar](chapter-1.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-3.md) > # ⚙️ ** PVM (PROMETEU VM) — Instruction Set** ## 1. Visão Geral A **PROMETEU VM** é uma máquina virtual obrigatória e sempre presente no hardware lógico: * **stack-based** * determinística * orientada a ciclos * projetada para ensino e inspeção Ela existe para: * mapear conceitos de linguagens de alto nível * tornar custo computacional visível * permitir análise de execução * servir como base do cartucho PROMETEU > A PROMETEU VM é simples por escolha. > Simplicidade é uma ferramenta pedagógica. --- ## 2. Modelo de Execução ### 2.1 Componentes Principais A VM possui: * **PC (Program Counter)** — próxima instrução * **Operand Stack** — pilha de valores * **Call Stack** — pilha de frames * **Heap** — memória dinâmica * **Globals** — variáveis globais * **Constant Pool** — literais e referências * **ROM** — bytecode do cartucho * **RAM** — dados mutáveis --- ### 2.2 Ciclo de Execução Cada instrução executa: ``` FETCH → DECODE → EXECUTE → ADVANCE PC ``` Propriedades: * toda instrução tem custo fixo em ciclos * não há trabalho implícito invisível * execução é totalmente determinística --- ## 3. Tipos Fundamentais | Tipo | Descrição | | --------- | ----------------------- | | `integer` | inteiro 64-bit (signed) | | `float` | ponto flutuante 64-bit | | `boolean` | verdadeiro/falso | | `string` | UTF-8 imutável | | `null` | ausência de valor | | `ref` | referência ao heap | Não existem: * coerções mágicas * casts implícitos * overflows silenciosos --- ## 4. Convenções da Pilha * Operações usam o topo da pilha * Resultado sempre volta para a pilha * Último empilhado = primeiro consumido Exemplo: ``` PUSH_CONST 3 PUSH_CONST 4 ADD ``` Estado: ``` [3] [3, 4] [7] ``` --- ## 5. Categorias de Instruções 1. Controle de fluxo 2. Pilha 3. Aritmética e lógica 4. Variáveis 5. Funções 6. Heap e estruturas 7. Periféricos (syscalls) 8. Sistema --- ## 6. Instruções — VM Set 1 ### 6.1 Controle de Execução | Instrução | Ciclos | Descrição | | ------------------- | ------ | ----------------------- | | `NOP` | 1 | Não faz nada | | `HALT` | 1 | Encerra execução | | `JMP addr` | 2 | Salto incondicional | | `JMP_IF_FALSE addr` | 3 | Salta se topo for falso | --- ### 6.2 Pilha | Instrução | Ciclos | Descrição | | -------------- | ------ | ----------------- | | `PUSH_CONST k` | 2 | Empilha constante | | `POP` | 1 | Remove topo | | `DUP` | 1 | Duplica topo | | `SWAP` | 1 | Troca dois topos | --- ### 6.3 Aritmética | Instrução | Ciclos | | --------- | ------ | | `ADD` | 2 | | `SUB` | 2 | | `MUL` | 4 | | `DIV` | 6 | --- ### 6.4 Comparação e Lógica | Instrução | Ciclos | | --------- | ------ | | `EQ` | 2 | | `NEQ` | 2 | | `LT` | 2 | | `GT` | 2 | | `AND` | 2 | | `OR` | 2 | | `NOT` | 1 | --- ### 6.5 Variáveis | Instrução | Ciclos | Descrição | | -------------- | ------ | -------------- | | `GET_GLOBAL i` | 3 | Lê global | | `SET_GLOBAL i` | 3 | Escreve global | | `GET_LOCAL i` | 2 | Lê local | | `SET_LOCAL i` | 2 | Escreve local | --- ### 6.6 Funções | Instrução | Ciclos | Descrição | |----------------| ------ |---------------------------------| | `CALL addr` | 5 | Chamada | | `RET` | 4 | Retorno | | `PUSH_SCOPE n` | 3 | Cria escopo (frame de execução) | | `POP_SCOPE` | 3 | Remove escopo | --- ### 6.7 Heap | Instrução | Ciclos | Descrição | | --------------- | ------ | ------------- | | `ALLOC size` | 10 | Aloca no heap | | `LOAD_REF off` | 3 | Lê campo | | `STORE_REF off` | 3 | Escreve campo | Heap é: * finito * monitorado * contabilizado no CAP --- ### 6.8 Periféricos (Syscalls) | Instrução | Ciclos | Descrição | |--------------| -------- | ------------------- | | `SYSCALL id` | variável | Chamada ao hardware | #### Syscalls Implementadas (v0.1) | ID | Nome | Argumentos (Pilha) | Retorno | | ---------- | ----------------- | ---------------------------- | ------- | | `0x0001` | `system.has_cart` | - | `bool` | | `0x0002` | `system.run_cart` | - | - | | `0x1001` | `gfx.clear` | `color_idx` | - | | `0x1002` | `gfx.draw_rect` | `x, y, w, h, color_idx` | - | | `0x2001` | `input.get_pad` | `button_id` | `bool` | | `0x3001` | `audio.play` | `s_id, v_id, vol, pan, pitch`| - | **IDs de Botões:** - `0`: Up, `1`: Down, `2`: Left, `3`: Right - `4`: A, `5`: B, `6`: X, `7`: Y - `8`: L, `9`: R - `10`: Start, `11`: Select --- ## 7. Erros de Execução Erros são: * explícitos * fatais * nunca silenciosos Tipos: * stack underflow * tipo inválido * heap inválido * frame inválido Geram: * mensagem clara * dump de estado * stack trace --- ## 8. Determinismo Garantias: * mesma entrada → mesmo resultado * mesma sequência → mesmos ciclos * sem execução especulativa * sem otimizações invisíveis > Se você vê a instrução, você paga por ela. --- ## 9. Relação com Linguagens Java, TypeScript, Lua etc: * são linguagens-fonte * compiladas para esse bytecode * nunca executadas diretamente Todas rodam na **mesma VM**. --- ## 10. Exemplo Fonte: ```java x = 3 + 4; ``` Bytecode: ``` PUSH_CONST 3 PUSH_CONST 4 ADD SET_GLOBAL 0 ``` Custo: ``` 2 + 2 + 2 + 3 = 9 ciclos ``` --- ## 11. Execução por Tick A VM não roda infinitamente. Ela executa: * até consumir o budget do **frame lógico** * ou até `HALT` O budget é definido pelo hardware lógico do PROMETEU (ex.: `CYCLES_PER_FRAME`). Exemplo: ``` vm.step_budget(10_000) ``` Isso alimenta: * CAP * profiling * certificação --- ## 12. Frame Lógico e `FRAME_SYNC` O PROMETEU define **frame lógico** como a unidade mínima de atualização consistente do jogo. * **Input é latched por frame lógico** (não muda enquanto o frame lógico não for concluído). * O **budget de ciclos** é aplicado ao frame lógico. * Um novo frame lógico só começa quando o frame atual termina. ### 12.1 Instrução de Sistema: `FRAME_SYNC` A instrução `FRAME_SYNC` marca o **fim do frame lógico**. | Instrução | Ciclos | Descrição | | ------------ | ------ | ----------------------------- | | `FRAME_SYNC` | 1 | Finaliza o frame lógico atual | Propriedades: * `FRAME_SYNC` é uma **instrução do sistema**. * Não deve ser exposta como API “manual” ao usuário. * O tooling/compilador pode **injetar** `FRAME_SYNC` automaticamente ao final do loop principal. ### 12.2 Semântica (o que acontece quando executa) Ao executar `FRAME_SYNC`, o core: 1. **Finaliza** o frame lógico atual. 2. **Apresenta** o frame (`gfx.present()` ou `gfx.compose_and_present()` conforme o modelo do GFX). 3. **Libera** o latch de input. 4. **Reseta** o budget para o próximo frame lógico. ### 12.3 Overbudget (quando o frame não termina a tempo) Se o budget do frame lógico acabar **antes** da VM alcançar `FRAME_SYNC`: * a VM **pausa** (PC e pilhas permanecem no ponto exato) * **não há present** * o latch de input é **mantido** * no próximo tick do host, a VM **continua** de onde parou, ainda no mesmo frame lógico Efeito prático: * se o código precisa de 2 budgets para alcançar `FRAME_SYNC`, o jogo passa a atualizar a ~30 FPS (frame lógico leva 2 ticks) * isso é determinístico e reportável no CAP --- ## 15. Extensibilidade O Instruction Set é versionado. Futuro: * DMA * streaming * vetores * coprocessadores fictícios Nenhuma instrução existente muda de significado. --- ## 16. Resumo * VM stack-based * custo explícito * execução determinística * integrada ao CAP * base de todo cartucho PROMETEU < [Voltar](chapter-1.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-3.md) >