1 /* Subroutines for insn-output.c for MIL-STD-1750.
2 Copyright (C) 1994, 1995, 1996 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)
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. */
33 #include "conditions.h"
36 struct datalabel_array datalbl[DATALBL_ARRSIZ];
38 struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
40 int label_pending = 0, program_counter = 0;
41 enum section current_section = Normal;
43 {"Init", "Normal", "Konst", "Static"};
46 notice_update_cc (exp)
49 if (GET_CODE (exp) == SET)
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)
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))
59 /* Function calls clobber the cc's. */
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)
73 /* Tests and compares set the cc's in predictable ways. */
74 if (SET_DEST (exp) == cc0_rtx)
77 cc_status.value1 = SET_SRC (exp);
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);
86 else if (GET_CODE (exp) == PARALLEL
87 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
89 if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
91 if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
94 cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
107 function_arg (cum, mode, type, named)
109 enum machine_mode mode;
115 if (MUST_PASS_IN_STACK (mode, type))
118 size = int_size_in_bytes (type);
120 size = GET_MODE_SIZE (mode);
122 return gen_rtx (REG, mode, cum);
136 if ((p = (char *) malloc (strlen (str) + 1)) == NULL)
138 fprintf (stderr, "dynamic memory exhausted");
141 return strcpy (p, str);
158 du.i[0] = CONST_DOUBLE_LOW (x);
159 du.i[1] = CONST_DOUBLE_HIGH (x);
164 float_label (code, value)
169 static char label[32];
174 sprintf (p, "%lf", value);
177 *p = (*p == '+') ? 'p' :
178 (*p == '-') ? 'm' : *p;
181 return strdup (label);
186 movcnt_regno_adjust (op)
189 static char outstr[80];
190 int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
194 #define cntreg_1750 (op0r + 1)
196 if (cntreg == cntreg_1750)
197 sprintf (outstr, "mov r%d,r%d", op0r, op1r);
198 else if (dstreg + 1 == srcreg && cntreg > srcreg)
199 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r);
200 else if (dstreg == cntreg + 1)
201 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r);
202 else if (dstreg == srcreg + 1)
203 sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
204 op0r, op1r, op0r, op2r, op1r, op2r);
205 else if (cntreg + 1 == srcreg)
206 sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
207 op2r, op1r, op0r, op2r, op2r, op0r);
208 else if (cntreg == srcreg + 1)
209 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r);
211 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,%d\n\txwr r%d,r%d",
212 op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750);
217 mod_regno_adjust (instr, op)
221 static char outstr[40];
222 char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
223 int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
225 if (modregno_gcc == modregno_1750)
226 sprintf (outstr, "%s r%%0,%s%%2", instr, r);
228 sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
229 modregno_gcc, modregno_1750, instr, r, modregno_1750, modregno_gcc);
234 /* Auxiliary to `nonindirect_operand':
235 Check if op is a valid memory operand for 1750A arith./logic (non-move)
241 if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode)
243 switch (GET_CODE (op))
251 if (!memop_valid (XEXP (op, 0)))
253 return memop_valid (XEXP (op, 1));
264 printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
269 /* extra predicate for recog: */
271 nonindirect_operand (op, mode)
273 enum machine_mode mode;
277 switch (GET_CODE (op))
280 retval = memop_valid (XEXP (op, 0));
285 if (!CONSTANT_P (op))
291 /* predicate for the MOV instruction: */
293 mov_memory_operand (op, mode)
295 enum machine_mode mode;
297 return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
300 /* predicate for the STC instruction: */
302 small_nonneg_const (op, mode)
304 enum machine_mode mode;
306 if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
311 /* predicate for constant zero: */
313 zero_operand (op, mode)
315 enum machine_mode mode;
317 return op == CONST0_RTX (mode);
321 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
327 if (GET_CODE (op) == MEM)
329 rtx inner = XEXP (op, 0);
330 if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
332 if (GET_CODE (inner) == PLUS)
334 rtx plus_op0 = XEXP (inner, 0);
335 if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
337 rtx plus_op1 = XEXP (inner, 1);
338 if (GET_CODE (plus_op1) == CONST_INT
339 && INTVAL (plus_op1) >= 0
340 && INTVAL (plus_op1) <= 255)
348 /* predicate needed for adding 1 to mem (short before output) */
350 simple_memory_operand (op, mode)
352 enum machine_mode mode;
355 if (GET_CODE (op) != MEM)
357 inner = XEXP (op, 0);
358 switch (GET_CODE (inner))
365 if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
367 inner = (XEXP (inner, 0));
368 switch (GET_CODE (inner))
375 if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
377 switch (GET_CODE (XEXP (inner, 0)))
389 /* destructively add one to memory address */
390 add_1_to_mem (opnd) /* returns 0 for success, -1 for failure */
391 rtx opnd; /* OPND must be a MEM rtx */
393 rtx inner = XEXP (opnd, 0);
395 if (GET_CODE (opnd) != MEM)
397 fprintf (stderr, "add_1_to_mem: input is not MEM\n");
398 return -1; /* failure */
400 switch (GET_CODE (inner))
403 inner = XEXP (inner, 0);
404 if (GET_CODE (inner) != PLUS
405 || GET_CODE (XEXP (inner, 1)) != CONST_INT)
407 fprintf (stderr, "add_1_to_mem: CONST failure\n");
410 INTVAL (XEXP (XEXP (XEXP (opnd, 0), 0), 1)) += 1;
413 XEXP (opnd, 0) = gen_rtx (PLUS, Pmode, inner, const1_rtx);
417 XEXP (opnd, 0) = gen_rtx (CONST, VOIDmode,
418 gen_rtx (PLUS, Pmode, inner, const1_rtx));
421 inner = XEXP (inner, 1);
422 switch (GET_CODE (inner))
425 inner = XEXP (inner, 0);
426 if (GET_CODE (inner) != PLUS
427 || GET_CODE (XEXP (inner, 1)) != CONST_INT)
429 fprintf (stderr, "add_1_to_mem: PLUS CONST failure\n");
432 INTVAL (XEXP (XEXP (XEXP (XEXP (opnd, 0), 1), 0), 1)) += 1;
435 INTVAL (XEXP (XEXP (opnd, 0), 1)) += 1;
439 XEXP (XEXP (opnd, 0), 1) = gen_rtx (CONST, VOIDmode,
440 gen_rtx (PLUS, Pmode, inner, const1_rtx));
443 fprintf (stderr, "add_1_to_mem: PLUS failure\n");
451 /* Decide whether to output a conditional jump as a "Jump Conditional"
452 or as a "Branch Conditional": */
455 find_jmplbl (labelnum)
460 for (i = 0; i <= jmplbl_ndx; i++)
461 if (labelnum == jmplbl[i].num)
472 branch_or_jump (condition, targetlabel_number)
474 int targetlabel_number;
479 if ((index = find_jmplbl (targetlabel_number)) >= 0)
480 if (program_counter - jmplbl[index].pc < 128)
482 sprintf (buf, "b%s %%l0", condition);
485 sprintf (buf, "jc %s,%%l0", condition);
491 unsigned_comparison_operator (insn)
494 switch (GET_CODE (insn))
507 next_cc_user_is_unsigned (insn)
510 if ( !(insn = next_cc0_user (insn)))
512 else if (GET_CODE (insn) == JUMP_INSN
513 && GET_CODE (PATTERN (insn)) == SET
514 && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
515 return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0));
516 else if (GET_CODE (insn) == INSN
517 && GET_CODE (PATTERN (insn)) == SET)
518 return unsigned_comparison_operator (SET_SRC (PATTERN (insn)));
525 /* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been
528 print_operand (file, x, kode)
533 switch (GET_CODE (x))
536 fprintf (file, "%d", REGNO (x));
539 fprintf (file, "%s", XSTR (x, 0));
546 rtx inner = XEXP (x, 0);
547 switch (GET_CODE (inner))
550 fprintf (file, "r%d,0", REGNO (inner));
553 fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
554 INTVAL (XEXP (inner, 1)));
557 fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
561 output_address (XEXP (x, 0));
565 double value = get_double (x);
567 sprintf (fltstr, "%lf", value);
569 if (kode == 'D' || kode == 'E')
572 for (i = 0; i <= datalbl_ndx; i++)
573 if (strcmp (fltstr, datalbl[i].value) == 0)
580 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
581 datalbl[i].name = float_label (kode, value);
582 datalbl[i].size = (kode == 'E') ? 3 : 2;
583 check_section (Konst);
584 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
585 (kode == 'E' ? "ef" : "f"), fltstr);
586 check_section (Normal);
589 else if (kode == 'F' || kode == 'G')
592 for (i = 0; i <= datalbl_ndx; i++)
593 if (strcmp (fltstr, datalbl[i].value) == 0)
601 "float value %lfnot found upon label reference\n", value);
602 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
603 datalbl[i].name = float_label (kode, value);
604 datalbl[i].size = (kode == 'G') ? 3 : 2;
605 check_section (Konst);
606 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
607 (kode == 'G' ? "ef" : "f"), fltstr);
608 check_section (Normal);
610 fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
613 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
616 fprintf (file, "%lf", get_double (x));
620 fprintf (file, "%d", -INTVAL (x));
621 else if (INTVAL (x) > 0x7FFF)
622 fprintf (file, "%d ; range correction (val>0x7FFF) applied",
623 INTVAL (x) - 0x10000);
625 fprintf (file, "%d", INTVAL (x));
628 fprintf (file, "L%d", XINT (x, 3));
631 fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
632 XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
636 rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
637 int op0code = GET_CODE (op0), op1code = GET_CODE (op1);
638 if (op1code == CONST_INT)
642 fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
643 INTVAL (op1), REGNO (op0));
646 fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
649 fprintf (file, "%d,[mem:", INTVAL (op1));
650 output_address (XEXP (op0, 0));
651 fprintf (file, "] ;P_O plus");
654 fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
655 (int) op0code, INTVAL (op1));
657 else if (op1code == SYMBOL_REF && op0code == REG)
658 fprintf (file, "%s,r%d ; P_O: (plus reg sym)",
659 XSTR (op1, 0), REGNO (op0));
661 fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
665 fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
669 print_operand_address (file, addr)
673 switch (GET_CODE (addr))
676 fprintf (file, "0,r%d ; P_O_A", REGNO (addr));
680 register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
681 switch (GET_CODE (x))
684 switch (GET_CODE (y))
687 output_address (XEXP (y, 0));
688 fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
691 fprintf (file, "%d,r%d", INTVAL (y), REGNO (x));
694 fprintf (file, "%s,r%d ; P_O_A reg + sym",
695 XSTR (y, 0), REGNO (x));
698 output_address (XEXP (y, 0));
699 fprintf (file, ",r%d ; P_O_A reg + label", REGNO (x));
702 fprintf (file, "[P_O_A reg%d+UFO code=%d]",
703 REGNO (x), GET_CODE (y));
707 output_address (XEXP (x, 0));
710 switch (GET_CODE (y))
713 fprintf (file, "%d+%s", INTVAL (y), XSTR (x, 0));
716 fprintf (file, "%s,r%d ;P_O_A sym + reg",
717 XSTR (x, 0), REGNO (y));
720 fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
721 XSTR (x, 0), GET_CODE (y));
725 output_address (XEXP (x, 0));
726 if (GET_CODE (y) == REG)
727 fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
729 fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
733 fprintf (file, ",[mem:");
734 output_address (XEXP (x, 0));
735 fprintf (file, "] ;P_O_A plus");
738 fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
739 GET_CODE (x), GET_CODE (y));
744 if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
745 fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
748 fprintf (file, "[p_o_a=ILLEGAL_CONST]");
749 output_addr_const (file, addr);
754 fprintf (file, "%s", XSTR (addr, 0));
757 fprintf (file, "[memUFO:");
758 output_address (XEXP (addr, 0));
762 output_address (XEXP (addr, 0));
763 fprintf (file, " ;P_O_A const");
766 fprintf (file, "L%d", XINT (addr, 3));
769 fprintf (file, " p_o_a UFO, code=%d val=0x%x",
770 (int) GET_CODE (addr), INTVAL (addr));