Initial revision
[official-gcc.git] / gcc / config / 1750a / 1750a.c
blob26a30da34dc5c128c3675795992f55d43613773a
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)
5 This file is part of GNU CC.
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.
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.
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. */
22 #ifndef FILE
23 #include <stdio.h>
24 #endif
25 #include <string.h>
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"
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"};
46 int
47 notice_update_cc (exp)
48 rtx exp;
50 if (GET_CODE (exp) == SET)
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)
63 CC_STATUS_INIT;
64 return;
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)
71 CC_STATUS_INIT;
72 return;
74 /* Tests and compares set the cc's in predictable ways. */
75 if (SET_DEST (exp) == cc0_rtx)
77 CC_STATUS_INIT;
78 cc_status.value1 = SET_SRC (exp);
79 return;
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;
87 else if (GET_CODE (exp) == PARALLEL
88 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
90 if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
91 return;
92 if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
94 CC_STATUS_INIT;
95 cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
96 return;
98 CC_STATUS_INIT;
100 else
102 CC_STATUS_INIT;
108 function_arg (cum, mode, type, named)
109 int cum;
110 enum machine_mode mode;
111 tree type;
112 int named;
114 int size;
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;
129 double
130 get_double (x)
131 rtx x;
133 union
135 double d;
136 long i[2];
140 du.i[0] = CONST_DOUBLE_LOW (x);
141 du.i[1] = CONST_DOUBLE_HIGH (x);
142 return du.d;
145 char *
146 float_label (code, value)
147 char code;
148 double value;
150 int i = 1;
151 static char label[32];
152 char *p;
154 label[0] = code;
155 p = label + 1;
156 sprintf (p, "%lf", value);
157 while (*p)
159 *p = (*p == '+') ? 'p' :
160 (*p == '-') ? 'm' : *p;
161 p++;
163 return xstrdup (label);
167 char *
168 movcnt_regno_adjust (op)
169 rtx *op;
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)
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;
198 char *
199 mod_regno_adjust (instr, op)
200 char *instr;
201 rtx *op;
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;
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;
220 /* Check if op is a valid memory operand for 1750A Load/Store instructions
221 (memory indirection permitted.) */
224 memop_valid (op)
225 rtx op;
227 static int recurred = 0;
228 int valid;
230 if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
231 && GET_MODE (op) != QImode)
232 return 0;
233 switch (GET_CODE (op))
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;
265 /* predicate for the MOV instruction: */
267 mov_memory_operand (op, mode)
268 rtx op;
269 enum machine_mode mode;
271 return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
274 /* predicate for the STC instruction: */
276 small_nonneg_const (op, mode)
277 rtx op;
278 enum machine_mode mode;
280 if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
281 return 1;
282 return 0;
285 /* predicate for constant zero: */
287 zero_operand (op, mode)
288 rtx op;
289 enum machine_mode mode;
291 return op == CONST0_RTX (mode);
295 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
296 memory operand */
298 b_mode_operand (op)
299 rtx op;
301 if (GET_CODE (op) == MEM)
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)
308 rtx plus_op0 = XEXP (inner, 0);
309 if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
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;
319 return 0;
323 /* Decide whether to output a conditional jump as a "Jump Conditional"
324 or as a "Branch Conditional": */
327 find_jmplbl (labelnum)
328 int labelnum;
330 int i, found = 0;
332 for (i = 0; i <= jmplbl_ndx; i++)
333 if (labelnum == jmplbl[i].num)
335 found = 1;
336 break;
338 if (found)
339 return i;
340 return -1;
343 char *
344 branch_or_jump (condition, targetlabel_number)
345 char *condition;
346 int targetlabel_number;
348 static char buf[30];
349 int index;
351 if ((index = find_jmplbl (targetlabel_number)) >= 0)
352 if (program_counter - jmplbl[index].pc < 128)
354 sprintf (buf, "b%s %%l0", condition);
355 return buf;
357 sprintf (buf, "jc %s,%%l0", condition);
358 return buf;
363 unsigned_comparison_operator (insn)
364 rtx insn;
366 switch (GET_CODE (insn))
368 case GEU:
369 case GTU:
370 case LEU:
371 case LTU:
372 return 1;
373 default:
374 return 0;
379 next_cc_user_is_unsigned (insn)
380 rtx insn;
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 ();
396 static int addr_inc;
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.
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.
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'.
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.
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
428 print_operand (file, x, letter)
429 FILE *file;
430 rtx x;
431 int letter;
433 switch (GET_CODE (x))
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;
444 case SYMBOL_REF:
445 fprintf (file, "%s", XSTR (x, 0));
446 if (letter == 'A')
447 fprintf (file, "+1");
448 break;
450 case LABEL_REF:
451 case CONST:
452 case MEM:
453 if (letter == 'Q')
455 rtx inner = XEXP (x, 0);
456 switch (GET_CODE (inner))
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));
469 else
471 addr_inc = (letter == 'A' ? 1 : 0);
472 output_address (XEXP (x, 0));
474 break;
476 case CONST_DOUBLE:
477 /* {
478 double value = get_double (x);
479 char fltstr[32];
480 sprintf (fltstr, "%lf", value);
482 if (letter == 'D' || letter == 'E')
484 int i, found = 0;
485 for (i = 0; i <= datalbl_ndx; i++)
486 if (strcmp (fltstr, datalbl[i].value) == 0)
488 found = 1;
489 break;
491 if (!found)
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);
502 else if (letter == 'F' || letter == 'G')
504 int i, found = 0;
505 for (i = 0; i <= datalbl_ndx; i++)
506 if (strcmp (fltstr, datalbl[i].value) == 0)
508 found = 1;
509 break;
511 if (!found)
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);
523 fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
525 else
526 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
529 fprintf (file, "%lf", get_double (x));
530 break;
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;
545 case CODE_LABEL:
546 fprintf (file, "L%d", XINT (x, 3));
547 break;
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;
554 case PLUS:
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)
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));
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);
583 break;
585 default:
586 fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
589 addr_inc = 0;
592 print_operand_address (file, addr)
593 FILE *file;
594 rtx addr;
596 switch (GET_CODE (addr))
598 case REG:
599 fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
600 break;
601 case PLUS:
603 register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
604 switch (GET_CODE (x))
606 case REG:
607 switch (GET_CODE (y))
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));
630 break;
631 case LABEL_REF:
632 output_address (XEXP (x, 0));
633 break;
634 case SYMBOL_REF:
635 switch (GET_CODE (y))
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));
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));
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
673 fprintf (file, "[p_o_a=ILLEGAL_CONST]");
674 output_addr_const (file, addr);
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;
700 addr_inc = 0;
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.
710 one_bit_set_p (x)
711 int x;
713 x &= 0xffff;
714 return x && (x & (x - 1)) == 0;
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.
723 which_bit (x)
724 int x;
726 int b = 15;
728 while (b > 0 && (x & 1) == 0)
730 b--;
731 x >>= 1;
734 return b;