3

The C function

double retfp(void) { return 42; }

, when compiled with OpenWatcom C compiler for Linux i386:

owcc -blinux -fno-stack-check -fsigned-char -march=i386 -Os -W -Wall -Wextra -Werror -mregparm=0 -c -o retfp.owcc.obj retfp.c

has code which returns the double in EDX:EAX. However, I want to get it in ST(0) instead, like how GCC does it. Is thiss possible with OpenWatcom, maybe via a command-line flag?

pts
  • 80,836
  • 20
  • 110
  • 183
  • This seems like a calling convention issue which would be built into the compiler.. But what's wrong if it returns in edx:eax, do you need those two registers ? – Irelia May 17 '23 at 23:33
  • One option I can think of is write a wrapper function in x86 which takes registers edx:eax and puts them into st0 then returns them to the caller. Then all your C functions would return to the wrapper function, hehe – Irelia May 17 '23 at 23:34
  • @Irelia: I need ST(0) for interoperability with code already compiled with other compilers, expecting ST(0). I know that I can write wrapper functions, but I'd prefer a simpler and easier to maintain solution, if available. – pts May 18 '23 at 00:08
  • 1
    I can accept *doubles are hardwired to be returned in EDX:EAX* as an answer. However, I'm optimistic that I missed a setting somewhere. – pts May 18 '23 at 00:10

2 Answers2

2

You should specify calling convention which returns floating point values in ST(0), for example cdecl:

double __cdecl retfp(void) {  return 42; }

Dissassembler output:

Segment: _TEXT BYTE USE32 00000007 bytes
0000                            _retfp:
0000  DD 05 00 00 00 00                 fld             qword ptr L$1
0006  C3                                ret
...
Segment: CONST DWORD USE32 00000008 bytes
0000                            L$1:
0000  00 00 00 00 00 00 45 40                         ......E@

Also you can specify default calling convention to owcc with -mabi flag.

dimich
  • 1,305
  • 1
  • 5
  • 7
0

TL;DR Use owcc -mabi=cdecl instead of owcc -mregparm=0.

Extending the answer of @dimich:

  • The owcc -mabi=... and owcc =mregparm=... flag values together determine the calling convention, and the calling convention determines (e.g.) in which registers values are returned.
  • The owcc -mabi=... flag corresponds to the wcc386 -ec... flag, e.g. owcc -mabi=cdecl is the same as wcc386 -ecc.
  • The owcc -mregparm=... flag corresponds to the undocumented (!) wcc386 -3... flag, e.g. owcc -mregparm=0 is the same as wcc386 -3s, and owcc -mregparm=3 is the same as wcc386 -3r.
  • The default is owcc -mregparm=3 -mabi=watcall.
  • doubles are returned in EDX:EAX with owcc -mregparm=0 -mabi=pascal, owcc -mregparm=0 -mabi=fortran, owcc -mregparm=0 -mabi=watcall, owcc -mregparm=0.
  • doubles are returned in ST(0) with owcc -mregparm=0 -mabi=cdecl, owcc -mregparm=0 -mabi=stdcall, owcc -mregparm=0 -mabi=fastcall, -mregparm=0 -mabi=syscall, owcc -mregparm=3, and also with owcc -mregparm=3 -mabi=... (any -mabi=... value).
pts
  • 80,836
  • 20
  • 110
  • 183