home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gcc-2.7.2.1-base.tgz / gcc-2.7.2.1-base.tar / fsf / gcc / config / 1750a / 1750a.c next >
C/C++ Source or Header  |  1995-09-15  |  15KB  |  632 lines

  1. /* Subroutines for insn-output.c for MIL-STD-1750.
  2.    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.    Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.  */
  21.  
  22. #ifndef FILE
  23. #include <stdio.h>
  24. #endif
  25. #include <string.h>
  26.  
  27. #define __datalbl
  28. #include "config.h"
  29. #include "rtl.h"
  30. #include "tree.h"
  31. #include "expr.h"
  32. #define HAVE_cc0
  33. #include "conditions.h"
  34. #include "real.h"
  35.  
  36. struct datalabel_array datalbl[DATALBL_ARRSIZ];
  37. int datalbl_ndx = -1;
  38. struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
  39. int jmplbl_ndx = -1;
  40. int label_pending = 0, program_counter = 0;
  41. enum section current_section = Normal;
  42. char *sectname[4] =
  43. {"Init", "Normal", "Konst", "Static"};
  44.  
  45. int
  46. notice_update_cc (exp)
  47.      rtx exp;
  48. {
  49.   if (GET_CODE (exp) == SET)
  50.     {
  51.       enum rtx_code src_code = GET_CODE (SET_SRC (exp));
  52.       /* Jumps do not alter the cc's.  */
  53.       if (SET_DEST (exp) == pc_rtx)
  54.     return;
  55.       /* Moving a register or constant into memory doesn't alter the cc's. */
  56.       if (GET_CODE (SET_DEST (exp)) == MEM
  57.       && (src_code == REG || src_code == CONST_INT))
  58.     return;
  59.       /* Function calls clobber the cc's.  */
  60.       if (src_code == CALL)
  61.     {
  62.       CC_STATUS_INIT;
  63.       return;
  64.     }
  65.       /* Emulated longword bit-ops leave cc's incorrect */
  66.       if (GET_MODE (SET_DEST (exp)) == HImode ?
  67.            src_code == AND || src_code == IOR ||
  68.            src_code == XOR || src_code == NOT : 0)
  69.     {
  70.       CC_STATUS_INIT;
  71.       return;
  72.     }
  73.       /* Tests and compares set the cc's in predictable ways.  */
  74.       if (SET_DEST (exp) == cc0_rtx)
  75.     {
  76.       CC_STATUS_INIT;
  77.       cc_status.value1 = SET_SRC (exp);
  78.       return;
  79.     }
  80.       /* Anything else will set cc_status. */
  81.       cc_status.flags = CC_NO_OVERFLOW;
  82.       cc_status.value1 = SET_SRC (exp);
  83.       cc_status.value2 = SET_DEST (exp);
  84.       return;
  85.     }
  86.   else if (GET_CODE (exp) == PARALLEL
  87.        && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
  88.     {
  89.       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
  90.     return;
  91.       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
  92.     {
  93.       CC_STATUS_INIT;
  94.       cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
  95.       return;
  96.     }
  97.       CC_STATUS_INIT;
  98.     }
  99.   else
  100.     {
  101.       CC_STATUS_INIT;
  102.     }
  103. }
  104.  
  105.  
  106. rtx
  107. function_arg (cum, mode, type, named)
  108.      int cum;
  109.      enum machine_mode mode;
  110.      tree type;
  111.      int named;
  112. {
  113.   int size;
  114.   rtx result;
  115.  
  116.   if (MUST_PASS_IN_STACK (mode, type))
  117.     return (rtx) 0;
  118.   if (mode == BLKmode)
  119.     size = int_size_in_bytes (type);
  120.   else
  121.     size = GET_MODE_SIZE (mode);
  122.   if (cum + size < 12)
  123.     return gen_rtx (REG, mode, cum);
  124.   else
  125.     return (rtx) 0;
  126. }
  127.  
  128.  
  129. #ifndef STRDUP
  130. char *
  131. strdup (str)
  132.      char *str;
  133. {
  134.   char *p;
  135.   if (str == NULL)
  136.     return NULL;
  137.   if ((p = (char *) malloc (strlen (str) + 1)) == NULL)
  138.     {
  139.       fprintf (stderr, "dynamic memory exhausted");
  140.       abort ();
  141.     }
  142.   return strcpy (p, str);
  143. }
  144.  
  145. #endif
  146.  
  147.  
  148. double
  149. get_double (x)
  150.      rtx x;
  151. {
  152.   union
  153.     {
  154.       double d;
  155.       long i[2];
  156.     }
  157.   du;
  158.  
  159.   du.i[0] = CONST_DOUBLE_LOW (x);
  160.   du.i[1] = CONST_DOUBLE_HIGH (x);
  161.   return du.d;
  162. }
  163.  
  164. char *
  165. float_label (code, value)
  166.      char code;
  167.      double value;
  168. {
  169.   int i = 1;
  170.   static char label[32];
  171.   char *p;
  172.  
  173.   label[0] = code;
  174.   p = label + 1;
  175.   sprintf (p, "%lf", value);
  176.   while (*p)
  177.     {
  178.       *p = (*p == '+') ? 'p' :
  179.     (*p == '-') ? 'm' : *p;
  180.       p++;
  181.     }
  182.   return strdup (label);
  183. }
  184.  
  185.  
  186. char *
  187. movcnt_regno_adjust (op)
  188.      rtx *op;
  189. {
  190.   static char outstr[40];
  191.   int cntreg = REGNO (op[2]), cntreg_1750 = REGNO (op[0]) + 1;
  192.   int dstreg = REGNO (op[0]), srcreg = REGNO (op[1]);
  193.  
  194.   if (cntreg == cntreg_1750)
  195.     sprintf (outstr, "mov r%%0,r%%1");
  196.   else if (dstreg + 1 == srcreg && srcreg == cntreg + 2)
  197.     sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", cntreg, dstreg);
  198.   else if (dstreg + 1 == srcreg && srcreg < cntreg)
  199.     sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, cntreg);
  200.   else if (srcreg + 1 == cntreg && dstreg > cntreg)
  201.     sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, dstreg);
  202.   else
  203.     sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,%%1\n\txwr r%d,r%d",
  204.          cntreg, cntreg_1750, cntreg_1750, cntreg);
  205.   return outstr;
  206. }
  207.  
  208. char *
  209. mod_regno_adjust (instr, op)
  210.      char *instr;
  211.      rtx *op;
  212. {
  213.   static char outstr[40];
  214.   char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
  215.   int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
  216.  
  217.   if (modregno_gcc == modregno_1750)
  218.     sprintf (outstr, "%s r%%0,%s%%2", instr, r);
  219.   else
  220.     sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
  221.     modregno_gcc, modregno_1750, instr, r, modregno_1750, modregno_gcc);
  222.   return outstr;
  223. }
  224.  
  225.  
  226. /* Auxiliary to `nonindirect_operand':
  227.    Check if op is a valid memory operand for 1750A arith./logic (non-move)
  228.    instructions. */
  229. int
  230. memop_valid (op)
  231.      rtx op;
  232. {
  233.   if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode)
  234.     return 0;
  235.   switch (GET_CODE (op))
  236.     {
  237.     case MEM:
  238.     case MINUS:
  239.     case MULT:
  240.     case DIV:
  241.       return 0;
  242.     case PLUS:
  243.       if (!memop_valid (XEXP (op, 0)))
  244.     return 0;
  245.       return memop_valid (XEXP (op, 1));
  246.     case REG:
  247.       if (REGNO (op) > 0)
  248.     return 1;
  249.       return 0;
  250.     case CONST:
  251.     case CONST_INT:
  252.     case SYMBOL_REF:
  253.     case SUBREG:
  254.       return 1;
  255.     default:
  256.       printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
  257.       return 1;
  258.     }
  259. }
  260.  
  261. /* extra predicate for recog: */
  262. int
  263. nonindirect_operand (op, mode)
  264.      rtx op;
  265.      enum machine_mode mode;
  266. {
  267.   int retval;
  268.  
  269.   switch (GET_CODE (op))
  270.     {
  271.     case MEM:
  272.       retval = memop_valid (XEXP (op, 0));
  273.       return retval;
  274.     case REG:
  275.       return 1;
  276.     default:
  277.       if (!CONSTANT_P (op))
  278.     return 0;
  279.     }
  280.   return 1;
  281. }
  282.  
  283. /* predicate for the STC instruction: */
  284. int
  285. small_nonneg_const (op, mode)
  286.      rtx op;
  287.      enum machine_mode mode;
  288. {
  289.   if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
  290.     return 1;
  291.   return 0;
  292. }
  293.  
  294.  
  295. /* predicate for 1750 `B' addressing mode (Base Register with Offset)
  296.    memory operand */
  297. int
  298. b_mode_operand (op)
  299.      rtx op;
  300. {
  301.   if (GET_CODE (op) == MEM)
  302.     {
  303.       rtx inner = XEXP (op, 0);
  304.       if (GET_CODE (inner) == PLUS)
  305.     {
  306.       rtx plus_op0 = XEXP (inner, 0);
  307.       if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
  308.         {
  309.           rtx plus_op1 = XEXP (inner, 1);
  310.           if (GET_CODE (plus_op1) == CONST_INT
  311.           && INTVAL (plus_op1) >= 0
  312.           && INTVAL (plus_op1) <= 255)
  313.         return 1;
  314.         }
  315.     }
  316.     }
  317.   return 0;
  318. }
  319.  
  320. /* Decide whether to output a conditional jump as a "Jump Conditional"
  321.    or as a "Branch Conditional": */
  322.  
  323. int
  324. find_jmplbl (labelnum)
  325.      int labelnum;
  326. {
  327.   int i, found = 0;
  328.  
  329.   for (i = 0; i <= jmplbl_ndx; i++)
  330.     if (labelnum == jmplbl[i].num)
  331.       {
  332.     found = 1;
  333.     break;
  334.       }
  335.   if (found)
  336.     return i;
  337.   return -1;
  338. }
  339.  
  340. char *
  341. branch_or_jump (condition, targetlabel_number)
  342.      char *condition;
  343.      int targetlabel_number;
  344. {
  345.   static char buf[30];
  346.   int index;
  347.  
  348.   if ((index = find_jmplbl (targetlabel_number)) >= 0)
  349.     if (program_counter - jmplbl[index].pc < 128)
  350.       {
  351.     sprintf (buf, "b%s %%l0", condition);
  352.     return buf;
  353.       }
  354.   sprintf (buf, "jc %s,%%l0", condition);
  355.   return buf;
  356. }
  357.  
  358.  
  359. int
  360. unsigned_comparison_operator (insn)
  361.      rtx insn;
  362. {
  363.   switch (GET_CODE (insn))
  364.     {
  365.     case GEU:
  366.     case GTU:
  367.     case LEU:
  368.     case LTU:
  369.       return 1;
  370.     default:
  371.       return 0;
  372.     }
  373. }
  374.  
  375. int
  376. next_cc_user_is_unsigned (insn)
  377.      rtx insn;
  378. {
  379.   if ( !(insn = next_cc0_user (insn)))
  380.     abort ();
  381.   else if (GET_CODE (insn) == JUMP_INSN
  382.        && GET_CODE (PATTERN (insn)) == SET
  383.        && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
  384.     return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0));
  385.   else if (GET_CODE (insn) == INSN
  386.        && GET_CODE (PATTERN (insn)) == SET)
  387.     return unsigned_comparison_operator (SET_SRC (PATTERN (insn)));
  388.   else
  389.     abort ();
  390. }
  391.  
  392.  
  393.  
  394. /* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been
  395.    made functions: */
  396.  
  397. print_operand (file, x, kode)
  398.      FILE *file;
  399.      rtx x;
  400.      enum rtx_code kode;
  401. {
  402.   switch (GET_CODE (x))
  403.     {
  404.     case REG:
  405.       fprintf (file, "%d", REGNO (x));
  406.       break;
  407.     case SYMBOL_REF:
  408.       fprintf (file, "%s", XSTR (x, 0));
  409.       break;
  410.     case LABEL_REF:
  411.     case CONST:
  412.     case MEM:
  413.       if (kode == 'Q')
  414.     fprintf (file, "r%d,%d",
  415.          REGNO (XEXP (XEXP (x, 0), 0)),
  416.          INTVAL (XEXP (XEXP (x, 0), 1)));
  417.       else
  418.         output_address (XEXP (x, 0));
  419.       break;
  420.     case CONST_DOUBLE:
  421. /*    {
  422.     double value = get_double (x);
  423.     char fltstr[32];
  424.     sprintf (fltstr, "%lf", value);
  425.  
  426.     if (kode == 'D' || kode == 'E')
  427.       {
  428.         int i, found = 0;
  429.         for (i = 0; i <= datalbl_ndx; i++)
  430.           if (strcmp (fltstr, datalbl[i].value) == 0)
  431.         {
  432.           found = 1;
  433.           break;
  434.         }
  435.         if (!found)
  436.           {
  437.         strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
  438.         datalbl[i].name = float_label (kode, value);
  439.         datalbl[i].size = (kode == 'E') ? 3 : 2;
  440.         check_section (Konst);
  441.         fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
  442.             (kode == 'E' ? "ef" : "f"), fltstr);
  443.         check_section (Normal);
  444.           }
  445.       }
  446.     else if (kode == 'F' || kode == 'G')
  447.       {
  448.         int i, found = 0;
  449.         for (i = 0; i <= datalbl_ndx; i++)
  450.           if (strcmp (fltstr, datalbl[i].value) == 0)
  451.         {
  452.           found = 1;
  453.           break;
  454.         }
  455.         if (!found)
  456.           {
  457.         fprintf (stderr,
  458.            "float value %lfnot found upon label reference\n", value);
  459.         strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
  460.         datalbl[i].name = float_label (kode, value);
  461.         datalbl[i].size = (kode == 'G') ? 3 : 2;
  462.         check_section (Konst);
  463.         fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
  464.             (kode == 'G' ? "ef" : "f"), fltstr);
  465.         check_section (Normal);
  466.           }
  467.         fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
  468.       }
  469.     else
  470.       fprintf (file, " %s  ;P_O cst_dbl ", fltstr);
  471.       }
  472.  */
  473.       fprintf (file, "%lf", get_double (x));
  474.       break;
  475.     case CONST_INT:
  476.       if (kode == 'J')
  477.     fprintf (file, "%d", -INTVAL (x));
  478.       else if (INTVAL (x) > 0x7FFF)
  479.     fprintf (file, "%d  ; range correction (val>0x7FFF) applied",
  480.          INTVAL (x) - 0x10000);
  481.       else
  482.     fprintf (file, "%d", INTVAL (x));
  483.       break;
  484.     case CODE_LABEL:
  485.       fprintf (file, "L%d", XINT (x, 3));
  486.       break;
  487.     case CALL:
  488.       fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
  489.        XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
  490.       break;
  491.     case PLUS:
  492.       {
  493.     rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
  494.     int op0code = GET_CODE (op0), op1code = GET_CODE (op1);
  495.     if (op1code == CONST_INT)
  496.       switch (op0code)
  497.         {
  498.         case REG:
  499.           fprintf (file, "%d,r%d  ; p_o_PLUS for REG and CONST",
  500.                INTVAL (op1), REGNO (op0));
  501.           break;
  502.         case SYMBOL_REF:
  503.           fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
  504.           break;
  505.         case MEM:
  506.           fprintf (file, "%d,[mem:", INTVAL (op1));
  507.           output_address (XEXP (op0, 0));
  508.           fprintf (file, "] ;P_O plus");
  509.           break;
  510.         default:
  511.           fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
  512.                (int) op0code, INTVAL (op1));
  513.         }
  514.     else if (op1code == SYMBOL_REF && op0code == REG)
  515.       fprintf (file, "%s,r%d  ; P_O: (plus reg sym)",
  516.            XSTR (op1, 0), REGNO (op0));
  517.     else
  518.       fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
  519.       }
  520.       break;
  521.     default:
  522.       fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
  523.     }
  524. }
  525.  
  526. print_operand_address (file, addr)
  527.      FILE *file;
  528.      rtx addr;
  529. {
  530.   switch (GET_CODE (addr))
  531.     {
  532.     case REG:
  533.       fprintf (file, "0,r%d ; P_O_A", REGNO (addr));
  534.       break;
  535.     case PLUS:
  536.       {
  537.     register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
  538.     switch (GET_CODE (x))
  539.       {
  540.       case REG:
  541.         switch (GET_CODE (y))
  542.           {
  543.           case CONST:
  544.         output_address (XEXP (y, 0));
  545.         fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
  546.         break;
  547.           case CONST_INT:
  548.         fprintf (file, "%d,r%d", INTVAL (y), REGNO (x));
  549.         break;
  550.           case SYMBOL_REF:
  551.         fprintf (file, "%s,r%d  ; P_O_A reg + sym",
  552.              XSTR (y, 0), REGNO (x));
  553.         break;
  554.           case LABEL_REF:
  555.         output_address (XEXP (y, 0));
  556.         fprintf (file, ",r%d  ; P_O_A reg + label", REGNO (x));
  557.         break;
  558.           default:
  559.         fprintf (file, "[P_O_A reg%d+UFO code=%d]",
  560.              REGNO (x), GET_CODE (y));
  561.           }
  562.         break;
  563.       case LABEL_REF:
  564.         output_address (XEXP (x, 0));
  565.         break;
  566.       case SYMBOL_REF:
  567.         switch (GET_CODE (y))
  568.           {
  569.           case CONST_INT:
  570.         fprintf (file, "%d+%s", INTVAL (y), XSTR (x, 0));
  571.         break;
  572.           case REG:
  573.         fprintf (file, "%s,r%d ;P_O_A sym + reg",
  574.              XSTR (x, 0), REGNO (y));
  575.         break;
  576.           default:
  577.         fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
  578.              XSTR (x, 0), GET_CODE (y));
  579.           }
  580.         break;
  581.       case CONST:
  582.         output_address (XEXP (x, 0));
  583.         if (GET_CODE (y) == REG)
  584.           fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
  585.         else
  586.           fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
  587.         break;
  588.       case MEM:
  589.         output_address (y);
  590.         fprintf (file, ",[mem:");
  591.         output_address (XEXP (x, 0));
  592.         fprintf (file, "] ;P_O_A plus");
  593.         break;
  594.       default:
  595.         fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
  596.              GET_CODE (x), GET_CODE (y));
  597.       }
  598.       }
  599.       break;
  600.     case CONST_INT:
  601.       if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
  602.     fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
  603.       else
  604.     {
  605.       fprintf (file, "[p_o_a=ILLEGAL_CONST]");
  606.       output_addr_const (file, addr);
  607.     }
  608.       break;
  609.     case LABEL_REF:
  610.     case SYMBOL_REF:
  611.       fprintf (file, "%s", XSTR (addr, 0));
  612.       break;
  613.     case MEM:
  614.       fprintf (file, "[memUFO:");
  615.       output_address (XEXP (addr, 0));
  616.       fprintf (file, "]");
  617.       break;
  618.     case CONST:
  619.       output_address (XEXP (addr, 0));
  620.       fprintf (file, " ;P_O_A const");
  621.       break;
  622.     case CODE_LABEL:
  623.       fprintf (file, "L%d", XINT (addr, 3));
  624.       break;
  625.     default:
  626.       fprintf (file, " p_o_a UFO, code=%d val=0x%x",
  627.            (int) GET_CODE (addr), INTVAL (addr));
  628.       break;
  629.     }
  630. }
  631.  
  632.