Welcome, Guest. Please login or register.

Author Topic: Help needed combining GCC/C++ with asm sources  (Read 5754 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Help needed combining GCC/C++ with asm sources
« on: March 22, 2004, 02:20:11 AM »
Hi,

As part of an ongoing effort to move my old C++ codebase away from stormc, I'm struggling with gcc regarding calling assembler functions.

Specifically, I'm having problems specifying which registers are used for 680x0 asm function parameters. Most of the functions that I have that are asm generally dont return anything (void) and generally trash d0/d1/a0/a1.

So assume I have a function that takes an int in d0, and a char* in a0.

How do I define the function within gcc/c++?

In C mode the following was ok

void func(int i __asm("d0"), char* c __asm("a0"));

but C++ mode did not want to know. I also tried making the above a header and using extern "C", but this didnt work either.

Furthermore, the gnu assembler is scary. Can asm code assembled with phxass be linked with gcc code and are there any known issues?

Any help gladly received :-D
int p; // A
 

Offline bloodline

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12114
    • Show only replies by bloodline
    • http://www.troubled-mind.com
Re: Help needed combining GCC/C++ with asm sources
« Reply #1 on: March 22, 2004, 11:09:51 AM »
My Advice?

I suggest you recode your ASM parts in C, it will be better in the long run :-)

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #2 on: March 22, 2004, 02:52:53 PM »
Hi Matt,

Whilst I appreciate the sentiment, the project in question is the amiga OS3.x 680x0 backend implementation my C++ framework.

Hence portability of this particular code is not an issue. C++ versions of this code already exist in the "generic" part of the tree, the asm used here replaces these for speed gains *specifically* on the 680x0 - other implementations may or may not have similarly optimised code.

Now, the asm used therein is sparse but essential for performance. They are used in memory copy / set / endian swap routines. No matter how good your compiler or algorithm, some things C/C++ just cannot achieve with the same level of performance.

For instance, you can byteswap a 32-bit longword with just 3 instructions in asm thanks to instructions like "rol.w" and "swap", for which C/C++ have no equivalent operators.

I also have some pixel conversion routines etc. that are up to 5x slower in the generic C++ code than the asm, despite loop unrolling, longword only accesses and stuff, again simply due to the lack of rotate instructions.

I'm moving the code to gcc, purely so the generic branch of it is easier to port cross platform and more advanced C++ features can be used.

Any given backend, be it Amiga680x0/PPC, AROS, Linux, Win32, etc. will always use whatever it can to get the best performance, only the public front needs to be completely platform intependent.
int p; // A
 

Offline bloodline

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12114
    • Show only replies by bloodline
    • http://www.troubled-mind.com
Re: Help needed combining GCC/C++ with asm sources
« Reply #3 on: March 22, 2004, 03:31:10 PM »
Sorry, yes, I did think before I clicked "Submit" that It could be eligable for "most useless post of the year award"... but even without portability, I would still recommend using C :-)

My thinking is that CPU's only get faster, theny  never get slower... so I wouldn't worry about optimising it (Yes I can't believe I just said that... Next you will hear that I've just got the job of cheif architect at MicroSoft).

Can't you assemble your ASM functions serparatley and then link them in at link time?

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #4 on: March 22, 2004, 03:44:18 PM »
Quote

bloodline wrote:
Sorry, yes, I did think before I clicked "Submit" that It could be eligable for "most useless post of the year award"... but even without portability, I would still recommend using C :-)


On any CPU other than 680x0 I'd probably agree. Although I have a very nice endian conversion loop for ppc too ;-)

Quote

My thinking is that CPU's only get faster, theny  never get slower... so I wouldn't worry about optimising it (Yes I can't believe I just said that... Next you will hear that I've just got the job of cheif architect at MicroSoft).


:lol:

Quote

Can't you assemble your ASM functions serparatley and then link them in at link time?


This is basically what I'm trying to do. The problem is in specifying (for those asm functions that use it) which registers arguments are expected in.

Worst case scenario is that I will have to just use stack passing and modify the asm side. Then I should be able to use 'extern "C"' at least ;-)
int p; // A
 

Offline bloodline

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12114
    • Show only replies by bloodline
    • http://www.troubled-mind.com
