Class: Flux::FluxVM

Inherits:
Object
  • Object
show all
Includes:
OpcodeRegistry
Defined in:
lib/superinstance/flux-runtime/flux_vm.rb

Overview

Main FLUX ISA v3.0 Virtual Machine

Register Model:

  • 16 GP registers (R0-R15, int32)

  • 16 FP registers (F0-F15, float64)

  • 16 VR registers (V0-V15, 256 bytes each)

  • PC, SP, FP_REG, FLAGS, STATE

Memory: flat binary string, 64KB default

Constant Summary collapse

RV =

Register aliases per ISA

8
A0 =

Return value

9
A1 =

First argument

10
SP_REG =

Second argument

11
FP_REG =

Stack pointer

12
FLAGS =

Frame pointer

13
TP =

Flags register

14
LR =

Temporary

15
RUNNING =

VM states

:running
HALTED =
:halted
PANICKED =
:panicked
YIELDED =
:yielded
FLAG_Z =

Flag bits

1 << 0
FLAG_S =
1 << 1
FLAG_C =
1 << 2
FLAG_V =
1 << 3
@@opcode_registry =

Opcode registry for runtime-registered opcodes

{}
@@runtime_opcodes =
{}

Constants included from OpcodeRegistry

OpcodeRegistry::OPCODE_CLASSES, OpcodeRegistry::OPCODE_NAMES

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from OpcodeRegistry

opcode_name

Constructor Details

#initialize(memory_size: 65536) ⇒ FluxVM

Returns a new instance of FluxVM.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 57

def initialize(memory_size: 65536)
  @memory_size = memory_size
  @memory = [0] * memory_size  # Simpler Array of integers

  # General purpose registers (int32)
  @gp = [0] * 16

  # Floating point registers (float64)
  @fp = [0.0] * 16

  # Vector registers (256 bytes each as binary string)
  @vr = Array.new(16) { "\x00" * 256 }

  # System registers
  @pc = 0
  @sp = memory_size  # Stack grows down
  @fp_reg = 0
  @flags = 0
  @state = RUNNING

  # Stats
  @cycles = 0
  @instruction_count = 0
end

Class Attribute Details

.opcode_registryObject

Returns the value of attribute opcode_registry.



50
51
52
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 50

def opcode_registry
  @opcode_registry
end

.runtime_opcodesObject

Returns the value of attribute runtime_opcodes.



50
51
52
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 50

def runtime_opcodes
  @runtime_opcodes
end

Instance Attribute Details

#flagsObject

Returns the value of attribute flags.



42
43
44
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 42

def flags
  @flags
end

#fpObject

Returns the value of attribute fp.



41
42
43
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 41

def fp
  @fp
end

#fp_regObject

Returns the value of attribute fp_reg.



42
43
44
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 42

def fp_reg
  @fp_reg
end

#gpObject

Returns the value of attribute gp.



41
42
43
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 41

def gp
  @gp
end

#memoryObject (readonly)

Returns the value of attribute memory.



43
44
45
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 43

def memory
  @memory
end

#memory_sizeObject (readonly)

Returns the value of attribute memory_size.



43
44
45
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 43

def memory_size
  @memory_size
end

#pcObject

Returns the value of attribute pc.



42
43
44
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 42

def pc
  @pc
end

#spObject

Returns the value of attribute sp.



42
43
44
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 42

def sp
  @sp
end

#stateObject

Current VM state



154
155
156
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 154

def state
  @state
end

#vrObject

Returns the value of attribute vr.



41
42
43
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 41

def vr
  @vr
end

Class Method Details

.register_opcode(opcode_class) ⇒ Object



52
53
54
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 52

def register_opcode(opcode_class)
  @@runtime_opcodes[opcode_class.opcode_id] = opcode_class
end

Instance Method Details

#load(bytecode_string) ⇒ Object

Load bytecode into memory starting at address 0

Raises:



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 83

def load(bytecode_string)
  bytecode = bytecode_string.dup.force_encoding('BINARY')
  raise FluxRuntimeError, 'Bytecode too large' if bytecode.bytesize > @memory_size

  bytecode.bytes.each_with_index do |byte, i|
    @memory[i] = byte
  end

  @pc = 0
  @sp = @memory_size
  self
