Last visit was: Sat Dec 21, 2024 2:24 pm
It is currently Sat Dec 21, 2024 2:24 pm



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

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1808
I wonder if, for clarity, we could write
Code:
memory store  -  sto rdest, rsrc, imm       -   mem(rsrc + imm) <- rdest
as
Code:
memory store  -  sto rdata, raddress, imm   -   mem(raddress + imm) <- rdata


(I'm not sure!)


Tue Aug 15, 2017 5:46 pm

Joined: Tue Apr 25, 2017 7:33 pm
Posts: 32
Well, I still slightly prefer the original in the spec but only because in the context of the whole instruction table it's clear that very nearly all instructions perform the same effective data/address calculation.

Something else which is also becoming clear though is that we could do with more documentation, maybe in a tutorial style, on top of the original one page spec. :)

R


Tue Aug 15, 2017 6:02 pm

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1808
Indeed! The oddity with store is that the LHS register is a source, which is different from all others. I know why that is, and it's not too much of a cognitive load, but if there's a way to make it less surprising that would be nice.


Tue Aug 15, 2017 6:04 pm

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2231
Location: Canada
The compiler was failing to initialize the temporaries properly after changing it to be two pass.
It decided to load the address of the putchar() routine into a register because it was used so many times, but then didn't load the register with the putchar() address.

'C' doesn't have a way to represent an I/O address versus a memory address. If it did the compiler could output in / out instructions instead of ld / sto.
I've been trying to think of an easy way to specify I/O in C64. There is the volatile keyword, but perhaps another keyword for I/O is in order. The current means of handling I/O in C is to use function calls that implement the I/O instructions.
'io' is too short of a keyword and likely used already by C programs. Although '__io' would be okay. (Double underscore names are reserved for the compiler).
It's really for the address calculation when pointers are used. The '&' operator return the address of a variable.

Declaring something like:
__io char *ptr;
Would tell the compiler ptr points to I/O and not memory.

The other issue with I/O is fixing the I/O address associated with a variable.
It would be nice to be able to specify something like:
__io screenbuf[2000] at 0xa000

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


Tue Aug 15, 2017 7:43 pm WWW

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

Thanks for the speedy update. That has fixed math16.c.

But pi is still not working.

The first error I spotted is with:
Code:
         x = 10 * pi[i]+ q * i;

Code:
018f  10c6 fea9                            mov     r6,r12,-343
0191  0035                                 mov     r5,r3
0192  0465                                 add     r5,r6
0193  0051                                 mov     r1,r5        # should be ld r1, r5
0194  1002 000a                            mov     r2,r0,10
0196  190d 0332                            jsr     r13,r0,__mul
0198  0015                                 mov     r5,r1
0199  17c1 fffa                            ld      r1,r12,-6
019b  0032                                 mov     r2,r3
019c  190d 0332                            jsr     r13,r0,__mul
019e  0016                                 mov     r6,r1
019f  0051                                 mov     r1,r5
01a0  0461                                 add     r1,r6
01a1  0015                                 mov     r5,r1
01a2  0054                                 mov     r4,r5

Separately, there is an issue in math32.c with setting the MS word of a 32-bit variable.
Code:
void init() {
   asm  {
      ORG 0x100
      mov  r15, r0, _main
   };
}

void putchar(char c) {
   asm __leafs {
      ld  r1, r14, 1
      jsr r13, r0, 0xffee
   };
}

void main() {
   long a,b,c,d,e;
   a = 123456L;
   b = 1234L;
   c = a * b;
   if (c == 0x9149880) {
      putchar('.');
   } else {
      putchar('x');
   }
   d = a / b;
   if (d == 100) {
      putchar('.');
   } else {
      putchar('x');
   }
   e = a % b;
   if (e == 56) {
      putchar('.');
   } else {
      putchar('x');
   }
   putchar(10);
   putchar(13);
}

Code:
010a                        _main:
010a  28ed                                 push    r13,r14
010b  28ec                                 push    r12,r14
010c  00ec                                 mov     r12,r14
010d  0eee                                 dec     r14,14
010e  1005 e240                            mov     r5,r0,57920
0110  1006 0000                            mov     r6,r0,r0            # malformed, should be mov r6, r0, 1
0112  16c5 fffe                            sto     r5,r12,-2
0114  16c6 ffff                            sto     r6,r12,-1
0116  1005 04d2                            mov     r5,r0,1234
0118  1006 0000                            mov     r6,r0,r0            # malformed, should be mov r6, r0
011a  16c5 fffc                            sto     r5,r12,-4
011c  16c6 fffd                            sto     r6,r12,-3

Dave


Tue Aug 15, 2017 8:32 pm

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

I've just re-tested the latest compiler (git commit 73c5ce2):
- Pi is working
- Math16 is working
- Math32 is failing at one of the 32-bit compares:

