linker scripts

Please note that this toolsuite is not part of the official Firewing release but we will try and help where we can...

Re: linker scripts

Postby David John Barker » Sat Apr 05, 2014 4:11 pm

> I'm not sure the resulting code will actually work

Thinking on this - I do recall GCC having problems with anything other than -O0 on Firewing generated code. Basically, there is a lot of underlying ASM used in the Firewing code which the GCC optimiser doesn't handle very well. There may be a better way of coding the ASM macros used (they are open source, so can be modified) so the optimiser handles them correctly but at the time there were written, I couldn't find one. The Firewing32 compiler uses a completely different approach, where no ASM was used at all. This allowed the GCC optimiser to be used, so all Firewing 32 programs can have all -Ox options enabled. However, you have this strange situation where optimised high level GCC code isn't necessarily better than hand rolled ASM so I'm very reluctant to re-code all the macros in order to test. It would be interesting to compare performance against a native Firewing program with -O0 against an equivalent c program with -O2. If I get time I may look at that - any suggestions of the type of program for the test would be welcome. I've written quite a lot of commercial code using Firewing16 in the last year and never encountered any performance issues, even with the default -O0.
User avatar
David John Barker
 
Posts: 491
Joined: Thu Nov 08, 2012 12:21 pm

Re: linker scripts

Postby Jerry Messina » Sun Apr 06, 2014 1:06 pm

You're probably right. I took the sample progUART.bas, compiled it to C, and played around with it some.

Something I noticed is that a lot of the code differences seem to have something to do with this section in progUART.C
Code: Select all
// system registers...
register unsigned int w10 asm("w10");
register unsigned int w11 asm("w11");
register unsigned int w12 asm("w12");
register unsigned int w13 asm("w13");
register unsigned int w14 asm("w14");
register unsigned int w15 asm("w15");

#define reg0 w10
#define reg1 w11
#define a0 w12
#define a1 w13
#define a2 w14
#define sp w15


With those declarations, when you enable -o1 a number of instructions that reference these regs don't generate any code, even the C macros like AddrOf_Var_xx

For example, using -o0:
Code: Select all
490:                  __AddrOf_Var_16 (P48_U144,a0);
 003EA  20830C     mov.w #0x830,0x0018           <<<< this is fine... addr placed in WREG12
491:


using -o1:
Code: Select all
490:                  __AddrOf_Var_16 (P48_U144,a0);   <<<<< NO CODE AT ALL!!
491:                  __CodeLoad_EA (_DB_StrConst_00);


The optimizer got rid of some other code too, like code for
Code: Select all
349:                  // *(addr0-) = number + 48



So I thought maybe the regs should be declared 'volatile' and then it would leave the code alone...
Code: Select all
// system registers...
volatile register unsigned int w10 asm("w10");
volatile register unsigned int w11 asm("w11");
volatile register unsigned int w12 asm("w12");
volatile register unsigned int w13 asm("w13");
volatile register unsigned int w14 asm("w14");
volatile register unsigned int w15 asm("w15");


This is what happened...
using -o0:
Code: Select all
490:                  __AddrOf_Var_16 (P48_U144,a0);
 003F0  208300     mov.w #0x830,0x0000
 003F2  780600     mov.w 0x0000,0x0018       <<<< now it's moved thru WREG, but gets to W12...


using -o1:
Code: Select all
490:                  __AddrOf_Var_16 (P48_U144,a0);
 003C0  208309     mov.w #0x830,0x0012              <<<< THIS ISN'T THE ADDR OF a0 (w12)


It would seem that the optimizer definitely isn't happy when registers are accessed. It's a shame since -o1 gets you a reasonable bit of code reduction, and they let you use it in the free version. Performance-wise it's likely not too much of an issue unless you're trying to squeak out every last drop of speed.
Jerry Messina
 
Posts: 280
Joined: Thu Feb 14, 2013 10:16 am

Re: linker scripts

Postby David John Barker » Sun Apr 06, 2014 8:12 pm

Do you know of a way to embed ASM into a "C" program without the optmiser chewing it up? Volatile doesn't seem to work.
User avatar
David John Barker
 
Posts: 491
Joined: Thu Nov 08, 2012 12:21 pm

Re: linker scripts

Postby Jerry Messina » Sun Apr 06, 2014 10:50 pm

I'm still really new to a lot of this, so I'm shooting in the dark.

