Prog8 language and compiler topic

All aspects of programming on the Commander X16.
Post Reply
geek504
Posts: 95
Joined: Wed Aug 26, 2020 4:52 pm

Prog8 language and compiler topic

Post by geek504 »



1 hour ago, desertfish said:




It no longer uses the software-eval-stack for that.



Hi! Is this "software-eval-stack" you mention a software-based stack used for mathematical computations based on a RPN-type stack? E.g. 2+3 becomes 2, PUSH, 3, PUSH, +? This is what I am using for my BASIC compiler. If so, it does do a lot of function calling and can be greatly optimized if one bypasses the stack entirely but involves major compiler modifications as you mentioned. This is a sample code from my compiler using macros that greatly improves readability:


Quote






10 REM ASSIGNMENT

20 AX = 3 : REM NEED TO OPTIMIZE

30 V = ABS(AX + 2)

35 Q = 1 + 2 * 6 / 3

40 PRINT "THE END"

50 END



start

  line

    10

    comment    REM ASSIGNMENT

  line

    20

    assignment

      AX

      3

    comment    REM NEED TO OPTIMIZE

  line

    30

    assignment

      V

      abs

        add_exp

          AX

          +

          2

  line

    35

    assignment

      Q

      add_exp

        1

        +

        mul_exp

          mul_exp

            2

            *

            6

          /

          3

  line

    40

    print    "THE END"

  line

    50

    end



Tree('start', [Tree('line', [Token('INT', '10'), Tree('comment', [Token('COMMENT', 'REM ASSIGNMENT')])]), Tree('line', [Token('INT', '20'), Tree('assignment', [Token('VAR_ID', 'AX'), Token('INT', '3')]), Tree('comment', [Token('COMMENT', 'REM NEED TO OPTIMIZE')])]), Tree('line', [Token('INT', '30'), Tree('assignment', [Token('VAR_ID', 'V'), Tree('abs', [Tree('add_exp', [Token('VAR_ID', 'AX'), Token('ADD_OP', '+'), Token('INT', '2')])])])]), Tree('line', [Token('INT', '35'), Tree('assignment', [Token('VAR_ID', 'Q'), Tree('add_exp', [Token('INT', '1'), Token('ADD_OP', '+'), Tree('mul_exp', [Tree('mul_exp', [Token('INT', '2'), Token('MUL_OP', '*'), Token('INT', '6')]), Token('MUL_OP', '/'), Token('INT', '3')])])])]), Tree('line', [Token('INT', '40'), Tree('print', [Token('STRING', '"THE END"')])]), Tree('line', [Token('INT', '50'), Tree('end', [])])])



.include "macros.inc"

.include "header.inc"

.code



L10:        ; REM ASSIGNMENT

L20:        PushInt 3

        PullVar AX

        ; REM NEED TO OPTIMIZE

L30:        PushVar AX

        PushInt 2

        jsr ADD

        jsr ABS

        PullVar V

L35:        PushInt 1

        PushInt 2

        PushInt 6

        jsr UMUL

        PushInt 3

        jsr UDIV

        jsr ADD

        PullVar Q

L40:        LoadAddress S0        ; to r0

        jsr PrString

L50:        rts



S0:        .asciiz "the end"

AX:        .res 2

V:        .res 2

Q:        .res 2



.include "io.asm"

.include "math.asm"

 



As you can see, line 20 does a PUSH and a PULL to/from stack for a simple AX=3. It could have simply copied over the INT 3 directly into VAR AX. I'm planning in writing a post-compiler optimizer much later. Note that I couldn't use VAR A since A is a reserved keyword in ca65!

User avatar
desertfish
Posts: 1073
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

Prog8 language and compiler topic

Post by desertfish »


Exactly like that, @geek504  the software eval stack of Prog8 is a (low/high byte split) stack indexed by the X register that functions as a second stack pointer.  Expressions like A+B are evaluated like you pointed out.   I've been working on eliminating some of the need for this stack for intermediary results and trivial expressions and assignments, but for most non-trivial expressions it is still required.