Code:
   d = a / b;
   if (d == 100) {
      putchar('.');
   } else {
      putchar('x');
   }

Code:
0148  17c1 fffe                            ld           r1,r12,-2
014a  17c2 ffff                            ld           r2,r12,-1
014c  28e3                                 push         r3,r14
014d  28e4                                 push         r4,r14
014e  17c3 fffc                            ld           r3,r12,-4
0150  17c4 fffd                            ld           r4,r12,-3
0152  190d 0289                            jsr          r13,r0,__div32
0154  29e4                                 pop          r4,r14
0155  29e3                                 pop          r3,r14
0156  0015                                 mov          r5,r1
0157  0026                                 mov          r6,r2
0158  16c5 fff8                            sto          r5,r12,-8
015a  16c6 fff9                            sto          r6,r12,-7
015c  17c6 fff9                            ld           r6,r12,-7
015e  17c5 fff8                            ld           r5,r12,-8
0160  1004 0064                            mov          r4,r0,100
0162  0008                                 mov          r8,r0       # r8 is never used
0163  0049                                 mov          r9,r4       # r9 is never used
0164  0005                                 mov          r5,r0       # ??? r5 is over-written here
0165  0204                                 or           r4,r0       # ???
0166  d005 ffff                         mi.mov          r5,r0,-1    # ???
0168  2a75                                 cmp          r5,r7       # seems like r7 is incorrect
0169  2b36                                 cmpc         r6,r3       # seems like r3 is incorrect
016a  6c7f                              nz.inc          r15,math32_32-PC
016b  1005 002e                            mov          r5,r0,46
016d  28e5                                 push         r5,r14
016e  190d 0103                            jsr          r13,r0,_putchar
0170  0c1e                                 inc          r14,1
0171  0c6f                                 inc          r15,math32_33-PC
0172                        math32_32:
0172  1005 0078                            mov          r5,r0,120
0174  28e5                                 push         r5,r14
0175  190d 0103                            jsr          r13,r0,_putchar
0177  0c1e                                 inc          r14,1
0178                        math32_33:

All the programs I'm testing with are here:
https://github.com/hoglet67/opc/tree/c_ ... i-spigot-c

Dave


Wed Aug 16, 2017 8:17 am

Joined: Tue Feb 10, 2015 7:07 am
Posts: 52
One more thing... if use long instead of int in the pi test program I get a core dump:
Code:
dmb@quadhog:~/atom/opc/examples/pi-spigot-c$ ./c64 pi.c
Segmentation fault (core dumped)

