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

[MiNT] GCC return register



Hello.

I would like we decide how to configure GCC regarding to the register used to return values from functions. We already have discussed that a bit on the "PML trouble with -m68020-60" thread.

GCC can return the values in different registers according to:
- the returned type
- the target CPU
- an FPU is present or not
- the target OS

For integer values, d0 is used in any case.

For pointers, m68k/Linux uses a0. It can be a bit faster, because the pointer is most likely to be dereferenced, and that requires an address register. Unfortunately, some old/bad assembler code expects the return value in d0. So currently, GCC for m68k/Linux returns pointers in both a0 and d0 for compatibility ! This is bad for performance.

For float/doubles, if no FPU is present, they are returned into d0/d1. If an FPU is present, it depends. By default GCC returns them into d0/d1, like with no FPU. The generic m68k-elf and m68k/Linux returns them into fp0 for greater performance. For ColdFire targets, d0/d1 are used in any case.

As a result, m68000 and m6800-60 code can't be mixed if some function returns float/double.

As explained in other messages, returning values into different registers according to their types requires to have the function prototype before calling it. Also, the assembler programmers (both callers and callees) must be aware of that.

What about our MiNT target ?

It seems that GCC always returns pointers to d0 only. So let's keep that behavior.

For returning float/doubles when a FPU is present, things are more complicated.
- GCC 2.95.3 returns float/doubles into fp0.
- GCC 4.x returns float/doubles into fp0 (I kept compatibility)
- *BUT* old assembler code (MiNTLib, PML) clearly indicates that the return value is expected to be in d0, in any case. Maybe some ancient GCC for MiNT was configured like that, and at some point the patch has been changed.

Currently, regarding to float/double functions with m68020-60, both the MiNTLib and PML are broken. My experimental patches tested with POV-Ray shown that things can be fixed. So we have to change something.

* Solution 1:
- We don't change GCC (both 2.95.3 and 4.x)
- We patch old code (MiNTLib, PML...) to match the GCC behaviour.
- m68000 and m68020-60 code still can't be mixed
- never forget a prototype when calling a float function
- never forget the rules when writing assembler code
- we get optimal speed

* Solution 2:
- Change GCC to always return values into d0
- No need to patch old code
- m68000 and m68020-60 code *can* be mixed
- forget a prototype is allowed (but still a bad idea)
- always use d0 in assembler code
- the speed is not optimal, due to transfers between fp0 and d0/d1. Probably not a big slowdown, and most math.h functions will be inlined.

My question: which solution do we chose ?

- Solution 1 is technically the best, but requires some attention when writing software. However, it works fine when the rules are respected.

- Solution 2 is safer, and requires almost no attention from the programmer. Mixing libraries for different 680x0 CPUs/FPUs is allowed. However, it requires changing GCC (easy), so the old m68020-60 binary libraries using floats will become unusable. Since math stuff is currently broken with m68020-60, I don't think it is a big issue.

Personally, I vote for solution 2. It requires fewer changes, and is safer. We could always change the method later if we have the proof it is significantly faster, and we are ready to face the drawbacks.

We could also recompile GCC 2.95.3 with that little change to keep it usable with new libraries, if people want to use it.

Please give your opinion.

--
Vincent Rivière