Skip to main content

truthlinked_axiom/
opcode.rs

1//! Truthlinked Axiom Src Opcode
2//!
3//! Owns the canonical opcode set and instruction metadata.
4//! VM and bytecode changes are consensus-sensitive and must remain deterministic across platforms.
5
6/// Register index - 256 general-purpose registers, each holds a [u8; 32].
7/// r0 is always zero (read-only). Writes to r0 are silently discarded.
8pub type Reg = u8;
9
10/// Wide register pair for u256 ops: (hi_reg, lo_reg).
11pub type WideReg = (Reg, Reg);
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Op {
15    // ── Arithmetic ───────────────────────────────────────────────────────────
16    Add(Reg, Reg, Reg),
17    Sub(Reg, Reg, Reg),
18    Mul(Reg, Reg, Reg),
19    Div(Reg, Reg, Reg),
20    Mod(Reg, Reg, Reg),
21    AddSat(Reg, Reg, Reg),
22    SubSat(Reg, Reg, Reg),
23
24    // ── Bitwise ──────────────────────────────────────────────────────────────
25    And(Reg, Reg, Reg),
26    Or(Reg, Reg, Reg),
27    Xor(Reg, Reg, Reg),
28    Not(Reg, Reg),
29    Shl(Reg, Reg, u8),
30    Shr(Reg, Reg, u8),
31
32    // ── Comparison ───────────────────────────────────────────────────────────
33    Eq(Reg, Reg, Reg),
34    Ne(Reg, Reg, Reg),
35    Lt(Reg, Reg, Reg),
36    Lte(Reg, Reg, Reg),
37    Gt(Reg, Reg, Reg),
38    Gte(Reg, Reg, Reg),
39    IsZero(Reg, Reg),
40
41    // ── Control flow ─────────────────────────────────────────────────────────
42    Jump(u32),
43    JumpIf(Reg, u32),
44    JumpIfNot(Reg, u32),
45    Call(u32),
46    Return,
47    Halt,
48    Trap(u16),
49
50    // ── Data ─────────────────────────────────────────────────────────────────
51    LoadConst(Reg, u16),
52    LoadImm8(Reg, u8),
53    LoadImm64(Reg, u64),
54    Move(Reg, Reg),
55    Swap(Reg, Reg),
56
57    // ── Storage ──────────────────────────────────────────────────────────────
58    SLoad(Reg, Reg),
59    SStore(Reg, Reg),
60    SDelete(Reg),
61
62    // ── Context ──────────────────────────────────────────────────────────────
63    GetCaller(Reg),
64    GetOwner(Reg),
65    GetCellId(Reg),
66    GetHeight(Reg),
67    GetTimestamp(Reg),
68    GetValue(Reg),
69    GetCalldataLen(Reg),
70    GetCalldata(Reg, Reg),
71
72    // ── Output ───────────────────────────────────────────────────────────────
73    SetReturn(Reg, Reg),
74    /// set_return_data from register (data_reg holds ptr into calldata, len_reg holds length)
75    SetReturnReg(Reg, Reg),
76    EmitLog(Reg, Reg),
77    /// emit_log with topic, data, and length from registers
78    EmitLogReg(Reg, Reg, Reg),
79
80    // ── Cross-cell ───────────────────────────────────────────────────────────
81    CallCell(Reg, Reg, Reg, Reg),
82    /// Reset the call buffer and set write cursor to 0.
83    BufReset,
84    /// Append a const-pool entry (arbitrary bytes) to the call buffer.
85    BufWriteConst(u16),
86    /// Append 32 bytes from a register to the call buffer.
87    BufWriteReg(Reg),
88    /// Call a cell using the call buffer as calldata.
89    /// BufCallCell(cell_reg, value_reg) - result flag written to r1.
90    BufCallCell(Reg, Reg),
91    /// Set return data from the call buffer contents.
92    BufSetReturn,
93
94    // ── Crypto ───────────────────────────────────────────────────────────────
95    Hash32(Reg, Reg),
96    Hash32Const(Reg, u16),
97
98    // ── Access control ───────────────────────────────────────────────────────
99    RequireOwner,
100    RequireCaller(Reg),
101    RequireEq(Reg, Reg),
102    RequireNe(Reg, Reg),
103    RequireLt(Reg, Reg),
104    RequireNonZero(Reg),
105    RequireGas(u64),
106
107    // ── Token ops ────────────────────────────────────────────────────────────
108    /// dst = token_balance(token_reg, account_reg)  → u128 in low 16 bytes
109    TokenBalance(Reg, Reg, Reg),
110    /// token_transfer(token_reg, from_reg, to_reg, amount_reg)
111    TokenTransfer(Reg, Reg, Reg, Reg),
112    /// token_mint(token_reg, recipient_reg, amount_reg)
113    TokenMint(Reg, Reg, Reg),
114    /// token_burn(token_reg, owner_reg, amount_reg)
115    TokenBurn(Reg, Reg, Reg),
116    /// token_freeze(token_reg, account_reg)
117    TokenFreeze(Reg, Reg),
118    /// token_thaw(token_reg, account_reg)
119    TokenThaw(Reg, Reg),
120
121    // ── Accord (external data consensus) ─────────────────────────────────────
122    /// Submit an accord request. Returns request_id in dst.
123    /// accord_request(dst_reg, url_const_idx_reg, method_reg, body_const_idx_reg)
124    AccordRequest(Reg, Reg, Reg, Reg),
125    /// Read accord response into dst. Returns 0 if pending, 1 if ready.
126    /// accord_read(dst_reg, request_id_reg)
127    AccordRead(Reg, Reg),
128}
129
130/// Opcode byte tags for encoding/decoding.
131pub mod tag {
132    pub const ADD: u8 = 0x01;
133    pub const SUB: u8 = 0x02;
134    pub const MUL: u8 = 0x03;
135    pub const DIV: u8 = 0x04;
136    pub const MOD: u8 = 0x05;
137    pub const ADD_SAT: u8 = 0x06;
138    pub const SUB_SAT: u8 = 0x07;
139    pub const AND: u8 = 0x10;
140    pub const OR: u8 = 0x11;
141    pub const XOR: u8 = 0x12;
142    pub const NOT: u8 = 0x13;
143    pub const SHL: u8 = 0x14;
144    pub const SHR: u8 = 0x15;
145    pub const EQ: u8 = 0x20;
146    pub const NE: u8 = 0x21;
147    pub const LT: u8 = 0x22;
148    pub const LTE: u8 = 0x23;
149    pub const GT: u8 = 0x24;
150    pub const GTE: u8 = 0x25;
151    pub const IS_ZERO: u8 = 0x26;
152    pub const JUMP: u8 = 0x30;
153    pub const JUMP_IF: u8 = 0x31;
154    pub const JUMP_IF_NOT: u8 = 0x32;
155    pub const CALL: u8 = 0x33;
156    pub const RETURN: u8 = 0x34;
157    pub const HALT: u8 = 0x35;
158    pub const TRAP: u8 = 0x36;
159    pub const LOAD_CONST: u8 = 0x40;
160    pub const LOAD_IMM8: u8 = 0x41;
161    pub const LOAD_IMM64: u8 = 0x42;
162    pub const MOVE: u8 = 0x43;
163    pub const SWAP: u8 = 0x44;
164    pub const SLOAD: u8 = 0x50;
165    pub const SSTORE: u8 = 0x51;
166    pub const SDELETE: u8 = 0x52;
167    pub const GET_CALLER: u8 = 0x60;
168    pub const GET_OWNER: u8 = 0x61;
169    pub const GET_CELL_ID: u8 = 0x62;
170    pub const GET_HEIGHT: u8 = 0x63;
171    pub const GET_TIMESTAMP: u8 = 0x64;
172    pub const GET_VALUE: u8 = 0x65;
173    pub const GET_CALLDATA_LEN: u8 = 0x66;
174    pub const GET_CALLDATA: u8 = 0x67;
175    pub const SET_RETURN: u8 = 0x70;
176    pub const SET_RETURN_REG: u8 = 0x72;
177    pub const EMIT_LOG: u8 = 0x71;
178    pub const EMIT_LOG_REG: u8 = 0x73;
179    pub const CALL_CELL: u8 = 0x80;
180    pub const BUF_RESET: u8 = 0xD0;
181    pub const BUF_WRITE_CONST: u8 = 0xD1;
182    pub const BUF_WRITE_REG: u8 = 0xD2;
183    pub const BUF_CALL_CELL: u8 = 0xD3;
184    pub const BUF_SET_RETURN: u8 = 0xD4;
185    pub const HASH32: u8 = 0x90;
186    pub const HASH32_CONST: u8 = 0x91;
187    pub const REQUIRE_OWNER: u8 = 0xA0;
188    pub const REQUIRE_CALLER: u8 = 0xA1;
189    pub const REQUIRE_EQ: u8 = 0xA2;
190    pub const REQUIRE_NE: u8 = 0xA3;
191    pub const REQUIRE_LT: u8 = 0xA4;
192    pub const REQUIRE_NON_ZERO: u8 = 0xA5;
193    pub const REQUIRE_GAS: u8 = 0xA6;
194    // Token ops
195    pub const TOKEN_BALANCE: u8 = 0xB0;
196    pub const TOKEN_TRANSFER: u8 = 0xB1;
197    pub const TOKEN_MINT: u8 = 0xB2;
198    pub const TOKEN_BURN: u8 = 0xB3;
199    pub const TOKEN_FREEZE: u8 = 0xB4;
200    pub const TOKEN_THAW: u8 = 0xB5;
201    // Accord
202    pub const ACCORD_REQUEST: u8 = 0xC0;
203    pub const ACCORD_READ: u8 = 0xC1;
204}