Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

stack machine emulator in ksh

132 views
Skip to first unread message

hohensee

unread,
Mar 7, 2021, 7:06:43 PM3/7/21
to
# : Hnsm machine stack N Hohensee ; ( Hnsm)

# ksh emulation of 4-stack CPU. About 60 typeable ASCII opcodes.
# needs printf in Bash or in $PATH. Helpers use od, grep...
# 2021 March; most opcodes kinda work
# This program is public domain.
# Rick presidentbyamendment Hohensee.

. ASC.sh

# To get the feel of a semi-typeable machine language, I want Hnsm code
# to be actually binary, and sh just understands C text strings. Binary
# zero is therefor impossible. Gotta have zero. SO, we swap 'z' and
# zero in the ASCII routine. A byte value of 122 is therefor impossible
# in literals. Otherwise, 'z' is a valid opcode. If you really need a
# 122 byte in a literal... figure something out. Other memory will be
# sh integers, which are apparently strings. 0 works. I doubt if
# lacking 122 will be a problem, but be aware that z in a literal is a
# zero.


pc=0 rsp=0x1000 fsp=0x1000 cl=0x100 asp=0x1000 as=0
csp=0x2000 cs=0 lp=0x10 macro=0

fs[$fsp]=0 fs[$fsp-1]=0 fs[$fsp-2]=0 fs[$fsp-3]=0 fs[$fsp-4]=0
fs[$fsp-5]=0 fs[$fsp-6]=0 fs[$fsp-7]=0 fs[$fsp-8]=0 fs[$fsp-9]=0
fs[$fsp-10]=0

S=0 Z=0 C=0 V=0
# settable switches for addressing modes;
# post-pre, naked/writeback, incr/decr
PO=0 WB=0 DN=0

# pointer terminus flag
P=0

boole () (
for i in $*; do
let j=i\&1
echo -n $j" "
done
)


hex () {
printf "%08x " $1
}


hexdual () {
printf "%04x " $1
}


ifhex () {
if test -v $1 ; then
hex 0
else
hex $1
fi
}


ifhexdual () {
if test -v $1 ; then
hexdual 0
else
hexdual $1
fi
}



PIC () {

echo "
"${code:$pc:60}
echo "^
PC Z S C V P PO WB DN "
ifhex $pc
boole $Z
boole $S
boole $C
boole $V
echo -n " "
boole $P
boole $PO
echo -n " "
boole $WB
echo -n " "
boole $DN
echo " loops
return data address lim cnt coproc"
ifhex ${rs[$(($rsp))]}
ifhex ${fs[$fsp]}
ifhex ${as[$asp]}
ifhexdual ${lim[$lp]}
ifhexdual ${lc[$lp]}
echo -n " "
ifhex ${cs[$csp]}
echo
ifhex ${rs[$(($rsp-1))]}
ifhex ${fs[$(($fsp-1))]}
ifhex ${as[$asp-1]}
ifhexdual ${lim[$lp-1]}
ifhexdual ${lc[$lp-1]}
echo -n " "
ifhex ${cs[$(($csp-1))]}
echo
ifhex ${rs[$(($rsp-2))]}
ifhex ${fs[$(($fsp-2))]}
ifhex ${as[$asp-2]}
ifhexdual ${lim[$lp-2]}
ifhexdual ${lc[$lp-2]}
echo -n " "
ifhex ${cs[$csp-2]}
echo
ifhex ${rs[$(($rsp-3))]}
ifhex ${fs[$(($fsp-3))]}
ifhex ${as[$asp-3]}
ifhexdual ${lim[$lp-3]}
ifhexdual ${lc[$lp-3]}
echo -n " "
ifhex ${cs[$(($csp-3))]}
echo
ifhex ${rs[$(($rsp-4))]}
ifhex ${fs[$(($fsp-4))]}
ifhex ${as[$asp-4]}
ifhexdual ${lim[$lp-4]}
ifhexdual ${lc[$lp-4]}
echo -n " "
ifhex ${cs[$(($csp-4))]}
echo
ifhex ${rs[$(($rsp-5))]}
ifhex ${fs[$(($fsp-5))]}
ifhex ${as[$asp-5]}
ifhexdual ${lim[$lp-5]}
ifhexdual ${lc[$lp-5]}
echo -n " "
ifhex ${cs[$csp-5]}
echo
ifhex ${rs[$(($rsp-6))]}
ifhex ${fs[$(($fsp-6))]}
ifhex ${as[$asp-6]}
ifhexdual ${lim[$lp-6]}
ifhexdual ${lc[$lp-6]}
echo -n " "
ifhex ${cs[$csp-6]}
echo
}


NEXT ()
{
wv=${code:$pc:1}
let pc=$pc+1
}


DROP ()
{
let fsp-=1
}


BUMP ()
{
let fsp+=1
}

LIT2 ()
{
NEXT
a=`ASCII $wv`
NEXT
b=`ASCII $wv`
let e=b\<\<8\|a
echo $e
}


LIT4 ()
{
NEXT
a=`ASCII $wv`
NEXT
b=`ASCII $wv`
NEXT
c=`ASCII $wv`
NEXT
d=`ASCII $wv`
let e=$d\<\<24\|$c\<\<16\|$b\<\<8\|$a
echo $e
}


ZEROTEST ()
{
if test ${fs[$fsp]} -eq 0; then
let Z=1
else
let Z=0
fi
}


SIGNTEST ()
{
if test $((${fs[$fsp]}&0x80000000)) -eq 0; then
let S=0
else
let S=1
fi
}




POINTERFLAG ()
{
if test ! ${as[$asp]} ; then
echo "set some pointers"
return 1
fi
if test ${as[$asp]} = ${as[$asp-1]} -o ${as[$asp]} = "0" ; then
let P=0
else
let P=1
fi
}


LOOPTEST ()
{
if test ${lim[$lp]} -eq ${lc[$lp]}; then
let lt=0
else
let lt=1
fi
}


HILOMUL ()
{
let a=0 b=0 c=0 d=0
let a=$1\&0xffff
let b=($1\&0xffffffff)\>\>16
let c=($2\&0xffffffff)\>\>16
let d=$2\&0xffff
let e=a*d
let f=a*c
let g=b*d
let h=b*c
let mid=g+f
let lomid=(mid\<\<16)\&0xffffffff
let himid=mid\>\>16
let lo=lomid+e
let hi=himid+h
}


ATOM ()
{
set -f
case $wv in
" ")
echo "space \"nop\""
;;
"!")
echo "! \"store\""
case $PO$WB$DN in
000)
let mem[${as[$asp]}]=${fs[$fsp]}
;;
001)
let mem[${as[$asp]}]=${fs[$fsp]}
;;
010)
let mem[${as[$asp]}]=${fs[$fsp]}
let as[$asp]+=1
;;
011)
let mem[${as[$asp]}]=${fs[$fsp]}
let as[$asp]-=1
;;
100)
let mem[${as[$asp]}+1]=${fs[$fsp]}
;;
101)
let mem[${as[$asp]}-1]=${fs[$fsp]}
;;
110)
let as[$asp]+=1
let mem[${as[$asp]}]=${fs[$fsp]}

