Jump to content


New Members
  • Content Count

  • Joined

  • Last visited

Everything posted by JesperGravgaard

  1. Hi, The author of KickC here. @ivop and @ilmenit are correct that the goal is not to be a drop-in replacement for cc65. What I really want to create is a compiler that allows a programmer who knows C an easy way to get started on any 6502-platform, to be able to create C-programs that runs as fast or faster than naively coded ASM, and finally to be able to seamlessly switch to optimized ASM for any performance-critical parts. The semi-prioritized goals of KickC could be stated as: 1) Generate optimized and readable 6502-family ASM. 2) Support different existing 6502-based hardware platforms. 3) Allow the programmer to utilize the strength of KickAsm. 4) Be standard C compatible. However, it would be great if porting CC65 programs to KickC was pretty easy to do. For instance CC65 and KickC can and should have a bunch of libraries that are compatible. An existing example of this is the <conio.h> library. If anyone wants to contribute an implementation of <fcnlt.h> or any other standard C / cc65 library for Atari 8bit I will gladly merge it into the KickC master and include it in future releases. Feel free to reach out to me with any questions. /Jesper
  2. KickC version 0.8.5 adds a number of improvements and new features. Of specific interest for the Atari 8bit it adds support for creating "real" XEX-files with multiple segments - supporting both run-address and init-addresses. This is achieved through a new KickAss linker plugin https://gitlab.com/jespergravgaard/kickass-plugin-atari-xex. The plug-in was developed in cooperation with @fenrock Get the new release here: https://gitlab.com/camelot/kickc/-/releases
  3. None of those LAXes are opcode $AB LAX #IMM. They will become $A7 LAX ZP or $AF LAX ABS. The AXS #IMM will become a $CB SBX #IMM. Neither of these are marked as unstable in https://xxl.atari.pl/sally-6502c/, so these fragments should not present any problem
  4. @fenrock Very nice table! However, I have looked through all the compiler fragments, and I cannot find any fragments in the compiler using LAX #n. Could you point me towards the 2 fragments you have found? I have looked through several articles on the illegal opcodes. There are several (old) articles that have contradictory information about how they work. Some of the best sources I could find are http://visual6502.org/wiki/index.php?title=6502_Unsupported_Opcodes and http://www.oxyron.de/html/opcodes02.html. I have so far never seen well-documented examples of undocumented opcodes that work differently on different CPU's. Are you certain that any of the codes on SALLY actually works differently from an original MOS 6502? If anyone has confirmed this I would love a link to more information! My understanding so far is that all the CPU's where the undocumented opcodes work actually contain an almost exact copy of the original MOS 6502 core (transistor by transistor). See for instance this die shot of a NES RP2A, where you can see the 6502 core in the lower right corner http://www.visual6502.org/images/pages/Nintendo_RP2A_die_shots.html. Here is an original 6502 die shot to compare with http://www.visual6502.org/images/6502/index.html. A die shot of SALLY is on their TODO-list - so when that arrives we can check it out
  5. @Dmitry From the ASM fragment you posted it seems the code continues at label __b99 (elsewhere in the ASM-file). Here I would expect the AF2-comparison. So to understand the problem you are experiencing I would need to se more of the resulting ASM-file. Also, the compiler can detect code that is never run - and remove it. For instance if your AF3 is constant !=0 and <=56 then the compiler will delete the body of the if(). So to understand your problem completely it would also be necessary to see more of the C-file. If you can share more details with me I would love to understand your problem, and if there is an error in the compiler I will of course fix it! /Jesper
  6. I just had a go at https://adventofcode.com/ . That looks like a lot of fun! I solved the first challenges in KickC running on Atari 8bit
  7. @fenrock That is a very nice demonstration of the new XEX format! The next release of KickC will include this linker plugin to make it easier to create better XEX files directly from KickC. If anyone want to use it before it is released officially it is always possible to download the newest master build from https://gitlab.com/camelot/kickc
  8. This is how I usually initialize a char[] to the contents of a binary file. export char TILES[] = kickasm(resource "smb1_chr.bin") {{ .import binary "smb1_chr.bin" }}; If you know the size of the file to be 3840 you can help the compiler by specifying that export char DATA[3840] = ... A final note: The export keyword is not needed if your code uses the DATA array. It is only needed if you want to include the data in your program even if the code does not use it.
  9. @Gury You have found a bug in the current version of KickC! The code loading source files looks through a list of search folders - but does not consider that the file name may be absolute. I have fixed it, and the fix will be in the next release. https://gitlab.com/camelot/kickc/-/issues/576 Thank you for finding the problem!
  10. I have created a KickAssembler plugin to support the XEX file format. You can get that here if you like to code code ASM: https://gitlab.com/jespergravgaard/kickass-plugin-atari-xex I have also integrated the plugin into KickC. So in the next release KickC will be able to create XEX-files where each memory block is stored as a seperate segment in the XEX-file. This will help you to get smaller XEX-files if you for instance have some code in $1000 and some data in $3000 with an empty gap in between.
  11. I really like the Mad Pascal benchmark suite! The different tests examine different aspects of the language nicely. However, I am somewhat unsure in which tests "higher is better" and in which "lower is better". Is there a list showing this somewhere, that I have missed? @zbyti maybe you can point me in the right direction.
  12. @Blues76 Here are some of the differences. The most significant difference is the modern compiler optimization techniques KickC uses to generate fast ASM from your C-code. A second difference is that KickC can generate very small binaries, since it only includes code for the functions that are actually used. This includes functions in libraries. If you include a library and only use a single function the compiler will only generate ASM for that one function. It even optimizes the library functions based on the parameters you pass, so if you only call the library function once or always pass the same parameters it will optimize the ASM based on the constant parameter. A third difference is that the generated ASM is very readable, so you can directly compare your C-program to the ASM it generates. As an example This C-code: https://gitlab.com/camelot/kickc/-/blob/master/src/test/kc/examples/atarixl/rasterbars.c compiles to this ASM-code: https://gitlab.com/camelot/kickc/-/blob/master/src/test/ref/examples/atarixl/rasterbars.asm A minor difference is the ability to initialize data structures using inline KickAssembler macro code. Kick Assembler has a great macro language, so this allows for very easy initialization of look-up tables. char SINTABLE[0x100] = kickasm {{ .fill $100, round(127.5+127.5*sin(2*PI*i/256)) }}; CC65 on the other hand is a lot more mature than KickC. It very rarely fails. It has better library support. There are more examples and information available online.
  13. @fenrockKickC already supports putting functions into different named segments using #pragma code_seg(name). Here is a tiny example where the main() function is in the default "Code" segment and the fillscreen() function in the "CodeHigh" segment. https://gitlab.com/camelot/kickc/-/blob/master/src/test/kc/examples/linking/linking.c You can also choose which segment data ends up in using #pragma data_seg(name)
  14. Thank you for the suggestions @ivop I do plan to change align() to __align()in a future release. Most of the other non-standard modifiers already use the __ prefix. https://gitlab.com/camelot/kickc/-/issues/572 I also have a plan for better support for "empty" data structures, which currently generates zeros into the binary file. https://gitlab.com/camelot/kickc/-/issues/545 The Atari 8bit-platform XEX-format is unique in supporting multiple memory segments in a single binary file. It is currently possible to write your own linker definition in KickC, and by doing that and using #pragma data_seg() / #pragma code_seg() you can generate XEX-files with multiple segments. Maybe I could find a way for the compiler to automatically generate the linker configuration needed for creating a XEX-file with multiple segments. However, I have not currently planned that feature, since I am unsure how I can find a good general solution for adding it. /Jesper
  15. KickC tries to optimize the code as well as it can by analyzing the code thoroughly to identify variables that are actually constants. One of the methods is uses is converting the entire program to single static assignment form, which effectively changes the program (by introducing new variables) to ensure that each variable is only assigned once. This makes the compiler quite good at constant detection. However, it will compile faster and leave less room for mistakes if the programmer marks pointers as constant. Also @ivop has a point on creating portable code. Even with the best current compiler methods, nothing beats a programmer that has a thorough look at the code and rewrites it to achieve optimal performance.
  16. Hi everyone, A new version of KickC has just been released. This release adds conio.h support for Atari XL/XE and improves conio.h on Commodore platforms. It fixes a lot of bugs and and adds a lot of new/improved ASM fragments. https://gitlab.com/camelot/kickc/-/releases The new version also compiles the awesome benchmarks created by @fenrock out-of-the-box. https://github.com/markjfisher/kickc-benchmarks A huge thanks to all of you who have tried out KickC and given feedback, suggestions and questions!
  17. I will try to make a new release with the changes that have been merged before next monday. I will make a post on the forum when it is available. If anyone is impatient and dare to run stuff on the current unreleased "master" it is pretty easy to download the source code and compile KickC. See https://gitlab.com/camelot/kickc/-/blob/master/CONTRIBUTING.md
  18. That is very nice!! It will serve as a good test bench when optimizing the KickC compiler.
  19. I honestly did not really consider portability from cc65's library when creating the headers. I made a quick check, and it seems the macro-based solution above generates the same ASM as the current pointer-to-struct solution. So it would probably be possible to make the chipset headers more portable by using the same member names and using a macro instead the pointer-to-struct. The lack of unions in the current version of kickc may result in some compatibility issues - if the cc65 structs utilize unions. If anyone here in the forum want to have a go at creating the header-files I will gladly merge them into kickc. In any case I will add a TODO to my list.
  20. The C standard is pretty clear that the signedness of char is implementation dependant. See for instance A.4.2 in https://xuron.com/uploads/Kernighan_Ritchie_Language_C.pdf The 6502 CPU is better at performing unsigned numeric operations than is it at at signed numeric operations. This is especially true for comparisons. Try looking at section 5 in http://www.6502.org/tutorials/compare_beyond.html This is the reason I decided that a C-compiler targetting the 6502 platform should have unsigned char as the default. The aim of the compiler is to help people create C-code that runs as fast as possible on the 6502, and unsigned chars run faster than signed chars. So I felt unsigned was the best default. The authors of cc65 seems to have made the same choice. /Jesper
  21. The headers for the ATARI chipset included in the KickC release is based on pointers to structs. // Atari GTIA write registers struct ATARI_GTIA_WRITE * const GTIA = 0xd000; The compiler recognizes that GTIA->GRACTL is in fact a static address and generates code poking directly to that. The struct-based approach was primarily chosen because I prefer the registers of each chip grouped together and I like that is is clear that code is addressing a register a specific chip. Some editors also offer code completion after you have entered GTIA-> which helps find the register you are looking for. The struct in the header-file also serves as a place to dump a little documentation describing each register. See https://gitlab.com/camelot/kickc/-/blob/master/src/main/kc/include/atari-gtia.h If you prefer a different notation it is pretty easy to create another header-file supporting that.
  22. Thank you @fenrock ! I will be merging your conio.c implementation into KickC master, and it will be included in the next release.
  23. @fenrock These are the 2 files you need: https://gitlab.com/camelot/kickc/-/blob/master/src/main/fragment/mos6502-common/_deref_pwuc1=vbuaa.asm https://gitlab.com/camelot/kickc/-/blob/master/src/main/fragment/mos6502-common/_deref_pwuc1=_word_vbuaa.asm
  24. @fenrock You probably want something like the following code then. Notice that SAVMSC is now a pointer to a pointer (char**). char * const ROWCRS = 0x54; // Row on the screen that the cursor is currently on word * const COLCRS = 0x55; // Column that the cursor is on, ranging from 0 to 319. char ** const SAVMSC = 0x58; // The lowest address of the screen memory, corresponding to the upper left corner of the screen void main() { char* cursor = *SAVMSC + (word)*ROWCRS*40 + *COLCRS; *cursor = 'x'; }
  25. @fenrock You have found a bug! It affects address-of, when used on some expressions. This forced the compiler has to create an anonymous variable to hold the value to be able to get a pointer - and this then fails for some expressions. I will make a fix ASAP https://gitlab.com/camelot/kickc/-/issues/536 You are welcome to continue posting here. You can also report any problems directly into the KickC issue tracker if you prefer that. In the meantime the following works because w3 is now a "normal" named variable. word w3 = *SAVMSC + (word)(*ROWCRS)*40 + *COLCRS; word *wp3 = &w3;
  • Create New...