Fast Bytecode Interpreter

1242526272830»

Comments

  • There's also a giant 'Hive' processor Darpa were working on
  • who told you that? its classified...

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • cgraceycgracey Posts: 11,694
    edited 2018-09-15 - 08:47:50
    I think the interpreter is done, barring any bugs which may pop up later, as more code gets run through it.

    Unsigned divide, remainder, and comparisons were added per Eric Smith's recommendation.

    This interpreter leaves cog registers $000..$0BF free for user programs, while $0C0..$0DF is a buffer that only gets disturbed by MOVExxxx/FILLxxxx/STRSIZE/STRCOMP instructions, but might serve as local-variable copies for in-line PASM code.

    To execute a PASM program, you just do this in Spin2:

    EXEC(@pasm_program)

    Here is how you write the PASM code for this usage (2-byte header tells org/length):
    DAT
    pasm_program	byte	$000,3-1	'PASM loads/executes at $000 and is 3 instructions long
    		org	$000		'set origin to load/execute address
    
    		xor	outa,#$FF	'initially executes
    	_ret_	xor	outb,#$FF	'...then returns to execute next bytecode
    
    tognib	_ret_	xor	outb,#$0F	'can be called
    

    PASM programs can be terminate-stay-resident and use interrupts, if you want.

    To call PASM code that is already loaded into $000..$0BF from Spin2:

    CALL(tognib)

    There will be some automation of the 2-byte header generation for in-line PASM, as well as local variable referencing.
  • For goodness sake don't use the terms "master" and "slave" for anything. The PC police will lynch you.
    https://www.rt.com/news/438298-python-master-slave-code/
  • wow, super nice effort Chip.

    I really like the mix of spin2 and pasm inside a single cog. Its going to be great.
  • I like the EXEC / CALL idea, Chip. Thanks for putting it in! A few questions:

    (1) How can we pass values to the PASM code and get results back? It seems a common use case would be to use PASM to accelerate some frequently used functions, e.g. for floating point. It looks like we can almost pass things on the ptra stack, but I think the top of stack is kept in "x". Maybe that could be located in a known fixed location (like $1DC)?

    (2) We can HUBEXEC via EXEC of a JMP instruction, but I wonder if that's a common enough use case to warrant its own instruction? It's not a big deal either way: once we can get into PASM we can do anything :)
  • LOL, have to agree with Roy and potatohead even though I find this to bee hilarious.

    CORE is a better choice, not because it provides a better or more accurate description than COG does, but because it gives the folks who are familiar with the term CORE some idea of what the P1/P2 is.
    In science there is no authority. There is only experiment.
    Life is unpredictable. Eat dessert first.
  • Re: Passing data between spin2 and pasm.

    Maybe hub addresses $00 to $7f can be reserved for this purpose.
    For each cog we have 4 longs representing count_out,address,count_in,address

    for example
    to_pasm		cogid	ptra
    		shl	ptra,#4		'calc address of pointers for cog
    		wrlong	count,ptra[0]	'number of variables passed to pasm
    		wrlong	addr,ptra[1]	'address of variable list
    ..
    back2spin2	cogid	ptra
    		shl	ptra,#4		'calc address of pointers for cog
    		rdlong	count,ptra[2]	'number of returned variables to spin2
    		rdlong	addr,ptra[3]	'address of returned varaiables
    
    
    Melbourne, Australia
  • cgraceycgracey Posts: 11,694
    edited 2018-09-17 - 04:46:04
    ozpropdev wrote: »
    Re: Passing data between spin2 and pasm.

    Maybe hub addresses $00 to $7f can be reserved for this purpose.
    For each cog we have 4 longs representing count_out,address,count_in,address

    for example
    to_pasm		cogid	ptra
    		shl	ptra,#4		'calc address of pointers for cog
    		wrlong	count,ptra[0]	'number of variables passed to pasm
    		wrlong	addr,ptra[1]	'address of variable list
    ..
    back2spin2	cogid	ptra
    		shl	ptra,#4		'calc address of pointers for cog
    		rdlong	count,ptra[2]	'number of returned variables to spin2
    		rdlong	addr,ptra[3]	'address of returned varaiables
    
    

    Yes, there needs to be something like that, where the local variables will be copied into some registers for the PASM code and then restored to hub RAM on exit. Registers $0C0-$0DF can serve this purpose. This way, inline PASM code can use the local variables by name, as registers.
  • Great call.
    Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
    Parallax colors simplified: https://forums.parallax.com/discussion/123709/commented-graphics-demo-spin<br>
  • msrobotsmsrobots Posts: 2,909
    edited 2018-09-17 - 05:27:57
    wow, this opens spin to c and c to spin calls also, @ozpropdev you are a smart person, thank you.

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • Chip
    Can I make a suggestion for an addition to Pnut.
    Two new directives for generating bytes for use with the RFVAR/RFVARS instructions.
    Maybe somethng like
    pgm	byte	0,1,2,3
    	fvar	1234
    	fvars	-2468
    
    Melbourne, Australia
  • ozpropdev wrote: »
    Chip
    Can I make a suggestion for an addition to Pnut.
    Two new directives for generating bytes for use with the RFVAR/RFVARS instructions.
    Maybe somethng like
    pgm	byte	0,1,2,3
    	fvar	1234
    	fvars	-2468
    

    Yes, I was just thinking about that today. There is a problem, though, in that the assembler is only two-pass. We'd need more passes to resolve cases where the data are forward addresses, so that their sizes are not known on the first pass. We'd need more passes to resolve their sizes. It would take some brain power to improve the assembler. One clunky way around the problem is to have var7/var14/var21/var29 and vars7/vars14/vars21/vars29, where the data size is stated and then the data is qualified. That's probably what I'll do for now.
  • cgracey wrote: »
    Yes, I was just thinking about that today. There is a problem, though, in that the assembler is only two-pass. We'd need more passes to resolve cases where the data are forward addresses, so that their sizes are not known on the first pass. We'd need more passes to resolve their sizes. It would take some brain power to improve the assembler. One clunky way around the problem is to have var7/var14/var21/var29 and vars7/vars14/vars21/vars29, where the data size is stated and then the data is qualified. That's probably what I'll do for now.

    Yikes!
    I hadn't thought about the extra passes needed. That adds a bit of complexity.
    And of course the SPIN2 component suffers the same issue.
    Melbourne, Australia
  • Actually, the Spin compiler does multiple passes, until the size stops changing.
  • cgracey wrote: »
    Actually, the Spin compiler does multiple passes, until the size stops changing.
    Phew!
    That's a relief. :)

    Melbourne, Australia
  • I think the interpreter is done, though I need to test it with compiled code.

    Here is what inline PASM will look like:
    PRI doit(b,c,d) : a | e, f, g
    
      spin2_code_here_if_wanted
    
    	---
    	add	a,b	'assembles from $000..$0BF
    	sub	c,a	'a,b,c,d,e,f,g,... at $0C0..$0DF
    	mul	a,b
    	xor	d,a
    	---
    
      spin2_code_here_if_wanted
    

    You can do labels and byte/word/long declarations, as well.

    Here is the interpreter code that executes an inline PASM routine:
    '
    '
    ' In-line PASM
    '
    inline		rfvar	y		'get address of pasm code
    		add	y,pbase
    
    		rfbyte	z		'get length of pasm code
    
    		setq	z		'load pasm code starting at register 0
    		rdlong	0,y
    
    		rfbyte	y		'get local variable count
    
    		setq	y		'load local variables from hub into buff
    		rdlong	buff,dbase
    
    		call	#0		'call pasm code
    
    		setq	y		'store local variables in buff back to hub
    		wrlong	buff,dbase
    
    	_ret_	rdfast	#0,pb		'restart bytecode stream, in case FIFO disrupted
    
  • Does the pasm have to have that --- before and after it?
    If so, then it should be something like a PASM keyword at the start and then indent the actual pasm lines. That would fit the language syntax better and not use --- as a keyword which i think is awful.
  • Roy Eltham wrote: »
    Does the pasm have to have that --- before and after it?
    If so, then it should be something like a PASM keyword at the start and then indent the actual pasm lines. That would fit the language syntax better and not use --- as a keyword which i think is awful.

    I agree with you about --- as a keyword, but indentation alone won't cut it if the inline assembly can contain labels (which won't be indented). In fastspin I used asm / endasm to delimit the inline assembly block.
  • Chip
    I've been running the SPIN2 interpreter through my debugger and it's running great!
    Here's the current bytecodes isolated to their final sequences for verification.
    Melbourne, Australia
  • ersmith
    Yeah, you are right. Although, there's nothing really that couldn't stop it from having the labels indented that I can think of right now.
    I prefer the ASM/ENDASM keywords though to allow for nicer formatting of the PASM code inside.
  • ASM/ENDASM would help with syntax highlighting too, I think...
    Prop Info and Apps: http://www.rayslogic.com/
  • ASM/ENDASM would be fine. There would be no indention sensitivity within the pasm code.
Sign In or Register to comment.