[gnu.gcc.bug] gcc 1.35 on MIPS

trq@MOOSE.CITA.UTORONTO.CA (Tom Quinn) (05/25/89)

I have played with trying to bring up gcc 1.35 on an SGI 4D/120.  I am
using mips.md, out-mips.c, tm-mips.h and xm-umips.h.  Here
are the problems so far:

In mips.md: output_asm_insn() barfs at the "%u" construct in assembler
strings saying something about having no operand number after a
letter.  I kludged around this by changing every instance of "%u" to
"%u0" in mips.md eg:
***************
*** 60,64
  {  if(GET_CODE(operands[2])==CONST_INT)
       { if (CONST_OK_FOR_LETTER_P(INTVAL(operands[2]),'I'))
!            { return \"addi%u\\t%0,%1,%x2\\t#addsi3\\t%1,%d2 -> %0\";
             }
         else  if (CONST_OK_FOR_LETTER_P(INTVAL(operands[2]),'J'))

--- 60,64 -----
  {  if(GET_CODE(operands[2])==CONST_INT)
       { if (CONST_OK_FOR_LETTER_P(INTVAL(operands[2]),'I'))
!            { return \"addi%u0\\t%0,%1,%x2\\t#addsi3\\t%1,%d2 -> %0\";
             }
         else  if (CONST_OK_FOR_LETTER_P(INTVAL(operands[2]),'J'))

etc.

In out-mips.c:  SGIs don't have the include file <sys/timeb.h>; I
#ifdefed it out with "#ifndef USG"

my_print_rtx() and my_print_insncode() play around with "outfile"
which is declared as static in print-tree.c and rtl.c.  I just made
these routines no-ops (programming by ommission).

In tm-mips.h, the MIPS compiler barfed at the HARD_REGNO_MODE_OK()
macro.  It said something about incompatible operands to "?".  I added
a cast to make it happy.
There were a couple of typos in the PRINT_OPERAND macro.  Here is a
diff for the tm-mips.h file:
diff -c2 -r1.1 tm-mips.h
*** /tmp/,RCSt1a00749   Wed May 24 17:42:13 1989
--- tm-mips.h   Mon May  1 19:08:15 1989
***************
*** 210,214

  #define HARD_REGNO_MODE_OK(REGNO, MODE) \
!    (((REGNO) <32) ? ((MODE) != SFmode) && ((MODE) != DFmode)\
                  : (   ((MODE) == SFmode) || ((MODE) == DFmode)) \
                      && (((REGNO) % 2 ) == 0))

--- 210,214 -----

  #define HARD_REGNO_MODE_OK(REGNO, MODE) \
!    (((REGNO) <32) ? (int)(((MODE) != SFmode) && ((MODE) != DFmode))\
                  : (   ((MODE) == SFmode) || ((MODE) == DFmode)) \
                      && (((REGNO) % 2 ) == 0))
***************
*** 1264,1268

  #define PRINT_OPERAND(FILE, X, CODE)  \
! { if ((CODE) == 'u')\
      if (TARGET_NOFIXED_OVFL)fprintf(FILE,"u");      \
    else if (GET_CODE (X) == REG)
\

--- 1264,1268 -----

  #define PRINT_OPERAND(FILE, X, CODE)  \
! { if ((CODE) == 'u') {\
      if (TARGET_NOFIXED_OVFL)fprintf(FILE,"u");      \
    } \
***************
*** 1266,1269
  { if ((CODE) == 'u')\
      if (TARGET_NOFIXED_OVFL)fprintf(FILE,"u");      \
    else if (GET_CODE (X) == REG)
\
      { extern char *reg_numchar[];\

--- 1266,1270 -----
  { if ((CODE) == 'u') {\
      if (TARGET_NOFIXED_OVFL)fprintf(FILE,"u");      \
+   } \
    else if (GET_CODE (X) == REG)
\
      { extern char *reg_numchar[];\
***************
*** 1271,1275
               :reg_numchar[REGNO (X) ]);       \
      }\
!   else
      { \
        if (GET_CODE (X) == MEM)
\

--- 1272,1276 -----
               :reg_numchar[REGNO (X) ]);       \
      }\
!   else \
      { \
        if (GET_CODE (X) == MEM)
\

I ended up creating a "tm-iris.h" file which included "tm-mips.h" and
added a few things.  The meat of this follows, but some coments are in
order:
STACK_ARGS_ADJUST() was misspelled in tm-mips.h.  Also the minimum
size has to be 32, not 16.
Now the nasty bit: In the FUNCTION_PROLOGUE() macro, an instruction to
decrement the stack pointer must be emitted before using it.  It
appears that if a negative offset from the stackpointer crosses a page
boundary, the program will receive a segmentation violation.  My guess
is that memory management is accomplished by comparing the address
against the stackpointer when a page fault occurs.  If the address is
lower than the stackpointer, a segmentation signal is delivered;
otherwise, all pages from the stackpointer up are made valid.

This scheme will cause problems with GCC's builtin_alloca.  (At least
in stage2/cccp) If builtin_alloca is used to decrement the
stackpointer below a page boundary, and that space is not used until
passed to a system call (say read()) then the call will return with an
invalid address error because a page fault didn't occur to give the
system a chance to make it valid.  A kludge to get around this is to
have a piece of code in expand_builtin() that would emit an
instruction to write or read the memory where the stackpointer points,
thereby causing the pagefault.  (Can someone tell me how to do this?)

Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

-------tm-iris.h----------
#include "tm-mips.h"
^L
/* Names to predefine in the preprocessor for this target machine.  */

#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -Dmips"
#undef CPP_SPEC
#define CPP_SPEC "-Dsgi -DSVR3 -Dhost_mips -DMIPSEB -DSYSTYPE_SYSV -DLANGUAGE_C
"

#define STARTFILE_SPEC  \
  "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"

#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} crtn.o%s"

#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
  fprintf (FILE, "\t.file\t1 \"%s\"\n", FILENAME)

#undef ASM_OUTPUT_SOURCE_LINE
#define ASM_OUTPUT_SOURCE_LINE(file, line)              \
  { static int sym_lineno = 1;                          \
    fprintf (file, "\t.loc\t1 %d\nLM%d:\n",     \
             line, sym_lineno);         \
    sym_lineno += 1; }

#undef STACK_ARGS_ADJUST
#define STACK_ARGS_ADJUST(SIZE)                                         \
{                                                                       \
  SIZE.constant += 4;                                                   \
  if (SIZE.var)                                                         \
    {                                                                   \
      rtx size1 = ARGS_SIZE_RTX (SIZE);                                 \
      rtx rounded = gen_reg_rtx (SImode);                               \
      rtx label = gen_label_rtx ();                                     \
      emit_move_insn (rounded, size1);                                  \
      /* Needed: insns to jump to LABEL if ROUNDED is < 16.  */         \
      abort ();                                                         \
      emit_move_insn (rounded, gen_rtx (CONST_INT, VOIDmode, 16));      \
      emit_label (label);                                               \
      SIZE.constant = 0;                                                \
      SIZE.var = rounded;                                               \
    }                                                                   \
  else if (SIZE.constant < 32)                                          \
    SIZE.constant = 32;                                                 \
}

#undef FUNCTION_PROLOGUE
#define FUNCTION_PROLOGUE(FILE, SIZE)     \
{ register int regno;                                           \
  register int mask = 0, fmask=0;                                       \
  static char dont_save_regs[] = CALL_USED_REGISTERS;   \
  register int push_loc = 0,tsize = SIZE  - (STARTING_FRAME_OFFSET)+4;\
  char *fp_str;\
  extern char *reg_numchar[];\
  extern int  current_function_total_framesize;  \
  this_varargs_suspect = VARARGS_SUSPECTED  ;\
  fp_str = TARGET_NAME_REGS ? reg_names[STACK_POINTER_REGNUM]\
               : reg_numchar[STACK_POINTER_REGNUM];\
  for (regno = 0; regno < 32; regno++)  \
    if (MUST_SAVE_REG_LOGUES || (regs_ever_live[regno] && !dont_save_regs[regno]
))\
      {tsize += 4; mask |= 1 << regno;}\
  for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno += 2)   \
    if (regs_ever_live[regno] && !dont_save_regs[regno])        \
      {tsize += 8; fmask |= 1 << (regno-32);}\
    if (THIS_VARARGS_SUSPECTED) tsize += 16;  \
  fprintf(FILE," #PROLOGUE\n");\
    regno = STACK_POINTER_REGNUM;  \
    tsize = AL_ADJUST_ALIGN(tsize);  \
\
  fprintf(FILE,"\tsubu\t%s,%d\t#temp=%5d,saveregs=%5d, sfo=%5d\n",\
                TARGET_NAME_REGS ? reg_names[29]\
           :reg_numchar[29],tsize,SIZE,tsize-SIZE+ (STARTING_FRAME_OFFSET),\
           STARTING_FRAME_OFFSET);\
  if(!frame_pointer_needed)\
    fprintf(FILE,"#define __0__gcc  %d\n",tsize);\
  \
  push_loc = 0; current_function_total_framesize = tsize;\
  fprintf (FILE, " #\t.mask\t0x%x\n", mask);            \
  for (regno = 31; regno >= 30; regno--)        \
   {\
    if (MUST_SAVE_REG_LOGUES ||(regs_ever_live[regno] && !dont_save_regs[regno])
){      \
      push_loc += 4;\
       fprintf(FILE,"\tsw\t%s,%d(%s)\n", TARGET_NAME_REGS ? reg_names[regno]\
               : reg_numchar[regno],push_loc,fp_str);}\
\
    \
   }   \
   if (THIS_VARARGS_SUSPECTED)\
      { int fregno;\
        fprintf(FILE,"\taddi\t%s,$0,%d\t#Varargs suspicion\n",\
             TARGET_NAME_REGS ? reg_names[9]\
                : reg_numchar[9],tsize);\
        fprintf(FILE,"\tsw\t%s,%d(%s)\t#Varargs suspicion\n",\
             TARGET_NAME_REGS ? reg_names[9]\
                : reg_numchar[9],\
                tsize-4, \
             TARGET_NAME_REGS ? reg_names[29]\
                : reg_numchar[29]);\
        for (fregno = 44; fregno< 48; fregno += 2)\
         {push_loc += 8;        \
       fprintf(FILE,"\ts.d\t%s,%d(%s)\t#Varargs Suspicion\n",\
                     ((TARGET_NAME_REGS)\
                       ?reg_names[fregno]: reg_numchar[fregno]),\
                                         push_loc,fp_str);}\
        }\
  for (regno = 29; regno >= 0; regno--) \
   {\
    if (MUST_SAVE_REG_LOGUES ||(regs_ever_live[regno] && !dont_save_regs[regno])
){      \
      push_loc += 4;\
       fprintf(FILE,"\tsw\t%s,%d(%s)\n", TARGET_NAME_REGS ? reg_names[regno]\
               : reg_numchar[regno],push_loc,fp_str);}\
\
    \
   }   \
  fprintf (FILE, " #\t.fmask\t0x%x\n", fmask);          \
  for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno += 2)   \
    if (regs_ever_live[regno] && !dont_save_regs[regno]){push_loc += 8; \
       fprintf(FILE,"\ts.d\t%s,%d(%s)\n",((TARGET_NAME_REGS) ?reg_names[regno]\
               : reg_numchar[regno]),push_loc,fp_str);}\
  if(frame_pointer_needed)\
    fprintf(FILE,"\taddu\t%s,%s,%d\n",\
               (TARGET_NAME_REGS ? reg_names[FRAME_POINTER_REGNUM]  :\
               reg_numchar[FRAME_POINTER_REGNUM]),\
               (TARGET_NAME_REGS ? reg_names[29]  : reg_numchar[29]), tsize);\
  fprintf(FILE," #END PROLOGUE\n");\
  }