dmb@quadhog:~/atom/opc/examples/pi-spigot-c$ gdb ./c64 core
Core was generated by `./c64 pi.c'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x08078ab7 in copy_addr (ap=0x807b427 <ZeroMemory(void*, size_t)+32>) at Peepgen.cpp:53
53                      if (ap->offset->nodetype==en_icon) {
(gdb) bt
#0  0x08078ab7 in copy_addr (ap=0x807b427 <ZeroMemory(void*, size_t)+32>) at Peepgen.cpp:53
#1  0x08078e35 in GenerateDiadic (op=7, len=0, ap1=0xa3c88bc, ap2=0x807b427 <ZeroMemory(void*, size_t)+32>) at Peepgen.cpp:144
#2  0x0804cb7b in GenStore (ap1=0x807b427 <ZeroMemory(void*, size_t)+32>, ap3=0xa3c875c, size=2) at CodeGenerator.cpp:448
#3  0x08052bfb in GenerateAssignModiv (node=0xa3c536c, flags=33807, size=2) at CodeGenerator.cpp:2122
#4  0x080551be in GenerateExpression (node=0xa3c536c, flags=33807, size=2) at CodeGenerator.cpp:2937
#5  0x0805b7a8 in Statement::Generate (this=0xa3c1f84) at GenerateStatement.cpp:742
#6  0x0805b62e in Statement::GenerateCompound (this=0xa3c1d44) at GenerateStatement.cpp:677
#7  0x0805b700 in Statement::Generate (this=0xa3c1d44) at GenerateStatement.cpp:713
#8  0x08059e5d in Statement::GenerateWhile (this=0xa3c1c84) at GenerateStatement.cpp:193
#9  0x0805b816 in Statement::Generate (this=0xa3c1c84) at GenerateStatement.cpp:761
#10 0x0805b62e in Statement::GenerateCompound (this=0xa3c1b04) at GenerateStatement.cpp:677
#11 0x0805b700 in Statement::Generate (this=0xa3c1b04) at GenerateStatement.cpp:713
#12 0x0806352f in GenerateFunction (sym=0x80a153c <compiler+42652>) at OPC6.cpp:560
#13 0x08076428 in ParseFunctionBody (sp=0x80a153c <compiler+42652>) at ParseFunction.cpp:478
#14 0x08075dbe in ParseFunction (sp=0x80a153c <compiler+42652>) at ParseFunction.cpp:340
#15 0x0806bfd5 in Declaration::declare (parent=0x0, table=0x8095180 <gsyms>, al=2, ilc=0, ztype=28) at ParseDeclarations.cpp:1391
#16 0x0806c590 in GlobalDeclaration::Parse (this=0xa3bda44) at ParseDeclarations.cpp:1533
#17 0x0805632f in Compiler::compile (this=0x8096ea0 <compiler>) at Compiler.cpp:104
#18 0x0804b773 in main (argc=1, argv=0xbf961128) at Cmain.cpp:83
(gdb) p ap
$1 = (AMODE *) 0x807b427 <ZeroMemory(void*, size_t)+32>
(gdb) p ap->offset
$2 = (ENODE *) 0x875cf
(gdb) p ap->offset->nodetype
Cannot access memory at address 0x875cf
(gdb)


Wed Aug 16, 2017 8:20 am

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2231
Location: Canada
Fixed the crash in the assign divide logic.
Fixed the long compare.
Redundant sign extension of immediate values was removed.
For long math if a an 'L' is not specified after a constant number it may cause more code to be generated. (It loads the constant into a reg rather than using it directly sometimes).

Long math is still broken if no_regs is specified for the routine and the compiler uses memory variables. The compiler needs to be coded to access memory in an indirect fashion because a pointer to a value is stored in a memory location instead of in a register.

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


Thu Aug 17, 2017 2:50 am WWW

Joined: Tue Feb 10, 2015 7:07 am
Posts: 52
robfinch wrote:
Fixed the crash in the assign divide logic.
Fixed the long compare.
Redundant sign extension of immediate values was removed.
For long math if a an 'L' is not specified after a constant number it may cause more code to be generated. (It loads the constant into a reg rather than using it directly sometimes).

With these fixes, all three of my test programs are now working. Well done!
- math16
- math32
- pi
robfinch wrote:
Long math is still broken if no_regs is specified for the routine and the compiler uses memory variables. The compiler needs to be coded to access memory in an indirect fashion because a pointer to a value is stored in a memory location instead of in a register.

The only remaining issue I'm currently seeing is if I compile pi using "long" instead of "int" as the main type, I'm getting malformed assembler. I'm not sure if this is a manifestation of the same issue you mention above, or something else.

Here's a smaller example of the same:
Code:
#define SCALE 10000L

void putchar(char c) {
   asm __leafs {
      ld  r1, r14, 1
      jsr r13, r0, 0xffee
   };
}

void bug21(long i) {
   long d = SCALE / 10L;
   while (d) {
      long c = (i / d);
      putchar(48 + c % 10);
      d /= 10L;
   }
}

Code:
_bug21:
               push    r13,r14
               push    r12,r14
               mov     r12,r14
               dec     r14,8
               mov     r5,r0,1000
               mov     r6,r0
               sto     r5,r12,-2
               sto     r6,r12,-1
bug21_18:
               ld      r6,r12,-1
               ld      r5,r12,-2
               add     r5,r0
             z.mov     r15,r0,bug21_19
               ld      r1,r12,2
               ld      r2,r12,-2
               jsr     r13,r0,__div
               mov     r5,r1
               sto     r5,r12,-4
               sto 
               mov     r5,r0,48
               mov     r6,r0
               mov     r7,r0,10
               mov     r3,r0
               ld      r1,r12,-4
               mov     r2,r7
               jsr     r13,r0,__mod
               mov     r7,r1
               mov     r1,r5
               add     r1,r7
               mov     r5,r1
               push    r5,r14
               jsr     r13,r0,_putchar
               inc     r14,1
               ld      r6,r12,-1
               ld      r5,r12,-2
               mov     r1,r5
               mov     r2,r6
               push    r3,r14
               push    r4,r14
               mov     r3,r0,10
               mov     r4,r0
               jsr     r13,r0,__div32
               pop     r4,r14
               pop     r3,r14
               sto     r1,r12,-2
               sto     r2,r12,-1
               mov     r15,r0,bug21_18
bug21_19:
               mov     r14,r12
               pop     r12,r14
               pop     r13,r14
               mov     r15,r13


Thu Aug 17, 2017 9:05 am

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2231
Location: Canada
The size of the expression needed to be set correctly in a couple of places.
Passing long arguments on the stack was broken. A function could receive the argument properly but a function call didn't place the arguments on the stack correctly.
A long argument has to be passed on the stack, it cannot be passed properly in a register.
The size of an immediate constant needed to be preserved through optimization.

Learning lots!

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


Thu Aug 17, 2017 10:50 am WWW

Joined: Tue Feb 10, 2015 7:07 am
Posts: 52
robfinch wrote:
The size of the expression needed to be set correctly in a couple of places.
Passing long arguments on the stack was broken. A function could receive the argument properly but a function call didn't place the arguments on the stack correctly.
A long argument has to be passed on the stack, it cannot be passed properly in a register.
The size of an immediate constant needed to be preserved through optimization.

Learning lots!

Yeh, me too! It's fascinating to see this work evolve.

Here's the next issue:

23. malformed code generated from expressions that mix 16 and 32 bit values
Code:
void bug23() {
   long a = 123;
   int q  = 10;
   int i  = 1;
   long x = 10 * a + q * i;
}

Code:
_bug23:
               push    r13,r14
               push    r12,r14
               mov     r12,r14
               dec     r14,12         # not quite sure why the stack frame is 12 words, I make it 6
               mov     r5,r0,123
               mov     r6,r0
               sto     r5,r12,-2
               sto     r6,r12,-1
               mov     r5,r0,10
               sto     r5,r12,-3
               mov     r5,r0,1
               sto     r5,r12,-4
               mov     r5,r0,10
               mov     r6,r0
               mov     r1,r5
               mov     r2,r6
               push    r3,r14
               push    r4,r14
               ld      r3,r12,-2
               ld      r4,r12,-1
               jsr     r13,r0,__mul32
               pop     r4,r14
               pop     r3,r14
               mov     r5,r1
               mov     r6,r2
               ld      r1,r12,-3
               ld      r2                      # malformed (should be mov r2, r0)
               push    r3,r14
               push    r4,r14
               ld      r3,r12,-4
               ld      r4                      # malformed (should be mov r4, r0)
               jsr     r13,r0,__mul32
               pop     r4,r14
               pop     r3,r14
               mov     r4,r1
               mov     r8,r2
               mov     r7,r4
               mov     r3,r0
               or      r4,r0                 # not sure what's going on here...
            mi.mov     r3,r0,-1
               mov     r1,r5
               mov     r2,r6
               add     r1,r7
               adc     r2,r3
               mov     r5,r1
               mov     r6,r2
               sto     r5,r12,-6
               sto     r6,r12,-5
               mov     r14,r12
               pop     r12,r14
               pop     r13,r14

Dave


Thu Aug 17, 2017 11:55 am

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2231
Location: Canada
Not sure about this one. Should it perform q * I first as an int value, then convert it to a long ? the problem with that is if the value q * I overflows an int it won't be converted sensibly. Or should it convert q,i to longs first since the expression is a long result ?

Code:
void bug23() {
   long a = 123;
   int q  = 10;
   int i  = 1;
   long x = 10 * a + q * i;
}


I suppose the vars could be typecast to longs if desired.

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


Thu Aug 17, 2017 1:58 pm WWW

Joined: Tue Feb 10, 2015 7:07 am
Posts: 52
robfinch wrote:
Not sure about this one. Should it perform q * I first as an int value, then convert it to a long ? the problem with that is if the value q * I overflows an int it won't be converted sensibly. Or should it convert q,i to longs first since the expression is a long result ?

This is definitely a minefield!

When evaluating the multiply operator, as both the operands are ints, the multiplication should happen at int precision (and return an int)

When evaluating the add operator, a long is being added to an int, so the int should be promoted to a long.

I think this behaviour is part of what's called "usual arithmetic conversion" in the C standard.

It's a little hard to test this in gcc, because long and int (on my system at least) are the same precision. Also, you can't test with smaller types, as these will be automatically promoted to an int.

But here's an example that shows overflow can happen:
Code:

#include <stdio.h>
void main() {
  long long  a = 1000000000000L;
  int        b = 1000000000;
  long long  c = a + b * b;
  long long  d = a + b * ((long long)b);
  printf("%lld %d %lld %lld\n", a, b, c, d);
}
$ ./test2
1000000000000 1000000000 998513381376 1000001000000000000

Dave


Last edited by hoglet on Thu Aug 17, 2017 4:50 pm, edited 1 time in total.



Thu Aug 17, 2017 3:14 pm

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1808
Sometimes, getting the "wrong" answer is the compliant thing to do! (Which is to say, I think it's best to do what C is defined to do, not to try to improve on it.)


Thu Aug 17, 2017 4:15 pm

Joined: Tue Feb 10, 2015 7:07 am
Posts: 52
BigEd wrote:
Sometimes, getting the "wrong" answer is the compliant thing to do! (Which is to say, I think it's best to do what C is defined to do, not to try to improve on it.)

There is a good discussion in the comments of this stackexchange thread:
https://stackoverflow.com/questions/128 ... sion-rules

Dave


Thu Aug 17, 2017 5:00 pm
 [ 77 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

Who is online

Users browsing this forum: claudebot and 0 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

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