81be6a7595/vm/gonga/ngaro.go
Commiter: Charles Childers
Author: Charles Childers
Revision: 81be6a7595
File Size: 4.3 KB
(March 12, 2010 20:49 UTC) About 2 years ago
update gonga (yiyus)
// Original Ngaro Virtual Machine and Uki framework:
// Copyright (C) 2008, 2009, 2010 Charles Childers
// Go port
// Copyright 2009, 2010 JGL
// Public Domain or LICENSE file
/*
Ngaro virtual machines.
Ngaro is a portable virtual machine / emulator for a dual
stack processor and various I/O devices. The instruction set
is concise (31 core instructions), and the basic I/O devices
are kept minimal. For more information see
http://github.com/crcx/ngaro
Communication with the virtual machine is done through
int chanels for input (port 1) and output (port 2). The
port 4 can be used to save the current image to a file,
while port 5 is used to get information about the virtual
machine.
In addition to normal ngaro features, this Go version
allows to launch new cores writing 1 to the port 13. The
new core will start running the same (shared) image
from the address at the top of the stack. Cores communicate
writing and id to port 1 (to receive) and 2 (to send). To
remove a channel write its id to ports 1 and 2 and wait.
Some useful words:
: :go ( a- ) 1 13 out wait ; ( start new core with ip set to a )
: go ( "- ) ' :go ; ( parse a word and run it on a new core )
: ->c ( xy- ) 2 out wait ; ( send x to channel y )
: c-> ( x-y ) 1 out wait 1 in ; ( receive y from channel x )
: delchan ( x- ) dup 1 out 2 out wait ; ( delete channel )
Example:
create ch1 ( It is not needed to create channels, but a )
create ch2 ( good way to get a semi-random new id )
: odd ( - ) 1 repeat dup ch1 ->c 2 + again ;
: even ( - ) 2 repeat dup ch2 ->c 2 + again ;
go odd
go even
ch1 c-> . ch1 c-> . ch1 c-> . ( prints: 1 3 5 )
ch2 c-> . ch2 c-> . ch2 c-> . ( prints: 2 4 6 )
ch1 delchan ( clean up )
ch2 delchan
Usage from go: See gonga.go
*/
package ngaro
const (
// Instruction set
Nop = iota
Lit
Dup
Drop
Swap
Push
Pop
Call
Jump
Return
GtJump
LtJump
NeJump
EqJump
Fetch
Store
Add
Sub
Mul
Dinod
And
Or
Xor
ShL
ShR
ZeroExit
Inc
Dec
In
Out
Wait
stackDepth = 100
chanBuffer = 128
nports = 64
)
type NgaroVM struct {
img []int
dump string
channel map[int]chan int
Input *Input
Output
EndOk chan bool
}
func (vm *NgaroVM) core(ip int) {
var port [nports]int
var sp, rsp int
var tos int
var data, addr [stackDepth + 2]int
sp = 2 // to avoid underflows
for ; ip < len(vm.img); ip++ {
switch vm.img[ip] {
case Nop:
case Lit:
sp++
ip++
data[sp] = vm.img[ip]
case Dup:
sp++
data[sp] = tos
case Drop:
sp--
case Swap:
data[sp], data[sp-1] = data[sp-1], tos
case Push:
rsp++
addr[rsp] = tos
sp--
case Pop:
sp++
data[sp] = addr[rsp]
rsp--
case Call:
ip++
rsp++
addr[rsp] = ip
ip = vm.img[ip] - 1
case Jump:
ip++
ip = vm.img[ip] - 1
case Return:
ip = addr[rsp]
rsp--
case GtJump:
ip++
if data[sp-1] > tos {
ip = vm.img[ip] - 1
}
sp = sp - 2
case LtJump:
ip++
if data[sp-1] < tos {
ip = vm.img[ip] - 1
}
sp = sp - 2
case NeJump:
ip++
if data[sp-1] != tos {
ip = vm.img[ip] - 1
}
sp = sp - 2
case EqJump:
ip++
if data[sp-1] == tos {
ip = vm.img[ip] - 1
}
sp = sp - 2
case Fetch:
data[sp] = vm.img[tos]
case Store:
vm.img[tos] = data[sp-1]
sp = sp - 2
case Add:
data[sp-1] += tos
sp--
case Sub:
data[sp-1] -= tos
sp--
case Mul:
data[sp-1] *= tos
sp--
case Dinod:
data[sp] = data[sp-1] / tos
data[sp-1] = data[sp-1] % tos
case And:
data[sp-1] &= tos
sp--
case Or:
data[sp-1] |= tos
sp--
case Xor:
data[sp-1] ^= tos
sp--
case ShL:
data[sp-1] <<= uint(tos)
sp--
case ShR:
data[sp-1] >>= uint(tos)
sp--
case ZeroExit:
if tos == 0 {
sp--
ip = addr[rsp]
rsp--
}
case Inc:
data[sp]++
case Dec:
data[sp]--
case In:
data[sp] = port[tos]
port[tos] = 0
case Out:
port[0] = 0
port[tos] = data[sp-1]
sp = sp - 2
case Wait:
sp -= vm.wait(&port, tos, ip)
default:
rsp++
addr[rsp] = ip
ip = vm.img[ip] - 1
}
// to avoid segfaults:
if sp < 2 {
sp = 2
}
tos = data[sp]
}
}
func NewVM(img []int, dump string, in *Input, out Output) *NgaroVM {
vm := NgaroVM{
dump: dump,
channel: make(map[int]chan int),
Input: in,
Output: out,
EndOk: make(chan bool),
img: img,
}
go vm.core(0)
return &vm
} |