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 / gmicro / gmicro.c next >
C/C++ Source or Header  |  1995-06-15  |  21KB  |  985 lines

  1. /* Subroutines for insn-output.c for the Gmicro.
  2.    Ported by Masanobu Yuhara, Fujitsu Laboratories LTD.
  3.    (yuhara@flab.fujitsu.co.jp)
  4.  
  5.    Copyright (C) 1990, 1991 Free Software Foundation, Inc.
  6.  
  7. This file is part of GNU CC.
  8.  
  9. GNU CC is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2, or (at your option)
  12. any later version.
  13.  
  14. GNU CC is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. Among other things, the copyright
  20. notice and this notice must be preserved on all copies.
  21.  
  22. You should have received a copy of the GNU General Public License
  23. along with GNU CC; see the file COPYING.  If not, write to
  24. the Free Software Foundation, 59 Temple Place - Suite 330,
  25. Boston, MA 02111-1307, USA.  */
  26.  
  27.  
  28. #include <stdio.h>
  29. #include "config.h"
  30. #include "rtl.h"
  31. #include "regs.h"
  32. #include "hard-reg-set.h"
  33. #include "real.h"
  34. #include "insn-config.h"
  35. #include "conditions.h"
  36. #include "insn-flags.h"
  37. #include "output.h"
  38. #include "insn-attr.h"
  39.  
  40. extern char *rtx_name[];
  41.  
  42. mypr (s, a1, a2, a3, a4, a5)
  43.      char *s;
  44.      int a1, a2, a3, a4, a5;
  45. {
  46.   fprintf (stderr, s, a1, a2, a3, a4, a5);
  47. }
  48.  
  49. myprcode (i)
  50.      int i;
  51. {
  52.   if (i < 0 || i > 90)
  53.     fprintf (stderr, "code = %d\n", i);
  54.   else
  55.     fprintf (stderr, "code = %s\n", rtx_name[i]);
  56. }
  57.  
  58. myabort (i)
  59.      int i;
  60. {
  61.   fprintf (stderr, "myabort");
  62.   myprcode (i);
  63. }
  64.  
  65.  
  66. /* This is how to output an ascii string.  */
  67. /* See ASM_OUTPUT_ASCII in gmicro.h.  */
  68. output_ascii (file, p, size)
  69.      FILE *file;
  70.      char *p;
  71.      int size;
  72. {
  73.   int i;
  74.   int in_quote = 0;
  75.   register int c;
  76.  
  77.   fprintf (file, "\t.sdata ");
  78.  
  79.   for (i = 0; i < size; i++) 
  80.     {
  81.       c = p[i];
  82.       if (c >= ' ' && c < 0x7f) 
  83.     {
  84.       if (!in_quote) 
  85.         {
  86.           putc ('"', file);
  87.           in_quote = 1;
  88.         }
  89.       putc (c, file);
  90.     }
  91.       else 
  92.     {
  93.       if (in_quote) 
  94.         {
  95.           putc ('"', file);
  96.           in_quote = 0;
  97.         }
  98.       fprintf (file, "<%d>", c);
  99.     }
  100.     }
  101.   if (in_quote)
  102.     putc ('"', file);
  103.   putc ('\n', file);
  104. }
  105.  
  106.  
  107. /* call this when GET_CODE (index) is MULT. */
  108. print_scaled_index (file, index)
  109.      FILE *file;
  110.      register rtx index;
  111. {
  112.   register rtx ireg;
  113.   int scale;
  114.  
  115.   if (GET_CODE (XEXP (index, 0)) == REG) 
  116.     {
  117.       ireg = XEXP (index, 0);
  118.       scale = INTVAL (XEXP (index, 1));
  119.     }
  120.   else 
  121.     {
  122.       ireg = XEXP (index, 1);
  123.       scale = INTVAL (XEXP (index, 0));
  124.     }
  125.   if (scale == 1)
  126.     fprintf (file, "%s", reg_names[REGNO (ireg)]);
  127.   else
  128.     fprintf (file, "%s*%d", reg_names[REGNO (ireg)], scale);
  129. }
  130.     
  131.  
  132. print_operand_address (file, addr)
  133.      FILE *file;
  134.      register rtx addr;
  135. {
  136.   register rtx xtmp0, xtmp1, breg, ixreg;
  137.   int scale;
  138.   int needcomma = 0;
  139.   rtx offset;
  140.  
  141.   fprintf (file, "@");
  142.  retry:
  143.   switch (GET_CODE (addr)) 
  144.     {
  145.     case MEM:
  146.       fprintf (file, "@");
  147.       addr = XEXP (addr, 0);
  148.       goto retry;
  149.  
  150.     case REG:
  151.       fprintf (file, "%s", reg_names[REGNO (addr)]);
  152.       break;
  153.  
  154.     case MULT:
  155.       print_scaled_index (file, addr);
  156.       break;
  157.  
  158.     case PRE_DEC:
  159.       fprintf (file, "-%s", reg_names[REGNO (XEXP (addr, 0))]);
  160.       break;
  161.  
  162.     case POST_INC:
  163.       fprintf (file, "%s+", reg_names[REGNO (XEXP (addr, 0))]);
  164.       break;
  165.  
  166.     case PLUS:
  167.       xtmp0 = XEXP (addr, 0);
  168.       xtmp1 = XEXP (addr, 1);
  169.       ixreg = 0;    breg = 0;
  170.       offset = 0;
  171.       if (CONSTANT_ADDRESS_P (xtmp0)) 
  172.     {
  173.       offset = xtmp0;
  174.       breg = xtmp1;
  175.     }
  176.       else if (CONSTANT_ADDRESS_P (xtmp1)) 
  177.     {
  178.       offset = xtmp1;
  179.       breg = xtmp0;
  180.     }
  181.       else 
  182.     {
  183.       goto NOT_DISP;
  184.     }
  185.  
  186.       if (REG_CODE_BASE_P (breg))
  187.     goto PRINT_MEM;
  188.  
  189.       if (GET_CODE (breg) == MULT) 
  190.     {
  191.       if (REG_CODE_INDEX_P (XEXP (breg, 0))) 
  192.         {
  193.           ixreg = XEXP (breg, 0);
  194.           scale = INTVAL (XEXP (breg, 1));
  195.           breg = 0;
  196.         }
  197.       else 
  198.         {
  199.           ixreg = XEXP (breg, 1);
  200.           scale = INTVAL (XEXP (breg, 0));
  201.           breg = 0;
  202.         }
  203.       goto PRINT_MEM;
  204.     }
  205.  
  206.       /* GET_CODE (breg) must be PLUS here. */
  207.       xtmp0 = XEXP (breg, 0);
  208.       xtmp1 = XEXP (breg, 1);
  209.       if (REG_CODE_BASE_P (xtmp0)) 
  210.     {
  211.       breg = xtmp0;
  212.       xtmp0 = xtmp1;
  213.     }
  214.       else 
  215.     {
  216.       breg = xtmp1;
  217.       /* xtmp0 = xtmp0; */
  218.     }
  219.  
  220.       if (GET_CODE (xtmp0) == MULT) 
  221.     {
  222.       if (REG_CODE_INDEX_P (XEXP (xtmp0, 0))) 
  223.         {
  224.           ixreg = XEXP (xtmp0, 0);
  225.           scale = INTVAL (XEXP (xtmp0, 1));
  226.         }
  227.       else 
  228.         {
  229.           ixreg = XEXP (xtmp0, 1);
  230.           scale = INTVAL (XEXP (xtmp0, 0));
  231.         }
  232.     }
  233.       else 
  234.     {
  235.       ixreg = xtmp0;
  236.       scale = 1;
  237.     }
  238.       goto PRINT_MEM;
  239.  
  240.     NOT_DISP:
  241.       if (REG_CODE_BASE_P (xtmp0)) 
  242.     {
  243.       breg = xtmp0;
  244.       xtmp0 = xtmp1;
  245.     }
  246.       else if (REG_CODE_BASE_P (xtmp1)) 
  247.     {
  248.       breg = xtmp1;
  249.       /* xtmp0 = xtmp0; */
  250.     }
  251.       else
  252.     goto NOT_BASE;
  253.     
  254.       if (REG_CODE_INDEX_P (xtmp0)) 
  255.     {
  256.       ixreg = xtmp0;
  257.       scale = 1;
  258.       goto PRINT_MEM;
  259.     }
  260.       else if (CONSTANT_ADDRESS_P (xtmp0)) 
  261.     {
  262.       offset = xtmp0;
  263.       goto PRINT_MEM;
  264.     }
  265.       else if (GET_CODE (xtmp0) == MULT) 
  266.     {
  267.       if (REG_CODE_INDEX_P (XEXP (xtmp0, 0))) 
  268.         {
  269.           ixreg = XEXP (xtmp0, 0);
  270.           scale = INTVAL (XEXP (xtmp0, 1));
  271.         }
  272.       else 
  273.         {
  274.           ixreg = XEXP (xtmp0, 1);
  275.           scale = INTVAL (XEXP (xtmp0, 0));
  276.         }
  277.       goto PRINT_MEM;
  278.     }
  279.  
  280.       /* GET_CODE (xtmp0) must be PLUS. */
  281.       xtmp1 = XEXP (xtmp0, 1);
  282.       xtmp0 = XEXP (xtmp0, 0);
  283.  
  284.       if (CONSTANT_ADDRESS_P (xtmp0)) 
  285.     {
  286.       offset = xtmp0;
  287.       xtmp0 = xtmp1;
  288.     }
  289.       else 
  290.     {
  291.       offset = xtmp1;
  292.       /* xtmp0 = xtmp0; */
  293.     }
  294.  
  295.       if (REG_CODE_INDEX_P (xtmp0)) 
  296.     {
  297.       ixreg = xtmp0;
  298.     }
  299.       else 
  300.     {            /* GET_CODE (xtmp0) must be MULT. */
  301.       if (REG_CODE_INDEX_P (XEXP (xtmp0, 0))) 
  302.         {
  303.           ixreg = XEXP (xtmp0, 0);
  304.           scale = INTVAL (XEXP (xtmp0, 1));
  305.         }
  306.       else 
  307.         {
  308.           ixreg = XEXP (xtmp0, 1);
  309.           scale = INTVAL (XEXP (xtmp0, 0));
  310.         }
  311.     }
  312.       goto PRINT_MEM;
  313.  
  314.     NOT_BASE:
  315.       if (GET_CODE (xtmp0) == PLUS) 
  316.     {
  317.       ixreg = xtmp1;
  318.       /* xtmp0 = xtmp0; */
  319.     }
  320.       else 
  321.     {
  322.       ixreg = xtmp0;
  323.       xtmp0 = xtmp1;
  324.     }
  325.  
  326.       if (REG_CODE_INDEX_P (ixreg)) 
  327.     {
  328.       scale = 1;
  329.     }
  330.       else if (REG_CODE_INDEX_P (XEXP (ixreg, 0))) 
  331.     {
  332.       scale = INTVAL (XEXP (ixreg, 1));
  333.       ixreg = XEXP (ixreg, 0);
  334.     }
  335.       else 
  336.     {            /* was else if with no condition. OK ??? */
  337.       scale = INTVAL (XEXP (ixreg, 0));
  338.       ixreg = XEXP (ixreg, 1);
  339.     }
  340.  
  341.       if (REG_CODE_BASE_P (XEXP (xtmp0, 0))) 
  342.     {
  343.       breg = XEXP (xtmp0, 0);
  344.       offset = XEXP (xtmp0, 1);
  345.     }
  346.       else 
  347.     {
  348.       breg = XEXP (xtmp0, 1);
  349.       offset = XEXP (xtmp0, 0);
  350.     }
  351.  
  352.     PRINT_MEM:
  353.       if (breg == 0 && ixreg == 0) 
  354.     {
  355.       output_address (offset);
  356.       break;
  357.     }
  358.       else if (ixreg == 0 && offset == 0) 
  359.     {
  360.       fprintf (file, "%s", reg_names[REGNO (breg)]);
  361.       break;
  362.     }
  363.       else 
  364.     {
  365.       fprintf (file, "(");
  366.       if (offset != 0) 
  367.         {
  368.           output_addr_const (file, offset);
  369.           needcomma = 1;
  370.         }
  371.       if (breg != 0) 
  372.         {
  373.           if (needcomma)
  374.         fprintf (file, ",");
  375.           fprintf (file, "%s", reg_names[REGNO (breg)]);
  376.           needcomma = 1;
  377.         }
  378.       if (ixreg != 0) 
  379.         {
  380.           if (needcomma)
  381.         fprintf (file, ",");
  382.           fprintf (file, "%s", reg_names[REGNO (ixreg)]);
  383.           if (scale != 1)
  384.         fprintf (file,"*%d", scale);
  385.         }
  386.       fprintf (file, ")");
  387.  
  388.       break;
  389.     }
  390.  
  391.     default:
  392.       output_addr_const (file, addr);
  393.     }
  394. }
  395.  
  396.  
  397.  
  398. /* Return a REG that occurs in ADDR with coefficient 1.
  399.    ADDR can be effectively incremented by incrementing REG.  */
  400.  
  401. static rtx
  402. find_addr_reg (addr)
  403.      rtx addr;
  404. {
  405.   while (GET_CODE (addr) == PLUS)
  406.     {
  407.       if (GET_CODE (XEXP (addr, 0)) == REG)
  408.     addr = XEXP (addr, 0);
  409.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  410.     addr = XEXP (addr, 1);
  411.       else if (GET_CODE (XEXP (addr, 0)) == PLUS)
  412.     addr = XEXP (addr, 0);
  413.       else if (GET_CODE (XEXP (addr, 1)) == PLUS)
  414.     addr = XEXP (addr, 1);
  415.     }
  416.   if (GET_CODE (addr) == REG)
  417.     return addr;
  418.   return 0;
  419. }
  420.  
  421.  
  422.     /* Return the best assembler insn template
  423.     for moving operands[1] into operands[0] as a fullword.  */
  424.  
  425. static char *
  426. singlemove_string (operands)
  427.      rtx *operands;
  428. {
  429.   if (FPU_REG_P (operands[0]) || FPU_REG_P (operands[1])) 
  430.     {
  431.       if (GREG_P (operands[0]) || GREG_P (operands[1])) 
  432.     {
  433.       myabort (101);    /* Not Supported yet !! */
  434.     }
  435.       else 
  436.     {
  437.       return "fmov.s %1,%0";
  438.     }
  439.     }
  440.   return "mov.w %1,%0";
  441. }
  442.  
  443.  
  444. /* Output assembler code to perform a doubleword move insn
  445.    with operands OPERANDS.  */
  446.  
  447. char *
  448. output_move_double (operands)
  449.      rtx *operands;
  450. {
  451.   enum 
  452.     { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP }
  453.   optype0, optype1;
  454.   rtx latehalf[2];
  455.   rtx addreg0 = 0, addreg1 = 0;
  456.  
  457.   /* First classify both operands.  */
  458.  
  459.   if (REG_P (operands[0]))
  460.     optype0 = REGOP;
  461.   else if (offsettable_memref_p (operands[0]))
  462.     optype0 = OFFSOP;
  463.   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
  464.     optype0 = POPOP;
  465.   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
  466.     optype0 = PUSHOP;
  467.   else if (GET_CODE (operands[0]) == MEM)
  468.     optype0 = MEMOP;
  469.   else
  470.     optype0 = RNDOP;
  471.  
  472.   if (REG_P (operands[1]))
  473.     optype1 = REGOP;
  474.   else if (CONSTANT_P (operands[1]))
  475.     optype1 = CNSTOP;
  476.   else if (offsettable_memref_p (operands[1]))
  477.     optype1 = OFFSOP;
  478.   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  479.     optype1 = POPOP;
  480.   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
  481.     optype1 = PUSHOP;
  482.   else if (GET_CODE (operands[1]) == MEM)
  483.     optype1 = MEMOP;
  484.   else
  485.     optype1 = RNDOP;
  486.  
  487.   /* Check for the cases that the operand constraints are not
  488.      supposed to allow to happen.  Abort if we get one,
  489.      because generating code for these cases is painful.  */
  490.  
  491.   if (optype0 == RNDOP || optype1 == RNDOP)
  492.     myabort (102);
  493.  
  494.   /* If one operand is decrementing and one is incrementing
  495.      decrement the former register explicitly
  496.      and change that operand into ordinary indexing.  */
  497.  
  498.   if (optype0 == PUSHOP && optype1 == POPOP)
  499.     {
  500.       operands[0] = XEXP (XEXP (operands[0], 0), 0);
  501.       output_asm_insn ("sub.w %#8,%0", operands);
  502.       operands[0] = gen_rtx (MEM, DImode, operands[0]);
  503.       optype0 = OFFSOP;
  504.     }
  505.   if (optype0 == POPOP && optype1 == PUSHOP)
  506.     {
  507.       operands[1] = XEXP (XEXP (operands[1], 0), 0);
  508.       output_asm_insn ("sub.w %#8,%1", operands);
  509.       operands[1] = gen_rtx (MEM, DImode, operands[1]);
  510.       optype1 = OFFSOP;
  511.     }
  512.  
  513.   /* If an operand is an unoffsettable memory ref, find a register
  514.      we can increment temporarily to make it refer to the second word.  */
  515.  
  516.   if (optype0 == MEMOP)
  517.     addreg0 = find_addr_reg (operands[0]);
  518.  
  519.   if (optype1 == MEMOP)
  520.     addreg1 = find_addr_reg (operands[1]);
  521.  
  522.   /* Ok, we can do one word at a time.
  523.      Normally we do the low-numbered word first,
  524.      but if either operand is autodecrementing then we
  525.      do the high-numbered word first.
  526.      
  527.      In either case, set up in LATEHALF the operands to use
  528.      for the high-numbered word and in some cases alter the
  529.      operands in OPERANDS to be suitable for the low-numbered word.  */
  530.  
  531.   if (optype0 == REGOP)
  532.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  533.   else if (optype0 == OFFSOP)
  534.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  535.   else
  536.     latehalf[0] = operands[0];
  537.  
  538.   if (optype1 == REGOP)
  539.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  540.   else if (optype1 == OFFSOP)
  541.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  542.   else if (optype1 == CNSTOP)
  543.     {
  544.       if (GET_CODE (operands[1]) == CONST_DOUBLE)
  545.     split_double (operands[1], &operands[1], &latehalf[1]);
  546.       else if (CONSTANT_P (operands[1]))
  547.     latehalf[1] = const0_rtx;
  548.     }
  549.   else
  550.     latehalf[1] = operands[1];
  551.  
  552.   /* If insn is effectively movd N(sp),-(sp) then we will do the
  553.      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
  554.      for the low word as well, to compensate for the first decrement of sp.  */
  555.   if (optype0 == PUSHOP
  556.       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
  557.       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
  558.     operands[1] = latehalf[1];
  559.  
  560.   /* If one or both operands autodecrementing,
  561.      do the two words, high-numbered first.  */
  562.  
  563.   /* Likewise,  the first move would clobber the source of the second one,
  564.      do them in the other order.  This happens only for registers;
  565.      such overlap can't happen in memory unless the user explicitly
  566.      sets it up, and that is an undefined circumstance.  */
  567.  
  568.   if (optype0 == PUSHOP || optype1 == PUSHOP
  569.       || (optype0 == REGOP && optype1 == REGOP
  570.       && REGNO (operands[0]) == REGNO (latehalf[1])))
  571.     {
  572.       /* Make any unoffsettable addresses point at high-numbered word.  */
  573.       if (addreg0)
  574.     output_asm_insn ("add.w %#4,%0", &addreg0);
  575.       if (addreg1)
  576.     output_asm_insn ("add.w %#4,%0", &addreg1);
  577.  
  578.       /* Do that word.  */
  579.       output_asm_insn (singlemove_string (latehalf), latehalf);
  580.  
  581.       /* Undo the adds we just did.  */
  582.       if (addreg0)
  583.     output_asm_insn ("sub.w %#4,%0", &addreg0);
  584.       if (addreg1)
  585.     output_asm_insn ("sub.w %#4,%0", &addreg1);
  586.  
  587.       /* Do low-numbered word.  */
  588.       return singlemove_string (operands);
  589.     }
  590.  
  591.   /* Normal case: do the two words, low-numbered first.  */
  592.  
  593.   output_asm_insn (singlemove_string (operands), operands);
  594.  
  595.   /* Make any unoffsettable addresses point at high-numbered word.  */
  596.   if (addreg0)
  597.     output_asm_insn ("add.w %#4,%0", &addreg0);
  598.   if (addreg1)
  599.     output_asm_insn ("add.w %#4,%0", &addreg1);
  600.  
  601.   /* Do that word.  */
  602.   output_asm_insn (singlemove_string (latehalf), latehalf);
  603.  
  604.   /* Undo the adds we just did.  */
  605.   if (addreg0)
  606.     output_asm_insn ("sub.w %#4,%0", &addreg0);
  607.   if (addreg1)
  608.     output_asm_insn ("sub.w %#4,%0", &addreg1);
  609.  
  610.   return "";
  611. }
  612.  
  613. /* Move const_double to floating point register (DF) */
  614. char *
  615. output_move_const_double (operands)
  616.      rtx *operands;
  617. {
  618.   int code = standard_fpu_constant_p (operands[1]);
  619.  
  620.   if (FPU_REG_P (operands[0])) 
  621.     {
  622.       if (code != 0)
  623.     {
  624.       static char buf[40];
  625.  
  626.       sprintf (buf, "fmvr from%d,%%0.d", code);
  627.       return buf;
  628.     }
  629.       else 
  630.     {
  631.       return "fmov %1,%0.d";
  632.     }
  633.     }
  634.   else if (GREG_P (operands[0])) 
  635.     {
  636.       rtx xoperands[2];
  637.       xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  638.       xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
  639.                   CONST_DOUBLE_HIGH (operands[1]));
  640.       output_asm_insn ("mov.w %1,%0", xoperands);
  641.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  642.                  CONST_DOUBLE_LOW (operands[1]));
  643.       return "mov.w %1,%0";
  644.     }
  645.   else 
  646.     {
  647.       return output_move_double (operands); /* ?????? */
  648.     }
  649. }
  650.  
  651. char *
  652. output_move_const_single (operands)
  653.      rtx *operands;
  654. {
  655.   int code = standard_fpu_constant_p (operands[1]);
  656.   static char buf[40];
  657.  
  658.   if (FPU_REG_P (operands[0])) 
  659.     {
  660.       if (code != 0)
  661.     {
  662.       sprintf (buf, "fmvr from%d,%%0.s", code);
  663.       return buf;
  664.     }
  665.       return "fmov.s %f1,%0";
  666.     }
  667.   else 
  668.     return "mov.w %f1,%0";
  669. }
  670.  
  671.  
  672. /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
  673.    from the "fmvr" instruction of the Gmicro FPU.
  674.    The value, anded with 0xff, gives the code to use in fmovecr
  675.    to get the desired constant.  */
  676.  
  677.   u.i[0] = CONST_DOUBLE_LOW (x);
  678.   u.i[1] = CONST_DOUBLE_HIGH (x);
  679.   d = u.d;
  680.  
  681.   if (d == 0.0)            /* +0.0 */
  682.     return 0x0;
  683.   /* Note: there are various other constants available
  684.      but it is a nuisance to put in their values here.  */
  685.   if (d == 1.0)            /* +1.0 */
  686.     return 0x1;
  687.  
  688.   /*
  689.    * Stuff that looks different if it's single or double
  690.    */
  691.   if (GET_MODE (x) == SFmode)
  692.     {
  693.       if (d == S_PI)
  694.     return 0x2;
  695.       if (d == (S_PI / 2.0))
  696.     return 0x3;
  697.       if (d == S_E)
  698.     return 0x4;
  699.       if (d == S_LOGEof2)
  700.     return 0x5;
  701.       if (d == S_LOGEof10)
  702.     return 0x6;
  703.       if (d == S_LOG10of2)
  704.     return 0x7;
  705.       if (d == S_LOG10ofE)
  706.     return 0x8;
  707.       if (d == S_LOG2ofE)
  708.     return 0x9;
  709.     }
  710.   else
  711.     {
  712.       if (d == D_PI)
  713.     return 0x2;
  714.       if (d == (D_PI / 2.0))
  715.     return 0x3;
  716.       if (d == D_E)
  717.     return 0x4;
  718.       if (d == D_LOGEof2)
  719.     return 0x5;
  720.       if (d == D_LOGEof10)
  721.     return 0x6;
  722.       if (d == D_LOG10of2)
  723.     return 0x7;
  724.       if (d == D_LOG10ofE)
  725.     return 0x8;
  726.       if (d == D_LOG2ofE)
  727.     return 0x9;
  728.     }
  729.  
  730.   return 0;
  731. }
  732.  
  733. #undef S_PI
  734. #undef D_PI
  735. #undef S_E
  736. #undef D_E
  737. #undef S_LOGEof2
  738. #undef D_LOGEof2
  739. #undef S_LOGEof10
  740. #undef D_LOGEof10
  741. #undef S_LOG10of2
  742. #undef D_LOG10of2
  743. #undef S_LOG10ofE
  744. #undef D_LOG10ofE
  745. #undef S_LOG2ofE
  746. #undef D_LOG2ofE
  747.  
  748. /* dest should be operand 0 */
  749. /* imm should be operand 1 */
  750.  
  751. extern char *sub_imm_word ();
  752.  
  753. char *
  754. add_imm_word (imm, dest, immp)
  755.      int imm;
  756.      rtx dest, *immp;
  757. {
  758.   int is_reg, short_ok;
  759.  
  760.  
  761.   if (imm < 0) 
  762.     {
  763.       *immp = gen_rtx (CONST_INT, VOIDmode, -imm);
  764.       return sub_imm_word (-imm, dest);
  765.     }
  766.     
  767.   if (imm == 0)
  768.     return "mov:l.w #0,%0";
  769.     
  770.   short_ok = short_format_ok (dest);
  771.  
  772.   if (short_ok && imm <= 8)
  773.     return "add:q %1,%0.w";
  774.  
  775.   if (imm < 128)
  776.     return "add:e %1,%0.w";
  777.  
  778.   is_reg = (GET_CODE (dest) == REG);
  779.  
  780.   if (is_reg)
  781.     return "add:l %1,%0.w";
  782.     
  783.   if (short_ok)
  784.     return "add:i %1,%0.w";
  785.     
  786.   return "add %1,%0.w";
  787. }
  788.  
  789. char *
  790. sub_imm_word (imm, dest, immp)
  791.      int imm;
  792.      rtx dest, *immp;
  793. {
  794.   int is_reg, short_ok;
  795.  
  796.   if (imm < 0 &&  imm != 0x80000000) 
  797.     {
  798.       *immp = gen_rtx (CONST_INT, VOIDmode, -imm);
  799.       return add_imm_word (-imm, dest);
  800.     }
  801.     
  802.   if (imm == 0)
  803.     return "mov:z.w #0,%0";
  804.     
  805.   short_ok = short_format_ok (dest);
  806.  
  807.   if (short_ok && imm <= 8)
  808.     return "sub:q %1,%0.w";
  809.  
  810.   if (imm < 128)
  811.     return "sub:e %1,%0.w";
  812.  
  813.   is_reg = (GET_CODE (dest) == REG);
  814.  
  815.   if (is_reg)
  816.     return "sub:l %1,%0.w";
  817.     
  818.   if (short_ok)
  819.     return "sub:i %1,%0.w";
  820.     
  821.   return "sub %1,%0.w";
  822. }
  823.  
  824. int
  825. short_format_ok (x)
  826.      rtx x;
  827. {
  828.   rtx x0, x1;
  829.  
  830.   if (GET_CODE (x) == REG)
  831.     return 1;
  832.  
  833.   if (GET_CODE (x) == MEM 
  834.       && GET_CODE (XEXP (x, 0)) == PLUS) 
  835.     {
  836.       x0 = XEXP (XEXP (x, 0), 0);
  837.       x1 = XEXP (XEXP (x, 0), 1);
  838.       return ((GET_CODE (x0) == REG
  839.            && CONSTANT_P (x1)
  840.            && ((unsigned) (INTVAL (x1) + 0x8000)  < 0x10000))
  841.           ||
  842.           (GET_CODE (x1) == REG
  843.            && CONSTANT_P (x0)
  844.            && ((unsigned) (INTVAL (x0) + 0x8000)  < 0x10000)));
  845.     }
  846.  
  847.   return 0;
  848. }
  849.  
  850. myoutput_sp_adjust (file, op, fsize)
  851.      FILE *file;
  852.      char *op;
  853.      int fsize;
  854. {
  855.   if (fsize == 0)
  856.     ;
  857.   else if (fsize < 8)
  858.     fprintf (file, "\t%s:q #%d,sp.w\n", op, fsize);
  859.   else if (fsize < 128)
  860.     fprintf (file, "\t%s:e #%d,sp.w\n", op, fsize);
  861.   else
  862.     fprintf (file, "\t%s:l #%d,sp.w\n", op, fsize);
  863. }
  864.  
  865.  
  866. char *
  867. mov_imm_word (imm, dest)
  868.      int imm;
  869.      rtx dest;
  870. {
  871.   int is_reg, short_ok;
  872.  
  873.   if (imm == 0)
  874.     return "mov:z.w #0,%0";
  875.     
  876.   short_ok = short_format_ok (dest);
  877.  
  878.   if (short_ok && imm > 0 && imm <= 8)
  879.     return "mov:q %1,%0.w";
  880.  
  881.   if (-128 <= imm && imm < 128)
  882.     return "mov:e %1,%0.w";
  883.  
  884.   is_reg = (GET_CODE (dest) == REG);
  885.  
  886.   if (is_reg)
  887.     return "mov:l %1,%0.w";
  888.     
  889.   if (short_ok)
  890.     return "mov:i %1,%0.w";
  891.     
  892.   return "mov %1,%0.w";
  893. }
  894.  
  895. char *
  896. cmp_imm_word (imm, dest)
  897.      int imm;
  898.      rtx dest;
  899. {
  900.   int is_reg, short_ok;
  901.  
  902.   if (imm == 0)
  903.     return "cmp:z.w #0,%0";
  904.     
  905.   short_ok = short_format_ok (dest);
  906.  
  907.   if (short_ok && imm >0 && imm <= 8)
  908.     return "cmp:q %1,%0.w";
  909.  
  910.   if (-128 <= imm && imm < 128)
  911.     return "cmp:e %1,%0.w";
  912.  
  913.   is_reg = (GET_CODE (dest) == REG);
  914.  
  915.   if (is_reg)
  916.     return "cmp:l %1,%0.w";
  917.     
  918.   if (short_ok)
  919.     return "cmp:i %1,%0.w";
  920.     
  921.   return "cmp %1,%0.w";
  922. }
  923.  
  924. char *
  925. push_imm_word (imm)
  926.      int imm;
  927. {
  928.   if (imm == 0)
  929.     return "mov:z.w #0,%-";
  930.     
  931.   if (imm > 0 && imm <= 8)
  932.     return "mov:q %1,%-.w";
  933.  
  934.   if (-128 <= imm && imm < 128)
  935.     return "mov:e %1,%-.w";
  936.  
  937.   return "mov:g %1,%-.w";
  938.     
  939.   /* In some cases, g-format may be better than I format.??
  940.      return "mov %1,%0.w";
  941.      */
  942. }
  943.  
  944. my_signed_comp (insn)
  945.      rtx insn;
  946. {
  947.   rtx my_insn;
  948.  
  949.   my_insn = NEXT_INSN (insn);
  950.   if (GET_CODE (my_insn) != JUMP_INSN) 
  951.     {
  952.       fprintf (stderr, "my_signed_comp: Not Jump_insn ");
  953.       myabort (GET_CODE (my_insn));
  954.     }
  955.   my_insn = PATTERN (my_insn);
  956.   if (GET_CODE (my_insn) != SET) 
  957.     {
  958.       fprintf (stderr, "my_signed_comp: Not Set ");
  959.       myabort (GET_CODE (my_insn));
  960.     }
  961.   my_insn = SET_SRC (my_insn);
  962.   if (GET_CODE (my_insn) != IF_THEN_ELSE) 
  963.     {
  964.       fprintf (stderr, "my_signed_comp: Not if_then_else ");
  965.       myabort (GET_CODE (my_insn));
  966.     }
  967.   switch (GET_CODE (XEXP (my_insn, 0)))
  968.     {
  969.     case NE:
  970.     case EQ:
  971.     case GE:
  972.     case GT:
  973.     case LE:
  974.     case LT:
  975.       return 1;
  976.     case GEU:
  977.     case GTU:
  978.     case LEU:
  979.     case LTU:
  980.       return 0;
  981.     }
  982.   fprintf (stderr, "my_signed_comp: Not cccc ");
  983.   myabort (GET_CODE (XEXP (my_insn, 0)));
  984. }
  985.