1 /* Subroutines for insn-output.c for MIL-STD-1750.
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999,
3 2000 Free Software Foundation, Inc.
4 Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de)
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
31 #include "conditions.h"
38 #include "target-def.h"
40 struct datalabel_array datalbl
[DATALBL_ARRSIZ
];
42 struct jumplabel_array jmplbl
[JMPLBL_ARRSIZ
];
44 int label_pending
= 0, program_counter
= 0;
45 enum section current_section
= Normal
;
46 const char *const sectname
[4] =
47 {"Init", "Normal", "Konst", "Static"};
49 static int which_bit
PARAMS ((int));
50 static void output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
51 static void output_function_epilogue
PARAMS ((FILE *, HOST_WIDE_INT
));
53 /* Initialize the GCC target structure. */
54 #undef TARGET_ASM_FUNCTION_PROLOGUE
55 #define TARGET_ASM_FUNCTION_PROLOGUE output_function_prologue
56 #undef TARGET_ASM_FUNCTION_EPILOGUE
57 #define TARGET_ASM_FUNCTION_EPILOGUE output_function_epilogue
59 struct gcc_target target
= TARGET_INITIALIZER
;
61 /* Generate the assembly code for function entry. FILE is a stdio
62 stream to output the code to. SIZE is an int: how many units of
63 temporary storage to allocate.
65 Refer to the array `regs_ever_live' to determine which registers to
66 save; `regs_ever_live[I]' is nonzero if register number I is ever
67 used in the function. This function is responsible for knowing
68 which registers should not be saved even if used. */
71 output_function_prologue (file
, size
)
77 int regno
, regs_used
= 0;
79 fprintf (file
, "\t; registers used: ");
80 for (regno
= 0; regno
< 14; regno
++)
81 if (regs_ever_live
[regno
])
83 fprintf (file
, " %s", reg_names
[regno
]);
88 fprintf (file
, "(none)");
93 fprintf (file
, "\n\t%s\tr15,%d",
94 (size
<= 16 ? "sisp" : "sim"), size
);
96 fprintf (file
, " ; reserve local-variable space");
99 if (frame_pointer_needed
)
101 fprintf(file
, "\n\tpshm\tr14,r14");
102 if (flag_verbose_asm
)
103 fprintf (file
, " ; push old frame");
104 fprintf (file
, "\n\tlr\tr14,r15");
105 if (flag_verbose_asm
)
106 fprintf (file
, " ; set new frame");
109 fprintf (file
, "\n");
114 /* This function generates the assembly code for function exit.
115 Args are as for output_function_prologue ().
117 The function epilogue should not depend on the current stack
118 pointer! It should use the frame pointer only. This is mandatory
119 because of alloca; we also take advantage of it to omit stack
120 adjustments before returning. */
123 output_function_epilogue (file
, size
)
127 if (frame_pointer_needed
)
129 fprintf (file
, "\tlr\tr15,r14");
130 if (flag_verbose_asm
)
131 fprintf (file
, " ; set stack ptr to frame ptr");
132 fprintf (file
, "\n\tpopm\tr14,r14");
133 if (flag_verbose_asm
)
134 fprintf (file
, " ; restore previous frame ptr");
135 fprintf (file
, "\n");
140 fprintf (file
, "\t%s\tr15,%d",
141 (size
<= 16 ? "aisp" : "aim"), size
);
142 if (flag_verbose_asm
)
143 fprintf (file
, " ; free up local-var space");
144 fprintf (file
, "\n");
147 fprintf (file
, "\turs\tr15\n\n");
151 notice_update_cc (exp
)
154 if (GET_CODE (exp
) == SET
)
156 enum rtx_code src_code
= GET_CODE (SET_SRC (exp
));
157 /* Jumps do not alter the cc's. */
158 if (SET_DEST (exp
) == pc_rtx
)
160 /* Moving a register or constant into memory doesn't alter the cc's. */
161 if (GET_CODE (SET_DEST (exp
)) == MEM
162 && (src_code
== REG
|| src_code
== CONST_INT
))
164 /* Function calls clobber the cc's. */
165 if (src_code
== CALL
)
170 /* Emulated longword bit-ops leave cc's incorrect */
171 if (GET_MODE (SET_DEST (exp
)) == HImode
?
172 src_code
== AND
|| src_code
== IOR
||
173 src_code
== XOR
|| src_code
== NOT
: 0)
178 /* Tests and compares set the cc's in predictable ways. */
179 if (SET_DEST (exp
) == cc0_rtx
)
182 cc_status
.value1
= SET_SRC (exp
);
185 /* Anything else will set cc_status. */
186 cc_status
.flags
= CC_NO_OVERFLOW
;
187 cc_status
.value1
= SET_SRC (exp
);
188 cc_status
.value2
= SET_DEST (exp
);
191 else if (GET_CODE (exp
) == PARALLEL
192 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
194 if (SET_DEST (XVECEXP (exp
, 0, 0)) == pc_rtx
)
196 if (SET_DEST (XVECEXP (exp
, 0, 0)) == cc0_rtx
)
199 cc_status
.value1
= SET_SRC (XVECEXP (exp
, 0, 0));
212 function_arg (cum
, mode
, type
, named
)
214 enum machine_mode mode
;
216 int named ATTRIBUTE_UNUSED
;
220 if (MUST_PASS_IN_STACK (mode
, type
))
223 size
= int_size_in_bytes (type
);
225 size
= GET_MODE_SIZE (mode
);
227 return gen_rtx_REG (mode
, cum
);
244 du
.i
[0] = CONST_DOUBLE_LOW (x
);
245 du
.i
[1] = CONST_DOUBLE_HIGH (x
);
250 float_label (code
, value
)
254 static char label
[32];
259 sprintf (p
, "%f", value
);
262 *p
= (*p
== '+') ? 'p' :
263 (*p
== '-') ? 'm' : *p
;
266 return xstrdup (label
);
271 movcnt_regno_adjust (op
)
274 static char outstr
[80];
275 int op0r
= REGNO (op
[0]), op1r
= REGNO (op
[1]), op2r
= REGNO (op
[2]);
279 #define cntreg_1750 (op0r + 1)
281 if (cntreg
== cntreg_1750
)
282 sprintf (outstr
, "mov r%d,r%d", op0r
, op1r
);
283 else if (dstreg
+ 1 == srcreg
&& cntreg
> srcreg
)
284 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d", op2r
, op1r
, op0r
, op2r
);
285 else if (dstreg
== cntreg
+ 1)
286 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d", op0r
, op2r
, op2r
, op1r
);
287 else if (dstreg
== srcreg
+ 1)
288 sprintf (outstr
, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
289 op0r
, op1r
, op0r
, op2r
, op1r
, op2r
);
290 else if (cntreg
+ 1 == srcreg
)
291 sprintf (outstr
, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
292 op2r
, op1r
, op0r
, op2r
, op2r
, op0r
);
293 else if (cntreg
== srcreg
+ 1)
294 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d", op0r
, op1r
, op1r
, op0r
);
296 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
297 op2r
, cntreg_1750
, op0r
, op1r
, op2r
, cntreg_1750
);
302 mod_regno_adjust (instr
, op
)
306 static char outstr
[40];
307 const char *r
= (!strncmp (instr
, "dvr", 3) ? "r" : "");
308 int modregno_gcc
= REGNO (op
[3]), modregno_1750
= REGNO (op
[0]) + 1;
310 if (modregno_gcc
== modregno_1750
311 || (reg_renumber
!= NULL
312 && reg_renumber
[modregno_gcc
] >= 0
313 && reg_renumber
[modregno_gcc
] == reg_renumber
[modregno_1750
]))
314 sprintf (outstr
, "%s r%%0,%s%%2", instr
, r
);
316 sprintf (outstr
, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
317 modregno_gcc
, modregno_1750
, instr
, r
, modregno_1750
,
323 /* Check if op is a valid memory operand for 1750A Load/Store instructions
324 (memory indirection permitted.) */
330 static int recurred
= 0;
333 if (GET_MODE (op
) != Pmode
&& GET_MODE (op
) != VOIDmode
334 && GET_MODE (op
) != QImode
)
336 switch (GET_CODE (op
))
339 if (!recurred
&& GET_CODE (XEXP (op
, 0)) == REG
)
347 valid_operand
= memop_valid (XEXP (op
, 0));
349 valid_operand
= memop_valid (XEXP (op
, 1));
351 return valid_operand
;
362 printf ("memop_valid: code=%d\n", (int) GET_CODE (op
));
368 /* predicate for the MOV instruction: */
370 mov_memory_operand (op
, mode
)
372 enum machine_mode mode ATTRIBUTE_UNUSED
;
374 return (GET_CODE (op
) == MEM
&& GET_CODE (XEXP (op
, 0)) == REG
);
377 /* predicate for the STC instruction: */
379 small_nonneg_const (op
, mode
)
381 enum machine_mode mode ATTRIBUTE_UNUSED
;
383 if (GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0 && INTVAL (op
) <= 15)
388 /* predicate for constant zero: */
390 zero_operand (op
, mode
)
392 enum machine_mode mode
;
394 return op
== CONST0_RTX (mode
);
398 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
404 if (GET_CODE (op
) == MEM
)
406 rtx inner
= XEXP (op
, 0);
407 if (GET_CODE (inner
) == REG
&& REG_OK_FOR_INDEX_P (inner
))
409 if (GET_CODE (inner
) == PLUS
)
411 rtx plus_op0
= XEXP (inner
, 0);
412 if (GET_CODE (plus_op0
) == REG
&& REG_OK_FOR_INDEX_P (plus_op0
))
414 rtx plus_op1
= XEXP (inner
, 1);
415 if (GET_CODE (plus_op1
) == CONST_INT
416 && INTVAL (plus_op1
) >= 0
417 && INTVAL (plus_op1
) <= 255)
426 /* Decide whether to output a conditional jump as a "Jump Conditional"
427 or as a "Branch Conditional": */
430 find_jmplbl (labelnum
)
435 for (i
= 0; i
<= jmplbl_ndx
; i
++)
436 if (labelnum
== jmplbl
[i
].num
)
447 branch_or_jump (condition
, targetlabel_number
)
448 const char *condition
;
449 int targetlabel_number
;
454 if ((index
= find_jmplbl (targetlabel_number
)) >= 0)
455 if (program_counter
- jmplbl
[index
].pc
< 128)
457 sprintf (buf
, "b%s %%l0", condition
);
460 sprintf (buf
, "jc %s,%%l0", condition
);
466 unsigned_comparison_operator (insn
)
469 switch (GET_CODE (insn
))
482 next_cc_user_is_unsigned (insn
)
485 if ( !(insn
= next_cc0_user (insn
)))
487 else if (GET_CODE (insn
) == JUMP_INSN
488 && GET_CODE (PATTERN (insn
)) == SET
489 && GET_CODE (SET_SRC (PATTERN (insn
))) == IF_THEN_ELSE
)
490 return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn
)), 0));
491 else if (GET_CODE (insn
) == INSN
492 && GET_CODE (PATTERN (insn
)) == SET
)
493 return unsigned_comparison_operator (SET_SRC (PATTERN (insn
)));
501 /* A C compound statement to output to stdio stream STREAM the
502 assembler syntax for an instruction operand X. X is an RTL
505 CODE is a value that can be used to specify one of several ways
506 of printing the operand. It is used when identical operands
507 must be printed differently depending on the context. CODE
508 comes from the `%' specification that was used to request
509 printing of the operand. If the specification was just `%DIGIT'
510 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
511 is the ASCII code for LTR.
513 If X is a register, this macro should print the register's name.
514 The names can be found in an array `reg_names' whose type is
515 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
517 When the machine description has a specification `%PUNCT' (a `%'
518 followed by a punctuation character), this macro is called with
519 a null pointer for X and the punctuation character for CODE.
521 The 1750 specific codes are:
522 'J' for the negative of a constant
523 'Q' for printing addresses in B mode syntax
524 'd' for the second register in a pair
525 't' for the third register in a triple
526 'b' for the bit number (using 1750 test bit convention)
527 'B' for the bit number of the 1's complement (for bit clear)
532 print_operand (file
, x
, letter
)
537 switch (GET_CODE (x
))
541 fprintf (file
, "%d", REGNO (x
) + 1);
542 else if (letter
== 't')
543 fprintf (file
, "%d", REGNO (x
) + 2);
545 fprintf (file
, "%d", REGNO (x
));
549 fprintf (file
, "%s", XSTR (x
, 0));
551 fprintf (file
, "+1");
559 rtx inner
= XEXP (x
, 0);
560 switch (GET_CODE (inner
))
563 fprintf (file
, "r%d,0", REGNO (inner
));
566 fprintf (file
, "r%d,%d", REGNO (XEXP (inner
, 0)),
567 INTVAL (XEXP (inner
, 1)));
570 fprintf (file
, "[ill Q code=%d]", GET_CODE (inner
));
575 addr_inc
= (letter
== 'A' ? 1 : 0);
576 output_address (XEXP (x
, 0));
582 double value = get_double (x);
584 sprintf (fltstr, "%f", value);
586 if (letter == 'D' || letter == 'E')
589 for (i = 0; i <= datalbl_ndx; i++)
590 if (strcmp (fltstr, datalbl[i].value) == 0)
597 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
598 datalbl[i].name = float_label (letter, value);
599 datalbl[i].size = (letter == 'E') ? 3 : 2;
600 check_section (Konst);
601 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
602 (letter == 'E' ? "ef" : "f"), fltstr);
603 check_section (Normal);
606 else if (letter == 'F' || letter == 'G')
609 for (i = 0; i <= datalbl_ndx; i++)
610 if (strcmp (fltstr, datalbl[i].value) == 0)
618 "float value %f not found upon label reference\n", value);
619 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
620 datalbl[i].name = float_label (letter, value);
621 datalbl[i].size = (letter == 'G') ? 3 : 2;
622 check_section (Konst);
623 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
624 (letter == 'G' ? "ef" : "f"), fltstr);
625 check_section (Normal);
627 fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
630 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
633 fprintf (file
, "%f", get_double (x
));
638 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, -INTVAL (x
));
639 else if (letter
== 'b')
640 fprintf (file
, "%d", which_bit (INTVAL (x
)));
641 else if (letter
== 'B')
642 fprintf (file
, "%d", which_bit (~INTVAL (x
)));
643 else if (letter
== 'w')
644 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) - 16);
646 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
650 fprintf (file
, "L%d", XINT (x
, 3));
654 fprintf (file
, "CALL nargs=");
655 fprintf (file
, HOST_PTR_PRINTF
, XEXP (x
, 1));
656 fprintf (file
, ", func is either '%s' or '%s'",
657 XSTR (XEXP (XEXP (x
, 0), 1), 0), XSTR (XEXP (x
, 0), 1));
662 rtx op0
= XEXP (x
, 0), op1
= XEXP (x
, 1);
663 int op0code
= GET_CODE (op0
), op1code
= GET_CODE (op1
);
664 if (op1code
== CONST_INT
)
668 fprintf (file
, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
669 INTVAL (op1
), REGNO (op0
));
672 fprintf (file
, "%d+%s", INTVAL (op1
), XSTR (op0
, 0));
675 fprintf (file
, "%d,[mem:", INTVAL (op1
));
676 output_address (XEXP (op0
, 0));
677 fprintf (file
, "] ;P_O plus");
680 fprintf (file
, "p_o_PLUS UFO, code=%d, with CONST=%d",
681 (int) op0code
, INTVAL (op1
));
683 else if (op1code
== SYMBOL_REF
&& op0code
== REG
)
684 fprintf (file
, "%s,r%d ; P_O: (plus reg sym)",
685 XSTR (op1
, 0), REGNO (op0
));
687 fprintf (file
, "p_o_+: op0code=%d, op1code=%d", op0code
, op1code
);
692 fprintf (file
, "p_o_UFO code=%d", GET_CODE (x
));
699 print_operand_address (file
, addr
)
703 switch (GET_CODE (addr
))
706 fprintf (file
, "%d,r%d ; P_O_A", addr_inc
, REGNO (addr
));
710 register rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
711 switch (GET_CODE (x
))
714 switch (GET_CODE (y
))
717 output_address (XEXP (y
, 0));
718 fprintf (file
, ",r%d ;P_O_A reg + const expr", REGNO (x
));
721 fprintf (file
, "%d,r%d", INTVAL (y
) + addr_inc
, REGNO (x
));
724 fprintf (file
, "%s", XSTR (y
, 0));
726 fprintf (file
, "+%d", addr_inc
);
727 fprintf (file
, ",r%d ; P_O_A reg + sym", REGNO (x
));
730 output_address (XEXP (y
, 0));
731 fprintf (file
, ",r%d ; P_O_A reg + label", REGNO (x
));
734 fprintf (file
, "[P_O_A reg%d+UFO code=%d]",
735 REGNO (x
), GET_CODE (y
));
739 output_address (XEXP (x
, 0));
742 switch (GET_CODE (y
))
745 fprintf (file
, "%d+%s", INTVAL (y
) + addr_inc
, XSTR (x
, 0));
748 fprintf (file
, "%s,r%d ;P_O_A sym + reg",
749 XSTR (x
, 0), REGNO (y
));
752 fprintf (file
, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
753 XSTR (x
, 0), GET_CODE (y
));
757 output_address (XEXP (x
, 0));
758 if (GET_CODE (y
) == REG
)
759 fprintf (file
, ",r%d ;P_O_A const + reg", REGNO (x
));
761 fprintf (file
, "P_O_A const+UFO code(y)=%d]", GET_CODE (y
));
765 fprintf (file
, ",[mem:");
766 output_address (XEXP (x
, 0));
767 fprintf (file
, "] ;P_O_A plus");
770 fprintf (file
, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
771 GET_CODE (x
), GET_CODE (y
));
776 if (INTVAL (addr
) < 0x10000 && INTVAL (addr
) >= -0x10000)
777 fprintf (file
, "%d ; p_o_a const addr?!", INTVAL (addr
));
780 fprintf (file
, "[p_o_a=ILLEGAL_CONST]");
781 output_addr_const (file
, addr
);
786 fprintf (file
, "%s", XSTR (addr
, 0));
788 fprintf (file
, "+%d", addr_inc
);
791 fprintf (file
, "[memUFO:");
792 output_address (XEXP (addr
, 0));
796 output_address (XEXP (addr
, 0));
797 fprintf (file
, " ;P_O_A const");
800 fprintf (file
, "L%d", XINT (addr
, 3));
803 fprintf (file
, " p_o_a UFO, code=%d val=0x%x",
804 (int) GET_CODE (addr
), INTVAL (addr
));
812 * Return non zero if the LS 16 bits of the given value has just one bit set,
813 * otherwise return zero. Note this function may be used to detect one
814 * bit clear by inverting the param.
821 return x
&& (x
& (x
- 1)) == 0;
826 * Return the number of the least significant bit set, using the same
827 * convention for bit numbering as in the MIL-STD-1750 sb instruction.
835 while (b
> 0 && (x
& 1) == 0)