;;
111)
let as[$asp]=${as[$asp]}-1
let mem[${as[$asp]}]=${fs[$fsp]}
;;
esac
DROP
;;

"\"")
echo "\" \"lit\""
BUMP
fs[$fsp]=`LIT4`
let pc+=4
ZEROTEST
SIGNTEST
;;

"#")
echo "# \"comment\""
while test "$wv" != "#"; do
NEXT
done
;;
"$")
echo "$ \"syscall\""
echo $pc $wv
while test "$wv" != "$"; do
NEXT
syscall+=$wv
done
;;
"%")
# A B C --- wide(B*C)>>A Forth */ with a downshift.
# 2 instructions on 386. 1 on Hnsm.
echo "% \"scale\""
a=${fs[$fsp]}
let b=a\|31
let c=32-b
DROP
HILOMUL ${fs[$fsp]} ${fs[$fsp-1]}
let d=lo\>\>b
let e=hi\<\<c
DROP
let fs[$fsp]=d\|e
ZEROTEST
SIGNTEST
;;
"&") echo "& \"and\""
let fs[$fsp-1]\&=${fs[$fsp]}
DROP
ZEROTEST
SIGNTEST
;;
"(")
echo "( \"for/until\""
let lp+=1
lim[$lp]=`LIT2`
let pc+=2
lc[$lp]=`LIT2`
let pc+=2
;;
")")
echo -n ") \"loop\""
LOOPTEST
if test $lt == "1"; then
if test ${lim[$lp]} -eq 0; then
let lc[$lp]-=1\&0xffffffff
echo "for "
else
echo "until"
let lc[$lp]+=1\&0xffffffff
fi
let pc=\(pc-`LIT2`\)\&0xffffffff
else
let lp-=1
fi
;;
"*")
echo "* \"times\""
HILOMUL ${fs[$fsp]} ${fs[$fsp-1]}
let fs[$fsp]=hi
let fs[$fsp-1]=lo
ZEROTEST
SIGNTEST
;;
+)
echo "+ \"plus\""
let fs[$fsp-1]+=${fs[$fsp]}\&0xffffffff
DROP
ZEROTEST
SIGNTEST
;;
,)
echo ", \"nop\""
;;
"'")
echo "\' \"nor\""
let fs[$fsp-1]\|=${fs[$fsp]}
let fs[$fsp-1]=~${fs[$fsp-1]}\&0xffffffff
DROP
ZEROTEST
SIGNTEST
;;
-)
echo "- \"minus\""
let fs[$fsp-1]=\(${fs[$fsp-1]}-${fs[$fsp]}\)\&0xffffffff
DROP
ZEROTEST
SIGNTEST
;;
.)
echo ". \"halt\""
# suspend -f ?
;;
/)
echo "/ \"divmod\""
let a=${fs[$fsp-1]}
let fs[$fsp-1]=${fs[$fsp-1]}/${fs[$fsp]}
let fs[$fsp]=$a%${fs[$fsp]}
ZEROTEST
SIGNTEST
;;
0)
echo "0 \"zero\""
BUMP
let fs[$fsp]=0
Z=1
S=0
;;
1)
echo "1 \"increment\""
let fs[$fsp]+=1
ZEROTEST
SIGNTEST
;;
2)
echo "2 \"times 2\""
if test $((${fs[$fsp]}&0X80000000)) -eq 0; then
let C=0
else
let C=1
fi
let fs[$fsp]=${fs[$fsp]}\<\<1\&0xffffffff
ZEROTEST
SIGNTEST
;;
3)
echo "3 \"div 3\""
let a=0
a=${fs[$fsp]}
BUMP
let fs[$fsp]=$a%3
let fs[$fsp-1]=$a/3
ZEROTEST
SIGNTEST
;;
4) echo "4 nop"
;;
5)
echo "5 \"div 5\""
let a=0
a=${fs[$fsp]}
BUMP
let fs[$fsp]=$a%5
let fs[$fsp-1]=$a/5
ZEROTEST
SIGNTEST
;;
6) echo "6 nop"
;;
7) echo "7 \"jarble\""
# A B --- swap bit B in A with bit 0 in A
# so does nothing if they're the same.
DROP
let j=fs[$fsp+1]\&31
let bn=1\<\<j
let b0=fs[$fsp]\&1
let mask=b0\|bn
let a=\!bn
if test $a -ne $b0 ; then
let fs[$fsp]=v^mask
fi
;;
8) echo nop
;;
9) echo nop
;;
":")
echo ": \"call\""
let rsp+=1
let rs[$rsp]=pc+4
pc=`LIT4`
;;
";")
echo "; \"return\""
let pc=rs[$rsp]
let rsp-=1
;;
"<")
echo "< \"min\""
if test ${fs[$fsp]} -le ${fs[$fsp-1]}; then
let fs[$fsp-1]=${fs[$fsp]}
fi
DROP
ZEROTEST
SIGNTEST
;;
"=")
echo "= \"nexor\""
let fs[$fsp-1]\^=~${fs[$fsp]}\&0xffffffff
DROP
ZEROTEST
SIGNTEST
;;
">")
echo "> \"max\""
if test ${fs[$fsp]} -gt ${fs[$fsp-1]}; then
let fs[$fsp-1]=${fs[$fsp]}
fi
DROP
ZEROTEST
SIGNTEST
;;
"?")
echo "? \"if\""
NEXT
condition=$wv
branch=`LIT2`
let pc+=2
if test $branch -gt $((0x7fff)) ; then
let branch=$((-branch))
fi

