2070 lines
76 KiB
Plaintext
2070 lines
76 KiB
Plaintext
|
'******************************************************************************
|
||
|
' P1 Spin Interpreter for P2
|
||
|
'
|
||
|
' Copyright (c) 2014, Dave Hein
|
||
|
' See end of file for terms of use.
|
||
|
'******************************************************************************
|
||
|
CON
|
||
|
_clkmode = xtal1+pll16x
|
||
|
_clkfreq = 80_000_000
|
||
|
|
||
|
DAT
|
||
|
orgh $380
|
||
|
org
|
||
|
|
||
|
' Add address offset to Spin header
|
||
|
startup mov temp1, ptestprog
|
||
|
add temp1, #6
|
||
|
mov temp3, #5
|
||
|
:loop rdword temp2, temp1
|
||
|
add temp2, ptestprog
|
||
|
wrword temp2, temp1
|
||
|
add temp1, #2
|
||
|
djnz temp3, @:loop
|
||
|
|
||
|
' Clear VAR area
|
||
|
mov temp1, ptestprog
|
||
|
add temp1, #8 ' Get address of vbase
|
||
|
rdword temp2, temp1 ' Get vbase
|
||
|
add temp1, #2 ' Get address of dbase
|
||
|
rdword temp3, temp1 ' Get dbase
|
||
|
sub temp3, temp2 ' Compute number of bytes
|
||
|
shr temp3, #2 ' Compute number of longs
|
||
|
mov temp4, #0
|
||
|
:loop1 wrlong temp4, temp2
|
||
|
add temp2, #4
|
||
|
djnz temp3, @:loop1
|
||
|
|
||
|
' Initialize stack frame and result variable
|
||
|
mov temp1, ptestprog
|
||
|
add temp1, #10 ' Get address of dbase
|
||
|
rdword temp1, temp1 ' Get dbase
|
||
|
mov temp2, #0
|
||
|
wrlong temp2, temp1 ' Initialize result to zero
|
||
|
sub temp1, #2
|
||
|
wrword pexitcode, temp1 ' Set return address to exit code
|
||
|
sub temp1, #6
|
||
|
mov temp2, #2
|
||
|
wrword temp2, temp1 ' Write first word of stack frame
|
||
|
|
||
|
' Start the Spin interpreter
|
||
|
mov temp1, pinterp
|
||
|
mov temp2, ptestprog
|
||
|
add temp2, #4
|
||
|
coginit temp1, temp2, #0
|
||
|
|
||
|
temp1 long 0
|
||
|
temp2 long 0
|
||
|
temp3 long 0
|
||
|
temp4 long 0
|
||
|
pinterp long @interp
|
||
|
ptestprog long @testprog
|
||
|
ppbase long @pbase
|
||
|
pexitcode long @exitcode
|
||
|
|
||
|
orgh
|
||
|
|
||
|
DAT
|
||
|
|
||
|
' This table decodes the Spin bytecode.
|
||
|
jump_table
|
||
|
' 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F
|
||
|
word {00} ldfrmr, ldfrmr, ldfrmr, ldfrmr, _jmp, _call, callobj,callobx
|
||
|
word {08} _tjz, _djnz, _jz, _jnz, casedon,caseval,caseran,lookdon
|
||
|
word {10} lookupv,lookdnv,lookupr,lookdnr,_pop, _run, _strsiz,_strcmp
|
||
|
word {18} _bytefl,_wordfl,_longfl,_waitpe,_bytemv,_wordmv,_longmv,_waitpn
|
||
|
|
||
|
word {20} _clkset,cogstp, lckret, _waitcn,rwregx, rwregx, rwregx, _waitvi
|
||
|
word {28} _cogini,lcknewr,lcksetr,lckclrr,_cogini,lcknew, lckset, lckclr
|
||
|
word {30} _abort, abrtval,_ret, retval, ldlix, ldlix, ldlix, ldlip
|
||
|
word {38} ldbi, ldwi, ldmi, ldli, unsupp, rwregb, rwregbs,rwreg
|
||
|
|
||
|
word {40} ldlvc, stlvc, exlvc, lalvc, ldlvc, stlvc, exlvc, lalvc
|
||
|
word {48} ldlvc, stlvc, exlvc, lalvc, ldlvc, stlvc, exlvc, lalvc
|
||
|
word {50} ldlvc, stlvc, exlvc, lalvc, ldlvc, stlvc, exlvc, lalvc
|
||
|
word {58} ldlvc, stlvc, exlvc, lalvc, ldlvc, stlvc, exlvc, lalvc
|
||
|
|
||
|
word {60} ldllc, stllc, exllc, lallc, ldllc, stllc, exllc, lallc
|
||
|
word {68} ldllc, stllc, exllc, lallc, ldllc, stllc, exllc, lallc
|
||
|
word {70} ldllc, stllc, exllc, lallc, ldllc, stllc, exllc, lallc
|
||
|
word {78} ldllc, stllc, exllc, lallc, ldllc, stllc, exllc, lallc
|
||
|
|
||
|
word {80} ldba, stba, exba, la_a, ldbo, stbo, exbo, la_o
|
||
|
word {88} ldbv, stbv, exbv, la_v, ldbl, stbl, exwl, la_l
|
||
|
word {90} ldbax, stbax, exbax, labax, ldbox, stbox, exbox, labox
|
||
|
word {98} ldbvx, stbvx, exbvx, labvx, ldblx, stblx, exblx, lablx
|
||
|
|
||
|
word {A0} ldwa, stwa, exwa, la_a, ldwo, stwo, exwo, la_o
|
||
|
word {A8} ldwv, stwv, exwv, la_v, ldwl, stwl, exwl, la_l
|
||
|
word {B0} ldwax, stwax, exwax, lawax, ldwox, stwox, exwox, lawox
|
||
|
word {B8} ldwvx, stwvx, exwvx, lawvx, ldwlx, stwlx, exwlx, lawlx
|
||
|
|
||
|
word {C0} ldla, stla, exla, la_a, ldlo, stlo, exlo, la_o
|
||
|
word {C8} ldlv, stlv, exlv, la_v, ldll, stll, exll, la_l
|
||
|
word {D0} ldlax, stlax, exlax, lalax, ldlox, stlox, exlox, lalox
|
||
|
word {D8} ldlvx, stlvx, exlvx, lalvx, ldllx, stllx, exllx, lallx
|
||
|
|
||
|
word {E0} _ror, _rol, _shr, _shl, _min, _max, _neg, _com
|
||
|
word {E8} _and, _abs, _or, _xor, _add, _sub, _sar, _rev
|
||
|
word {F0} _andl, encode, _orl, decode, _mul, _mulh, _div, _mod
|
||
|
word {F8} _sqrt, _cmplt, _cmpgt, _cmpne, _cmpeq, _cmple, _cmpge, _notl
|
||
|
|
||
|
' This table decodes the extra byte that is used to perform extended operations.
|
||
|
jump_table_ex
|
||
|
' 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F
|
||
|
word {00} store, unsupx, repeatx,unsupx, unsupx, unsupx, repeats,unsupx
|
||
|
word {08} randf, unsupx, unsupx, unsupx, randr, unsupx, unsupx, unsupx
|
||
|
word {10} sexb, unsupx, unsupx, unsupx, sexw, unsupx, unsupx, unsupx
|
||
|
word {18} postclr,unsupx, unsupx, unsupx, postset,unsupx, unsupx, unsupx
|
||
|
|
||
|
word {20} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, preinc, unsupx
|
||
|
word {28} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, postinc,unsupx
|
||
|
word {30} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, predec, unsupx
|
||
|
word {38} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, postdec,unsupx
|
||
|
|
||
|
word {40} _rorx, _rolx, _shrx, _shlx, _minx, _maxx, _negx, _comx
|
||
|
word {48} _andx, _absx, _orx, _xorx, _addx, _subx, _sarx, _revx
|
||
|
word {50} _andlx, encodex,_orlx, decodex,_mulx, _mulhx, _divx, _modx
|
||
|
word {58} _sqrtx, _cmpltx,_cmpgtx,_cmpnex,_cmpeqx,_cmplex,_cmpgex,_notlx
|
||
|
|
||
|
word {60} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx
|
||
|
word {68} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx
|
||
|
word {70} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx
|
||
|
word {78} unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx, unsupx
|
||
|
|
||
|
' Bytecodes for cogstop(cogid)
|
||
|
exitcode byte $3f, $89, $21
|
||
|
|
||
|
org 0
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Copy 5 Spin state variable to registers
|
||
|
'***********************************************************************
|
||
|
interp setinda #pbase
|
||
|
reps #5, #1
|
||
|
cogid id
|
||
|
rdword inda++,++ptra
|
||
|
jmp #loop
|
||
|
long 0[3]
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Push x to the stack
|
||
|
'***********************************************************************
|
||
|
pushx1 wrlong x, dcurr
|
||
|
add dcurr, #4
|
||
|
|
||
|
'***********************************************************************
|
||
|
' This is the main loop that fetches bytecodes and executes them
|
||
|
'***********************************************************************
|
||
|
loop mov t1, jumps
|
||
|
rdbyte op,pcurr 'get opcode
|
||
|
add pcurr,#1
|
||
|
add t1, op
|
||
|
add t1, op
|
||
|
rdword t2, t1
|
||
|
jmp t2
|
||
|
|
||
|
'***********************************************************************
|
||
|
' This code handles extended operators, such as ++ and +=
|
||
|
'***********************************************************************
|
||
|
exoplong add adr, op2
|
||
|
exoplong1 rdlong x, adr
|
||
|
mov savex, #exoplong2
|
||
|
jmp #exop1
|
||
|
|
||
|
exopword add adr, op2
|
||
|
exopword1 rdword x, adr
|
||
|
mov savex, #exopword2
|
||
|
jmp #exop1
|
||
|
|
||
|
exopbyte add adr, op2
|
||
|
exopbyte1 rdbyte x, adr
|
||
|
mov savex, #exopbyte2
|
||
|
|
||
|
exop1 rdbyte op2,pcurr
|
||
|
mov t1, op2
|
||
|
and t1, #$7f
|
||
|
shl t1, #1
|
||
|
add t1, jumpx
|
||
|
rdword t2, t1
|
||
|
add pcurr,#1
|
||
|
jmp t2
|
||
|
|
||
|
'***********************************************************************
|
||
|
' This code saves the result from the extended operation
|
||
|
'***********************************************************************
|
||
|
postsave add savex, #1
|
||
|
jmp savex
|
||
|
|
||
|
exopbyte2 mov y, x
|
||
|
postbyte wrbyte y, adr
|
||
|
and x, #$ff
|
||
|
jmp #exopdone
|
||
|
|
||
|
exopword2 mov y, x
|
||
|
postword wrword y, adr
|
||
|
and x, maskword
|
||
|
jmp #exopdone
|
||
|
|
||
|
exoplong2 mov y, x
|
||
|
postlong wrlong y, adr
|
||
|
|
||
|
exopdone test op2, #$80 wc 'check for load bit
|
||
|
mov savex, #pushx1
|
||
|
if_c jmp #pushx1
|
||
|
if_nc jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Load Immediate Instructions
|
||
|
'***********************************************************************
|
||
|
'
|
||
|
' Load Long Immediate 1, 0 and -1
|
||
|
ldlix sub op, #$35
|
||
|
mov x, op
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Long Immediate Packed
|
||
|
ldlip mov x, #2
|
||
|
rdbyte y,pcurr 'constant mask, get data byte
|
||
|
add pcurr,#1
|
||
|
rol x,y 'decode, x = 2 before
|
||
|
test y,#%001_00000 wc 'decrement?
|
||
|
if_c sub x,#1
|
||
|
test y,#%010_00000 wc 'not?
|
||
|
if_c xor x,masklong
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Byte Immediate
|
||
|
ldbi call #fetchbyte
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Word Immediate
|
||
|
ldli call #fetchbyte
|
||
|
mov a, #3
|
||
|
jmp #addbytes
|
||
|
|
||
|
' Load Word Immediate
|
||
|
ldmi call #fetchbyte
|
||
|
mov a, #2
|
||
|
jmp #addbytes
|
||
|
|
||
|
' Load Word Immediate
|
||
|
ldwi call #fetchbyte
|
||
|
mov a, #1
|
||
|
|
||
|
addbytes shl x, #8
|
||
|
rdbyte y, pcurr
|
||
|
add pcurr, #1
|
||
|
or x, y
|
||
|
djnz a, @addbytes
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Compact Local Variable Instructions
|
||
|
'***********************************************************************
|
||
|
' Load Long Local Compact
|
||
|
ldllc mov op2, dbase
|
||
|
mov adr, op
|
||
|
and adr, #$1c
|
||
|
|
||
|
ldlong add adr, op2
|
||
|
rdlong x, adr
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Store Long Local Compact
|
||
|
stllc mov adr, op
|
||
|
and adr, #$1c
|
||
|
mov op2, dbase
|
||
|
|
||
|
stlong add adr, op2
|
||
|
call #popx1
|
||
|
wrlong x, adr
|
||
|
jmp #loop
|
||
|
|
||
|
' Execute Long Local Compact
|
||
|
exllc mov adr, op
|
||
|
and adr, #$1c
|
||
|
mov op2, dbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Long Local Compact
|
||
|
lallc and op, #$1c
|
||
|
add op, dbase
|
||
|
mov x, op
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' DAT Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Long Object
|
||
|
ldlo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long Object
|
||
|
stlo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Execute Long Object
|
||
|
exlo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Object
|
||
|
la_o call #getadrz
|
||
|
mov x, op2
|
||
|
add x, pbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Indexed DAT Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Byte Object with Index
|
||
|
ldbox call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, pbase
|
||
|
jmp #ldbyte
|
||
|
|
||
|
ldbyte add adr, op2
|
||
|
rdbyte x, adr
|
||
|
jmp #pushx1
|
||
|
|
||
|
ldword add adr, op2
|
||
|
rdword x, adr
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Store Byte Object with Index
|
||
|
stbox call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, pbase
|
||
|
jmp #stbyte
|
||
|
|
||
|
stbyte add adr, op2
|
||
|
call #popx1
|
||
|
wrbyte x, adr
|
||
|
jmp #loop
|
||
|
|
||
|
stword add adr, op2
|
||
|
call #popx1
|
||
|
wrword x, adr
|
||
|
jmp #loop
|
||
|
|
||
|
' Load Address Byte Object with Index
|
||
|
labox call #getadrz
|
||
|
call #popx1
|
||
|
add x, op2
|
||
|
add x, pbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Absolute Address Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Byte Absolute
|
||
|
ldba call #popy1
|
||
|
jmp #ldba1
|
||
|
|
||
|
' Load Word Absolute
|
||
|
ldwa call #popy1
|
||
|
jmp #ldwa1
|
||
|
|
||
|
' Load Long Absolute
|
||
|
ldla call #popy1
|
||
|
if_z jmp #ldclkfreq
|
||
|
jmp #ldla1
|
||
|
|
||
|
ldbax call #popay
|
||
|
add y, a
|
||
|
ldba1 rdbyte x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Word Absolute with Index
|
||
|
ldwax call #popay
|
||
|
shl a, #1
|
||
|
add y, a
|
||
|
ldwa1 rdword x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Long Absolute with Index
|
||
|
ldlax call #popay
|
||
|
shl a, #2
|
||
|
add y, a
|
||
|
ldla1 rdlong x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Jump Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Test and Jump on Zero
|
||
|
_tjz call #getadrs
|
||
|
call #popx1
|
||
|
if_nz add dcurr, #4
|
||
|
jmp #_jz1
|
||
|
|
||
|
' Jump on Zero
|
||
|
_jz call #getadrs
|
||
|
call #popx1
|
||
|
_jz1 if_z add pcurr, op2
|
||
|
jmp #loop
|
||
|
|
||
|
' Decrement and Jump on NonZero
|
||
|
_djnz call #getadrs
|
||
|
call #popx1
|
||
|
sub x, #1 wz
|
||
|
if_nz add pcurr, op2
|
||
|
if_nz jmp #pushx1
|
||
|
jmp #loop
|
||
|
|
||
|
' Jump on NonZero
|
||
|
_jnz call #getadrs
|
||
|
call #popx1
|
||
|
if_nz add pcurr, op2
|
||
|
jmp #loop
|
||
|
|
||
|
' Jump
|
||
|
_jmp call #getadrs
|
||
|
add pcurr, op2
|
||
|
jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Math Instructions
|
||
|
'***********************************************************************
|
||
|
_shr call #popyx
|
||
|
shr x, y
|
||
|
jmp savex
|
||
|
|
||
|
_shl call #popyx
|
||
|
shl x, y
|
||
|
jmp savex
|
||
|
|
||
|
_ror call #popyx
|
||
|
rol x, y
|
||
|
jmp savex
|
||
|
|
||
|
_rol call #popyx
|
||
|
rol x, y
|
||
|
jmp savex
|
||
|
|
||
|
' Complement
|
||
|
_com call #popx1
|
||
|
xor x, masklong
|
||
|
jmp savex
|
||
|
|
||
|
_and call #popyx
|
||
|
and x, y
|
||
|
jmp savex
|
||
|
|
||
|
' Absolute
|
||
|
_abs call #popx1
|
||
|
abs x, x
|
||
|
jmp savex
|
||
|
|
||
|
_or call #popyx
|
||
|
or x, y
|
||
|
jmp savex
|
||
|
|
||
|
' Add
|
||
|
_add call #popyx
|
||
|
add x, y
|
||
|
jmp savex
|
||
|
|
||
|
' Subtract
|
||
|
_sub call #popyx
|
||
|
sub x, y
|
||
|
jmp savex
|
||
|
|
||
|
_neg call #popx1
|
||
|
neg x, x
|
||
|
jmp savex
|
||
|
|
||
|
_xor call #popyx
|
||
|
xor x, y
|
||
|
jmp savex
|
||
|
|
||
|
_sar call #popyx
|
||
|
sar x, y
|
||
|
jmp savex
|
||
|
|
||
|
' Or Logical
|
||
|
_orl call #popx1
|
||
|
if_nz neg x, #1
|
||
|
call #popy1
|
||
|
if_nz neg x, #1
|
||
|
jmp savex
|
||
|
|
||
|
_andl call #popx1
|
||
|
if_nz neg x, #1
|
||
|
call #popy1
|
||
|
if_z mov x, #0
|
||
|
jmp savex
|
||
|
|
||
|
_notl call #popx1
|
||
|
muxz x, masklong
|
||
|
jmp savex
|
||
|
|
||
|
_mul call #popyx
|
||
|
mul32 x, y
|
||
|
getmull x
|
||
|
jmp savex
|
||
|
|
||
|
_mulh call #popyx
|
||
|
mul32 x, y
|
||
|
getmulh x
|
||
|
jmp savex
|
||
|
|
||
|
_div call #popyx
|
||
|
div32 x, y
|
||
|
getdivq x
|
||
|
jmp savex
|
||
|
|
||
|
_mod call #popyx
|
||
|
div32 x, y
|
||
|
getdivr x
|
||
|
jmp savex
|
||
|
|
||
|
' Compare if Less Than
|
||
|
_cmplt call #popyx
|
||
|
cmps x, y wz, wc
|
||
|
muxc x, masklong
|
||
|
jmp savex
|
||
|
|
||
|
' Compare if Greater Than
|
||
|
_cmpgt call #popyx
|
||
|
cmps x, y wz, wc
|
||
|
if_nz_and_nc neg x, #1
|
||
|
if_z_or_c mov x, #0
|
||
|
jmp savex
|
||
|
|
||
|
' Compare if Less than or Equal
|
||
|
_cmple call #popyx
|
||
|
cmps x, y wz, wc
|
||
|
if_nz_and_nc mov x, #0
|
||
|
if_z_or_c neg x, #1
|
||
|
jmp savex
|
||
|
|
||
|
' Compare if Not Equal
|
||
|
_cmpne call #popyx
|
||
|
sub x, y wz
|
||
|
if_nz neg x, #1
|
||
|
jmp savex
|
||
|
|
||
|
|
||
|
' Compare if Equal
|
||
|
_cmpeq call #popyx
|
||
|
sub x, y wz
|
||
|
jmp #_notlx
|
||
|
|
||
|
' Compare if Greater than or Equal
|
||
|
_cmpge call #popyx
|
||
|
cmps x, y wz, wc
|
||
|
muxnc x, masklong
|
||
|
jmp savex
|
||
|
|
||
|
retval call #popx1
|
||
|
jmp #_ret1
|
||
|
_ret rdlong x,dbase
|
||
|
_ret1 call #return1
|
||
|
pushz if_z jmp #pushx1
|
||
|
if_nz jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Calling and Return Instructions
|
||
|
'***********************************************************************
|
||
|
return1 mov dcurr,dbase 'restore dcurr
|
||
|
sub dcurr,#2 'pop pcurr
|
||
|
rdword pcurr,dcurr
|
||
|
sub dcurr,#2 'pop dbase
|
||
|
rdword dbase,dcurr
|
||
|
sub dcurr,#2 'pop vbase
|
||
|
rdword vbase,dcurr
|
||
|
sub dcurr,#2 'pop pbase (and flags)
|
||
|
rdword pbase,dcurr
|
||
|
test pbase,#%01 wz 'get push flag
|
||
|
test pbase,#%10 wc 'get abort flag
|
||
|
and pbase,maskpar 'trim pbase
|
||
|
ret
|
||
|
|
||
|
' Load Stack Frame
|
||
|
ldfrmr
|
||
|
ldfrm
|
||
|
ldfrmar
|
||
|
ldfrma jmp #loadframe
|
||
|
|
||
|
callobj mov a, #0
|
||
|
callobj1 call #getcallparms
|
||
|
add pbase, x
|
||
|
add vbase, y
|
||
|
|
||
|
_call mov a, #0
|
||
|
call #getcallparms
|
||
|
jmp #callmethod
|
||
|
|
||
|
' Read values from the Method Table
|
||
|
getcallparms rdbyte y,pcurr 'get method table entry number
|
||
|
add pcurr,#1
|
||
|
add y,a 'add index
|
||
|
shl y,#2 'lookup words from table
|
||
|
add y,pbase
|
||
|
rdlong y,y
|
||
|
mov x,y 'get low word
|
||
|
and x,maskword
|
||
|
shr y,#16 'get high word
|
||
|
ret
|
||
|
|
||
|
' Call Method
|
||
|
callmethod mov dbase,dcall 'get new dcall
|
||
|
rdword dcall,dcall 'set old dcall
|
||
|
wrword pcurr,dbase 'set return pcurr
|
||
|
add dbase,#2 'set call dbase
|
||
|
add dcurr,y 'set call dcurr
|
||
|
mov pcurr,pbase 'set call pcurr
|
||
|
add pcurr,x
|
||
|
jmp #loop
|
||
|
|
||
|
loadframe or op,pbase 'add pbase into flags
|
||
|
wrword op,dcurr 'push pbase plus flags
|
||
|
add dcurr,#2
|
||
|
wrword vbase,dcurr 'push vbase
|
||
|
add dcurr,#2
|
||
|
wrword dbase,dcurr 'push dbase
|
||
|
add dcurr,#2
|
||
|
wrword dcall,dcurr 'push dcall
|
||
|
mov dcall,dcurr 'set new dcall
|
||
|
add dcurr,#2
|
||
|
mov x, #0 'init result to 0
|
||
|
jmp #pushx1
|
||
|
|
||
|
_cogini1 coginit y, a, #0
|
||
|
jmp #pushz
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Helper Functions
|
||
|
'***********************************************************************
|
||
|
' Get Unsigned Address
|
||
|
getadrz rdbyte op2,pcurr
|
||
|
test op2,#$80 wc
|
||
|
and op2,#$7F
|
||
|
jmp #getadr2
|
||
|
' Get Signed Address
|
||
|
getadrs rdbyte op2,pcurr
|
||
|
test op2,#$80 wc
|
||
|
shl op2,#25
|
||
|
sar op2,#25
|
||
|
getadr2 add pcurr,#1
|
||
|
if_nc ret
|
||
|
rdbyte t2,pcurr
|
||
|
add pcurr,#1
|
||
|
shl op2,#8
|
||
|
or op2,t2
|
||
|
ret
|
||
|
|
||
|
' Fetch a bytecode
|
||
|
fetchbyte rdbyte x, pcurr
|
||
|
add pcurr, #1
|
||
|
ret
|
||
|
|
||
|
' Pop a from the stack
|
||
|
popayx sub dcurr,#4
|
||
|
rdlong a,dcurr
|
||
|
|
||
|
' Pop y from the stack
|
||
|
popyx sub dcurr,#4
|
||
|
rdlong y,dcurr
|
||
|
|
||
|
' Pop x from the stack
|
||
|
popx1 sub dcurr,#4
|
||
|
rdlong x,dcurr wz
|
||
|
ret
|
||
|
|
||
|
' Pop a from the stack
|
||
|
popay sub dcurr,#4
|
||
|
rdlong a,dcurr
|
||
|
|
||
|
' Pop y from the stack
|
||
|
popy1 sub dcurr, #4
|
||
|
rdlong y, dcurr wz
|
||
|
ret
|
||
|
|
||
|
' Pop adr from the stack
|
||
|
pop_adr sub dcurr,#4
|
||
|
rdlong adr,dcurr
|
||
|
ret
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Extended Instructions
|
||
|
'***********************************************************************
|
||
|
store call #popx1
|
||
|
jmp savex
|
||
|
|
||
|
postclr mov y, #0
|
||
|
jmp #postsave
|
||
|
|
||
|
postset neg y, #1
|
||
|
jmp #postsave
|
||
|
|
||
|
postinc mov y, x
|
||
|
add y, #1
|
||
|
jmp #postsave
|
||
|
|
||
|
postdec mov y, x
|
||
|
sub y, #1
|
||
|
jmp #postsave
|
||
|
|
||
|
_rolx call #popy1
|
||
|
rol x, y
|
||
|
jmp savex
|
||
|
|
||
|
_shlx call #popy1
|
||
|
shl x, y
|
||
|
jmp savex
|
||
|
|
||
|
_divx call #popy1
|
||
|
jmp #_div+1
|
||
|
|
||
|
_modx call #popy1
|
||
|
jmp #_mod+1
|
||
|
|
||
|
_notlx muxz x, masklong
|
||
|
jmp savex
|
||
|
|
||
|
_rorx call #popy1
|
||
|
ror x, y
|
||
|
jmp savex
|
||
|
|
||
|
_shrx call #popy1
|
||
|
shr x, y
|
||
|
jmp savex
|
||
|
|
||
|
_andx call #popy1
|
||
|
and x, y
|
||
|
jmp savex
|
||
|
|
||
|
_absx abs x, x
|
||
|
jmp savex
|
||
|
|
||
|
_negx neg x, x
|
||
|
jmp savex
|
||
|
|
||
|
_comx xor x, masklong
|
||
|
jmp savex
|
||
|
|
||
|
_orx call #popy1
|
||
|
or x, y
|
||
|
jmp savex
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Read/Write Register Instructions
|
||
|
'***********************************************************************
|
||
|
rwreg0 rdbyte op, pcurr
|
||
|
add pcurr, #1
|
||
|
mov adr, op
|
||
|
rwreg1 and adr, #$1f
|
||
|
add adr, #$1e0
|
||
|
call #mapreg
|
||
|
mov regrevflag, #0
|
||
|
mov reglsb, t1
|
||
|
mov regnbits, t2
|
||
|
sub regnbits,reglsb wc
|
||
|
if_c neg regnbits, regnbits
|
||
|
if_c mov reglsb, t2
|
||
|
if_c mov regrevflag, #1
|
||
|
xor regnbits, #31
|
||
|
neg regmask, #1
|
||
|
shr regmask, regnbits
|
||
|
test op, #$20 wz
|
||
|
if_z jmp #ldreg
|
||
|
|
||
|
streg sets streg1, adr
|
||
|
setd streg2, adr
|
||
|
call #popx1
|
||
|
and x, regmask
|
||
|
cmp regrevflag, #0 wz
|
||
|
if_nz rev x, regnbits
|
||
|
shl regmask, reglsb
|
||
|
streg1 mov y, 0-0
|
||
|
andn y, regmask
|
||
|
shl x, reglsb
|
||
|
or y, x
|
||
|
streg2 mov 0-0, y
|
||
|
jmp #loop
|
||
|
|
||
|
ldreg sets ldreg1, adr
|
||
|
nop
|
||
|
cmp adr, #$1f1 wz
|
||
|
if_z getcnt x
|
||
|
ldreg1 if_nz mov x, 0-0
|
||
|
mov regsave, x
|
||
|
shr x, reglsb
|
||
|
and x, regmask
|
||
|
cmp regrevflag, #0 wz
|
||
|
if_nz rev x, regnbits
|
||
|
test op, #$40 wz
|
||
|
if_z jmp #pushx1
|
||
|
mov savex, #exopreg2
|
||
|
jmp #exop1
|
||
|
|
||
|
exopreg2 mov y, x
|
||
|
postreg setd exopreg3, adr
|
||
|
and x, regmask
|
||
|
and y, regmask
|
||
|
cmp regrevflag, #0 wz
|
||
|
if_nz rev y, regnbits
|
||
|
shl y, reglsb
|
||
|
shl regmask, reglsb
|
||
|
andn regsave, regmask
|
||
|
or y, regsave
|
||
|
exopreg3 mov 0-0, y
|
||
|
jmp #exopdone
|
||
|
|
||
|
' Mapping for port A
|
||
|
mapreg cmp adr, #$1f2 wz 'P1 INA
|
||
|
if_z mov adr, #$1f4 'P2 PINA
|
||
|
if_z ret
|
||
|
cmp adr, #$1f4 wz 'P1 OUTA
|
||
|
if_z mov adr, #$1f8 'P2 OUTA
|
||
|
if_z ret
|
||
|
cmp adr, #$1f6 wz 'P1 DIRA
|
||
|
if_z mov adr, #$1fc 'P2 DIRA
|
||
|
ret
|
||
|
{
|
||
|
' Mapping for port C
|
||
|
mapreg cmp adr, #$1f2 wz 'P1 INA
|
||
|
if_z mov adr, #$1f6 'P2 PINC
|
||
|
if_z ret
|
||
|
cmp adr, #$1f4 wz 'P1 OUTA
|
||
|
if_z mov adr, #$1fa 'P2 OUTC
|
||
|
if_z ret
|
||
|
cmp adr, #$1f6 wz 'P1 DIRA
|
||
|
if_z mov adr, #$1fe 'P2 DIRC
|
||
|
ret
|
||
|
}
|
||
|
regrevflag long 0
|
||
|
reglsb long 0
|
||
|
regmask long 0
|
||
|
regnbits long 0
|
||
|
regsave long 0
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Constants and Variables
|
||
|
'***********************************************************************
|
||
|
bitcycles long 80000000 / 115200
|
||
|
jumps long @jump_table
|
||
|
jumpx long @jump_table_ex
|
||
|
savex long pushx1
|
||
|
masklong long $FFFFFFFF
|
||
|
maskword long $FFFF
|
||
|
maskpar long $0000FFFC
|
||
|
fit $1E9
|
||
|
|
||
|
org $1E9
|
||
|
id res 1
|
||
|
dcall res 1
|
||
|
pbase res 1
|
||
|
vbase res 1
|
||
|
dbase res 1
|
||
|
pcurr res 1
|
||
|
dcurr res 1
|
||
|
|
||
|
fit $1F0
|
||
|
|
||
|
org 0
|
||
|
x res 1
|
||
|
y res 1
|
||
|
a res 1
|
||
|
t1 res 1
|
||
|
t2 res 1
|
||
|
op res 1
|
||
|
op2 res 1
|
||
|
adr res 1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' These instructions execute from hub memory
|
||
|
'***********************************************************************
|
||
|
orgh
|
||
|
|
||
|
' casedone
|
||
|
casedon sub dcurr, #8
|
||
|
rdlong pcurr, dcurr
|
||
|
add pcurr, pbase
|
||
|
jmp #loop
|
||
|
|
||
|
' casevalue
|
||
|
caseval call #getadrs
|
||
|
call #popyx
|
||
|
add dcurr, #4
|
||
|
cmp x, y wz
|
||
|
if_z add pcurr, op2
|
||
|
jmp #loop
|
||
|
|
||
|
' caserange
|
||
|
caseran call #getadrs
|
||
|
call #popayx
|
||
|
add dcurr, #4
|
||
|
cmps a, y wz, wc
|
||
|
if_nz_and_nc jmp #caseran1
|
||
|
cmps a, x wz, wc
|
||
|
if_nz_and_nc jmp #loop
|
||
|
cmps x, y wz, wc
|
||
|
if_nz_and_nc jmp #loop
|
||
|
add pcurr, op2
|
||
|
jmp #loop
|
||
|
caseran1 cmps y, x wz, wc
|
||
|
if_nz_and_nc jmp #loop
|
||
|
cmps x, a wz, wc
|
||
|
if_nz_and_nc jmp #loop
|
||
|
add pcurr, op2
|
||
|
jmp #loop
|
||
|
|
||
|
' lookdone
|
||
|
lookdon sub dcurr, #12
|
||
|
mov x, #0
|
||
|
jmp #pushx1
|
||
|
|
||
|
' lookupval
|
||
|
lookupv call #pop_adr
|
||
|
call #popayx
|
||
|
add dcurr, #12
|
||
|
cmps a, x wz, wc
|
||
|
if_c jmp #lookupv1
|
||
|
if_z jmp #lookupv2
|
||
|
add x, #1
|
||
|
sub dcurr, #12
|
||
|
wrlong x, dcurr
|
||
|
add dcurr, #12
|
||
|
jmp #loop
|
||
|
lookupv1 mov pcurr, y
|
||
|
add pcurr, pbase
|
||
|
sub dcurr, #12
|
||
|
mov x, #0
|
||
|
jmp #pushx1
|
||
|
lookupv2 mov pcurr, y
|
||
|
add pcurr, pbase
|
||
|
sub dcurr, #12
|
||
|
mov x, adr
|
||
|
jmp #pushx1
|
||
|
' lookdnval
|
||
|
lookdnv call #popyx
|
||
|
add dcurr, #4
|
||
|
cmp x, y wz
|
||
|
if_nz jmp #lookdnv1
|
||
|
sub dcurr, #8
|
||
|
rdlong pcurr, dcurr
|
||
|
add pcurr, pbase
|
||
|
jmp #loop
|
||
|
lookdnv1 sub dcurr, #12
|
||
|
rdlong x, dcurr
|
||
|
add x, #1
|
||
|
wrlong x, dcurr
|
||
|
add dcurr, #12
|
||
|
jmp #loop
|
||
|
|
||
|
' lookuprange
|
||
|
lookupr call #popyx
|
||
|
mov t1, y
|
||
|
mov t2, x
|
||
|
call #popayx
|
||
|
add dcurr, #12
|
||
|
mov adr, t1
|
||
|
sub adr, t2
|
||
|
abs adr, adr
|
||
|
sub a, x wc
|
||
|
if_c jmp #lookupr1
|
||
|
cmp a, adr wc, wz
|
||
|
if_c_or_z jmp #lookupr2
|
||
|
add x, adr
|
||
|
add x, #1
|
||
|
sub dcurr, #12
|
||
|
wrlong x, dcurr
|
||
|
add dcurr, #12
|
||
|
jmp #loop
|
||
|
lookupr1 sub dcurr, #12
|
||
|
mov pcurr, y
|
||
|
add pcurr, pbase
|
||
|
mov x, #0
|
||
|
jmp #pushx1
|
||
|
lookupr2 sub dcurr, #12
|
||
|
mov pcurr, y
|
||
|
add pcurr, pbase
|
||
|
cmp t2, t1 wc, wz
|
||
|
mov x, t2
|
||
|
if_c_or_z add x, a
|
||
|
if_nc_and_nz sub x, a
|
||
|
jmp #pushx1
|
||
|
|
||
|
' lookdnrange
|
||
|
lookdnr call #popayx
|
||
|
add dcurr, #4
|
||
|
mov t1, a
|
||
|
mov t2, y
|
||
|
max t1, y ' Get minimum
|
||
|
min t2, a ' Get maximum
|
||
|
cmps x, t1 wc
|
||
|
if_c jmp #lookdnr1
|
||
|
cmps t2, x wc
|
||
|
if_c jmp #lookdnr1
|
||
|
sub dcurr, #8
|
||
|
rdlong pcurr, dcurr
|
||
|
add pcurr, pbase
|
||
|
call #pop_adr
|
||
|
cmps y, a wc
|
||
|
sub x, y
|
||
|
if_nc neg x, x
|
||
|
add x, adr
|
||
|
jmp #pushx1
|
||
|
lookdnr1 sub dcurr, #12
|
||
|
rdlong x, dcurr
|
||
|
add x, #1
|
||
|
add x, t2
|
||
|
sub x, t1
|
||
|
wrlong x, dcurr
|
||
|
add dcurr, #12
|
||
|
jmp #loop
|
||
|
|
||
|
_waitcn call #popx1
|
||
|
waitcnt x, #0
|
||
|
jmp #loop
|
||
|
|
||
|
_waitpe call #popayx
|
||
|
test a, #1 wz
|
||
|
getcnt t1
|
||
|
' Port A and B
|
||
|
:loop if_nz waitpeq x, y, #1 wc
|
||
|
if_z waitpeq x, y, #0 wc
|
||
|
{
|
||
|
' Port C and D
|
||
|
:loop if_nz waitpeq x, y, #3 wc
|
||
|
if_z waitpeq x, y, #2 wc
|
||
|
}
|
||
|
if_c jmp #:loop
|
||
|
jmp #loop
|
||
|
|
||
|
_waitpn call #popayx
|
||
|
test a, #1 wz
|
||
|
getcnt t1
|
||
|
:loop if_z waitpne x, y, #1 wc
|
||
|
if_nz waitpne x, y, #0 wc
|
||
|
if_c jmp #:loop
|
||
|
jmp #loop
|
||
|
|
||
|
cogstp call #popx1
|
||
|
cogstop x
|
||
|
jmp #loop
|
||
|
|
||
|
_cogini call #popayx 'coginit, pop parameters
|
||
|
test x, #8 wc
|
||
|
and x, #7
|
||
|
setnib _cogini1, x, #6
|
||
|
test op,#%100 wz 'push result?
|
||
|
if_nc jmp #_cogini1
|
||
|
cognew y, a wc
|
||
|
if_c neg x, #1 '-1 if c, else 0..7
|
||
|
if_nc mov x, y '-1 if c, else 0..7
|
||
|
jmp #pushz
|
||
|
|
||
|
callobx call #popx1
|
||
|
mov a, x
|
||
|
jmp #callobj1
|
||
|
|
||
|
_pop call #popx1
|
||
|
sub dcurr, x
|
||
|
jmp #loop
|
||
|
|
||
|
abrtval call #popx1
|
||
|
jmp #_abort1
|
||
|
_abort rdlong x,dbase
|
||
|
_abort1 call #return1
|
||
|
if_nc jmp #_abort1
|
||
|
jmp #pushz
|
||
|
|
||
|
rwreg mov t2, #31
|
||
|
mov t1, #0
|
||
|
jmp #rwreg0
|
||
|
|
||
|
rwregb call #popx1
|
||
|
and x, #31
|
||
|
mov t2, x
|
||
|
mov t1, x
|
||
|
jmp #rwreg0
|
||
|
|
||
|
rwregbs call #popyx
|
||
|
and x, #31
|
||
|
and y, #31
|
||
|
mov t2, x
|
||
|
mov t1, y
|
||
|
jmp #rwreg0
|
||
|
|
||
|
rwregx call #pop_adr
|
||
|
or adr, #$10
|
||
|
shl op, #5
|
||
|
jmp #rwreg1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Prepare to start a Spin cog
|
||
|
'***********************************************************************
|
||
|
'run(metindex, stackaddr)
|
||
|
_run call #popyx
|
||
|
|
||
|
'stackptr := (metindex >> 8) << 2
|
||
|
mov adr, x
|
||
|
shr adr, #8
|
||
|
shl adr, #2 wz
|
||
|
|
||
|
'metindex := ((metindex & 255) << 2) + PBASE
|
||
|
and x, #255
|
||
|
shl x, #2
|
||
|
add x, pbase
|
||
|
|
||
|
'skip bytemove if no parms
|
||
|
if_z jmp #_run1
|
||
|
|
||
|
't2 := stackaddr + 12
|
||
|
mov t2, y
|
||
|
add t2, #12
|
||
|
|
||
|
't1 := DCURR - stackptr
|
||
|
mov t1, dcurr
|
||
|
sub t1, adr
|
||
|
|
||
|
'a := stackptr
|
||
|
mov a, adr
|
||
|
|
||
|
'bytemove(t2, t1, a)
|
||
|
:loop rdbyte op2, t1
|
||
|
add t1, #1
|
||
|
wrbyte op2, t2
|
||
|
add t2, #1
|
||
|
djnz a, @:loop
|
||
|
|
||
|
'pop(stackptr)
|
||
|
sub dcurr, adr
|
||
|
|
||
|
'long[stackaddr] := -1
|
||
|
_run1 neg t1, #1
|
||
|
wrlong t1, y
|
||
|
add y, #4
|
||
|
|
||
|
'long[stackaddr][1] := (@exitcode << 16)
|
||
|
mov t1, ##@exitcode
|
||
|
shl t1, #16
|
||
|
wrlong t1, y
|
||
|
add y, #4
|
||
|
|
||
|
'word[stackaddr][2] := 0
|
||
|
mov t1, #0
|
||
|
wrlong t1, y
|
||
|
|
||
|
'stackptr += stackaddr + 12
|
||
|
add adr, y
|
||
|
add adr, #4
|
||
|
|
||
|
'word[stackptr][1] := pbase
|
||
|
add adr, #2
|
||
|
wrword pbase, adr
|
||
|
|
||
|
'word[stackptr][2] := vbase
|
||
|
add adr, #2
|
||
|
wrword vbase, adr
|
||
|
|
||
|
'word[stackptr][3] := stackaddr + 8
|
||
|
add adr, #2
|
||
|
wrword y, adr
|
||
|
|
||
|
'word[stackptr][4] := word[metindex] + PBASE
|
||
|
add adr, #2
|
||
|
rdword t1, x
|
||
|
add t1, pbase
|
||
|
wrword t1, adr
|
||
|
|
||
|
'word[stackptr][5] := word[metindex][1] + stackptr
|
||
|
add adr, #2
|
||
|
add x, #2
|
||
|
rdword t1, x
|
||
|
add t1, adr
|
||
|
sub t1, #10
|
||
|
wrword t1, adr
|
||
|
sub adr, #10
|
||
|
|
||
|
'(-1, @interp, stackptr)
|
||
|
neg t1, #1
|
||
|
wrlong t1, dcurr
|
||
|
add dcurr, #4
|
||
|
mov t1, ##@interp
|
||
|
wrlong t1, dcurr
|
||
|
add dcurr, #4
|
||
|
wrlong adr, dcurr
|
||
|
add dcurr, #4
|
||
|
|
||
|
jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' String, Block Move and Block Fill Instructions
|
||
|
'***********************************************************************
|
||
|
' strsize
|
||
|
_strsiz call #popx1
|
||
|
mov y, x
|
||
|
:loop rdbyte a, x wz
|
||
|
if_nz add x, #1
|
||
|
if_nz jmp #:loop
|
||
|
sub x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
' strcomp
|
||
|
_strcmp call #popyx
|
||
|
:loop rdbyte t1, x wz
|
||
|
add x, #1
|
||
|
if_z jmp #_strcmp1
|
||
|
rdbyte t2, y wz
|
||
|
add y, #1
|
||
|
if_z jmp #_strcmp2
|
||
|
cmp t1, t2 wz
|
||
|
if_z jmp #:loop
|
||
|
_strcmp2 mov x, #0
|
||
|
jmp #pushx1
|
||
|
_strcmp1 rdbyte t2, y wz
|
||
|
jmp #_notlx
|
||
|
|
||
|
' longfill
|
||
|
_longfl call #popayx
|
||
|
:loop wrlong y, x
|
||
|
add x, #4
|
||
|
djnz a, @:loop
|
||
|
jmp #loop
|
||
|
|
||
|
' wordfill
|
||
|
_wordfl call #popayx
|
||
|
:loop wrword y, x
|
||
|
add x, #2
|
||
|
djnz a, @:loop
|
||
|
jmp #loop
|
||
|
|
||
|
' bytefill
|
||
|
_bytefl call #popayx
|
||
|
:loop wrbyte y, x
|
||
|
add x, #1
|
||
|
djnz a, @:loop
|
||
|
jmp #loop
|
||
|
|
||
|
' longmove
|
||
|
_longmv call #popayx
|
||
|
:loop rdlong t1, y
|
||
|
add y, #4
|
||
|
wrlong t1, x
|
||
|
add x, #4
|
||
|
djnz a, @:loop
|
||
|
jmp #loop
|
||
|
|
||
|
' wordmove
|
||
|
_wordmv call #popayx
|
||
|
:loop rdword t1, y
|
||
|
add y, #2
|
||
|
wrword t1, x
|
||
|
add x, #2
|
||
|
djnz a, @:loop
|
||
|
jmp #loop
|
||
|
|
||
|
' bytemove
|
||
|
_bytemv call #popayx
|
||
|
:loop rdbyte t1, y
|
||
|
add y, #1
|
||
|
wrbyte t1, x
|
||
|
add x, #1
|
||
|
djnz a, @:loop
|
||
|
jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Lock instructions
|
||
|
'***********************************************************************
|
||
|
lcknewr locknew x wc
|
||
|
if_c neg x, #1
|
||
|
jmp #pushx1
|
||
|
|
||
|
lcksetr call #popx1
|
||
|
lockset x wc
|
||
|
if_c neg x, #1
|
||
|
if_nc mov x, #0
|
||
|
jmp #pushx1
|
||
|
|
||
|
lckclrr call #popx1
|
||
|
lockclr x wc
|
||
|
if_c neg x, #1
|
||
|
if_nc mov x, #0
|
||
|
jmp #pushx1
|
||
|
|
||
|
lcknew locknew x
|
||
|
jmp #loop
|
||
|
|
||
|
lckset call #popx1
|
||
|
lockset x
|
||
|
jmp #loop
|
||
|
|
||
|
lckclr call #popx1
|
||
|
lockclr x
|
||
|
jmp #loop
|
||
|
|
||
|
lckret call #popx1
|
||
|
lockret x
|
||
|
jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Local Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Long Var
|
||
|
ldll call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long Var
|
||
|
stll call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Execute Long Var
|
||
|
exll call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Var
|
||
|
la_l call #getadrz
|
||
|
mov x, op2
|
||
|
add x, dbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Word Var
|
||
|
ldwl call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #ldword
|
||
|
|
||
|
' Store Word Var
|
||
|
stwl call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #stword
|
||
|
|
||
|
' Execute Word Var
|
||
|
exwl call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #exopword
|
||
|
|
||
|
' Load Byte Var
|
||
|
ldbl call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #ldbyte
|
||
|
|
||
|
' Store Byte Var
|
||
|
stbl call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #stbyte
|
||
|
|
||
|
' Execute Byte Var
|
||
|
exbl call #getadrz
|
||
|
mov adr, dbase
|
||
|
jmp #exopbyte
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Compact VAR Variable Instructions
|
||
|
'***********************************************************************
|
||
|
' Load Long Local Compact
|
||
|
ldlvc mov op2, vbase
|
||
|
mov adr, op
|
||
|
and adr, #$1c
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long Local Compact
|
||
|
stlvc mov adr, op
|
||
|
and adr, #$1c
|
||
|
mov op2, vbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Execute Long Local Compact
|
||
|
exlvc mov adr, op
|
||
|
and adr, #$1c
|
||
|
mov op2, vbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Long Local Compact
|
||
|
lalvc and op, #$1c
|
||
|
add op, vbase
|
||
|
mov x, op
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' VAR Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Long Var
|
||
|
ldlv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long Var
|
||
|
stlv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Load Word Var
|
||
|
ldwv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #ldword
|
||
|
|
||
|
' Store Word Var
|
||
|
stwv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #stword
|
||
|
|
||
|
' Load Byte Var
|
||
|
ldbv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #ldbyte
|
||
|
|
||
|
' Store Byte Var
|
||
|
stbv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #stbyte
|
||
|
|
||
|
' Execute Long Var
|
||
|
exlv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Execute Word Var
|
||
|
exwv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #exopword
|
||
|
|
||
|
' Execute Byte Var
|
||
|
exbv call #getadrz
|
||
|
mov adr, vbase
|
||
|
jmp #exopbyte
|
||
|
|
||
|
' Load Address Var
|
||
|
la_v call #getadrz
|
||
|
mov x, op2
|
||
|
add x, vbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Indexed Local Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Long Local with Index
|
||
|
ldllx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, dbase
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long Local with Index
|
||
|
stllx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, dbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Execute Long Local with Index
|
||
|
exllx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, dbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Long Local with Index
|
||
|
lallx call #getadrz
|
||
|
call #popx1
|
||
|
shl x, #2
|
||
|
add x, op2
|
||
|
add x, dbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Word Local with Index
|
||
|
ldwlx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, dbase
|
||
|
jmp #ldword
|
||
|
|
||
|
' Store Word Local with Index
|
||
|
stwlx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, dbase
|
||
|
jmp #stword
|
||
|
|
||
|
' Execute Word Local with Index
|
||
|
exwlx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, dbase
|
||
|
jmp #exopword
|
||
|
|
||
|
' Load Address Word Local with Index
|
||
|
lawlx call #getadrz
|
||
|
call #popx1
|
||
|
shl x, #1
|
||
|
add x, op2
|
||
|
add x, dbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Byte Local with Index
|
||
|
ldblx call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, dbase
|
||
|
jmp #ldbyte
|
||
|
|
||
|
' Store Byte Local with Index
|
||
|
stblx call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, dbase
|
||
|
jmp #stbyte
|
||
|
|
||
|
' Execute Byte Local with Index
|
||
|
exblx call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, dbase
|
||
|
jmp #exopbyte
|
||
|
|
||
|
' Load Address Byte Local with Index
|
||
|
lablx call #getadrz
|
||
|
call #popx1
|
||
|
add x, op2
|
||
|
add x, dbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Indexed VAR Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Long VAR with Index
|
||
|
ldlvx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, vbase
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long VAR with Index
|
||
|
stlvx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, vbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Execute Long VAR with Index
|
||
|
exlvx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, vbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Long VAR with Index
|
||
|
lalvx call #getadrz
|
||
|
call #popx1
|
||
|
shl x, #2
|
||
|
add x, op2
|
||
|
add x, vbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Word VAR with Index
|
||
|
ldwvx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, vbase
|
||
|
jmp #ldword
|
||
|
|
||
|
' Store Word VAR with Index
|
||
|
stwvx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, vbase
|
||
|
jmp #stword
|
||
|
|
||
|
' Execute Word VAR with Index
|
||
|
exwvx call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, vbase
|
||
|
jmp #exopword
|
||
|
|
||
|
' Load Address Word VAR with Index
|
||
|
lawvx call #getadrz
|
||
|
call #popx1
|
||
|
shl x, #1
|
||
|
add x, op2
|
||
|
add x, vbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Byte VAR with Index
|
||
|
ldbvx call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, vbase
|
||
|
jmp #ldbyte
|
||
|
|
||
|
' Store Byte VAR with Index
|
||
|
stbvx call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, vbase
|
||
|
jmp #stbyte
|
||
|
|
||
|
' Execute Byte VAR with Index
|
||
|
exbvx call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, vbase
|
||
|
jmp #exopbyte
|
||
|
|
||
|
' Load Address Byte VAR with Index
|
||
|
labvx call #getadrz
|
||
|
call #popx1
|
||
|
add x, op2
|
||
|
add x, vbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' DAT Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Word Object
|
||
|
ldwo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #ldword
|
||
|
|
||
|
' Store Word Object
|
||
|
stwo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #stword
|
||
|
|
||
|
' Execute Word Object
|
||
|
exwo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #exopword
|
||
|
|
||
|
' Load Byte Object
|
||
|
ldbo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #ldbyte
|
||
|
|
||
|
' Store Byte Object
|
||
|
stbo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #stbyte
|
||
|
|
||
|
' Execute Byte Object
|
||
|
exbo call #getadrz
|
||
|
mov adr, pbase
|
||
|
jmp #exopbyte
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Indexed DAT Variable Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Load Long Object with Index
|
||
|
ldlox call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, pbase
|
||
|
jmp #ldlong
|
||
|
|
||
|
' Store Long Object with Index
|
||
|
stlox call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, pbase
|
||
|
jmp #stlong
|
||
|
|
||
|
' Execute Long Object with Index
|
||
|
exlox call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #2
|
||
|
add adr, pbase
|
||
|
jmp #exoplong
|
||
|
|
||
|
' Load Address Long Object with Index
|
||
|
lalox call #getadrz
|
||
|
call #popx1
|
||
|
shl x, #2
|
||
|
add x, op2
|
||
|
add x, pbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Load Word Object with Index
|
||
|
ldwox call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, pbase
|
||
|
jmp #ldword
|
||
|
|
||
|
' Store Word Object with Index
|
||
|
stwox call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, pbase
|
||
|
jmp #stword
|
||
|
|
||
|
' Execute Word Object with Index
|
||
|
exwox call #getadrz
|
||
|
call #pop_adr
|
||
|
shl adr, #1
|
||
|
add adr, pbase
|
||
|
jmp #exopword
|
||
|
|
||
|
' Load Address Word Object with Index
|
||
|
lawox call #getadrz
|
||
|
call #popx1
|
||
|
shl x, #1
|
||
|
add x, op2
|
||
|
add x, pbase
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Execute Byte Object with Index
|
||
|
exbox call #getadrz
|
||
|
call #pop_adr
|
||
|
add adr, pbase
|
||
|
jmp #exopbyte
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Absolute Address Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
' Store Byte Absolute
|
||
|
stba call #popyx
|
||
|
jmp #stba1
|
||
|
|
||
|
' Store Word Absolute
|
||
|
stwa call #popyx
|
||
|
jmp #stwa1
|
||
|
|
||
|
' Store Long Absolute
|
||
|
stla call #popyx
|
||
|
jmp #stla1
|
||
|
|
||
|
' Execute Long Absolute
|
||
|
exla sub dcurr, #4
|
||
|
rdlong adr, dcurr
|
||
|
jmp #exoplong1
|
||
|
|
||
|
' Execute Word Absolute
|
||
|
exwa sub dcurr, #4
|
||
|
rdlong adr, dcurr
|
||
|
jmp #exopword1
|
||
|
|
||
|
' Execute Byte Absolute
|
||
|
exba sub dcurr, #4
|
||
|
rdlong adr, dcurr
|
||
|
jmp #exopbyte1
|
||
|
|
||
|
' Load Address Absolute (NOP)
|
||
|
la_a jmp #loop
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Absolute Address with Index Instructions
|
||
|
'***********************************************************************
|
||
|
' Load Byte Absolute with Index
|
||
|
' Store Byte Absolute with Index
|
||
|
stbax call #popayx
|
||
|
add y, a
|
||
|
stba1 wrbyte x, y
|
||
|
jmp #loop
|
||
|
|
||
|
' Store Word Absolute with Index
|
||
|
stwax call #popayx
|
||
|
shl a, #1
|
||
|
add y, a
|
||
|
stwa1 wrword x, y
|
||
|
jmp #loop
|
||
|
|
||
|
' Store Long Absolute with Index
|
||
|
stlax call #popayx
|
||
|
shl a, #2
|
||
|
add y, a
|
||
|
stla1 wrlong x, y
|
||
|
jmp #loop
|
||
|
|
||
|
' Execute Long Absolute with Index
|
||
|
exlax call #popay
|
||
|
shl a, #2
|
||
|
mov adr, y
|
||
|
add adr, a
|
||
|
jmp #exoplong1
|
||
|
|
||
|
' Load Address Long Absolute with Index
|
||
|
lalax call #popyx
|
||
|
shl y, #2
|
||
|
add x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Execute Word Absolute with Index
|
||
|
exwax call #popay
|
||
|
shl a, #1
|
||
|
mov adr, y
|
||
|
add adr, a
|
||
|
jmp #exopword1
|
||
|
|
||
|
' Load Address Word Absolute with Index
|
||
|
lawax call #popyx
|
||
|
shl y, #1
|
||
|
add x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
' Execute Word Absolute with Index
|
||
|
exbax call #popay
|
||
|
mov adr, y
|
||
|
add adr, a
|
||
|
jmp #exopbyte1
|
||
|
|
||
|
' Load Address Byte Absolute with Index
|
||
|
labax call #popyx
|
||
|
add x, y
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Extended Instructions
|
||
|
'***********************************************************************
|
||
|
|
||
|
sexb shl x, #24
|
||
|
sar x, #24
|
||
|
jmp savex
|
||
|
|
||
|
sexw shl x, #16
|
||
|
sar x, #16
|
||
|
jmp savex
|
||
|
|
||
|
preinc add x, #1
|
||
|
jmp savex
|
||
|
|
||
|
predec sub x, #1
|
||
|
jmp savex
|
||
|
|
||
|
' Repeat-from-to-step Instruction
|
||
|
repeats call #popay
|
||
|
sub dcurr, #4
|
||
|
rdlong t1, dcurr
|
||
|
jmp #repeaty
|
||
|
|
||
|
' Repeat-from-to Instruction
|
||
|
repeatx
|
||
|
call #popay 'pop data (a=to, y=from, t1=step)
|
||
|
mov t1, #1
|
||
|
repeaty call #getadrs
|
||
|
cmps a,y wc 'reverse range?
|
||
|
sumc x,t1 'add/sub step to/from var
|
||
|
call #range 'check if x in range y..a according to c
|
||
|
if_nc add pcurr,op2 'if in range, branch
|
||
|
mov op2, #0 'ensure we don't push to the stack
|
||
|
jmp savex
|
||
|
|
||
|
' Check range
|
||
|
' must be preceded by: cmps a,y wc
|
||
|
'
|
||
|
range if_c xor a,y 'if reverse range, swap range values
|
||
|
if_c xor y,a
|
||
|
if_c xor a,y
|
||
|
cmps x,y wc 'c=0 if x within range
|
||
|
if_nc cmps a,x wc
|
||
|
ret
|
||
|
|
||
|
randf neg t1, #1 wz
|
||
|
jmp #rand1
|
||
|
randr mov t1, #0 wz
|
||
|
rand1 min x,#1
|
||
|
mov y,#32
|
||
|
mov a,#%10111
|
||
|
if_z ror a,#1
|
||
|
rand2 test x,a wc
|
||
|
if_nz rcr x,#1
|
||
|
if_z rcl x,#1
|
||
|
djnz y,@rand2
|
||
|
jmp savex
|
||
|
|
||
|
_sarx call #popy1
|
||
|
sar x, y
|
||
|
jmp savex
|
||
|
|
||
|
_mulx call #popy1
|
||
|
mul32 x, y
|
||
|
getmull x
|
||
|
jmp savex
|
||
|
|
||
|
_mulhx call #popy1
|
||
|
mul32 x, y
|
||
|
getmulh x
|
||
|
jmp savex
|
||
|
|
||
|
_addx call #popy1
|
||
|
add x, y
|
||
|
jmp savex
|
||
|
|
||
|
_subx call #popy1
|
||
|
sub x, y
|
||
|
jmp savex
|
||
|
|
||
|
_xorx call #popy1
|
||
|
xor x, y
|
||
|
jmp savex
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Math Instructions
|
||
|
'***********************************************************************
|
||
|
_min call #popyx
|
||
|
min x, y
|
||
|
jmp savex
|
||
|
|
||
|
_max call #popyx
|
||
|
max x, y
|
||
|
jmp savex
|
||
|
|
||
|
_rev call #popyx
|
||
|
rev x, y
|
||
|
jmp savex
|
||
|
|
||
|
decode call #popy1
|
||
|
mov x, #1
|
||
|
shl x, y
|
||
|
jmp savex
|
||
|
|
||
|
encode call #popy1
|
||
|
mov x, #1
|
||
|
encode1 if_z jmp savex
|
||
|
add x, #1
|
||
|
shr y, #1 wz
|
||
|
jmp #encode1
|
||
|
|
||
|
_sqrt call #popx1
|
||
|
_sqrtx sqrt32 x
|
||
|
getsqrt x
|
||
|
jmp savex
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Extended Math Instructions
|
||
|
'***********************************************************************
|
||
|
_andlx cmp x, #0 wz
|
||
|
jmp #_andl+1
|
||
|
|
||
|
_orlx cmp x, #0 wz
|
||
|
jmp #_orl+1
|
||
|
|
||
|
_cmpltx call #popy1
|
||
|
jmp #_cmplt+1
|
||
|
|
||
|
_cmpgtx call #popy1
|
||
|
jmp #_cmpgt+1
|
||
|
|
||
|
_cmpnex call #popy1
|
||
|
jmp #_cmpne+1
|
||
|
|
||
|
_cmpeqx call #popy1
|
||
|
jmp #_cmpeq+1
|
||
|
|
||
|
_cmplex call #popy1
|
||
|
jmp #_cmple+1
|
||
|
|
||
|
_cmpgex call #popy1
|
||
|
jmp #_cmpge+1
|
||
|
|
||
|
_minx call #popy1
|
||
|
min x, y
|
||
|
jmp savex
|
||
|
|
||
|
_maxx call #popy1
|
||
|
max x, y
|
||
|
jmp savex
|
||
|
|
||
|
_revx call #popy1
|
||
|
rev x, y
|
||
|
jmp savex
|
||
|
|
||
|
decodex mov y, x
|
||
|
jmp #decode+1
|
||
|
|
||
|
encodex mov y, x
|
||
|
jmp #encode+1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' This code is used when absolute address 0 is accessed
|
||
|
'***********************************************************************
|
||
|
ldclkfreq mov x, ##_clkfreq
|
||
|
jmp #pushx1
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Trap for unsupported instructions
|
||
|
'***********************************************************************
|
||
|
_waitvi
|
||
|
_clkset
|
||
|
unsupp mov op2, #0
|
||
|
unsupx mov t1, ##@str1
|
||
|
call #putstr
|
||
|
mov t1, op
|
||
|
call #puthex
|
||
|
mov x, #" "
|
||
|
call #putch
|
||
|
mov t1, op2
|
||
|
call #puthex
|
||
|
mov x, #13
|
||
|
call #putch
|
||
|
cogid x
|
||
|
cogstop x
|
||
|
|
||
|
puthex rol t1, #28
|
||
|
call #puthexdigit
|
||
|
rol t1, #4
|
||
|
call #puthexdigit
|
||
|
ret
|
||
|
|
||
|
puthexdigit mov x, #15
|
||
|
and x, t1
|
||
|
mov y, ##@hexdigits
|
||
|
add y, x
|
||
|
rdbyte x, y
|
||
|
call #putch
|
||
|
ret
|
||
|
|
||
|
putstr rdbyte x, t1 wz
|
||
|
if_z ret
|
||
|
add t1, #1
|
||
|
call #putch
|
||
|
jmp #putstr
|
||
|
|
||
|
putch or x, #$100
|
||
|
shl x, #1
|
||
|
mov y, #10
|
||
|
getcnt a
|
||
|
add a, bitcycles
|
||
|
:loop ror x, #1 wc
|
||
|
'setpc #30
|
||
|
setpc #90
|
||
|
waitcnt a, bitcycles
|
||
|
djnz y, @:loop
|
||
|
ret
|
||
|
|
||
|
str1 byte "Unsupported opcode ", 0
|
||
|
hexdigits byte "0123456789ABCDEF"
|
||
|
|
||
|
'***********************************************************************
|
||
|
' Spin program binary file
|
||
|
'***********************************************************************
|
||
|
testprog file "test.binary"
|
||
|
|
||
|
{{
|
||
|
+-----------------------------------------------------------------------------+
|
||
|
| TERMS OF USE: MIT License |
|
||
|
+-----------------------------------------------------------------------------+
|
||
|
|Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||
|
|of this software and associated documentation files (the "Software"), to deal|
|
||
|
|in the Software without restriction, including without limitation the rights |
|
||
|
|to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||
|
|copies of the Software, and to permit persons to whom the Software is |
|
||
|
|furnished to do so, subject to the following conditions: |
|
||
|
| |
|
||
|
|The above copyright notice and this permission notice shall be included in |
|
||
|
|all copies or substantial portions of the Software. |
|
||
|
| |
|
||
|
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||
|
|IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||
|
|FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||
|
|AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||
|
|LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,|
|
||
|
|OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE|
|
||
|
|SOFTWARE. |
|
||
|
+-----------------------------------------------------------------------------+
|
||
|
}}
|