View unanswered posts | View active topics It is currently Sun Dec 16, 2018 4:48 am



Reply to topic  [ 77 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next
 Porting the C64 compiler to target OPC5 (or OPC6) 
Author Message

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
The compiler is now updated for OPC6. It spits out jsr's, pushes, pops and inc's / dec's.

I've just been eyeballing the output so far without actually running it through the assembler and simulator.

Dave, you're welcome to try the compiler at any time, but I don't guarantee the code will work. It might be a few days yet before I've run things in the simulator.
It's built on Windows as a console app using the MS Visual Studio 10 Express (free) edition. the target machine was set to X86. It looks like it might be a 32 bit app.
It also needs FPP.exe (or something called fpp.exe) which it shells out to perform the pre-processing.

_________________
Robert Finch http://www.finitron.ca


Thu Aug 03, 2017 8:01 am
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
Quote:
Have you, or anyone else, ever tried building FPP or C64 on Linux?

I've not tried building it in Linux. About the closest is Bloodshed and gcc IIRC. It should build without too many hiccups because it's a console app not a gui app and most of the code doesn't use any unusual features ( I believe it doesn't use .NET for instance). Some of the int types are defined in stdafx.h I think for building with gcc instead of MSC.
In stdafx.h:
Code:
#ifdef _MSC_VER
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int64 int64_t;

typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int64 uint64_t;
#else
#include <inttypes.h>
#endif

_________________
Robert Finch http://www.finitron.ca


Thu Aug 03, 2017 6:24 pm
Profile WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
I cleaned up some of the extra code that wasn't needed for OPC6.
Also "fixed" a bug having to do with multi-dimensional arrays.
Arrays with more than 4 dimensions are not supported. 4 dimensional array may not work, but there's code for it.
I'm pretty sure arrays of one and two dimension are working.

_________________
Robert Finch http://www.finitron.ca


Fri Aug 04, 2017 4:23 am
Profile WWW

Joined: Tue Feb 10, 2015 7:07 am
Posts: 50
Rob,
robfinch wrote:
I've not tried building it in Linux. About the closest is Bloodshed and gcc IIRC. It should build without too many hiccups because it's a console app not a gui app and most of the code doesn't use any unusual features ( I believe it doesn't use .NET for instance). Some of the int types are defined in stdafx.h I think for building with gcc instead of MSC.

I've been successful in building and running C64 on Linux:
Code:
dmb@quadhog:~/atom/robfinch/Cores/test$ ls -l
total 4
lrwxrwxrwx 1 dmb dmb 33 Aug  5 18:51 c64 -> ../software/C64 - OPC5/source/c64
lrwxrwxrwx 1 dmb dmb 23 Aug  5 18:51 fpp -> ../software/fpp/src/fpp
-rw-rw-r-- 1 dmb dmb 50 Aug  5 18:47 test.c

dmb@quadhog:~/atom/robfinch/Cores/test$ cat test.c
min(int a, int b) {
   return a < b ? a : b; 
}

dmb@quadhog:~/atom/robfinch/Cores/test$ c64 test.c

 -- 0 errors found.

dmb@quadhog:~/atom/robfinch/Cores/test$ ls -l
total 24
lrwxrwxrwx 1 dmb dmb   33 Aug  5 18:51 c64 -> ../software/C64 - OPC5/source/c64
lrwxrwxrwx 1 dmb dmb   23 Aug  5 18:51 fpp -> ../software/fpp/src/fpp
-rw-rw-r-- 1 dmb dmb   50 Aug  5 18:47 test.c
-rw-rw-r-- 1 dmb dmb 4828 Aug  5 19:13 test.c.xml
-rw-rw-r-- 1 dmb dmb   50 Aug  5 19:13 test.fpp
-rw-rw-r-- 1 dmb dmb  286 Aug  5 19:13 test.lis
-rw-rw-r-- 1 dmb dmb  358 Aug  5 19:13 test.s

dmb@quadhog:~/atom/robfinch/Cores/test$ cat test.s
#    code
_min:
                 push     r12
                 mov      r12,r14
                 ld       r1,r12,1
                 ld       r2,r12,2
                 cmp      r1,r2
              mi.inc      r15,test_4-PC
                 ld       r1,r12,1
                 inc      r15,test_5-PC
test_4:
                 ld       r1,r12,2
test_5:
                 mov      r14,r12
                 pop      r12
                 mov      r15,r13
#    rodata
#    extern    _min

I'll clean up my code and check it into a fork tomorrow so you can see what changes I have made.

One thing I really struggled with was the case of filenames, especially in the fpp source directory. I know in Windows this doesn't matter, but in Linux it does, and gcc assumes a file with a .C suffix is C++. Would it be a lot of trouble to rename these files? Anyway, let me check my changes into a fork tomorrow and you can see what I needed to do.