case $condition in
Z)
if test $Z = "1"; then
let pc+=$branch
fi
;;
z)
if test $Z = "0"; then
let pc+=$branch
fi
;;
S|N)
if test $S = "1"; then
let pc+=$branch
fi
;;
s|n)
if test $S = "0"; then
let pc+=$branch
fi
;;
C)
if test $C = "1"; then
let pc+=$branch
fi
;;
c)
if test $C = "0"; then
let pc+=$branch
fi
;;
O|V)
if test $V = "1"; then
let pc+=$branch
fi
;;
o|v)
if test $Z = "0"; then
let pc+=$branch
fi
;;
P)
if test $P = "1"; then
let pc+=$branch
fi
;;
p)
if test $P = "0"; then
let pc+=$branch
fi
;;
G|g)
if test $C = "1" -a $Z = "0"; then
let pc+=$branch
fi
;;
L|l)
if test $C = "0" -o $Z = "1"; then
let pc+=$branch
fi
;;
m)
if test $N = $V; then
let pc+=$branch
fi
;;
n)
if test $N != $V; then
let pc+=$branch
fi
;;
q) # skip p and o for use above
if test $Z = "0" -a $N = $V; then
let pc+=$branch
fi
;;
r)
if test $Z = "1" -o $N != $V; then
let pc+=$branch
fi
;;
A)
let pc+=$branch
;;
esac
;;
@)
echo "@ \"fetch\""
BUMP
# pre/wb/dn
case $PO$WB$DN in
000)
let fs[$fsp]=mem[${as[$asp]}]
;;
001)
let fs[$fsp]=mem[${as[$asp]}]
;;
010)
let fs[$fsp]=mem[${as[$asp]}+1]
let as[$asp]+=1
;;
011)
let fs[$fsp]=mem[${as[$asp]}-1]
let as[$asp]-=1
;;
100)
let fs[$fsp]=mem[${as[$asp]+1}]
;;
101)
let fs[$fsp]=mem[${as[$asp]}-1]
;;
110)
let as[$asp]+=1
let fs[$fsp]=mem[${as[$asp]}]
;;
111)
let as[$asp]-=1
let fs[$fsp]=mem[${as[$asp]}]
;;
esac
;;
A)
echo "A \"A mode\""
NEXT
AMODE=$wv
case $wv in
0)
let PO=0 WB=0 DN=0
;;
1)
let PO=0 WB=0 DN=1
;;
2)
let PO=0 WB=1 DN=0
;;
3)
let PO=0 WB=1 DN=1
;;
4)
let PO=1 WB=0 DN=0
;;
5)
let PO=1 WB=0 DN=1
;;
6)
let PO=1 WB=1 DN=0
;;
7)
let PO=1 WB=1 DN=1
;;
esac
;;
B)
echo "B \"revbytes\""
let c=0
let a=fs[$fsp]

let b=a\&255
let c=c\<\<8
let c=c\|b
let a=a\>\>8

let b=a\&255
let c=c\<\<8
let c=c\|b
let a=a\>\>8

let b=a\&255
let c=c\<\<8
let c=c\|b
let a=a\>\>8

let b=a\&255
let c=c\<\<8
let c=c\|b
let fs[$fsp]=$c
ZEROTEST
SIGNTEST

;;
C)
echo "C \"copro\""
while test "$wv" != "C"; do
NEXT
done
;;
D)
echo "D \"dupe\""
BUMP
let fs[$fsp]=${fs[$fsp-1]}
;;
E) echo nop
;;
F) echo nop
;;
G)
echo "G \"go to\""
let pc=`LIT4`
;;
H) echo nop
;;
I) echo nop
;;
J)
echo "J \"jump V\""
let pc=${fs[$fsp]}
DROP
;;
K)
echo nop
;;
L)
echo "L \"macro if\""
# ? in an M...M, 1 byte condition, 1 byte signed branch
NEXT
condition=$wv
NEXT
let branch=$wv
if test $((128&$branch)) -eq 128 ; then
let branch=$((0-$branch)) # signed byte
fi
case $condition in
Z)
if test $Z = "1"; then
let mpc+=$branch
fi
;;
z)
if test $Z = "0"; then
let mpc+=$branch
fi
;;
S|N)
if test $S = "1"; then
let mpc+=$branch
fi
;;
s|n)
if test $S = "0"; then
let mpc+=$branch
fi
;;
C)
if test $C = "1"; then
let mpc+=$branch
fi
;;
c)
if test $C = "0"; then
let mpc+=$branch
fi
;;
O|V)
if test $V = "1"; then
let mpc+=$branch
fi
;;
o|v)
if test $Z = "0"; then
let mpc+=$branch
fi
;;
P)
if test $P = "1"; then
let mpc+=$branch
fi
;;
p)
if test $P = "0"; then
let mpc+=$branch
fi
;;
G|g)
if test $C = "1" -a $Z = "0"; then
let mpc+=$branch
fi
;;
L|l)
if test $C = "0" -o $Z = "1"; then
let mpc+=$branch
fi
;;
m)
if test $N = $V; then
let mpc+=$branch
fi
;;
n)
if test $N != $V; then
let mpc+=$branch
fi
;;
q) # skip p and o for use above
if test $Z = "0" -a $N = $V; then
let mpc+=$branch
fi
;;
r)
if test $Z = "1" -o $N != $V; then
let mpc+=$branch
fi
;;
A)
let mpc+=$branch
;;
esac
;;
M)
echo "M \"macro\""
NEXT
a=`ASCII $wv`
while test "$wv" != "M"; do
molecule[$a]+=$wv
NEXT
done
;;
N) echo "N \"nip\""
DROP
let fs[$fsp]=${fs[$fsp+1]}
ZEROTEST
SIGNTEST
;;
O)
echo "O \"over\""
BUMP
let fs[$fsp]=${fs[$fsp-2]}
ZEROTEST
SIGNTEST
;;
P) echo nop
;;
Q) echo nop
;;
R)
echo "R \"ratchet\""
let asp+=1
let as[$asp]=${mem[${as[$asp-1]}]}
POINTERFLAG
;;
S)
echo "S \"swap\""
let a=0
let a=${fs[$fsp]}
let fs[$fsp]=${fs[$fsp-1]}
let fs[$fsp-1]=$a
ZEROTEST
SIGNTEST
;;
T) echo "T \"true\""
BUMP
let Z=0
let S=1
let fs[$fsp]=0xffffffff
;;
U) echo nop
;;
V)
echo "V \"value\""
SIGNTEST
if test $S = 1 ; then
let fs[$fsp]=~fs[$fsp]+1\&0xffffffff
fi
ZEROTEST
S=0
;;
W) echo "W \"nop\""
;;
X)
echo "X \"extend dual\""
if test $((0x8000&${fs[$fsp]})) -eq $((0x8000)) ; then
let fs[$fsp]=fs[$fsp]\|0xffff0000
fi
SIGNTEST
ZEROTEST
;;
Y)
echo "Y \"yank\""
let as[$asp]=mem[as[$asp]]
POINTERFLAG
;;
Z) echo nop
;;
"[")
echo "[ \"upshift\""
let fs[$fsp-1]=fs[$fsp-1]\<\<fs[$fsp]\&0xffffffff
DROP
ZEROTEST
SIGNTEST
;;
"\\")
echo "\\ \"ADC\""
let ADCA=fs[$fsp]
let ADCB=fs[$fsp-1]
let ADCAL=ADCA\&0XFFFF
let ADCBL=ADCB\&0XFFFF
let ADCAH=ADCA\>\>16
let ADCBH=ADCB\>\>16
let ADCSL=(ADCAL+ADCBL+C)\&0xffff
let ADCSLC=(ADCAL+ADCBL+C)\>\>16
let ADCHS=(ADCAH+ADCBH+ADCSLC)\&0xffff
let ADCCF=(ADCAH+ADCBH+ADCSLC)\>\>16
let ADCSUM=ADCSL+\(ADCHS\<\<16\)
let fs[$fsp]=$ADCSUM
ZEROTEST
SIGNTEST
# needs to propagate a carry if there is one
;;
"]")
echo "] \"downshift\""
let fs[$fsp-1]=fs[$fsp-1]\>\>fs[$fsp]
DROP
ZEROTEST
SIGNTEST
;;
"^")
echo "^ \"exor\""
let fs[$fsp-1]=${fs[$fsp]}^fs[$fsp-1]
DROP
ZEROTEST
SIGNTEST
;;
_)
echo "_ \"sinum\""
let fs[$fsp-1]=fs[$fsp]-fs[$fsp-1]\&0xffffffff
DROP
ZEROTEST
SIGNTEST
;;
"\`")
echo "\` \"nand\""
let let fs[$fsp-1]\&=${fs[$fsp]}
DROP
let fs[$fsp]=~fs[$fsp]\&0xffffffff
ZEROTEST
SIGNTEST
;;
a)
echo "a \"a-drop\""
let asp+=-1
POINTERFLAG
;;
b) echo "b \"bitpop\""
BUMP
let fs[$fsp]=0
let a=fs[$fsp-1]
while test $a -ne 0; do
let fs[$fsp]+=a\&1
let a/=2;
done
;;
c) echo nop
;;
d)
echo "d \"drop\""
DROP
ZEROTEST
SIGNTEST
;;
e) echo nop
;;
f) echo nop
;;
g) echo nop
;;
h) echo nop
;;
i)
echo "i \"eye\""
# push current loop count to TOS
BUMP
let fs[$fsp]=lc[$lp]
ZEROTEST
;;
j) echo "j nop"
;;
k) echo "k nop"
;;
l) echo nop
;;
m) echo nop
;;
n) echo nop
;;
o) echo nop
;;
p) echo nop
;;
q) echo nop
;;
r) echo nop
;;
s) echo "s \"sub b\""
let fs[$fsp-1]=\(${fs[$fsp-1]}-${fs[$fsp]}-$C\)\&0xffffffff
DROP
ZEROTEST
SIGNTEST