end

#opAAskObject



967
968
969
970
971
972
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 967

def opAAsk
  length = fetch8
  agent_id = fetch8
  reg = fetch8
  $stderr.puts "A2A: AAsk agent_id=#{agent_id} reg=#{reg}"
end

#opABroadcastObject



988
989
990
991
992
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 988

def opABroadcast
  length = fetch8
  reg = fetch8
  $stderr.puts "A2A: ABroadcast reg=#{reg}"
end

#opADelegateObject



981
982
983
984
985
986
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 981

def opADelegate
  length = fetch8
  agent_id = fetch8
  bc_start = fetchu16
  $stderr.puts "A2A: ADelegate agent_id=#{agent_id} bc_start=#{bc_start}"
end

#opARecvObject



960
961
962
963
964
965
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 960

def opARecv
  length = fetch8
  agent_id = fetch8
  reg = fetch8
  $stderr.puts "A2A: ARecv agent_id=#{agent_id} reg=#{reg}"
end

#opASendObject

A2A Opcodes (stub implementations)



953
954
955
956
957
958
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 953

def opASend
  length = fetch8
  agent_id = fetch8
  reg = fetch8
  $stderr.puts "A2A: ASend agent_id=#{agent_id} reg=#{reg}"
end

#opASubscribeObject



994
995
996
997
998
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 994

def opASubscribe
  length = fetch8
  channel_id = fetch8
  $stderr.puts "A2A: ASubscribe channel_id=#{channel_id}"
end

#opATellObject



974
975
976
977
978
979
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 974

def opATell
  length = fetch8
  agent_id = fetch8
  reg = fetch8
  $stderr.puts "A2A: ATell agent_id=#{agent_id} reg=#{reg}"
end

#opATrustObject



1006
1007
1008
1009
1010
1011
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 1006

def opATrust
  length = fetch8
  agent_id = fetch8
  level = fetch8
  $stderr.puts "A2A: ATrust agent_id=#{agent_id} level=#{level}"
end

#opAVerifyObject



1013
1014
1015
1016
1017
1018
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 1013

def opAVerify
  length = fetch8
  agent_id = fetch8
  result_reg = fetch8
  $stderr.puts "A2A: AVerify agent_id=#{agent_id} result_reg=#{result_reg}"
end

#opAWaitObject



1000
1001
1002
1003
1004
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 1000

def opAWait
  length = fetch8
  cond_reg = fetch8
  $stderr.puts "A2A: AWait cond_reg=#{cond_reg}"
end

#opBAnd(rd, ra, rb) ⇒ Object

Bitwise



870
871
872
873
874
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 870

def opBAnd(rd, ra, rb)
  result = @gp[ra] & @gp[rb]
  set_zn(result)
  @gp[rd] = result
end

#opBNot(rd, ra, rb) ⇒ Object



900
901
902
903
904
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 900

def opBNot(rd, ra, rb)
  result = ~@gp[ra]
  set_zn(result)
  @gp[rd] = result
end

#opBOr(rd, ra, rb) ⇒ Object



876
877
878
879
880
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 876

def opBOr(rd, ra, rb)
  result = @gp[ra] | @gp[rb]
  set_zn(result)
  @gp[rd] = result
end

#opBShl(rd, ra, rb) ⇒ Object



888
889
890
891
892
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 888

def opBShl(rd, ra, rb)
  result = @gp[ra] << (@gp[rb] & 31)
  set_zn(result)
  @gp[rd] = result
end

#opBShr(rd, ra, rb) ⇒ Object



894
895
896
897
898
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 894

def opBShr(rd, ra, rb)
  result = @gp[ra] >> (@gp[rb] & 31)
  set_zn(result)
  @gp[rd] = result
end

#opBToI(rd, ra, rb) ⇒ Object



845
846
847
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 845

def opBToI(rd, ra, rb)
  @gp[rd] = (@gp[ra] != 0) ? 1 : 0
end

#opBXor(rd, ra, rb) ⇒ Object



882
883
884
885
886
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 882

def opBXor(rd, ra, rb)
  result = @gp[ra] ^ @gp[rb]
  set_zn(result)
  @gp[rd] = result
end

#opCallObject



