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 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.
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 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.
....
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
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: 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.