;;
t)
echo "t \"trans\""
NEXT
let b=wv\&15
case $b in
0) let a=rsp ;;
1) let a=sp ;;
2) let a=rs[$rsp]
let rsp-=1 ;;
3) let a=fs[$fsp]
let fsp-=1 ;;
4) let a=as[$asp]
let asp-=1 ;;
5) let a=asp ;;
6) let a=ls[$lsp]
let lsp-=1 ;;
7) let a=lsp ;;
8) let a=cs[$csp]
let csp-=1 ;;
9) let a=csp ;;
10) let a=PO ;;
11) let a=WB ;;
12) let a=DN ;;
13) let unimplemented=1 ;;
14) let unimplemented=1 ;;
15) let a=pc ;;
esac
let b=wv\>\>4
case $b in
0) let rsp=a ;;
1) BUMP
let fs[$fsp]=a ;;
2) let rsp+=1
let rs[$rsp]=a ;;
3) let fsp+=1
let fs[$fsp]=a ;;
4) let asp+=1
let as[$asp]=a ;;
5) let asp=a ;;
6) let to/lim\to/cnt ;;
7) let lsp+=1
let ls[$lsp]=a ;;
8) LET csp+=1
let cs[$csp]=a ;;
9) let csp=a ;;
10) let PO=a\&1 ;;
11) let WB=a\&1 ;;
12) let DN=a\&1 ;;
13) let unimplemented=1 ;;
14) let unimplemented=1 ;;
15) let pc=a ;;
esac
;;
u) echo nop
;;
v) echo nop
;;
w) echo nop
;;
x)
echo "x \"extend byte\""
if test $((128&${fs[$fsp]})) -eq 128 ; then
let fs[$fsp]=${fs[$fsp]}\|0xffffff00
fi
SIGNTEST
ZEROTEST
;;
y) echo nop
;;
z) echo "z \"mac z\""
# branch if TOS !0
if test $Z -eq 0 ; then
let mpc=0
fi
;;
"{") echo "{ \"roll\""
let a=fs[$fsp-1]\<\<fs[$fsp]\&0xffffffff
let b=fs[$fsp-1]\>\>\(32-fs[$fsp]\)
let fs[$fsp-1]=a\|b
DROP
SIGNTEST
;;
"|")
echo "| \"or\""
let fs[$fsp-1]\|=${fs[$fsp]}
DROP
ZEROTEST
SIGNTEST
;;
"}") echo "} \"eggroll\""
SIGNTEST
let bit0=S
let C=S
let fs[$fsp]=fs[$fsp]\<\<1\|bit0\&0xffffffff

;;
"~")
echo "~ \"not\""
let fs[$fsp]=~${fs[$fsp]}\&0xffffffff
ZEROTEST
SIGNTEST
;;
esac
set +f
}


IPL () { # initial load binary program file to $code
# Be sure file ends with a newline. TWICE in asm.sh does that once.
code= COUNT=0
REPLY=
while read ; do
code=$code$REPLY
let COUNT+=1
done
echo ${#code} $COUNT
echo "echo \$code if you're curious."
}


MEXT ()
{
let mpc+=1
wv=${mcode:$mpc:1}
}


MOLECULE () {
mpc=0
mcode=${molecule[$a]}
echo ${molecule[$a]}
while
MEXT
test -n $wv -a $wv != M ;do
ATOM
done
}


OPCODE ()
{
a=`ASCII $1`
if test ${molecule[$a]} ; then
MOLECULE
else
ATOM
fi
}


STEP () {
NEXT ; OPCODE $wv ; PIC
}


STEPS () {
while read
do
pc=0
code=$REPLY
aaaa=${#code}
while test $pc -le $aaaa ; do
OPCODE
NEXT
done
PIC
done
}


SALT () {
molecule[68]="kjnk\@\#\$\%\6\%\^\&\*\(\)\-\_+=jnkjnM"
molecule[65]="kj;;;;;;;;,,,,,,,,,,,M"
molecule[66]="kjnlxxsfflkjkjnM"

wv=1

rs[$rsp]=0
fs[$fsp]=0
as[$asp]=0
cs[$csp]=0
lim[$lp]=0
lc[$lp]=333
rs[$rsp-1]=2
fs[$fsp-1]=22
fs[$fsp-2]=22
fs[$fsp-3]=22
fs[$fsp-5]=22
fs[$fsp-4]=2
fs[$fsp-6]=2
fs[$fsp-7]=2
as[$asp-1]=222
cs[$csp-1]=2222
lim[$lp-1]=22222
lc[$lp-1]=0

pc=0

code=120812ffggzzxx92384MkdbcsHBEDEEMMMM


echo "code "$code
echo "pc "$pc " wv "$wv " mpc "$mpc
}


LIST () {
grep \"\" vm.sh
}

# getting started:$ . vm.sh $ LIST $ SALT; PIC; STEP; STEP;...

hohensee

unread,
Mar 7, 2021, 7:12:20 PM3/7/21
to
# unix thinks this is a binary file.
# Probably should remain detached from other scriptage.
# see the hack alert appended at the end

ASCII () {
case $1 in
" ") echo 0 ;; # it's here, but it's impossible in a C string
" ") echo 1 ;;
" ") echo 2 ;;
" ") echo 3 ;;
" ") echo 4 ;;
" ") echo 5 ;;
" ") echo 6 ;;
" ") echo 7 ;;
" ") echo 8 ;;
" ") echo 9 ;;
"
") echo 10 ;;
" ") echo 11 ;;
" ") echo 12 ;;
"
") echo 13 ;;
" ") echo 14 ;;
" ") echo 15 ;;
" ") echo 16 ;;
" ") echo 17 ;;
" ") echo 18 ;;
" ") echo 19 ;;
" ") echo 20 ;;
" ") echo 21 ;;
" ") echo 22 ;;
" ") echo 23 ;;
" ") echo 24 ;;
" ") echo 25 ;;
" ") echo 26 ;;
" ") echo 27 ;;
" ") echo 28 ;;
" ") echo 29 ;;
" ") echo 30 ;;
" ") echo 31 ;;