Dave


Sat Aug 05, 2017 8:46 pm
Profile

Joined: Tue Feb 10, 2015 7:07 am
Posts: 50
Hi Rob,

I've checked my changes that allow building with gcc into a fork (and I can generate a pull request when you are ready):
https://github.com/hoglet67/Cores/commits/OPC_gcc_fixes

Most of the changes are in a new file compat.h which provides static inline wrappers to non-standard MS library calls.

I've also added a Makefile, so to build all you need to is:
Code:
cd 'software/C64 - OPC5/source'
make clean c64

I followed your suggestion of using "cpp -P" as a preprocessor, so that avoided having to port FPP.

There are a few warnings that it would be nice to get rid of, so I can drop the -fpermissive flag. Log file attached.

A couple of things I wasn't sure about:

- I had some problems with duplicate definitions of OptimizationDesireability() - one in Analyze.cpp the other on OPC6.cpp. Is the one in Analyzer.cpp superfluous?

- There is a empty declaration of Statement in C.h that was also causing lots of warnings.

Both of these I effectively ifdefed out, but thought it best to check with you that's the right thing to do.

Dave


Attachments:
gcc.log [5.83 KiB]
Downloaded 138 times
Sun Aug 06, 2017 12:16 pm
Profile

Joined: Tue Feb 10, 2015 7:07 am
Posts: 50
Rob,

I have a couple of further questions...

1. Can you give me an example showing the correct syntax for the asm keyword?

2. I see in the generated code there are references to external functions like _mul, _mod, _div.

Is this the full list of these?
  • _mod
  • _modu
  • _div
  • _divu
  • _mul
  • _mulu
  • memcpy_
Do any of them exist yet?

Would they need to be need to be 32 bit?

3. Is there anything like libc (i.e. a standard library) for C64?

Dave


Sun Aug 06, 2017 1:29 pm
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
A sample of the asm keyword in use:
Quote:
int TestAsm(register int a, register int b)
{
asm __leafs {
push r8
push r9
jsr a_sub
inc r14,2
};
}

The __leafs is optional but it tells the compiler that the routine isn't a leaf routine. It should be used if there is a jsr to other code. Otherwise the compiler doesn't know to save and restore the link register. Note leading spaces are allowed. I see they've been eliminated for posting.

for _mod, _mul, _div etc. none of them exist yet.
They are currently expected to be 16 bit. _mulu is probably a priority as it's used to calculate array indexes.

There are a few simple functions collected in something called c64libc. It's just enough for some simple programs. I haven't ported over the standard C library yet. I will place them on GitHub, but they may be somewhat specific to a different processing core.

_________________
Robert Finch http://www.finitron.ca


Sun Aug 06, 2017 4:07 pm
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1030
hoglet wrote:
I've checked my changes that allow building with gcc into a fork (and I can generate a pull request when you are ready):
https://github.com/hoglet67/Cores/commits/OPC_gcc_fixes

Excellent! That doesn't seem too intrusive and is a big leap forward for those of us without Windows.


Mon Aug 07, 2017 10:14 am
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
Looks good to me. I've not handled a pull request before so I may be a bit sluggish on the uptake. I'm assuming a pull request will allow me to incorporate your changes. Please create a pull request.
One thing I changed was I got rid of the duplicate OptimizationDesirability() - moved it into a class method.

_________________
Robert Finch http://www.finitron.ca


Mon Aug 07, 2017 4:55 pm
Profile WWW

Joined: Tue Feb 10, 2015 7:07 am
Posts: 50
Rob,
robfinch wrote:
Looks good to me. I've not handled a pull request before so I may be a bit sluggish on the uptake. I'm assuming a pull request will allow me to incorporate your changes. Please create a pull request.
One thing I changed was I got rid of the duplicate OptimizationDesirability() - moved it into a class method.

I've updated and retested my patch against your latest code (as things have moved on and there were conflicts....)

You should now see a pull request:
https://github.com/robfinch/Cores/pull/1

At the moment it will clean merge, as I just rebased it off you latest master.

Separately, I am now seeing a line ending issue with the following files, which makes them look like they are always modified locally:
Code:
   software/C64 - OPC5/test/ClassTest.cpp.xml
   software/C64 - OPC5/test/ClassTest.s
   software/C64 - OPC5/test/TestArrayAssign.s
   software/C64 - OPC5/test/TestFor.s
   software/C64 - OPC5/test/TestFunccall.s


Can you see anything wrong with them at your end?

Edit: It looks like these files have managed to get checked in with CRLF terminators, where as all the others have been normalized.

This is unrelated to my changes as far as I can tell.

Dave


Mon Aug 07, 2017 6:10 pm
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
I've merged the changes into the base code. It rebuilds fine in VS10 express too.
I'll go through the code and convert any CRLF pairs into just LF's just to be safe. DOS days are long gone.

