home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / gcc / config / next / machopic.c next >
C/C++ Source or Header  |  1996-06-21  |  23KB  |  999 lines

  1. /* NeXTSTEP mach-o pic support functions.
  2.    Copyright (C) 1992, 1994 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* 
  21.  * flag_pic = 1 ... generate only indirections
  22.  * flag_pic = 2 ... generate indirections and pure code
  23.  */
  24.  
  25.  
  26. /* 
  27.  *   This module assumes that (const (symbol_ref "foo")) is
  28.  *   a legal pic reference, which will not be changed.
  29.  */
  30. #include "config.h"
  31.  
  32. #ifdef MACHO_PIC
  33.  
  34. #include "tree.h"
  35. #include "obcp/cp-tree.h"
  36. #include "rtl.h"
  37. #include "output.h"
  38. #include "next/machopic.h"
  39. #include "insn-config.h"
  40. #include "insn-flags.h"
  41. #include "regs.h"
  42.  
  43. #include <stdio.h>
  44.  
  45. /* Answer if the symbol named IDENT is known to be defined in 
  46.    the current module.  It is critical, that it *never* says
  47.    something is defined, when it isn't.  However, it is ok to be 
  48.    sloppy on the other end of the scale, it will only generate 
  49.    worse code than if it guessed correct. */
  50.  
  51. static tree machopic_defined_list = 0;
  52.  
  53. extern int flag_dave_indirect;
  54.  
  55. enum machopic_addr_class
  56. machopic_classify_ident (ident)
  57.      tree ident;
  58. {
  59.   char *name = IDENTIFIER_POINTER (ident);
  60.   int lprefix = ((name[0] == '*' 
  61.           && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
  62.          || (   name[0] == '_' 
  63.              && name[1] == 'O' 
  64.              && name[2] == 'B' 
  65.              && name[3] == 'J'
  66.              && name[4] == 'C'
  67.              && name[5] == '_'));
  68.     
  69.   tree temp, decl  = lookup_name (ident, 0);
  70.  
  71.   if (!decl)
  72.     {
  73.       if (lprefix)
  74.     {
  75.       char *name = IDENTIFIER_POINTER (ident);
  76.       while (*name++)
  77.         {
  78.           if (! strncmp (name, "$stub\0", 6)
  79.           || ! strncmp (name, "$stub\"\0", 7))
  80.         return MACHOPIC_DEFINED_FUNCTION;
  81.         }
  82.       return MACHOPIC_DEFINED_DATA;
  83.     }
  84.  
  85.       for (temp = machopic_defined_list;
  86.        temp != NULL_TREE; 
  87.        temp = TREE_CHAIN (temp))
  88.     {
  89.       if (ident == TREE_VALUE (temp))
  90.         return MACHOPIC_DEFINED_DATA;
  91.     }
  92.  
  93.       return MACHOPIC_UNDEFINED;
  94.     }
  95.  
  96.   /* variable declarations */
  97.   else if (TREE_CODE (decl) == VAR_DECL)
  98.     {
  99.       if ((DECL_INITIAL (decl)
  100.            || TREE_STATIC (decl))
  101.           && ! TREE_PUBLIC (decl))
  102.     return MACHOPIC_DEFINED_DATA;
  103.     }
  104.  
  105.   /* function declarations */
  106.   else if (TREE_CODE (decl) == FUNCTION_DECL
  107.        && (!DECL_EXTERNAL (decl)
  108.            || DECL_LANG_SPECIFIC (decl) && DECL_NOT_REALLY_EXTERN (decl)))
  109.     {
  110.       if (TREE_STATIC (decl)
  111.       || TREE_ASM_WRITTEN (decl))
  112.     return MACHOPIC_DEFINED_FUNCTION;
  113.     }
  114.  
  115.   for (temp = machopic_defined_list;
  116.        temp != NULL_TREE; 
  117.        temp = TREE_CHAIN (temp))
  118.     {
  119.       if (ident == TREE_VALUE (temp))
  120.     if (TREE_CODE (decl) == FUNCTION_DECL)
  121.       return MACHOPIC_DEFINED_FUNCTION;
  122.     else
  123.       return MACHOPIC_DEFINED_DATA;
  124.     }
  125.   
  126.   if (TREE_CODE (decl) == FUNCTION_DECL)
  127.     {
  128.       if (lprefix)
  129.     return MACHOPIC_DEFINED_FUNCTION;
  130.       else
  131.     return MACHOPIC_UNDEFINED_FUNCTION;
  132.     }
  133.   else
  134.     {
  135.       if (lprefix)
  136.     return MACHOPIC_DEFINED_DATA;
  137.       else
  138.     return MACHOPIC_UNDEFINED_DATA;
  139.     }
  140. }
  141.  
  142.      
  143. enum machopic_addr_class
  144. machopic_classify_name (name)
  145.      char *name;
  146. {
  147.   return machopic_classify_ident (get_identifier (name));
  148. }
  149.  
  150. int
  151. machopic_ident_defined_p (ident)
  152.      tree ident;
  153. {
  154.   switch (machopic_classify_ident (ident))
  155.     {
  156.     case MACHOPIC_UNDEFINED:
  157.     case MACHOPIC_UNDEFINED_DATA:
  158.     case MACHOPIC_UNDEFINED_FUNCTION:
  159.       return 0;
  160.     default:
  161.       return 1;
  162.     }
  163. }
  164.  
  165. int
  166. machopic_name_defined_p (name)
  167.      char *name;
  168. {
  169.   return machopic_ident_defined_p (get_identifier (name));
  170. }
  171.  
  172. void
  173. machopic_define_ident (ident)
  174.      tree ident;
  175. {
  176.   if (!machopic_ident_defined_p (ident))
  177.     machopic_defined_list = 
  178.       perm_tree_cons (NULL_TREE, ident, machopic_defined_list);
  179. }
  180.  
  181. void
  182. machopic_define_name (name)
  183.      char *name;
  184. {
  185.   machopic_define_ident (get_identifier (name));
  186. }
  187.  
  188. /* This is a static to make inline functions work.  The rtx */
  189. /* representing the PIC base symbol allways points to here. */
  190. static char function_base[256];
  191.  
  192. char*
  193. machopic_function_base_name ()
  194. {
  195.   static char *name = 0, *curr_name;
  196.   static int base = 0;
  197.  
  198.   curr_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
  199.  
  200.   if (name != curr_name)
  201.     {
  202.       current_function_uses_pic_offset_table = 1;
  203.  
  204.       if (strchr (curr_name, ' '))
  205.     sprintf (function_base, "*\"L%s$pic_base\"", curr_name);
  206.       else
  207.     sprintf (function_base, "*L%s$pic_base", curr_name);
  208.  
  209.       name = curr_name;
  210.     }
  211.  
  212.   return function_base;
  213. }
  214.  
  215. static tree machopic_non_lazy_pointers = 0;
  216.  
  217. char* 
  218. machopic_non_lazy_ptr_name (name)
  219.      char *name;
  220. {
  221.   tree temp, ident = get_identifier (name);
  222.   
  223.   for (temp = machopic_non_lazy_pointers;
  224.        temp != NULL_TREE; 
  225.        temp = TREE_CHAIN (temp))
  226.     {
  227.       if (ident == TREE_VALUE (temp))
  228.     return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  229.     }
  230.  
  231.   {
  232.     char buffer[256];
  233.     tree ptr_name;
  234.  
  235.     strcpy (buffer, "*L");
  236.     if (name[0] == '*')
  237.       strcat (buffer, name+1);
  238.     else
  239.       {
  240.     strcat (buffer, "_");
  241.     strcat (buffer, name);
  242.       }
  243.       
  244.     strcat (buffer, "$non_lazy_ptr");
  245.     ptr_name = get_identifier (buffer);
  246.  
  247.     machopic_non_lazy_pointers 
  248.       = perm_tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
  249.  
  250.     TREE_USED (machopic_non_lazy_pointers) = 0;
  251.     return IDENTIFIER_POINTER (ptr_name);
  252.   }
  253. }
  254.  
  255. void
  256. machopic_validate_non_lazy_ptr (name)
  257.   char *name;
  258. {
  259.     tree temp, ident = get_identifier (name);
  260.  
  261.     for (temp = machopic_non_lazy_pointers;
  262.          temp != NULL_TREE;
  263.          temp = TREE_CHAIN (temp))
  264.       {
  265.         if (ident == TREE_PURPOSE (temp))
  266.           TREE_USED (temp) = 1;
  267.       }
  268. }
  269.  
  270.  
  271. static tree machopic_stubs = 0;
  272.  
  273. static int
  274. name_needs_quotes(name)
  275.      char *name;
  276. {
  277.   int c;
  278.   while ((c = *name++) != '\0')
  279.     {
  280.       if (!isalnum(c) && c != '_')
  281.         return 1;
  282.     }
  283.   return 0;
  284. }
  285.  
  286. char* 
  287. machopic_stub_name (name)
  288.      char *name;
  289. {
  290.   tree temp, ident = get_identifier (name);
  291.   
  292.   for (temp = machopic_stubs;
  293.        temp != NULL_TREE; 
  294.        temp = TREE_CHAIN (temp))
  295.     {
  296.       if (ident == TREE_VALUE (temp))
  297.     return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  298.     }
  299.  
  300.   {
  301.     char buffer[256];
  302.     tree ptr_name;
  303.     int needs_quotes = name_needs_quotes(name);
  304.  
  305.     if (needs_quotes)
  306.       strcpy (buffer, "*\"L");
  307.     else
  308.       strcpy (buffer, "*L");
  309.     if (name[0] == '*')
  310.       {
  311.     strcat (buffer, name+1);
  312.       }
  313.     else
  314.       {
  315.     strcat (buffer, "_");
  316.     strcat (buffer, name);
  317.       }
  318.  
  319.     if (needs_quotes)
  320.       strcat (buffer, "$stub\"");
  321.     else
  322.       strcat (buffer, "$stub");
  323.     ptr_name = get_identifier (buffer);
  324.  
  325.     machopic_stubs = perm_tree_cons (ptr_name, ident, machopic_stubs);
  326.     TREE_USED (machopic_stubs) = 0;
  327.  
  328.     return IDENTIFIER_POINTER (ptr_name);
  329.   }
  330. }
  331.  
  332. void
  333. machopic_validate_stub (name)
  334.   char *name;
  335. {
  336.     tree temp, ident = get_identifier (name);
  337.  
  338.     for (temp = machopic_stubs;
  339.          temp != NULL_TREE;
  340.          temp = TREE_CHAIN (temp))
  341.       {
  342.         if (ident == TREE_PURPOSE (temp))
  343.           TREE_USED (temp) = 1;
  344.       }
  345. }
  346.  
  347. /*
  348.  *  Transfrom ORIG, which any data source to the corresponding
  349.  *  source using indirections.  
  350.  */
  351.  
  352. rtx
  353. machopic_indirect_data_reference (orig, reg)
  354.      rtx orig, reg;
  355. {
  356.   rtx ptr_ref = orig;
  357.   
  358.   if (! MACHOPIC_INDIRECT)
  359.     return orig;
  360.  
  361.   if (GET_CODE (orig) == SYMBOL_REF)
  362.     {
  363.       char *name = XSTR (orig, 0);
  364.  
  365.       if (machopic_name_defined_p (name))
  366.     {
  367.       rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
  368.                    machopic_function_base_name ());
  369.  
  370. #ifdef HAVE_hi_sum
  371.       rtx hi_sum;
  372.       rtx offset = gen_rtx (CONST, Pmode, gen_rtx (MINUS, Pmode, orig, pic_base));
  373.  
  374.           rtx hi_sum_reg;
  375.           if (reload_in_progress)
  376.               hi_sum_reg = HI_SUM_TARGET_RTX;
  377.           else
  378.               hi_sum_reg = gen_reg_rtx (SImode);
  379.  
  380.       if (reg == 0) abort ();
  381.  
  382.       hi_sum = gen_rtx (SET, Pmode, hi_sum_reg,
  383.                 gen_rtx (PLUS, Pmode,
  384.                      pic_offset_table_rtx,
  385.                      gen_rtx (HIGH, Pmode, offset)));
  386.  
  387.       emit_insn (hi_sum);
  388.       
  389.       emit_insn (gen_rtx (SET, Pmode, reg,
  390.                   gen_rtx (LO_SUM, Pmode, 
  391.                        hi_sum_reg, 
  392.                        offset)));
  393.       if (0)
  394.       {
  395.         rtx insn = get_last_insn ();
  396.         rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
  397.         
  398.         if (note)
  399.           XEXP (note, 0) = orig;
  400.         else
  401.           REG_NOTES (insn) = gen_rtx (EXPR_LIST, 
  402.                       REG_EQUAL, orig, REG_NOTES (insn));
  403.       }
  404.  
  405.       orig = reg;
  406. #else
  407. #ifdef HAVE_lo_sum
  408.       if (reg == 0) abort ();
  409.  
  410.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  411.                   gen_rtx (HIGH, Pmode, 
  412.                        gen_rtx (CONST, Pmode, 
  413.                         gen_rtx (MINUS, Pmode,
  414.                              orig, pic_base)))));
  415.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  416.                   gen_rtx (LO_SUM, Pmode, reg, 
  417.                        gen_rtx (CONST, Pmode, 
  418.                         gen_rtx (MINUS, Pmode,
  419.                              orig, pic_base)))));
  420.       emit_insn (gen_rtx (USE, VOIDmode,
  421.                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  422.  
  423.       orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
  424. #else
  425. #ifdef MACHOPIC_M68K
  426.       orig = gen_rtx (PLUS, Pmode,
  427.               pic_offset_table_rtx, 
  428.               gen_rtx (CONST, Pmode, 
  429.                    gen_rtx (MINUS, Pmode,
  430.                         orig, pic_base)));
  431. #endif
  432. #endif
  433. #endif
  434.       return orig;
  435.     }
  436.  
  437.  
  438.       ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
  439.                          machopic_non_lazy_ptr_name (name));
  440.  
  441.  
  442.       ptr_ref = gen_rtx (MEM, Pmode, ptr_ref);
  443.       RTX_UNCHANGING_P (ptr_ref) = 1;
  444.  
  445.       return ptr_ref;
  446.     }
  447.   else if (GET_CODE (orig) == CONST)
  448.     {
  449.       rtx base, offset, result;
  450.  
  451.       /* legitimize both operands of the PLUS */
  452.       if (GET_CODE (XEXP (orig, 0)) == PLUS)
  453.     {
  454.       base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0), reg);
  455.       orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
  456.                            base == reg ? 0 : reg);
  457.     }
  458.       else 
  459.     return orig;
  460.  
  461.  
  462.       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
  463.         {
  464. #ifdef INT_14_BITS
  465.           if (INT_14_BITS (orig))
  466.             {
  467. #endif
  468.               result = plus_constant_for_output (base, INTVAL (orig));
  469. #ifdef INT_14_BITS
  470.             }
  471.  
  472.           else if (!reload_in_progress)
  473.             {
  474.                 orig = force_reg (Pmode, orig);
  475.                 result = gen_rtx (PLUS, Pmode, base, orig);
  476.             }
  477.           else
  478.             {
  479.               emit_insn (gen_rtx (SET, SImode, reg,
  480.                                   gen_rtx (PLUS, Pmode,
  481.                                            base, gen_rtx (HIGH, SImode, orig))));
  482.               emit_insn (gen_rtx (SET, SImode, reg,
  483.                                   gen_rtx (LO_SUM, SImode,
  484.                                            reg, orig)));
  485.               result = reg;
  486.             }
  487. #endif
  488.         }
  489.       else
  490.         {
  491.            result = gen_rtx (PLUS, Pmode, base, orig);
  492.         }
  493.  
  494.       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
  495.     RTX_UNCHANGING_P (result) = 1;
  496.  
  497.       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
  498.     {
  499.       if (reg)
  500.         {
  501.           emit_move_insn (reg, result);
  502.           result = reg;
  503.         }
  504.       else
  505.         {
  506.           result = force_reg (GET_MODE (result), result);
  507.         }
  508.     }
  509.  
  510.       return result;
  511.  
  512.     }
  513.   else if (GET_CODE (orig) == MEM)
  514.     {
  515.       XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
  516.       return ptr_ref;
  517.     }
  518. #ifndef MACHOPIC_M68K
  519.   else if (GET_CODE (orig) == PLUS
  520.        && GET_CODE (XEXP (orig, 0)) == REG
  521.        && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM)
  522.     {
  523.       if (reg)
  524.     {
  525.       emit_move_insn (reg, XEXP (orig, 0));
  526.       XEXP (ptr_ref, 0) = reg;
  527.     }
  528.  
  529.       return ptr_ref;
  530.     }
  531. #endif
  532.   else
  533.     return ptr_ref;
  534. }
  535.  
  536.  
  537. /* 
  538.  *  Transform TARGET (a MEM), which is a function call target, to the
  539.  *  corresponding symbol_stub if nessecary.  Return the a new MEM.
  540.  */
  541.  
  542. rtx
  543. machopic_indirect_call_target (target)
  544.      rtx target;
  545. {
  546.   if (GET_CODE (target) != MEM)
  547.     return target;
  548.   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
  549.     { 
  550.       enum machine_mode mode = GET_MODE (XEXP (target, 0));
  551.       char *name = XSTR (XEXP (target, 0), 0);
  552.       if (!machopic_name_defined_p (name)) 
  553.     {
  554.       if (flag_dave_indirect) 
  555.         {
  556.           XEXP (target, 0) = force_reg (Pmode, XEXP (target, 0));
  557.         }
  558.       else /* kevin_indirect */
  559.         {
  560.           char *stub_name = (char*)machopic_stub_name (name);
  561.           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
  562.           RTX_UNCHANGING_P (target) = 1;
  563.         }
  564.     } 
  565.     }
  566.   return target;
  567. }
  568.  
  569.  
  570. rtx
  571. machopic_legitimize_pic_address (orig, mode, reg)
  572.      rtx orig, reg;
  573.      enum machine_mode mode;
  574. {
  575.   rtx pic_ref = orig;
  576.  
  577.   if (! MACHOPIC_PURE)
  578.     return orig;
  579.  
  580.   /* First handle a simple SYMBOL_REF or LABEL_REF */
  581.   if (GET_CODE (orig) == LABEL_REF
  582.       || (GET_CODE (orig) == SYMBOL_REF
  583.       ))
  584.     {
  585.       /* addr(foo) = &func+(foo-func) */
  586.       rtx equiv = orig;
  587.       rtx pic_base;
  588.       orig = machopic_indirect_data_reference (orig, reg);
  589.       if (GET_CODE (orig) == PLUS 
  590.       && GET_CODE (XEXP (orig, 0)) == REG)
  591.     {
  592.       if (reg == 0)
  593.         return force_reg (mode, orig);
  594.  
  595.       emit_move_insn (reg, orig);
  596.       return reg;
  597.     }  
  598.  
  599.       pic_base = gen_rtx (SYMBOL_REF, Pmode, 
  600.               machopic_function_base_name ());
  601.  
  602.       if (GET_CODE (orig) == MEM)
  603.     {
  604.       if (reg == 0)
  605.         if (reload_in_progress)
  606.           abort ();
  607.         else
  608.           reg = gen_reg_rtx (Pmode);
  609.     
  610. #ifdef HAVE_lo_sum
  611.       if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
  612.           || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
  613.         {
  614. #ifdef HAVE_hi_sum
  615.           rtx hi_sum;
  616.           rtx offset = gen_rtx (CONST, Pmode,
  617.                     gen_rtx (MINUS, Pmode, XEXP (orig, 0), pic_base));
  618.     
  619.               rtx hi_sum_reg;
  620.  
  621.               if (reload_in_progress)
  622.                   hi_sum_reg = HI_SUM_TARGET_RTX;
  623.               else
  624.                   hi_sum_reg = gen_reg_rtx (SImode);
  625.  
  626.           hi_sum = gen_rtx (SET, Pmode, hi_sum_reg,
  627.                 gen_rtx (PLUS, Pmode,
  628.                      pic_offset_table_rtx,
  629.                      gen_rtx (HIGH, Pmode, offset)));
  630.  
  631.           emit_insn (hi_sum);
  632.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  633.                   gen_rtx (MEM, GET_MODE (orig),
  634.                        gen_rtx (LO_SUM, Pmode, 
  635.                             hi_sum_reg, 
  636.                             offset))));
  637.           pic_ref = reg;
  638.  
  639. #else
  640.           emit_insn (gen_rtx (USE, VOIDmode,
  641.                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  642.  
  643.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  644.                   gen_rtx (HIGH, Pmode, 
  645.                        gen_rtx (CONST, Pmode, 
  646.                             gen_rtx (MINUS, Pmode,
  647.                                  XEXP (orig, 0), 
  648.                                  pic_base)))));
  649.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  650.                   gen_rtx (LO_SUM, Pmode, reg, 
  651.                        gen_rtx (CONST, Pmode, 
  652.                             gen_rtx (MINUS, Pmode,
  653.                                  XEXP (orig, 0), 
  654.                                  pic_base)))));
  655.           pic_ref = gen_rtx (PLUS, Pmode,
  656.                  pic_offset_table_rtx, reg);
  657. #endif
  658.         }
  659.       else
  660. #endif
  661. #ifndef PIC_OFFSET_TABLE_RTX
  662. #define PIC_OFFSET_TABLE_RTX pic_offset_table_rtx
  663. #endif
  664.         {
  665.                 rtx pic = PIC_OFFSET_TABLE_RTX;
  666.                 if (GET_CODE (pic) != REG)
  667.                   {
  668.                     emit_move_insn (reg, pic);
  669.                     pic = reg;
  670.                   }
  671. #if 0
  672.           emit_insn (gen_rtx (USE, VOIDmode,
  673.                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  674. #endif
  675.  
  676.  
  677.           pic_ref = gen_rtx (PLUS, Pmode,
  678.                  pic, 
  679.                  gen_rtx (CONST, Pmode, 
  680.                       gen_rtx (MINUS, Pmode,
  681.                            XEXP (orig, 0), 
  682.                            pic_base)));
  683.         }
  684.       
  685. #ifndef HAVE_hi_sum
  686.       RTX_UNCHANGING_P (pic_ref) = 1;
  687.       emit_move_insn (reg, pic_ref);
  688.       pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
  689. #endif
  690.     }
  691.       else
  692.     {
  693.  
  694. #ifdef HAVE_lo_sum
  695.       if (GET_CODE (orig) == SYMBOL_REF 
  696.           || GET_CODE (orig) == LABEL_REF)
  697.         {
  698. #ifdef HAVE_hi_sum
  699.           rtx hi_sum;
  700.           rtx offset = gen_rtx (CONST, Pmode,
  701.                     gen_rtx (MINUS, Pmode, orig, pic_base));
  702.               rtx hi_sum_reg;
  703.  
  704.           if (reg == 0)
  705.         if (reload_in_progress)
  706.           abort ();
  707.         else
  708.          reg = gen_reg_rtx (SImode);
  709.     
  710.               if (reload_in_progress)
  711.                   hi_sum_reg = HI_SUM_TARGET_RTX;
  712.               else
  713.                   hi_sum_reg = gen_reg_rtx (SImode);
  714.  
  715.           hi_sum = gen_rtx (SET, Pmode, hi_sum_reg,
  716.                 gen_rtx (PLUS, Pmode,
  717.                      pic_offset_table_rtx,
  718.                      gen_rtx (HIGH, Pmode, offset)));
  719.  
  720.           emit_insn (hi_sum);
  721.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  722.                   gen_rtx (LO_SUM, Pmode, 
  723.                        hi_sum_reg, 
  724.                        offset)));
  725.           pic_ref = reg;
  726. #else
  727.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  728.                   gen_rtx (HIGH, Pmode, 
  729.                        gen_rtx (CONST, Pmode, 
  730.                             gen_rtx (MINUS, Pmode,
  731.                                  orig, pic_base)))));
  732.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  733.                   gen_rtx (LO_SUM, Pmode, reg, 
  734.                        gen_rtx (CONST, Pmode, 
  735.                             gen_rtx (MINUS, Pmode,
  736.                                  orig, pic_base)))));
  737.           pic_ref = gen_rtx (PLUS, Pmode,
  738.                  pic_offset_table_rtx, reg);
  739. #endif
  740.         }
  741.       else
  742. #endif
  743.         if (GET_CODE (orig) == REG)
  744.           {
  745.         return orig;
  746.           }
  747.         else
  748.           {
  749.                   rtx pic = PIC_OFFSET_TABLE_RTX;
  750.                   if (GET_CODE (pic) != REG)
  751.                     {
  752.                       emit_move_insn (reg, pic);
  753.                       pic = reg;
  754.                     }
  755. #if 0
  756.             emit_insn (gen_rtx (USE, VOIDmode,
  757.                     pic_offset_table_rtx));
  758. #endif
  759.         
  760.             pic_ref = gen_rtx (PLUS, Pmode,
  761.                    pic, 
  762.                    gen_rtx (CONST, Pmode, 
  763.                         gen_rtx (MINUS, Pmode,
  764.                              orig, pic_base)));
  765.           }
  766.     }
  767.  
  768.       RTX_UNCHANGING_P (pic_ref) = 1;
  769.  
  770.       if (GET_CODE (pic_ref) != REG)
  771.         {
  772.           if (reg != 0)
  773.             {
  774.               emit_move_insn (reg, pic_ref);
  775.               return reg;
  776.             }
  777.           else
  778.             {
  779.               return force_reg (mode, pic_ref);
  780.             }
  781.         }
  782.       else
  783.         {
  784.           return pic_ref;
  785.         }
  786.     }
  787.  
  788.   else if (GET_CODE (orig) == SYMBOL_REF)
  789.     return orig;
  790.  
  791.   else if (GET_CODE (orig) == PLUS
  792.        && (GET_CODE (XEXP (orig, 0)) == MEM
  793.            || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
  794.            || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
  795.        && XEXP (orig, 0) != pic_offset_table_rtx
  796.        && GET_CODE (XEXP (orig, 1)) != REG)
  797.     
  798.     {
  799.       rtx base, offset;
  800.       int is_complex;
  801.  
  802.       is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
  803.  
  804.       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
  805.       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
  806.                           Pmode, base == reg ? 0 : reg);
  807.       if (GET_CODE (orig) == CONST_INT)
  808.     {
  809. #ifdef INT_14_BITS
  810.           if (INT_14_BITS (orig))
  811. #endif
  812.             {
  813.               pic_ref = plus_constant_for_output (base, INTVAL (orig));
  814.               is_complex = 1;
  815.             }
  816. #ifdef INT_14_BITS
  817.           else if (!reload_in_progress)
  818.             {
  819.                 orig = force_reg (Pmode, orig);
  820.                 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
  821.             }
  822.           else
  823.             {
  824.               emit_insn (gen_rtx (SET, SImode, reg,
  825.                                   gen_rtx (PLUS, Pmode,
  826.                                            base, gen_rtx (HIGH, SImode, orig))));
  827.               emit_insn (gen_rtx (SET, SImode, reg,
  828.                                   gen_rtx (LO_SUM, SImode,
  829.                                            reg, orig)));
  830.               pic_ref = reg;
  831.             }
  832. #endif
  833.     }
  834.       else
  835.     {
  836.       pic_ref = gen_rtx (PLUS, Pmode, base, orig);
  837.     }
  838.  
  839.       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
  840.     RTX_UNCHANGING_P (pic_ref) = 1;
  841.  
  842.       if (reg && is_complex)
  843.     {
  844.       emit_move_insn (reg, pic_ref);
  845.       pic_ref = reg;
  846.     }
  847.       /* Likewise, should we set special REG_NOTEs here?  */
  848.     }
  849.  
  850.   else if (GET_CODE (orig) == CONST)
  851.     {
  852.       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
  853.     }
  854.  
  855.   else if (GET_CODE (orig) == MEM
  856.        && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
  857.     {
  858.       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
  859.  
  860.       addr = gen_rtx (MEM, GET_MODE (orig), addr);
  861.       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
  862.       emit_move_insn (reg, addr);
  863.       pic_ref = reg;
  864.     }
  865.  
  866.   return pic_ref;
  867. }
  868.  
  869.  
  870. void
  871. machopic_finish (asm_out_file)
  872.      FILE *asm_out_file;
  873. {
  874.   tree temp;
  875.  
  876.   for (temp = machopic_stubs;
  877.        temp != NULL_TREE; 
  878.        temp = TREE_CHAIN (temp))
  879.     {
  880.       char symb[256];
  881.       char stub[256];
  882.       char *symb_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
  883.       char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  884.  
  885.       tree decl  = lookup_name (TREE_VALUE (temp), 0);
  886.  
  887.       if (! TREE_USED (temp))
  888.           continue;
  889.  
  890.       /* don't emit stubs for static inline functions which has not been compiled. */
  891.       if (decl
  892.           && TREE_CODE (decl) == FUNCTION_DECL
  893.           && DECL_INLINE (decl)
  894.           && ! TREE_PUBLIC (decl)
  895.           && ! TREE_ASM_WRITTEN (decl))
  896.           continue;
  897.   
  898.       if (symb_name[0] == '*')
  899.     strcpy (symb, symb_name+1);
  900.       else if (symb_name[0] == '-' || symb_name[0] == '+')
  901.     strcpy (symb, symb_name);      
  902.       else
  903.     symb[0] = '_', strcpy (symb+1, symb_name);
  904.  
  905.       if (stub_name[0] == '*')
  906.     strcpy (stub, stub_name+1);
  907.       else
  908.     stub[0] = '_', strcpy (stub+1, stub_name);
  909.  
  910.       /* must be in aux-out.c */
  911.       machopic_output_stub (asm_out_file, symb, stub);
  912.       
  913.     }
  914.  
  915.   for (temp = machopic_non_lazy_pointers;
  916.        temp != NULL_TREE; 
  917.        temp = TREE_CHAIN (temp))
  918.     {
  919.       char *symb_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
  920.       char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  921.  
  922.       tree decl  = lookup_name (TREE_VALUE (temp), 0);
  923.  
  924.       if (! TREE_USED (temp))
  925.           continue;
  926.  
  927.       if (machopic_ident_defined_p (TREE_VALUE (temp))
  928.           || (decl && DECL_PRIVATE_EXTERN (decl)))
  929.     {
  930.       char symb[256];
  931.       
  932.       if (symb_name[0] == '*')
  933.         strcpy (symb, symb_name+1);
  934.       else
  935.         strcpy (symb, symb_name);
  936.  
  937.       data_section ();
  938.       assemble_align (UNITS_PER_WORD * BITS_PER_UNIT);
  939.       assemble_label (lazy_name);
  940.       assemble_integer (gen_rtx (SYMBOL_REF, Pmode, symb_name),
  941.                 GET_MODE_SIZE (Pmode), 1);
  942.     }
  943.       else
  944.     {
  945.       machopic_nl_symbol_ptr_section ();
  946.       assemble_name (asm_out_file, lazy_name); 
  947.       fprintf (asm_out_file, ":\n");
  948.  
  949.       fprintf (asm_out_file, "\t.indirect_symbol ");
  950.       assemble_name (asm_out_file, symb_name); 
  951.       fprintf (asm_out_file, "\n");
  952.  
  953.       assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 1);
  954.     }
  955.     }
  956. }
  957.  
  958. int 
  959. machopic_operand_p (op)
  960.      rtx op;
  961. {
  962.   if (MACHOPIC_JUST_INDIRECT)
  963.     {
  964.       while (GET_CODE (op) == CONST)
  965.     op = XEXP (op, 0);
  966.  
  967.       if (GET_CODE (op) == SYMBOL_REF)
  968.     return machopic_name_defined_p (XSTR (op, 0));
  969.       else
  970.     return 0;
  971.     }
  972.  
  973.   while (GET_CODE (op) == CONST)
  974.     op = XEXP (op, 0);
  975.  
  976.   if (GET_CODE (op) == MINUS
  977.        && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
  978.        && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
  979.        && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
  980.        && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
  981.     {
  982.       return 1;
  983.     }
  984.  
  985. #if 0
  986.   else if (GET_CODE (op) == SYMBOL_REF
  987.        && (machopic_classify_name (XSTR (op, 0))
  988.            == MACHOPIC_DEFINED_FUNCTION))
  989.     {
  990.       return 1;
  991.     }
  992. #endif
  993.  
  994.   return 0;
  995. }
  996.  
  997. #endif
  998.  
  999.