" ") echo 32 ;;
"!") echo 33 ;;
"\"") echo 34 ;;
"#") echo 35 ;;
"$") echo 36 ;;
"%") echo 37 ;;
"&") echo 38 ;;
"'") echo 39 ;;
"(") echo 40 ;;
")") echo 41 ;;
"*") echo 42 ;;
"+") echo 43 ;;
",") echo 44 ;;

"-") echo 45 ;;
".") echo 46 ;;
"/") echo 47 ;;
"0") echo 48 ;;
"1") echo 49 ;;
"2") echo 50 ;;
"3") echo 51 ;;
"4") echo 52 ;;
"5") echo 53 ;;
"6") echo 54 ;;
"7") echo 55 ;;
"8") echo 56 ;;
"9") echo 57 ;;
":") echo 58 ;;
";") echo 59 ;;
"<") echo 60 ;;
"=") echo 61 ;;
">") echo 62 ;;
"?") echo 63 ;;
"@") echo 64 ;;
"A") echo 65 ;;
"B") echo 66 ;;
"C") echo 67 ;;
"D") echo 68 ;;
"E") echo 69 ;;
"F") echo 70 ;;
"G") echo 71 ;;
"H") echo 72 ;;
"I") echo 73 ;;
"J") echo 74 ;;
"K") echo 75 ;;
"L") echo 76 ;;
"M") echo 77 ;;
"N") echo 78 ;;
"O") echo 79 ;;
"P") echo 80 ;;
"Q") echo 81 ;;
"R") echo 82 ;;
"S") echo 83 ;;
"T") echo 84 ;;
"U") echo 85 ;;
"V") echo 86 ;;
"W") echo 87 ;;
"X") echo 88 ;;
"Y") echo 89 ;;
"Z") echo 90 ;;
"[") echo 91 ;;
"\\") echo 92 ;;
"]") echo 93 ;;
"^") echo 94 ;;
"_") echo 95 ;;
"\`") echo 96 ;;

"a") echo 97 ;;
"b") echo 98 ;;
"c") echo 99 ;;
"d") echo 100 ;;
"e") echo 101 ;;
"f") echo 102 ;;
"g") echo 103 ;;
"h") echo 104 ;;
"i") echo 105 ;;
"j") echo 106 ;;
"k") echo 107 ;;
"l") echo 108 ;;
"m") echo 109 ;;
"n") echo 110 ;;
"o") echo 111 ;;
"p") echo 112 ;;
"q") echo 113 ;;
"r") echo 114 ;;
"s") echo 115 ;;
"t") echo 116 ;;
"u") echo 117 ;;
"v") echo 118 ;;
"w") echo 119 ;;
"x") echo 120 ;;
"y") echo 121 ;;

"z") echo 0 ;; # HACK ALERT HACK A LERT

"{") echo 123 ;;
"|") echo 124 ;;
"}") echo 125 ;;
"~") echo 126 ;;
" ") echo 127 ;;

"�") echo 128 ;;
"�") echo 129 ;;
"�") echo 130 ;;
"�") echo 131 ;;
"�") echo 132 ;;
"�") echo 133 ;;
"�") echo 134 ;;
"�") echo 135 ;;
"�") echo 136 ;;
"�") echo 137 ;;
"�") echo 138 ;;
"�") echo 139 ;;
"�") echo 140 ;;
"�") echo 141 ;;
"�") echo 142 ;;
"�") echo 143 ;;
"�") echo 144 ;;
"�") echo 145 ;;
"�") echo 146 ;;
"�") echo 147 ;;
"�") echo 148 ;;
"�") echo 149 ;;
"�") echo 150 ;;
"�") echo 151 ;;
"�") echo 152 ;;
"�") echo 153 ;;
"�") echo 154 ;;
"�") echo 155 ;;
"�") echo 156 ;;
"�") echo 157 ;;
"�") echo 158 ;;
"�") echo 159 ;;
"�") echo 160 ;;
"�") echo 161 ;;
"�") echo 162 ;;
"�") echo 163 ;;
"�") echo 164 ;;
"�") echo 165 ;;
"�") echo 166 ;;
"�") echo 167 ;;
"�") echo 168 ;;
"�") echo 169 ;;
"�") echo 170 ;;
"�") echo 171 ;;
"�") echo 172 ;;
"�") echo 173 ;;
"�") echo 174 ;;
"�") echo 175 ;;
"�") echo 176 ;;
"�") echo 177 ;;
"�") echo 178 ;;
"�") echo 179 ;;
"�") echo 180 ;;
"�") echo 181 ;;
"�") echo 182 ;;
"�") echo 183 ;;
"�") echo 184 ;;
"�") echo 185 ;;
"�") echo 186 ;;
"�") echo 187 ;;
"�") echo 188 ;;
"�") echo 189 ;;
"�") echo 190 ;;
"�") echo 191 ;;
"�") echo 192 ;;
"�") echo 193 ;;
"�") echo 194 ;;
"�") echo 195 ;;
"�") echo 196 ;;
"�") echo 197 ;;
"�") echo 198 ;;
"�") echo 199 ;;
"�") echo 200 ;;
"�") echo 201 ;;
"�") echo 202 ;;
"�") echo 203 ;;
"�") echo 204 ;;
"�") echo 205 ;;
"�") echo 206 ;;
"�") echo 207 ;;
"�") echo 208 ;;
"�") echo 209 ;;
"�") echo 210 ;;
"�") echo 211 ;;
"�") echo 212 ;;
"�") echo 213 ;;
"�") echo 214 ;;
"�") echo 215 ;;
"�") echo 216 ;;
"�") echo 217 ;;
"�") echo 218 ;;
"�") echo 219 ;;
"�") echo 220 ;;
"�") echo 221 ;;
"�") echo 222 ;;
"�") echo 223 ;;
"�") echo 224 ;;
"�") echo 225 ;;
"�") echo 226 ;;
"�") echo 227 ;;
"�") echo 228 ;;
"�") echo 229 ;;
"�") echo 230 ;;
"�") echo 231 ;;
"�") echo 232 ;;
"�") echo 233 ;;
"�") echo 234 ;;
"�") echo 235 ;;
"�") echo 236 ;;
"�") echo 237 ;;
"�") echo 238 ;;
"�") echo 239 ;;
"�") echo 240 ;;
"�") echo 241 ;;
"�") echo 242 ;;
"�") echo 243 ;;
"�") echo 244 ;;
"�") echo 245 ;;
"�") echo 246 ;;
"�") echo 247 ;;
"�") echo 248 ;;
"�") echo 249 ;;
"�") echo 250 ;;
"�") echo 251 ;;
"�") echo 252 ;;
"�") echo 253 ;;
"�") echo 254 ;;
"�") echo 255 ;;
esac


}

