GNUH8 mixed C and assembly

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
I am working with HEW4 and GNUH8 5.03 targeted at the H8/3664 and
H8/3687 and I can write C programs with only moderate difficulty. I seem
to have no problem writing code in .src files and calling it from C.
What I seem unable to find out is how to write functions in assembler
and then either access the arguments that are passed in, or how to
return values to the calling function.

Also, how can I know what registers it is safe to use in my assembler
functions?

At the moment, all I want to do is to give a function an integer and
possibly return an integer. Am I going to have to learn the arcane ways
of the inline assembly stuff? An example project would be good.

FWIW, the exact need just now is a soft time delay. These are short
delays of a few tens of microseconds I appreciate these are less than
ideal in many ways. I can write one in C - as appears in any number of
example projects. However, I am nervous about how the optimizer might
treat my code. In other systems, it is not uncommon for the optimization
to completely remove apparently inactive code fragments. I am running
with -Os normally and tests seem to show that GCC will not remove lines
like this:

int temp = 1000;
while(temp--);

under any optimization but that the generated code (and thus the delay)
may change between no optimization and any level of optimization. I do
understand that that is exactly why soft delays are dodgy. Thus I figure
that, if I must have a soft delay, it should really be in assembler so
that I know what code is generated. Would I be better staying in C? Can
I ever guarantee that code will not be removed if I change the
optimization level?

Pete Harrison


Re: GNUH8 mixed C and assembly

Quoted text here. Click to load it

Soft delays are never fixed if they can be interupted, if you need a
fixed delay use a timer. There are different ways of including assembly
into your programs. Inline lines or blocks of assy instructions, C
functions who's code is written in assembler or pure assy routines
called directly. You need to look at the compiler docs for the syntax.
You can usually get to a C value from assember by putting an underbar
in front of the variable name but the H8 instructions mostly work only
with registers so this method is very limited. The other way is to use
the frame pointer to acces the stack directly but this requires you to
fully understand how your compiler works. The H8 also has complex assy
intructions best avoided if humanly possible.


Re: GNUH8 mixed C and assembly
On 12 Nov, in article
Quoted text here. Click to load it

.....

....


Considering the number of registers and sizes upto 32 bits not as limited
as quite a few processors.

Quoted text here. Click to load it

GCC/GNU uses R0 to R2 (for 16bit args) or ER0 to ER2 (32bit args) for the
first THREE parameters, the rest are passed on the stack.

Quoted text here. Click to load it

Actually quite easy to use, some of the modes on some instructions
are limiting but a lot can be done in straight assembly. Most users
create their own startup code in assembly.

--
Paul Carpenter          | snipped-for-privacy@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/ PC Services
We've slightly trimmed the long signature. Click to see the full one.
Re: GNUH8 mixed C and assembly

Quoted text here. Click to load it

That's definitely the wrong way to do it.

GCC's inline parameter syntax will cause the compiler to emit
code to load the input value(s) into register(s) for you if you
want it to. GCC's inline parameter syntax is very powerful and
doesn't require that you know much of anything about how the
compiler works. Just tell it what register(s) you want the
input values in, what registers you're clobbering, and where to
get the output values.

Quoted text here. Click to load it

Yup, that's another wrong way to do it.  The right way is to
use the extended asm feature.  Quoting from the gcc info page:


   Assembler Instructions with C Expression Operands
   =================================================
  
      In an assembler instruction using asm', you can specify the
   operands of the instruction using C expressions.  This means
   you need not guess which registers or memory locations will
   contain the data you want to use.
  
      You must specify an assembler instruction template much like
   what appears in a machine description, plus an operand
   constraint string for each operand.
  
      For example, here is how to use the 68881's fsinx'
   instruction:
  
        asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));

   Here angle' is the C expression for the input operand while
   result' is that of the output operand.  Each has "f"' as its
   operand constraint, saying that a floating point register is
   required. The =' in =f' indicates that the operand is an
   output; all output operands' constraints must use ='.  The
   constraints use the same language used in the machine
   description (*note Constraints::.).
  

Quoted text here. Click to load it

Really?  I found H8 assembly to be quite orthogonal,
striagh-forward, and very nice to work with.

--
Grant Edwards                   grante             Yow!  My DIGITAL WATCH
                                  at               has an automatic SNOOZE
We've slightly trimmed the long signature. Click to see the full one.
Re: GNUH8 mixed C and assembly
On Saturday, in article

Quoted text here. Click to load it

Interesting version numbers ?

Where did you get this package from?

Quoted text here. Click to load it

You should have checked the documentation for the compiler.

If it is a genuine GCC/GNU compiler then you should find the link in my
sig useful, also the following link:-

        http://gcc.gnu.org/projects/h8300-abi.html

Quoted text here. Click to load it

Personally you have timers on chip, use them and interrupts to get
your delays right. Your method only works if ABSOLUTELY nothing else
is going to happen and the whole programme is linear.

Quoted text here. Click to load it

