Any information regarding power requirements? Just doing some preliminary work for our in-house development boards and need a ball park figure to proceed.
Many thanks
Rob
We don't know yet, but on our module we are using a 2-amp 1.8V switching power supply. It's possible that the chip could dissipate over two watts, going full-bore with everything running. Hopefully, we'll know what the power requirements are in 8 weeks when we hope to get a working chip back from the foundry.
We don't know yet, but on our module we are using a 2-amp 1.8V switching power supply. It's possible that the chip could dissipate over two watts, going full-bore with everything running. Hopefully, we'll know what the power requirements are in 8 weeks when we hope to get a working chip back from the foundry.
8 weeks until a new chip! That's very exciting! Did you end up staying with TSMC or did you go to a different foundry?
2W seems like an awful lot, if that is indeed possible, you'll need to consider a thermally enhanced QFP (exposed pad type) and tie that into the PCB to dissipate that power.
It can't be just the logic, is that the peripheral analog circuitry? In which case the worst case won't be typical. In a standard QFP package of that size will see a 50 deg-C rise in junction temp/Watt. With most chips will begin failing at 150 C
We don't know yet, but on our module we are using a 2-amp 1.8V switching power supply. It's possible that the chip could dissipate over two watts, going full-bore with everything running. Hopefully, we'll know what the power requirements are in 8 weeks when we hope to get a working chip back from the foundry.
[Over] 2W seems like an awful lot, if that is indeed possible, you'll need to consider a thermally enhanced QFP (exposed pad type) and tie that into the PCB to dissipate that power.
Agreed, even as a theoretical maximum that seems a bit much.
2W seems like an awful lot, if that is indeed possible, you'll need to consider a thermally enhanced QFP (exposed pad type) and tie that into the PCB to dissipate that power.
Exposed pad is a relatively simple change, (I think no die impact?) and it would be a good idea to bond some of the pilot run into Exposed -Pad QFP.
That way, Parallax can measure the differences, and decide if the performance gains, are worth the (small) added cost.
The Exposed Pad variants I like the most, are ones where the package designer thought to allow via-space between the exposed pad, and pin areas.
In a larger package like TQFP128, this should be practical.
Are there any updates on Prop 2 Counters documenting ?
- have some threads been removed from here ? Seems less than there was in my browser.
I have been working on the new Spin compiler. I think I've got the interpreter code operable, but I must get the compiler done to prove it all. I've been working on this for over a month and so I haven't made any new documentation during this period. I really want to get the compiler operating, since that's the biggest thing hanging over my head, at this point. The rest is like a mop-up operation.
About a thermal-pad TQFP package: This could be done, but it will be a custom package design that will cost us $50k, since our die is too big for the thermal-pad package offered by our packager. If we see that the die works and runs hot, we'll spring for this, but first we must learn what we're dealing with.
CON
base = $E80'''***************'* Interpreter *'***************'DAT
orgh base
org$15B''' Append word to x - used to make $0xxxx or $1xxxx address'
xword rdbytec y,ptra++
xword_ret retd
movf x,y
rdbytec y,ptra++
movf x,y
''' call obj.sub' call obj.sub[]' call obj[].sub' call obj[].sub[]' call sub' call sub[]' call ptr'
call_obj shl x,#2'lookup obj vbase/pbase offsetsadd x,pbase
rdlong x,x
call_ptr rol x,#4'set relative pbaseadd pbase,x
and pbase,h0001FFF0
ror x,#16'set relative vbaseadd vbase,x
and vbase,h0001FFF0
call_sub shl y,#2'lookup locals/pbase offsetsadd y,pbase
rdlong y,y
mov dbase,dcall 'set call dbaseadd dbase,#3
setspb dcall 'get old dcallpopb dcall
getptra x 'set return pcurrpushb x
setptra pbase 'set call pcurr
jmpd #getbyte'loop to getbyte, delayed
addptra y
shr y,#32-4'add locals to dcurr
addspa y
''' Bitfield addressing, pop and set bitfield parameters'
bitfield popa bshift 'pop range lsbpopabmask'pop range msband bshift,#$1F'trim lsb/msbandbmask,#$1Fcmpbmask,bshift wc'reverse range?if_cxor bshift,bmask'if reverse range, swap msb/lsbif_cxorbmask,bshift
if_cxor bshift,bmasksubbmask,bshift 'get number of bitsaddbmask,#1neg brev,bmask'get rev count
bitfield_ret retd 'return, delayed
setbc brev,#6'save reverse flag
blmask bmask'get bitlength maskshlbmask,bshift 'bmask = mask, brev = reverse, bshift = lsb offset''' Write register, if OUTA..OUTD then update PINA..PIND (x = value)'
writer movd writer_reg,addr
movd writer_pin,addr
setb writer_pin,#9+3
writer_reg mov$000,x
writer_ret retd
xor addr,#$1F0test addr,#$1FCwz
writer_pin if_zmov$000,x
''' Do bitfield read (x = value)'
readb and x,bmask
jmpd #getbyteshr x,bshift
if_crev x,brev
pusha x
''' Do bitfield write (bval = value, writeb_i = write instruction)'
writeb popa x 'pop value to writeif_crev x,brev 'reverse bits?shl x,bshift 'shift into positionand x,bmask'mask bitsandn bval,bmask'mask away original bitsor x,bval 'merge bits
writeb_i pushbr x 'call #writer / pushbr x / wrxxxx x,addr
writeb_ret jmp #getbyte''' Do bitfield assignment (bval = value, assignb_i = write instruction, mask = sized mask)'
assignb_long mov mask,hFFFFFFFF 'set long mask
assignb movs jmpback,#assignb_ret 'set jmpback address to assignb_retmov x,bval 'save original value
jmpd #assign_op 'get math operator and execute, delayedand x,bmask'extract bitfield for operationshr x,bshift
if_crev x,brev
assignb_ret testb brev,#6wc'snippet returns to here, get reverse flag into ccall #writeb 'write bitfield
movs writeb_ret,#getbyte'restore jump to getbyteand x,mask 'mask it
jmpd #assign_p 'push it (optional), delayedand x,bmask'extract bitfield for pushingshr x,bshift
if_crev x,brev
''' Do assignment (x = value, assign_i = write instruction, mask = sized mask)'
assign_local mov assign_i,pushbrx 'set local write
assign_long mov mask,hFFFFFFFF 'set long mask
assign movs jmpback,#assign_ret 'set jmpback address to :ret
assign_op rdbytec a,ptra++ 'get math operator and flags
setzc a wz,wc'load flags, operator already in positionmuxz assign_p,h003C0000 'set push condition to z
jmpd #hotbyte 'load and execute math snippet, delayedif_cpopa y 'swap args?pusha x
if_cpusha y
assign_ret popa x 'snippet returns to here, pop value
assign_i pushbr x 'write it (call #writer / pushbr x / wrxxxx x,addr)and x,mask 'mask it
assign_p pusha x 'push it (optional)
movs jmpback,#getbyte'replace jmpback address, getbyte next''' Get byte code, look up descriptor long, load code longs in-line, execute, repeat'getbyte rdbytec a,ptra++ wz' get byte code, extended?if_z rdbytec a,ptra++ ' if extended, get extended byte codeif_zor a,#$100' ...and add offsetshl a,#2' shift to make long offset
hotbyte add a,descbase ' add base address of descriptor longsrdlong x,a '..2 get descriptor long
movd :reps,x '3 descriptor[8..0] holds code longs minus 1shr x,#7'4 descriptor[23..7] is code offset
setptrb x '5 point PTRB to code longs
:reps reps #1,#1'6 ready for fast in-line code load
setindb #snippet '7 point INDB to in-line code
rdlongc indb++,ptrb++ '0.. load code longs in-line using cached readmov indb++,jmpback '+1 finish in-line code with 'jmp #getbyte'shr x,#25-7wz,wc'+1 descriptor[31..25] is a value, [24] is C
snippet long0[22] '? execute in-line code snippet, loop''' Constants'
pushbrx pushbr x
callwriter call #writer
jmpback jmp #getbyte
descbase long @descs-4'account for $01 offset
h0001FFF0 long$0001FFF0'vbase/pbase mask
h003C0000 long$003C0000'conditional field bits
hFFFFFFFF long$FFFFFFFF'all bits
x long0'variables
y long0
a long0
b long0
addr long0'assignment
mask long0
bshift long0'bitfield addressingbmasklong0
brev long0
bval long0
dcall long0' pointer
dbase long0' pointeroutalong0'@$1F0 OUTA..OUTDoutblong0'@$1F1 (writes update PINA..PIND)outclong0'@$1F2
outd long0'@$1F3
vbase long0'@$1F4 pointer
pbase long0'@$1F5 pointer'''************************'* Bytecode Descriptors *'************************'
descs
' variable modifiers (14)
op_writep long%0000000_0 << 24 + @_clr << 7 + 0'write w/push %10 push
op_rep long%0000000_0 << 24 + @_rep << 7 + 12'repeat var %00 no
op_clr long%0000000_0 << 24 + @_clr << 7 + 1'clear %00 no
op_clrpost long%0000000_0 << 24 + @_clrpost << 7 + 0'clear post %00 push
op_set long%0000000_0 << 24 + @_set << 7 + 1'set %00 no
op_setpost long%0000000_0 << 24 + @_setpost << 7 + 0'set post %00 push
op_incpre long%0000000_0 << 24 + @_incdec << 7 + 3'inc pre / inc %10 push / %00 no
op_incpost long%0000001_0 << 24 + @_incdec << 7 + 3'inc post %00 push
op_decpre long%0000000_1 << 24 + @_incdec << 7 + 3'dec pre / dec %10 push / %00 no
op_decpost long%0000001_1 << 24 + @_incdec << 7 + 3'dec post %00 push
op_incmod long%0000000_0 << 24 + @_idmod << 7 + 6'incmod %00 no
op_incmodp long%0000001_0 << 24 + @_idmod << 7 + 6'incmod w/push %00 push
op_decmod long%0000000_1 << 24 + @_idmod << 7 + 6'decmod %00 no
op_decmodp long%0000001_1 << 24 + @_idmod << 7 + 6'decmod w/push %00 push' unaries (23)
op_notb long%0000000_0 << 24 + @_notb << 7 + 2'NOT %x0
op_not long%0000000_0 << 24 + @_not << 7 + 2'! %x0
op_neg long%0000000_0 << 24 + @_neg << 7 + 2'- %x0
op_abs long%0000000_0 << 24 + @_abs << 7 + 2'|| %x0
op_enc long%0000000_0 << 24 + @_enc << 7 + 2'>| %x0
op_decod5 long%0000000_0 << 24 + @_decod5 << 7 + 2'|<, DECOD5(x) %x0
op_decod4 long%0000000_0 << 24 + @_decod4 << 7 + 2'DECOD4(x) %x0
op_decod3 long%0000000_0 << 24 + @_decod3 << 7 + 2'DECOD3(x) %x0
op_decod2 long%0000000_0 << 24 + @_decod2 << 7 + 2'DECOD2(x) %x0
op_blmask long%0000000_0 << 24 + @_blmask << 7 + 2'BLMASK(x) %x0
op_onecnt long%0000000_0 << 24 + @_onecnt << 7 + 2'ONECNT(x) %x0
op_zercnt long%0000000_0 << 24 + @_zercnt << 7 + 2'ZERCNT(x) %x0
op_incpat long%0000000_0 << 24 + @_incpat << 7 + 2'INCPAT(x) %x0
op_decpat long%0000000_0 << 24 + @_decpat << 7 + 2'DECPAT(x) %x0
op_bingry long%0000000_0 << 24 + @_bingry << 7 + 2'BINGRY(x) %x0
op_grybin long%0000000_0 << 24 + @_grybin << 7 + 2'GRYBIN(x) %x0
op_mergew long%0000000_0 << 24 + @_mergew << 7 + 2'MERGEW(x) %x0
op_splitw long%0000000_0 << 24 + @_splitw << 7 + 2'SPLITW(x) %x0
op_seussf long%0000000_0 << 24 + @_seussf << 7 + 2'SEUSSF(x) %x0
op_seussr long%0000000_0 << 24 + @_seussr << 7 + 2'SEUSSR(x) %x0
op_sqrt long%0000000_0 << 24 + @_sqrt << 7 + 4'SQRT(x) %x0
op_qlog long%0000000_0 << 24 + @_qlogexp << 7 + 5'QLOG(x) %x0
op_qexp long%0000000_1 << 24 + @_qlogexp << 7 + 5'QEXP(x) %x0' binaries (23)
op_andb long%0000000_0 << 24 + @_andb << 7 + 4'AND %x1
op_orb long%0000000_0 << 24 + @_orb << 7 + 4'OR %x1
op_xorb long%0000000_0 << 24 + @_xorb << 7 + 5'XOR %x1
op_andn long%0000000_0 << 24 + @_andn << 7 + 3'&! %x1
op_and long%0000000_0 << 24 + @_and << 7 + 3'& %x1
op_or long%0000000_0 << 24 + @_or << 7 + 3'| %x1
op_xor long%0000000_0 << 24 + @_xor << 7 + 3'^ %x1
op_ror long%0000000_0 << 24 + @_ror << 7 + 3'-> %x1
op_rol long%0000000_0 << 24 + @_rol << 7 + 3'<- %x1
op_shr long%0000000_0 << 24 + @_shr << 7 + 3'>> %x1
op_shl long%0000000_0 << 24 + @_shl << 7 + 3'<< %x1
op_sar long%0000000_0 << 24 + @_sar << 7 + 3'~> %x1
op_sal long%0000000_0 << 24 + @_sal << 7 + 5'<~ %x1
op_rev long%0000000_0 << 24 + @_rev << 7 + 4'>< %x1
op_mins long%0000000_0 << 24 + @_mins << 7 + 3'#> %x1
op_maxs long%0000000_0 << 24 + @_maxs << 7 + 3'<# %x1
op_add long%0000000_0 << 24 + @_add << 7 + 3'+ %x1
op_sub long%0000000_0 << 24 + @_sub << 7 + 3'- %x1
op_mul long%0000000_0 << 24 + @_mul << 7 + 6'* %x1
op_scl long%0000001_0 << 24 + @_scl << 7 + 6'** %x1
op_quo long%0000000_0 << 24 + @_divx << 7 + 7'/ %x1
op_rem long%0000001_0 << 24 + @_divx << 7 + 7'// %x1
op_fra long%0000000_0 << 24 + @_fra << 7 + 7'*/ %x1' equality tests (6)
op_b long%0000000_0 << 24 + @_b << 7 + 4'<
op_a long%0000000_0 << 24 + @_a << 7 + 4'>
op_ne long%0000000_0 << 24 + @_ne << 7 + 4'<>
op_eq long%0000000_0 << 24 + @_eq << 7 + 4'==
op_be long%0000000_0 << 24 + @_be << 7 + 4'=< / <=
op_ae long%0000000_0 << 24 + @_ae << 7 + 4'=> / >=' math terms (8)
op_quo64 long%0000000_0 << 24 + @_divh64 << 7 + 10'QUO64(al,ah,b)
op_quo64u long%0000000_1 << 24 + @_divh64 << 7 + 10'QUO64U(al,ah,b)
op_rem64 long%0000001_0 << 24 + @_divh64 << 7 + 10'REM64(al,ah,b)
op_rem64u long%0000001_1 << 24 + @_divh64 << 7 + 10'REM64U(al,ah,b)
op_sqrt64 long%0000000_0 << 24 + @_sqrt64 << 7 + 6'SQRT64(l,h)
op_negb long%0000000_0 << 24 + @_negb << 7 + 3'NEGB(x,bool)
op_muxb long%0000000_0 << 24 + @_muxb << 7 + 4'MUXB(x,y,bool)
op_ternary long%0000000_0 << 24 + @_ternary << 7 + 4'sel ? true : false' math procedures (20)
op_mul64 long%0000000_0 << 24 + @_mul64 << 7 + 9'MUL64(a,b : l,h)
op_mulu64 long%0000000_1 << 24 + @_mul64 << 7 + 9'MUL64U(a,b : l,h)
op_div64 long%0000000_0 << 24 + @_div64 << 7 + 11'DIV64(a,b : l,h)
op_divu64 long%0000000_1 << 24 + @_div64 << 7 + 11'DIV64U(a,b : l,h)
op_qsincos long%0000000_0 << 24 + @_qtrig << 7 + 12'QSINCOS(r,t : x,y)
op_qarctan long%0000001_0 << 24 + @_qtrig << 7 + 12'QARCTAN(x,y : r,t)
op_qrotate long%0000000_1 << 24 + @_qtrig << 7 + 12'QROTATE(x,y,t : x,y)
op_setqi long%0000000_1 << 24 + @_div64 << 7 + 1'SETQI(x)
op_clraccs long%0000000_0 << 24 + @_clraccs << 7 + 0'CLRACCS
op_clracca long%0000000_0 << 24 + @_clracca << 7 + 0'CLRACCA
op_clraccb long%0000000_0 << 24 + @_clraccb << 7 + 0'CLRACCB
op_fitaccs long%0000000_0 << 24 + @_fitaccs << 7 + 0'FITACCS
op_fitacca long%0000000_0 << 24 + @_fitacca << 7 + 0'FITACCA
op_fitaccb long%0000000_0 << 24 + @_fitaccb << 7 + 0'FITACCB
op_setacca long%0000000_0 << 24 + @_setacca << 7 + 2'SETACCA(l,h)
op_setaccb long%0000000_0 << 24 + @_setaccb << 7 + 2'SETACCB(l,h)
op_getacca long%0000000_0 << 24 + @_getacca << 7 + 3'GETACCA(l,h)
op_getaccb long%0000000_0 << 24 + @_getaccb << 7 + 3'GETACCB(l,h)
op_maca long%0000000_0 << 24 + @_maca << 7 + 2'MACA(x,y)
op_macb long%0000000_0 << 24 + @_macb << 7 + 2'MACB(x,y)' constants (13)
op_con1n long%0000000_0 << 24 + @_conxn << 7 + 1'constant -1
op_con0 long%0000000_0 << 24 + @_conxp << 7 + 0'constant 0
op_con1 long%0000001_0 << 24 + @_conxp << 7 + 0'constant 1
op_con8p long%0000000_0 << 24 + @_con8p << 7 + 1'constant $000000xx
op_con9p long%0000000_0 << 24 + @_con9p << 7 + 2'constant $000001xx
op_con8n long%0000000_0 << 24 + @_con8n << 7 + 2'constant $FFFFFFxx
op_con16p long%0000000_0 << 24 + @_con16p << 7 + 3'constant $0000xxxx
op_con17p long%0000000_0 << 24 + @_con17p << 7 + 3'constant $0001xxxx
op_con16n long%0000000_0 << 24 + @_con16n << 7 + 4'constant $FFFFxxxx
op_con24p long%0000000_0 << 24 + @_con24 << 7 + 4'constant $00xxxxxx
op_con24n long%0000000_1 << 24 + @_con24 << 7 + 4'constant $FFxxxxxx
op_con32 long%0000000_0 << 24 + @_con32 << 7 + 4'constant $xxxxxxxx
op_conexp long%0000000_0 << 24 + @_conexp << 7 + 4'constant 2^n,dec,not' register reads/writes/assigns (6)
op_rdreg long%0000000_0 << 24 + @_rdreg << 7 + 4'read register
op_wrreg long%0000000_0 << 24 + @_wrreg << 7 + 2'write register
op_asreg long%0000000_0 << 24 + @_asreg << 7 + 5'assign register
op_rdregb long%0000000_0 << 24 + @_rdregb << 7 + 6'read register bitfield
op_wrregb long%0000000_0 << 24 + @_wrregb << 7 + 6'write register bitfield
op_asregb long%0000000_0 << 24 + @_asregb << 7 + 6'assign register bitfield' local reads/writes/assigns (54)
op_rdloc0 long%0000000_0 << 24 + @_rdloc << 7 + 3'read local 0
op_rdloc1 long%0000001_0 << 24 + @_rdloc << 7 + 3'read local 1
op_rdloc2 long%0000010_0 << 24 + @_rdloc << 7 + 3'read local 2
op_rdloc3 long%0000011_0 << 24 + @_rdloc << 7 + 3'read local 3
op_rdloc4 long%0000100_0 << 24 + @_rdloc << 7 + 3'read local 4
op_rdloc5 long%0000101_0 << 24 + @_rdloc << 7 + 3'read local 5
op_rdloc6 long%0000110_0 << 24 + @_rdloc << 7 + 3'read local 6
op_rdloc7 long%0000111_0 << 24 + @_rdloc << 7 + 3'read local 7
op_rdloc8 long%0001000_0 << 24 + @_rdloc << 7 + 3'read local 8
op_rdloc9 long%0001001_0 << 24 + @_rdloc << 7 + 3'read local 9
op_rdloc10 long%0001010_0 << 24 + @_rdloc << 7 + 3'read local 10
op_rdloc11 long%0001011_0 << 24 + @_rdloc << 7 + 3'read local 11
op_rdloc12 long%0001100_0 << 24 + @_rdloc << 7 + 3'read local 12
op_rdloc13 long%0001101_0 << 24 + @_rdloc << 7 + 3'read local 13
op_rdloc14 long%0001110_0 << 24 + @_rdloc << 7 + 3'read local 14
op_rdloc15 long%0001111_0 << 24 + @_rdloc << 7 + 3'read local 15
op_wrloc0 long%0000000_0 << 24 + @_wrloc << 7 + 3'write local 0
op_wrloc1 long%0000001_0 << 24 + @_wrloc << 7 + 3'write local 1
op_wrloc2 long%0000010_0 << 24 + @_wrloc << 7 + 3'write local 2
op_wrloc3 long%0000011_0 << 24 + @_wrloc << 7 + 3'write local 3
op_wrloc4 long%0000100_0 << 24 + @_wrloc << 7 + 3'write local 4
op_wrloc5 long%0000101_0 << 24 + @_wrloc << 7 + 3'write local 5
op_wrloc6 long%0000110_0 << 24 + @_wrloc << 7 + 3'write local 6
op_wrloc7 long%0000111_0 << 24 + @_wrloc << 7 + 3'write local 7
op_wrloc8 long%0001000_0 << 24 + @_wrloc << 7 + 3'write local 8
op_wrloc9 long%0001001_0 << 24 + @_wrloc << 7 + 3'write local 9
op_wrloc10 long%0001010_0 << 24 + @_wrloc << 7 + 3'write local 10
op_wrloc11 long%0001011_0 << 24 + @_wrloc << 7 + 3'write local 11
op_wrloc12 long%0001100_0 << 24 + @_wrloc << 7 + 3'write local 12
op_wrloc13 long%0001101_0 << 24 + @_wrloc << 7 + 3'write local 13
op_wrloc14 long%0001110_0 << 24 + @_wrloc << 7 + 3'write local 14
op_wrloc15 long%0001111_0 << 24 + @_wrloc << 7 + 3'write local 15
op_asloc0 long%0000000_0 << 24 + @_asloc << 7 + 3'assign local 0
op_asloc1 long%0000001_0 << 24 + @_asloc << 7 + 3'assign local 1
op_asloc2 long%0000010_0 << 24 + @_asloc << 7 + 3'assign local 2
op_asloc3 long%0000011_0 << 24 + @_asloc << 7 + 3'assign local 3
op_asloc4 long%0000100_0 << 24 + @_asloc << 7 + 3'assign local 4
op_asloc5 long%0000101_0 << 24 + @_asloc << 7 + 3'assign local 5
op_asloc6 long%0000110_0 << 24 + @_asloc << 7 + 3'assign local 6
op_asloc7 long%0000111_0 << 24 + @_asloc << 7 + 3'assign local 7
op_asloc8 long%0001000_0 << 24 + @_asloc << 7 + 3'assign local 8
op_asloc9 long%0001001_0 << 24 + @_asloc << 7 + 3'assign local 9
op_asloc10 long%0001010_0 << 24 + @_asloc << 7 + 3'assign local 10
op_asloc11 long%0001011_0 << 24 + @_asloc << 7 + 3'assign local 11
op_asloc12 long%0001100_0 << 24 + @_asloc << 7 + 3'assign local 12
op_asloc13 long%0001101_0 << 24 + @_asloc << 7 + 3'assign local 13
op_asloc14 long%0001110_0 << 24 + @_asloc << 7 + 3'assign local 14
op_asloc15 long%0001111_0 << 24 + @_asloc << 7 + 3'assign local 15
op_rdloci long%0000000_0 << 24 + @_rdloci << 7 + 6'read local indexed
op_wrloci long%0000000_0 << 24 + @_wrloci << 7 + 6'write local indexed
op_asloci long%0000000_0 << 24 + @_asloci << 7 + 6'assign local indexed
op_rdlocb long%0000000_0 << 24 + @_rdlocb << 7 + 5'read local bitfield
op_wrlocb long%0000000_0 << 24 + @_wrlocb << 7 + 6'write local bitfield
op_aslocb long%0000000_0 << 24 + @_aslocb << 7 + 6'assign local bitfield' memory reads/writes/assigns (18)
op_rdbyte long%0000000_0 << 24 + @_rdbyte << 7 + 2'read byte
op_rdword long%0000000_0 << 24 + @_rdword << 7 + 2'read word
op_rdlong long%0000000_0 << 24 + @_rdlong << 7 + 2'read long
op_wrbyte long%0000000_0 << 24 + @_wrbyte << 7 + 2'write byte
op_wrword long%0000000_0 << 24 + @_wrword << 7 + 2'write word
op_wrlong long%0000000_0 << 24 + @_wrlong << 7 + 2'write long
op_asbyte long%0000000_0 << 24 + @_asbyte << 7 + 5'assign byte
op_asword long%0000000_0 << 24 + @_asword << 7 + 6'assign word
op_aslong long%0000000_0 << 24 + @_aslong << 7 + 4'assign long
op_rdbyteb long%0000000_0 << 24 + @_rdbyteb << 7 + 3'read byte bitfield
op_rdwordb long%0000000_0 << 24 + @_rdwordb << 7 + 3'read word bitfield
op_rdlongb long%0000000_0 << 24 + @_rdlongb << 7 + 3'read long bitfield
op_wrbyteb long%0000000_0 << 24 + @_wrbyteb << 7 + 5'write byte bitfield
op_wrwordb long%0000000_0 << 24 + @_wrwordb << 7 + 5'write word bitfield
op_wrlongb long%0000000_0 << 24 + @_wrlongb << 7 + 5'write long bitfield
op_asbyteb long%0000000_0 << 24 + @_asbyteb << 7 + 6'assign byte bitfield
op_aswordb long%0000000_0 << 24 + @_aswordb << 7 + 7'assign word bitfield
op_aslongb long%0000000_0 << 24 + @_aslongb << 7 + 5'assign long bitfield' memory offsets and indexing (7)
op_vbase0 long%0000000_0 << 24 + @_base << 7 + 3'vbase $0xxxx
op_pbase0 long%0000000_1 << 24 + @_base << 7 + 3'pbase $0xxxx
op_vbase1 long%0000001_0 << 24 + @_base << 7 + 3'vbase $1xxxx
op_pbase1 long%0000001_1 << 24 + @_base << 7 + 3'pbase $1xxxx
op_ibyte long%0000000_0 << 24 + @_index << 7 + 4'byte index
op_iword long%0000001_0 << 24 + @_index << 7 + 4'word index
op_ilong long%0000010_0 << 24 + @_index << 7 + 4'long index' branches jmp/jz/jnz/tjz/djnz (10)
op_jmp0 long%0000000_0 << 24 + @_jmp << 7 + 1'jmp +$0xxxx
op_jmp1 long%0000001_0 << 24 + @_jmp << 7 + 1'jmp +$1xxxx
op_jz0 long%0000000_1 << 24 + @_jxz << 7 + 2'jz +$0xxxx
op_jz1 long%0000001_1 << 24 + @_jxz << 7 + 2'jz +$1xxxx
op_jnz0 long%0000000_0 << 24 + @_jxz << 7 + 2'jnz +$0xxxx
op_jnz1 long%0000001_0 << 24 + @_jxz << 7 + 2'jnz +$1xxxx
op_tjz0 long%0000000_0 << 24 + @_tjz << 7 + 3'tjz +$0xxxx
op_tjz1 long%0000001_0 << 24 + @_tjz << 7 + 3'tjz +$1xxxx
op_djnz0 long%0000000_0 << 24 + @_djnz << 7 + 4'djnz +$0xxxx
op_djnz1 long%0000001_0 << 24 + @_djnz << 7 + 4'djnz +$1xxxx' anchor drops (4)
op_dropt long%0000000_0 << 24 + @_drop << 7 + 6'drop, \sub
op_droptr long%0000001_0 << 24 + @_drop << 7 + 6'drop, \sub w/result
op_drop long%0000010_0 << 24 + @_drop << 7 + 6'drop, sub
op_dropr long%0000011_0 << 24 + @_drop << 7 + 6'drop, sub w/result' calls (7)
op_callos long%0000000_0 << 24 + @_callobj << 7 + 6'call obj.sub
op_callosi long%0000000_1 << 24 + @_callobj << 7 + 6'call obj.sub[]
op_callois long%0000001_0 << 24 + @_callobj << 7 + 6'call obj[].sub
op_calloisi long%0000001_1 << 24 + @_callobj << 7 + 6'call obj[].sub[]
op_calls long%0000000_0 << 24 + @_callsub << 7 + 3'call sub
op_callsi long%0000000_1 << 24 + @_callsub << 7 + 3'call sub[]
op_callp long%0000000_0 << 24 + @_callptr << 7 + 10'call ptr' returns (4)
op_return long%0000000_0 << 24 + @_return << 7 + 13'RETURN
op_abort long%0000000_1 << 24 + @_return << 7 + 13'ABORT
op_returnv long%0000001_0 << 24 + @_return << 7 + 13'RETURN value
op_abortv long%0000001_1 << 24 + @_return << 7 + 13'ABORT value' call pointer generation (5)
op_basesub long%0000000_0 << 24 + @_basesub << 7 + 5'vbase/pbase of current
op_baseobj long%0000000_0 << 24 + @_baseobj << 7 + 16'vbase/pbase of obj
op_baseobji long%0000000_1 << 24 + @_baseobj << 7 + 16'vbase/pbase of obj[]
op_subptr long%0000000_0 << 24 + @_subptr << 7 + 11'base.sub
op_subptri long%0000000_1 << 24 + @_subptr << 7 + 11'base.sub[]' case (5)
op_casev0 long%0000000_0 << 24 + @_casev << 7 + 5'case value, +$0xxxx branch
op_casev1 long%0000001_0 << 24 + @_casev << 7 + 5'case value, +$1xxxx branch
op_caser0 long%0000000_0 << 24 + @_caser << 7 + 10'case range, +$0xxxx branch
op_caser1 long%0000001_0 << 24 + @_caser << 7 + 10'case range, +$1xxxx branch
op_casedone long%0000000_0 << 24 + @_casedone << 7 + 2'case done' lookup/lookdown (5)
op_lookupv long%0000000_0 << 24 + @_lookupv << 7 + 9'lookup value
op_lookupr long%0000000_0 << 24 + @_lookupr << 7 + 14'lookup range
op_lookdnv long%0000000_0 << 24 + @_lookdnv << 7 + 9'lookdown value
op_lookdnr long%0000000_0 << 24 + @_lookdnr << 7 + 15'lookdown range
op_lookdone long%0000000_0 << 24 + @_lookdone << 7 + 1'lookup/lookdown done' miscellaneous (6)
op_pop long%0000000_0 << 24 + @_pop << 7 + 1'pop
op_clkset long%0000000_0 << 24 + @_clkset << 7 + 1'clkset
op_cogid long%0000000_0 << 24 + @_cogid << 7 + 1'cogid
op_coginit long%0000000_0 << 24 + @_coginit << 7 + 6'coginit
op_coginitp long%0000001_0 << 24 + @_coginit << 7 + 6'coginit w/push
op_cogstop long%0000000_0 << 24 + @_cogstop << 7 + 1'cogstop'''************'* Snippets *'************'''' Variable modifiers'org snippet 'repeat-var loop (assign)
_rep popa mask 'pop varpopa y 'pop steppopa b 'pop terminalpopa a 'pop initialpopa addr 'pop branch offsetcmps b,a wc'get reverse range into csumc mask,y 'update var with steprcl x,#1wz'get c into nzif_zcmps b,mask wc'if forward range, check if var > terminalif_nzcmps mask,b wc'if reverse range, check if var < terminalif_nc subptra addr 'if var within range, branchif_nc addspa #4'..unpop offset/initial/terminal/steppusha mask 'push new varorg snippet 'var~, clear and post-clear (assign)
_clr popa x 'clear, pop var (single pop also used by op_writep)
_clrpost pusha #0'post-clear, push 0 (leave var on stack)org snippet 'var~~, set and post-set (assign)
_set popa x 'set, pop var
_setpost pusha hFFFFFFFF 'post-set, push -1 (leave var on stack)org snippet '++var/--var/var++/var-- (assign)
_incdec popa x 'pop varif_nzpusha x 'if nz, push original varsumc x,#1'inc or dec var by cpusha x 'push new varorg snippet 'INCMOD/DECMOD(var,limit) (assign)
_idmod setbc :i,#26'set INCMOD/DECMOD by cpopa y 'pop limitpopa x 'pop var
:i incmod x,y wc'incmod/decmod, c=limitif_nz_and_ncpusha #0'push false if nz and ncif_nz_and_cpusha hFFFFFFFF 'push true if nz and cpusha x 'push new var''' Unary functions'org snippet
_notb popa x wz'NOT, booleanmuxz x,hFFFFFFFF
pusha x
org snippet
_not popa x '!, bitwise notnot x
pusha x
org snippet
_neg popa x '-, negateneg x,x
pusha x
org snippet
_abs popa x '||, absoluteabs x,x
pusha x
org snippet
_enc popa x '>|, encode (0..32)
enc x,x
pusha x
org snippet
_decod5 popa x '|< / DECOD5(x)
decod5 x
pusha x
org snippet
_decod4 popa x 'DECOD4(x)
decod4 x
pusha x
org snippet
_decod3 popa x 'DECOD3(x)
decod3 x
pusha x
org snippet
_decod2 popa x 'DECOD2(x)
decod2 x
pusha x
org snippet
_blmask popa x 'BLMASK(x)
blmask x
pusha x
org snippet
_onecnt popa x 'ONECNT(x)
onecnt x
pusha x
org snippet
_zercnt popa x 'ZERCNT(x)
zercnt x
pusha x
org snippet
_incpat popa x 'INCPAT(x)
incpat x
pusha x
org snippet
_decpat popa x 'DECPAT(x)
decpat x
pusha x
org snippet
_bingry popa x 'BINGRY(x)
bingry x
pusha x
org snippet
_grybin popa x 'GRYBIN(x)
grybin x
pusha x
org snippet
_mergew popa x 'MERGEW(x)mergew x
pusha x
org snippet
_splitw popa x 'SPLITW(x)splitw x
pusha x
org snippet
_seussf popa x 'SEUSSF(x)seussf x
pusha x
org snippet
_seussr popa x 'SEUSSR(x)seussr x
pusha x
org snippet
_sqrt popa x 'SQRT(x)
setsqrl x
getsqrt x wcif_ncjmp #$-1pusha x
org snippet
_qlogexp popa x 'QLOG(x), c=0if_ncqlog x 'QEXP(x), c=1if_cqexp x
getqz x wcif_ncjmp #$-1pusha x
''' Binary functions'org snippet
_andb popa x wz'AND, booleanif_zpopa x
if_nzpopa x wzmuxnz x,hFFFFFFFF
pusha x
org snippet
_orb popa x wz'OR, booleanif_nzpopa x
if_zpopa x wzmuxnz x,hFFFFFFFF
pusha x
org snippet
_xorb popa y wz'XOR, booleanmuxnz y,hFFFFFFFF
popa x wzmuxnz x,hFFFFFFFF
xor x,y
pusha x
org snippet
_andn popa y '&!, bitwise andnotpopa x
andn x,y
pusha x
org snippet
_and popa y '&, bitwise andpopa x
and x,y
pusha x
org snippet
_or popa y '|, bitwise orpopa x
or x,y
pusha x
org snippet
_xor popa y '^, bitwise xorpopa x
xor x,y
pusha x
org snippet
_ror popa y '->, rotate rightpopa x
ror x,y
pusha x
org snippet
_rol popa y '<-, rotate leftpopa x
rol x,y
pusha x
org snippet
_shr popa y '>>, shift rightpopa x
shr x,y
pusha x
org snippet
_shl popa y '<<, shift leftpopa x
shl x,y
pusha x
org snippet
_sar popa y '~>, shift arithmetic rightpopa x
sar x,y
pusha x
org snippet
_sal popa y '<~, shift arithmetic leftpopa x
rev x,#0sar x,y
rev x,#0pusha x
org snippet
_rev popa y '><, reverse bitspopa x
neg y,y
rev x,y
pusha x
org snippet
_mins popa y '|>, limit minimumpopa x
mins x,y
pusha x
org snippet
_maxs popa y '<|, limit maximumpopa x
maxs x,y
pusha x
org snippet
_add popa y '+, addpopa x
add x,y
pusha x
org snippet
_sub popa y '-, subpopa x
sub x,y
pusha x
org snippet
_mul popa y '*, multiply and return lower longpopa x
setmula x
setmulb y
getmull x wcif_ncjmp #$-1pusha x
org snippet
_scl popa y '**, multiply return upper long, unsignedpopa x
setmulu x
setmulb y
getmulh x wcif_ncjmp #$-1pusha x
org snippet
_divx popa y '/, divide and return quotient, z=1popa x '//, divide and return remainder, z=0
setdiva x
setdivb y
getdivq x wcif_ncjmp #$-1if_nz getdivr x
pusha x
org snippet
_fra popa y '*/, fractionpopa x
setdivu #0
setdivu x
setdivb y
getdivq x wcif_ncjmp #$-1pusha x
''' Equality tests'org snippet
_b popa y '<, test belowpopa x
cmps x,y wcmuxc x,hFFFFFFFF
pusha x
org snippet
_a popa y '>, test abovepopa x
cmps y,x wcmuxc x,hFFFFFFFF
pusha x
org snippet
_ne popa y '<>, test not equalpopa x
cmps x,y wzmuxnz x,hFFFFFFFF
pusha x
org snippet
_eq popa y '==, test equalpopa x
cmps x,y wzmuxz x,hFFFFFFFF
pusha x
org snippet
_be popa y '=< / <=, test below or equalpopa x
cmps y,x wcmuxnc x,hFFFFFFFF
pusha x
org snippet
_ae popa y '=> / >=, test above or equalpopa x
cmps x,y wcmuxnc x,hFFFFFFFF
pusha x
''' Math terms'org snippet
_divh64 popa y 'QUO64(al,ah,b), z=1, c=0popa x 'QUO64U(al,ah,b), z=1, c=1popa a 'REM64(al,ah,b), z=0, c=0if_nc setdiva a 'REM64U(al,ah,b), z=0, c=1if_c setdivu a
setdiva x
setdivb y
getdivq x wcif_ncjmp #$-1if_nz getdivr x wcpusha x
org snippet
_sqrt64 popa x 'SQRT64(l,h)
setsqrh x
popa x
setsqrl x
getsqrt x wcif_ncjmp #$-1pusha x
org snippet
_negb popa x wz'NEGB(x,bool)popa x
negnz x,x
pusha x
org snippet
_muxb popa y wz'MUXB(x,y,bool)popa y
popa x
muxnz x,y
pusha x
org snippet
_ternary popa y 'a ? x : ypopa x
popa a wzif_zpusha y
if_nzpusha x
''' Math procedures'org snippet
_mul64 popa x 'MUL64(a,b : l,h), c=0if_nc setmula x 'MUL64U(a,b : l,h), c=1if_c setmulu x
popa x
setmulb x
getmulh x wcif_ncjmp #$-1pusha x
getmull x
pusha x
org snippet
_div64 popa y 'DIV64(al,ah,b : q,r), c=0popa x 'DIV64U(al,ah,b : q,r), c=1popa a
if_nc setdiva a
if_c setdivu a
setdiva x
setdivb y
getdivr x wcif_ncjmp #$-1pusha x
getdivq x wcpusha x
org snippet
_qtrig if_z_and_cpopa x 'QSINCOS(r,t : x,y), z=1, c=0if_z_and_c setqz x 'QROTATE(x,y,t : x,y), z=1, c=1popa y 'QARCTAN(x,y : r,t), z=0popa x
if_z_and_nc qsincos y,x
if_z_and_cqrotate x,y
if_nz qarctan x,y
getqz x wcif_ncjmp #$-1if_zgetqy x
pusha x
getqx x
pusha x
org snippet
_setqi popa x 'SETQI(i)
setqi x
org snippet
_clraccs clraccs 'CLRACCSorg snippet
_clracca clracca 'CLRACCAorg snippet
_clraccb clraccb 'CLRACCBorg snippet
_fitaccs fitaccs 'FITACCSorg snippet
_fitacca fitacca 'FITACCAorg snippet
_fitaccb fitaccb 'FITACCBorg snippet
_setacca popa y 'SETACCA(l,h)popa x
setacca x,y
org snippet
_setaccb popa y 'SETACCB(l,h)popa x
setaccb x,y
org snippet
_getacca getacca x 'GETACCA(l,h)
getacca y
pusha y
pusha x
org snippet
_getaccb getaccb x 'GETACCB(l,h)
getaccb y
pusha y
pusha x
org snippet
_maca popa y 'MACA(x,y)popa x
maca x,y
org snippet
_macb popa y 'MACB(x,y)popa x
macb x,y
''' Constants'org snippet
_con8p rdbytec x,ptra++ 'con8p
_conxp pusha x 'con0..con3org snippet
_con9p rdbytec x,ptra++ 'con9p
setb x,#8pusha x
org snippet
_con8n rdbytec x,ptra++ 'con8n
_conxn xor x,hFFFFFFFF 'conm1pusha x
org snippet
_con16p rdbytec x,ptra++ 'con16p
rdbytec y,ptra++
movf x,y
pusha x
org snippet
_con17p rdbytec x,ptra++ 'con17p
rdbytec y,ptra++
movf x,y
setb x,#16pusha x
org snippet
_con16n rdbytec x,ptra++ 'con16n
rdbytec y,ptra++
movf x,y
xor x,hFFFFFFFF
pusha x
org snippet
_con24 reps #3,#2'con24p, con24nmuxc x,#$FF
rdbytec y,ptra++
movf x,y
pusha x
_con32 reps #4,#2'con32nop
rdbytec y,ptra++
movf x,y
pusha x
org snippet
_conexp rdbytec x,ptra++ 'conexp
decod5 x wz, wcif_zsub x,#1if_cnot x
pusha x
''' Register read/write/assign'org snippet
_rdreg popa x 'read register
movd :rd,x
nopnop
:rd pusha$000org snippet
_wrreg popa addr 'write registerpopa x
call #writer
org snippet
_asreg popa addr 'assign register
movs :rd,addr
jmpd #assign_long
mov assign_i,callwriter
:rd mov x,$000noporg snippet
_rdregb call #bitfield 'read register bitfieldpopa x
movs :rd,x
jmpd #readb
nop
:rd mov x,$000noporg snippet
_wrregb call #bitfield 'write register bitfieldpopa addr
movs :rd,addr
jmpd #writeb
mov writeb_i,callwriter
:rd mov bval,$000noporg snippet
_asregb call #bitfield 'assign register bitfieldpopa addr
movs :rd,addr
jmpd #assignb_long
mov writeb_i,callwriter
:rd mov bval,$000nop''' Local read/write/assign'org snippet
_rdloci popa y 'read local, indexed
rdbytec x,ptra++
add x,y
_rdloc add x,dbase 'read local, fixed
setspb x
popbr x
pusha x
org snippet
_wrloci popa y 'write local, indexed
rdbytec x,ptra++
add x,y
_wrloc add x,dbase 'write local, fixed
setspb x
popa x
pushb x
org snippet
_asloci popa y 'assign local, indexed
rdbytec x,ptra++
add x,y
_asloc jmpd #assign_local 'assign local, fixedadd x,dbase
setspb x
popbr x
org snippet
_rdlocb call #bitfield 'read local bitfieldpopa x
jmpd #readb
add x,dbase
setspb x
popbr x
org snippet
_wrlocb call #bitfield 'write local bitfieldpopa x
add x,dbase
jmpd #writeb
setspb x
popbr bval
mov writeb_i,pushbrx
org snippet
_aslocb call #bitfield 'assign local bitfieldpopa x
add x,dbase
jmpd #assignb_long
setspb x
popbr bval
mov writeb_i,pushbrx
''' Memory read/write/assign'org snippet
_rdbyte popa x 'read byterdbyte x,x
pusha x
org snippet
_rdword popa x 'read wordrdword x,x
pusha x
org snippet
_rdlong popa x 'read longrdlong x,x
pusha x
org snippet
_wrbyte popa y 'write bytepopa x
wrbyte x,y
org snippet
_wrword popa y 'write wordpopa x
wrword x,y
org snippet
_wrlong popa y 'write longpopa x
wrlong x,y
org snippet
_asbyte popa addr 'assign byte
jmpd #assign
rdbyte x,addr
mov assign_i,:i
mov mask,#$FF
:i wrbyte x,addr
org snippet
_asword popa addr 'assign word
jmpd #assign
rdword x,addr
mov assign_i,:i
mov mask,:m
:i wrword x,addr
:m long$0000FFFForg snippet
_aslong jmpd #assign_long 'assign longpopa addr
rdlong x,addr
mov assign_i,:i
:i wrlong x,addr
org snippet
_rdbyteb call #bitfield 'read byte bitfieldpopa x
rdbyte x,x
jmp #readb
org snippet
_rdwordb call #bitfield 'read word bitfieldpopa x
rdword x,x
jmp #readb
org snippet
_rdlongb call #bitfield 'read long bitfieldpopa x
rdlong x,x
jmp #readb
org snippet
_wrbyteb call #bitfield 'write byte bitfield
jmpd #writeb
popa addr
rdbyte bval,addr
mov writeb_i,:wr
:wr wrbyte x,addr
org snippet
_wrwordb call #bitfield 'write word bitfield
jmpd #writeb
popa addr
rdword bval,addr
mov writeb_i,:wr
:wr wrword x,addr
org snippet
_wrlongb call #bitfield 'write long bitfield
jmpd #writeb
popa addr
rdlong bval,addr
mov writeb_i,:wr
:wr wrlong x,addr
org snippet
_asbyteb call #bitfield 'assign byte bitfieldmov mask,#$FF
jmpd #assignb
popa addr
rdbyte bval,addr
mov writeb_i,:wr
:wr wrbyte x,addr
org snippet
_aswordb call #bitfield 'assign word bitfieldmov mask,:mask
jmpd #assignb
popa addr
rdword bval,addr
mov writeb_i,:wr
:wr wrword x,addr
:mask long$0000FFFForg snippet
_aslongb call #bitfield 'assign long bitfield
jmpd #assignb_long
popa addr
rdlong bval,addr
mov writeb_i,:wr
:wr wrlong x,addr
''' Memory offsets and indexing'org snippet
_base call #xword
if_ncadd x,vbase 'vbase, c=0if_cadd x,pbase 'pbase, c=1pusha x
org snippet
_index popa y 'ibyte, x=0shl y,x 'iword, x=1popa x 'ilong, x=2add x,y
pusha x
''' Branch jmp/jz/jnz/tjz/djnz'org snippet
_jmp call #xword 'jmp
addptra x
org snippet
_jxz popa y wz'jz, c=1 jnz, c=0call #xword
if_z_eq_c addptra x
org snippet
_tjz popa y wz'tjzif_nzpusha y
call #xword
if_z addptra x
org snippet
_djnz popa y 'djnzsub y,#1wzif_nzpusha y
call #xword
if_nz addptra x
''' Drop anchor'' \sub x = %00' \sub result x = %01' sub x = %10' sub result x = %11'org snippet
_drop pusha dcall 'push dcall (later used for pcurr)
getspa dcall 'set new dcallpusha dbase 'push return dbasepusha vbase 'push return vbaseor x,pbase 'push return pbase w/flagspusha x
pusha #0'init 'result' to 0''' Call'' obj.sub z=1, c=0' obj.sub[] z=1, c=1' obj[].sub z=0, c=0' obj[].sub[] z=0, c=1' sub c=0' sub[] c=1' ptr'org snippet
_callobj rdbytec x,ptra++ 'get obj byteif_nzpopa a 'add any indexif_nzadd x,a
jmpd #call_obj 'jump to handler, delayed
rdbytec y,ptra++ 'get sub byteif_cpopa a 'add any indexif_cadd y,a
org snippet
_callsub jmpd #call_sub 'jump to handler, delayed
rdbytec y,ptra++ 'get sub byteif_cpopa a 'add any indexif_cadd y,a
org snippet
_callptr popa x 'get sub [31..29]/[15..13], vbase [28..16], pbase [12..0]mov vbase,#0'clear vbase/pbasemov pbase,#0mov y,x 'get sub (6-bits)mov a,x
shr y,#32-3-3and y,#%111000
jmpd #call_ptr 'jump to handler, delayedshr a,#16-3and a,#%000111or y,a
''' RETURN/ABORT'' RETURN z=1, c=0' ABORT z=1, c=1' RETURN value z=0, c=0' ABORT value z=0, c=1'org snippet
_return if_z setspa dbase 'if no value, return resultif_z popar x
if_nzpopa x 'if value, pop it
:again setspa dbase 'set dbasepopa pbase 'pop pbaseif_ctest pbase,#%10wc'if abort and try, return againif_c jmpd #:again
popa vbase 'pop vbasepopa dbase 'pop dbasepopa y 'pop pcurr
setptra y 'set ptra to pcurrtest pbase,#%01wc'push result?andn pbase,#%11if_cpusha x
''' Get vbase/pbase'org snippet
_basesub mov y,vbase
shl y,#16-4mov x,pbase
shr x,#4or x,y
pusha x
''' Get pbase/vbase of obj'' obj c=0' obj[] c=1'org snippet
_baseobj rdbytec x,ptra++ 'get obj byteif_cpopa y 'handle indexif_cadd x,y
shl x,#2'scale offsetadd x,pbase 'get obj pbase/vbase offsetrdlong x,x
mov y,x 'get obj vbaseshr y,#16-4add y,vbase
and y,h0001FFF0
shl y,#16-4shl x,#4'get obj pbaseadd x,pbase
and x,h0001FFF0
shr x,#4or x,y 'merge vbase/pbasepusha x 'push obj vbase/pbase''' Make subroutine ptr'' base.sub c=0' base.sub[] c=1'org snippet
_subptr rdbytec a,ptra++ 'get sub numberif_cpopa b 'handle sub indexif_cadd a,b
mov b,a 'split 6-bit indexand b,#%111000'top 3 bits into [31..29]shl b,#32-6and a,#%000111'bottom 3 bits into [15..13]shl a,#16-3popa x 'pop base vbase/pbaseor x,b 'install index into pbase/vbaseor x,a
pusha x 'push subroutine pointer''' Case'org snippet 'case value
_casev call #xword 'get branch addresspopa a 'pop valuepopa y 'pop targetcmp a,y wz'value = target?if_nz addspa #1'if mismatch, unpop targetif_z addptra x 'if match, branchorg snippet 'case range (z=1)
_caser call #xword 'get branch addresspopa b 'pop range endpopa a 'pop range beginpopa y 'pop targetsub b,a '||(end - begin), c=1 if reverse rangeabs b,b wcsub y,a '+/-(target - begin)negc y,y
cmp b,y wc'match if ||(end - begin) => +/-(target - begin)if_c addspa #1'if mismatch, unpop targetif_nc addptra x 'if match, branchorg snippet 'case done
_casedone popa x 'pop targetpopa x 'pop address
addptra x 'jump to address''' Lookup/lookdown'org snippet 'lookup value
_lookupv popa a 'pop valuepopa x 'pop indexpopa y 'pop targetcmp x,y wz'match if index = targetif_nz addspa #1'if no match, unpop targetif_nzadd x,#1'..increment indexif_nzpusha x '..push indexif_zpopa addr 'if match, pop addressif_zpusha a '..push resultif_z setptra addr '..branchorg snippet 'lookup range
_lookupr popa b 'pop range endpopa a 'pop range beginpopa x 'pop indexpopa y 'pop targetsub b,a 'end - beginabs b,b wc'||(end - begin), c=1 if reverse rangesub y,x 'target - indexsumc a,y 'result = begin +/- (target - index)cmp b,y wc'match if ||(end - begin) => (target - index)if_c addspa #1'if no match, unpop targetif_caddx x,b '..add ||(end - begin) + 1 to indexif_cpusha x '..push indexif_ncpopa addr 'if match, pop addressif_ncpusha a '..push resultif_nc setptra addr '..branchorg snippet 'lookdown value
_lookdnv popa a 'pop valuepopa x 'pop indexpopa y 'pop targetcmp a,y wz'match if value = targetif_nz addspa #1'if no match, unpop targetif_nzadd x,#1'..increment indexif_nzpusha x '..push indexif_zpopa addr 'if match, pop addressif_zpusha x '..push resultif_z setptra addr '..branchorg snippet 'lookdown range
_lookdnr popa b 'pop range endpopa a 'pop range beginpopa x 'pop indexpopa y 'pop targetsub b,a '||(end - begin), c=1 if reverse rangeabs b,b wcsub y,a '+/-(target - begin)negc y,y
cmp b,y wc'match if ||(end - begin) => +/-(target - begin)if_c addspa #1'if no match, unpop targetif_caddx x,b '..add ||(end - begin) + 1 to indexif_cpusha x '..push indexif_ncpopa addr 'if match, pop addressif_ncadd x,y '..result = index +/- (target - begin)if_ncpusha x '..push resultif_nc setptra addr '..branchorg snippet 'lookup/lookdown done
_lookdone subspa #3'pop index/target/addresspusha #0'push 0 result''' Miscellaneous'org snippet
_pop rdbytec x,ptra++ 'pop
subspa x
org snippet
_clkset popa x 'clksetclkset x
org snippet
_cogid cogid x 'cogidpusha x
org snippet
_coginit popa y 'coginitpopa x
popa a
setcog a
coginit x,y wcif_nz_and_cpusha #0if_nz_and_ncpusha hFFFFFFFF
org snippet
_cogstop popa x 'cogstopcogstop x
This interpreter is for the built-in 17-bit address space (128KB), but can easily be changed to 32-bit XMM. I started out on the 32-bit addressing path, but figured it was more practical, at first, to make a native 17-bit version, as an external SDRAM can easily be managed by Spin code for huge data.
This interpreter leaves the first $150+ longs in the cog free for in-line assembly code and terminate-stay-resident type applications which can run concurrently with the interpreter via hardware multi-tasking.
In the new Spin, all variables are bit-range addressable for read/write/read-modify-write operations. Bit ranges can be high..low or low..high. This is mainly important for I/O registers which relate to physical pins, but it makes bit fields within other types (locals, hub ram, cog RAM registers) easy to manipulate, as well.
This interpreter works by getting a byte code, looking up a descriptor long, loading a snippet of assembly code, and executing it. The interpreter currently lacks initialization code, which will be written last, but it has all the snippets for math operations, calls, branches, lookup/lookdown, cog starting and stopping, and housekeeping. It's about 4.5KB now. Once I get the compiler working on the PC side, I'll augment the interpreter to include special I/O handling and other functions that are not needed at first, but make it complete.
CON
base = $E80'''***************'* Interpreter *'***************'DAT
[B][COLOR=#ff0000] orgh base
org$15B
[/COLOR][/B]''' Append word to x - used to make $0xxxx or $1xxxx address'
xword rdbytec y,ptra++
xword_ret retd
movf x,y
rdbytec y,ptra++
movf x,y
''' call obj.sub' call obj.sub[]' call obj[].sub' call obj[].sub[]' call sub' call sub[]' call ptr'
call_obj shl x,#2'lookup obj vbase/pbase offsetsadd x,pbase
rdlong x,x
call_ptr rol x,#4'set relative pbaseadd pbase,x
and pbase,h0001FFF0
ror x,#16'set relative vbaseadd vbase,x
and vbase,h0001FFF0
call_sub shl y,#2'lookup locals/pbase offsetsadd y,pbase
rdlong y,y
mov dbase,dcall 'set call dbaseadd dbase,#3
setspb dcall 'get old dcallpopb dcall
getptra x 'set return pcurrpushb x
setptra pbase 'set call pcurr
jmpd #getbyte'loop to getbyte, delayed
addptra y
shr y,#32-4'add locals to dcurr
addspa y
''' Bitfield addressing, pop and set bitfield parameters'
bitfield popa bshift 'pop range lsbpopabmask'pop range msband bshift,#$1F'trim lsb/msbandbmask,#$1Fcmpbmask,bshift wc'reverse range?if_cxor bshift,bmask'if reverse range, swap msb/lsbif_cxorbmask,bshift
if_cxor bshift,bmasksubbmask,bshift 'get number of bitsaddbmask,#1neg brev,bmask'get rev count
bitfield_ret retd 'return, delayed
setbc brev,#6'save reverse flag
blmask bmask'get bitlength maskshlbmask,bshift 'bmask = mask, brev = reverse, bshift = lsb offset''' Write register, if OUTA..OUTD then update PINA..PIND (x = value)'
writer movd writer_reg,addr
movd writer_pin,addr
setb writer_pin,#9+3
writer_reg mov$000,x
writer_ret retd
xor addr,#$1F0test addr,#$1FCwz
writer_pin if_zmov$000,x
''' Do bitfield read (x = value)'
readb and x,bmask
jmpd #getbyteshr x,bshift
if_crev x,brev
pusha x
''' Do bitfield write (bval = value, writeb_i = write instruction)'
writeb popa x 'pop value to writeif_crev x,brev 'reverse bits?shl x,bshift 'shift into positionand x,bmask'mask bitsandn bval,bmask'mask away original bitsor x,bval 'merge bits
writeb_i pushbr x 'call #writer / pushbr x / wrxxxx x,addr
writeb_ret jmp #getbyte''' Do bitfield assignment (bval = value, assignb_i = write instruction, mask = sized mask)'
assignb_long mov mask,hFFFFFFFF 'set long mask
assignb movs jmpback,#assignb_ret 'set jmpback address to assignb_retmov x,bval 'save original value
jmpd #assign_op 'get math operator and execute, delayedand x,bmask'extract bitfield for operationshr x,bshift
if_crev x,brev
assignb_ret testb brev,#6wc'snippet returns to here, get reverse flag into ccall #writeb 'write bitfield
movs writeb_ret,#getbyte'restore jump to getbyteand x,mask 'mask it
jmpd #assign_p 'push it (optional), delayedand x,bmask'extract bitfield for pushingshr x,bshift
if_crev x,brev
''' Do assignment (x = value, assign_i = write instruction, mask = sized mask)'
assign_local mov assign_i,pushbrx 'set local write
assign_long mov mask,hFFFFFFFF 'set long mask
assign movs jmpback,#assign_ret 'set jmpback address to :ret
assign_op rdbytec a,ptra++ 'get math operator and flags
setzc a wz,wc'load flags, operator already in positionmuxz assign_p,h003C0000 'set push condition to z
jmpd #hotbyte 'load and execute math snippet, delayedif_cpopa y 'swap args?pusha x
if_cpusha y
assign_ret popa x 'snippet returns to here, pop value
assign_i pushbr x 'write it (call #writer / pushbr x / wrxxxx x,addr)and x,mask 'mask it
assign_p pusha x 'push it (optional)
movs jmpback,#getbyte'replace jmpback address, getbyte next''' Get byte code, look up descriptor long, load code longs in-line, execute, repeat'getbyte rdbytec a,ptra++ wz' get byte code, extended?if_z rdbytec a,ptra++ ' if extended, get extended byte codeif_zor a,#$100' ...and add offsetshl a,#2' shift to make long offset
hotbyte add a,descbase ' add base address of descriptor longsrdlong x,a '..2 get descriptor long
movd :reps,x '3 descriptor[8..0] holds code longs minus 1shr x,#7'4 descriptor[23..7] is code offset
setptrb x '5 point PTRB to code longs
:reps reps #1,#1'6 ready for fast in-line code load
setindb #snippet '7 point INDB to in-line code
rdlongc indb++,ptrb++ '0.. load code longs in-line using cached readmov indb++,jmpback '+1 finish in-line code with 'jmp #getbyte'shr x,#25-7wz,wc'+1 descriptor[31..25] is a value, [24] is C
snippet long0[22] '? execute in-line code snippet, loop''' Constants'
pushbrx pushbr x
callwriter call #writer
jmpback jmp #getbyte
descbase long @descs-4'account for $01 offset
h0001FFF0 long$0001FFF0'vbase/pbase mask
h003C0000 long$003C0000'conditional field bits
hFFFFFFFF long$FFFFFFFF'all bits
x long0'variables
y long0
a long0
b long0
addr long0'assignment
mask long0
bshift long0'bitfield addressingbmasklong0
brev long0
bval long0
dcall long0' pointer
dbase long0' pointeroutalong0'@$1F0 OUTA..OUTDoutblong0'@$1F1 (writes update PINA..PIND)outclong0'@$1F2
outd long0'@$1F3
vbase long0'@$1F4 pointer
pbase long0'@$1F5 pointer'''************************'* Bytecode Descriptors *'************************'
descs
' variable modifiers (14)
op_writep long%0000000_0 << 24 + @_clr << 7 + 0'write w/push %10 push
op_rep long%0000000_0 << 24 + @_rep << 7 + 12'repeat var %00 no
op_clr long%0000000_0 << 24 + @_clr << 7 + 1'clear %00 no
op_clrpost long%0000000_0 << 24 + @_clrpost << 7 + 0'clear post %00 push
op_set long%0000000_0 << 24 + @_set << 7 + 1'set %00 no
op_setpost long%0000000_0 << 24 + @_setpost << 7 + 0'set post %00 push
op_incpre long%0000000_0 << 24 + @_incdec << 7 + 3'inc pre / inc %10 push / %00 no
op_incpost long%0000001_0 << 24 + @_incdec << 7 + 3'inc post %00 push
op_decpre long%0000000_1 << 24 + @_incdec << 7 + 3'dec pre / dec %10 push / %00 no
op_decpost long%0000001_1 << 24 + @_incdec << 7 + 3'dec post %00 push
op_incmod long%0000000_0 << 24 + @_idmod << 7 + 6'incmod %00 no
op_incmodp long%0000001_0 << 24 + @_idmod << 7 + 6'incmod w/push %00 push
op_decmod long%0000000_1 << 24 + @_idmod << 7 + 6'decmod %00 no
op_decmodp long%0000001_1 << 24 + @_idmod << 7 + 6'decmod w/push %00 push' unaries (23)
op_notb long%0000000_0 << 24 + @_notb << 7 + 2'NOT %x0
op_not long%0000000_0 << 24 + @_not << 7 + 2'! %x0
op_neg long%0000000_0 << 24 + @_neg << 7 + 2'- %x0
op_abs long%0000000_0 << 24 + @_abs << 7 + 2'|| %x0
op_enc long%0000000_0 << 24 + @_enc << 7 + 2'>| %x0
op_decod5 long%0000000_0 << 24 + @_decod5 << 7 + 2'|<, DECOD5(x) %x0
op_decod4 long%0000000_0 << 24 + @_decod4 << 7 + 2'DECOD4(x) %x0
op_decod3 long%0000000_0 << 24 + @_decod3 << 7 + 2'DECOD3(x) %x0
op_decod2 long%0000000_0 << 24 + @_decod2 << 7 + 2'DECOD2(x) %x0
op_blmask long%0000000_0 << 24 + @_blmask << 7 + 2'BLMASK(x) %x0
op_onecnt long%0000000_0 << 24 + @_onecnt << 7 + 2'ONECNT(x) %x0
op_zercnt long%0000000_0 << 24 + @_zercnt << 7 + 2'ZERCNT(x) %x0
op_incpat long%0000000_0 << 24 + @_incpat << 7 + 2'INCPAT(x) %x0
op_decpat long%0000000_0 << 24 + @_decpat << 7 + 2'DECPAT(x) %x0
op_bingry long%0000000_0 << 24 + @_bingry << 7 + 2'BINGRY(x) %x0
op_grybin long%0000000_0 << 24 + @_grybin << 7 + 2'GRYBIN(x) %x0
op_mergew long%0000000_0 << 24 + @_mergew << 7 + 2'MERGEW(x) %x0
op_splitw long%0000000_0 << 24 + @_splitw << 7 + 2'SPLITW(x) %x0
op_seussf long%0000000_0 << 24 + @_seussf << 7 + 2'SEUSSF(x) %x0
op_seussr long%0000000_0 << 24 + @_seussr << 7 + 2'SEUSSR(x) %x0
op_sqrt long%0000000_0 << 24 + @_sqrt << 7 + 4'SQRT(x) %x0
op_qlog long%0000000_0 << 24 + @_qlogexp << 7 + 5'QLOG(x) %x0
op_qexp long%0000000_1 << 24 + @_qlogexp << 7 + 5'QEXP(x) %x0' binaries (23)
op_andb long%0000000_0 << 24 + @_andb << 7 + 4'AND %x1
op_orb long%0000000_0 << 24 + @_orb << 7 + 4'OR %x1
op_xorb long%0000000_0 << 24 + @_xorb << 7 + 5'XOR %x1
op_andn long%0000000_0 << 24 + @_andn << 7 + 3'&! %x1
op_and long%0000000_0 << 24 + @_and << 7 + 3'& %x1
op_or long%0000000_0 << 24 + @_or << 7 + 3'| %x1
op_xor long%0000000_0 << 24 + @_xor << 7 + 3'^ %x1
op_ror long%0000000_0 << 24 + @_ror << 7 + 3'-> %x1
op_rol long%0000000_0 << 24 + @_rol << 7 + 3'<- %x1
op_shr long%0000000_0 << 24 + @_shr << 7 + 3'>> %x1
op_shl long%0000000_0 << 24 + @_shl << 7 + 3'<< %x1
op_sar long%0000000_0 << 24 + @_sar << 7 + 3'~> %x1
op_sal long%0000000_0 << 24 + @_sal << 7 + 5'<~ %x1
op_rev long%0000000_0 << 24 + @_rev << 7 + 4'>< %x1
op_mins long%0000000_0 << 24 + @_mins << 7 + 3'#> %x1
op_maxs long%0000000_0 << 24 + @_maxs << 7 + 3'<# %x1
op_add long%0000000_0 << 24 + @_add << 7 + 3'+ %x1
op_sub long%0000000_0 << 24 + @_sub << 7 + 3'- %x1
op_mul long%0000000_0 << 24 + @_mul << 7 + 6'* %x1
op_scl long%0000001_0 << 24 + @_scl << 7 + 6'** %x1
op_quo long%0000000_0 << 24 + @_divx << 7 + 7'/ %x1
op_rem long%0000001_0 << 24 + @_divx << 7 + 7'// %x1
op_fra long%0000000_0 << 24 + @_fra << 7 + 7'*/ %x1' equality tests (6)
op_b long%0000000_0 << 24 + @_b << 7 + 4'<
op_a long%0000000_0 << 24 + @_a << 7 + 4'>
op_ne long%0000000_0 << 24 + @_ne << 7 + 4'<>
op_eq long%0000000_0 << 24 + @_eq << 7 + 4'==
op_be long%0000000_0 << 24 + @_be << 7 + 4'=< / <=
op_ae long%0000000_0 << 24 + @_ae << 7 + 4'=> / >=' math terms (8)
op_quo64 long%0000000_0 << 24 + @_divh64 << 7 + 10'QUO64(al,ah,b)
op_quo64u long%0000000_1 << 24 + @_divh64 << 7 + 10'QUO64U(al,ah,b)
op_rem64 long%0000001_0 << 24 + @_divh64 << 7 + 10'REM64(al,ah,b)
op_rem64u long%0000001_1 << 24 + @_divh64 << 7 + 10'REM64U(al,ah,b)
op_sqrt64 long%0000000_0 << 24 + @_sqrt64 << 7 + 6'SQRT64(l,h)
op_negb long%0000000_0 << 24 + @_negb << 7 + 3'NEGB(x,bool)
op_muxb long%0000000_0 << 24 + @_muxb << 7 + 4'MUXB(x,y,bool)
op_ternary long%0000000_0 << 24 + @_ternary << 7 + 4'sel ? true : false' math procedures (20)
op_mul64 long%0000000_0 << 24 + @_mul64 << 7 + 9'MUL64(a,b : l,h)
op_mulu64 long%0000000_1 << 24 + @_mul64 << 7 + 9'MUL64U(a,b : l,h)
op_div64 long%0000000_0 << 24 + @_div64 << 7 + 11'DIV64(a,b : l,h)
op_divu64 long%0000000_1 << 24 + @_div64 << 7 + 11'DIV64U(a,b : l,h)
op_qsincos long%0000000_0 << 24 + @_qtrig << 7 + 12'QSINCOS(r,t : x,y)
op_qarctan long%0000001_0 << 24 + @_qtrig << 7 + 12'QARCTAN(x,y : r,t)
op_qrotate long%0000000_1 << 24 + @_qtrig << 7 + 12'QROTATE(x,y,t : x,y)
op_setqi long%0000000_1 << 24 + @_div64 << 7 + 1'SETQI(x)
op_clraccs long%0000000_0 << 24 + @_clraccs << 7 + 0'CLRACCS
op_clracca long%0000000_0 << 24 + @_clracca << 7 + 0'CLRACCA
op_clraccb long%0000000_0 << 24 + @_clraccb << 7 + 0'CLRACCB
op_fitaccs long%0000000_0 << 24 + @_fitaccs << 7 + 0'FITACCS
op_fitacca long%0000000_0 << 24 + @_fitacca << 7 + 0'FITACCA
op_fitaccb long%0000000_0 << 24 + @_fitaccb << 7 + 0'FITACCB
op_setacca long%0000000_0 << 24 + @_setacca << 7 + 2'SETACCA(l,h)
op_setaccb long%0000000_0 << 24 + @_setaccb << 7 + 2'SETACCB(l,h)
op_getacca long%0000000_0 << 24 + @_getacca << 7 + 3'GETACCA(l,h)
op_getaccb long%0000000_0 << 24 + @_getaccb << 7 + 3'GETACCB(l,h)
op_maca long%0000000_0 << 24 + @_maca << 7 + 2'MACA(x,y)
op_macb long%0000000_0 << 24 + @_macb << 7 + 2'MACB(x,y)' constants (13)
op_con1n long%0000000_0 << 24 + @_conxn << 7 + 1'constant -1
op_con0 long%0000000_0 << 24 + @_conxp << 7 + 0'constant 0
op_con1 long%0000001_0 << 24 + @_conxp << 7 + 0'constant 1
op_con8p long%0000000_0 << 24 + @_con8p << 7 + 1'constant $000000xx
op_con9p long%0000000_0 << 24 + @_con9p << 7 + 2'constant $000001xx
op_con8n long%0000000_0 << 24 + @_con8n << 7 + 2'constant $FFFFFFxx
op_con16p long%0000000_0 << 24 + @_con16p << 7 + 3'constant $0000xxxx
op_con17p long%0000000_0 << 24 + @_con17p << 7 + 3'constant $0001xxxx
op_con16n long%0000000_0 << 24 + @_con16n << 7 + 4'constant $FFFFxxxx
op_con24p long%0000000_0 << 24 + @_con24 << 7 + 4'constant $00xxxxxx
op_con24n long%0000000_1 << 24 + @_con24 << 7 + 4'constant $FFxxxxxx
op_con32 long%0000000_0 << 24 + @_con32 << 7 + 4'constant $xxxxxxxx
op_conexp long%0000000_0 << 24 + @_conexp << 7 + 4'constant 2^n,dec,not' register reads/writes/assigns (6)
op_rdreg long%0000000_0 << 24 + @_rdreg << 7 + 4'read register
op_wrreg long%0000000_0 << 24 + @_wrreg << 7 + 2'write register
op_asreg long%0000000_0 << 24 + @_asreg << 7 + 5'assign register
op_rdregb long%0000000_0 << 24 + @_rdregb << 7 + 6'read register bitfield
op_wrregb long%0000000_0 << 24 + @_wrregb << 7 + 6'write register bitfield
op_asregb long%0000000_0 << 24 + @_asregb << 7 + 6'assign register bitfield' local reads/writes/assigns (54)
op_rdloc0 long%0000000_0 << 24 + @_rdloc << 7 + 3'read local 0
op_rdloc1 long%0000001_0 << 24 + @_rdloc << 7 + 3'read local 1
op_rdloc2 long%0000010_0 << 24 + @_rdloc << 7 + 3'read local 2
op_rdloc3 long%0000011_0 << 24 + @_rdloc << 7 + 3'read local 3
op_rdloc4 long%0000100_0 << 24 + @_rdloc << 7 + 3'read local 4
op_rdloc5 long%0000101_0 << 24 + @_rdloc << 7 + 3'read local 5
op_rdloc6 long%0000110_0 << 24 + @_rdloc << 7 + 3'read local 6
op_rdloc7 long%0000111_0 << 24 + @_rdloc << 7 + 3'read local 7
op_rdloc8 long%0001000_0 << 24 + @_rdloc << 7 + 3'read local 8
op_rdloc9 long%0001001_0 << 24 + @_rdloc << 7 + 3'read local 9
op_rdloc10 long%0001010_0 << 24 + @_rdloc << 7 + 3'read local 10
op_rdloc11 long%0001011_0 << 24 + @_rdloc << 7 + 3'read local 11
op_rdloc12 long%0001100_0 << 24 + @_rdloc << 7 + 3'read local 12
op_rdloc13 long%0001101_0 << 24 + @_rdloc << 7 + 3'read local 13
op_rdloc14 long%0001110_0 << 24 + @_rdloc << 7 + 3'read local 14
op_rdloc15 long%0001111_0 << 24 + @_rdloc << 7 + 3'read local 15
op_wrloc0 long%0000000_0 << 24 + @_wrloc << 7 + 3'write local 0
op_wrloc1 long%0000001_0 << 24 + @_wrloc << 7 + 3'write local 1
op_wrloc2 long%0000010_0 << 24 + @_wrloc << 7 + 3'write local 2
op_wrloc3 long%0000011_0 << 24 + @_wrloc << 7 + 3'write local 3
op_wrloc4 long%0000100_0 << 24 + @_wrloc << 7 + 3'write local 4
op_wrloc5 long%0000101_0 << 24 + @_wrloc << 7 + 3'write local 5
op_wrloc6 long%0000110_0 << 24 + @_wrloc << 7 + 3'write local 6
op_wrloc7 long%0000111_0 << 24 + @_wrloc << 7 + 3'write local 7
op_wrloc8 long%0001000_0 << 24 + @_wrloc << 7 + 3'write local 8
op_wrloc9 long%0001001_0 << 24 + @_wrloc << 7 + 3'write local 9
op_wrloc10 long%0001010_0 << 24 + @_wrloc << 7 + 3'write local 10
op_wrloc11 long%0001011_0 << 24 + @_wrloc << 7 + 3'write local 11
op_wrloc12 long%0001100_0 << 24 + @_wrloc << 7 + 3'write local 12
op_wrloc13 long%0001101_0 << 24 + @_wrloc << 7 + 3'write local 13
op_wrloc14 long%0001110_0 << 24 + @_wrloc << 7 + 3'write local 14
op_wrloc15 long%0001111_0 << 24 + @_wrloc << 7 + 3'write local 15
op_asloc0 long%0000000_0 << 24 + @_asloc << 7 + 3'assign local 0
op_asloc1 long%0000001_0 << 24 + @_asloc << 7 + 3'assign local 1
op_asloc2 long%0000010_0 << 24 + @_asloc << 7 + 3'assign local 2
op_asloc3 long%0000011_0 << 24 + @_asloc << 7 + 3'assign local 3
op_asloc4 long%0000100_0 << 24 + @_asloc << 7 + 3'assign local 4
op_asloc5 long%0000101_0 << 24 + @_asloc << 7 + 3'assign local 5
op_asloc6 long%0000110_0 << 24 + @_asloc << 7 + 3'assign local 6
op_asloc7 long%0000111_0 << 24 + @_asloc << 7 + 3'assign local 7
op_asloc8 long%0001000_0 << 24 + @_asloc << 7 + 3'assign local 8
op_asloc9 long%0001001_0 << 24 + @_asloc << 7 + 3'assign local 9
op_asloc10 long%0001010_0 << 24 + @_asloc << 7 + 3'assign local 10
op_asloc11 long%0001011_0 << 24 + @_asloc << 7 + 3'assign local 11
op_asloc12 long%0001100_0 << 24 + @_asloc << 7 + 3'assign local 12
op_asloc13 long%0001101_0 << 24 + @_asloc << 7 + 3'assign local 13
op_asloc14 long%0001110_0 << 24 + @_asloc << 7 + 3'assign local 14
op_asloc15 long%0001111_0 << 24 + @_asloc << 7 + 3'assign local 15
op_rdloci long%0000000_0 << 24 + @_rdloci << 7 + 6'read local indexed
op_wrloci long%0000000_0 << 24 + @_wrloci << 7 + 6'write local indexed
op_asloci long%0000000_0 << 24 + @_asloci << 7 + 6'assign local indexed
op_rdlocb long%0000000_0 << 24 + @_rdlocb << 7 + 5'read local bitfield
op_wrlocb long%0000000_0 << 24 + @_wrlocb << 7 + 6'write local bitfield
op_aslocb long%0000000_0 << 24 + @_aslocb << 7 + 6'assign local bitfield' memory reads/writes/assigns (18)
op_rdbyte long%0000000_0 << 24 + @_rdbyte << 7 + 2'read byte
op_rdword long%0000000_0 << 24 + @_rdword << 7 + 2'read word
op_rdlong long%0000000_0 << 24 + @_rdlong << 7 + 2'read long
op_wrbyte long%0000000_0 << 24 + @_wrbyte << 7 + 2'write byte
op_wrword long%0000000_0 << 24 + @_wrword << 7 + 2'write word
op_wrlong long%0000000_0 << 24 + @_wrlong << 7 + 2'write long
op_asbyte long%0000000_0 << 24 + @_asbyte << 7 + 5'assign byte
op_asword long%0000000_0 << 24 + @_asword << 7 + 6'assign word
op_aslong long%0000000_0 << 24 + @_aslong << 7 + 4'assign long
op_rdbyteb long%0000000_0 << 24 + @_rdbyteb << 7 + 3'read byte bitfield
op_rdwordb long%0000000_0 << 24 + @_rdwordb << 7 + 3'read word bitfield
op_rdlongb long%0000000_0 << 24 + @_rdlongb << 7 + 3'read long bitfield
op_wrbyteb long%0000000_0 << 24 + @_wrbyteb << 7 + 5'write byte bitfield
op_wrwordb long%0000000_0 << 24 + @_wrwordb << 7 + 5'write word bitfield
op_wrlongb long%0000000_0 << 24 + @_wrlongb << 7 + 5'write long bitfield
op_asbyteb long%0000000_0 << 24 + @_asbyteb << 7 + 6'assign byte bitfield
op_aswordb long%0000000_0 << 24 + @_aswordb << 7 + 7'assign word bitfield
op_aslongb long%0000000_0 << 24 + @_aslongb << 7 + 5'assign long bitfield' memory offsets and indexing (7)
op_vbase0 long%0000000_0 << 24 + @_base << 7 + 3'vbase $0xxxx
op_pbase0 long%0000000_1 << 24 + @_base << 7 + 3'pbase $0xxxx
op_vbase1 long%0000001_0 << 24 + @_base << 7 + 3'vbase $1xxxx
op_pbase1 long%0000001_1 << 24 + @_base << 7 + 3'pbase $1xxxx
op_ibyte long%0000000_0 << 24 + @_index << 7 + 4'byte index
op_iword long%0000001_0 << 24 + @_index << 7 + 4'word index
op_ilong long%0000010_0 << 24 + @_index << 7 + 4'long index' branches jmp/jz/jnz/tjz/djnz (10)
op_jmp0 long%0000000_0 << 24 + @_jmp << 7 + 1'jmp +$0xxxx
op_jmp1 long%0000001_0 << 24 + @_jmp << 7 + 1'jmp +$1xxxx
op_jz0 long%0000000_1 << 24 + @_jxz << 7 + 2'jz +$0xxxx
op_jz1 long%0000001_1 << 24 + @_jxz << 7 + 2'jz +$1xxxx
op_jnz0 long%0000000_0 << 24 + @_jxz << 7 + 2'jnz +$0xxxx
op_jnz1 long%0000001_0 << 24 + @_jxz << 7 + 2'jnz +$1xxxx
op_tjz0 long%0000000_0 << 24 + @_tjz << 7 + 3'tjz +$0xxxx
op_tjz1 long%0000001_0 << 24 + @_tjz << 7 + 3'tjz +$1xxxx
op_djnz0 long%0000000_0 << 24 + @_djnz << 7 + 4'djnz +$0xxxx
op_djnz1 long%0000001_0 << 24 + @_djnz << 7 + 4'djnz +$1xxxx' anchor drops (4)
op_dropt long%0000000_0 << 24 + @_drop << 7 + 6'drop, \sub
op_droptr long%0000001_0 << 24 + @_drop << 7 + 6'drop, \sub w/result
op_drop long%0000010_0 << 24 + @_drop << 7 + 6'drop, sub
op_dropr long%0000011_0 << 24 + @_drop << 7 + 6'drop, sub w/result' calls (7)
op_callos long%0000000_0 << 24 + @_callobj << 7 + 6'call obj.sub
op_callosi long%0000000_1 << 24 + @_callobj << 7 + 6'call obj.sub[]
op_callois long%0000001_0 << 24 + @_callobj << 7 + 6'call obj[].sub
op_calloisi long%0000001_1 << 24 + @_callobj << 7 + 6'call obj[].sub[]
op_calls long%0000000_0 << 24 + @_callsub << 7 + 3'call sub
op_callsi long%0000000_1 << 24 + @_callsub << 7 + 3'call sub[]
op_callp long%0000000_0 << 24 + @_callptr << 7 + 10'call ptr' returns (4)
op_return long%0000000_0 << 24 + @_return << 7 + 13'RETURN
op_abort long%0000000_1 << 24 + @_return << 7 + 13'ABORT
op_returnv long%0000001_0 << 24 + @_return << 7 + 13'RETURN value
op_abortv long%0000001_1 << 24 + @_return << 7 + 13'ABORT value' call pointer generation (5)
op_basesub long%0000000_0 << 24 + @_basesub << 7 + 5'vbase/pbase of current
op_baseobj long%0000000_0 << 24 + @_baseobj << 7 + 16'vbase/pbase of obj
op_baseobji long%0000000_1 << 24 + @_baseobj << 7 + 16'vbase/pbase of obj[]
op_subptr long%0000000_0 << 24 + @_subptr << 7 + 11'base.sub
op_subptri long%0000000_1 << 24 + @_subptr << 7 + 11'base.sub[]' case (5)
op_casev0 long%0000000_0 << 24 + @_casev << 7 + 5'case value, +$0xxxx branch
op_casev1 long%0000001_0 << 24 + @_casev << 7 + 5'case value, +$1xxxx branch
op_caser0 long%0000000_0 << 24 + @_caser << 7 + 10'case range, +$0xxxx branch
op_caser1 long%0000001_0 << 24 + @_caser << 7 + 10'case range, +$1xxxx branch
op_casedone long%0000000_0 << 24 + @_casedone << 7 + 2'case done' lookup/lookdown (5)
op_lookupv long%0000000_0 << 24 + @_lookupv << 7 + 9'lookup value
op_lookupr long%0000000_0 << 24 + @_lookupr << 7 + 14'lookup range
op_lookdnv long%0000000_0 << 24 + @_lookdnv << 7 + 9'lookdown value
op_lookdnr long%0000000_0 << 24 + @_lookdnr << 7 + 15'lookdown range
op_lookdone long%0000000_0 << 24 + @_lookdone << 7 + 1'lookup/lookdown done' miscellaneous (6)
op_pop long%0000000_0 << 24 + @_pop << 7 + 1'pop
op_clkset long%0000000_0 << 24 + @_clkset << 7 + 1'clkset
op_cogid long%0000000_0 << 24 + @_cogid << 7 + 1'cogid
op_coginit long%0000000_0 << 24 + @_coginit << 7 + 6'coginit
op_coginitp long%0000001_0 << 24 + @_coginit << 7 + 6'coginit w/push
op_cogstop long%0000000_0 << 24 + @_cogstop << 7 + 1'cogstop'''************'* Snippets *'************'''' Variable modifiers'org snippet 'repeat-var loop (assign)
_rep popa mask 'pop varpopa y 'pop steppopa b 'pop terminalpopa a 'pop initialpopa addr 'pop branch offsetcmps b,a wc'get reverse range into csumc mask,y 'update var with steprcl x,#1wz'get c into nzif_zcmps b,mask wc'if forward range, check if var > terminalif_nzcmps mask,b wc'if reverse range, check if var < terminalif_nc subptra addr 'if var within range, branchif_nc addspa #4'..unpop offset/initial/terminal/steppusha mask 'push new varorg snippet 'var~, clear and post-clear (assign)
_clr popa x 'clear, pop var (single pop also used by op_writep)
_clrpost pusha #0'post-clear, push 0 (leave var on stack)org snippet 'var~~, set and post-set (assign)
_set popa x 'set, pop var
_setpost pusha hFFFFFFFF 'post-set, push -1 (leave var on stack)org snippet '++var/--var/var++/var-- (assign)
_incdec popa x 'pop varif_nzpusha x 'if nz, push original varsumc x,#1'inc or dec var by cpusha x 'push new varorg snippet 'INCMOD/DECMOD(var,limit) (assign)
_idmod setbc :i,#26'set INCMOD/DECMOD by cpopa y 'pop limitpopa x 'pop var
:i incmod x,y wc'incmod/decmod, c=limitif_nz_and_ncpusha #0'push false if nz and ncif_nz_and_cpusha hFFFFFFFF 'push true if nz and cpusha x 'push new var''' Unary functions'org snippet
_notb popa x wz'NOT, booleanmuxz x,hFFFFFFFF
pusha x
org snippet
_not popa x '!, bitwise notnot x
pusha x
org snippet
_neg popa x '-, negateneg x,x
pusha x
org snippet
_abs popa x '||, absoluteabs x,x
pusha x
org snippet
_enc popa x '>|, encode (0..32)
enc x,x
pusha x
org snippet
_decod5 popa x '|< / DECOD5(x)
decod5 x
pusha x
org snippet
_decod4 popa x 'DECOD4(x)
decod4 x
pusha x
org snippet
_decod3 popa x 'DECOD3(x)
decod3 x
pusha x
org snippet
_decod2 popa x 'DECOD2(x)
decod2 x
pusha x
org snippet
_blmask popa x 'BLMASK(x)
blmask x
pusha x
org snippet
_onecnt popa x 'ONECNT(x)
onecnt x
pusha x
org snippet
_zercnt popa x 'ZERCNT(x)
zercnt x
pusha x
org snippet
_incpat popa x 'INCPAT(x)
incpat x
pusha x
org snippet
_decpat popa x 'DECPAT(x)
decpat x
pusha x
org snippet
_bingry popa x 'BINGRY(x)
bingry x
pusha x
org snippet
_grybin popa x 'GRYBIN(x)
grybin x
pusha x
org snippet
_mergew popa x 'MERGEW(x)mergew x
pusha x
org snippet
_splitw popa x 'SPLITW(x)splitw x
pusha x
org snippet
_seussf popa x 'SEUSSF(x)seussf x
pusha x
org snippet
_seussr popa x 'SEUSSR(x)seussr x
pusha x
org snippet
_sqrt popa x 'SQRT(x)
setsqrl x
getsqrt x wcif_ncjmp #$-1pusha x
org snippet
_qlogexp popa x 'QLOG(x), c=0if_ncqlog x 'QEXP(x), c=1if_cqexp x
getqz x wcif_ncjmp #$-1pusha x
''' Binary functions'org snippet
_andb popa x wz'AND, booleanif_zpopa x
if_nzpopa x wzmuxnz x,hFFFFFFFF
pusha x
org snippet
_orb popa x wz'OR, booleanif_nzpopa x
if_zpopa x wzmuxnz x,hFFFFFFFF
pusha x
org snippet
_xorb popa y wz'XOR, booleanmuxnz y,hFFFFFFFF
popa x wzmuxnz x,hFFFFFFFF
xor x,y
pusha x
org snippet
_andn popa y '&!, bitwise andnotpopa x
andn x,y
pusha x
org snippet
_and popa y '&, bitwise andpopa x
and x,y
pusha x
org snippet
_or popa y '|, bitwise orpopa x
or x,y
pusha x
org snippet
_xor popa y '^, bitwise xorpopa x
xor x,y
pusha x
org snippet
_ror popa y '->, rotate rightpopa x
ror x,y
pusha x
org snippet
_rol popa y '<-, rotate leftpopa x
rol x,y
pusha x
org snippet
_shr popa y '>>, shift rightpopa x
shr x,y
pusha x
org snippet
_shl popa y '<<, shift leftpopa x
shl x,y
pusha x
org snippet
_sar popa y '~>, shift arithmetic rightpopa x
sar x,y
pusha x
org snippet
_sal popa y '<~, shift arithmetic leftpopa x
rev x,#0sar x,y
rev x,#0pusha x
org snippet
_rev popa y '><, reverse bitspopa x
neg y,y
rev x,y
pusha x
org snippet
_mins popa y '|>, limit minimumpopa x
mins x,y
pusha x
org snippet
_maxs popa y '<|, limit maximumpopa x
maxs x,y
pusha x
org snippet
_add popa y '+, addpopa x
add x,y
pusha x
org snippet
_sub popa y '-, subpopa x
sub x,y
pusha x
org snippet
_mul popa y '*, multiply and return lower longpopa x
setmula x
setmulb y
getmull x wcif_ncjmp #$-1pusha x
org snippet
_scl popa y '**, multiply return upper long, unsignedpopa x
setmulu x
setmulb y
getmulh x wcif_ncjmp #$-1pusha x
org snippet
_divx popa y '/, divide and return quotient, z=1popa x '//, divide and return remainder, z=0
setdiva x
setdivb y
getdivq x wcif_ncjmp #$-1if_nz getdivr x
pusha x
org snippet
_fra popa y '*/, fractionpopa x
setdivu #0
setdivu x
setdivb y
getdivq x wcif_ncjmp #$-1pusha x
''' Equality tests'org snippet
_b popa y '<, test belowpopa x
cmps x,y wcmuxc x,hFFFFFFFF
pusha x
org snippet
_a popa y '>, test abovepopa x
cmps y,x wcmuxc x,hFFFFFFFF
pusha x
org snippet
_ne popa y '<>, test not equalpopa x
cmps x,y wzmuxnz x,hFFFFFFFF
pusha x
org snippet
_eq popa y '==, test equalpopa x
cmps x,y wzmuxz x,hFFFFFFFF
pusha x
org snippet
_be popa y '=< / <=, test below or equalpopa x
cmps y,x wcmuxnc x,hFFFFFFFF
pusha x
org snippet
_ae popa y '=> / >=, test above or equalpopa x
cmps x,y wcmuxnc x,hFFFFFFFF
pusha x
''' Math terms'org snippet
_divh64 popa y 'QUO64(al,ah,b), z=1, c=0popa x 'QUO64U(al,ah,b), z=1, c=1popa a 'REM64(al,ah,b), z=0, c=0if_nc setdiva a 'REM64U(al,ah,b), z=0, c=1if_c setdivu a
setdiva x
setdivb y
getdivq x wcif_ncjmp #$-1if_nz getdivr x wcpusha x
org snippet
_sqrt64 popa x 'SQRT64(l,h)
setsqrh x
popa x
setsqrl x
getsqrt x wcif_ncjmp #$-1pusha x
org snippet
_negb popa x wz'NEGB(x,bool)popa x
negnz x,x
pusha x
org snippet
_muxb popa y wz'MUXB(x,y,bool)popa y
popa x
muxnz x,y
pusha x
org snippet
_ternary popa y 'a ? x : ypopa x
popa a wzif_zpusha y
if_nzpusha x
''' Math procedures'org snippet
_mul64 popa x 'MUL64(a,b : l,h), c=0if_nc setmula x 'MUL64U(a,b : l,h), c=1if_c setmulu x
popa x
setmulb x
getmulh x wcif_ncjmp #$-1pusha x
getmull x
pusha x
org snippet
_div64 popa y 'DIV64(al,ah,b : q,r), c=0popa x 'DIV64U(al,ah,b : q,r), c=1popa a
if_nc setdiva a
if_c setdivu a
setdiva x
setdivb y
getdivr x wcif_ncjmp #$-1pusha x
getdivq x wcpusha x
org snippet
_qtrig if_z_and_cpopa x 'QSINCOS(r,t : x,y), z=1, c=0if_z_and_c setqz x 'QROTATE(x,y,t : x,y), z=1, c=1popa y 'QARCTAN(x,y : r,t), z=0popa x
if_z_and_nc qsincos y,x
if_z_and_cqrotate x,y
if_nz qarctan x,y
getqz x wcif_ncjmp #$-1if_zgetqy x
pusha x
getqx x
pusha x
org snippet
_setqi popa x 'SETQI(i)
setqi x
org snippet
_clraccs clraccs 'CLRACCSorg snippet
_clracca clracca 'CLRACCAorg snippet
_clraccb clraccb 'CLRACCBorg snippet
_fitaccs fitaccs 'FITACCSorg snippet
_fitacca fitacca 'FITACCAorg snippet
_fitaccb fitaccb 'FITACCBorg snippet
_setacca popa y 'SETACCA(l,h)popa x
setacca x,y
org snippet
_setaccb popa y 'SETACCB(l,h)popa x
setaccb x,y
org snippet
_getacca getacca x 'GETACCA(l,h)
getacca y
pusha y
pusha x
org snippet
_getaccb getaccb x 'GETACCB(l,h)
getaccb y
pusha y
pusha x
org snippet
_maca popa y 'MACA(x,y)popa x
maca x,y
org snippet
_macb popa y 'MACB(x,y)popa x
macb x,y
''' Constants'org snippet
_con8p rdbytec x,ptra++ 'con8p
_conxp pusha x 'con0..con3org snippet
_con9p rdbytec x,ptra++ 'con9p
setb x,#8pusha x
org snippet
_con8n rdbytec x,ptra++ 'con8n
_conxn xor x,hFFFFFFFF 'conm1pusha x
org snippet
_con16p rdbytec x,ptra++ 'con16p
rdbytec y,ptra++
movf x,y
pusha x
org snippet
_con17p rdbytec x,ptra++ 'con17p
rdbytec y,ptra++
movf x,y
setb x,#16pusha x
org snippet
_con16n rdbytec x,ptra++ 'con16n
rdbytec y,ptra++
movf x,y
xor x,hFFFFFFFF
pusha x
org snippet
_con24 reps #3,#2'con24p, con24nmuxc x,#$FF
rdbytec y,ptra++
movf x,y
pusha x
_con32 reps #4,#2'con32nop
rdbytec y,ptra++
movf x,y
pusha x
org snippet
_conexp rdbytec x,ptra++ 'conexp
decod5 x wz, wcif_zsub x,#1if_cnot x
pusha x
''' Register read/write/assign'org snippet
_rdreg popa x 'read register
movd :rd,x
nopnop
:rd pusha$000org snippet
_wrreg popa addr 'write registerpopa x
call #writer
org snippet
_asreg popa addr 'assign register
movs :rd,addr
jmpd #assign_long
mov assign_i,callwriter
:rd mov x,$000noporg snippet
_rdregb call #bitfield 'read register bitfieldpopa x
movs :rd,x
jmpd #readb
nop
:rd mov x,$000noporg snippet
_wrregb call #bitfield 'write register bitfieldpopa addr
movs :rd,addr
jmpd #writeb
mov writeb_i,callwriter
:rd mov bval,$000noporg snippet
_asregb call #bitfield 'assign register bitfieldpopa addr
movs :rd,addr
jmpd #assignb_long
mov writeb_i,callwriter
:rd mov bval,$000nop''' Local read/write/assign'org snippet
_rdloci popa y 'read local, indexed
rdbytec x,ptra++
add x,y
_rdloc add x,dbase 'read local, fixed
setspb x
popbr x
pusha x
org snippet
_wrloci popa y 'write local, indexed
rdbytec x,ptra++
add x,y
_wrloc add x,dbase 'write local, fixed
setspb x
popa x
pushb x
org snippet
_asloci popa y 'assign local, indexed
rdbytec x,ptra++
add x,y
_asloc jmpd #assign_local 'assign local, fixedadd x,dbase
setspb x
popbr x
org snippet
_rdlocb call #bitfield 'read local bitfieldpopa x
jmpd #readb
add x,dbase
setspb x
popbr x
org snippet
_wrlocb call #bitfield 'write local bitfieldpopa x
add x,dbase
jmpd #writeb
setspb x
popbr bval
mov writeb_i,pushbrx
org snippet
_aslocb call #bitfield 'assign local bitfieldpopa x
add x,dbase
jmpd #assignb_long
setspb x
popbr bval
mov writeb_i,pushbrx
''' Memory read/write/assign'org snippet
_rdbyte popa x 'read byterdbyte x,x
pusha x
org snippet
_rdword popa x 'read wordrdword x,x
pusha x
org snippet
_rdlong popa x 'read longrdlong x,x
pusha x
org snippet
_wrbyte popa y 'write bytepopa x
wrbyte x,y
org snippet
_wrword popa y 'write wordpopa x
wrword x,y
org snippet
_wrlong popa y 'write longpopa x
wrlong x,y
org snippet
_asbyte popa addr 'assign byte
jmpd #assign
rdbyte x,addr
mov assign_i,:i
mov mask,#$FF
:i wrbyte x,addr
org snippet
_asword popa addr 'assign word
jmpd #assign
rdword x,addr
mov assign_i,:i
mov mask,:m
:i wrword x,addr
:m long$0000FFFForg snippet
_aslong jmpd #assign_long 'assign longpopa addr
rdlong x,addr
mov assign_i,:i
:i wrlong x,addr
org snippet
_rdbyteb call #bitfield 'read byte bitfieldpopa x
rdbyte x,x
jmp #readb
org snippet
_rdwordb call #bitfield 'read word bitfieldpopa x
rdword x,x
jmp #readb
org snippet
_rdlongb call #bitfield 'read long bitfieldpopa x
rdlong x,x
jmp #readb
org snippet
_wrbyteb call #bitfield 'write byte bitfield
jmpd #writeb
popa addr
rdbyte bval,addr
mov writeb_i,:wr
:wr wrbyte x,addr
org snippet
_wrwordb call #bitfield 'write word bitfield
jmpd #writeb
popa addr
rdword bval,addr
mov writeb_i,:wr
:wr wrword x,addr
org snippet
_wrlongb call #bitfield 'write long bitfield
jmpd #writeb
popa addr
rdlong bval,addr
mov writeb_i,:wr
:wr wrlong x,addr
org snippet
_asbyteb call #bitfield 'assign byte bitfieldmov mask,#$FF
jmpd #assignb
popa addr
rdbyte bval,addr
mov writeb_i,:wr
:wr wrbyte x,addr
org snippet
_aswordb call #bitfield 'assign word bitfieldmov mask,:mask
jmpd #assignb
popa addr
rdword bval,addr
mov writeb_i,:wr
:wr wrword x,addr
:mask long$0000FFFForg snippet
_aslongb call #bitfield 'assign long bitfield
jmpd #assignb_long
popa addr
rdlong bval,addr
mov writeb_i,:wr
:wr wrlong x,addr
''' Memory offsets and indexing'org snippet
_base call #xword
if_ncadd x,vbase 'vbase, c=0if_cadd x,pbase 'pbase, c=1pusha x
org snippet
_index popa y 'ibyte, x=0shl y,x 'iword, x=1popa x 'ilong, x=2add x,y
pusha x
''' Branch jmp/jz/jnz/tjz/djnz'org snippet
_jmp call #xword 'jmp
addptra x
org snippet
_jxz popa y wz'jz, c=1 jnz, c=0call #xword
if_z_eq_c addptra x
org snippet
_tjz popa y wz'tjzif_nzpusha y
call #xword
if_z addptra x
org snippet
_djnz popa y 'djnzsub y,#1wzif_nzpusha y
call #xword
if_nz addptra x
''' Drop anchor'' \sub x = %00' \sub result x = %01' sub x = %10' sub result x = %11'org snippet
_drop pusha dcall 'push dcall (later used for pcurr)
getspa dcall 'set new dcallpusha dbase 'push return dbasepusha vbase 'push return vbaseor x,pbase 'push return pbase w/flagspusha x
pusha #0'init 'result' to 0''' Call'' obj.sub z=1, c=0' obj.sub[] z=1, c=1' obj[].sub z=0, c=0' obj[].sub[] z=0, c=1' sub c=0' sub[] c=1' ptr'org snippet
_callobj rdbytec x,ptra++ 'get obj byteif_nzpopa a 'add any indexif_nzadd x,a
jmpd #call_obj 'jump to handler, delayed
rdbytec y,ptra++ 'get sub byteif_cpopa a 'add any indexif_cadd y,a
org snippet
_callsub jmpd #call_sub 'jump to handler, delayed
rdbytec y,ptra++ 'get sub byteif_cpopa a 'add any indexif_cadd y,a
org snippet
_callptr popa x 'get sub [31..29]/[15..13], vbase [28..16], pbase [12..0]mov vbase,#0'clear vbase/pbasemov pbase,#0mov y,x 'get sub (6-bits)mov a,x
shr y,#32-3-3and y,#%111000
jmpd #call_ptr 'jump to handler, delayedshr a,#16-3and a,#%000111or y,a
''' RETURN/ABORT'' RETURN z=1, c=0' ABORT z=1, c=1' RETURN value z=0, c=0' ABORT value z=0, c=1'org snippet
_return if_z setspa dbase 'if no value, return resultif_z popar x
if_nzpopa x 'if value, pop it
:again setspa dbase 'set dbasepopa pbase 'pop pbaseif_ctest pbase,#%10wc'if abort and try, return againif_c jmpd #:again
popa vbase 'pop vbasepopa dbase 'pop dbasepopa y 'pop pcurr
setptra y 'set ptra to pcurrtest pbase,#%01wc'push result?andn pbase,#%11if_cpusha x
''' Get vbase/pbase'org snippet
_basesub mov y,vbase
shl y,#16-4mov x,pbase
shr x,#4or x,y
pusha x
''' Get pbase/vbase of obj'' obj c=0' obj[] c=1'org snippet
_baseobj rdbytec x,ptra++ 'get obj byteif_cpopa y 'handle indexif_cadd x,y
shl x,#2'scale offsetadd x,pbase 'get obj pbase/vbase offsetrdlong x,x
mov y,x 'get obj vbaseshr y,#16-4add y,vbase
and y,h0001FFF0
shl y,#16-4shl x,#4'get obj pbaseadd x,pbase
and x,h0001FFF0
shr x,#4or x,y 'merge vbase/pbasepusha x 'push obj vbase/pbase''' Make subroutine ptr'' base.sub c=0' base.sub[] c=1'org snippet
_subptr rdbytec a,ptra++ 'get sub numberif_cpopa b 'handle sub indexif_cadd a,b
mov b,a 'split 6-bit indexand b,#%111000'top 3 bits into [31..29]shl b,#32-6and a,#%000111'bottom 3 bits into [15..13]shl a,#16-3popa x 'pop base vbase/pbaseor x,b 'install index into pbase/vbaseor x,a
pusha x 'push subroutine pointer''' Case'org snippet 'case value
_casev call #xword 'get branch addresspopa a 'pop valuepopa y 'pop targetcmp a,y wz'value = target?if_nz addspa #1'if mismatch, unpop targetif_z addptra x 'if match, branchorg snippet 'case range (z=1)
_caser call #xword 'get branch addresspopa b 'pop range endpopa a 'pop range beginpopa y 'pop targetsub b,a '||(end - begin), c=1 if reverse rangeabs b,b wcsub y,a '+/-(target - begin)negc y,y
cmp b,y wc'match if ||(end - begin) => +/-(target - begin)if_c addspa #1'if mismatch, unpop targetif_nc addptra x 'if match, branchorg snippet 'case done
_casedone popa x 'pop targetpopa x 'pop address
addptra x 'jump to address''' Lookup/lookdown'org snippet 'lookup value
_lookupv popa a 'pop valuepopa x 'pop indexpopa y 'pop targetcmp x,y wz'match if index = targetif_nz addspa #1'if no match, unpop targetif_nzadd x,#1'..increment indexif_nzpusha x '..push indexif_zpopa addr 'if match, pop addressif_zpusha a '..push resultif_z setptra addr '..branchorg snippet 'lookup range
_lookupr popa b 'pop range endpopa a 'pop range beginpopa x 'pop indexpopa y 'pop targetsub b,a 'end - beginabs b,b wc'||(end - begin), c=1 if reverse rangesub y,x 'target - indexsumc a,y 'result = begin +/- (target - index)cmp b,y wc'match if ||(end - begin) => (target - index)if_c addspa #1'if no match, unpop targetif_caddx x,b '..add ||(end - begin) + 1 to indexif_cpusha x '..push indexif_ncpopa addr 'if match, pop addressif_ncpusha a '..push resultif_nc setptra addr '..branchorg snippet 'lookdown value
_lookdnv popa a 'pop valuepopa x 'pop indexpopa y 'pop targetcmp a,y wz'match if value = targetif_nz addspa #1'if no match, unpop targetif_nzadd x,#1'..increment indexif_nzpusha x '..push indexif_zpopa addr 'if match, pop addressif_zpusha x '..push resultif_z setptra addr '..branchorg snippet 'lookdown range
_lookdnr popa b 'pop range endpopa a 'pop range beginpopa x 'pop indexpopa y 'pop targetsub b,a '||(end - begin), c=1 if reverse rangeabs b,b wcsub y,a '+/-(target - begin)negc y,y
cmp b,y wc'match if ||(end - begin) => +/-(target - begin)if_c addspa #1'if no match, unpop targetif_caddx x,b '..add ||(end - begin) + 1 to indexif_cpusha x '..push indexif_ncpopa addr 'if match, pop addressif_ncadd x,y '..result = index +/- (target - begin)if_ncpusha x '..push resultif_nc setptra addr '..branchorg snippet 'lookup/lookdown done
_lookdone subspa #3'pop index/target/addresspusha #0'push 0 result''' Miscellaneous'org snippet
_pop rdbytec x,ptra++ 'pop
subspa x
org snippet
_clkset popa x 'clksetclkset x
org snippet
_cogid cogid x 'cogidpusha x
org snippet
_coginit popa y 'coginitpopa x
popa a
setcog a
coginit x,y wcif_nz_and_cpusha #0if_nz_and_ncpusha hFFFFFFFF
org snippet
_cogstop popa x 'cogstopcogstop x
This interpreter is for the built-in 17-bit address space (128KB), but can easily be changed to 32-bit XMM. I started out on the 32-bit addressing path, but figured it was more practical, at first, to make a native 17-bit version, as an external SDRAM can easily be managed by Spin code for huge data.
This interpreter leaves the first $150+ longs in the cog free for in-line assembly code and terminate-stay-resident type applications which can run concurrently with the interpreter via hardware multi-tasking.
In the new Spin, all variables are bit-range addressable for read/write/read-modify-write operations. Bit ranges can be high..low or low..high. This is mainly important for I/O registers which relate to physical pins, but it makes bit fields within other types (locals, hub ram, cog RAM registers) easy to manipulate, as well.
This interpreter works by getting a byte code, looking up a descriptor long, loading a snippet of assembly code, and executing it. The interpreter currently lacks initialization code, which will be written last, but it has all the snippets for math operations, calls, branches, lookup/lookdown, cog starting and stopping, and housekeeping. It's about 4.5KB now. Once I get the compiler working on the PC side, I'll augment the interpreter to include special I/O handling and other functions that are not needed at first, but make it complete.
....
This interpreter leaves the first $150+ longs in the cog free for in-line assembly code and terminate-stay-resident type applications which can run concurrently with the interpreter via hardware multi-tasking.
....
Thanks Chip for the very interesting code.
A lot to study, but one thing caught my eye immediatly: You use a lot of delayed jumps/calls/returns. All with 3 delay slots. The problem is: if you do hardware multi tasking the number of the delay slots depends on the number of tasks and the task-scheduler settings.
So if the assembly code installs hardware tasks, the interpreter will no longer work. The only reliable solution for code that should work with and without tasks is to avoid delayed instructions. Unfortunatly this will make the interpreter a bit slower.
Some of the snippets (the short ones) would be faster implemented as LMM but of course that can come later.
I noticed that you don't have the return from the snippet coded within each snippet, nor a way to determine its length, so do you plan to make the compiler add this? Some form of a macro expansion would be nice for this.
The description table holds the length of the snippets in the lower 7 bits and the overlay loader always adds a jump back at the end of the loaded instructions.
A lot to study, but one thing caught my eye immediatly: You use a lot of delayed jumps/calls/returns. All with 3 delay slots. The problem is: if you do hardware multi tasking the number of the delay slots depends on the number of tasks and the task-scheduler settings.
So if the assembly code installs hardware tasks, the interpreter will no longer work. The only reliable solution for code that should work with and without tasks is to avoid delayed instructions. Unfortunatly this will make the interpreter a bit slower.
Andy
Good observation, Ariba! I guess I was on the road to "finding out" there was a problem. I'll have to get rid of all delayed jumps, as you've pointed out.
There is another more insidious problem that I've been thinking about: read-modify-writes to PINx and DIRx registers in Spin will conflict with concurrent multi-tasking PASM code doing atomic operations on PINx/DIRx. The only way around this is to limit Spin operations on PINx/DIRx to atomic operations like concurrent PASM code is likely to do. It makes affecting a bit field within those registers kind of impossible, unless your desire is to simply set or clear some bits. If we revise the Verilog, I'll make some atomic masked-write instructions that could get around this problem. For now, it's a problem. Even multi-threading can't get around this, as several Spin instructions might perform a r-m-w process on PINx/DIRx.
Good observation, Ariba! I guess I was on the road to "finding out" there was a problem. I'll have to get rid of all delayed jumps, as you've pointed out.
There is another more insidious problem that I've been thinking about: read-modify-writes to PINx and DIRx registers in Spin will conflict with concurrent multi-tasking PASM code doing atomic operations on PINx/DIRx. The only way around this is to limit Spin operations on PINx/DIRx to atomic operations like concurrent PASM code is likely to do. It makes affecting a bit field within those registers kind of impossible, unless your desire is to simply set or clear some bits. If we revise the Verilog, I'll make some atomic masked-write instructions that could get around this problem. For now, it's a problem. Even multi-threading can't get around this, as several Spin instructions might perform a r-m-w process on PINx/DIRx.
With an XOR instruction it should be possible to change a field of bits to any state you wish with an atomic instruction:.
Example:
As long as the concurrent PASM code does not change bits 3..9 of outa this should work.
Andy
Wow!!! That's a great idea. As long as the Spin code and concurrent PASM code don't mess with each other's pins, there would be no conflict. Problem solved. And no need for new instructions!
Thanks for thinking about this, Andy.
I'll have to make shadow registers for not just PINx, but DIRx, as well.
That sounds like you decided not to go with the shuttle run and share a mask with other designs?
The foundry we are using offers multi-layer reticles, not just single-layer. This means that a mask will have images for more than one process step. It's not ideal for mass production because they expose only half the area (or 1/3 or 1/4, etc.) at a time that a single-layer reticle would.
Comments
We don't know yet, but on our module we are using a 2-amp 1.8V switching power supply. It's possible that the chip could dissipate over two watts, going full-bore with everything running. Hopefully, we'll know what the power requirements are in 8 weeks when we hope to get a working chip back from the foundry.
It can't be just the logic, is that the peripheral analog circuitry? In which case the worst case won't be typical. In a standard QFP package of that size will see a 50 deg-C rise in junction temp/Watt. With most chips will begin failing at 150 C
Eight weeks is survivable, I'm crossing my fingers that everything works
Do you have an updated pinout for the modules, and descriptions of how you will handle the *DQM strapping?
Exposed pad is a relatively simple change, (I think no die impact?) and it would be a good idea to bond some of the pilot run into Exposed -Pad QFP.
That way, Parallax can measure the differences, and decide if the performance gains, are worth the (small) added cost.
The Exposed Pad variants I like the most, are ones where the package designer thought to allow via-space between the exposed pad, and pin areas.
In a larger package like TQFP128, this should be practical.
- have some threads been removed from here ? Seems less than there was in my browser.
I have been working on the new Spin compiler. I think I've got the interpreter code operable, but I must get the compiler done to prove it all. I've been working on this for over a month and so I haven't made any new documentation during this period. I really want to get the compiler operating, since that's the biggest thing hanging over my head, at this point. The rest is like a mop-up operation.
About a thermal-pad TQFP package: This could be done, but it will be a custom package design that will cost us $50k, since our die is too big for the thermal-pad package offered by our packager. If we see that the die works and runs hot, we'll spring for this, but first we must learn what we're dealing with.
Spin2interpreter.spin
CON base = $E80 ' ' '*************** '* Interpreter * '*************** ' DAT orgh base org $15B ' ' ' Append word to x - used to make $0xxxx or $1xxxx address ' xword rdbytec y,ptra++ xword_ret retd movf x,y rdbytec y,ptra++ movf x,y ' ' ' call obj.sub ' call obj.sub[] ' call obj[].sub ' call obj[].sub[] ' call sub ' call sub[] ' call ptr ' call_obj shl x,#2 'lookup obj vbase/pbase offsets add x,pbase rdlong x,x call_ptr rol x,#4 'set relative pbase add pbase,x and pbase,h0001FFF0 ror x,#16 'set relative vbase add vbase,x and vbase,h0001FFF0 call_sub shl y,#2 'lookup locals/pbase offsets add y,pbase rdlong y,y mov dbase,dcall 'set call dbase add dbase,#3 setspb dcall 'get old dcall popb dcall getptra x 'set return pcurr pushb x setptra pbase 'set call pcurr jmpd #getbyte 'loop to getbyte, delayed addptra y shr y,#32-4 'add locals to dcurr addspa y ' ' ' Bitfield addressing, pop and set bitfield parameters ' bitfield popa bshift 'pop range lsb popa bmask 'pop range msb and bshift,#$1F 'trim lsb/msb and bmask,#$1F cmp bmask,bshift wc 'reverse range? if_c xor bshift,bmask 'if reverse range, swap msb/lsb if_c xor bmask,bshift if_c xor bshift,bmask sub bmask,bshift 'get number of bits add bmask,#1 neg brev,bmask 'get rev count bitfield_ret retd 'return, delayed setbc brev,#6 'save reverse flag blmask bmask 'get bitlength mask shl bmask,bshift 'bmask = mask, brev = reverse, bshift = lsb offset ' ' ' Write register, if OUTA..OUTD then update PINA..PIND (x = value) ' writer movd writer_reg,addr movd writer_pin,addr setb writer_pin,#9+3 writer_reg mov $000,x writer_ret retd xor addr,#$1F0 test addr,#$1FC wz writer_pin if_z mov $000,x ' ' ' Do bitfield read (x = value) ' readb and x,bmask jmpd #getbyte shr x,bshift if_c rev x,brev pusha x ' ' ' Do bitfield write (bval = value, writeb_i = write instruction) ' writeb popa x 'pop value to write if_c rev x,brev 'reverse bits? shl x,bshift 'shift into position and x,bmask 'mask bits andn bval,bmask 'mask away original bits or x,bval 'merge bits writeb_i pushbr x 'call #writer / pushbr x / wrxxxx x,addr writeb_ret jmp #getbyte ' ' ' Do bitfield assignment (bval = value, assignb_i = write instruction, mask = sized mask) ' assignb_long mov mask,hFFFFFFFF 'set long mask assignb movs jmpback,#assignb_ret 'set jmpback address to assignb_ret mov x,bval 'save original value jmpd #assign_op 'get math operator and execute, delayed and x,bmask 'extract bitfield for operation shr x,bshift if_c rev x,brev assignb_ret testb brev,#6 wc 'snippet returns to here, get reverse flag into c call #writeb 'write bitfield movs writeb_ret,#getbyte 'restore jump to getbyte and x,mask 'mask it jmpd #assign_p 'push it (optional), delayed and x,bmask 'extract bitfield for pushing shr x,bshift if_c rev x,brev ' ' ' Do assignment (x = value, assign_i = write instruction, mask = sized mask) ' assign_local mov assign_i,pushbrx 'set local write assign_long mov mask,hFFFFFFFF 'set long mask assign movs jmpback,#assign_ret 'set jmpback address to :ret assign_op rdbytec a,ptra++ 'get math operator and flags setzc a wz,wc 'load flags, operator already in position muxz assign_p,h003C0000 'set push condition to z jmpd #hotbyte 'load and execute math snippet, delayed if_c popa y 'swap args? pusha x if_c pusha y assign_ret popa x 'snippet returns to here, pop value assign_i pushbr x 'write it (call #writer / pushbr x / wrxxxx x,addr) and x,mask 'mask it assign_p pusha x 'push it (optional) movs jmpback,#getbyte 'replace jmpback address, getbyte next ' ' ' Get byte code, look up descriptor long, load code longs in-line, execute, repeat ' getbyte rdbytec a,ptra++ wz ' get byte code, extended? if_z rdbytec a,ptra++ ' if extended, get extended byte code if_z or a,#$100 ' ...and add offset shl a,#2 ' shift to make long offset hotbyte add a,descbase ' add base address of descriptor longs rdlong x,a '..2 get descriptor long movd :reps,x '3 descriptor[8..0] holds code longs minus 1 shr x,#7 '4 descriptor[23..7] is code offset setptrb x '5 point PTRB to code longs :reps reps #1,#1 '6 ready for fast in-line code load setindb #snippet '7 point INDB to in-line code rdlongc indb++,ptrb++ '0.. load code longs in-line using cached read mov indb++,jmpback '+1 finish in-line code with 'jmp #getbyte' shr x,#25-7 wz,wc '+1 descriptor[31..25] is a value, [24] is C snippet long 0[22] '? execute in-line code snippet, loop ' ' ' Constants ' pushbrx pushbr x callwriter call #writer jmpback jmp #getbyte descbase long @descs-4 'account for $01 offset h0001FFF0 long $0001FFF0 'vbase/pbase mask h003C0000 long $003C0000 'conditional field bits hFFFFFFFF long $FFFFFFFF 'all bits x long 0 'variables y long 0 a long 0 b long 0 addr long 0 'assignment mask long 0 bshift long 0 'bitfield addressing bmask long 0 brev long 0 bval long 0 dcall long 0 ' pointer dbase long 0 ' pointer outa long 0 '@$1F0 OUTA..OUTD outb long 0 '@$1F1 (writes update PINA..PIND) outc long 0 '@$1F2 outd long 0 '@$1F3 vbase long 0 '@$1F4 pointer pbase long 0 '@$1F5 pointer ' ' '************************ '* Bytecode Descriptors * '************************ ' descs ' variable modifiers (14) op_writep long %0000000_0 << 24 + @_clr << 7 + 0 'write w/push %10 push op_rep long %0000000_0 << 24 + @_rep << 7 + 12 'repeat var %00 no op_clr long %0000000_0 << 24 + @_clr << 7 + 1 'clear %00 no op_clrpost long %0000000_0 << 24 + @_clrpost << 7 + 0 'clear post %00 push op_set long %0000000_0 << 24 + @_set << 7 + 1 'set %00 no op_setpost long %0000000_0 << 24 + @_setpost << 7 + 0 'set post %00 push op_incpre long %0000000_0 << 24 + @_incdec << 7 + 3 'inc pre / inc %10 push / %00 no op_incpost long %0000001_0 << 24 + @_incdec << 7 + 3 'inc post %00 push op_decpre long %0000000_1 << 24 + @_incdec << 7 + 3 'dec pre / dec %10 push / %00 no op_decpost long %0000001_1 << 24 + @_incdec << 7 + 3 'dec post %00 push op_incmod long %0000000_0 << 24 + @_idmod << 7 + 6 'incmod %00 no op_incmodp long %0000001_0 << 24 + @_idmod << 7 + 6 'incmod w/push %00 push op_decmod long %0000000_1 << 24 + @_idmod << 7 + 6 'decmod %00 no op_decmodp long %0000001_1 << 24 + @_idmod << 7 + 6 'decmod w/push %00 push ' unaries (23) op_notb long %0000000_0 << 24 + @_notb << 7 + 2 'NOT %x0 op_not long %0000000_0 << 24 + @_not << 7 + 2 '! %x0 op_neg long %0000000_0 << 24 + @_neg << 7 + 2 '- %x0 op_abs long %0000000_0 << 24 + @_abs << 7 + 2 '|| %x0 op_enc long %0000000_0 << 24 + @_enc << 7 + 2 '>| %x0 op_decod5 long %0000000_0 << 24 + @_decod5 << 7 + 2 '|<, DECOD5(x) %x0 op_decod4 long %0000000_0 << 24 + @_decod4 << 7 + 2 'DECOD4(x) %x0 op_decod3 long %0000000_0 << 24 + @_decod3 << 7 + 2 'DECOD3(x) %x0 op_decod2 long %0000000_0 << 24 + @_decod2 << 7 + 2 'DECOD2(x) %x0 op_blmask long %0000000_0 << 24 + @_blmask << 7 + 2 'BLMASK(x) %x0 op_onecnt long %0000000_0 << 24 + @_onecnt << 7 + 2 'ONECNT(x) %x0 op_zercnt long %0000000_0 << 24 + @_zercnt << 7 + 2 'ZERCNT(x) %x0 op_incpat long %0000000_0 << 24 + @_incpat << 7 + 2 'INCPAT(x) %x0 op_decpat long %0000000_0 << 24 + @_decpat << 7 + 2 'DECPAT(x) %x0 op_bingry long %0000000_0 << 24 + @_bingry << 7 + 2 'BINGRY(x) %x0 op_grybin long %0000000_0 << 24 + @_grybin << 7 + 2 'GRYBIN(x) %x0 op_mergew long %0000000_0 << 24 + @_mergew << 7 + 2 'MERGEW(x) %x0 op_splitw long %0000000_0 << 24 + @_splitw << 7 + 2 'SPLITW(x) %x0 op_seussf long %0000000_0 << 24 + @_seussf << 7 + 2 'SEUSSF(x) %x0 op_seussr long %0000000_0 << 24 + @_seussr << 7 + 2 'SEUSSR(x) %x0 op_sqrt long %0000000_0 << 24 + @_sqrt << 7 + 4 'SQRT(x) %x0 op_qlog long %0000000_0 << 24 + @_qlogexp << 7 + 5 'QLOG(x) %x0 op_qexp long %0000000_1 << 24 + @_qlogexp << 7 + 5 'QEXP(x) %x0 ' binaries (23) op_andb long %0000000_0 << 24 + @_andb << 7 + 4 'AND %x1 op_orb long %0000000_0 << 24 + @_orb << 7 + 4 'OR %x1 op_xorb long %0000000_0 << 24 + @_xorb << 7 + 5 'XOR %x1 op_andn long %0000000_0 << 24 + @_andn << 7 + 3 '&! %x1 op_and long %0000000_0 << 24 + @_and << 7 + 3 '& %x1 op_or long %0000000_0 << 24 + @_or << 7 + 3 '| %x1 op_xor long %0000000_0 << 24 + @_xor << 7 + 3 '^ %x1 op_ror long %0000000_0 << 24 + @_ror << 7 + 3 '-> %x1 op_rol long %0000000_0 << 24 + @_rol << 7 + 3 '<- %x1 op_shr long %0000000_0 << 24 + @_shr << 7 + 3 '>> %x1 op_shl long %0000000_0 << 24 + @_shl << 7 + 3 '<< %x1 op_sar long %0000000_0 << 24 + @_sar << 7 + 3 '~> %x1 op_sal long %0000000_0 << 24 + @_sal << 7 + 5 '<~ %x1 op_rev long %0000000_0 << 24 + @_rev << 7 + 4 '>< %x1 op_mins long %0000000_0 << 24 + @_mins << 7 + 3 '#> %x1 op_maxs long %0000000_0 << 24 + @_maxs << 7 + 3 '<# %x1 op_add long %0000000_0 << 24 + @_add << 7 + 3 '+ %x1 op_sub long %0000000_0 << 24 + @_sub << 7 + 3 '- %x1 op_mul long %0000000_0 << 24 + @_mul << 7 + 6 '* %x1 op_scl long %0000001_0 << 24 + @_scl << 7 + 6 '** %x1 op_quo long %0000000_0 << 24 + @_divx << 7 + 7 '/ %x1 op_rem long %0000001_0 << 24 + @_divx << 7 + 7 '// %x1 op_fra long %0000000_0 << 24 + @_fra << 7 + 7 '*/ %x1 ' equality tests (6) op_b long %0000000_0 << 24 + @_b << 7 + 4 '< op_a long %0000000_0 << 24 + @_a << 7 + 4 '> op_ne long %0000000_0 << 24 + @_ne << 7 + 4 '<> op_eq long %0000000_0 << 24 + @_eq << 7 + 4 '== op_be long %0000000_0 << 24 + @_be << 7 + 4 '=< / <= op_ae long %0000000_0 << 24 + @_ae << 7 + 4 '=> / >= ' math terms (8) op_quo64 long %0000000_0 << 24 + @_divh64 << 7 + 10 'QUO64(al,ah,b) op_quo64u long %0000000_1 << 24 + @_divh64 << 7 + 10 'QUO64U(al,ah,b) op_rem64 long %0000001_0 << 24 + @_divh64 << 7 + 10 'REM64(al,ah,b) op_rem64u long %0000001_1 << 24 + @_divh64 << 7 + 10 'REM64U(al,ah,b) op_sqrt64 long %0000000_0 << 24 + @_sqrt64 << 7 + 6 'SQRT64(l,h) op_negb long %0000000_0 << 24 + @_negb << 7 + 3 'NEGB(x,bool) op_muxb long %0000000_0 << 24 + @_muxb << 7 + 4 'MUXB(x,y,bool) op_ternary long %0000000_0 << 24 + @_ternary << 7 + 4 'sel ? true : false ' math procedures (20) op_mul64 long %0000000_0 << 24 + @_mul64 << 7 + 9 'MUL64(a,b : l,h) op_mulu64 long %0000000_1 << 24 + @_mul64 << 7 + 9 'MUL64U(a,b : l,h) op_div64 long %0000000_0 << 24 + @_div64 << 7 + 11 'DIV64(a,b : l,h) op_divu64 long %0000000_1 << 24 + @_div64 << 7 + 11 'DIV64U(a,b : l,h) op_qsincos long %0000000_0 << 24 + @_qtrig << 7 + 12 'QSINCOS(r,t : x,y) op_qarctan long %0000001_0 << 24 + @_qtrig << 7 + 12 'QARCTAN(x,y : r,t) op_qrotate long %0000000_1 << 24 + @_qtrig << 7 + 12 'QROTATE(x,y,t : x,y) op_setqi long %0000000_1 << 24 + @_div64 << 7 + 1 'SETQI(x) op_clraccs long %0000000_0 << 24 + @_clraccs << 7 + 0 'CLRACCS op_clracca long %0000000_0 << 24 + @_clracca << 7 + 0 'CLRACCA op_clraccb long %0000000_0 << 24 + @_clraccb << 7 + 0 'CLRACCB op_fitaccs long %0000000_0 << 24 + @_fitaccs << 7 + 0 'FITACCS op_fitacca long %0000000_0 << 24 + @_fitacca << 7 + 0 'FITACCA op_fitaccb long %0000000_0 << 24 + @_fitaccb << 7 + 0 'FITACCB op_setacca long %0000000_0 << 24 + @_setacca << 7 + 2 'SETACCA(l,h) op_setaccb long %0000000_0 << 24 + @_setaccb << 7 + 2 'SETACCB(l,h) op_getacca long %0000000_0 << 24 + @_getacca << 7 + 3 'GETACCA(l,h) op_getaccb long %0000000_0 << 24 + @_getaccb << 7 + 3 'GETACCB(l,h) op_maca long %0000000_0 << 24 + @_maca << 7 + 2 'MACA(x,y) op_macb long %0000000_0 << 24 + @_macb << 7 + 2 'MACB(x,y) ' constants (13) op_con1n long %0000000_0 << 24 + @_conxn << 7 + 1 'constant -1 op_con0 long %0000000_0 << 24 + @_conxp << 7 + 0 'constant 0 op_con1 long %0000001_0 << 24 + @_conxp << 7 + 0 'constant 1 op_con8p long %0000000_0 << 24 + @_con8p << 7 + 1 'constant $000000xx op_con9p long %0000000_0 << 24 + @_con9p << 7 + 2 'constant $000001xx op_con8n long %0000000_0 << 24 + @_con8n << 7 + 2 'constant $FFFFFFxx op_con16p long %0000000_0 << 24 + @_con16p << 7 + 3 'constant $0000xxxx op_con17p long %0000000_0 << 24 + @_con17p << 7 + 3 'constant $0001xxxx op_con16n long %0000000_0 << 24 + @_con16n << 7 + 4 'constant $FFFFxxxx op_con24p long %0000000_0 << 24 + @_con24 << 7 + 4 'constant $00xxxxxx op_con24n long %0000000_1 << 24 + @_con24 << 7 + 4 'constant $FFxxxxxx op_con32 long %0000000_0 << 24 + @_con32 << 7 + 4 'constant $xxxxxxxx op_conexp long %0000000_0 << 24 + @_conexp << 7 + 4 'constant 2^n,dec,not ' register reads/writes/assigns (6) op_rdreg long %0000000_0 << 24 + @_rdreg << 7 + 4 'read register op_wrreg long %0000000_0 << 24 + @_wrreg << 7 + 2 'write register op_asreg long %0000000_0 << 24 + @_asreg << 7 + 5 'assign register op_rdregb long %0000000_0 << 24 + @_rdregb << 7 + 6 'read register bitfield op_wrregb long %0000000_0 << 24 + @_wrregb << 7 + 6 'write register bitfield op_asregb long %0000000_0 << 24 + @_asregb << 7 + 6 'assign register bitfield ' local reads/writes/assigns (54) op_rdloc0 long %0000000_0 << 24 + @_rdloc << 7 + 3 'read local 0 op_rdloc1 long %0000001_0 << 24 + @_rdloc << 7 + 3 'read local 1 op_rdloc2 long %0000010_0 << 24 + @_rdloc << 7 + 3 'read local 2 op_rdloc3 long %0000011_0 << 24 + @_rdloc << 7 + 3 'read local 3 op_rdloc4 long %0000100_0 << 24 + @_rdloc << 7 + 3 'read local 4 op_rdloc5 long %0000101_0 << 24 + @_rdloc << 7 + 3 'read local 5 op_rdloc6 long %0000110_0 << 24 + @_rdloc << 7 + 3 'read local 6 op_rdloc7 long %0000111_0 << 24 + @_rdloc << 7 + 3 'read local 7 op_rdloc8 long %0001000_0 << 24 + @_rdloc << 7 + 3 'read local 8 op_rdloc9 long %0001001_0 << 24 + @_rdloc << 7 + 3 'read local 9 op_rdloc10 long %0001010_0 << 24 + @_rdloc << 7 + 3 'read local 10 op_rdloc11 long %0001011_0 << 24 + @_rdloc << 7 + 3 'read local 11 op_rdloc12 long %0001100_0 << 24 + @_rdloc << 7 + 3 'read local 12 op_rdloc13 long %0001101_0 << 24 + @_rdloc << 7 + 3 'read local 13 op_rdloc14 long %0001110_0 << 24 + @_rdloc << 7 + 3 'read local 14 op_rdloc15 long %0001111_0 << 24 + @_rdloc << 7 + 3 'read local 15 op_wrloc0 long %0000000_0 << 24 + @_wrloc << 7 + 3 'write local 0 op_wrloc1 long %0000001_0 << 24 + @_wrloc << 7 + 3 'write local 1 op_wrloc2 long %0000010_0 << 24 + @_wrloc << 7 + 3 'write local 2 op_wrloc3 long %0000011_0 << 24 + @_wrloc << 7 + 3 'write local 3 op_wrloc4 long %0000100_0 << 24 + @_wrloc << 7 + 3 'write local 4 op_wrloc5 long %0000101_0 << 24 + @_wrloc << 7 + 3 'write local 5 op_wrloc6 long %0000110_0 << 24 + @_wrloc << 7 + 3 'write local 6 op_wrloc7 long %0000111_0 << 24 + @_wrloc << 7 + 3 'write local 7 op_wrloc8 long %0001000_0 << 24 + @_wrloc << 7 + 3 'write local 8 op_wrloc9 long %0001001_0 << 24 + @_wrloc << 7 + 3 'write local 9 op_wrloc10 long %0001010_0 << 24 + @_wrloc << 7 + 3 'write local 10 op_wrloc11 long %0001011_0 << 24 + @_wrloc << 7 + 3 'write local 11 op_wrloc12 long %0001100_0 << 24 + @_wrloc << 7 + 3 'write local 12 op_wrloc13 long %0001101_0 << 24 + @_wrloc << 7 + 3 'write local 13 op_wrloc14 long %0001110_0 << 24 + @_wrloc << 7 + 3 'write local 14 op_wrloc15 long %0001111_0 << 24 + @_wrloc << 7 + 3 'write local 15 op_asloc0 long %0000000_0 << 24 + @_asloc << 7 + 3 'assign local 0 op_asloc1 long %0000001_0 << 24 + @_asloc << 7 + 3 'assign local 1 op_asloc2 long %0000010_0 << 24 + @_asloc << 7 + 3 'assign local 2 op_asloc3 long %0000011_0 << 24 + @_asloc << 7 + 3 'assign local 3 op_asloc4 long %0000100_0 << 24 + @_asloc << 7 + 3 'assign local 4 op_asloc5 long %0000101_0 << 24 + @_asloc << 7 + 3 'assign local 5 op_asloc6 long %0000110_0 << 24 + @_asloc << 7 + 3 'assign local 6 op_asloc7 long %0000111_0 << 24 + @_asloc << 7 + 3 'assign local 7 op_asloc8 long %0001000_0 << 24 + @_asloc << 7 + 3 'assign local 8 op_asloc9 long %0001001_0 << 24 + @_asloc << 7 + 3 'assign local 9 op_asloc10 long %0001010_0 << 24 + @_asloc << 7 + 3 'assign local 10 op_asloc11 long %0001011_0 << 24 + @_asloc << 7 + 3 'assign local 11 op_asloc12 long %0001100_0 << 24 + @_asloc << 7 + 3 'assign local 12 op_asloc13 long %0001101_0 << 24 + @_asloc << 7 + 3 'assign local 13 op_asloc14 long %0001110_0 << 24 + @_asloc << 7 + 3 'assign local 14 op_asloc15 long %0001111_0 << 24 + @_asloc << 7 + 3 'assign local 15 op_rdloci long %0000000_0 << 24 + @_rdloci << 7 + 6 'read local indexed op_wrloci long %0000000_0 << 24 + @_wrloci << 7 + 6 'write local indexed op_asloci long %0000000_0 << 24 + @_asloci << 7 + 6 'assign local indexed op_rdlocb long %0000000_0 << 24 + @_rdlocb << 7 + 5 'read local bitfield op_wrlocb long %0000000_0 << 24 + @_wrlocb << 7 + 6 'write local bitfield op_aslocb long %0000000_0 << 24 + @_aslocb << 7 + 6 'assign local bitfield ' memory reads/writes/assigns (18) op_rdbyte long %0000000_0 << 24 + @_rdbyte << 7 + 2 'read byte op_rdword long %0000000_0 << 24 + @_rdword << 7 + 2 'read word op_rdlong long %0000000_0 << 24 + @_rdlong << 7 + 2 'read long op_wrbyte long %0000000_0 << 24 + @_wrbyte << 7 + 2 'write byte op_wrword long %0000000_0 << 24 + @_wrword << 7 + 2 'write word op_wrlong long %0000000_0 << 24 + @_wrlong << 7 + 2 'write long op_asbyte long %0000000_0 << 24 + @_asbyte << 7 + 5 'assign byte op_asword long %0000000_0 << 24 + @_asword << 7 + 6 'assign word op_aslong long %0000000_0 << 24 + @_aslong << 7 + 4 'assign long op_rdbyteb long %0000000_0 << 24 + @_rdbyteb << 7 + 3 'read byte bitfield op_rdwordb long %0000000_0 << 24 + @_rdwordb << 7 + 3 'read word bitfield op_rdlongb long %0000000_0 << 24 + @_rdlongb << 7 + 3 'read long bitfield op_wrbyteb long %0000000_0 << 24 + @_wrbyteb << 7 + 5 'write byte bitfield op_wrwordb long %0000000_0 << 24 + @_wrwordb << 7 + 5 'write word bitfield op_wrlongb long %0000000_0 << 24 + @_wrlongb << 7 + 5 'write long bitfield op_asbyteb long %0000000_0 << 24 + @_asbyteb << 7 + 6 'assign byte bitfield op_aswordb long %0000000_0 << 24 + @_aswordb << 7 + 7 'assign word bitfield op_aslongb long %0000000_0 << 24 + @_aslongb << 7 + 5 'assign long bitfield ' memory offsets and indexing (7) op_vbase0 long %0000000_0 << 24 + @_base << 7 + 3 'vbase $0xxxx op_pbase0 long %0000000_1 << 24 + @_base << 7 + 3 'pbase $0xxxx op_vbase1 long %0000001_0 << 24 + @_base << 7 + 3 'vbase $1xxxx op_pbase1 long %0000001_1 << 24 + @_base << 7 + 3 'pbase $1xxxx op_ibyte long %0000000_0 << 24 + @_index << 7 + 4 'byte index op_iword long %0000001_0 << 24 + @_index << 7 + 4 'word index op_ilong long %0000010_0 << 24 + @_index << 7 + 4 'long index ' branches jmp/jz/jnz/tjz/djnz (10) op_jmp0 long %0000000_0 << 24 + @_jmp << 7 + 1 'jmp +$0xxxx op_jmp1 long %0000001_0 << 24 + @_jmp << 7 + 1 'jmp +$1xxxx op_jz0 long %0000000_1 << 24 + @_jxz << 7 + 2 'jz +$0xxxx op_jz1 long %0000001_1 << 24 + @_jxz << 7 + 2 'jz +$1xxxx op_jnz0 long %0000000_0 << 24 + @_jxz << 7 + 2 'jnz +$0xxxx op_jnz1 long %0000001_0 << 24 + @_jxz << 7 + 2 'jnz +$1xxxx op_tjz0 long %0000000_0 << 24 + @_tjz << 7 + 3 'tjz +$0xxxx op_tjz1 long %0000001_0 << 24 + @_tjz << 7 + 3 'tjz +$1xxxx op_djnz0 long %0000000_0 << 24 + @_djnz << 7 + 4 'djnz +$0xxxx op_djnz1 long %0000001_0 << 24 + @_djnz << 7 + 4 'djnz +$1xxxx ' anchor drops (4) op_dropt long %0000000_0 << 24 + @_drop << 7 + 6 'drop, \sub op_droptr long %0000001_0 << 24 + @_drop << 7 + 6 'drop, \sub w/result op_drop long %0000010_0 << 24 + @_drop << 7 + 6 'drop, sub op_dropr long %0000011_0 << 24 + @_drop << 7 + 6 'drop, sub w/result ' calls (7) op_callos long %0000000_0 << 24 + @_callobj << 7 + 6 'call obj.sub op_callosi long %0000000_1 << 24 + @_callobj << 7 + 6 'call obj.sub[] op_callois long %0000001_0 << 24 + @_callobj << 7 + 6 'call obj[].sub op_calloisi long %0000001_1 << 24 + @_callobj << 7 + 6 'call obj[].sub[] op_calls long %0000000_0 << 24 + @_callsub << 7 + 3 'call sub op_callsi long %0000000_1 << 24 + @_callsub << 7 + 3 'call sub[] op_callp long %0000000_0 << 24 + @_callptr << 7 + 10 'call ptr ' returns (4) op_return long %0000000_0 << 24 + @_return << 7 + 13 'RETURN op_abort long %0000000_1 << 24 + @_return << 7 + 13 'ABORT op_returnv long %0000001_0 << 24 + @_return << 7 + 13 'RETURN value op_abortv long %0000001_1 << 24 + @_return << 7 + 13 'ABORT value ' call pointer generation (5) op_basesub long %0000000_0 << 24 + @_basesub << 7 + 5 'vbase/pbase of current op_baseobj long %0000000_0 << 24 + @_baseobj << 7 + 16 'vbase/pbase of obj op_baseobji long %0000000_1 << 24 + @_baseobj << 7 + 16 'vbase/pbase of obj[] op_subptr long %0000000_0 << 24 + @_subptr << 7 + 11 'base.sub op_subptri long %0000000_1 << 24 + @_subptr << 7 + 11 'base.sub[] ' case (5) op_casev0 long %0000000_0 << 24 + @_casev << 7 + 5 'case value, +$0xxxx branch op_casev1 long %0000001_0 << 24 + @_casev << 7 + 5 'case value, +$1xxxx branch op_caser0 long %0000000_0 << 24 + @_caser << 7 + 10 'case range, +$0xxxx branch op_caser1 long %0000001_0 << 24 + @_caser << 7 + 10 'case range, +$1xxxx branch op_casedone long %0000000_0 << 24 + @_casedone << 7 + 2 'case done ' lookup/lookdown (5) op_lookupv long %0000000_0 << 24 + @_lookupv << 7 + 9 'lookup value op_lookupr long %0000000_0 << 24 + @_lookupr << 7 + 14 'lookup range op_lookdnv long %0000000_0 << 24 + @_lookdnv << 7 + 9 'lookdown value op_lookdnr long %0000000_0 << 24 + @_lookdnr << 7 + 15 'lookdown range op_lookdone long %0000000_0 << 24 + @_lookdone << 7 + 1 'lookup/lookdown done ' miscellaneous (6) op_pop long %0000000_0 << 24 + @_pop << 7 + 1 'pop op_clkset long %0000000_0 << 24 + @_clkset << 7 + 1 'clkset op_cogid long %0000000_0 << 24 + @_cogid << 7 + 1 'cogid op_coginit long %0000000_0 << 24 + @_coginit << 7 + 6 'coginit op_coginitp long %0000001_0 << 24 + @_coginit << 7 + 6 'coginit w/push op_cogstop long %0000000_0 << 24 + @_cogstop << 7 + 1 'cogstop ' ' '************ '* Snippets * '************ ' ' ' ' Variable modifiers ' org snippet 'repeat-var loop (assign) _rep popa mask 'pop var popa y 'pop step popa b 'pop terminal popa a 'pop initial popa addr 'pop branch offset cmps b,a wc 'get reverse range into c sumc mask,y 'update var with step rcl x,#1 wz 'get c into nz if_z cmps b,mask wc 'if forward range, check if var > terminal if_nz cmps mask,b wc 'if reverse range, check if var < terminal if_nc subptra addr 'if var within range, branch if_nc addspa #4 '..unpop offset/initial/terminal/step pusha mask 'push new var org snippet 'var~, clear and post-clear (assign) _clr popa x 'clear, pop var (single pop also used by op_writep) _clrpost pusha #0 'post-clear, push 0 (leave var on stack) org snippet 'var~~, set and post-set (assign) _set popa x 'set, pop var _setpost pusha hFFFFFFFF 'post-set, push -1 (leave var on stack) org snippet '++var/--var/var++/var-- (assign) _incdec popa x 'pop var if_nz pusha x 'if nz, push original var sumc x,#1 'inc or dec var by c pusha x 'push new var org snippet 'INCMOD/DECMOD(var,limit) (assign) _idmod setbc :i,#26 'set INCMOD/DECMOD by c popa y 'pop limit popa x 'pop var :i incmod x,y wc 'incmod/decmod, c=limit if_nz_and_nc pusha #0 'push false if nz and nc if_nz_and_c pusha hFFFFFFFF 'push true if nz and c pusha x 'push new var ' ' ' Unary functions ' org snippet _notb popa x wz 'NOT, boolean muxz x,hFFFFFFFF pusha x org snippet _not popa x '!, bitwise not not x pusha x org snippet _neg popa x '-, negate neg x,x pusha x org snippet _abs popa x '||, absolute abs x,x pusha x org snippet _enc popa x '>|, encode (0..32) enc x,x pusha x org snippet _decod5 popa x '|< / DECOD5(x) decod5 x pusha x org snippet _decod4 popa x 'DECOD4(x) decod4 x pusha x org snippet _decod3 popa x 'DECOD3(x) decod3 x pusha x org snippet _decod2 popa x 'DECOD2(x) decod2 x pusha x org snippet _blmask popa x 'BLMASK(x) blmask x pusha x org snippet _onecnt popa x 'ONECNT(x) onecnt x pusha x org snippet _zercnt popa x 'ZERCNT(x) zercnt x pusha x org snippet _incpat popa x 'INCPAT(x) incpat x pusha x org snippet _decpat popa x 'DECPAT(x) decpat x pusha x org snippet _bingry popa x 'BINGRY(x) bingry x pusha x org snippet _grybin popa x 'GRYBIN(x) grybin x pusha x org snippet _mergew popa x 'MERGEW(x) mergew x pusha x org snippet _splitw popa x 'SPLITW(x) splitw x pusha x org snippet _seussf popa x 'SEUSSF(x) seussf x pusha x org snippet _seussr popa x 'SEUSSR(x) seussr x pusha x org snippet _sqrt popa x 'SQRT(x) setsqrl x getsqrt x wc if_nc jmp #$-1 pusha x org snippet _qlogexp popa x 'QLOG(x), c=0 if_nc qlog x 'QEXP(x), c=1 if_c qexp x getqz x wc if_nc jmp #$-1 pusha x ' ' ' Binary functions ' org snippet _andb popa x wz 'AND, boolean if_z popa x if_nz popa x wz muxnz x,hFFFFFFFF pusha x org snippet _orb popa x wz 'OR, boolean if_nz popa x if_z popa x wz muxnz x,hFFFFFFFF pusha x org snippet _xorb popa y wz 'XOR, boolean muxnz y,hFFFFFFFF popa x wz muxnz x,hFFFFFFFF xor x,y pusha x org snippet _andn popa y '&!, bitwise andnot popa x andn x,y pusha x org snippet _and popa y '&, bitwise and popa x and x,y pusha x org snippet _or popa y '|, bitwise or popa x or x,y pusha x org snippet _xor popa y '^, bitwise xor popa x xor x,y pusha x org snippet _ror popa y '->, rotate right popa x ror x,y pusha x org snippet _rol popa y '<-, rotate left popa x rol x,y pusha x org snippet _shr popa y '>>, shift right popa x shr x,y pusha x org snippet _shl popa y '<<, shift left popa x shl x,y pusha x org snippet _sar popa y '~>, shift arithmetic right popa x sar x,y pusha x org snippet _sal popa y '<~, shift arithmetic left popa x rev x,#0 sar x,y rev x,#0 pusha x org snippet _rev popa y '><, reverse bits popa x neg y,y rev x,y pusha x org snippet _mins popa y '|>, limit minimum popa x mins x,y pusha x org snippet _maxs popa y '<|, limit maximum popa x maxs x,y pusha x org snippet _add popa y '+, add popa x add x,y pusha x org snippet _sub popa y '-, sub popa x sub x,y pusha x org snippet _mul popa y '*, multiply and return lower long popa x setmula x setmulb y getmull x wc if_nc jmp #$-1 pusha x org snippet _scl popa y '**, multiply return upper long, unsigned popa x setmulu x setmulb y getmulh x wc if_nc jmp #$-1 pusha x org snippet _divx popa y '/, divide and return quotient, z=1 popa x '//, divide and return remainder, z=0 setdiva x setdivb y getdivq x wc if_nc jmp #$-1 if_nz getdivr x pusha x org snippet _fra popa y '*/, fraction popa x setdivu #0 setdivu x setdivb y getdivq x wc if_nc jmp #$-1 pusha x ' ' ' Equality tests ' org snippet _b popa y '<, test below popa x cmps x,y wc muxc x,hFFFFFFFF pusha x org snippet _a popa y '>, test above popa x cmps y,x wc muxc x,hFFFFFFFF pusha x org snippet _ne popa y '<>, test not equal popa x cmps x,y wz muxnz x,hFFFFFFFF pusha x org snippet _eq popa y '==, test equal popa x cmps x,y wz muxz x,hFFFFFFFF pusha x org snippet _be popa y '=< / <=, test below or equal popa x cmps y,x wc muxnc x,hFFFFFFFF pusha x org snippet _ae popa y '=> / >=, test above or equal popa x cmps x,y wc muxnc x,hFFFFFFFF pusha x ' ' ' Math terms ' org snippet _divh64 popa y 'QUO64(al,ah,b), z=1, c=0 popa x 'QUO64U(al,ah,b), z=1, c=1 popa a 'REM64(al,ah,b), z=0, c=0 if_nc setdiva a 'REM64U(al,ah,b), z=0, c=1 if_c setdivu a setdiva x setdivb y getdivq x wc if_nc jmp #$-1 if_nz getdivr x wc pusha x org snippet _sqrt64 popa x 'SQRT64(l,h) setsqrh x popa x setsqrl x getsqrt x wc if_nc jmp #$-1 pusha x org snippet _negb popa x wz 'NEGB(x,bool) popa x negnz x,x pusha x org snippet _muxb popa y wz 'MUXB(x,y,bool) popa y popa x muxnz x,y pusha x org snippet _ternary popa y 'a ? x : y popa x popa a wz if_z pusha y if_nz pusha x ' ' ' Math procedures ' org snippet _mul64 popa x 'MUL64(a,b : l,h), c=0 if_nc setmula x 'MUL64U(a,b : l,h), c=1 if_c setmulu x popa x setmulb x getmulh x wc if_nc jmp #$-1 pusha x getmull x pusha x org snippet _div64 popa y 'DIV64(al,ah,b : q,r), c=0 popa x 'DIV64U(al,ah,b : q,r), c=1 popa a if_nc setdiva a if_c setdivu a setdiva x setdivb y getdivr x wc if_nc jmp #$-1 pusha x getdivq x wc pusha x org snippet _qtrig if_z_and_c popa x 'QSINCOS(r,t : x,y), z=1, c=0 if_z_and_c setqz x 'QROTATE(x,y,t : x,y), z=1, c=1 popa y 'QARCTAN(x,y : r,t), z=0 popa x if_z_and_nc qsincos y,x if_z_and_c qrotate x,y if_nz qarctan x,y getqz x wc if_nc jmp #$-1 if_z getqy x pusha x getqx x pusha x org snippet _setqi popa x 'SETQI(i) setqi x org snippet _clraccs clraccs 'CLRACCS org snippet _clracca clracca 'CLRACCA org snippet _clraccb clraccb 'CLRACCB org snippet _fitaccs fitaccs 'FITACCS org snippet _fitacca fitacca 'FITACCA org snippet _fitaccb fitaccb 'FITACCB org snippet _setacca popa y 'SETACCA(l,h) popa x setacca x,y org snippet _setaccb popa y 'SETACCB(l,h) popa x setaccb x,y org snippet _getacca getacca x 'GETACCA(l,h) getacca y pusha y pusha x org snippet _getaccb getaccb x 'GETACCB(l,h) getaccb y pusha y pusha x org snippet _maca popa y 'MACA(x,y) popa x maca x,y org snippet _macb popa y 'MACB(x,y) popa x macb x,y ' ' ' Constants ' org snippet _con8p rdbytec x,ptra++ 'con8p _conxp pusha x 'con0..con3 org snippet _con9p rdbytec x,ptra++ 'con9p setb x,#8 pusha x org snippet _con8n rdbytec x,ptra++ 'con8n _conxn xor x,hFFFFFFFF 'conm1 pusha x org snippet _con16p rdbytec x,ptra++ 'con16p rdbytec y,ptra++ movf x,y pusha x org snippet _con17p rdbytec x,ptra++ 'con17p rdbytec y,ptra++ movf x,y setb x,#16 pusha x org snippet _con16n rdbytec x,ptra++ 'con16n rdbytec y,ptra++ movf x,y xor x,hFFFFFFFF pusha x org snippet _con24 reps #3,#2 'con24p, con24n muxc x,#$FF rdbytec y,ptra++ movf x,y pusha x _con32 reps #4,#2 'con32 nop rdbytec y,ptra++ movf x,y pusha x org snippet _conexp rdbytec x,ptra++ 'conexp decod5 x wz, wc if_z sub x,#1 if_c not x pusha x ' ' ' Register read/write/assign ' org snippet _rdreg popa x 'read register movd :rd,x nop nop :rd pusha $000 org snippet _wrreg popa addr 'write register popa x call #writer org snippet _asreg popa addr 'assign register movs :rd,addr jmpd #assign_long mov assign_i,callwriter :rd mov x,$000 nop org snippet _rdregb call #bitfield 'read register bitfield popa x movs :rd,x jmpd #readb nop :rd mov x,$000 nop org snippet _wrregb call #bitfield 'write register bitfield popa addr movs :rd,addr jmpd #writeb mov writeb_i,callwriter :rd mov bval,$000 nop org snippet _asregb call #bitfield 'assign register bitfield popa addr movs :rd,addr jmpd #assignb_long mov writeb_i,callwriter :rd mov bval,$000 nop ' ' ' Local read/write/assign ' org snippet _rdloci popa y 'read local, indexed rdbytec x,ptra++ add x,y _rdloc add x,dbase 'read local, fixed setspb x popbr x pusha x org snippet _wrloci popa y 'write local, indexed rdbytec x,ptra++ add x,y _wrloc add x,dbase 'write local, fixed setspb x popa x pushb x org snippet _asloci popa y 'assign local, indexed rdbytec x,ptra++ add x,y _asloc jmpd #assign_local 'assign local, fixed add x,dbase setspb x popbr x org snippet _rdlocb call #bitfield 'read local bitfield popa x jmpd #readb add x,dbase setspb x popbr x org snippet _wrlocb call #bitfield 'write local bitfield popa x add x,dbase jmpd #writeb setspb x popbr bval mov writeb_i,pushbrx org snippet _aslocb call #bitfield 'assign local bitfield popa x add x,dbase jmpd #assignb_long setspb x popbr bval mov writeb_i,pushbrx ' ' ' Memory read/write/assign ' org snippet _rdbyte popa x 'read byte rdbyte x,x pusha x org snippet _rdword popa x 'read word rdword x,x pusha x org snippet _rdlong popa x 'read long rdlong x,x pusha x org snippet _wrbyte popa y 'write byte popa x wrbyte x,y org snippet _wrword popa y 'write word popa x wrword x,y org snippet _wrlong popa y 'write long popa x wrlong x,y org snippet _asbyte popa addr 'assign byte jmpd #assign rdbyte x,addr mov assign_i,:i mov mask,#$FF :i wrbyte x,addr org snippet _asword popa addr 'assign word jmpd #assign rdword x,addr mov assign_i,:i mov mask,:m :i wrword x,addr :m long $0000FFFF org snippet _aslong jmpd #assign_long 'assign long popa addr rdlong x,addr mov assign_i,:i :i wrlong x,addr org snippet _rdbyteb call #bitfield 'read byte bitfield popa x rdbyte x,x jmp #readb org snippet _rdwordb call #bitfield 'read word bitfield popa x rdword x,x jmp #readb org snippet _rdlongb call #bitfield 'read long bitfield popa x rdlong x,x jmp #readb org snippet _wrbyteb call #bitfield 'write byte bitfield jmpd #writeb popa addr rdbyte bval,addr mov writeb_i,:wr :wr wrbyte x,addr org snippet _wrwordb call #bitfield 'write word bitfield jmpd #writeb popa addr rdword bval,addr mov writeb_i,:wr :wr wrword x,addr org snippet _wrlongb call #bitfield 'write long bitfield jmpd #writeb popa addr rdlong bval,addr mov writeb_i,:wr :wr wrlong x,addr org snippet _asbyteb call #bitfield 'assign byte bitfield mov mask,#$FF jmpd #assignb popa addr rdbyte bval,addr mov writeb_i,:wr :wr wrbyte x,addr org snippet _aswordb call #bitfield 'assign word bitfield mov mask,:mask jmpd #assignb popa addr rdword bval,addr mov writeb_i,:wr :wr wrword x,addr :mask long $0000FFFF org snippet _aslongb call #bitfield 'assign long bitfield jmpd #assignb_long popa addr rdlong bval,addr mov writeb_i,:wr :wr wrlong x,addr ' ' ' Memory offsets and indexing ' org snippet _base call #xword if_nc add x,vbase 'vbase, c=0 if_c add x,pbase 'pbase, c=1 pusha x org snippet _index popa y 'ibyte, x=0 shl y,x 'iword, x=1 popa x 'ilong, x=2 add x,y pusha x ' ' ' Branch jmp/jz/jnz/tjz/djnz ' org snippet _jmp call #xword 'jmp addptra x org snippet _jxz popa y wz 'jz, c=1 jnz, c=0 call #xword if_z_eq_c addptra x org snippet _tjz popa y wz 'tjz if_nz pusha y call #xword if_z addptra x org snippet _djnz popa y 'djnz sub y,#1 wz if_nz pusha y call #xword if_nz addptra x ' ' ' Drop anchor ' ' \sub x = %00 ' \sub result x = %01 ' sub x = %10 ' sub result x = %11 ' org snippet _drop pusha dcall 'push dcall (later used for pcurr) getspa dcall 'set new dcall pusha dbase 'push return dbase pusha vbase 'push return vbase or x,pbase 'push return pbase w/flags pusha x pusha #0 'init 'result' to 0 ' ' ' Call ' ' obj.sub z=1, c=0 ' obj.sub[] z=1, c=1 ' obj[].sub z=0, c=0 ' obj[].sub[] z=0, c=1 ' sub c=0 ' sub[] c=1 ' ptr ' org snippet _callobj rdbytec x,ptra++ 'get obj byte if_nz popa a 'add any index if_nz add x,a jmpd #call_obj 'jump to handler, delayed rdbytec y,ptra++ 'get sub byte if_c popa a 'add any index if_c add y,a org snippet _callsub jmpd #call_sub 'jump to handler, delayed rdbytec y,ptra++ 'get sub byte if_c popa a 'add any index if_c add y,a org snippet _callptr popa x 'get sub [31..29]/[15..13], vbase [28..16], pbase [12..0] mov vbase,#0 'clear vbase/pbase mov pbase,#0 mov y,x 'get sub (6-bits) mov a,x shr y,#32-3-3 and y,#%111000 jmpd #call_ptr 'jump to handler, delayed shr a,#16-3 and a,#%000111 or y,a ' ' ' RETURN/ABORT ' ' RETURN z=1, c=0 ' ABORT z=1, c=1 ' RETURN value z=0, c=0 ' ABORT value z=0, c=1 ' org snippet _return if_z setspa dbase 'if no value, return result if_z popar x if_nz popa x 'if value, pop it :again setspa dbase 'set dbase popa pbase 'pop pbase if_c test pbase,#%10 wc 'if abort and try, return again if_c jmpd #:again popa vbase 'pop vbase popa dbase 'pop dbase popa y 'pop pcurr setptra y 'set ptra to pcurr test pbase,#%01 wc 'push result? andn pbase,#%11 if_c pusha x ' ' ' Get vbase/pbase ' org snippet _basesub mov y,vbase shl y,#16-4 mov x,pbase shr x,#4 or x,y pusha x ' ' ' Get pbase/vbase of obj ' ' obj c=0 ' obj[] c=1 ' org snippet _baseobj rdbytec x,ptra++ 'get obj byte if_c popa y 'handle index if_c add x,y shl x,#2 'scale offset add x,pbase 'get obj pbase/vbase offset rdlong x,x mov y,x 'get obj vbase shr y,#16-4 add y,vbase and y,h0001FFF0 shl y,#16-4 shl x,#4 'get obj pbase add x,pbase and x,h0001FFF0 shr x,#4 or x,y 'merge vbase/pbase pusha x 'push obj vbase/pbase ' ' ' Make subroutine ptr ' ' base.sub c=0 ' base.sub[] c=1 ' org snippet _subptr rdbytec a,ptra++ 'get sub number if_c popa b 'handle sub index if_c add a,b mov b,a 'split 6-bit index and b,#%111000 'top 3 bits into [31..29] shl b,#32-6 and a,#%000111 'bottom 3 bits into [15..13] shl a,#16-3 popa x 'pop base vbase/pbase or x,b 'install index into pbase/vbase or x,a pusha x 'push subroutine pointer ' ' ' Case ' org snippet 'case value _casev call #xword 'get branch address popa a 'pop value popa y 'pop target cmp a,y wz 'value = target? if_nz addspa #1 'if mismatch, unpop target if_z addptra x 'if match, branch org snippet 'case range (z=1) _caser call #xword 'get branch address popa b 'pop range end popa a 'pop range begin popa y 'pop target sub b,a '||(end - begin), c=1 if reverse range abs b,b wc sub y,a '+/-(target - begin) negc y,y cmp b,y wc 'match if ||(end - begin) => +/-(target - begin) if_c addspa #1 'if mismatch, unpop target if_nc addptra x 'if match, branch org snippet 'case done _casedone popa x 'pop target popa x 'pop address addptra x 'jump to address ' ' ' Lookup/lookdown ' org snippet 'lookup value _lookupv popa a 'pop value popa x 'pop index popa y 'pop target cmp x,y wz 'match if index = target if_nz addspa #1 'if no match, unpop target if_nz add x,#1 '..increment index if_nz pusha x '..push index if_z popa addr 'if match, pop address if_z pusha a '..push result if_z setptra addr '..branch org snippet 'lookup range _lookupr popa b 'pop range end popa a 'pop range begin popa x 'pop index popa y 'pop target sub b,a 'end - begin abs b,b wc '||(end - begin), c=1 if reverse range sub y,x 'target - index sumc a,y 'result = begin +/- (target - index) cmp b,y wc 'match if ||(end - begin) => (target - index) if_c addspa #1 'if no match, unpop target if_c addx x,b '..add ||(end - begin) + 1 to index if_c pusha x '..push index if_nc popa addr 'if match, pop address if_nc pusha a '..push result if_nc setptra addr '..branch org snippet 'lookdown value _lookdnv popa a 'pop value popa x 'pop index popa y 'pop target cmp a,y wz 'match if value = target if_nz addspa #1 'if no match, unpop target if_nz add x,#1 '..increment index if_nz pusha x '..push index if_z popa addr 'if match, pop address if_z pusha x '..push result if_z setptra addr '..branch org snippet 'lookdown range _lookdnr popa b 'pop range end popa a 'pop range begin popa x 'pop index popa y 'pop target sub b,a '||(end - begin), c=1 if reverse range abs b,b wc sub y,a '+/-(target - begin) negc y,y cmp b,y wc 'match if ||(end - begin) => +/-(target - begin) if_c addspa #1 'if no match, unpop target if_c addx x,b '..add ||(end - begin) + 1 to index if_c pusha x '..push index if_nc popa addr 'if match, pop address if_nc add x,y '..result = index +/- (target - begin) if_nc pusha x '..push result if_nc setptra addr '..branch org snippet 'lookup/lookdown done _lookdone subspa #3 'pop index/target/address pusha #0 'push 0 result ' ' ' Miscellaneous ' org snippet _pop rdbytec x,ptra++ 'pop subspa x org snippet _clkset popa x 'clkset clkset x org snippet _cogid cogid x 'cogid pusha x org snippet _coginit popa y 'coginit popa x popa a setcog a coginit x,y wc if_nz_and_c pusha #0 if_nz_and_nc pusha hFFFFFFFF org snippet _cogstop popa x 'cogstop cogstop x
This interpreter is for the built-in 17-bit address space (128KB), but can easily be changed to 32-bit XMM. I started out on the 32-bit addressing path, but figured it was more practical, at first, to make a native 17-bit version, as an external SDRAM can easily be managed by Spin code for huge data.
This interpreter leaves the first $150+ longs in the cog free for in-line assembly code and terminate-stay-resident type applications which can run concurrently with the interpreter via hardware multi-tasking.
In the new Spin, all variables are bit-range addressable for read/write/read-modify-write operations. Bit ranges can be high..low or low..high. This is mainly important for I/O registers which relate to physical pins, but it makes bit fields within other types (locals, hub ram, cog RAM registers) easy to manipulate, as well.
This interpreter works by getting a byte code, looking up a descriptor long, loading a snippet of assembly code, and executing it. The interpreter currently lacks initialization code, which will be written last, but it has all the snippets for math operations, calls, branches, lookup/lookdown, cog starting and stopping, and housekeeping. It's about 4.5KB now. Once I get the compiler working on the PC side, I'll augment the interpreter to include special I/O handling and other functions that are not needed at first, but make it complete.
Why You don't use that sequence in this place
orgh base
org $0
orgF $15B
That give even correct place with loading to COG.
I will do something like that. I'm just not there yet.
Thanks for replay.
I have posted in PNut thread one dumb question to You.
Have You read that?
Link to question
http://forums.parallax.com/showthread.php/148611-New-PNUT.EXE-loads-all-128KB-of-Hub-RAM?p=1190665&viewfull=1#post1190665
Thanks Chip for the very interesting code.
A lot to study, but one thing caught my eye immediatly: You use a lot of delayed jumps/calls/returns. All with 3 delay slots. The problem is: if you do hardware multi tasking the number of the delay slots depends on the number of tasks and the task-scheduler settings.
So if the assembly code installs hardware tasks, the interpreter will no longer work. The only reliable solution for code that should work with and without tasks is to avoid delayed instructions. Unfortunatly this will make the interpreter a bit slower.
Andy
Some of the snippets (the short ones) would be faster implemented as LMM but of course that can come later.
I noticed that you don't have the return from the snippet coded within each snippet, nor a way to determine its length, so do you plan to make the compiler add this? Some form of a macro expansion would be nice for this.
The description table holds the length of the snippets in the lower 7 bits and the overlay loader always adds a jump back at the end of the loaded instructions.
Andy
Good observation, Ariba! I guess I was on the road to "finding out" there was a problem. I'll have to get rid of all delayed jumps, as you've pointed out.
There is another more insidious problem that I've been thinking about: read-modify-writes to PINx and DIRx registers in Spin will conflict with concurrent multi-tasking PASM code doing atomic operations on PINx/DIRx. The only way around this is to limit Spin operations on PINx/DIRx to atomic operations like concurrent PASM code is likely to do. It makes affecting a bit field within those registers kind of impossible, unless your desire is to simply set or clear some bits. If we revise the Verilog, I'll make some atomic masked-write instructions that could get around this problem. For now, it's a problem. Even multi-threading can't get around this, as several Spin instructions might perform a r-m-w process on PINx/DIRx.
With an XOR instruction it should be possible to change a field of bits to any state you wish with an atomic instruction:.
Example:
outa[9..3] := $55 mov bits,#$55 mov mask,#%1111111 shl bits,#3 shl mask,#3 mov tmp,outa xor tmp,bits and tmp,mask xor outa,tmp 'atomic modify
As long as the concurrent PASM code does not change bits 3..9 of outa this should work.Andy
Wow!!! That's a great idea. As long as the Spin code and concurrent PASM code don't mess with each other's pins, there would be no conflict. Problem solved. And no need for new instructions!
Thanks for thinking about this, Andy.
I'll have to make shadow registers for not just PINx, but DIRx, as well.
I especially like the 150 long fcache area, that is going to be extremely useful.
I think perhaps there should be two versions of the interpreter:
1) supports tasks, does not use delayed instructions
2) does not support tasks, but uses delayed instructions
The second version should probably come well after (1) is fully functional and debugged
Looking forward to the new PNut with Spin support!
Sorry for the news on the first run. 8 weeks will go by quick. I'm very eager to play with the new chip when the time arrives.
Good luck!!!!!
-Parsko
If this new chip works, we'll be able to make 100k more units from the same mask set, so there won't be much delay for actual chips.
That sounds like you decided not to go with the shuttle run and share a mask with other designs?
The foundry we are using offers multi-layer reticles, not just single-layer. This means that a mask will have images for more than one process step. It's not ideal for mass production because they expose only half the area (or 1/3 or 1/4, etc.) at a time that a single-layer reticle would.