# THIS PROGRAM DOESN'T WORK 100%
#
# You can emit any byte value in the shell with echo -e.
# Inputting any byte, not so much. The shell has no BASIC
# ASC function.
#
# FURTHERMORE, Shell strings drop zeroes and adjacent whitespace.
# Strings are 0-delimited in unix. And the shell. including
# all variables apparently.
#
# So the shell can't even read a zero byte out of a file
# into a string.
#
# As Hnsm is written, this is only a problem for literals.
# This is not why there's a 0 instruction, but it helps.
#
# For single digit values like the A address mode flags we
# use ASCII numbers.
#
# Otherwise, check for z in literals, and call that zero.
# 0x7a. Decimal 122. EXEC needs to do that. The assembler
# needs to do the converse; convert literal 0 bytes to
# 'z'.
#
# AB can maybe convert 0x00 to z. LITAB it is.
#
# Why do you need a byte value of 122 in a literal? You
# don't. OK, off we go. ARM doesn't even have a 32 bit
# literal. SO there.
#
# Check for 122 in literals and scream like a banshee.
#
# Did I mention that I don't like nul-terminated strings?
# Even when I'm not writing a CPU in Bash. Nasty
# implementation hack, 'nul' terminated strings. Yick. C
# strings should be Forth 'words'.
#

hohensee

unread,
Mar 7, 2021, 7:17:52 PM3/7/21
to
# the assembler SO far


AB () { #> this is how to bang bits in sh. assemble byte.
#> AB byte [byte byte...]
for i in $*
do
echo -en "${oct[$i]}" >> a.out
let HERE+=1
done
}


LITAB () { #> heinous hack to use a shell string as code memory
#> and still be able to have literal zeros.
# Decimal value 122, 0x7a, 'z' is thus impossible
# instead of 0. This is the price of CPU emulation
# in sh.
for i in $*
do
if test $i == 0 ; then
i=122
echo "literal 0 byte being converted to 122/0x7a/z"
fi
echo -en "${oct[$i]}" >> a.out
let HERE+=1
done
}


oct[0]="\00" oct[1]="\01" oct[2]="\02" oct[3]="\03" oct[4]="\04"
oct[5]="\05" oct[6]="\06" oct[7]="\07" oct[8]="\010" oct[9]="\011"
oct[10]="\012" oct[11]="\013" oct[12]="\014" oct[13]="\015" oct[14]="\016"
oct[15]="\017" oct[16]="\020" oct[17]="\021" oct[18]="\022" oct[19]="\023"
oct[20]="\024" oct[21]="\025" oct[22]="\026" oct[23]="\027" oct[24]="\030"
oct[25]="\031" oct[26]="\032" oct[27]="\033" oct[28]="\034" oct[29]="\035"
oct[30]="\036" oct[31]="\037" oct[32]="\040" oct[33]="\041" oct[34]="\042"
oct[35]="\043" oct[36]="\044" oct[37]="\045" oct[38]="\046" oct[39]="\047"
oct[40]="\050" oct[41]="\051" oct[42]="\052" oct[43]="\053" oct[44]="\054"
oct[45]="\055" oct[46]="\056" oct[47]="\057" oct[48]="\060" oct[49]="\061"
oct[50]="\062" oct[51]="\063" oct[52]="\064" oct[53]="\065" oct[54]="\066"
oct[55]="\067" oct[56]="\070" oct[57]="\071" oct[58]="\072" oct[59]="\073"
oct[60]="\074" oct[61]="\075" oct[62]="\076" oct[63]="\077"
oct[64]="\0100" oct[65]="\0101" oct[66]="\0102" oct[67]="\0103"
oct[68]="\0104" oct[69]="\0105" oct[70]="\0106" oct[71]="\0107"
oct[72]="\0110" oct[73]="\0111" oct[74]="\0112" oct[75]="\0113"
oct[76]="\0114" oct[77]="\0115" oct[78]="\0116" oct[79]="\0117"
oct[80]="\0120" oct[81]="\0121" oct[82]="\0122" oct[83]="\0123"
oct[84]="\0124" oct[85]="\0125" oct[86]="\0126" oct[87]="\0127"
oct[88]="\0130" oct[89]="\0131" oct[90]="\0132" oct[91]="\0133"
oct[92]="\0134" oct[93]="\0135" oct[94]="\0136" oct[95]="\0137"
oct[96]="\0140" oct[97]="\0141" oct[98]="\0142" oct[99]="\0143"
oct[100]="\0144" oct[101]="\0145" oct[102]="\0146" oct[103]="\0147"
oct[104]="\0150" oct[105]="\0151" oct[106]="\0152" oct[107]="\0153"
oct[108]="\0154" oct[109]="\0155" oct[110]="\0156" oct[111]="\0157"
oct[112]="\0160" oct[113]="\0161" oct[114]="\0162" oct[115]="\0163"
oct[116]="\0164" oct[117]="\0165" oct[118]="\0166" oct[119]="\0167"
oct[120]="\0170" oct[121]="\0171" oct[122]="\0172" oct[123]="\0173"
oct[124]="\0174" oct[125]="\0175" oct[126]="\0176" oct[127]="\0177"
oct[128]="\0200" oct[129]="\0201" oct[130]="\0202" oct[131]="\0203"
oct[132]="\0204" oct[133]="\0205" oct[134]="\0206" oct[135]="\0207"
oct[136]="\0210" oct[137]="\0211" oct[138]="\0212" oct[139]="\0213"
oct[140]="\0214" oct[141]="\0215" oct[142]="\0216" oct[143]="\0217"
oct[144]="\0220" oct[145]="\0221" oct[146]="\0222" oct[147]="\0223"
oct[148]="\0224" oct[149]="\0225" oct[150]="\0226" oct[151]="\0227"
oct[152]="\0230" oct[153]="\0231" oct[154]="\0232" oct[155]="\0233"
oct[156]="\0234" oct[157]="\0235" oct[158]="\0236" oct[159]="\0237"
oct[160]="\0240" oct[161]="\0241" oct[162]="\0242" oct[163]="\0243"
oct[164]="\0244" oct[165]="\0245" oct[166]="\0246" oct[167]="\0247"
oct[168]="\0250" oct[169]="\0251" oct[170]="\0252" oct[171]="\0253"
oct[172]="\0254" oct[173]="\0255" oct[174]="\0256" oct[175]="\0257"
oct[176]="\0260" oct[177]="\0261" oct[178]="\0262" oct[179]="\0263"
oct[180]="\0264" oct[181]="\0265" oct[182]="\0266" oct[183]="\0267"
oct[184]="\0270" oct[185]="\0271" oct[186]="\0272" oct[187]="\0273"
oct[188]="\0274" oct[189]="\0275" oct[190]="\0276" oct[191]="\0277"
oct[192]="\0300" oct[193]="\0301" oct[194]="\0302" oct[195]="\0303"
oct[196]="\0304" oct[197]="\0305" oct[198]="\0306" oct[199]="\0307"
oct[200]="\0310" oct[201]="\0311" oct[202]="\0312" oct[203]="\0313"
oct[204]="\0314" oct[205]="\0315" oct[206]="\0316" oct[207]="\0317"
oct[208]="\0320" oct[209]="\0321" oct[210]="\0322" oct[211]="\0323"
oct[212]="\0324" oct[213]="\0325" oct[214]="\0326" oct[215]="\0327"
oct[216]="\0330" oct[217]="\0331" oct[218]="\0332" oct[219]="\0333"
oct[220]="\0334" oct[221]="\0335" oct[222]="\0336" oct[223]="\0337"
oct[224]="\0340" oct[225]="\0341" oct[226]="\0342" oct[227]="\0343"
oct[228]="\0344" oct[229]="\0345" oct[230]="\0346" oct[231]="\0347"
oct[232]="\0350" oct[233]="\0351" oct[234]="\0352" oct[235]="\0353"
oct[236]="\0354" oct[237]="\0355" oct[238]="\0356" oct[239]="\0357"
oct[240]="\0360" oct[241]="\0361" oct[242]="\0362" oct[243]="\0363"
oct[244]="\0364" oct[245]="\0365" oct[246]="\0366" oct[247]="\0367"
oct[248]="\0370" oct[249]="\0371" oct[250]="\0372" oct[251]="\0373"
oct[252]="\0374" oct[253]="\0375" oct[254]="\0376" oct[255]="\0377"