According to this reference(http://wiki.osdev.org/Inline_Assembly), declaring them
Code: Select all
asm volatile (".... ::: "memory")
should keep it from getting optimized out
Clobbered Registers List

It is important to remember one thing: The C/C++ compiler knows nothing about Assembler. For the compiler, the asm statement is opaque, and if you did not specify any output, it might even come to the conclusion that it's a no-op and optimize it away. Some third-party docs indicate that using asm volatile will cause the keyword to not be moved. However, according to the GCC documentation, The volatile keyword indicates that the instruction has important side-effects. GCC will not delete a volatile asm if it is reachable., which only indicates that it will not be deleted (i.e. whether it may still be moved is an unanswered question). An approach that should work is to use asm (volatile) and put memory in the clobber registers, like so:

__asm__("cli": : :"memory"); // Will cause the statement not to be moved, but it may be optimized away.
__asm__ __volatile__("cli": : :"memory"); // Will cause the statement not to be moved nor optimized away.

Since the compiler uses CPU registers for internal optimization of your C/C++ variables, and doesn't know about ASM opcodes, you have to warn it about any registers that might get clobbered as a side effect, so the compiler can save their contents before making your ASM call.

The Clobbered Registers List is a comma-separated list of register names, as string literals.


I didn't try it to see if it makes any difference or not
Jerry Messina
 
Posts: 280
Joined: Thu Feb 14, 2013 10:16 am

Re: linker scripts

Postby David John Barker » Mon Apr 07, 2014 8:30 am

> should keep it from getting optimized out

You would think, but it doesn't. The coded macros all have cloberred lists and the optimizer still gets confused. If you look at the code that gets a variable address, it's actually not written in ASM but the optmizer still gets it wrong. I think it must be the way I am declaring variables or something else that's impacting on the optimizer.
User avatar
David John Barker
 
Posts: 491
Joined: Thu Nov 08, 2012 12:21 pm

Re: linker scripts

Postby David John Barker » Mon Apr 07, 2014 9:49 am

I've just recoded the progUSART "c" file to use the 32 macros. After much tweaking I got it to work with -Ox. I don't think there would be an easy fix with the way 16 bit code is currently generated, probably better to use the approach taken by the 32 bit generator. It would be a large undertaking, but I need to revisit my code to be sure. It may be worth doing as -O1 does give some improvements. In addition, native Firewing for PIC24 can handle all -Ox options, so significant improvements could be achieved.
User avatar
David John Barker
 
Posts: 491
Joined: Thu Nov 08, 2012 12:21 pm

Re: linker scripts

Postby Jerry Messina » Mon Apr 07, 2014 10:36 am

> After much tweaking I got it to work with -Ox.
You're the Man!

> In addition, native Firewing for PIC24 can handle all -Ox options, so significant improvements could be achieved.
That would be cool.

I googled "gcc optimize asm volatile" and came up with a few interesting references like
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm
and
http://stackoverflow.com/questions/18097463/why-doesnt-gcc-handle-volatile-register

XC is my first time using GCC. It really seems to take optimization and volatile to a whole new level,
at least compared to other embedded C compilers I've used. GCC is way too smart for me.

Luckily it's you doing it!
Jerry Messina
 
Posts: 280
Joined: Thu Feb 14, 2013 10:16 am

Re: linker scripts

Postby David John Barker » Mon Apr 07, 2014 2:37 pm

Yes, I remember seeing those posts and numerous others like it. In this respect, GCC can be a little difficult when trying to obtain a definitive answer to certain types of problem. Unless further information is forthcoming, I think the FW32 approach to code generation may be the only way forward...
User avatar
David John Barker
 
Posts: 491
Joined: Thu Nov 08, 2012 12:21 pm

Re: linker scripts

Postby Jerry Messina » Mon Apr 07, 2014 2:45 pm

> I think the FW32 approach to code generation may be the only way forward...

Is there a downside to that? Sounds like less ASM involved, if I understand correctly...
Jerry Messina
 
Posts: 280
Joined: Thu Feb 14, 2013 10:16 am

Re: linker scripts

Postby David John Barker » Mon Apr 07, 2014 2:55 pm

Removing the ASM will, I'm almost sure, increase the code size when using -O0. However, speed will increase and code size will reduce when using -O1. But will it be better that the current approach? Who knows, you would have to try it and see! However, if native Firewing could then be driven with -O2 (remember, the Firewing GCC code generator has no microchip imposed licensing restrictions) then I'm sure the results would be very good indeed. Other than the problems outlined with using -O0, I can't see any disadvantages using the FW32 approach.
User avatar
David John Barker
 
Posts: 491
Joined: Thu Nov 08, 2012 12:21 pm

PreviousNext

Return to Microchip 16

Who is online

Users browsing this forum: No registered users and 1 guest

cron

x