Re: Help needed combining GCC/C++ with asm sources
« Reply #5 on: March 22, 2004, 04:06:05 PM »
Quote
Worst case scenario is that I will have to just use stack passing and modify the asm side. Then I should be able to use 'extern "C"' at least


Real Men use stacks... Eh? what? yes Bill I can hear you! You need an heir to the SmallFlacid throne? Yes! I will heed the calling... :lol:


Yes, due to the unfortunate deadend nature of the 68k... you have a very good point.


I think you should make a shared library, that way we can all have the benefit of your functions :-)

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #6 on: March 22, 2004, 04:17:39 PM »
Quote

bloodline wrote:
I think you should make a shared library, that way we can all have the benefit of your functions :-)


The 680x0 asm stuff in a normal amiga os linrary you mean? a memfunc.library...?

Hmm, I don't see why not. Wouldn't have too many functions in it just now though. Just copy, set, set16, set32, set64, swap16, swap32, swap64.

The pixel conversion stuff would only be useful for folks dealing directly with CGX pixel formats...

The C++ framework thing will go opensource once its' de storm-ified and gnu-ified anyway, then the actual source will be available to anybody wanting to play with it.
int p; // A
 

Offline bloodline

  • Master Sock Abuser
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 12114
    • Show only replies by bloodline
    • http://www.troubled-mind.com
Re: Help needed combining GCC/C++ with asm sources
« Reply #7 on: March 22, 2004, 04:20:34 PM »
Quote

The 680x0 asm stuff in a normal amiga os linrary you mean? a memfunc.library...?

Hmm, I don't see why not. Wouldn't have too many functions in it just now though. Just copy, set, set16, set32, set64, swap16, swap32, swap64.

 


It might be nice to have a standardized API for those functions, especially when porting from 68k code to x86 for example.

Offline Steady

Re: Help needed combining GCC/C++ with asm sources
« Reply #8 on: March 22, 2004, 05:24:52 PM »
Quote
especially when porting from 68k code to x86 for example.


Hmmm... I wonder what that would be useful for ;-)
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #9 on: March 22, 2004, 06:10:11 PM »
Quote

bloodline wrote:
Quote

The 680x0 asm stuff in a normal amiga os linrary you mean? a memfunc.library...?

Hmm, I don't see why not. Wouldn't have too many functions in it just now though. Just copy, set, set16, set32, set64, swap16, swap32, swap64.

 


It might be nice to have a standardized API for those functions, especially when porting from 68k code to x86 for example.


Well, the original StormC3 Mem class member functions all operate on blocks of memort and are defined like this


Code: [Select]

class Mem {
   // Mem:: should really be a namespace

   // ... snip ...

  public:
    // low level block memory operations
    static void copy(REGP0 void* dst, REGP1 void* src, REGI0 size_t len);
    static void move(REGP0 void* dst, REGP1 void* src, REGI0 size_t len);
    static void swap16(REGP0 void* dst, REGP1 void* src, REGI0 size_t num);
    static void swap32(REGP0 void* dst, REGP1 void* src, REGI0 size_t num);
    static void swap64(REGP0 void* dst, REGP1 void* src, REGI0 size_t num);
    static void zero(REGP0 void* dst, REGI0 size_t len);
    static void set(REGP0 void* dst, REGI0 int val, REGI1 size_t len);
    static void set16(REGP0 void* dst, REGI0 uint16 val, REGI1 size_t num);
    static void set32(REGP0 void* dst, REGI0 uint32 val, REGI1 size_t num);
    static void set64(REGP0 void* dst, REGP1 uint64& val, REGI0 size_t num);

    //...snip
};
[/size]

In the old definitions, REGP0 - REGP7 (register pointer parameter) are #defined as register __a0 to register __a7.

Similarly, REGI0 - REGI7 (register integer parameter) are #defined as register __d0 to register __d7

On non amiga 680x0 targets, these macros may be empty or mapped to other registers etc.

The "size_t num" parameter is always defined in terms of the element size for any function that has an implicit size (eg swap32, set16 etc.). So, byteswapping swapping a block of 128 32-bit entities would be

uint32* source;

//...

Mem::swap32(source, source, 128); // NOTE : overlap only allowed when destination address == source source address