# That's how you send a binary byte to a file in ksh/bash,
# or without the -e in dash

LEAQ () { #> little endian quad AB as binary bytes
let f=$1\&255
AB $f
let f=$1\>\>8
let f=$f\&255
AB $f
let f=$1\>\>16
let f=$f\&255
AB $f
let f=$1\>\>24
# signed. far out. so mask it.
let f=$f\&255
AB $f
}


LITLEAQ () { #> little endian quad AB as binary bytes
let f=$1\&255
LITAB $f
let f=$1\>\>8
let f=$f\&255
LITAB $f
let f=$1\>\>16
let f=$f\&255
LITAB $f
let f=$1\>\>24
# signed. far out. so mask it.
let f=$f\&255
LITAB $f
}


# and while we're HERE...
BEAQ () { #> big endian quad AB as binary bytes
let f=$1\>\>24 # signed. far out. so mask it.
let f=$f\&255
AB $f
f=$1\>\>16
let f=$f\&255
AB $f
let f=$1\>\>8
let f=$f\&255
AB $f
let f=$1\&255
AB $f
}


# LEAQ blows up if $1 is null.
# Ain't worth a if.


LEAD () { #> little endian quad AB as binary bytes
let f=$1\&255
AB $f
let f=$1\>\>8
let f=$f\&255
AB $f
}

LITLEAD () { #> little endian quad AB as binary bytes
let f=$1\&255
LITAB $f
let f=$1\>\>8
let f=$f\&255
LITAB $f
}


HO () { #> hexdump ./a.out. Single hex bytes. No endian swapping.
echo "\$HERE is " $HERE
od -t x1z -Ax a.out
}



homp () { # homp chomp is homp
echo ${1:1:100}
}


chom () { # chom "chomp" returns "chom"
echo ${1:0:${1}-1}
}


bigpic () {
echo "3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0"
echo "1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0"
}


bp () (
pic=""
qut=$1
for bla in 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3
do
let bit=1\&$qut
pic=$bit" "$pic
let qut=$qut\>\>1
done
bigpic
echo $pic
)


# assembler for Hnsm specifically
# Feb 2021


V () { # append ASCII VVVVVVerbatim. Like a "text" directive?
set -f
a=$1
b=${#1}
let HERE+=$b
echo -n $a >> a.out
set +f
}


IF () { #> IF condition # then do a ;RESOLVE $label
V "\?"
##########################################
case $1 in
Z) V Z
;;
ZC|z) V z
;;
S|N) V S
;;
SC|NC|s) V s
;;
C) V C
;;
CC|cc|c) V c
;;
O|V) V V
;;
v|o|OC|VC) V v
;;
P) V P
;;
p|PZ|PT|PC) V p
;;
G|GT|gt) V G
;;
l|L|LE|LTE) V L
;;
m|SGE|SGTE) V m
;;
n|SLT|SL) V n
;;
q|SG|SGT) V q
;;
r|SLE|SLTE) V r
;;
A) V A
;;
esac
}


RESOLVE () { #> This assembles a PC-relative branch o/s dual
let foo=$1-$HERE
LITLEAD $foo
}


AMODE () { #> ASSEMBLE addressing mode
# ASCII 0<->7 = POST/PRE NAKED/WRITEBACK UP/DOWN
let f=0x30
for a in $*
do
case $a in
"100"|4|higher|cdr)
let f=0x34
;;
"101"|5|lower|c3r)
let f=0x35
;;
0|1| direct | post|up|UP|car)
;;
pre)
let f=f\|4
;;
"010"|2| WB|writeback|index|indexed |C++)
let f=f\|2
;;
down | DN | dn )
let f=f\|1
;;
"011"|3|"C--")
let f=0x33
;;
"111"|7|"--C")
let f=0x37
;;
"110"|6|"++C")
let f=0x36
esac
done
echo -en "A"${oct[$f]} >> a.out
}


FOR () { #> same opcode as UNTIL, assemble a loop init
#> At runtime ( pushes the following duals onto LS, ++LSC
echo -n "(" >> a.out
let HERE+=1
LEAD $1
AB 122 122 # will be converted to zeroes
let lOoP=HERE
}