476
477
478
479
480
481
482
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 476

def opCall
  length = fetch8
  func_idx = fetchu16
  push(@pc)
  @gp[LR] = @pc
  @pc = func_idx
end

#opCallIndirectObject



484
485
486
487
488
489
490
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 484

def opCallIndirect
  length = fetch8
  reg = fetch8
  push(@pc)
  @gp[LR] = @pc
  @pc = @gp[reg]
end

#opCast(rd, ra, rb) ⇒ Object

Type/Meta



854
855
856
857
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 854

def opCast(rd, ra, rb)
  # Type-cast: simplified implementation
  @gp[rd] = @gp[ra]
end

#opDup(rd, rs) ⇒ Object



501
502
503
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 501

def opDup(rd, rs)
  @gp[rd] = @gp[rs]
end

#opFAbs(rd, ra, rb) ⇒ Object



748
749
750
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 748

def opFAbs(rd, ra, rb)
  @fp[rd] = @fp[ra].abs
end

#opFAdd(rd, ra, rb) ⇒ Object

Float Arithmetic



719
720
721
722
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 719

def opFAdd(rd, ra, rb)
  result = @fp[ra] + @fp[rb]
  @fp[rd] = result
end

#opFCeil(rd, ra, rb) ⇒ Object



760
761
762
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 760

def opFCeil(rd, ra, rb)
  @fp[rd] = @fp[ra].ceil
end

#opFClamp(rd, ra, rb) ⇒ Object



792
793
794
795
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 792

def opFClamp(rd, ra, rb)
  # FP[Rd] = clamp(FP[Ra], FP[Rb], Rc) - simplified, just min of ra,rb
  @fp[rd] = [@fp[ra], @fp[rb]].min
end

#opFCmpEq(rd, ra, rb) ⇒ Object

Float Comparisons



806
807
808
809
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 806

