Subject: [clisp-list] some background about avcall-i386/m68k/etc.c

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Wed Apr 10 01:54:03 2002

Hi,

these are my comments on the topic. I can only speak facts for *-m68k-amiga.[cs]. AFAIK, Bruno Haible wrote most of the others. However, -m68k-* is in some parts representative of the others.

1. We used the assembler files for lack of C compiler stability. We were tired of verifying the code after every new release of GCC which did different optimizations and broke the very sensible mixture of C and __asm__ statements.

> I don't suppose it really matters, and there _may_ be something wrong
> with compiling with the c file that I don't know about.

Really, doing what avcall etc. do in C is next to not doable. And it's not strictly C, witness all the __asm__() statements therein.

> Another advantage to using the .c file is you can follow Clisp into
> avcall on gdb - well, you can do it with the .s file too, but
> assembler is ... assembler.
IMHO, if you plan to follow the debugger on avcall, you should know assembler.

I consider the C code more like a schema of what the code is supposed to do. It gives you the frame (e.g. pulling args) from which you work on the core (filling registers and calling the function).

2. I believe some of our usage of __asm__() for register allocation
was not covered by the GNU-C team. Worse - IIRC -  they expressly said
we cannot rely on this. It worked though, for our purposes.

Do you want to rely on C + __asm__() code of which the compiler
maintainers state it's unsupported?

3. Working assembler code was first, C afterwards. It was an iterative cycle, trying to find out C code which, when compiled, would produce working code. It very much depends on the compiler switches and version. That's why comments say "Must be compiled with -O, while -fomit-frame-pointer is forbidden / necessary". Creating the C file was not a "let's write it from scratch in C".
For instance, Bruno's initial attempt at m68k.c was subtly broken (bad stack layout, i.e. ordering on things on the stack prior to foreign function call).

By nature then, the necessary C code may change at the next compiler generation. The assembly code wouldn't change. Which would you choose?

The good news is, using the C code allows you to send bug reports earlier to the GCC or other compiler maintainers... :-)

I consider the C code as the documentation of the assembly code.

3. We had to work with different assembler syntaxes.
The GNU as uses the so called MIT syntax - e.g. a6@ -, while all others use
the Motorola syntax - (a6) - for the m680x0 processor.

The solution (typical of CLISP) was to add preprocessing to assembly files.
I see similar similar things done in e.g. asmi386.h

BTW, GNU-as was not stable either.
We moved from gcc+-as-1.39/40 to gcc-2, the object format moved from UNIX a.out to xyz, GNU-as started using the BFD library (for better or worse), gcc + gas integrated patches as reported etc.

> grep -v '^ *#line' | 
> grep -v '^#ident' | grep -v '^#' | sed -e 's,% ,%,g' 
4. .s output from gcc (possibly others, maybe just -verbose output, #ident maybe Sun cc) may contain #lines (IIRC) directives which enable the assembler to refer to errors by line number in the C source file.
Also, gcc wraps it's own assembly code around
#NO_APP
and __asm__() with
#APP

5. sed -e 's,% ,%,g' 
This looks like a cure to the following:
An extra space is introduced by ANSI-C preprocessors around #define expansions (or is it # or ## token pasting?), which was not the case for K&R preprocessors.

6. sed with $ and %
IIRC, various assemblers wanted various prefixes in front of identifiers from C code or labels (or was it the prefix for registers?).

What I believe could work is this:
o Somebody knowledgeable of a given platform and assembler takes responsibility ("maintains") the corresponding {avcall,vacall,trampoline}-arch.[cs]
 + makes it work,
 + guarantees it works
 + and makes claims about the stability w.r.t. compiler changes of the code.
o somebody manages to manage the team of n people and 3n different implementations.

Regards,
	Jorg Hohle.

---

From: Peter Wood <[email-masked]>
Date: Wed Apr 10 08:23:05 2002

Hi,

On Wed, Apr 10, 2002 at 10:46:32AM +0200, Hoehle, Joerg-Cyril wrote:

> these are my comments on the topic.

Thanks for replying to my question.  The issues which you address
should be documented in avcall, so users don't have to guess.  I see
no insistence in the c file comments that the s file must be used.  On
the contrary, the comment for avcall-1386.c says:

 'Compile this routine with gcc -O (or -O2 -fno-omit-frame-pointer or -g -O)
  to get the right register variables. For other compilers use the
  pre-compiled assembler version.'

> 
> 1. We used the assembler files for lack of C compiler stability. We
were tired of verifying the code after every new release of GCC which
did different optimizations and broke the very sensible mixture of C
and __asm__ statements.
> Really, doing what avcall etc. do in C is next to not doable. And
it's not strictly C, witness all the __asm__() statements therein.

In avcall-1386.c there are three  __asm__ statements.  I would say
that its quite doable in c, with a bit of tweaking to get at the stack
and 2 registers.   At least on x86 Linux.

> IMHO, if you plan to follow the debugger on avcall, you should know
assembler.

Why?  I compiled with avcall-i386.c and have been following it with gdb.
What is wrong with this approach.

> we cannot rely on this. It worked though, for our purposes.

The fact that its apparently _still_ working, would suggest it is
reasonably safe.

> maintainers state it's unsupported?

Well, when code which was last *tweaked* 2! years ago (according to
Sourceforge cvs) compiles out of the box, apparently without breaking
anything, I would call that reasonable stability.  I note also that
the comment for many of the assembler files in the cvs is 'regenerated
with gcc-2.95.2' (including avcall-m68k-amiga.s!!) so I doubt wether
this is the hand coded assembler you remember.

> 3. Working assembler code was first, C afterwards. It was an
iterative cycle, trying to find out C code which, when compiled, would
produce working code. It very much depends on the compiler switches
and version. That's why comments say "Must be compiled with -O, while
-fomit-frame-pointer is forbidden / necessary". Creating the C file
was not a "let's write it from scratch in C".

This is interesting as an historical note on how the c files were
arrived at, but its not a good argument for not using the c files
today, if they are reasonably stable.  (See cvs comments on
'regenerated with gcc' for the various versions)  avcall-i386.c may
have been a devil to arrive at, but its reasonably clean and clear and
understandable today.

> I consider the C code as the documentation of the assembly code.

Then say so in the documentation/comments.

> We moved from gcc+-as-1.39/40 to gcc-2, the object format moved from
UNIX a.out to xyz, GNU-as started using the BFD library (for better or
worse), gcc + gas integrated patches as reported etc.

This is a long time ago.  Maybe the ground under our feet is a bit
more solid today?  The whole a.out move time is notorious.  Even I
have heard the horror stories.  

> o Somebody knowledgeable of a given platform and assembler takes responsibility ("maintains") the corresponding {avcall,vacall,trampoline}-arch.[cs]

This is free software.  Don't ask for (and don't give) guarantees...
Wait... remove 'free' from the line above [with sed, grep and cpp if
necessary :-).] 

> o somebody manages to manage the team of n people and 3n different implementations.

These requirements are completely unreasonable, Joerg.  Noone can ever
make such claims about avcall, or any other software.

I think people should test the c versions and if they work, they
should be used.  If/When stuff breaks with a new compiler, then it will
get fixed, if anyone needs it to work..  Noone is forced to move to a
new compiler.  You can also have more than one compiler, if
necessary. (It works for RedHat)

Regards,
Peter