# 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); } ```