News:

PlayBASIC2DLL V0.99 Revision I Commercial Edition released! - Convert PlayBASIC programs to super fast Machine Code. 

Main Menu

PlayBASICFX / PBFX Vm2 Translation (WIP)

Started by kevin, September 08, 2008, 12:13:35 PM

Previous topic - Next topic

kevin

PlayBasicFX VM2 translation WIP/BLOG

  This thread is mainly for me so I can keep track of what is functional and what changes have needed to be made during to the translation from the VM1 to VM2 runtime.  


 
Learn About VM2 + PlayBASIC FX


       * See Demo Retail and Upgrading Question FAQ
       * See www.PlayBasicFX.com




 
Work In Progress Blog Follows



ON Goto

    ON GOTO is now in VM2,  one change is the it only accepts Integer 'select' variables.  However, you can still use a float, but it's recast for you.

    Sample.

PlayBASIC Code: [Select]
   Setfps 30

Do
Cls 0

a#=rnd(5)
print a#
on a# goto l0,l1,l2,l3
print "MISSED"
goto Cont


L0:
print "label #0"
goto Cont
L1:
print "label #1"
goto Cont
L2:
print "label #2"
goto Cont
L3:
print "label #3"
goto Cont

Cont:

Sync
waitkey
loop







Loops - FOR/NEXT / REPEAT UNTIL / WHILE ENDWHILE & DO DECLOOP

   All variable loop structures are running on VM2



PlayBASIC Code: [Select]
   max=30000

Do
cls 0
inc frames