def opFCmpEq(rd, ra, rb)
  @gp[rd] = (@fp[ra] == @fp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opFCmpGe(rd, ra, rb) ⇒ Object



831
832
833
834
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 831

def opFCmpGe(rd, ra, rb)
  @gp[rd] = (@fp[ra] >= @fp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opFCmpGt(rd, ra, rb) ⇒ Object



826
827
828
829
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 826

def opFCmpGt(rd, ra, rb)
  @gp[rd] = (@fp[ra] > @fp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opFCmpLe(rd, ra, rb) ⇒ Object



821
822
823
824
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 821

def opFCmpLe(rd, ra, rb)
  @gp[rd] = (@fp[ra] <= @fp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opFCmpLt(rd, ra, rb) ⇒ Object



816
817
818
819
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 816

def opFCmpLt(rd, ra, rb)
  @gp[rd] = (@fp[ra] < @fp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opFCmpNe(rd, ra, rb) ⇒ Object



811
812
813
814
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 811

def opFCmpNe(rd, ra, rb)
  @gp[rd] = (@fp[ra] != @fp[rb]) ? 1 : 0
  set_z(1 - @gp[rd])
end

#opFCos(rd, ra, rb) ⇒ Object



780
781
782
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 780

def opFCos(rd, ra, rb)
  @fp[rd] = Math.cos(@fp[ra])
end

#opFDiv(rd, ra, rb) ⇒ Object



734
735
736
737
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 734

def opFDiv(rd, ra, rb)
  result = @fp[ra] / @fp[rb]
  @fp[rd] = result
end

#opFExp(rd, ra, rb) ⇒ Object



784
785
786
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 784

def opFExp(rd, ra, rb)
  @fp[rd] = Math.exp(@fp[ra])
end

#opFFloor(rd, ra, rb) ⇒ Object



756
757
758
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 756

def opFFloor(rd, ra, rb)
  @fp[rd] = @fp[ra].floor
end

#opFLerp(rd, ra, rb) ⇒ Object



797
798
799
800
801
802
803
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 797

def opFLerp(rd, ra, rb)
  # FP[Rd] = FP[Ra] * t + FP[Rb] * (1-t), with t in Rc
  # Simplified: use FP[Ra] as t, FP[Rb] as base
  t = @fp[ra]
  base = @fp[rb]
  @fp[rd] = base * (1 - t) + base * t
end

#opFLog(rd, ra, rb) ⇒ Object



788
789
790
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 788

def opFLog(rd, ra, rb)
  @fp[rd] = Math.log(@fp[ra])
end

#opFMax(rd, ra, rb) ⇒ Object



772
773
774
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 772

def opFMax(rd, ra, rb)
  @fp[rd] = [@fp[ra], @fp[rb]].max
end

#opFMin(rd, ra, rb) ⇒ Object



768
769
770
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 768

def opFMin(rd, ra, rb)
  @fp[rd] = [@fp[ra], @fp[rb]].min
end

#opFMod(rd, ra, rb) ⇒ Object



739
740
741
742
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 739

def opFMod(rd, ra, rb)
  result = @fp[ra] % @fp[rb]
  @fp[rd] = result
end

#opFMov(rd, rs) ⇒ Object



513
514
515
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 513

def opFMov(rd, rs)
  @fp[rd] = @fp[rs]
end

#opFMul(rd, ra, rb) ⇒ Object



729
730
731
732
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 729

def opFMul(rd, ra, rb)
  result = @fp[ra] * @fp[rb]
  @fp[rd] = result
end

#opFNeg(rd, ra, rb) ⇒ Object



744
745
746
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 744

def opFNeg(rd, ra, rb)
  @fp[rd] = -@fp[ra]
end

#opFRound(rd, ra, rb) ⇒ Object



764
765
766
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 764

def opFRound(rd, ra, rb)
  @fp[rd] = @fp[ra].round
end

#opFSin(rd, ra, rb) ⇒ Object



776
777
778
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 776

def opFSin(rd, ra, rb)
  @fp[rd] = Math.sin(@fp[ra])
end

#opFSqrt(rd, ra, rb) ⇒ Object



752
753
754
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 752

def opFSqrt(rd, ra, rb)
  @fp[rd] = Math.sqrt(@fp[ra])
end

#opFSub(rd, ra, rb) ⇒ Object



724
725
726
727
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 724

def opFSub(rd, ra, rb)
  result = @fp[ra] - @fp[rb]
  @fp[rd] = result
end

#opFToI(rd, ra, rb) ⇒ Object



841
842
843
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 841

def opFToI(rd, ra, rb)
  @gp[rd] = @fp[ra].to_i
end

#opHaltObject

Format A opcodes (1 byte)



430
431
432
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 430

def opHalt
  @state = HALTED
end

#opIAbs(rd, ra, rb) ⇒ Object



632
633
634
635
636
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 632

def opIAbs(rd, ra, rb)
  result = @gp[ra].abs
  set_zn(result)
  @gp[rd] = result
end

#opIAdd(rd, ra, rb) ⇒ Object

Integer Arithmetic (Format C)



594
595
596
597
598
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 594

def opIAdd(rd, ra, rb)
  result = @gp[ra] + @gp[rb]
  set_znv(result)
  @gp[rd] = result
end

#opIAnd(rd, ra, rb) ⇒ Object



650
651
652
653
654
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 650

def opIAnd(rd, ra, rb)
  result = @gp[ra] & @gp[rb]
  set_zn(result)
  @gp[rd] = result
end

#opICmpEq(rd, ra, rb) ⇒ Object

Integer Comparisons



688
689
690
691
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 688

def opICmpEq(rd, ra, rb)
  @gp[rd] = (@gp[ra] == @gp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opICmpGe(rd, ra, rb) ⇒ Object



713
714
715
716
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 713

def opICmpGe(rd, ra, rb)
  @gp[rd] = (@gp[ra] >= @gp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opICmpGt(rd, ra, rb) ⇒ Object



708
709
710
711
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 708

def opICmpGt(rd, ra, rb)
  @gp[rd] = (@gp[ra] > @gp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opICmpLe(rd, ra, rb) ⇒ Object



703
704
705
706
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 703

def opICmpLe(rd, ra, rb)
  @gp[rd] = (@gp[ra] <= @gp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opICmpLt(rd, ra, rb) ⇒ Object



698
699
700
701
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 698

def opICmpLt(rd, ra, rb)
  @gp[rd] = (@gp[ra] < @gp[rb]) ? 1 : 0
  set_z(@gp[rd])
end

#opICmpNe(rd, ra, rb) ⇒ Object



693
694
695
696
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 693

def opICmpNe(rd, ra, rb)
  @gp[rd] = (@gp[ra] != @gp[rb]) ? 1 : 0
  set_z(1 - @gp[rd])
end

#opIDec(rd) ⇒ Object



525
526
527
528
529
530
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 525

def opIDec(rd)
  imm = fetch16
  result = @gp[rd] - imm
  set_znv(result)
  @gp[rd] = result
end

#opIDiv(rd, ra, rb) ⇒ Object

Raises:



612
613
614
615
616
617
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 612

def opIDiv(rd, ra, rb)
  raise DivideByZeroError.new(@pc - 1) if @gp[rb] == 0
  result = @gp[ra] / @gp[rb]
  set_znv(result)
  @gp[rd] = result
end

#opIInc(rd) ⇒ Object

Format D opcodes (4 bytes: opcode + Rd + imm16)



518
519
520
521
522
523
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 518

def opIInc(rd)
  imm = fetch16
  result = @gp[rd] + imm
  set_znv(result)
  @gp[rd] = result
end

#opIMax(rd, ra, rb) ⇒ Object



644
645
646
647
648
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 644

def opIMax(rd, ra, rb)
  result = [@gp[ra], @gp[rb]].max
  set_zn(result)
  @gp[rd] = result
end

#opIMin(rd, ra, rb) ⇒ Object



638
639
640
641
642
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 638

def opIMin(rd, ra, rb)
  result = [@gp[ra], @gp[rb]].min
  set_zn(result)
  @gp[rd] = result
end

#opIMod(rd, ra, rb) ⇒ Object

Raises:



619
620
621
622
623
624
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 619

def opIMod(rd, ra, rb)
  raise DivideByZeroError.new(@pc - 1) if @gp[rb] == 0
  result = @gp[ra] % @gp[rb]
  set_znv(result)
  @gp[rd] = result
end

#opIMov(rd, rs) ⇒ Object



509
510
511
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 509

def opIMov(rd, rs)
  @gp[rd] = @gp[rs]
end

#opIMul(rd, ra, rb) ⇒ Object



606
607
608
609
610
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 606

def opIMul(rd, ra, rb)
  result = @gp[ra] * @gp[rb]
  set_znv(result)
  @gp[rd] = result
end

#opINeg(rd, ra, rb) ⇒ Object



626
627
628
629
630
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 626

def opINeg(rd, ra, rb)
  result = -@gp[ra]
  set_zn(result)
  @gp[rd] = result
end

#opINot(rd, ra, rb) ⇒ Object



681
682
683
684
685
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 681

def opINot(rd, ra, rb)
  result = ~@gp[ra]
  set_zn(result)
  @gp[rd] = result
end

#opIOr(rd, ra, rb) ⇒ Object



656
657
658
659
660
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 656

def opIOr(rd, ra, rb)
  result = @gp[ra] | @gp[rb]
  set_zn(result)
  @gp[rd] = result
end

#opIShl(rd, ra, rb) ⇒ Object



668
669
670
671
672
673
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 668

def opIShl(rd, ra, rb)
  result = @gp[ra] << (@gp[rb] & 31)
  set_z(result)
  set_c((@gp[ra] << (@gp[rb] & 31)) != result ? 1 : 0)
  @gp[rd] = result
end

#opIShr(rd, ra, rb) ⇒ Object



675
676
677
678
679
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 675

def opIShr(rd, ra, rb)
  result = @gp[ra] >> (@gp[rb] & 31)
  set_z(result)
  @gp[rd] = result
end

#opISub(rd, ra, rb) ⇒ Object



600
601
602
603
604
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 600

def opISub(rd, ra, rb)
  result = @gp[ra] - @gp[rb]
  set_znv(result)
  @gp[rd] = result
end

#opIToB(rd, ra, rb) ⇒ Object



849
850
851
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 849

def opIToB(rd, ra, rb)
  @gp[rd] = (@gp[ra] != 0) ? 1 : 0
end

#opIToF(rd, ra, rb) ⇒ Object

Conversions



837
838
839
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 837

def opIToF(rd, ra, rb)
  @fp[rd] = @gp[ra].to_f
end

#opIXor(rd, ra, rb) ⇒ Object



662
663
664
665
666
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 662

def opIXor(rd, ra, rb)
  result = @gp[ra] ^ @gp[rb]
  set_zn(result)
  @gp[rd] = result
end

#opJumpObject

Format G opcodes (variable)



456
457
458
459
460
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 456

def opJump
  length = fetch8
  offset = fetch16
  @pc = @pc &+ offset
end

#opJumpIfObject



462
463
464
465
466
467
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 462

def opJumpIf
  length = fetch8
  rd = fetch8
  offset = fetch16
  @pc = @pc &+ offset if @gp[rd] != 0
end

#opJumpIfNotObject



469
470
471
472
473
474
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 469

def opJumpIfNot
  length = fetch8
  rd = fetch8
  offset = fetch16
  @pc = @pc &+ offset if @gp[rd] == 0
end

#opLoad16(rd, rb) ⇒ Object



546
547
548
549
550
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 546

def opLoad16(rd, rb)
  off = fetchu16
  addr = @gp[rb] + off
  @gp[rd] = read_memory_u16(addr) || 0
end

#opLoad32(rd, rb) ⇒ Object



552
553
554
555
556
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 552

def opLoad32(rd, rb)
  off = fetchu16
  addr = @gp[rb] + off
  @gp[rd] = read_memory_i32(addr) || 0
end

#opLoad64(rd, rb) ⇒ Object



558
559
560
561
562
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 558

def opLoad64(rd, rb)
  off = fetchu16
  addr = @gp[rb] + off
  @gp[rd] = read_memory_u32(addr) || 0
end

#opLoad8(rd, rb) ⇒ Object

Format E opcodes (5 bytes: opcode + Rd + Rbase + off16)



540
541
542
543
544
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 540

def opLoad8(rd, rb)
  off = fetchu16
  addr = @gp[rb] + off
  @gp[rd] = read_memory_u8(addr) || 0
end

#opLoadAddr(rd, rb) ⇒ Object



588
589
590
591
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 588

def opLoadAddr(rd, rb)
  off = fetchu16
  @gp[rd] = @gp[rb] + off
end

#opNopObject



434
435
436
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 434

def opNop
  # No operation
end

#opPanicObject

Raises:



446
447
448
449
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 446

def opPanic
  @state = PANICKED
  raise PanicError.new(pc: @pc - 1)
end

#opPop(rd, rs) ⇒ Object



497
498
499
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 497

def opPop(rd, rs)
  @gp[rd] = pop
end

#opPush(rd, rs) ⇒ Object

Format B opcodes (3 bytes: opcode + Rd + Rs)



493
494
495
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 493

def opPush(rd, rs)
  push(@gp[rs])
end

#opRetObject



438
439
440
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 438

def opRet
  @pc = @gp[LR]
end

#opSizeOf(rd, ra, rb) ⇒ Object



859
860
861
862
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 859

def opSizeOf(rd, ra, rb)
  # Size of type in GP[Ra], result in GP[Rd]
  @gp[rd] = 4  # Default size
end

#opStackAlloc(rd) ⇒ Object

Raises:



532
533
534
535
536
537
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 532

def opStackAlloc(rd)
  size = fetch16
  @sp -= size
  raise FluxRuntimeError, 'Stack overflow' if @sp < 0
  @gp[rd] = @sp
end

#opStore16(rs, rb) ⇒ Object



570
571
572
573
574
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 570

def opStore16(rs, rb)
  off = fetchu16
  addr = @gp[rb] + off
  write_memory(addr, 2, @gp[rs])
end

#opStore32(rs, rb) ⇒ Object



576
577
578
579
580
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 576

def opStore32(rs, rb)
  off = fetchu16
  addr = @gp[rb] + off
  write_memory(addr, 4, @gp[rs])
end

#opStore64(rs, rb) ⇒ Object



582
583
584
585
586
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 582

def opStore64(rs, rb)
  off = fetchu16
  addr = @gp[rb] + off
  write_memory(addr, 8, @gp[rs])
end

#opStore8(rs, rb) ⇒ Object



564
565
566
567
568
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 564

def opStore8(rs, rb)
  off = fetchu16
  addr = @gp[rb] + off
  write_memory(addr, 1, @gp[rs])
end

#opSwap(ra, rb) ⇒ Object



505
506
507
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 505

def opSwap(ra, rb)
  @gp[ra], @gp[rb] = @gp[rb], @gp[ra]
end

#opTypeOf(rd, ra, rb) ⇒ Object



864
865
866
867
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 864

def opTypeOf(rd, ra, rb)
  # Runtime type tag
  @gp[rd] = 0  # Integer type
end

#opUnreachableObject

Raises:



451
452
453
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 451

def opUnreachable
  raise FluxRuntimeError.new('Unreachable instruction executed', opcode: :Unreachable, pc: @pc - 1)
end

#opVAdd(rd, ra, rb) ⇒ Object



921
922
923
924
925
926
927
928
929
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 921

def opVAdd(rd, ra, rb)
  # Component-wise addition
  (0...256).each do |i|
    a = @vr[ra][i].ord
    b = @vr[rb][i].ord
    result = (a + b) & 0xFF
    @vr[rd][i] = result.chr
  end
end

#opVDot(rd, ra, rb) ⇒ Object



941
942
943
944
945
946
947
948
949
950
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 941

def opVDot(rd, ra, rb)
  # Dot product -> scalar in F0
  sum = 0.0
  (0...256).each do |i|
    a = @vr[ra][i].ord
    b = @vr[rb][i].ord
    sum += a * b
  end
  @fp[rd] = sum
end

#opVLoad(rd, rb, off) ⇒ Object

Vector Operations



907
908
909
910
911
912
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 907

def opVLoad(rd, rb, off)
  addr = @gp[rb] + off
  (0...256).each do |i|
    @vr[rd][i] = read_memory_u8(addr + i) || 0
  end
end

#opVMul(rd, ra, rb) ⇒ Object



931
932
933
934
935
936
937
938
939
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 931

def opVMul(rd, ra, rb)
  # Component-wise multiplication
  (0...256).each do |i|
    a = @vr[ra][i].ord
    b = @vr[rb][i].ord
    result = (a * b) & 0xFF
    @vr[rd][i] = result.chr
  end
end

#opVStore(rs, rb, off) ⇒ Object



914
915
916
917
918
919
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 914

def opVStore(rs, rb, off)
  addr = @gp[rb] + off
  @vr[rs].bytes.each_with_index do |byte, i|
    write_memory(addr + i, 1, byte)
  end
end

#opYieldObject



442
443
444
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 442

def opYield
  @state = YIELDED
end

#popObject

Raises:



270
271
272
273
274
275
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 270

def pop
  raise FluxRuntimeError, 'Stack underflow' if @sp >= @memory_size
  val = read_memory_i32(@sp)
  @sp += 4
  val
end

#push(value) ⇒ Object

Stack helpers

Raises:



264
265
266
267
268
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 264

def push(value)
  @sp -= 4
  raise FluxRuntimeError, 'Stack overflow' if @sp < 0
  write_memory(@sp, 4, value)
end

#read_memory(addr, bytes) ⇒ Object

Memory read helpers



168
169
170
171
172
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 168

def read_memory(addr, bytes)
  return nil if addr < 0 || addr + bytes > @memory_size

  (0...bytes).map { |i| @memory[addr + i] }
end

#read_memory_i16(addr) ⇒ Object



201
202
203
204
205
206
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 201

def read_memory_i16(addr)
  return nil if addr < 0 || addr + 2 > @memory_size

  val = (@memory[addr] & 0xFF) | ((@memory[addr + 1] & 0xFF) << 8)
  (val << 16) >> 16  # Sign extend
end

#read_memory_i32(addr) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 180

def read_memory_i32(addr)
  return nil if addr < 0 || addr + 4 > @memory_size

  val = (@memory[addr] & 0xFF) |
        ((@memory[addr + 1] & 0xFF) << 8) |
        ((@memory[addr + 2] & 0xFF) << 16) |
        ((@memory[addr + 3] & 0xFF) << 24)

  # Sign extend
  (val << 24) >> 24
end

#read_memory_u16(addr) ⇒ Object



208
209
210
211
212
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 208

def read_memory_u16(addr)
  return nil if addr < 0 || addr + 2 > @memory_size

  (@memory[addr] & 0xFF) | ((@memory[addr + 1] & 0xFF) << 8)
end

#read_memory_u32(addr) ⇒ Object



192
193
194
195
196
197
198
199
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 192

def read_memory_u32(addr)
  return nil if addr < 0 || addr + 4 > @memory_size

  (@memory[addr] & 0xFF) |
    ((@memory[addr + 1] & 0xFF) << 8) |
    ((@memory[addr + 2] & 0xFF) << 16) |
    ((@memory[addr + 3] & 0xFF) << 24)
end

#read_memory_u8(addr) ⇒ Object



174
175
176
177
178
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 174

def read_memory_u8(addr)
  return nil if addr < 0 || addr >= @memory_size

  @memory[addr] & 0xFF
end

#regsObject

Get register values as hash



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 140

def regs
  {
    pc: @pc,
    sp: @sp,
    fp: @fp_reg,
    flags: @flags,
    state: @state,
    gp: @gp.dup,
    fp_regs: @fp.dup,
    vr: @vr.dup
  }
end

#resetObject

Reset VM state



124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 124

def reset
  @memory = [0] * @memory_size
  @gp = [0] * 16
  @fp = [0.0] * 16
  @vr = Array.new(16) { "\x00" * 256 }
  @pc = 0
  @sp = @memory_size
  @fp_reg = 0
  @flags = 0
  @state = RUNNING
  @cycles = 0
  @instruction_count = 0
  self
end

#run(max_cycles: nil) ⇒ Object

Run the VM until halt/panic/yield or max_cycles reached



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 97

def run(max_cycles: nil)
  @state = RUNNING

  loop do
    break if @state != RUNNING
    break if max_cycles && @cycles >= max_cycles

    step
  end

  self
end

#set_c(result) ⇒ Object



243
244
245
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 243

def set_c(result)
  @flags = (@flags & ~FLAG_C) | (result < 0 ? FLAG_C : 0)
end

#set_s(result) ⇒ Object



239
240
241
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 239

def set_s(result)
  @flags = (@flags & ~FLAG_S) | ((result < 0) ? FLAG_S : 0)
end

#set_v(result) ⇒ Object



247
248
249
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 247

def set_v(result)
  @flags = (@flags & ~FLAG_V) | (result < 0 ? FLAG_V : 0)
end

#set_z(result) ⇒ Object

Flag setting helpers



235
236
237
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 235

def set_z(result)
  @flags = (@flags & ~FLAG_Z) | (result.zero? ? FLAG_Z : 0)
end

#set_zn(result) ⇒ Object



251
252
253
254
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 251

def set_zn(result)
  set_z(result)
  set_s(result)
end

#set_znv(result) ⇒ Object



256
257
258
259
260
261
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 256

def set_znv(result)
  set_z(result)
  set_s(result)
  set_v(result)
  set_c(result)
end

#statsObject

Execution statistics



159
160
161
162
163
164
165
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 159

def stats
  {
    cycles: @cycles,
    instruction_count: @instruction_count,
    memory_used: @pc
  }
end

#stepObject

Execute one instruction

Raises:



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 111

def step
  raise FluxRuntimeError, 'VM not running' unless @state == RUNNING

  opcode = fetch8
  execute_opcode(opcode)

  @instruction_count += 1
  @cycles += 1

  self
end

#write_memory(addr, bytes, value) ⇒ Object

Memory write helpers



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/superinstance/flux-runtime/flux_vm.rb', line 215

def write_memory(addr, bytes, value)
  return if addr < 0 || addr + bytes > @memory_size

  case bytes
  when 1
    @memory[addr] = value & 0xFF
  when 2
    @memory[addr] = value & 0xFF
    @memory[addr + 1] = (value >> 8) & 0xFF
  when 4
    @memory[addr] = value & 0xFF
    @memory[addr + 1] = (value >> 8) & 0xFF
    @memory[addr + 2] = (value >> 16) & 0xFF
    @memory[addr + 3] = (value >> 24) & 0xFF
  when 8
    (0..7).each { |i| @memory[addr + i] = (value >> (i * 8)) & 0xFF }
  end
end