_________________
Robert Finch http://www.finitron.ca


Mon Aug 07, 2017 9:55 pm
Profile WWW

Joined: Tue Feb 10, 2015 7:07 am
Posts: 50
Hi Rob,

I'm in the process of testing the output of the C Compiler, with the goal of seeing if I can actually get a small piece of C to run on some real hardware. I thought I would use this post to log issues as I encounter them. I'll edit this post as I discover issues.

Note, these are not necessarily compiler issues. It may be the correct solution is to extend the assembler.

Issues:

1. Push/Pop don't assemble

Currently:
Code:
    push    r13
    ...
    pop     r13

Should be:
Code:
    push    r13, r14
    ...
    pop     r13, r14

(i.e. the register being used as the stack pointer, by convention r14, needs to be made explicit)

2. align pseudo-op does not exist (and probably isn't needed in OPC)

3. word pseudo-op should be WORD (i.e. upper case)

4. Incorrect code generation - the first character of the string is missed
Code:
void print(char *ptr) {
   while (*ptr) {
      outch(*ptr++);
   }
}

Code:
010d                        _print:
010d  28ed                                 push    r13,r14
010e  28ec                                 push    r12,r14
010f  00ec                                 mov     r12,r14
0110                        test_12:
0110  17c5 0002                            ld      r5,r12,2
0112  0755                                 ld      r5,r5
0113  0405                                 add     r5,r0
0114  4cef                               z.inc     r15,test_13-PC
0115  17c5 0002                            ld      r5,r12,2            # ptr++ is happening too early
0117  0c15                                 inc     r5,1
0118  16c5 0002                            sto     r5,r12,2
011a  17c5 0002                            ld      r5,r12,2
011c  0755                                 ld      r5,r5
011d  28e5                                 push    r5,r14
011e  190d 0106                            jsr     r13,r0,_outch
0120  0c1e                                 inc     r14,1
0121  100f 0110                            mov     r15,r0,test_12
0123                        test_13:
0123  00ce                                 mov     r14,r12
0124  29ec                                 pop     r12,r14
0125  29ed                                 pop     r13,r14
0126  00df                                 mov     r15,r13


5. Incorrect code generation - nothing is output
Code:
void print(char *ptr) {
   while (*ptr) {
      outch(*ptr);
      ptr++;
   }
}
void main() {
   print("Hello world\r\n");
}

Code:
010d                        _print:
010d  28ed                                 push    r13,r14
010e  28e3                                 push    r3,r14
010f                        test_12:
010f  0735                                 ld      r5,r3              # r3 doesn't contain anything at this point
0110  0405                                 add     r5,r0
0111  4c7f                               z.inc     r15,test_13-PC
0112  0735                                 ld      r5,r3
0113  28e5                                 push    r5,r14
0114  190d 0106                            jsr     r13,r0,_outch
0116  0c1e                                 inc     r14,1
0117  0c13                                 inc     r3,1
0118  -091                                 dec     r15,test_12-PC
0119                        test_13:
0119  29e3                                 pop     r3,r14
011a  29ed                                 pop     r13,r14
011b  00df                                 mov     r15,r13
011c                        _main:
011c  28ed                                 push    r13,r14
011d  1005 0125                            mov     r5,r0,test_15
011f  28e5                                 push    r5,r14
0120  190d 010d                            jsr     r13,r0,_print
0122  0c1e                                 inc     r14,1
0123  29ed                                 pop     r13,r14
0124  00df                                 mov     r15,r13


6. Assembler bug in the above code at address 0118:
Looking at the above assembler listing, it appears the assembler has barfed at 0118:
Code:
0118  -091                                 dec     r15,test_12-PC

What's actually been placed in memory is:
Code:
>> dis 110
0118 0912      : jsr r2, r1

I think what's happening here is that test_12-PC is negative, and this is confusing the assembler.

I think the correct results are obtained with:
Code:
0118  0eaf                                 inc     r15,test_12-PC

i.e. the assembler has noticed the negative offset and switched the opcode to dec:
Code:
>> dis 110
0118 0eaf       : dec r15, 10

Honestly I'm not sure if this is a compiler bug, an assembler bug or both!

7. Trailing ,r0 is sometimes omitted
Code:
int bug7(int d) {
   return (d / 1000) % 10;
}

Code:
_bug7:
               push    r12
               mov     r12,r14
               ld      r6,r12,1
               mov     r1,r6
               mov     r2              # error here
               push    r3
               push    r4
               mov     r3,1000
               mov     r4              # error here
               jsr     r13,r0,__div32
               pop     r4
               pop     r3
               mov     r5,r1
               mov                         # error here
               mov     r1,r5,0
               mov     r2,r0,10
               mov     r13,r15,2
               jsr     r13,r0,__mod
               mov     r14,r12
               pop     r12
               mov     r15,r13

8. Failing to save link register (r13) when using built-in functions like _mul
Code:
int bug8(int a, int b) {
   return a*b;
}

Code:
_bug8:
               push    r12
               mov     r12,r14
               ld      r5,r12,1
               ld      r6,r12,2
               mov     r1,r5
               mov     r2,r6
               jsr     r13,r0,__mul    # r13 used but not saved
               mov     r14,r12
               pop     r12
               mov     r15,r13

9. Sometimes dec is used for loops with too large an offset
Quote:
while (nines)
{
putchar('0');
nines--;
}

Code:
pi_32:
               ld      r5,r12,-4
               add     r5,r0
             z.inc     r15,pi_33-PC
               mov     r5,r0,48
               push    r5,r14
               jsr     r13,r0,_putchar
               inc     r14,1
               ld      r5,r12,-4
               dec     r5,1
               sto     r5,r12,-4
               dec     r15,pi_32-PC      # offset here here is

10. Array writing using wrong register
Code:
#define LEN 333
void bug10() {
   int x;
   int pi[LEN + 1];
   for (x = LEN; x > 0; x--) {
      pi[x] = 2;
   }
}

Code:
_bug10:
               push    r12
               mov     r12,r14
               sub     r14,r0,335
               push    r3
               mov     r3,r0,333
bug10_4:
               cmp     r3,r0
            mi.inc     r15,bug10_5-PC
               cmp     r3,r0
             z.inc     r15,bug10_5-PC
               mov     r1,r12,-335
               mov     r5,r3
               add     r3,r1      # should used r5 not r3
               mov     r1,r0,2
               sto     r1,r3      # should used r5 not r3
               dec     r3,1
               dec     r15,bug10_4-PC
bug10_5:
               pop     r3
               mov     r14,r12
               pop     r12
               mov     r15,r13

Dave


Thu Aug 10, 2017 11:13 am
Profile

Joined: Tue Apr 25, 2017 7:33 pm
Posts: 23
On Number 6 above ...

Quote:
Looking at the above assembler listing, it appears the assembler has barfed at 0118:

0118 -091 dec r15,test_12-PC

What's actually been placed in memory is:

>> dis 110
0118 0912 : jsr r2, r1

I think what's happening here is that test_12-PC is negative, and this is confusing the assembler.

I think the correct results are obtained with:

0118 0eaf inc r15,test_12-PC



... Dave is right, of course. Originally only positive offsets were legal for both inc and dec operations, and error checking was lamentably absent. I updated only inc to be able to take positive and negative values thinking that there was no longer a need to ever use dec in assembly source, but I've now corrected that. In the latest version on GitHub you can use either inc or dec with an offset in the range -15 ..+15 and the assembler will switch the instruction as required. So, no compiler changes here and just look on it as an assembler bug which is fixed now.

R


Thu Aug 10, 2017 7:57 pm
Profile

Joined: Tue Feb 10, 2015 7:07 am
Posts: 50
Revaldinho wrote:
... Dave is right, of course. Originally only positive offsets were legal for both inc and dec operations, and error checking was lamentably absent. I updated only inc to be able to take positive and negative values thinking that there was no longer a need to every use dec in assembly source, but I've now corrected that. In the latest version on GitHub you can use either inc or dec with an offset in the range -15 ..+15 and the assembler will switch the instruction as required. So, no compiler changes here and just look on it as an assembler bug which is fixed now.

Actually, I think a compiler change is needed as well.

Consider:
Code:
dec r15,test_12-PC

This is a backwards branch, yet test_12-PC is negative.

I think the compiler should emit:
Code:
inc r15,test_12-PC

or
Code:
dec r15,PC-test_12

Rob, we are making excellent progress here. Most of these issues are very localized to the Code Generation, and should be easy to resolve. This is all very cool indeed!

Dave


Thu Aug 10, 2017 8:07 pm
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 729
Location: Canada
Okay, I have updated the compiler. I got little side-tracked trying to add a color-graphing register allocator. It's just a bit too complex for me to understand :) So I've been researching and scratching my head.

Bug #4 isn't fixed yet. It maybe an issue with the 'C' standard. 'C' does not guarantee the order in which the auto-inc and auto-dec operations take place. Different compilers support them differently.
If one does something like p[ndx++] the index may be updated either before or after it's used to index the element depending on the compiler. I think not even brackets are respected.
When I found this out I started writing all the inc/dec operations as separate instructions with a semi-colon. So I write
p[ndx]; ndx++;
to guarantee the order and it's portable between compilers. (Yes I got burned on this issue before).

Something like the example isn't guaranteed to work in the order one expects.

I will have a look at it however.

_________________
Robert Finch http://www.finitron.ca


Fri Aug 11, 2017 8:36 am
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 77 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software