🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gcc.bug
Article #6335

GCC patch #6

#6335
From: buc
Date: Wed, 20 Dec 1995 00:00
190 lines
6693 bytes
        *emit-rtl.c (gen_lowpart_common): Handle lowpart on special hard regs
                             Dmitry K. Butskoy   (buc@stu.spb.su)

GCC:    2.7.2
CPU:    big-endians

(Our configuration:
        CPU:        mc68030/mc68882
        Computer:   BESTA   (similar to `mot3300 delta')
        System:     SVR3.1  (similar to sysV68)
        asm:        SGS  System V/68 R2V1  syntax  )


    I have found a better way to fix the problem reported by
`GCC patch v2' for GCC.2.7.0.

    There is `gen_lowpart_common' function in emit-rtl.c . This
function does:

****
    /* Return a value representing some low-order bits of X, where the number
       of low-order bits is given by MODE.  Note that no conversion is done
       between floating-point and fixed-point values, rather, the bit
       representation is returned.

       This function handles the cases in common between gen_lowpart, below,
       and two variants in cse.c and combine.c.  These are the cases that can
       be safely handled at all points in the compilation.

       If this is not a case we can handle, return 0.  */

    rtx
    gen_lowpart_common (mode, x)
         enum machine_mode mode;
         register rtx x;
    {
****

    To make this work `gen_lowpart_common()' computes a offset
of low part in X . To store this offset variable `word' is used.
    All is OK, but for cases when  X  is a COMPLEX_REAL type
represented by hard float-point registers, the value of `word' computes
incorrectly. E.g. (for m68k):


                  ** BIG  ENDIAN **

                   UNITS_PER_WORD = 4   (  o o o o  )

example #1 (memory):

        .__________complex__double__________.
        .____double_____.   .____double_____.

. . .   o o o o   o o o o   o o o o   o o o o   . . .
       $0        $4        $8       $12

        ,__high__part___,   ,___low__part___,

                            ^ word = 2  (= sizeof(high part) / UNITS_PER_WORD)


example #2 (data registers):

        .__________complex__double__________.
        .____double_____.   .____double_____.

. . .   o-o-o-o   o-o-o-o   o-o-o-o   o-o-o-o   . . .
        reg0      reg1      reg2      reg3

        ,__high__part___,   ,___low__part___,

                            ^ word = 2  (= sizeof(high part) / UNITS_PER_WORD)


example #3 (float-point registers):

        .__________complex__double__________.
        .____double_____.   .____double_____.

. . .   xxxxxxxxxxxxxxxxx   xxxxxxxxxxxxxxxxx   . . .
        fp_reg0             fp_reg1

        ,__high__part___,   ,___low__part___,

                            ^ word = 1  (!= sizeof(high part) / UNITS_PER_WORD)


    At the last example sizeof(high part) always is `1' in its context,
independent of the used machine mode (SFmode, DFmode or XFmode).

    I think there is some reasons to handle last case (example #3)
by `gen_lowpart_common()' . For example, it is actual for passing
complex real arguments by fp registers or returning complex real value
by fp registers.
    I tried to return complex reals such way on m68k. For test,

        typedef __complex double foo;
        foo bar(foo a , foo b ) {
                return a+b;
        }

instead of evident result,

                file  "bar.c"
                even
        global bar
        bar:
                fmov.d 4(%sp),%fp0
                fadd.d 20(%sp),%fp0
                fmov.d 12(%sp),%fp1
                fadd.d 28(%sp),%fp1
                rts
                nop

it produce,

                file  "bar.c"
                even
        global bar
        bar:
                fmov.d 4(%sp),%fp0
                fadd.d 20(%sp),%fp0
                fmov.d 12(%sp),%fp2
                fadd.d 28(%sp),%fp2
                rts
                nop

where instead of fp0/fp1 pair  fp0+fp2 are used.

    To fix the problem considered, one should recompute the `word' value
for case  `X' is a  `REG' (register). When  REG is not a special hard
register, it must produce the same value as a usual way.
    To recompute `word' value  I use a `HARD_REGNO_NREGS' macro, which
is defined in all tm-headers:

****
    /* Return number of consecutive hard regs needed starting at reg REGNO
       to hold something of mode MODE.
       This is ordinarily the length in words of a value of mode MODE
       but can be less for certain modes in special long registers.

    #define HARD_REGNO_NREGS(REGNO, MODE)   \
****


    Hear is a patch for emit-rtl.c,

`diff -p -c4':

*** emit-rtlO.c        Fri Dec  8 19:23:02 1995
--- emit-rtl.c  Mon Dec 18 17:43:29 1995
*************** gen_lowpart_common (mode, x)
*** 611,618 ****
--- 611,629 ----
            ? SUBREG_REG (x)
            : gen_rtx (SUBREG, mode, SUBREG_REG (x), SUBREG_WORD (x)));
    else if (GET_CODE (x) == REG)
      {
+       /* Recomputing `word' value for a case of hard registers.
+        Some special long registers can store modes which are
+        more wide than UNITS_PER_WORD .   */
+       /* We check first two conditions below as above, else `word' always
+        has value of 0 .  */
+       if (WORDS_BIG_ENDIAN
+         && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
+         && REGNO (x) < FIRST_PSEUDO_REGISTER)
+         word = HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)) -
+                   HARD_REGNO_NREGS (REGNO (x), mode) ;
+
        /* If the register is not valid for MODE, return 0.  If we don't
         do this, there is no way to fix up the resulting REG later.
         But we do do this if the current REG is not valid for its
         mode.  This latter is a kludge, but is required due to the


    (I use `REGNO(x)' in `HARD_REGNO_NREGS (REGNO (x), mode)' to get
    the number of the hard regs the same class as X ).

    This variant works on m68k, but I`m not sure about other big-endian
machines.

    I think, my previous message about the problem considered
(with subject `GCC patch v2') may be removed.

                        Dmitry K. Butskoy,
                        Saint-Petersburg State Technical University,
                        St. Petersburg, Russia.

                        <buc@stu.spb.su>
Technical Details
Message-ID: <AAJq-rmyI0@stu.spb.su>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 113d02,785ece42a51bdc8b,start
X-Google-Attributes: gid113d02,public
From: buc@stu.spb.SU
Subject: GCC patch #6
Date: 1995/12/20
Message-ID: <AAJq-rmyI0@stu.spb.su>
X-Deja-AN: 122393822
distribution: gnu
sender: daemon@cis.ohio-state.edu
organization: State Technical University of St. Petersburg
newsgroups: gnu.gcc.bug