public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Barry Wealand <barry.wealand@lmco.com>
To: gcc@gcc.gnu.org
Cc: barry.wealand@lmco.com, "Kancler, Cliff" <cliff.kancler@lmco.com>,
	reed@reedkotler.com
Subject: Operator overloading in (MIPS) assembly-language
Date: Tue, 23 Mar 2004 08:52:00 -0000	[thread overview]
Message-ID: <405F78DC.6F04DF55@lmco.com> (raw)

Hello -

We've been working with a GNU MIPS cross-compiler / toolset, generating
code for MIPS-like hardware to which we've added some new features.
These new features typically take the form of new instructions, and thus
we've needed a way to teach the compiler how to use these new
instructions.  We don't have the resources to undertake a genuine
compiler modification, but we've had pretty good success using the
following methodology:  We define a new (C++) type (typically a struct)
with a single data member of some built-in type; then we overload the
operators on that new type with inline functions containing
assembly-language statements using the new instructions.  Using the
-freg-struct-return compiler flag, the compiler does a pretty good job
of generating code in this fashion... but there's a mystery that's
puzzled me for some time now.

The best way to illustrate is with an example.  Assume we wanted to add
a new floating-point type to the MIPS instruction set architecture.  The
existing architecture supports single (assembler mnemonic "s"), and
double (assembler mnemonic "d") precisions; assembler mnemonics also
exist for word-with ("w") and double-word-width ("l") fixed-point /
integer data types, which are primarily used in type conversions.  For
this example, we'll define a new format that will use the assembler
mnemonic "f", and reuse the basic FPU instructions with this new
format.  So, for example, we'll define new instructions: add.f, sub.f,
mul.f, etc.  The mapping of these new instructions to machine code need
not be elaborated here - it will suffice to consider the
assembly-language code generated by the compiler.

Next, a header file is created, say new_float.h:


#ifndef _NEW_FLOAT_H
#define _NEW_FLOAT_H

struct new_float {
        float value;

        new_float() {value = 0.0;}
};

inline new_float operator+(new_float op1, new_float op2)
{
        new_float f;

        asm("add.f  %0,%1,%2" : "=f" (f.value) : "f" (op1.value), "f"
(op2.value));
        return f;
}

inline new_float operator-(new_float op1, new_float op2)
{
        new_float f;

        asm("sub.f  %0,%1,%2" : "=f" (f.value) : "f" (op1.value), "f"
(op2.value));
        return f;
}

inline new_float operator*(new_float op1, new_float op2)
{
        new_float f;

        asm("mul.f  %0,%1,%2" : "=f" (f.value) : "f" (op1.value), "f"
(op2.value));
        return f;
}

#endif

(This is intentionally abbreviated - the full-up version would have a
lot more stuff in it.)

Next, create a short C++ test program, call it new_float_test.C:


#include "new_float.h"

new_float test_func(
        new_float a,
        new_float b,
        new_float c
)
{
        new_float d, e;
        new_float result;

        d = a * b + b * c;
        e = a * c - b * d;
        result = d * e;
        return result;
}

Finally, compile this test program to assembly-language:

mips-elf-g++ -O2 -freg-struct-return -S new_float_test.C

and look at the generated assembly-language file, new_float_test.s:

1           .file   1 "new_float_test.C"
2           .section .mdebug.abi32
3           .previous
4           .text
5           .align  2
6           .globl  _Z9test_func9new_floatS_S_
7   $LFB1:
8           .ent    _Z9test_func9new_floatS_S_
9   _Z9test_func9new_floatS_S_:
10          .frame  $sp,8,$31               # vars= 8, regs= 0/0, args=
0, extra= 0
11          .mask   0x00000000,0
12          .fmask  0x00000000,0
13          subu    $sp,$sp,8
14  $LCFI0:
15          mtc1    $6,$f2
16   #APP
17          mul.f  $f8,$f12,$f2
18          mul.f  $f12,$f12,$f14
19          mul.f  $f2,$f14,$f2
20          add.f  $f4,$f12,$f2
21          mul.f  $f14,$f14,$f4
22          sub.f  $f6,$f8,$f14
23          mul.f  $f0,$f4,$f6
24   #NO_APP
25          s.s     $f12,0($sp)
26          s.s     $f2,0($sp)
27          s.s     $f4,0($sp)
28          s.s     $f8,0($sp)
29          s.s     $f14,0($sp)
30          s.s     $f6,0($sp)
31          .set    noreorder
32          .set    nomacro
33          j       $31
34          addu    $sp,$sp,8
35          .set    macro
36          .set    reorder
37
38          .end    _Z9test_func9new_floatS_S_
39  $LFE1:

(I've added the line numbers for convenience).  Everything in this
listing looks perfectly normal except lines 25 through 30.  None of
these 6 store instructions serves any purpose at all.  First of all,
they all write into the same slot on the stack, effectively clobbering
each other; and then everything in this stack frame is discarded on line
34, and nothing is ever read from it.

So that's the mystery I spoke of.  I'd like to find a way to eliminate
these extraneous store instructions.  I'm wondering if I might add any
directives, etc., to the operator functions, or whatever else might help
accomplish this.  Any insights would be greatly appreciated.

Thanks in advance -

Barry Wealand
Lockheed Martin Space Systems Co.
barry.wealand@lmco.com


             reply	other threads:[~2004-03-22 23:39 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-23  8:52 Barry Wealand [this message]
2004-03-30  9:46 ` Jim Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=405F78DC.6F04DF55@lmco.com \
    --to=barry.wealand@lmco.com \
    --cc=cliff.kancler@lmco.com \
    --cc=gcc@gcc.gnu.org \
    --cc=reed@reedkotler.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).