Shop OBEX P1 Docs P2 Docs Learn Events
Fast Bytecode Interpreter - Page 19 — Parallax Forums

Fast Bytecode Interpreter

1161719212230

Comments

  • cgraceycgracey Posts: 14,133
    edited 2017-04-08 01:53
    I've got AUGS working with RDxxxx/WRxxxx.

    AUGS can be used to either provide a 20-bit constant address, or invoke PTRA/PTRB with a 20-bit unscaled index:
    #s		00000000000000000000000_0aaaaaaaa = hub address $00000..$000FF
    #s		00000000000000000000000_1supiiiii = hub address PTRA/PTRB with 5-bit scaled index
    #s+augs		xxxxxxxxxxxxaaaaaaaaaaa_aaaaaaaaa = hub address $00000..$FFFFF (x != 000000001???)
    #s+augs		000000001supiiiiiiiiiii_iiiiiiiii = hub address PTRA/PTRB with 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.
  • evanhevanh Posts: 15,126
    I haven't been following this topic but found an old request from Bill that I suspect has probably been covered now - http://forums.parallax.com/discussion/comment/1343496/#Comment_1343496
  • Thanks, Chip.

    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
  • cgraceycgracey Posts: 14,133
    edited 2017-04-14 09:44
    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.
  • jmgjmg Posts: 15,140
    cgracey wrote: »
    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.
    There are some speed numbers in this thread, to compare with
    https://forums.parallax.com/discussion/comment/1407770/#Comment_1407770

  • jmg wrote: »
    cgracey wrote: »
    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.
    There are some speed numbers in this thread, to compare with
    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

  • jmgjmg Posts: 15,140
    cgracey wrote: »
    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
  • cgraceycgracey Posts: 14,133
    jmg wrote: »
    cgracey wrote: »
    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.
  • cgracey wrote: »
    jmg wrote: »
    cgracey wrote: »
    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.
  • cgraceycgracey Posts: 14,133
    dMajo wrote: »
    cgracey wrote: »
    jmg wrote: »
    cgracey wrote: »
    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
  • cgraceycgracey Posts: 14,133
    edited 2017-04-14 22:49
    dMajo wrote: »
    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!
  • JasonDorieJasonDorie Posts: 1,930
    edited 2017-04-14 22:58
    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.
  • cgraceycgracey Posts: 14,133
    edited 2017-04-14 23:04
    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.
  • jmgjmg Posts: 15,140
    dMajo wrote: »
    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

    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.
    dMajo wrote: »
    As a start point you could..
    The risk of short term workarounds, is they tend to become entrenched and never get around to being properly fixed.

  • jmgjmg Posts: 15,140
    JasonDorie wrote: »
    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.
  • dMajodMajo Posts: 855
    edited 2017-04-15 00:36
    @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).
  • kwinnkwinn Posts: 8,697
    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

  • jmgjmg Posts: 15,140
    kwinn wrote: »
    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."

  • Maybe we just don't need floats.
  • kwinnkwinn Posts: 8,697
    potatohead wrote: »
    Maybe we just don't need floats.

    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.
  • Heater.Heater. Posts: 21,230
    99.99% of projects do not need floats.

    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.
  • Heater.Heater. Posts: 21,230
    whicker,
    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.







  • Yes, SPIN is coupled to PASM. It's fine without floats.

    Or, let's keep this SPIN simple and lean. It can be the native tool at some point.

    Extend later.
  • Heater.Heater. Posts: 21,230
    Yep, I'm all for keeping it simple and float free.

    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.
  • Let those who will add to it resolve it then. This one needs to be the P1 SPIN with reasonable adaptations for P2.

    Lots of users ready for that.

    And I think they deserve that SPIN too. Should exist.

  • potatohead wrote: »
    Yes, SPIN is coupled to PASM. It's fine without floats.

    Or, let's keep this SPIN simple and lean. It can be the native tool at some point.

    Extend later.
    I thought that Spin was going to be compiled to byte codes. Isn't that what XBYTE is all about?
Sign In or Register to comment.