t=timer()
K=0
for lp=0 to max
K=K+1
next
t3#=t3#+(timer()-t)
print k
print "For loop:"+Str$(t3#/frames)



t=timer()
K=0
while K<max
K=K+1
endwhile
t1#=t1#+(timer()-t)
print k
print "While Loop:"+Str$(t1#/frames)


t=timer()
K=0
repeat
K=K+1
until K>=max
t2#=t2#+(timer()-t)
print k
print "Repeat Loop:"+Str$(t2#/frames)



t=timer()
lp=max
k=0
do
K=K+1
decloop lp
t4#=t4#+(timer()-t)
print k
print "Dec Loop:"+Str$(t4#/frames)

sync
loop




INC / DEC are inline

  Old INC/DEC opcodes are removed and recast as packed ADD/SUB opcodes.


PlayBASIC Code: [Select]
Do
Cls 0

a=0
b#=0
c=0
d#=0
For lp=0 to 1000
inc a
inc B#
dec c
dec d#

next
print a
print B#
print c
print D#

sync

loop




kevin

#1
Strings

    Started moving/reworking the base string operations code to Vm2.


PlayBASIC Code: [Select]
   a$="yeah"
b$="dude"
print a$
For lp =0 to 10
print "Hello"+Str$(lp)
print left$("Hello"+Str$(lp),2)
next
test("Local String")
Sync
Waitkey


Function test(LocalString$)
print LocalString$
EndFunction






String Addition

    Updated the String Addition opcodes,  it's following loop is now pure VM2.  The string addition test (1 meg long string) runs about 5 milliseconds faster than 1.64.   Running on average in 12.7 milliseconds... :).


PlayBASIC Code: [Select]
   a$="hello World"

max=99000


Do
cls 0

inc frames
c$=""
t=timer()
For lp=0 to max
c$=c$+a$
next
tt#=tt#+(timer()-t)

print len(c$)
print left$(c$,1024)
print tt#/frames

Sync

loop






String Compares


PlayBASIC Code: [Select]
   This$="Aaa"
That$="Bbb"

print "Strings Equal:"+Str$(This$=This$)
print "Strings Equal:"+Str$(This$=That$)
print "Strings Not Equal:"+Str$(This$<>That$)
print "Strings Less Than:"+Str$(This$<That$)
print "Strings Greater Than:"+Str$(This$>That$)
print "Strings Less Than Equal:"+Str$(This$<=That$)
print "Strings Greater Than Equal:"+Str$(This$>=That$)


Sync
waitkey




 Changed the opcode structure a little (smaller) and when the test loop are running purely on Vm2 all the string compare methods are about 2->4ms faster over a 100,000 iterations.  When comparing 41 chr strings.


PlayBASIC Code: [Select]
   This$="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1"
That$="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB2"

max=100000


Do
cls 0

inc frames
t=timer()
For lp=0 to max
result=This$=That$
next
t1#=t1#+(timer()-t)
print "Equals:"+Str$(t1#/frames)


t=timer()
For lp=0 to max
result=This$<>That$
next
t2#=t2#+(timer()-t)
print "Not Equals:"+Str$(t2#/frames)


t=timer()
For lp=0 to max
result=This$<That$
next
t3#=t3#+(timer()-t)
print "Less Than:"+Str$(t3#/frames)


t=timer()
For lp=0 to max
result=This$>That$
next
t4#=t4#+(timer()-t)
print "Greater Than:"+Str$(t4#/frames)



t=timer()
For lp=0 to max
result=This$<=That$
next
t5#=t5#+(timer()-t)
print "Less Than Equals:"+Str$(t5#/frames)


t=timer()
For lp=0 to max
result=This$>=That$
next
t6#=t6#+(timer()-t)
print "Greater Than Equals:"+Str$(t4#/frames)


Sync

loop





kevin

#2
Pointers

    The current beta has pointer operations hooked up.  So while the following works, it's not purely running on VM2 in this edition.  


PlayBASIC Code: [Select]
      Bank=NewBank(1000)
Dim Ptr as Byte Pointer

print Bank

Ptr=GetBankPtr(Bank)

For lp=0 to 100
*ptr =lp
print PeekBankByte(Bank,lp)
print *ptr
ptr=ptr+1
next

Sync
waitkey




 and

PlayBASIC Code: [Select]
   Type tviewport
x1,y1,x2,y2
Endtype

Type Stuff
state
cool
yeah
x
viewport as tviewport

Array(100)
EndType

Dim me as Stuff pointer
Me = new Stuff
me.state=1
me.state=2

SetVP(Me.Viewport,100,100,200,200)


For lp=0 to 10
me.array(lp)=100+lp
next


print int(me)
print me.state

Sync
waitkey



Function SetVP(Vp as tviewport pointer,x1,y1,x2,y2)
vp.x1=x1
vp.y1=y1
vp.x2=x2
vp.y2=y2

EndFunction






kevin

#3
Vm2 Stack

   Moving/changing how the Stack works in the VM2.  As such this means setting up various base controls again.  


Gosub/return

    Gosub is now running on Vm2,  the new code doesn't support stack errors though.  So under/overflow will crash the runtime.


PlayBASIC Code: [Select]
   gosub SubRoutine

print "done"

Sync
waitkey

end



SubRoutine:
print "inside gosub"
gosub SubRoutine2
gosub SubRoutine2
gosub SubRoutine2
gosub SubRoutine2
return


SubRoutine2:
print "inside gosub #2"
return






On Variable Gosub

   ON variable GOSUB is now in VM2.   The select variable is now integer only (as per on variable goto), but floats are recast for you.


    Sample.

PlayBASIC Code: [Select]
Setfps 30

Do
Cls 0

a#=rnd(10)
print a#

on a# gosub l0,l1,l2,l3

Sync
waitkey
loop



L0:
print "label #0"
gosub Hold
return
L1:
print "label #1"
gosub Hold
return
L2:
print "label #2"
gosub Hold
return
L3:
print "label #3"
gosub Hold
return


Hold:
Sync
waitkey
return




kevin

#4
   Scope / Stack Controls in VM2

    The new stack behaviors in VM2 give it about a 40->50% speed increase in calling functions.  It's also a little more logically firendly in regards to string thrashing also..  
 
PlayBASIC Code: [Select]
;      gosub SubRoutine

; print "done"

RecFun(100,200,"Cool")


Test(50.78,123.456,200)
Stuff()


print "pointer"
a= int(CalcTest(100,33.44))
print a
Fun(45, 33.33, "hello")
Fun(45, 33.33, "hello")

; push 1234567
; print pop()

Sync
#break

WaitKey
end

Function Stuff()
print "stuff"

EndFunction


Function Test(A,B#,C)

print a
print b#
print c

EndFunction




Function CalcTest(A,B#)

; print a
; print b#
result$="String Result"+str$(a+B#)

Bank=NewBank(100)
BankPtr= GetBankPtr(Bank)
Ptr=GetBankPtr(Bank)
; print Bank
; print int(PTR)

endFUnction Ptr as pointer



Function Fun(a,b#,c$)

print "FUNCTION BABY"
#break
print a
; print b#
print c$

g#=45
Stuffs$="Yeah yeah"
print Stuffs$
result=455
EndFunction



Function RecFun(a,b#,c$)

print "Recusive FUNCTION"
print a
print b#
print c$
Sync

g#=45
Stuffs$="Yeah yeah"
print Stuffs$
result=455

#break

if a<200
RecFun(a*2,b#*2,c$+c$)
endif

EndFunction




SubRoutine:
print "inside gosub"
gosub SubRoutine2
gosub SubRoutine2
gosub SubRoutine2
gosub SubRoutine2
return


SubRoutine2:
print "inside gosub #2"
return





  This second example is just for benching the function/psub and sub routine calling mechanisms.  I should point out that this code isn't running purely on VM2 just yet,  so some bits are slower than they should due to the context switches (falling back to run old opcodes in VM1)   But that's only temporary !  


PlayBASIC Code: [Select]
Tests=10000

Do
cls 0
inc frames

// ===================================
// USer Functions VS Projected Subroutines
// ===================================


// ==========
// Test #1
// ==========

T=timer()
For LP=0 to Tests
result=SomeFunctionCalc(10,lp)
next
tt1#=tt1#+(timer()-t)
Print "Test #1 Average Time:"+Str$(tt1#/frames)



// ==========
// Test #2
// ==========

T=timer()
// Call the Psub function
For LP=0 to Tests
result=SomesubCalc(10,lp)
next
tt2#=tt2#+(timer()-t)
Print "Test #2 Average Time:"+Str$(tt2#/frames)

T=timer()
// Call the Psub function
For LP=0 to Tests
gosub MySub
next
tt3#=tt3#+(timer()-t)
Print "Test #3 Sub Routine Calling:"+Str$(tt3#/frames)


Sync
loop


Function SomeFunctionCalc(A,B)

A=A*B

l1=23
l2=23
l3=23
l4=23
l5=23
l6=23
l7=23
l8=23
l9=23

EndFunction A



Psub SomeSubCalc(A,B)
A=A*B

l1=23
l2=23
l3=23
l4=23
l5=23
l6=23
l7=23
l8=23
l9=23

EndPsub A




MySub:
return




kevin

#5
   Assignments / Basic Arrays in VM2

    Today's revision now includes basic move operations on Vm2.   These instructions currently only support simple variables & arrays.   Speed wise they're about twice as fast (for integers & floats) as the quickest Vm1 edition (V1.64).  


PlayBASIC Code: [Select]
   Dim table(1000)
Dim table#(1000)

address=GetArrayPtr(Table())
print address
for lp=0 to 100
pokeint PBArrayStruct_size+address+(lp*4),lp
next

for lp=0 to PBArrayStruct_size-1 step 4
print peekint(Address+lp)
next

lp=10
print Table(lp)
print hex$(Table(lp))

Table(lp)=45.23
print Table(lp)
print hex$(Table(lp))

Sync
Waitkey


max=50000
Do
cls 0
inc frames
Offset=(Offset+1) and 255

t=timer()
For lp=0 to max
Table(offset)=lp
a=Table(offset)
next
T1#=t1#+(timer()-t)
print t1#/frames

t=timer()
For lp=0 to max
Table#(offset)=lp
a=Table#(offset)
next
T2#=t2#+(timer()-t)
print t2#/frames

sync
loop





kevin

#6
   User Defined Types/Structures

     Today's little task has been to expand upon the 'move' instruction set by adding support for UDT structures on Vm2.    This allows for types to be nulled/freed on VM2 side.   The following NULL type runs about 4->5 times faster than PB1.64.  However,  field accesses still fall back through vm1 ATM.


PlayBASIC Code: [Select]
   Type  Kev2
MyInteger
MyFloat#
MyString$
MyInteger2
MyFloat2#
EndType


constant ArraySize=100
Type Kev
MyInteger
MyFloat#
MyString$
IntegerArray(ArraySize)
FloatArray(ArraySize)
StringArray$(ArraySize)
MyInteger2
MyFloat2#
EndType


Dim me as kev

max=1000

Do
cls 0
inc frames

me.MYinteger=45
me.MYFloat#=123.456
me.MYString$="Abccddeded"
me.MYinteger2=10045
me.MYFloat2#=200123.456

For lp=0 to ArraySize
me.Integerarray(lp)=30000+lp
me.Floatarray(lp)=22222.45+lp
me.stringarray$(lp)="yeah"+str$(lp)
next

// Clear the fields to zero
t=timer()
For test=0 to max
me.kev =null
next
t1#=t1#+(timer()-t)
print t1#/frames
Sync
loop





kevin

#7
   Bound Function Calling

     Finally moved & updated the function calling opcodes to the Vm2 runtime.  The new approach is a lot cleaner, which results is less man handling of data and thus faster call/return behaviors.   Todays edition of the Vm2 can call the RGB() function 50000 times in 2.8/2.9 milliseconds.  Compared to PB1.64 which takes 10.8/10.9 milliseconds,  making Vm2 about 3 times faster.   There will be difference depending upon the number of parameters etc.  

 
PlayBASIC Code: [Select]
   max=5000

Do
cls 0
inc frames

// calling the rgb function
t=timer()
For test=0 to max
; unroll so were timing the function calling mainly
result=rgb(r,g,b)
result=rgb(r,g,b)
result=rgb(r,g,b)
result=rgb(r,g,b)
result=rgb(r,g,b)

result=rgb(r,g,b)
result=rgb(r,g,b)
result=rgb(r,g,b)
result=rgb(r,g,b)
result=rgb(r,g,b)
next
t1#=t1#+(timer()-t)
a#=t1#/frames
print a#

// Calls per second
print "Calls Per second:"+str$(int((1000.0/a#)*(max*10)))

Sync
loop

 

     

kevin

#8
   Select /Case

     Somehow the select/case opcodes had been missed, so those have been tonight's little focus.  While the update it's not finished, Integer immediate selects are already some 3 times faster.  


PlayBASIC Code: [Select]
   SelectionValue=30

max=50000

Do
cls 0
print "Select Value:"+str$(SelectionValue)

inc frames
t=timer()

For lp=0 to max
Select SelectionValue
case 10
R=10

case 20
R=20

case 30
R=30
EndSelect
next
t1#=t1#+(Timer()-t)

print t1#/frames
print "Result:"+Str$(r)
print "done Select case"

Sync
loop







  Select /Case  String$

    All the operations are supported now.   Bellow is a demo of string range case trapping.  Vm2 can run this code a little over twice as fast as Vm1.


PlayBASIC Code: [Select]
   max=50000

SelectionValue$="feef"

Do

Cls rgb(0,0,0)
Print "Select Value:"+(SelectionValue$)

inc frames
t=timer()
For lp=0 to max
Select SelectionValue$
case "aa"
R=10
case "bb"
R=20
case "cc"
R=30
case "dd" to "zz"
R=40
EndSelect
next
t1#=t1#+(Timer()-t)

print t1#/frames
print lp
print "Result:"+Str$(r)
print "Done Select case"

Sync
loop



kevin

#9
   String Functions on Vm2

   Tonight I've been working on the moving the built in string functions across.  So far the only one that works is the "LEN" function.  Only another 25 or so to go..  What fun :)


PlayBASIC Code: [Select]
  a$="abcdef"
print len(a$)
Sync
waitkey





MID$()  & Mid()
PlayBASIC Code: [Select]
  a$="abcdef"
print mid$(a$,2,3)

for lp=1 to len(a$)
print mid(a$,lp)
next

Sync
waitkey




LEFT$() & RIGHT$()

PlayBASIC Code: [Select]
  a$="abcdef"

print Left$(a$,1)
print Right$(a$,1)

Sync
waitkey



CutLeft$() & CutRight$()

PlayBASIC Code: [Select]
  a$="abcdef"

print CutLeft$(a$,3)
print CutRight$(a$,3)

Sync
waitkey




Trim$(), TrimLeft$(),TrimRight$()

PlayBASIC Code: [Select]
  a$="<<<<>>>>"
print trim$(a$,"<>")
print trimLEft$(a$,"<")
print trimRight$(a$,">")
Sync
waitkey




Upper$(),lower$(),AutoCaps$()

PlayBASIC Code: [Select]
  a$="aaaaaa"
b$="BBBBBBBB"
c$="hello world"
print upper$(a$)
print lower$(b$)
print autocaps$(c$)
Sync
waitkey




CHR$() / bin$(), HEX$()

PlayBASIC Code: [Select]
   For lp=32 to 40
print chr$(lp)
print bin$(lp)
print hex$(lp)
next

Sync
waitkey




ASC()
PlayBASIC Code: [Select]
   a$="abcdefg"
For lp=1 to len(a$)
print asc(mid$(a$,lp,1))
print mid(a$,lp)
next
Sync
waitkey



 VAL() & VAL#()

PlayBASIC Code: [Select]
   a$="123.456"
print Val(a$)
print Val#(a$)

Sync
waitkey



 STR$()

PlayBASIC Code: [Select]
   a$="123.456"
for lp=0 to 10
print "yeah"+str$(lp)
print "yeah"+str$(float(lp))
next

Sync
waitkey




Replace$()
PlayBASIC Code: [Select]
   a$="aaaaabbbbBBBBcdefg"
print replace$(a$,"b","-",1,0,0)
print replace$(a$,"b","-",1,0,true)
print replace$(a$,"b","-",1,true,false)

Sync
waitkey






Instring()


PlayBASIC Code: [Select]
   a$="aaaaabbbbBBBBcdefg"

print instring(a$,"B",1,false)
print instring(a$,"B",1,true)


Sync
waitkey





Make$(), insert$, Digits$(),Flip$(),pad$()
PlayBASIC Code: [Select]
   a$="abc"
print make$(a$,10)
print pad$(a$,".",1)
print flip$(a$)
print Insert$(a$,"---",2)
print digits$(12,6)

Sync
waitkey




kevin

#10
  String Function Test

  I've now moved all the built in string functions across to VM2.  The following is a fairly nasty stress test comparison between Vm2 (found in 1.73j) and Vm1 found in PB V1.64.   The results are the same as other previous tests, with a good health (25->50%)  performance boast when running through Vm2.  The gain is mainly due to the faster loop processing though,  as I haven't really changed the library.  But anyway


PlayBASIC Code: [Select]
   b$="aaaaaaaaaaaaaaabbbbbbbbbbbbbbcccccccccccccccddddddddddddddddddddddd"

max=50000
Do
Cls rgb(0,0,0)
inc frames


t=timer()
For lp=0 to max
a$=mid$(b$,5,5)
next
t1#=t1#+(Timer()-t)
print "MID:"+str$(t1#/frames)
print a$


t=timer()
For lp=0 to max
a$=left$(b$,20)
next
t2#=t2#+(Timer()-t)
print "Left:"+str$(t2#/frames)
print a$

t=timer()
For lp=0 to max
a$=Right$(b$,20)
next
t3#=t3#+(Timer()-t)
print "Right:"+str$(t3#/frames)
print a$


t=timer()
For lp=0 to max
a$=Replace$(b$,"c","d",1,0,0,)
next
t4#=t4#+(Timer()-t)
print "Replace:"+str$(t4#/frames)
print a$

Sync
loop





kevin

#11
   Array Command Set

   Haven't had much computer time the past couple of days,  but the current WIP is the array command set.  So far,  the only command running on VM2 is DIM.   There's not really much to speed up with dim,  so I've mostly been breaking up the function set.  With any luck and a little bit of effort, this will make upgrading the rest of the library much easier.


PlayBASIC Code: [Select]
   Size=50

max=10000
Do
Cls rgb(0,0,0)
inc frames

Memory=0
t=timer()
For lp=0 to max
Dim Table(Size)
next
t1#=t1#+(Timer()-t)
print "DIM1D:"+str$(t1#/frames)
Memory=Memory+(Max*Size)


t=timer()
For lp=0 to max
Dim Table(Size,Size)
next
t2#=t2#+(Timer()-t)
print "DIM2D:"+str$(t2#/frames)

Memory=Memory+(Max*(Size*Size))

print "Integers:"+Str$(Memory)
Sync
loop




kevin

#12
   Array Command Set Cont.

  Setting up the array query functions.  One change is the GetArrayElements() will return a zero if you access an illegal dimension (a dimension that doesn't exist).  Also, the new library doesn't throw errors ATM.


PlayBASIC Code: [Select]
   Dim Table(20,30)

Print GetArrayStatus(Table())
Print GetArrayDimensions(Table())

for lp=0 to GetArrayDimensions(Table())+1
print GetArrayElements(Table(),lp)
next

Sync
waitkey




Sort Array


PlayBASIC Code: [Select]
   Size=20
do
Cls 0
Dim Table(20)
Print "Random Array"
For lp=0 to size
Table(lp)=rnd(100)
print Table(lp)
next

SortArray Table(),0, size

Print "Sorted Array"
For lp=0 to size
print Table(lp)
next

Sync
waitkey
waitnokey
loop





kevin

#13
   Array Command Set Cont.


 Swap Array

PlayBASIC Code: [Select]
   Dim Table(20)
Dim Table2(10)

Print "Random Array"
FillArray(Table())
FillArray(Table2())

Do
Cls 0

Print "Table1"
ShowArray(Table())

Print "Table2"
ShowArray(Table2())

print "Press any key"
Sync
waitkey
waitnokey

swaparray Table(),Table2()
loop


Function ShowArray(ThisArray())
For lp=0 to GetArrayElements(ThisArray(),1)
print ThisArray(lp)
next
EndFunction

Function FillArray(ThisArray())
For lp=0 to GetArrayElements(ThisArray(),1)
ThisArray(lp)=rnd(100)
next
EndFunction






 Move Array

PlayBASIC Code: [Select]
   Dim Table(20)
Dim Table2(10)

Print "Random Array"
FillArray(Table())
FillArray(Table2())

Do
Cls 0

Print "Table1"
ShowArray(Table())

Print "Table2"
ShowArray(Table2())

print "Press any key"
Sync
waitkey
waitnokey

Movearray Table(),Table2()
loop


Function ShowArray(ThisArray())
For lp=0 to GetArrayElements(ThisArray(),1)
print ThisArray(lp)
next
EndFunction

Function FillArray(ThisArray())
For lp=0 to GetArrayElements(ThisArray(),1)
ThisArray(lp)=rnd(100)
next
EndFunction




kevin

#14
   Redim replacement.

   Working on REDIM reaplacement, it's sorta working, even though it's currently got some issues.


PlayBASIC Code: [Select]
   SIZE=100
Dim Table$(size)
For lp2=0 to size
table$(lp2)="test:"+str$(1000+lp2)
Next
Test()

Sync
WaitKey


Function Test()
redim Table$(10)
EndFunction