Zeroing the same block, however would be

Mem::zero(source, 128*sizeof(uint32));

Basing a shared library on these functions wouldn't be very difficult.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #10 on: March 24, 2004, 03:01:59 PM »
*bump*

I've been looking for the 680x0 backend info for gcc to see what conventions it uses for register usage, but I didnt find the info.

Assuming I can link my older asm code (perhaps with some modifications), do I have to preserve all registers, or (as with various other compilers) are d0/d1/d0/a1 deemed volatile?

Anybody?
int p; // A
 

Offline PiR

  • Full Member
  • ***
  • Join Date: Apr 2003
  • Posts: 148
    • Show only replies by PiR
Re: Help needed combining GCC/C++ with asm sources
« Reply #11 on: March 25, 2004, 11:37:15 AM »
Hi Karlos

As you have trouble to find 'anybody' you can count on me. ;-)

I don't know the convention of GNU, however having original SAS/C with printed documents I can tell you one thing for it:
d0/d1/a0/a1 can be used and trashed, but for C.

I'm sure that in C++ SAS uses one address register (don't remember wich one) for 'this' pointer, additionally one integer register in constructors/destructors for internal usage, and I guess one more register for something, but I can't remember at the moment. And of course while planning your shared library remember to reserve a6 for library base.
I guess GNU may have some similar requirements.

Honestly, being you, I would think of C++ inlines that simply call your functions via regular C interface.

Good luck
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #12 on: March 25, 2004, 02:55:30 PM »
Heh, cheers :-)

The shared library thing was just a spin off. It wouldn't be written in C++, so no need to worry there.

The main issue is just getting some old asm code that I wrote in phxass to work with StormC3 C++ code to work with the same C++ code compiled under gcc. As it goes, all of these functions are static class members, so worring about the this pointer isnt an issue :-)

As for inling, I was thinking the same thing. If we assume that a0/1, d0/1 are trashable, I assume something (excusing bad inline asm syntax, not fully up to speed with it yet) this should work...

Code: [Select]
[size=x-small]
public void Mem::zero(void* src, size_t len)
{
    // move args into d0/a0 and call asm linked
    // function.
    asm("move.l %0, a0\n" \
        "move.l %1, d0\n" \
        "jsr Mem__asmZero__r9Pvr0Uj\n" : src : len);
}
[/size]


Failing that, I can just make the old asm C like and make them retrieve their args from the stack themselves. I dont' really see much of a difference ;-)
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Help needed combining GCC/C++ with asm sources
« Reply #13 on: March 25, 2004, 07:23:18 PM »
Cool it worked :-D

Ok, just in case anybody else is in the same boat ever...

I found I can indeed make my old asm code work ok in GCC C++ mode. As I expected, I needed to make an inline function that calls the asm.

So, imagine you have some asm, that defines a function with the extported symbol _asmFunction. It takes register d0 and a0, clobbers d0/d1/a0/a1, returns nothing...

To call it (via an inline func in gcc c++ goes a bit like

Code: [Select]
[size=x-small]
inline void func(int i, int* j)
{
    asm("move.l %0, d0\n"
        "move.l %0, a0\n"
        "jsr _asmFunction\n"
        :                         // no outputs
        : "g"(i), "g"(j)          // inputs
        : "d0", "d1", "a0", "a1"  // clobbers
    );
}
[/size]


Right, now that little mystery is sorted, I can get on with stuff :-D
int p; // A
 

Offline PiR

  • Full Member
  • ***
  • Join Date: Apr 2003
  • Posts: 148
    • Show only replies by PiR
Re: Help needed combining GCC/C++ with asm sources
« Reply #14 on: March 25, 2004, 08:02:12 PM »
Hi again Karlos

I'm wondering why you wrote 'extern "C"' didn't work.
Why? What happend?
This would mean that some C headers are not compatible with C++ under GNU and that would be really strange. :-o

Thats great that your solution works, however repeating this for every function can mean a lot of stupid and potential buggy-introducing work.
The other thing is that simple 'jsr' makes your code position dependant always, regardles of the compiler options.

Besides this GNU asm-embeding mumbo-jumbo always scared me. :-o ;-)

Cheers