It makes the code generator itself a lot simpler however the generated code is quite inefficient in terms of 6502 assembly....

geek504
Posts: 95
Joined: Wed Aug 26, 2020 4:52 pm

Prog8 language and compiler topic

Post by geek504 »



13 hours ago, desertfish said:




It makes the code generator itself a lot simpler however the generated code is quite inefficient in terms of 6502 assembly....



@desertfish I started coding my compiler without a stack and while I can say it was efficient, it was just too slow (edit: to code and finish the compiler) and prone to bugs... I decided to implement the stack midway just to get the compiler ready and then re-implement the non-stack improvements later if at all. I'm guessing a rough 10-15% speed improvement and am not sure if it is worth the effort right now. 6502 assembly is inefficient by nature (but very simple to implement) especially if we write proper assembly code to preserve A, X, and Y, wasting bytes and cycles with PHA, PHX, PHY, and PLY, PLX, PLA prior to every subroutine. I do feel that this is still more efficient than cc65's C-stack implementation though.

I am not worrying too much about maximum efficiency (I don't think we will ever get close to super tight assembly code) because I hope one day in the future we will be able to crank up the X16's MHz to GHz range!

At least in the emulator scene, we can implement the following 6502 JIT-core to x64 which could bring to a realistic 12GHz!

https://scarybeastsecurity.blogspot.com/2020/04/clocking-6502-to-15ghz.html?m=1

beebjit_15GHz.png.e4ed4ecc5eb06833cbbd73b194b1fa16.png

User avatar
desertfish
Posts: 1073
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

Prog8 language and compiler topic

Post by desertfish »



10 hours ago, geek504 said:




(I don't think we will ever get close to super tight assembly code)



Indeed, especially not with my compiler writing skills ?

That's why I included the inline-assembly block in prog8 from the start, to make it easy and fairly transparent to write critical pieces of code in tuned assembly

User avatar
desertfish
Posts: 1073
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

Prog8 language and compiler topic

Post by desertfish »


I've just released Prog8 5.1

It contains a few bugfixes (such as making breakpoints in Vice work again), but the bulk of the changes are improvements to the generated assembly code.

Certain array accesses, value assignments and value comparisons have seen optimizations and the result is that the "plasma" benchmark from the millfork-benchmarks project now runs at around the same speed as the optimized CC65 version does.

 

note   I made an error in the setting of the graphics mode in this release. The VIC YSCROLL register ($d011) is not set correctly.  You can fix this in your own code or wait for the next Prog8 version to be released.... Sorry ?

geek504
Posts: 95
Joined: Wed Aug 26, 2020 4:52 pm

Prog8 language and compiler topic

Post by geek504 »


@desertfish curious... which PRNG algorithm did you use?

User avatar
desertfish
Posts: 1073
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

Prog8 language and compiler topic

Post by desertfish »


I use a few:

floats -> the RND routine in ROM

bytes and words -> the 'small fast' rnd routines by white flame fromhttps://www.codebase64.org/doku.php?id=base:small_fast_16-bit_prng 

User avatar
desertfish
Posts: 1073
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

Prog8 language and compiler topic

Post by desertfish »


I've just released Prog8 5.2

It contains a few important bug fixes (some value comparisons were done wrong, for instance) and the silly YSCROLL screen issue for graphics bitmap screen mode on the C64 that crept into the 5.1 release, is also fixed.

Note:  starting with this release,  you now require Java version 11 to run the compiler.

User avatar
desertfish
Posts: 1073
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

Prog8 language and compiler topic

Post by desertfish »


I've just released Prog8 5.3

Once again a bunch of important bugfixes have been made as well as various additions to the library modules.

Doigt
Posts: 28
Joined: Mon Jul 13, 2020 4:04 am

Prog8 language and compiler topic

Post by Doigt »


Good work desertfish!

Post Reply