Skip to content

Instantly share code, notes, and snippets.

@Sunjammer
Last active December 10, 2016 23:48
Show Gist options
  • Save Sunjammer/978e35476b694e7337494d01525a887b to your computer and use it in GitHub Desktop.
Save Sunjammer/978e35476b694e7337494d01525a887b to your computer and use it in GitHub Desktop.
VM nonsense for LD
package vm;
enum Instruction
{
LDA(v:Value); //Load value into A
LDX(v:Value); //Load value into X
LDY(v:Value); //Load value into Y
STA(v:Value); //Store A at memory
STX(v:Value); //Store X at memory
STY(v:Value); //Store Y at memory
WRM(pos:Value); //Write A to memory at pos
PHA; //Push A on stack
PLA; //Pull A from stack
TAX; // Copy A to X
TXA; // Copy X to A
TAY; // Copy A to Y
TYA; // Copy Y to A
TXY; // Copy X to Y
TYX; // Copy Y to X
SUB(v:Value); //Subtract value from A
ADD(v:Value); //Add value to A
SLI; //Sleep until interrupt
SLP(v:Value); //Sleep for N cycles
BNE(a:Value, b:Value, pos:Value); //Branch to pos if a != b
BEQ(a:Value, b:Value, pos:Value); //Branch to pos if a == b
BLT(a:Value, b:Value, pos:Value); //Branch to pos if a < b
BGT(a:Value, b:Value, pos:Value); //Branch to pos if a > b
JMP(v:Value); //Set program counter for next instruction
JSR(v:Value); //Begin subroutine
RTS; //Return from subroutine
RTI; //Return from interrupt
AND(v:Value); //& v with A and put the result in A
IOR(v:Value); //| v with A and put the result in A
XOR(v:Value); //^ v with A and put the result in A
LSH(v:Value); //Leftshift A by v and put the result in A
RSH(v:Value); //Rightshift A by v and put the result in A
BRK; //End program
NOP; //No operation
/* Debug stuff */
TRC(v:Dynamic); //Print value
MEM(a:Value, b:Value); //Print memory from A to B
}
package;
import js.Browser;
import js.Lib;
import js.html.Window;
import vm.Assembler;
import vm.Machine;
class Main {
var machines:Array<Machine>;
/**
* Microcontroller spec:
* 8mhz processor
* 512 "bytes" of memory (16 bit ints) :
* 442 : cycle counter
* 443 : accumulator
* 444 : register X
* 445 : register Y
* 446 : program counter
* 447 : stack pointer
* 448-512 : stack (64 bytes)
*
* Read/Write pins by memory address(es) (hardware specific)
* Interrupt handlers are bound by labelled instructions prefixed with IRQ (hardware specific)
*/
/**
* Syntax:
* INSTRUCTION ARG0 ... ARGN
* ;Comment
* alias word value
* label:
* int values only unless TRC which can print a single string
* int value prefix with # is a memory address
* int value prefix with @ is a relative program counter offset
* A, X and Y reference registers/"fastmem"
* A is accumulator, generally used for arithmetic results
*/
static function main() { new Main(); }
public function new() {
var loops = Assembler.assemble("start:
LDA 0 ;while A...
LDX 5 ;less than X...
LDY iter1 ;do iter1
JSR whileloop ;start loop subroutine
LDA 0
LDX 10
LDY iter2
JSR whileloop
JMP end
whileloop:
ADD 1
BGT A X @3
JSR Y
JMP @-3
RTS
iter1:
TRC 1
RTS
iter2:
TRC 2
RTS
end:
TRC Finished
BRK");
var timer = Assembler.assemble("start:
SLP 7994 ;sleep 8k cycles minus cost of following instructions
ADD 1
TRC A
JMP @-3
IRQ0: ; interrupt 0 to stop clock
TRC stop_timer
BRK");
var a = new Machine("Alpha");
a.load(loops);
var b = new Machine("Beta");
b.load(timer);
machines = [a, b];
Browser.window.requestAnimationFrame(update);
}
function update(time:Float) {
var clock = Math.floor(Machine.CLOCK_RATE / 60); //approx cycles per frame
while (clock-- > 0) {
for (m in machines) {
if (m.isRunning()) {
m.next();
if (!m.isRunning()) {
trace(m.name+" is complete");
}
}
}
}
if (machines[1].memory[443] == 10) //check if A-register on Beta is 10
machines[1].interrupt(0);
for (m in machines) {
if (m.isRunning()) {
Browser.window.requestAnimationFrame(update);
return;
}
}
trace("All machines done");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment