Since the operators are pretty much nailed down, I was able to code them up, along with their EXECF tables for use with the fast bytecode executor (XBYTE). I've got the random memory R/W, the constants, and the unary and binary operators in there, and I've used a little over 1/4th of the cog's total memory. That's good, because I think I have about half the interpreter written now. At least, all the big stuff is done. Next comes all the housekeeping details.
Here it is, so far. It doesn't run, yet, but contains the major sections so I can assemble it and check the size:
'
'
' Bytecode lookup constants
'
CON offset_byte = %110 << 10 'SKIPF patterns for mem_rw
offset_word = %101 << 10
offset_long = %011 << 10
base_pbase = %110 << 13
base_vbase = %101 << 13
base_dbase = %011 << 13
read_byte = %0000_0110_1111 << 16
read_byte_indx = %0000_0110_0110 << 16
read_word = %0000_0101_1111 << 16
read_word_indx = %0000_0101_0100 << 16
read_long = %0000_0011_1111 << 16
read_long_indx = %0000_0011_0010 << 16
write_byte = %0000_1111_1111 << 16
write_byte_indx = %0000_1111_0110 << 16
write_word = %0010_1111_1111 << 16
write_word_indx = %0010_1111_0100 << 16
write_long = %0110_1111_1111 << 16
write_long_indx = %0110_1111_0010 << 16
DAT org
'
'
' Memory read/write
'
mem_rw rfbyte m 'ob | | offset
rfword m '| ow |
rflong m '| | ol
add m,pbase 'bp | | base
add m,vbase '| bv |
add m,dbase '| | bd
popa y '| ib iw il index
shl y,#1 '| | iw |
shl y,#2 '| | | il
add m,y '| ib iw il
rdbyte y,m 'rb | | read
rdword y,m '| rw |
rdlong y,m '| | rl
_ret_ pusha y 'rb rw rl
popa y 'wb ww wl write
_ret_ wrbyte y,m 'wb | |
_ret_ wrword y,m ' ww |
_ret_ wrlong y,m ' wl
'
'
' Constants
'
con_low pusha x 'push a b c d e f g a: 0
_ret_ mov x,#0 ' a | | | | | | b: 1
_ret_ mov x,#1 ' b | | | | | c: 2
_ret_ mov x,#2 ' c | | | | d: 3
_ret_ mov x,#3 ' d | | | e: 4
_ret_ mov x,#4 ' e | | f: 5
_ret_ mov x,#5 ' f | g: 6
_ret_ mov x,#6 ' g
con_high pusha x 'push a b c d e f g a: 7
_ret_ mov x,#7 ' a | | | | | | b: 8
_ret_ mov x,#8 ' b | | | | | c: 15
_ret_ mov x,#15 ' c | | | | d: 16
_ret_ mov x,#16 ' d | | | e: 31
_ret_ mov x,#31 ' e | | f: 32
_ret_ mov x,#32 ' f | g: -1
_ret_ mov x,_FFFFFFFF ' g
con_data pusha x 'push a b c d e f g h i a: byte
_ret_ rfbyte x ' a | | | | | | | | b: !byte
rfbyte x ' b | | | f g h i c: word
_ret_ rfword x ' | c | | | | | | d: !word
rfword x ' | d | | | | | e: long
_ret_ rflong x ' | | e | | | | f: byte + decode
_ret_ decod x ' | | f | | | g: byte + decode + not
decod x ' | | g h i h: byte + decode + decrement
_ret_ not x ' b d g | | i: byte + decode + negate
_ret_ sub x,#1 ' h |
_ret_ neg x ' i
'
'
' Math operators
'
op_notb test x wz 'NOT
_ret_ muxz x,_FFFFFFFF
op_not _ret_ not x '!
op_neg _ret_ neg x '-
op_abs _ret_ abs x 'ABS
op_ncod _ret_ topone x 'NCOD
op_dcod _ret_ decod x 'DCOD
op_sqrt qsqrt x,#0 ' a a: SQRT
op_log2 qlog x ' | b b: LOG2
op_exp2 qexp x ' | | c c: EXP2
_ret_ getqx x ' a b c
op_shift mov y,x 'swap a b c d e f a: >>
popa x 'pop a b c d e f b: <<
_ret_ shr x,y ' a | | | | | c: SAR
_ret_ shl x,y ' b | | | | d: ROR
_ret_ sar x,y ' c | | | e: ROL
_ret_ ror x,y ' d | | f: REV
_ret_ rol x,y ' e |
rev x ' f
rol x,y ' f
rol x,#1 ' f
_ret_ triml x,y ' f
op_logic popa y wz 'pop a b c d e f a: AND
muxnz y,_FFFFFFFF ' a b c | | | b: XOR
test x wz ' a b c | | | c: OR
muxnz x,_FFFFFFFF ' a b c | | | d: &
_ret_ and x,y ' a | | d | | e: ^
_ret_ xor x,y ' b | e | f: |
_ret_ or x,y ' c f
op_muldiv popa y wc 'pop a b c d e a: *
testb x,#31 wz 'c=ys a b c | | b: /
abs y '!z=xs a b c | | c: MOD
abs x ' a b c | | d: SCAL
qmul y,x ' a | | d | e: FRAC
qdiv y,x ' | b c | |
qfrac y,x ' | | | | e
getqx x ' a b | | e
if_c_eq_z neg x ' a b | | |
getqy x ' | | c d |
if_c neg x ' | | c | |
ret ' a b c d e
op_addsub mov y,x 'swap a b c d e a: +
popa x 'pop a b c d e b: -
_ret_ add x,y ' a | | | | c: #>
_ret_ sub x,y ' b | | | d: <#
_ret_ mins x,y ' c | | e: SIGNX
_ret_ maxs x,y ' d |
not y ' e
shl x,y ' e
_ret_ sar x,y ' e
op_equal popa y 'pop a b c d e f a: <
cmps y,x wc,wz ' a | c d e | b: <=
cmps x,y wc,wz ' | b | | | f c: ==
_ret_ muxc x,_FFFFFFFF ' a | | | | f d: <>
_ret_ muxnc x,_FFFFFFFF ' b | | e e: >=
_ret_ muxz x,_FFFFFFFF ' c | f: >
_ret_ muxnz x,_FFFFFFFF ' d
'
'
' Data
'
_FFFFFFFF long $FFFFFFFF
x res 1
y res 1
m res 1
pbase res 1
vbase res 1
dbase res 1
'
'
' Bytecode lookup table
'
org $200 'lut space
table
long mem_rw |offset_byte|base_pbase|read_byte
long mem_rw |offset_word|base_pbase|read_byte
long mem_rw |offset_long|base_pbase|read_byte
long mem_rw |offset_byte|base_vbase|read_byte
long mem_rw |offset_word|base_vbase|read_byte
long mem_rw |offset_long|base_vbase|read_byte
long mem_rw |offset_byte|base_dbase|read_byte
long mem_rw |offset_word|base_dbase|read_byte
long mem_rw |offset_long|base_dbase|read_byte
long mem_rw |offset_byte|base_pbase|read_byte_indx
long mem_rw |offset_word|base_pbase|read_byte_indx
long mem_rw |offset_long|base_pbase|read_byte_indx
long mem_rw |offset_byte|base_vbase|read_byte_indx
long mem_rw |offset_word|base_vbase|read_byte_indx
long mem_rw |offset_long|base_vbase|read_byte_indx
long mem_rw |offset_byte|base_dbase|read_byte_indx
long mem_rw |offset_word|base_dbase|read_byte_indx
long mem_rw |offset_long|base_dbase|read_byte_indx
long mem_rw |offset_byte|base_pbase|read_word
long mem_rw |offset_word|base_pbase|read_word
long mem_rw |offset_long|base_pbase|read_word
long mem_rw |offset_byte|base_vbase|read_word
long mem_rw |offset_word|base_vbase|read_word
long mem_rw |offset_long|base_vbase|read_word
long mem_rw |offset_byte|base_dbase|read_word
long mem_rw |offset_word|base_dbase|read_word
long mem_rw |offset_long|base_dbase|read_word
long mem_rw |offset_byte|base_pbase|read_word_indx
long mem_rw |offset_word|base_pbase|read_word_indx
long mem_rw |offset_long|base_pbase|read_word_indx
long mem_rw |offset_byte|base_vbase|read_word_indx
long mem_rw |offset_word|base_vbase|read_word_indx
long mem_rw |offset_long|base_vbase|read_word_indx
long mem_rw |offset_byte|base_dbase|read_word_indx
long mem_rw |offset_word|base_dbase|read_word_indx
long mem_rw |offset_long|base_dbase|read_word_indx
long mem_rw |offset_byte|base_pbase|read_long
long mem_rw |offset_word|base_pbase|read_long
long mem_rw |offset_long|base_pbase|read_long
long mem_rw |offset_byte|base_vbase|read_long
long mem_rw |offset_word|base_vbase|read_long
long mem_rw |offset_long|base_vbase|read_long
long mem_rw |offset_byte|base_dbase|read_long
long mem_rw |offset_word|base_dbase|read_long
long mem_rw |offset_long|base_dbase|read_long
long mem_rw |offset_byte|base_pbase|read_long_indx
long mem_rw |offset_word|base_pbase|read_long_indx
long mem_rw |offset_long|base_pbase|read_long_indx
long mem_rw |offset_byte|base_vbase|read_long_indx
long mem_rw |offset_word|base_vbase|read_long_indx
long mem_rw |offset_long|base_vbase|read_long_indx
long mem_rw |offset_byte|base_dbase|read_long_indx
long mem_rw |offset_word|base_dbase|read_long_indx
long mem_rw |offset_long|base_dbase|read_long_indx
long mem_rw |offset_byte|base_pbase|write_byte
long mem_rw |offset_word|base_pbase|write_byte
long mem_rw |offset_long|base_pbase|write_byte
long mem_rw |offset_byte|base_vbase|write_byte
long mem_rw |offset_word|base_vbase|write_byte
long mem_rw |offset_long|base_vbase|write_byte
long mem_rw |offset_byte|base_dbase|write_byte
long mem_rw |offset_word|base_dbase|write_byte
long mem_rw |offset_long|base_dbase|write_byte
long mem_rw |offset_byte|base_pbase|write_byte_indx
long mem_rw |offset_word|base_pbase|write_byte_indx
long mem_rw |offset_long|base_pbase|write_byte_indx
long mem_rw |offset_byte|base_vbase|write_byte_indx
long mem_rw |offset_word|base_vbase|write_byte_indx
long mem_rw |offset_long|base_vbase|write_byte_indx
long mem_rw |offset_byte|base_dbase|write_byte_indx
long mem_rw |offset_word|base_dbase|write_byte_indx
long mem_rw |offset_long|base_dbase|write_byte_indx
long mem_rw |offset_byte|base_pbase|write_word
long mem_rw |offset_word|base_pbase|write_word
long mem_rw |offset_long|base_pbase|write_word
long mem_rw |offset_byte|base_vbase|write_word
long mem_rw |offset_word|base_vbase|write_word
long mem_rw |offset_long|base_vbase|write_word
long mem_rw |offset_byte|base_dbase|write_word
long mem_rw |offset_word|base_dbase|write_word
long mem_rw |offset_long|base_dbase|write_word
long mem_rw |offset_byte|base_pbase|write_word_indx
long mem_rw |offset_word|base_pbase|write_word_indx
long mem_rw |offset_long|base_pbase|write_word_indx
long mem_rw |offset_byte|base_vbase|write_word_indx
long mem_rw |offset_word|base_vbase|write_word_indx
long mem_rw |offset_long|base_vbase|write_word_indx
long mem_rw |offset_byte|base_dbase|write_word_indx
long mem_rw |offset_word|base_dbase|write_word_indx
long mem_rw |offset_long|base_dbase|write_word_indx
long mem_rw |offset_byte|base_pbase|write_long
long mem_rw |offset_word|base_pbase|write_long
long mem_rw |offset_long|base_pbase|write_long
long mem_rw |offset_byte|base_vbase|write_long
long mem_rw |offset_word|base_vbase|write_long
long mem_rw |offset_long|base_vbase|write_long
long mem_rw |offset_byte|base_dbase|write_long
long mem_rw |offset_word|base_dbase|write_long
long mem_rw |offset_long|base_dbase|write_long
long mem_rw |offset_byte|base_pbase|write_long_indx
long mem_rw |offset_word|base_pbase|write_long_indx
long mem_rw |offset_long|base_pbase|write_long_indx
long mem_rw |offset_byte|base_vbase|write_long_indx
long mem_rw |offset_word|base_vbase|write_long_indx
long mem_rw |offset_long|base_vbase|write_long_indx
long mem_rw |offset_byte|base_dbase|write_long_indx
long mem_rw |offset_word|base_dbase|write_long_indx
long mem_rw |offset_long|base_dbase|write_long_indx
long con_low | %00 << 10 'constant 0
long con_low | %010 << 10 'constant 1
long con_low | %0110 << 10 'constant 2
long con_low | %01110 << 10 'constant 3
long con_low | %011110 << 10 'constant 4
long con_low | %0111110 << 10 'constant 5
long con_low | %01111110 << 10 'constant 6
long con_high | %00 << 10 'constant 7
long con_high | %010 << 10 'constant 8
long con_high | %0110 << 10 'constant 15
long con_high | %01110 << 10 'constant 16
long con_high | %011110 << 10 'constant 31
long con_high | %0111110 << 10 'constant 32
long con_high | %01111110 << 10 'constant -1
long con_data | %00 << 10 'constant byte
long con_data | %011111010 << 10 'constant byte!
long con_data | %0110 << 10 'constant word
long con_data | %011101110 << 10 'constant word!
long con_data | %011110 << 10 'constant long
long con_data | %0111010 << 10 'constant byte+decode
long con_data | %001111010 << 10 'constant byte+decode+not
long con_data | %0101111010 << 10 'constant byte+decode+dec
long con_data | %01101111010 << 10 'constant byte+decode+neg
long op_notb 'operator unary NOT
long op_not 'operator unary !
long op_neg 'operator unary -
long op_abs 'operator unary ABS
long op_ncod 'operator unary NCOD
long op_dcod 'operator unary DCOD
long op_sqrt | %0110 << 10 'operator unary SQRT
long op_log2 | %010 << 10 'operator unary LOG2
long op_exp2 | %00 << 10 'operator unary EXP2
long op_shift | %000 << 10 'operator binary >>
long op_shift | %0100 << 10 'operator binary <<
long op_shift | %01100 << 10 'operator binary SAR
long op_shift | %011100 << 10 'operator binary ROR
long op_shift | %0111100 << 10 'operator binary ROL
long op_shift | %00001111100 << 10 'operator binary REV
long op_addsub | %000111100 << 10 'operator binary SIGNX
long op_logic | %00000 << 10 'operator binary AND
long op_logic | %010000 << 10 'operator binary XOR
long op_logic | %0110000 << 10 'operator binary OR
long op_logic | %01110 << 10 'operator binary &
long op_logic | %011110 << 10 'operator binary ^
long op_logic | %0111110 << 10 'operator binary |
long op_muldiv | %011001100000 << 10 'operator binary *
long op_muldiv | %011001010000 << 10 'operator binary /
long op_muldiv | %000111010000 << 10 'operator binary MOD
long op_muldiv | %010111101110 << 10 'operator binary SCAL
long op_muldiv | %011100111110 << 10 'operator binary FRAC
long op_addsub | %000 << 10 'operator binary +
long op_addsub | %0100 << 10 'operator binary -
long op_addsub | %01100 << 10 'operator binary #>
long op_addsub | %011100 << 10 'operator binary <#
long op_equal | %0100 << 10 'operator binary <
long op_equal | %01010 << 10 'operator binary <=
long op_equal | %011100 << 10 'operator binary ==
long op_equal | %0111100 << 10 'operator binary <>
long op_equal | %01100 << 10 'operator binary >=
long op_equal | %0010 << 10 'operator binary >
Tomorrow, I'll add the XBYTE stuff in and execute some bytecodes on I/O pins to see how the speed compares to Prop1. With this new setup of XBYTE, which includes EXECF, there's about zero clock cycles wasted on anything. It's all business. I'm anxious to see what it does.
Tomorrow, I'll add the XBYTE stuff in and execute some bytecodes on I/O pins to see how the speed compares to Prop1. With this new setup of XBYTE, which includes EXECF, there's about zero clock cycles wasted on anything. It's all business. I'm anxious to see what it does.
Tomorrow, I'll add the XBYTE stuff in and execute some bytecodes on I/O pins to see how the speed compares to Prop1. With this new setup of XBYTE, which includes EXECF, there's about zero clock cycles wasted on anything. It's all business. I'm anxious to see what it does.
Since the operators are pretty much nailed down, I was able to code them up, along with their EXECF tables for use with the fast bytecode executor (XBYTE). I've got the random memory R/W, the constants, and the unary and binary operators in there, and I've used a little over 1/4th of the cog's total memory. That's good, because I think I have about half the interpreter written now. At least, all the big stuff is done. Next comes all the housekeeping details.
If this comes in compact, is there room to add
? Scaled operator, that does (32b*32b/32b), with a 64b intermediate result, and maybe returns remainder too.
? Boolean Types, as the P2 now has bit-level instructions ?
? Floating point
Since the operators are pretty much nailed down, I was able to code them up, along with their EXECF tables for use with the fast bytecode executor (XBYTE). I've got the random memory R/W, the constants, and the unary and binary operators in there, and I've used a little over 1/4th of the cog's total memory. That's good, because I think I have about half the interpreter written now. At least, all the big stuff is done. Next comes all the housekeeping details.
If this comes in compact, is there room to add
? Scaled operator, that does (32b*32b/32b), with a 64b intermediate result, and maybe returns remainder too.
? Boolean Types, as the P2 now has bit-level instructions ?
? Floating point
The floating point is the only thing that would take much code to realize. Adding types, though, would complicate the language quite a bit.
Since the operators are pretty much nailed down, I was able to code them up, along with their EXECF tables for use with the fast bytecode executor (XBYTE). I've got the random memory R/W, the constants, and the unary and binary operators in there, and I've used a little over 1/4th of the cog's total memory. That's good, because I think I have about half the interpreter written now. At least, all the big stuff is done. Next comes all the housekeeping details.
If this comes in compact, is there room to add
? Scaled operator, that does (32b*32b/32b), with a 64b intermediate result, and maybe returns remainder too.
? Boolean Types, as the P2 now has bit-level instructions ?
? Floating point
The floating point is the only thing that would take much code to realize. Adding types, though, would complicate the language quite a bit.
I think that floating point should have a built-in support. Perhaps the routines can execute from LUT or hubexec if there is no space in the cog memory. Perhaps the compiler could add the code only if used in the hub.
But it would be nice to avoid the syntax that is now forced by the float32 object in favour of clean expressions used with integers.
Since the operators are pretty much nailed down, I was able to code them up, along with their EXECF tables for use with the fast bytecode executor (XBYTE). I've got the random memory R/W, the constants, and the unary and binary operators in there, and I've used a little over 1/4th of the cog's total memory. That's good, because I think I have about half the interpreter written now. At least, all the big stuff is done. Next comes all the housekeeping details.
If this comes in compact, is there room to add
? Scaled operator, that does (32b*32b/32b), with a 64b intermediate result, and maybe returns remainder too.
? Boolean Types, as the P2 now has bit-level instructions ?
? Floating point
The floating point is the only thing that would take much code to realize. Adding types, though, would complicate the language quite a bit.
I think that floating point should have a built-in support. Perhaps the routines can execute from LUT or hubexec if there is no space in the cog memory. Perhaps the compiler could add the code only if used in the hub.
But it would be nice to avoid the syntax that is now forced by the float32 object in favour of clean expressions used with integers.
I agree. This will take some thought, since we don't yet have variable types beyond byte/word/long/register.
As a start point you could introduce a FLOAT or REAL type but I think it is enough to just introduce a few more operators/bytecodes:
*R x *R y x *R= y binary 7, 16 Real Multiply
/R x /R y x /R= y binary 7, 16 Real Divide
+R x +R y x +R= y binary 8, 16 Add
-R x -R y x -R= y binary 8, 16 Subtract
If you have dedicated math operators for floating numbers than you do not need to identify variable types, the operator will expect the right type
And a few conversion functions more:
ITR Integer To Real
RTI Real to Integer
As a start point you could introduce a FLOAT or REAL type but I think it is enough to just introduce a few more operators/bytecodes:
*R x *R y x *R= y binary 7, 16 Real Multiply
/R x /R y x /R= y binary 7, 16 Real Divide
+R x +R y x +R= y binary 8, 16 Add
-R x -R y x -R= y binary 8, 16 Subtract
If you have dedicated math operators for floating numbers than you do not need to identify variable types, the operator will expect the right type
And a few conversion functions more:
ITR Integer To Real
RTI Real to Integer
Yes! That's way simpler, for sure. Good thinking! That eliminates all the contextual issues. Wow!
Worth mentioning that only the compiler itself is required to know types, and you could set the syntax up such that leaving out the type implies an integer, so it'd still be somewhat noob friendly. It does complicate the implementation, but the resulting code would be FAR easier to read than having R's littered all over your equations.
We would have to have R operators for the following, at least:
==r
<>r
>=r
<=r
>r
<r
*r
/r
%r
+r
-r
maybe a dot, instead of an R:
==.
<>.
>=.
<=.
>.
<.
*.
/.
%.
+.
-.
That doesn't stand out too much, almost gets lost, but is easier to read. I thought about putting the dot on the front, but that would cause parsing problems.
Worth mentioning that only the compiler itself is required to know types, and you could set the syntax up such that leaving out the type implies an integer, so it'd still be somewhat noob friendly. It does complicate the implementation, but the resulting code would be FAR easier to read than having R's littered all over your equations.
I agree, R's is a total kludge.
If there is a lot of work for Reals, this could be shifted to when P2 is in the FAB flows.
There is enough test coverage in P2 Spin already to be useful.
C/C++ for P2 should also be functional before P2 final signoff.
Having r's in there is also going to pooch the parser. It won't be legal any more to use if x>=result, for example, because that could parse to >=r esult, or >= result. There's a reason most operators don't use any legal label character. That said, I agree with JMG - this is the kind of thing that can be added later and it won't affect silicon. Get V1.0 out the door and then start complicating it.
@Chip
%(MOD) is not needed because the result of float division is a floating number. the result will eventually be converted to integer and the fractional part be lost.
BTW: yes, i've forgot the equity operators, these also needs R
PS: R is clearer than dot
@All
The idea of R comes from PLCs where floating point math is supported but operands cannot be mixed, they must be of the same type and the type is determined by the operator
L 1.0e1 //real
L 5.0e0 //real
+R
T destination //real (1.5e1)
L 10 //integer
ITR // conversion
L 5.0e0 //real
+R
T destination //real (1.5e1)
L 10 //integer
ITR //conversion
L 5.0e0 //real
+R
RTI //conversion
T destination //integer (15)
1. I still prefer the R operators rather than the actual float32 object syntax
2. I will still prefer R if the "autodetection" means variable type declaration (I am not against it) which complicates the interpreter and forces the move of floating point and other routines to hubexec rather than cogexec which will increase execution times.
Perhaps CORDIC engine can be used, I've read something about doing float-math with CORDIC with +/- 1/16777216 precision.
Ugh, I hate the idea of another set of operators with the R or dot tagged on for float operations.
I think it's cleaner and probably easier in the long run to just add the FLOAT var type.
The issue then becomes locals and params (which currently are always LONGs) would need to be able to have type tags (which we have already talked about wanting/needing for structs). I think that's easier that this operator junk (so gross).
How hard would it be to declare a block of variables as "real" and let the compiler handle the choice of operator while we use the standard math symbols in the source. Something like:
[code]
declare real
var1
var2
var3
.
.
.
var3 := var1 + var2
How hard would it be to declare a block of variables as "real" and let the compiler handle the choice of operator while we use the standard math symbols in the source.
That is certainly possible, as other Compilers can do that, however Chip said above P2Spin supports just 4 types now :
"This will take some thought, since we don't yet have variable types beyond byte/word/long/register."
So far I have not needed floats with the Propeller but that may be due to the type and small number of projects I have done, so I am more or less neutral to the idea. I do think that not having floats in Spin while they are available in C will be a disincentive for anyone not already familiar with Spin to learn it.
The 0.001% left don't understand that they don't need floats.
There are some rare people working with kalman filters or quaternions that probably do need floats, and know how they work.
I don't know. Either you have to add types to Spin. Which makes the whole language a lot more complex. Or you have to add weird float operators, which is an ugly kludge.
Spent about 45 minutes on this, writing some stuff, gave up.
Spin is too tied to the actual assembly instructions to do anything abstract like floating point.
To deal with floats, the spin interpreter would need a context switch to something like a 64-bit accumulator and only have a small subset of the operators be legal (++, --, +-*/, ABS, negate(-), etc.) but definitely no rotation, and no left and right shifts unless it was by 10's which would be awesomely bizarre.
The reason you'd want a 64-bit float accumulator is because it could hold an exact copy of every value of a 32-bit long signed integer, which is what would be converted back when going from float->long. To convert to an unsigned long would require a specific type coercion operator.
The reason you'd want a 64-bit float accumulator is because it could hold an exact copy of every value of a 32-bit long signed integer, which is what would be converted back when going from float->long. To convert to an unsigned long would require a specific type coercion operator.
I'm not sure where you are going with that but that is just what Javascript does. In JS all numbers are 64 bit floats, but it knows how to handle them as 32 bit ints.
Operators like "+", "-", "*", "/", etc work as if the numbers were floats.
Bitwise operators treat the numbers as 32 bit ints.
It's kind of weird but it has the magical result that you can compile C code to Javascript and have it run pretty damn quick.
Comments
AUGS can be used to either provide a 20-bit constant address, or invoke PTRA/PTRB with a 20-bit unscaled index:
I'm recompiling now. It's going to take 8 hours to get all the FPGA images done, with a lot of interstitial monkey motion.
I think the other thing that we need to nail down is how to interoperate between bytecodes and PASM. But I'll start a new thread for that.
Eric
Here it is, so far. It doesn't run, yet, but contains the major sections so I can assemble it and check the size:
Tomorrow, I'll add the XBYTE stuff in and execute some bytecodes on I/O pins to see how the speed compares to Prop1. With this new setup of XBYTE, which includes EXECF, there's about zero clock cycles wasted on anything. It's all business. I'm anxious to see what it does.
https://forums.parallax.com/discussion/comment/1407770/#Comment_1407770
Those are Prop1 numbers, of course. And I think a more comprehensive benchmark thread is:
http://forums.parallax.com/discussion/142803/some-multi-language-benchmarks/p1
? Scaled operator, that does (32b*32b/32b), with a 64b intermediate result, and maybe returns remainder too.
? Boolean Types, as the P2 now has bit-level instructions ?
? Floating point
The floating point is the only thing that would take much code to realize. Adding types, though, would complicate the language quite a bit.
I think that floating point should have a built-in support. Perhaps the routines can execute from LUT or hubexec if there is no space in the cog memory. Perhaps the compiler could add the code only if used in the hub.
But it would be nice to avoid the syntax that is now forced by the float32 object in favour of clean expressions used with integers.
I agree. This will take some thought, since we don't yet have variable types beyond byte/word/long/register.
And a few conversion functions more:
ITR Integer To Real
RTI Real to Integer
Yes! That's way simpler, for sure. Good thinking! That eliminates all the contextual issues. Wow!
==r
<>r
>=r
<=r
>r
<r
*r
/r
%r
+r
-r
maybe a dot, instead of an R:
==.
<>.
>=.
<=.
>.
<.
*.
/.
%.
+.
-.
That doesn't stand out too much, almost gets lost, but is easier to read. I thought about putting the dot on the front, but that would cause parsing problems.
Well, perhaps, but it screams kludge... and the exercise is to try to clean up Spin, not add ever-more-strange-operators...
Worse, if someone does use the wrong type, a system that has no type checking, gives no error message.
The risk of short term workarounds, is they tend to become entrenched and never get around to being properly fixed.
I agree, R's is a total kludge.
If there is a lot of work for Reals, this could be shifted to when P2 is in the FAB flows.
There is enough test coverage in P2 Spin already to be useful.
C/C++ for P2 should also be functional before P2 final signoff.
%(MOD) is not needed because the result of float division is a floating number. the result will eventually be converted to integer and the fractional part be lost.
BTW: yes, i've forgot the equity operators, these also needs R
PS: R is clearer than dot
@All
The idea of R comes from PLCs where floating point math is supported but operands cannot be mixed, they must be of the same type and the type is determined by the operator
1. I still prefer the R operators rather than the actual float32 object syntax
2. I will still prefer R if the "autodetection" means variable type declaration (I am not against it) which complicates the interpreter and forces the move of floating point and other routines to hubexec rather than cogexec which will increase execution times.
Perhaps CORDIC engine can be used, I've read something about doing float-math with CORDIC with +/- 1/16777216 precision.
I think it's cleaner and probably easier in the long run to just add the FLOAT var type.
The issue then becomes locals and params (which currently are always LONGs) would need to be able to have type tags (which we have already talked about wanting/needing for structs). I think that's easier that this operator junk (so gross).
[code]
declare real
var1
var2
var3
.
.
.
var3 := var1 + var2
"This will take some thought, since we don't yet have variable types beyond byte/word/long/register."
So far I have not needed floats with the Propeller but that may be due to the type and small number of projects I have done, so I am more or less neutral to the idea. I do think that not having floats in Spin while they are available in C will be a disincentive for anyone not already familiar with Spin to learn it.
The 0.001% left don't understand that they don't need floats.
There are some rare people working with kalman filters or quaternions that probably do need floats, and know how they work.
I don't know. Either you have to add types to Spin. Which makes the whole language a lot more complex. Or you have to add weird float operators, which is an ugly kludge.
Spin is too tied to the actual assembly instructions to do anything abstract like floating point.
To deal with floats, the spin interpreter would need a context switch to something like a 64-bit accumulator and only have a small subset of the operators be legal (++, --, +-*/, ABS, negate(-), etc.) but definitely no rotation, and no left and right shifts unless it was by 10's which would be awesomely bizarre.
The reason you'd want a 64-bit float accumulator is because it could hold an exact copy of every value of a 32-bit long signed integer, which is what would be converted back when going from float->long. To convert to an unsigned long would require a specific type coercion operator.
Operators like "+", "-", "*", "/", etc work as if the numbers were floats.
Bitwise operators treat the numbers as 32 bit ints.
It's kind of weird but it has the magical result that you can compile C code to Javascript and have it run pretty damn quick.
Or, let's keep this SPIN simple and lean. It can be the native tool at some point.
Extend later.
I'm not sure about the "extend later" part. I can't see how it's possible without turning Spin into a pigs ear like C++.
But, my vision is limited.
Lots of users ready for that.
And I think they deserve that SPIN too. Should exist.