bquarkz 694d6c8be6 dev/vm-improvements (#3)
Co-authored-by: Nilton Constantino <nilton.constantino@visma.com>
Reviewed-on: #3
2026-01-20 10:18:44 +00:00

153 lines
6.7 KiB
Markdown

# prometeu-bytecode
Contrato oficial (ABI) do ecossistema PROMETEU. Este crate define o conjunto de instruções (ISA), o formato de arquivo `.pbc` (Prometeu ByteCode) e ferramentas básicas de montagem (Assembler) e desmontagem (Disassembler).
## Design
A PVM (Prometeu Virtual Machine) é uma máquina baseada em pilha (**stack-based**). A maioria das instruções opera nos valores do topo da pilha de operandos. O formato de dados padrão para multi-byte na ROM é **Little-Endian**.
### Convenção de Notação da Pilha
Nas tabelas abaixo, usamos a seguinte notação para representar o estado da pilha:
`[a, b] -> [c]`
Significa que a instrução remove `a` e `b` da pilha (onde `b` estava no topo) e insere `c` no topo.
---
## Conjunto de Instruções (ISA)
### 6.1 Controle de Execução
| OpCode | Valor | Operandos | Pilha | Descrição |
| :--- | :--- | :--- | :--- | :--- |
| `Nop` | `0x00` | - | `[] -> []` | Nenhuma operação. |
| `Halt` | `0x01` | - | `[] -> []` | Interrompe a execução da VM permanentemente. |
| `Jmp` | `0x02` | `addr: u32` | `[] -> []` | Salto incondicional para o endereço absoluto `addr`. |
| `JmpIfFalse`| `0x03` | `addr: u32` | `[bool] -> []` | Salta para `addr` se o valor desempilhado for `false`. |
| `JmpIfTrue` | `0x04` | `addr: u32` | `[bool] -> []` | Salta para `addr` se o valor desempilhado for `true`. |
| `Trap` | `0x05` | - | `[] -> []` | Interrupção para debugger (breakpoint). |
### 6.2 Manipulação da Pilha
| OpCode | Valor | Operandos | Pilha | Descrição |
| :--- | :--- | :--- | :--- | :--- |
| `PushConst` | `0x10` | `idx: u32` | `[] -> [val]` | Carrega a constante do índice `idx` da Constant Pool. |
| `Pop` | `0x11` | - | `[val] -> []` | Remove e descarta o valor do topo da pilha. |
| `Dup` | `0x12` | - | `[val] -> [val, val]` | Duplica o valor no topo da pilha. |
| `Swap` | `0x13` | - | `[a, b] -> [b, a]` | Inverte a posição dos dois valores no topo. |
| `PushI64` | `0x14` | `val: i64` | `[] -> [i64]` | Empilha um inteiro de 64 bits imediato. |
| `PushF64` | `0x15` | `val: f64` | `[] -> [f64]` | Empilha um ponto flutuante de 64 bits imediato. |
| `PushBool` | `0x16` | `val: u8` | `[] -> [bool]` | Empilha um booleano (0=false, 1=true). |
| `PushI32` | `0x17` | `val: i32` | `[] -> [i32]` | Empilha um inteiro de 32 bits imediato. |
| `PopN` | `0x18` | `n: u16` | `[...] -> [...]` | Remove `n` valores da pilha de uma vez. |
### 6.3 Aritmética
A VM realiza promoção automática de tipos (ex: `i32` + `f64` resulta em `f64`).
| OpCode | Valor | Pilha | Descrição |
| :--- | :--- | :--- | :--- |
| `Add` | `0x20` | `[a, b] -> [a + b]` | Soma os dois valores do topo. |
| `Sub` | `0x21` | `[a, b] -> [a - b]` | Subtrai `b` de `a`. |
| `Mul` | `0x22` | `[a, b] -> [a * b]` | Multiplica os dois valores do topo. |
| `Div` | `0x23` | `[a, b] -> [a / b]` | Divide `a` por `b`. Erro se `b == 0`. |
| `Neg` | `0x3E` | `[a] -> [-a]` | Inverte o sinal numérico. |
### 6.4 Lógica e Comparação
| OpCode | Valor | Pilha | Descrição |
| :--- | :--- | :--- | :--- |
| `Eq` | `0x30` | `[a, b] -> [bool]` | Testa igualdade. |
| `Neq` | `0x31` | `[a, b] -> [bool]` | Testa desigualdade. |
| `Lt` | `0x32` | `[a, b] -> [bool]` | `a < b` |
| `Gt` | `0x33` | `[a, b] -> [bool]` | `a > b` |
| `Lte` | `0x3C` | `[a, b] -> [bool]` | `a <= b` |
| `Gte` | `0x3D` | `[a, b] -> [bool]` | `a >= b` |
| `And` | `0x34` | `[a, b] -> [bool]` | AND lógico (booleano). |
| `Or` | `0x35` | `[a, b] -> [bool]` | OR lógico (booleano). |
| `Not` | `0x36` | `[a] -> [!a]` | NOT lógico. |
| `BitAnd` | `0x37` | `[a, b] -> [int]` | AND bit a bit. |
| `BitOr` | `0x38` | `[a, b] -> [int]` | OR bit a bit. |
| `BitXor` | `0x39` | `[a, b] -> [int]` | XOR bit a bit. |
| `Shl` | `0x3A` | `[a, b] -> [int]` | Shift Left: `a << b`. |
| `Shr` | `0x3B` | `[a, b] -> [int]` | Shift Right: `a >> b`. |
### 6.5 Variáveis e Memória
| OpCode | Valor | Operandos | Pilha | Descrição |
| :--- | :--- | :--- | :--- | :--- |
| `GetGlobal`| `0x40` | `idx: u32` | `[] -> [val]` | Carrega valor da global `idx`. |
| `SetGlobal`| `0x41` | `idx: u32` | `[val] -> []` | Armazena topo na global `idx`. |
| `GetLocal` | `0x42` | `idx: u32` | `[] -> [val]` | Carrega local `idx` do frame atual. |
| `SetLocal` | `0x43` | `idx: u32` | `[val] -> []` | Armazena topo na local `idx` do frame atual. |
### 6.6 Funções e Escopo
| OpCode | Valor | Operandos | Pilha | Descrição |
| :--- | :--- | :--- | :--- | :--- |
| `Call` | `0x50` | `addr: u32, args: u32` | `[a1, a2] -> [...]` | Chama `addr`. Os `args` valores no topo viram locais do novo frame. |
| `Ret` | `0x51` | - | `[val] -> [val]` | Retorna da função atual, limpando o frame e devolvendo o valor do topo. |
| `PushScope`| `0x52` | - | `[] -> []` | Inicia um sub-escopo (bloco) para locais temporários. |
| `PopScope` | `0x53` | - | `[] -> []` | Finaliza sub-escopo, removendo locais criados nele da pilha. |
### 6.7 Heap (Memória Dinâmica)
| OpCode | Valor | Operandos | Pilha | Descrição |
| :--- | :--- | :--- | :--- | :--- |
| `Alloc` | `0x60` | `size: u32` | `[] -> [ref]` | Aloca `size` slots no heap e retorna uma referência. |
| `LoadRef` | `0x61` | `offset: u32`| `[ref] -> [val]` | Lê valor do heap no endereço `ref + offset`. |
| `StoreRef`| `0x62` | `offset: u32`| `[ref, val] -> []` | Escreve `val` no heap no endereço `ref + offset`. |
### 6.8 Sistema e Sincronização
| OpCode | Valor | Operandos | Pilha | Descrição |
| :--- | :--- | :--- | :--- | :--- |
| `Syscall` | `0x70` | `id: u32` | `[...] -> [...]` | Invoca uma função do sistema/firmware. A pilha depende da syscall. |
| `FrameSync`| `0x80` | - | `[] -> []` | Marca o fim do processamento do frame lógico atual (60 FPS). |
---
## Estrutura do PBC (Prometeu ByteCode)
O PBC é o formato binário oficial para programas Prometeu.
```rust
// Exemplo de como carregar um arquivo PBC
let bytes = std::fs::read("game.pbc")?;
let pbc = prometeu_bytecode::pbc::parse_pbc(&bytes)?;
println!("ROM size: {} bytes", pbc.rom.len());
println!("Constants: {}", pbc.cp.len());
```
---
## Assembler e Disassembler
Este crate fornece ferramentas para facilitar a geração e inspeção de código.
### Montagem (Assembler)
```rust
use prometeu_bytecode::asm::{assemble, Asm, Operand};
use prometeu_bytecode::opcode::OpCode;
let instructions = vec![
Asm::Op(OpCode::PushI32, vec![Operand::I32(10)]),
Asm::Op(OpCode::PushI32, vec![Operand::I32(20)]),
Asm::Op(OpCode::Add, vec![]),
Asm::Op(OpCode::Halt, vec![]),
];
let rom_bytes = assemble(&instructions).unwrap();
```
### Desmontagem (Disassembler)
```rust
use prometeu_bytecode::disasm::disasm;
let rom = vec![/* ... bytes ... */];
let code = disasm(&rom);
for instr in code {
println!("{:04X}: {:?} {:?}", instr.pc, instr.opcode, instr.operands);
}
```