[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Altivec Context Management



The basic problem is the same any multithreaded, non-unix sytem
has with gcc. It lacks an option to suppress implicit usage of floating-point
and vector registers. Recap two approaches:


--> we provide unix semantics:
compile (explicitely or implicitely) -maltivec -mhard-float and save/restore all
registers (int, float, vec) on every context switch (strictly, we also
must do this for interrupts unless ISRs are compiled separately
with -mno-altivec -msoft-float). Note that I already have experienced
the ISR/FPU (cf. PR833) issue.


     another option is 'lazy-context switching', i.e., at context switch
     disable fp and vec units but dont save/restore anything.
     Trap 1st use by another task and switch registers from
     the exception handler.

   Note that all of these can be costly (we're talking about ~1kB of data)

--> compile everything -mno-altivec (or a cpu < 7400) but implement
    vector context switching and an API to make tasks 'altivec aware'.
    Code executed by such a vector task must then be compiled with
    -maltivec. (There are a few details to be taken care of like vfprintf
    but I have some ideas there, too. No vecs on C++, probably.).

Currently, I favor the less expensive approach (2). I can't stress it enough:
what is *really* needed are -fno-implicit-fp / -fno-implicit-altivec gcc options.
Anything else will always cause headache.


Baseline: the current -maltivec multilib is of no use. It should be replaced
by

-mcpu=7400 -mno-altivec -mabi=altivec

That way,

a) code can #ifdef 7400 and compile altivec support (__ALTIVEC__ is not defined for -mno-altivec)
b) vector unit is never used by kernel/newlib or ordinary application code
c) stack alignment required by altivec is provided


Code to be executed from an altivec-enabled task is then explicitely compiled with -maltivec.
It could use the vector engine, finds an aligned stack and the CPU support would provide
context switching.


For altivec this is more straightforward to do - more difficult in the case of FP because
soft-float has implications on libm.


T.


Joel Sherrill <joel@OARcorp.com> wrote:

Ralf Corsepius wrote:

On Fri, 2005-11-04 at 10:25 -0600, Joel Sherrill  wrote:


The magic is deeply hidden in GCC's sources:

Check gcc-4.0.x/gcc/config/rs6000/rs6000.c for POWERPC_7400_MASK.


Yep.  It turns on Altivec.

Then RTEMS should just honor the __ALTIVEC__ flag which is set when -mcpu=7400 is set. It will require no tool changes for gcc 4.0.x.

The gcc version for 4.6 does not set __ALTIVEC__ when -mcpu=7400 is specified.



I current don't have such a toolchain at hand, but if I recall correctly, it didn't have an -mcpu=7400 multilib variant ;)


I lean to fixing this in 4.6 by saying "don't do that".

Checking GCC-3.4's source code however indicates that -mcpu=7400 already
implied -maltivec and -D__ALTIVEC__ in gcc-3.4. This matches with my
memory, because I believe altivec had been introduced in gcc-3.4 and
then more or less completely rewritten for gcc-4.x).


Apparently since it really uses them now. :)

It's the old problem with powerpc port:
powerpc-RTEMS classifies its internals on "cpu-variants", while GCC is
on the move towards classifying its internals on "cpu-features".


There is no legacy with this issue. The context switch code just needs to honor Altivec.

I hope we decide the interrupt code doesn't need serious work. If it does, we may be in for some refactoring and combining. It is needed anyway.

But RTEMS does need to honor the __ALTIVEC__ flag and based upon gcc's use of the vector registers, this would mean it is part of the basic integer context when available.



I recall we had a discussion on this topic when gcc-4.0 ca. at the time when about to be released or just released. The result of this discussion was to add an m7400 multilib variant.


Good.  Then we laid the groundwork and now we know what follow up to do.

BTW: Check gcc-4.0.x/gcc/config/rs6000/rs6000.c for OS_MISSING_ALTIVEC.
I didn't try to investigate what it actually is, but it's looks like it
probably related to the RTEMS altivec problem


It appears to just disable it:

#ifdef OS_MISSING_ALTIVEC
  if (OS_MISSING_ALTIVEC)
    set_masks &= ~MASK_ALTIVEC;
#endif

Not particularly useful. An automated version of "don't do that, it hurts." I would rather fix the problem.

--joel