UNTIL () { #> same opcode as FOR, assemble a loop init
#> At runtime ( pushes the following duals onto LS, ++LSC
echo -n "(" >> a.out
let HERE+=1
AB 122 122
LEAD $1
let lOoP=HERE
}

# assemble general transfer insn suffix byte
# TRANS src dest

TRANS ()
(
case $1 in
rsp|RSP) a=0 ;;
sp|FSP|SP|DSP) a=1 ;;
tors|TORS) a=2 ;;
tos|TOS|TOFS|TODS) a=3 ;;
toas|TOAS) a=4 ;;
asp) a=5 ;;
limit) a=6 ;;
lsp|LSP) a=7 ;;
count) a=8 ;;
csp|CSP) a=9 ;;
po|PO) a=10 ;;
wb|WB) a=11 ;;
dn|DN) a=12 ;;
pc|PC) a=15 ;;
esac

case $2 in
rsp|RSP) b=0 ;;
sp|FSP|SP|DSP) b=1 ;;
tors|TORS) b=2 ;;
tos|TOS|TOFS|TODS) b=3 ;;
toas|TOAS) b=4 ;;
asp) b=5 ;;
limit) b=6 ;;
lsp|LSP) b=7 ;;
count) b=8 ;;
csp|CSP) b=9 ;;
po|PO) b=10 ;;
wb|WB) b=11 ;;
dn|DN) b=12 ;;
pc|PC) b=15 ;;
esac
let c=b\<\<4\|a
AB $c
)

LIT () {
V "\""
LITLEAQ $1
}

GOTO () {
V G
LITLEAQ $1
}



TWICE () { # take 2 passes over sourcefile.
# Need that for forward branches.
rm a.out
HERE=0
. $1
rm a.out
HERE=0
. $1
echo >> a.out # IPL (read) needs this.
}


GOELPT () # greater or equal lowest power of two
# but this is getting kinda macro
# next thing you know people will do a Forth header...
{
let foo=1
while test $foo -lt $1; do
let foo*=2
done
echo $foo
}


Paul Rubin

unread,
Mar 8, 2021, 1:47:34 AM3/8/21
to
omg... well done.

hohensee

unread,
Mar 8, 2021, 7:43:19 AM3/8/21
to
On Monday, March 8, 2021 at 1:47:34 AM UTC-5, Paul Rubin wrote:
> omg... well done.
Thanks.

none albert

unread,
Mar 8, 2021, 10:02:12 AM3/8/21
to
In article <f9a93e65-62c2-4245...@googlegroups.com>,
hohensee <presidentb...@gmail.com> wrote:
># : Hnsm machine stack N Hohensee ; ( Hnsm)
>
># ksh emulation of 4-stack CPU. About 60 typeable ASCII opcodes.
># needs printf in Bash or in $PATH. Helpers use od, grep...
># 2021 March; most opcodes kinda work
># This program is public domain.
># Rick presidentbyamendment Hohensee.
>
>. ASC.sh
>
># To get the feel of a semi-typeable machine language, I want Hnsm code
># to be actually binary, and sh just understands C text strings. Binary
># zero is therefor impossible. Gotta have zero. SO, we swap 'z' and
># zero in the ASCII routine. A byte value of 122 is therefor impossible
># in literals. Otherwise, 'z' is a valid opcode. If you really need a
># 122 byte in a literal... figure something out. Other memory will be
># sh integers, which are apparently strings. 0 works. I doubt if
># lacking 122 will be a problem, but be aware that z in a literal is a
># zero.
>

<SNIP>

Duely impressed. It makes me wonder what else a person of your talent
and perseverance could accomplish.

Groetjes Albert
--
"in our communism country Viet Nam, people are forced to be
alive and in the western country like US, people are free to
die from Covid 19 lol" duc ha
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

hohensee

unread,
Mar 8, 2021, 2:46:21 PM3/8/21
to
Thanks so much. I should mention that Hnsm is WAY alpha,
but it mostly works it seems.

hohensee

unread,
Mar 15, 2021, 8:17:02 PM3/15/21
to
Hnsm instruction set reminder sheet

Hnsm has 63 first level machine codes, but the whole instruction set includes some
38 suffixes for the instructions ?, A and t. Most Hnsm opcodes can be typed
verbatim, and 'assembled' in strings with V. Literals and some other suffixes need
more help from an assembler. Below are the suffix tokens accepted by the IF, AMODE
and TRANS assembler functions for the ?, A and t machine codes. Some of the IF and
AMODE assembler tokens are the actual machine code suffix byte. Otherwise the
assembler may accept synonyms for a suffix.


t suffixer TRANS, e.g.
TRANS source dest
2 tokens required, each is one src/dest nybble in the actual suffix
rsp | RSP
sp | FSP | SP | DSP
tors | TORS
tos | TOS | TOFS | TODS
toas | TOAS
asp
limit
lsp | LSP
count
csp | CSP
po | PO
wb | WB
dn | DN
pc | PC


? suffixer IF
conditional branch conditions
zero set Z
zero clear z | ZC
sign set S | N
sign clear s | NC | SC
carry set C
carry clear c | cc | CC
overflow O | V
overflow clear o | v | OC | VC
uns. greater G | GT | gt
unsigned less l | L | LE | LTE
signed GE m | SGE | SGTE
signed less n | SLT | SL
signed G q | SG | SGT
signed LE r | SLE | SLTE
always A
pointer true P
pointer zero p | PZ | PT | PC
( first option shown is actual code byte suffix)


A suffixer AMODE
set @/! mode
higher | cdr | 4
lower | c3r | 5
direct | car | 0 | 1
C++ | WB | writeback | 2
C-- | 3
--C | 7
++C | 6
(single digit ASCII 0-7 is the actual code byte )

Hnsm first byte machine codes

! store " lit # comment $ syscall
% scale & and ( for/until ) loop
* times + plus , nop ' nor
- minus . halt / divmod 0 zero
1 increment 2 times 2 3 3 div 5 5 div
7 jarble : call ; return < min
= nexor > max ? if @ fetch
A A mode B revbytes C copro D dupe
G go lit J jump V L macro if M macro
N nip O over R ratchet S swap
T true V value W within X extend dual
Y yank [ upshift \ ADC ] downshift
^ exor _ sinum ` nand a a-drop
b bitpop d drop i eye s sub b
t trans x extend byte z mac z { roll
| or } eggroll ~ not

In Hnsm/program/asm.sh you can V e.g. A2 or ?Z, but IF, AMODE and TRANS
assemble the ?, A and t respectively, and the suffix.

hohensee

unread,
Mar 22, 2021, 5:47:45 PM3/22/21
to

There is now a tarball Hnsm0.tar at

http://rickfordictator.com/libris/Hnsm0.tar

containing what I posted here and some docs.
0 new messages