! AVM ISA v1 — Fortran Port (Strict Functional Execution) module avm implicit none ! ── Constants ────────────────────────────────────────────── integer, parameter :: AVM_CLAMP_MIN = -2147483647 integer, parameter :: AVM_CLAMP_MAX = 2147483647 integer, parameter :: AVM_Q0_MIN = -32767 integer, parameter :: AVM_Q0_MAX = 32767 integer, parameter :: Q16_SCALE = 65536 integer, parameter :: AVM_MAX_STACK = 1024 integer, parameter :: AVM_MAX_LOCALS = 256 ! ── Types ────────────────────────────────────────────────── integer, parameter :: TY_Q0 = 0, TY_Q16 = 1, TY_BOOL = 2 type :: AnyVal integer :: ty = TY_Q0 integer :: i = 0 logical :: b = .false. end type AnyVal ! ── Instruction encoding ─────────────────────────────────── integer, parameter :: OP_PUSH_Q16 = 0, OP_PUSH_BOOL = 1, OP_PUSH_Q0 = 2 integer, parameter :: OP_POP = 3, OP_DUP = 4, OP_SWAP = 5 integer, parameter :: OP_LOAD = 6, OP_STORE = 7 integer, parameter :: OP_JUMP = 8, OP_JUMP_IF = 9, OP_PRIM = 10, OP_HALT = 11 integer, parameter :: PRIM_ADD_Q0 = 0, PRIM_SUB_Q0 = 1 integer, parameter :: PRIM_ADD_Q16 = 2, PRIM_SUB_Q16 = 3 integer, parameter :: PRIM_MUL_Q16 = 4, PRIM_DIV_Q16 = 5 integer, parameter :: PRIM_LT_Q16 = 6, PRIM_EQ_Q16 = 7 integer, parameter :: PRIM_AND = 8, PRIM_OR = 9, PRIM_NOT = 10 type :: Instr integer :: op = OP_HALT integer :: arg = 0 logical :: arg2 = .false. end type Instr type :: State integer :: pc = 0 type(AnyVal) :: stack(AVM_MAX_STACK) integer :: sp = 0 type(AnyVal) :: locals(AVM_MAX_LOCALS) logical :: local_set(AVM_MAX_LOCALS) = .false. logical :: halted = .false. end type State contains ! ── Helpers ──────────────────────────────────────────────── function avm_clamp(x) result(r) integer(kind=8), intent(in) :: x integer :: r if (x > AVM_CLAMP_MAX) then; r = AVM_CLAMP_MAX else if (x < AVM_CLAMP_MIN) then; r = AVM_CLAMP_MIN else; r = int(x); end if end function avm_clamp function avm_q0_clamp(x) result(r) integer(kind=8), intent(in) :: x integer :: r if (x > AVM_Q0_MAX) then; r = AVM_Q0_MAX else if (x < AVM_Q0_MIN) then; r = AVM_Q0_MIN else; r = int(x); end if end function avm_q0_clamp function floor_div(a, b) result(r) integer(kind=8), intent(in) :: a, b integer :: r integer(kind=8) :: q q = a / b if (mod(a, b) /= 0 .and. ieor(a, b) < 0) q = q - 1 r = int(q) end function floor_div function lt_q16_v6(a, b) result(r) integer, intent(in) :: a, b logical :: r logical :: sa, sb sa = a < 0; sb = b < 0 if (sa .neqv. sb) then; r = sa; else; r = a < b; end if end function lt_q16_v6 ! ── Primitive execution ──────────────────────────────────── function eval_prim(p, a, b) result(r) integer, intent(in) :: p type(AnyVal), intent(in) :: a, b type(AnyVal) :: r r%ty = TY_Q0; r%i = 0; r%b = .false. if (p == PRIM_ADD_Q0) then if (a%ty /= TY_Q0 .or. b%ty /= TY_Q0) return r%ty = TY_Q0; r%i = avm_q0_clamp(int(a%i, 8) + int(b%i, 8)) else if (p == PRIM_SUB_Q0) then if (a%ty /= TY_Q0 .or. b%ty /= TY_Q0) return r%ty = TY_Q0; r%i = avm_q0_clamp(int(a%i, 8) - int(b%i, 8)) else if (p == PRIM_ADD_Q16) then if (a%ty /= TY_Q16 .or. b%ty /= TY_Q16) return r%ty = TY_Q16; r%i = avm_clamp(int(a%i, 8) + int(b%i, 8)) else if (p == PRIM_SUB_Q16) then if (a%ty /= TY_Q16 .or. b%ty /= TY_Q16) return r%ty = TY_Q16; r%i = avm_clamp(int(a%i, 8) - int(b%i, 8)) else if (p == PRIM_MUL_Q16) then if (a%ty /= TY_Q16 .or. b%ty /= TY_Q16) return r%ty = TY_Q16; r%i = avm_clamp(int(floor_div(int(a%i,8)*int(b%i,8), int(Q16_SCALE,8)), 8)) else if (p == PRIM_DIV_Q16) then if (a%ty /= TY_Q16 .or. b%ty /= TY_Q16 .or. b%i == 0) return r%ty = TY_Q16; r%i = avm_clamp(int(floor_div(int(a%i,8)*Q16_SCALE, int(b%i,8)), 8)) else if (p == PRIM_LT_Q16) then if (a%ty /= TY_Q16 .or. b%ty /= TY_Q16) return r%ty = TY_BOOL; r%b = lt_q16_v6(a%i, b%i) else if (p == PRIM_EQ_Q16) then if (a%ty /= TY_Q16 .or. b%ty /= TY_Q16) return r%ty = TY_BOOL; r%b = (a%i == b%i) else if (p == PRIM_AND) then if (a%ty /= TY_BOOL .or. b%ty /= TY_BOOL) return r%ty = TY_BOOL; r%b = a%b .and. b%b else if (p == PRIM_OR) then if (a%ty /= TY_BOOL .or. b%ty /= TY_BOOL) return r%ty = TY_BOOL; r%b = a%b .or. b%b else if (p == PRIM_NOT) then if (a%ty /= TY_BOOL) return r%ty = TY_BOOL; r%b = .not. a%b end if end function eval_prim ! ── Step ────────────────────────────────────────────────── function step(s, prog, prog_len) result(err) type(State), intent(inout) :: s type(Instr), intent(in) :: prog(*) integer, intent(in) :: prog_len integer :: err, npc, arity type(AnyVal) :: a, b, res type(Instr) :: cur err = 0 if (s%halted) then; err = -1; return; end if if (s%pc < 0 .or. s%pc >= prog_len) then; s%halted = .true.; return; end if cur = prog(s%pc + 1) npc = s%pc + 1 ! Stack depth check if (cur%op <= OP_PUSH_Q0 .or. cur%op == OP_DUP .or. cur%op == OP_LOAD) then if (s%sp >= AVM_MAX_STACK) then; err = -2; return; end if end if if (cur%op == OP_PUSH_Q16) then s%sp = s%sp + 1; s%stack(s%sp)%ty = TY_Q16; s%stack(s%sp)%i = avm_clamp(int(cur%arg, 8)) else if (cur%op == OP_PUSH_BOOL) then s%sp = s%sp + 1; s%stack(s%sp)%ty = TY_BOOL; s%stack(s%sp)%b = cur%arg2 else if (cur%op == OP_PUSH_Q0) then s%sp = s%sp + 1; s%stack(s%sp)%ty = TY_Q0; s%stack(s%sp)%i = avm_q0_clamp(int(cur%arg, 8)) else if (cur%op == OP_POP) then if (s%sp <= 0) then; err = -3; return; end if; s%sp = s%sp - 1 else if (cur%op == OP_DUP) then if (s%sp <= 0) then; err = -3; return; end if s%sp = s%sp + 1; s%stack(s%sp) = s%stack(s%sp - 1) else if (cur%op == OP_SWAP) then if (s%sp < 2) then; err = -4; return; end if a = s%stack(s%sp); s%stack(s%sp) = s%stack(s%sp-1); s%stack(s%sp-1) = a else if (cur%op == OP_LOAD) then if (cur%arg < 0 .or. cur%arg >= AVM_MAX_LOCALS .or. .not. s%local_set(cur%arg+1)) then err = -5; return end if s%sp = s%sp + 1; s%stack(s%sp) = s%locals(cur%arg+1) else if (cur%op == OP_STORE) then if (s%sp <= 0) then; err = -3; return; end if if (cur%arg < 0 .or. cur%arg >= AVM_MAX_LOCALS) then; err = -5; return; end if s%locals(cur%arg+1) = s%stack(s%sp); s%local_set(cur%arg+1) = .true. s%sp = s%sp - 1 else if (cur%op == OP_JUMP) then if (cur%arg < 0 .or. cur%arg >= prog_len) then; err = -6; return; end if npc = cur%arg else if (cur%op == OP_JUMP_IF) then if (s%sp <= 0) then; err = -3; return; end if a = s%stack(s%sp); s%sp = s%sp - 1 if (a%ty /= TY_BOOL) then; err = -7; return; end if if (a%b) then if (cur%arg < 0 .or. cur%arg >= prog_len) then; err = -6; return; end if npc = cur%arg end if else if (cur%op == OP_PRIM) then arity = 2; if (cur%arg == PRIM_NOT) arity = 1 if (s%sp < arity) then; err = -4; return; end if if (arity >= 2) then; b = s%stack(s%sp); s%sp = s%sp - 1; end if a = s%stack(s%sp); s%sp = s%sp - 1 res = eval_prim(cur%arg, a, b) s%sp = s%sp + 1; s%stack(s%sp) = res else if (cur%op == OP_HALT) then s%halted = .true. end if s%pc = npc end function step end module avm