--
Paul Carpenter          | snipped-for-privacy@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/ PC Services
We've slightly trimmed the long signature. Click to see the full one.
Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it

KPIT cummins http://www.kpitgnutools.com /
I should perhaps have noted that the version numbers were KPIT ones. The
compiler is GCC 4 based.

Quoted text here. Click to load it

I did try...
Quoted text here. Click to load it
but, of all the pages I chased about on today, I missed that one :)

Thanks - that all makes more sense now.

Quoted text here. Click to load it

I understand that. For many tasks, I do indeed use the timers. For
delays of a few milliseconds or more, I would use a 1kHz timer tick I
have. The steppers I am driving have pretty robust timing up to about
5000 interrupts per second. This is just for initialing a graphical LCD
so all I really want is a minimum delay for a set-up time - typically a
few tens of microseconds - and a simple busy-wait is fine.

Pete Harrison

Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it

For something that non-critical, and where the only real concern is minimum
time elapsed, I tend to use macros encapsulating a system-speed-dependent
constant which I can play with.

Steve
http://www.fivetrees.com



Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it

You got already many good answers, but nobody seems to
have told this yet:

For an assembly language subroutine, create a skeleton function
in C and compile it with the GCC -S switch, so you get the
assembler version of the function.

If you'd prefer an assembler listing instead, use

   gcc -c -Wa,-ahlms=myfile.lst myfile.c

Please keep the comma after -Wa and insert no spaces there.
You can insert other options on the command lien to match
those you're using in routine code, but beware of aggressive
optimization: it may delete most of your skeleton code if it's
doing nothing indeed.

HTH

--

Tauno Voipio
tauno voipio (at) iki fi


Re: GNUH8 mixed C and assembly

Quoted text here. Click to load it
  It was the optimiser that had me concerned. In other compilers (can't
remember exactly which) you can see non functional code like timimg
loops completely vanish under high levels of optimisation. I could only
think of two likely solutions (for this type of non-critical loop). One
was to make the counter value a volatile thus insisting that the
compiler assume nothing about its use; or to code the loop in assembler,
out of the way of the compiler's optimisation.

It seems that HEW allows you to set different levels of optimisation for
individual source files so that is another way to go I suppose.

pete Harrison


Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it

No, that's not the way to go.  Except in the case of compiler bugs (a
rarity, unless your code is absurdly complicated and provokes obscure
bugs), then code that fails when optimised is incorrect code.  A program
that only works when different parts are compiled with different
optimisation flags is a maintainance nightmare.

For extremely critical timing, then assembly is the only way to do it,
assuming you can't (sensibly) make use of hardware timers.  For
non-critical pauses like you need here, loops with volatile counters are
normally the correct way to go.  Alternatives such as a loop body
consisting of "asm volatile ("nop")" (or whatever fits for your target)
are another method.

Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it


Yes - good point. I had not really thought that through.

Quoted text here. Click to load it

Ah - I like that a bit.

Using a volatile variable forces the compiler to include the loop and
seems also to make the loop timing invariant with optimisation level.

Actually, I have been trying several simple loops and I have not yet
been able to persuade GCC to eliminate an empty loop by changing
optimisation levels. The code generated changes but  is always there.
Still, I will be happier when I can know what will be generated. At
present I just set the optimisation to -O -Os. As you say, it is no good
if a change in optimisation level stops things working.

Paul's link to the GCC ABI says that there are known clobbered registers
for this compiler so it will not be too hard to implement and
assembly-based delay that only uses the registers.

Peter Harrison



Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it

It won't necessarily make the loop timing invariant, but it is likely
to, especially for a simple loop, such as a while() loop, counting down.
  Sometimes a slightly more complex loop (such as a for loop) will be
optimised to different code.

Quoted text here. Click to load it

You'll probably find that small loops will disappear, but not large
ones.  When the compiler sees a 10 round loop, it might consider
unrolling it and then find it does nothing, so it is eliminated.  A 1000
round loop will not be unrolled, and will not get the same optimisation.
  But you can't be sure of this, nor can you be sure of changes in the
future as the compiler gets smarter.

Quoted text here. Click to load it

That's certainly possible, but unlikely to be necessary in this case
(since your timing is not strict).

Quoted text here. Click to load it

Re: GNUH8 mixed C and assembly
Quoted text here. Click to load it

Code such as your loop above have no effect (as far as the C virtual
machine is concerned), and thus it will be removed by any optimising
compiler, including gcc (when optimisations are enabled).  If you want
to force a delay loop in this way, the correct method is to declare
"temp" to be volatile, so the compiler is unable to remove it.  Examine
the generated assembly code for the loop under different realistic
optimisation levels (i.e., "-Os" or "-O2".  Avoid more aggressive
optimisations unless you really know what you are doing, as they'll
probably cost in code size for very little speed gain.  Occasionally,
"-O1" can be helpful in debugging, but "-O0" is useless for most
compilers).  You'll probably find that the generated code is identical
for such a simple loop, and the "volatile" on "temp" will stop the loop
being removed.

Site Timeline