OSDN Git Service

(memop_valid): Memory indirection now valid.
[pf3gnuchains/gcc-fork.git] / gcc / config / 1750a / 1750a.c
1 /* Subroutines for insn-output.c for MIL-STD-1750.
2    Copyright (C) 1994, 1995, 1996, 1997 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 #include "regs.h"
36
37 struct datalabel_array datalbl[DATALBL_ARRSIZ];
38 int datalbl_ndx = -1;
39 struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
40 int jmplbl_ndx = -1;
41 int label_pending = 0, program_counter = 0;
42 enum section current_section = Normal;
43 char *sectname[4] =
44 {"Init", "Normal", "Konst", "Static"};
45
46 int
47 notice_update_cc (exp)
48      rtx exp;
49 {
50   if (GET_CODE (exp) == SET)
51     {
52       enum rtx_code src_code = GET_CODE (SET_SRC (exp));
53       /* Jumps do not alter the cc's.  */
54       if (SET_DEST (exp) == pc_rtx)
55         return;
56       /* Moving a register or constant into memory doesn't alter the cc's. */
57       if (GET_CODE (SET_DEST (exp)) == MEM
58           && (src_code == REG || src_code == CONST_INT))
59         return;
60       /* Function calls clobber the cc's.  */
61       if (src_code == CALL)
62         {
63           CC_STATUS_INIT;
64           return;
65         }
66       /* Emulated longword bit-ops leave cc's incorrect */
67       if (GET_MODE (SET_DEST (exp)) == HImode ?
68                src_code == AND || src_code == IOR ||
69                src_code == XOR || src_code == NOT : 0)
70         {
71           CC_STATUS_INIT;
72           return;
73         }
74       /* Tests and compares set the cc's in predictable ways.  */
75       if (SET_DEST (exp) == cc0_rtx)
76         {
77           CC_STATUS_INIT;
78           cc_status.value1 = SET_SRC (exp);
79           return;
80         }
81       /* Anything else will set cc_status. */
82       cc_status.flags = CC_NO_OVERFLOW;
83       cc_status.value1 = SET_SRC (exp);
84       cc_status.value2 = SET_DEST (exp);
85       return;
86     }
87   else if (GET_CODE (exp) == PARALLEL
88            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
89     {
90       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
91         return;
92       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
93         {
94           CC_STATUS_INIT;
95           cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
96           return;
97         }
98       CC_STATUS_INIT;
99     }
100   else
101     {
102       CC_STATUS_INIT;
103     }
104 }
105
106
107 rtx
108 function_arg (cum, mode, type, named)
109      int cum;
110      enum machine_mode mode;
111      tree type;
112      int named;
113 {
114   int size;
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 double
130 get_double (x)
131      rtx x;
132 {
133   union
134     {
135       double d;
136       long i[2];
137     }
138   du;
139
140   du.i[0] = CONST_DOUBLE_LOW (x);
141   du.i[1] = CONST_DOUBLE_HIGH (x);
142   return du.d;
143 }
144
145 char *
146 float_label (code, value)
147      char code;
148      double value;
149 {
150   int i = 1;
151   static char label[32];
152   char *p;
153
154   label[0] = code;
155   p = label + 1;
156   sprintf (p, "%lf", value);
157   while (*p)
158     {
159       *p = (*p == '+') ? 'p' :
160         (*p == '-') ? 'm' : *p;
161       p++;
162     }
163   return xstrdup (label);
164 }
165
166
167 char *
168 movcnt_regno_adjust (op)
169      rtx *op;
170 {
171   static char outstr[80];
172   int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
173 #define dstreg op0r
174 #define srcreg op1r
175 #define cntreg op2r
176 #define cntreg_1750 (op0r + 1)
177
178   if (cntreg == cntreg_1750)
179     sprintf (outstr, "mov r%d,r%d", op0r, op1r);
180   else if (dstreg + 1 == srcreg && cntreg > srcreg)
181     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r);
182   else if (dstreg == cntreg + 1)
183     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r);
184   else if (dstreg == srcreg + 1)
185     sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
186              op0r, op1r, op0r, op2r, op1r, op2r);
187   else if (cntreg + 1 == srcreg)
188     sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
189              op2r, op1r, op0r, op2r, op2r, op0r);
190   else if (cntreg == srcreg + 1)
191     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r);
192   else
193     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
194              op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750);
195   return outstr;
196 }
197
198 char *
199 mod_regno_adjust (instr, op)
200      char *instr;
201      rtx *op;
202 {
203   static char outstr[40];
204   char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
205   int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
206
207   if (modregno_gcc == modregno_1750
208       || (reg_renumber != NULL
209           && reg_renumber[modregno_gcc] >= 0
210           && reg_renumber[modregno_gcc] == reg_renumber[modregno_1750]))
211     sprintf (outstr, "%s r%%0,%s%%2", instr, r);
212   else
213     sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
214              modregno_gcc, modregno_1750, instr, r, modregno_1750,
215              modregno_gcc);
216   return outstr;
217 }
218
219
220 /* Check if op is a valid memory operand for 1750A Load/Store instructions
221    (memory indirection permitted.)  */
222
223 int
224 memop_valid (op)
225      rtx op;
226 {
227   static int recurred = 0;
228   int valid;
229
230   if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
231       && GET_MODE (op) != QImode)
232     return 0;
233   switch (GET_CODE (op))
234     {
235     case MEM:
236       if (!recurred && GET_CODE (XEXP (op, 0)) == REG)
237         return 1;
238     case MINUS:
239     case MULT:
240     case DIV:
241       return 0;
242     case PLUS:
243       recurred = 1;
244       valid = memop_valid (XEXP (op, 0));
245       if (valid)
246         valid = memop_valid (XEXP (op, 1));
247        recurred = 0;
248        return valid;
249     case REG:
250       if (REGNO (op) > 0)
251         return 1;
252       return 0;
253     case CONST:
254     case CONST_INT:
255     case SYMBOL_REF:
256     case SUBREG:
257       return 1;
258     default:
259       printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
260       return 1;
261     }
262 }
263
264
265 /* predicate for the MOV instruction: */
266 int
267 mov_memory_operand (op, mode)
268      rtx op;
269      enum machine_mode mode;
270 {
271   return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
272 }
273
274 /* predicate for the STC instruction: */
275 int
276 small_nonneg_const (op, mode)
277      rtx op;
278      enum machine_mode mode;
279 {
280   if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
281     return 1;
282   return 0;
283 }
284
285 /* predicate for constant zero: */
286 int
287 zero_operand (op, mode)
288      rtx op;
289      enum machine_mode mode;
290 {
291   return op == CONST0_RTX (mode);
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) == REG && REG_OK_FOR_INDEX_P (inner))
305         return 1;
306       if (GET_CODE (inner) == PLUS)
307         {
308           rtx plus_op0 = XEXP (inner, 0);
309           if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
310             {
311               rtx plus_op1 = XEXP (inner, 1);
312               if (GET_CODE (plus_op1) == CONST_INT
313                   && INTVAL (plus_op1) >= 0
314                   && INTVAL (plus_op1) <= 255)
315                 return 1;
316             }
317         }
318     }
319   return 0;
320 }
321
322
323 /* Decide whether to output a conditional jump as a "Jump Conditional"
324    or as a "Branch Conditional": */
325
326 int
327 find_jmplbl (labelnum)
328      int labelnum;
329 {
330   int i, found = 0;
331
332   for (i = 0; i <= jmplbl_ndx; i++)
333     if (labelnum == jmplbl[i].num)
334       {
335         found = 1;
336         break;
337       }
338   if (found)
339     return i;
340   return -1;
341 }
342
343 char *
344 branch_or_jump (condition, targetlabel_number)
345      char *condition;
346      int targetlabel_number;
347 {
348   static char buf[30];
349   int index;
350
351   if ((index = find_jmplbl (targetlabel_number)) >= 0)
352     if (program_counter - jmplbl[index].pc < 128)
353       {
354         sprintf (buf, "b%s %%l0", condition);
355         return buf;
356       }
357   sprintf (buf, "jc %s,%%l0", condition);
358   return buf;
359 }
360
361
362 int
363 unsigned_comparison_operator (insn)
364      rtx insn;
365 {
366   switch (GET_CODE (insn))
367     {
368     case GEU:
369     case GTU:
370     case LEU:
371     case LTU:
372       return 1;
373     default:
374       return 0;
375     }
376 }
377
378 int
379 next_cc_user_is_unsigned (insn)
380      rtx insn;
381 {
382   if ( !(insn = next_cc0_user (insn)))
383     abort ();
384   else if (GET_CODE (insn) == JUMP_INSN
385            && GET_CODE (PATTERN (insn)) == SET
386            && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
387     return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0));
388   else if (GET_CODE (insn) == INSN
389            && GET_CODE (PATTERN (insn)) == SET)
390     return unsigned_comparison_operator (SET_SRC (PATTERN (insn)));
391   else
392     abort ();
393 }
394
395
396 static int addr_inc;
397
398 /* A C compound statement to output to stdio stream STREAM the
399    assembler syntax for an instruction operand X.  X is an RTL
400    expression.
401
402    CODE is a value that can be used to specify one of several ways
403    of printing the operand.  It is used when identical operands
404    must be printed differently depending on the context.  CODE
405    comes from the `%' specification that was used to request
406    printing of the operand.  If the specification was just `%DIGIT'
407    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
408    is the ASCII code for LTR.
409
410    If X is a register, this macro should print the register's name.
411    The names can be found in an array `reg_names' whose type is
412    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
413
414    When the machine description has a specification `%PUNCT' (a `%'
415    followed by a punctuation character), this macro is called with
416    a null pointer for X and the punctuation character for CODE.
417
418    The 1750 specific codes are:
419    'J' for the negative of a constant
420    'Q' for printing addresses in B mode syntax
421    'd' for the second register in a pair
422    't' for the third register in a triple 
423    'b' for the bit number (using 1750 test bit convention)
424    'B' for the bit number of the 1's complement (for bit clear)
425    'w' for int - 16
426 */
427
428 print_operand (file, x, letter)
429      FILE *file;
430      rtx x;
431      int letter;
432 {
433   switch (GET_CODE (x))
434     {
435     case REG:
436       if (letter == 'd')
437         fprintf (file, "%d", REGNO (x) + 1);
438       else if (letter == 't')
439         fprintf (file, "%d", REGNO (x) + 2);
440       else
441         fprintf (file, "%d", REGNO (x));
442       break;
443
444     case SYMBOL_REF:
445       fprintf (file, "%s", XSTR (x, 0));
446       if (letter == 'A')
447         fprintf (file, "+1");
448       break;
449
450     case LABEL_REF:
451     case CONST:
452     case MEM:
453       if (letter == 'Q')
454         {
455           rtx inner = XEXP (x, 0);
456           switch (GET_CODE (inner))
457             {
458             case REG:
459               fprintf (file, "r%d,0", REGNO (inner));
460               break;
461             case PLUS:
462               fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
463                        INTVAL (XEXP (inner, 1)));
464               break;
465             default:
466               fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
467             }
468         }
469       else
470         {
471           addr_inc = (letter == 'A' ? 1 : 0);
472           output_address (XEXP (x, 0));
473         }
474       break;
475
476     case CONST_DOUBLE:
477 /*    {
478         double value = get_double (x);
479         char fltstr[32];
480         sprintf (fltstr, "%lf", value);
481
482         if (letter == 'D' || letter == 'E')
483           {
484             int i, found = 0;
485             for (i = 0; i <= datalbl_ndx; i++)
486               if (strcmp (fltstr, datalbl[i].value) == 0)
487                 {
488                   found = 1;
489                   break;
490                 }
491             if (!found)
492               {
493                 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
494                 datalbl[i].name = float_label (letter, value);
495                 datalbl[i].size = (letter == 'E') ? 3 : 2;
496                 check_section (Konst);
497                 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
498                         (letter == 'E' ? "ef" : "f"), fltstr);
499                 check_section (Normal);
500               }
501           }
502         else if (letter == 'F' || letter == 'G')
503           {
504             int i, found = 0;
505             for (i = 0; i <= datalbl_ndx; i++)
506               if (strcmp (fltstr, datalbl[i].value) == 0)
507                 {
508                   found = 1;
509                   break;
510                 }
511             if (!found)
512               {
513                 fprintf (stderr,
514                    "float value %lfnot found upon label reference\n", value);
515                 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
516                 datalbl[i].name = float_label (letter, value);
517                 datalbl[i].size = (letter == 'G') ? 3 : 2;
518                 check_section (Konst);
519                 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
520                         (letter == 'G' ? "ef" : "f"), fltstr);
521                 check_section (Normal);
522               }
523             fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
524           }
525         else
526           fprintf (file, " %s  ;P_O cst_dbl ", fltstr);
527       }
528  */
529       fprintf (file, "%lf", get_double (x));
530       break;
531
532     case CONST_INT:
533       if (letter == 'J')
534         fprintf (file, "%d", -INTVAL (x));
535       else if (letter == 'b')
536         fprintf (file, "%d", which_bit (INTVAL (x)));
537       else if (letter == 'B')
538         fprintf (file, "%d", which_bit (~INTVAL (x)));
539       else if (letter == 'w')
540         fprintf (file, "%d", INTVAL (x) - 16);
541       else
542         fprintf (file, "%d", INTVAL (x));
543       break;
544
545     case CODE_LABEL:
546       fprintf (file, "L%d", XINT (x, 3));
547       break;
548
549     case CALL:
550       fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
551        XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
552       break;
553
554     case PLUS:
555       {
556         rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
557         int op0code = GET_CODE (op0), op1code = GET_CODE (op1);
558         if (op1code == CONST_INT)
559           switch (op0code)
560             {
561             case REG:
562               fprintf (file, "%d,r%d  ; p_o_PLUS for REG and CONST_INT",
563                        INTVAL (op1), REGNO (op0));
564               break;
565             case SYMBOL_REF:
566               fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
567               break;
568             case MEM:
569               fprintf (file, "%d,[mem:", INTVAL (op1));
570               output_address (XEXP (op0, 0));
571               fprintf (file, "] ;P_O plus");
572               break;
573             default:
574               fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
575                        (int) op0code, INTVAL (op1));
576             }
577         else if (op1code == SYMBOL_REF && op0code == REG)
578           fprintf (file, "%s,r%d  ; P_O: (plus reg sym)",
579                    XSTR (op1, 0), REGNO (op0));
580         else
581           fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
582       }
583       break;
584
585     default:
586       fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
587     }
588
589   addr_inc = 0;
590 }
591
592 print_operand_address (file, addr)
593      FILE *file;
594      rtx addr;
595 {
596   switch (GET_CODE (addr))
597     {
598     case REG:
599       fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
600       break;
601     case PLUS:
602       {
603         register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
604         switch (GET_CODE (x))
605           {
606           case REG:
607             switch (GET_CODE (y))
608               {
609               case CONST:
610                 output_address (XEXP (y, 0));
611                 fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
612                 break;
613               case CONST_INT:
614                 fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
615                 break;
616               case SYMBOL_REF:
617                 fprintf (file, "%s", XSTR (y, 0));
618                 if (addr_inc)
619                   fprintf (file, "+%d", addr_inc);
620                 fprintf (file, ",r%d  ; P_O_A reg + sym", REGNO (x));
621                 break;
622               case LABEL_REF:
623                 output_address (XEXP (y, 0));
624                 fprintf (file, ",r%d  ; P_O_A reg + label", REGNO (x));
625                 break;
626               default:
627                 fprintf (file, "[P_O_A reg%d+UFO code=%d]",
628                          REGNO (x), GET_CODE (y));
629               }
630             break;
631           case LABEL_REF:
632             output_address (XEXP (x, 0));
633             break;
634           case SYMBOL_REF:
635             switch (GET_CODE (y))
636               {
637               case CONST_INT:
638                 fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
639                 break;
640               case REG:
641                 fprintf (file, "%s,r%d ;P_O_A sym + reg",
642                          XSTR (x, 0), REGNO (y));
643                 break;
644               default:
645                 fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
646                          XSTR (x, 0), GET_CODE (y));
647               }
648             break;
649           case CONST:
650             output_address (XEXP (x, 0));
651             if (GET_CODE (y) == REG)
652               fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
653             else
654               fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
655             break;
656           case MEM:
657             output_address (y);
658             fprintf (file, ",[mem:");
659             output_address (XEXP (x, 0));
660             fprintf (file, "] ;P_O_A plus");
661             break;
662           default:
663             fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
664                      GET_CODE (x), GET_CODE (y));
665           }
666       }
667       break;
668     case CONST_INT:
669       if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
670         fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
671       else
672         {
673           fprintf (file, "[p_o_a=ILLEGAL_CONST]");
674           output_addr_const (file, addr);
675         }
676       break;
677     case LABEL_REF:
678     case SYMBOL_REF:
679       fprintf (file, "%s", XSTR (addr, 0));
680       if (addr_inc)
681         fprintf (file, "+%d", addr_inc);
682       break;
683     case MEM:
684       fprintf (file, "[memUFO:");
685       output_address (XEXP (addr, 0));
686       fprintf (file, "]");
687       break;
688     case CONST:
689       output_address (XEXP (addr, 0));
690       fprintf (file, " ;P_O_A const");
691       break;
692     case CODE_LABEL:
693       fprintf (file, "L%d", XINT (addr, 3));
694       break;
695     default:
696       fprintf (file, " p_o_a UFO, code=%d val=0x%x",
697                (int) GET_CODE (addr), INTVAL (addr));
698       break;
699     }
700   addr_inc = 0;
701 }
702
703
704 /*
705  *  Return non zero if the LS 16 bits of the given value has just one bit set,
706  *  otherwise return zero. Note this function may be used to detect one
707  *  bit clear by inverting the param.
708  */
709 int
710 one_bit_set_p (x)
711      int x;
712 {
713   x &= 0xffff; 
714   return x && (x & (x - 1)) == 0;
715 }
716
717
718 /*
719  * Return the number of the least significant bit set, using the  same
720  * convention for bit numbering as in the MIL-STD-1750 sb instruction.
721  */
722 int
723 which_bit (x)
724      int x;
725 {
726   int b = 15;
727
728   while (b > 0 && (x & 1) == 0)
729     {
730       b--;
731       x >>= 1;
732     }
733
734   return b;
735 }
736
737