jum Posted October 15, 2019 Share Posted October 15, 2019 (edited) Has anyone tried using Millfork language to compile something for the Lynx? A "middle-level programming language targeting 6502-based, 8080-based and Z80-based microcomputers." https://github.com/KarolS/millfork Readme says that it can target Atari Lynx and Atari 8-bit. (although primarily for C64). Edited October 15, 2019 by jum 2 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted October 15, 2019 Share Posted October 15, 2019 46 minutes ago, jum said: Has anyone tried using Millfork language to compile something for the Lynx? A "middle-level programming language targeting 6502-based, 8080-based and Z80-based microcomputers." https://github.com/KarolS/millfork Readme says that it can target Atari Lynx and Atari 8-bit. (although primarily for C64). Funny. There is a Lynx example. Quote Link to comment Share on other sites More sharing options...
laoo Posted October 15, 2019 Share Posted October 15, 2019 I must say that I'm impressed by first look at this project ?. Great finding. 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted October 15, 2019 Share Posted October 15, 2019 7 minutes ago, laoo said: I must say that I'm impressed by first look at this project ?. Great finding. Copy that. Need to look at the generated code though. 1 Quote Link to comment Share on other sites More sharing options...
laoo Posted October 15, 2019 Share Posted October 15, 2019 (edited) 21 minutes ago, 42bs said: Copy that. Need to look at the generated code though. I've already done cursory inspection of generic example on atari 8, and it seems to be quite reasonable. Regarding competition I doubt that you can do any worse than cc65 though EDIT: I've attached a disassembly of the main loop of that generic example (excluding printing etc). fizzbuzz.txt Edited October 15, 2019 by laoo 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted October 15, 2019 Share Posted October 15, 2019 9 minutes ago, laoo said: I've already done cursory inspection of generic example on atari 8, and it seems to be quite reasonable. Regarding competition I doubt that you can do any worse than cc65 though EDIT: I've attached the disassembly main loop of that generic example (excluding printing etc) fizzbuzz.txt 4.02 kB · 2 downloads You can set "-s" to get directly assembly output (yes, just playing with it also). Tried the Lynx example and it works! 1 Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted October 16, 2019 Share Posted October 16, 2019 I found this nice article "New Frontiers in High-Level 6502 Programming" recently: http://8bitworkshop.com/blog/languages/2018/11/19/higher-level-6502-programming.html 2 Quote Link to comment Share on other sites More sharing options...
42bs Posted October 17, 2019 Share Posted October 17, 2019 For millfork the same rules apply as for cc65: Check the code and help the compiler to optimize: byte t sbyte c c = 31 do { palette_ram_green[t]=palette[c] c -= 1 } while ( c >= 0 ) asm { nop } for t,31,downto,0 { palette_ram_green[t]=palette[t] } asm { nop } Both versions do the same, but resulting code is different (NOPs inserted as separator only): NOP LDY #$1F .do__00010: LDA palette.array, Y STA $FDA0, X DEY BPL .do__00010 NOP LDX #$20 .do__00013: DEX LDA palette.array, X STA $FDA0, X TXA BNE .do__00013 NOP But not bad anyway. 1 Quote Link to comment Share on other sites More sharing options...
jum Posted October 17, 2019 Author Share Posted October 17, 2019 (edited) Would be nice to see a comparison with cc65 generated ASM. If I get a chance tonight I will do same code in cc65 and upload the asm generated. Also would need to expand the lynx lib/module for Millfork. Edited October 17, 2019 by jum Quote Link to comment Share on other sites More sharing options...
jum Posted October 17, 2019 Author Share Posted October 17, 2019 11 hours ago, Turbo Laser Lynx said: I found this nice article "New Frontiers in High-Level 6502 Programming" recently: http://8bitworkshop.com/blog/languages/2018/11/19/higher-level-6502-programming.html Love that 8bitworkshop web IDE ( https://8bitworkshop.com/v3.4.2/? ) 1 Quote Link to comment Share on other sites More sharing options...
jum Posted October 18, 2019 Author Share Posted October 18, 2019 OK here's the cc65 code and ASM output for comparison. Note I used the cc65 "-Or" optimisation flag to enable register variables: cc65 code: void main() { uchar i; asm("nop"); i = 31; do { MIKEY.palette[i] = work_palette[i]; i -= 1; } while ( i >= 0 ); asm("nop"); for (i = 0; i < 32; i++) MIKEY.palette[i] = work_palette[i]; asm("nop"); } Assembler output (.s file): ; --------------------------------------------------------------- ; void __near__ main (void) ; --------------------------------------------------------------- .segment "CODE" .proc _main: near .segment "CODE" jsr decsp1 nop lda #$1F L0060: sta (sp) ldx #$FD lda #$A0 clc adc (sp) bcc L0044 inx L0044: jsr pushax ldy #$02 lda (sp),y tay lda _work_palette,y ldy #$00 jsr staspidx lda (sp) sec sbc #$01 bra L0060 L005F: lda (sp) cmp #$20 bcs L004E ldx #$FD lda #$A0 clc adc (sp) bcc L0058 inx L0058: jsr pushax ldy #$02 lda (sp),y tay lda _work_palette,y ldy #$00 jsr staspidx lda (sp) ina sta (sp) bra L005F L004E: nop jmp incsp1 .endproc Way longer/slower (for this example), and very hard to follow! 2 Quote Link to comment Share on other sites More sharing options...
laoo Posted October 19, 2019 Share Posted October 19, 2019 (edited) 18 hours ago, jum said: OK here's the cc65 code and ASM output for comparison. Note I used the cc65 "-Or" optimisation flag to enable register variables: Are you sure it's an optimization option giving the best possible code? Because the output is terrible and I wonder how it can be even called an optimized code. I know cc65 is bad, but still... Nevertheless the guy responsible for this project is responsive and the compiler is in active development. I think it's worth investing as it might be very good alternative. Edited October 19, 2019 by laoo Quote Link to comment Share on other sites More sharing options...
+karri Posted October 19, 2019 Share Posted October 19, 2019 Really guys.... The correct way to write this code is: #include <lynx.h> #include <string.h> unsigned char work_palette[32]; void main() { asm("nop"); memcpy(MIKEY.palette, work_palette, sizeof(work_palette)); asm("nop"); } Which translates to: ; ; asm("nop"); ; nop ; ; memcpy(MIKEY.palette, work_palette, sizeof(work_palette)); ; ldy #$1F L0023: lda _work_palette,y sta $FDA0,y dey bpl L0023 ; ; asm("nop"); ; nop ; ; } ; The beauty of C is the use of standard library functions that make the work easier to understand and faster to execute. Quote Link to comment Share on other sites More sharing options...
laoo Posted October 19, 2019 Share Posted October 19, 2019 (edited) Imho it's not the case. This whole program is meaningless and "perfect" optimization should be something like ldx #$1F L0023: stz $FDA0,x dex bpl L0023 as the global array according to standard should be zeroed. The obvious meaning of this comparison is to... well... compare how the compiler handles the same code construct, in this instance two versions of loops. Not to find which standard function to use. Edited October 19, 2019 by laoo 1 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted October 19, 2019 Share Posted October 19, 2019 (edited) 23 hours ago, jum said: OK here's the cc65 code and ASM output for comparison. Note I used the cc65 "-Or" optimisation flag to enable register variables: cc65 code: void main() { uchar i; asm("nop"); i = 31; do { MIKEY.palette[i] = work_palette[i]; i -= 1; } while ( i >= 0 ); asm("nop"); for (i = 0; i < 32; i++) MIKEY.palette[i] = work_palette[i]; asm("nop"); } If MIKEY is a struct for all Mikey registers, then the comparison is not fair. But nevertheless, for this code construct, Millfork is the better compiler. BTW: Doesn't cc65 warn about the "i >= 0" comparison? Actually it should create an endless loop as 0 - 1 => 0xff which is >= 0 ! EDIT: Oh, it really does ? Edited October 19, 2019 by 42bs Quote Link to comment Share on other sites More sharing options...
jum Posted October 23, 2019 Author Share Posted October 23, 2019 On 10/19/2019 at 3:17 PM, karri said: Really guys.... The correct way to write this code is: "memcpy" Yes, that is true for this specific example, but only because you have optimised it, not the compiler. It's not a good example, maybe a better example is something like: for (i = 0; i < 32; i++) { B[i] = A[i] * 2 + 1; // some processing is happening, not just a memcpy } As said before, the point of the comparison is to see how the the 2 compilers handle the same code construct. Quote Link to comment Share on other sites More sharing options...
zbyti Posted September 16, 2020 Share Posted September 16, 2020 (edited) sorry, wrong forum, I meant: Edited September 16, 2020 by zbyti wrong forum Quote Link to comment Share on other sites More sharing options...
zbyti Posted September 16, 2020 Share Posted September 16, 2020 (edited) sorry, wrong forum again Edited September 16, 2020 by zbyti again ;( Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.