pr1.4
This commit is contained in:
parent
6423c6b4bc
commit
7a65fbe02c
@ -7,20 +7,19 @@
|
||||
//! - `decode_next(pc, bytes)` returns a typed `DecodedInstr` with canonical `next_pc`.
|
||||
//! - Immediate helpers validate sizes deterministically and return explicit errors.
|
||||
|
||||
use crate::opcode::OpCode;
|
||||
use crate::opcode_spec::{OpCodeSpecExt, OpcodeSpec};
|
||||
use crate::isa::core::{CoreOpCode, CoreOpCodeSpecExt, CoreOpcodeSpec};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum DecodeError {
|
||||
TruncatedOpcode { pc: usize },
|
||||
UnknownOpcode { pc: usize, opcode: u16 },
|
||||
TruncatedImmediate { pc: usize, opcode: OpCode, need: usize, have: usize },
|
||||
ImmediateSizeMismatch { pc: usize, opcode: OpCode, expected: usize, actual: usize },
|
||||
TruncatedImmediate { pc: usize, opcode: CoreOpCode, need: usize, have: usize },
|
||||
ImmediateSizeMismatch { pc: usize, opcode: CoreOpCode, expected: usize, actual: usize },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct DecodedInstr<'a> {
|
||||
pub opcode: OpCode,
|
||||
pub opcode: CoreOpCode,
|
||||
pub pc: usize,
|
||||
pub next_pc: usize,
|
||||
/// Raw immediate bytes slice, guaranteed to have length `opcode.spec().imm_bytes`.
|
||||
@ -96,10 +95,10 @@ pub fn decode_next(pc: usize, bytes: &'_ [u8]) -> Result<DecodedInstr<'_>, Decod
|
||||
}
|
||||
|
||||
let opcode_val = u16::from_le_bytes([bytes[pc], bytes[pc + 1]]);
|
||||
let opcode = OpCode::try_from(opcode_val)
|
||||
let opcode = CoreOpCode::try_from(opcode_val)
|
||||
.map_err(|_| DecodeError::UnknownOpcode { pc, opcode: opcode_val })?;
|
||||
|
||||
let spec: OpcodeSpec = opcode.spec();
|
||||
let spec: CoreOpcodeSpec = opcode.spec();
|
||||
let imm_start = pc + 2;
|
||||
let imm_end = imm_start + (spec.imm_bytes as usize);
|
||||
|
||||
|
||||
11
crates/console/prometeu-bytecode/src/isa/core.rs
Normal file
11
crates/console/prometeu-bytecode/src/isa/core.rs
Normal file
@ -0,0 +1,11 @@
|
||||
//! Core ISA profile (bytecode-only, minimal and stable).
|
||||
//!
|
||||
//! This profile is the canonical surface used by decoder/disasm. It intentionally
|
||||
//! avoids higher-level constructs (e.g., closures/coroutines) at this stage.
|
||||
|
||||
// For PR-1.4 we define the core profile as the current `OpCode` set. We re-export
|
||||
// the opcode type and spec so downstream tools can import from a stable path:
|
||||
// `prometeu_bytecode::isa::core::*`.
|
||||
|
||||
pub use crate::opcode::OpCode as CoreOpCode;
|
||||
pub use crate::opcode_spec::{OpCodeSpecExt as CoreOpCodeSpecExt, OpcodeSpec as CoreOpcodeSpec};
|
||||
6
crates/console/prometeu-bytecode/src/isa/mod.rs
Normal file
6
crates/console/prometeu-bytecode/src/isa/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
//! ISA module tree
|
||||
//!
|
||||
//! This module defines stable ISA profiles. For PR-1.4 we expose the
|
||||
//! minimal core ISA surface used by the encoder/decoder and (later) verifier.
|
||||
|
||||
pub mod core;
|
||||
@ -6,6 +6,7 @@ mod opcode;
|
||||
mod opcode_spec;
|
||||
mod program_image;
|
||||
mod value;
|
||||
pub mod isa; // canonical ISA boundary (core and future profiles)
|
||||
|
||||
pub use abi::{
|
||||
TrapInfo, TRAP_BAD_RET_SLOTS, TRAP_DIV_ZERO, TRAP_ILLEGAL_INSTRUCTION, TRAP_INVALID_FUNC,
|
||||
|
||||
75
docs/bytecode/ISA_CORE.md
Normal file
75
docs/bytecode/ISA_CORE.md
Normal file
@ -0,0 +1,75 @@
|
||||
### Prometeu Bytecode — Core ISA (Minimal, Bytecode‑Only)
|
||||
|
||||
This document defines the minimal, stable Core ISA surface for the Prometeu Virtual Machine at the bytecode level. It specifies instruction encoding, the stack evaluation model, and the instruction set currently available. Higher‑level constructs (closures, coroutines) are intentionally out of scope at this stage.
|
||||
|
||||
#### Encoding Rules
|
||||
|
||||
- Endianness: Little‑endian.
|
||||
- Instruction layout: `[opcode: u16][immediate: spec.imm_bytes]`.
|
||||
- Opcodes are defined in `prometeu_bytecode::isa::core::CoreOpCode`.
|
||||
- Immediate sizes and stack effects are defined by `CoreOpCode::spec()` returning `CoreOpcodeSpec`.
|
||||
- All jump immediates are absolute u32 byte offsets from the start of the current function.
|
||||
|
||||
#### Stack Machine Model
|
||||
|
||||
- The VM is stack‑based. Unless noted, operands are taken from the top of the operand stack and results are pushed back.
|
||||
- Types at the bytecode level are represented by the `Value` enum; the VM may perform numeric promotion where appropriate (e.g., `Int32 + Float -> Float`).
|
||||
- Stack underflow is a trap (TRAP_STACK_UNDERFLOW).
|
||||
- Some operations may trap for other reasons (e.g., division by zero, invalid indices, type mismatches).
|
||||
|
||||
#### Instruction Set (Core)
|
||||
|
||||
- Execution control:
|
||||
- `NOP` — no effect.
|
||||
- `HALT` — terminates execution (block terminator).
|
||||
- `JMP u32` — unconditional absolute jump (block terminator).
|
||||
- `JMP_IF_FALSE u32` — pops `[bool]`, jumps if false.
|
||||
- `JMP_IF_TRUE u32` — pops `[bool]`, jumps if true.
|
||||
- `TRAP` — software trap/breakpoint (block terminator).
|
||||
|
||||
- Stack manipulation:
|
||||
- `PUSH_CONST u32` — load constant by index → pushes `[value]`.
|
||||
- `PUSH_I64 i64`, `PUSH_F64 f64`, `PUSH_BOOL u8`, `PUSH_I32 i32`, `PUSH_BOUNDED u32(<=0xFFFF)` — push literals.
|
||||
- `POP` — pops 1.
|
||||
- `POP_N u32` — pops N.
|
||||
- `DUP` — `[x] -> [x, x]`.
|
||||
- `SWAP` — `[a, b] -> [b, a]`.
|
||||
|
||||
- Arithmetic:
|
||||
- `ADD`, `SUB`, `MUL`, `DIV`, `MOD` — binary numeric ops.
|
||||
- `NEG` — unary numeric negation.
|
||||
- `BOUND_TO_INT` — `[bounded] -> [int64]`.
|
||||
- `INT_TO_BOUND_CHECKED` — `[int] -> [bounded]` (traps on overflow 0..65535).
|
||||
|
||||
- Comparison and logic:
|
||||
- `EQ`, `NEQ`, `LT`, `LTE`, `GT`, `GTE` — comparisons → `[bool]`.
|
||||
- `AND`, `OR`, `NOT` — boolean logic.
|
||||
- `BIT_AND`, `BIT_OR`, `BIT_XOR`, `SHL`, `SHR` — integer bit operations.
|
||||
|
||||
- Variables:
|
||||
- `GET_GLOBAL u32`, `SET_GLOBAL u32` — access global slots.
|
||||
- `GET_LOCAL u32`, `SET_LOCAL u32` — access local slots (current frame).
|
||||
|
||||
- Functions and scopes:
|
||||
- `CALL u32` — call by function index; argument/result arity per function metadata.
|
||||
- `RET` — return from current function (block terminator).
|
||||
- `PUSH_SCOPE`, `POP_SCOPE` — begin/end lexical scope.
|
||||
|
||||
- System/Timing:
|
||||
- `SYSCALL u32` — platform call; arity/types are verified by the VM/firmware layer.
|
||||
- `FRAME_SYNC` — yield until the next frame boundary (e.g., vblank); explicit safepoint.
|
||||
|
||||
For exact immediates and stack effects, see `CoreOpCode::spec()` which is the single source of truth used by the decoder, disassembler, and (later) verifier.
|
||||
|
||||
#### Canonical Decoder Contract
|
||||
|
||||
- The canonical decoder is `prometeu_bytecode::decode_next(pc, bytes)`.
|
||||
- It uses the Core ISA spec to determine immediate size and the canonical `next_pc`.
|
||||
- Unknown or legacy opcodes must produce a deterministic `UnknownOpcode` error.
|
||||
|
||||
#### Module Boundary
|
||||
|
||||
- Core ISA lives under `prometeu_bytecode::isa::core` and re‑exports:
|
||||
- `CoreOpCode` — the opcode enum of the core profile.
|
||||
- `CoreOpcodeSpec` and `CoreOpCodeSpecExt` — spec with `imm_bytes`, stack effects, and flags.
|
||||
- Consumers (encoder/decoder/disasm/verifier) should import from this module to avoid depending on internal layout.
|
||||
@ -1,41 +1,3 @@
|
||||
# PR-1.4 — Define the Minimal Core ISA Surface (Bytecode-Only)
|
||||
|
||||
### Briefing
|
||||
|
||||
After deleting legacy opcodes, we must explicitly define the **minimal ISA** that remains. This PR establishes the canonical core ISA module boundary and documentation.
|
||||
|
||||
### Target
|
||||
|
||||
* Introduce a “core ISA” definition that is small and stable.
|
||||
* Provide clear docs for stack effects and operand encoding at a bytecode level.
|
||||
|
||||
### Work items
|
||||
|
||||
* Create/reshape modules so the “core ISA” is clearly isolated (e.g., `isa/core` or similar).
|
||||
* Add module docs describing:
|
||||
|
||||
* Instruction encoding rules.
|
||||
* Stack-based evaluation model (bytecode-level).
|
||||
* Which instructions exist at this stage (no closures/coroutines yet unless already in the spec subset).
|
||||
* Add a `docs/bytecode/ISA_CORE.md` (or equivalent) that is short but precise.
|
||||
* Ensure the ISA definition is used by:
|
||||
|
||||
* Encoder/decoder.
|
||||
* Disasm.
|
||||
* Verifier (later).
|
||||
|
||||
### Acceptance checklist
|
||||
|
||||
* [ ] Minimal ISA is explicitly defined and documented.
|
||||
* [ ] No legacy instructions remain.
|
||||
* [ ] `cargo test` passes.
|
||||
|
||||
### Tests
|
||||
|
||||
* Existing tests only.
|
||||
|
||||
---
|
||||
|
||||
# PR-1.5 — Bytecode Module Pruning (Delete Unused/Experimental Modules)
|
||||
|
||||
### Briefing
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user