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 bool assemble_integer_1750a PARAMS ((rtx, unsigned int, int));
51 static void output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
52 static void output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
54 /* Initialize the GCC target structure. */
55 #undef TARGET_ASM_BYTE_OP
56 #define TARGET_ASM_BYTE_OP "\tdata\t"
57 #undef TARGET_ASM_ALIGNED_HI_OP
58 #define TARGET_ASM_ALIGNED_HI_OP "\tdatal\t"
59 #undef TARGET_ASM_ALIGNED_SI_OP
60 #define TARGET_ASM_ALIGNED_SI_OP NULL
61 #undef TARGET_ASM_INTEGER
62 #define TARGET_ASM_INTEGER assemble_integer_1750a
64 #undef TARGET_ASM_FUNCTION_PROLOGUE
65 #define TARGET_ASM_FUNCTION_PROLOGUE output_function_prologue
66 #undef TARGET_ASM_FUNCTION_EPILOGUE
67 #define TARGET_ASM_FUNCTION_EPILOGUE output_function_epilogue
69 struct gcc_target targetm = TARGET_INITIALIZER;
71 /* Generate the assembly code for function entry. FILE is a stdio
72 stream to output the code to. SIZE is an int: how many units of
73 temporary storage to allocate.
75 Refer to the array `regs_ever_live' to determine which registers to
76 save; `regs_ever_live[I]' is nonzero if register number I is ever
77 used in the function. This function is responsible for knowing
78 which registers should not be saved even if used. */
81 output_function_prologue (file, size)
87 int regno, regs_used = 0;
89 fprintf (file, "\t; registers used: ");
90 for (regno = 0; regno < 14; regno++)
91 if (regs_ever_live[regno])
93 fprintf (file, " %s", reg_names[regno]);
98 fprintf (file, "(none)");
103 fprintf (file, "\n\t%s\tr15,%d",
104 (size <= 16 ? "sisp" : "sim"), size);
105 if (flag_verbose_asm)
106 fprintf (file, " ; reserve local-variable space");
109 if (frame_pointer_needed)
111 fprintf(file, "\n\tpshm\tr14,r14");
112 if (flag_verbose_asm)
113 fprintf (file, " ; push old frame");
114 fprintf (file, "\n\tlr\tr14,r15");
115 if (flag_verbose_asm)
116 fprintf (file, " ; set new frame");
119 fprintf (file, "\n");
124 /* This function generates the assembly code for function exit.
125 Args are as for output_function_prologue ().
127 The function epilogue should not depend on the current stack
128 pointer! It should use the frame pointer only. This is mandatory
129 because of alloca; we also take advantage of it to omit stack
130 adjustments before returning. */
133 output_function_epilogue (file, size)
137 if (frame_pointer_needed)
139 fprintf (file, "\tlr\tr15,r14");
140 if (flag_verbose_asm)
141 fprintf (file, " ; set stack ptr to frame ptr");
142 fprintf (file, "\n\tpopm\tr14,r14");
143 if (flag_verbose_asm)
144 fprintf (file, " ; restore previous frame ptr");
145 fprintf (file, "\n");
150 fprintf (file, "\t%s\tr15,%d",
151 (size <= 16 ? "aisp" : "aim"), size);
152 if (flag_verbose_asm)
153 fprintf (file, " ; free up local-var space");
154 fprintf (file, "\n");
157 fprintf (file, "\turs\tr15\n\n");
161 notice_update_cc (exp)
164 if (GET_CODE (exp) == SET)
166 enum rtx_code src_code = GET_CODE (SET_SRC (exp));
167 /* Jumps do not alter the cc's. */
168 if (SET_DEST (exp) == pc_rtx)
170 /* Moving a register or constant into memory doesn't alter the cc's. */
171 if (GET_CODE (SET_DEST (exp)) == MEM
172 && (src_code == REG || src_code == CONST_INT))
174 /* Function calls clobber the cc's. */
175 if (src_code == CALL)
180 /* Emulated longword bit-ops leave cc's incorrect */
181 if (GET_MODE (SET_DEST (exp)) == HImode ?
182 src_code == AND || src_code == IOR ||
183 src_code == XOR || src_code == NOT : 0)
188 /* Tests and compares set the cc's in predictable ways. */
189 if (SET_DEST (exp) == cc0_rtx)
192 cc_status.value1 = SET_SRC (exp);
195 /* Anything else will set cc_status. */
196 cc_status.flags = CC_NO_OVERFLOW;
197 cc_status.value1 = SET_SRC (exp);
198 cc_status.value2 = SET_DEST (exp);
201 else if (GET_CODE (exp) == PARALLEL
202 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
204 if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
206 if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
209 cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
222 function_arg (cum, mode, type, named)
224 enum machine_mode mode;
226 int named ATTRIBUTE_UNUSED;
230 if (MUST_PASS_IN_STACK (mode, type))
233 size = int_size_in_bytes (type);
235 size = GET_MODE_SIZE (mode);
237 return gen_rtx_REG (mode, cum);
254 du.i[0] = CONST_DOUBLE_LOW (x);
255 du.i[1] = CONST_DOUBLE_HIGH (x);
260 float_label (code, value)
264 static char label[32];
269 sprintf (p, "%f", value);
272 *p = (*p == '+') ? 'p' :
273 (*p == '-') ? 'm' : *p;
276 return xstrdup (label);
281 movcnt_regno_adjust (op)
284 static char outstr[80];
285 int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
289 #define cntreg_1750 (op0r + 1)
291 if (cntreg == cntreg_1750)
292 sprintf (outstr, "mov r%d,r%d", op0r, op1r);
293 else if (dstreg + 1 == srcreg && cntreg > srcreg)
294 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r);
295 else if (dstreg == cntreg + 1)
296 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r);
297 else if (dstreg == srcreg + 1)
298 sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
299 op0r, op1r, op0r, op2r, op1r, op2r);
300 else if (cntreg + 1 == srcreg)
301 sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
302 op2r, op1r, op0r, op2r, op2r, op0r);
303 else if (cntreg == srcreg + 1)
304 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r);
306 sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
307 op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750);
312 mod_regno_adjust (instr, op)
316 static char outstr[40];
317 const char *const r = (!strncmp (instr, "dvr", 3) ? "r" : "");
318 int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
320 if (modregno_gcc == modregno_1750
321 || (reg_renumber != NULL
322 && reg_renumber[modregno_gcc] >= 0
323 && reg_renumber[modregno_gcc] == reg_renumber[modregno_1750]))
324 sprintf (outstr, "%s r%%0,%s%%2", instr, r);
326 sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
327 modregno_gcc, modregno_1750, instr, r, modregno_1750,
333 /* Check if op is a valid memory operand for 1750A Load/Store instructions
334 (memory indirection permitted.) */
340 static int recurred = 0;
343 if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
344 && GET_MODE (op) != QImode)
346 switch (GET_CODE (op))
349 if (!recurred && GET_CODE (XEXP (op, 0)) == REG)
357 valid_operand = memop_valid (XEXP (op, 0));
359 valid_operand = memop_valid (XEXP (op, 1));
361 return valid_operand;
372 printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
378 /* predicate for the MOV instruction: */
380 mov_memory_operand (op, mode)
382 enum machine_mode mode ATTRIBUTE_UNUSED;
384 return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
387 /* predicate for the STC instruction: */
389 small_nonneg_const (op, mode)
391 enum machine_mode mode ATTRIBUTE_UNUSED;
393 if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
398 /* predicate for constant zero: */
400 zero_operand (op, mode)
402 enum machine_mode mode;
404 return op == CONST0_RTX (mode);
408 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
414 if (GET_CODE (op) == MEM)
416 rtx inner = XEXP (op, 0);
417 if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
419 if (GET_CODE (inner) == PLUS)
421 rtx plus_op0 = XEXP (inner, 0);
422 if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
424 rtx plus_op1 = XEXP (inner, 1);
425 if (GET_CODE (plus_op1) == CONST_INT
426 && INTVAL (plus_op1) >= 0
427 && INTVAL (plus_op1) <= 255)
436 /* Decide whether to output a conditional jump as a "Jump Conditional"
437 or as a "Branch Conditional": */
440 find_jmplbl (labelnum)
445 for (i = 0; i <= jmplbl_ndx; i++)
446 if (labelnum == jmplbl[i].num)
457 branch_or_jump (condition, targetlabel_number)
458 const char *condition;
459 int targetlabel_number;
464 if ((index = find_jmplbl (targetlabel_number)) >= 0)
465 if (program_counter - jmplbl[index].pc < 128)
467 sprintf (buf, "b%s %%l0", condition);
470 sprintf (buf, "jc %s,%%l0", condition);
476 unsigned_comparison_operator (insn)
479 switch (GET_CODE (insn))
492 next_cc_user_is_unsigned (insn)
495 if ( !(insn = next_cc0_user (insn)))
497 else if (GET_CODE (insn) == JUMP_INSN
498 && GET_CODE (PATTERN (insn)) == SET
499 && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
500 return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0));
501 else if (GET_CODE (insn) == INSN
502 && GET_CODE (PATTERN (insn)) == SET)
503 return unsigned_comparison_operator (SET_SRC (PATTERN (insn)));
511 /* A C compound statement to output to stdio stream STREAM the
512 assembler syntax for an instruction operand X. X is an RTL
515 CODE is a value that can be used to specify one of several ways
516 of printing the operand. It is used when identical operands
517 must be printed differently depending on the context. CODE
518 comes from the `%' specification that was used to request
519 printing of the operand. If the specification was just `%DIGIT'
520 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
521 is the ASCII code for LTR.
523 If X is a register, this macro should print the register's name.
524 The names can be found in an array `reg_names' whose type is
525 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
527 When the machine description has a specification `%PUNCT' (a `%'
528 followed by a punctuation character), this macro is called with
529 a null pointer for X and the punctuation character for CODE.
531 The 1750 specific codes are:
532 'J' for the negative of a constant
533 'Q' for printing addresses in B mode syntax
534 'd' for the second register in a pair
535 't' for the third register in a triple
536 'b' for the bit number (using 1750 test bit convention)
537 'B' for the bit number of the 1's complement (for bit clear)
542 print_operand (file, x, letter)
547 switch (GET_CODE (x))
551 fprintf (file, "%d", REGNO (x) + 1);
552 else if (letter == 't')
553 fprintf (file, "%d", REGNO (x) + 2);
555 fprintf (file, "%d", REGNO (x));
559 fprintf (file, "%s", XSTR (x, 0));
561 fprintf (file, "+1");
569 rtx inner = XEXP (x, 0);
570 switch (GET_CODE (inner))
573 fprintf (file, "r%d,0", REGNO (inner));
576 fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
577 INTVAL (XEXP (inner, 1)));
580 fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
585 addr_inc = (letter == 'A' ? 1 : 0);
586 output_address (XEXP (x, 0));
592 double value = get_double (x);
594 sprintf (fltstr, "%f", value);
596 if (letter == 'D' || letter == 'E')
599 for (i = 0; i <= datalbl_ndx; i++)
600 if (strcmp (fltstr, datalbl[i].value) == 0)
607 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
608 datalbl[i].name = float_label (letter, value);
609 datalbl[i].size = (letter == 'E') ? 3 : 2;
610 check_section (Konst);
611 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
612 (letter == 'E' ? "ef" : "f"), fltstr);
613 check_section (Normal);
616 else if (letter == 'F' || letter == 'G')
619 for (i = 0; i <= datalbl_ndx; i++)
620 if (strcmp (fltstr, datalbl[i].value) == 0)
628 "float value %f not found upon label reference\n", value);
629 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
630 datalbl[i].name = float_label (letter, value);
631 datalbl[i].size = (letter == 'G') ? 3 : 2;
632 check_section (Konst);
633 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
634 (letter == 'G' ? "ef" : "f"), fltstr);
635 check_section (Normal);
637 fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
640 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
643 fprintf (file, "%f", get_double (x));
648 fprintf (file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (x));
649 else if (letter == 'b')
650 fprintf (file, "%d", which_bit (INTVAL (x)));
651 else if (letter == 'B')
652 fprintf (file, "%d", which_bit (~INTVAL (x)));
653 else if (letter == 'w')
654 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);
656 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
660 fprintf (file, "L%d", XINT (x, 3));
664 fprintf (file, "CALL nargs=");
665 fprintf (file, HOST_PTR_PRINTF, (PTR) XEXP (x, 1));
666 fprintf (file, ", func is either '%s' or '%s'",
667 XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
672 rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
673 int op0code = GET_CODE (op0), op1code = GET_CODE (op1);
674 if (op1code == CONST_INT)
678 fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
679 INTVAL (op1), REGNO (op0));
682 fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
685 fprintf (file, "%d,[mem:", INTVAL (op1));
686 output_address (XEXP (op0, 0));
687 fprintf (file, "] ;P_O plus");
690 fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
691 (int) op0code, INTVAL (op1));
693 else if (op1code == SYMBOL_REF && op0code == REG)
694 fprintf (file, "%s,r%d ; P_O: (plus reg sym)",
695 XSTR (op1, 0), REGNO (op0));
697 fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
702 fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
709 print_operand_address (file, addr)
713 switch (GET_CODE (addr))
716 fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
720 register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
721 switch (GET_CODE (x))
724 switch (GET_CODE (y))
727 output_address (XEXP (y, 0));
728 fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
731 fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
734 fprintf (file, "%s", XSTR (y, 0));
736 fprintf (file, "+%d", addr_inc);
737 fprintf (file, ",r%d ; P_O_A reg + sym", REGNO (x));
740 output_address (XEXP (y, 0));
741 fprintf (file, ",r%d ; P_O_A reg + label", REGNO (x));
744 fprintf (file, "[P_O_A reg%d+UFO code=%d]",
745 REGNO (x), GET_CODE (y));
749 output_address (XEXP (x, 0));
752 switch (GET_CODE (y))
755 fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
758 fprintf (file, "%s,r%d ;P_O_A sym + reg",
759 XSTR (x, 0), REGNO (y));
762 fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
763 XSTR (x, 0), GET_CODE (y));
767 output_address (XEXP (x, 0));
768 if (GET_CODE (y) == REG)
769 fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
771 fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
775 fprintf (file, ",[mem:");
776 output_address (XEXP (x, 0));
777 fprintf (file, "] ;P_O_A plus");
780 fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
781 GET_CODE (x), GET_CODE (y));
786 if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
787 fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
790 fprintf (file, "[p_o_a=ILLEGAL_CONST]");
791 output_addr_const (file, addr);
796 fprintf (file, "%s", XSTR (addr, 0));
798 fprintf (file, "+%d", addr_inc);
801 fprintf (file, "[memUFO:");
802 output_address (XEXP (addr, 0));
806 output_address (XEXP (addr, 0));
807 fprintf (file, " ;P_O_A const");
810 fprintf (file, "L%d", XINT (addr, 3));
813 fprintf (file, " p_o_a UFO, code=%d val=0x%x",
814 (int) GET_CODE (addr), INTVAL (addr));
820 /* Target hook for assembling integer objects. The 1750a version needs to
821 keep track of how many bytes have been written. */
824 assemble_integer_1750a (x, size, aligned_p)
829 if (default_assemble_integer (x, size, aligned_p))
833 datalbl[datalbl_ndx].size += size;
841 * Return non zero if the LS 16 bits of the given value has just one bit set,
842 * otherwise return zero. Note this function may be used to detect one
843 * bit clear by inverting the param.
850 return x && (x & (x - 1)) == 0;
855 * Return the number of the least significant bit set, using the same
856 * convention for bit numbering as in the MIL-STD-1750 sb instruction.
864 while (b > 0 && (x & 1) == 0)
874 /* Convert a REAL_VALUE_TYPE to the target float format:
877 ------------------------------------------------------
878 |S| Mantissa | Exponent |
879 ------------------------------------------------------
885 real_value_to_target_single(in)
891 #if HOST_WORDS_BIG_ENDIAN
892 unsigned int negative:1;
893 unsigned int exponent:11;
894 unsigned int mantissa0:20;
895 unsigned int mantissa1:32;
897 unsigned int mantissa1:32;
898 unsigned int mantissa0:20;
899 unsigned int exponent:11;
900 unsigned int negative:1;
908 if (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
913 /* Don't bother with NaN, Inf, 0 special cases, since they'll be handled
914 by the over/underflow code below. */
915 exp = ieee.s.exponent - 0x3ff;
916 mant = 1 << 23 | ieee.s.mantissa0 << 3 | ieee.s.mantissa1 >> 29;
918 /* The sign is actually part of the mantessa. Since we're comming from
919 IEEE we know that either bit 23 is set or we have a zero. */
920 if (! ieee.s.negative)
926 /* Check for overflow. Crop to FLT_MAX. */
930 mant = (ieee.s.negative ? 0xffffff : 0x7fffff);
932 /* Underflow to zero. */
939 return mant << 8 | (exp & 0xff);
942 /* Convert a REAL_VALUE_TYPE to the target 1750a extended float format:
944 ----------------------------------------------------
945 | | Mantissa | | Mantissa |
946 |S| MS |Exponent| LS |
947 ----------------------------------------------------
953 real_value_to_target_double(in, out)
960 #if HOST_WORDS_BIG_ENDIAN
961 unsigned int negative:1;
962 unsigned int exponent:11;
963 unsigned int mantissa0:20;
964 unsigned int mantissa1:32;
966 unsigned int mantissa1:32;
967 unsigned int mantissa0:20;
968 unsigned int exponent:11;
969 unsigned int negative:1;
974 unsigned int mant_h24, mant_l16;
977 if (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
982 /* Don't bother with NaN, Inf, 0 special cases, since they'll be handled
983 by the over/underflow code below. */
984 exp = ieee.s.exponent - 0x3ff;
985 mant_h24 = 1 << 23 | ieee.s.mantissa0 << 3 | ieee.s.mantissa1 >> 29;
986 mant_l16 = (ieee.s.mantissa1 >> 13) & 0xffff;
988 /* The sign is actually part of the mantessa. Since we're comming from
989 IEEE we know that either bit 23 is set or we have a zero. */
990 if (! ieee.s.negative)
992 mant_l16 = mant_l16 >> 1 | (mant_h24 & 1) << 15;
997 /* Check for overflow. Crop to DBL_MAX. */
1001 mant_h24 = (ieee.s.negative ? 0xffffff : 0x7fffff);
1004 /* Underflow to zero. */
1005 else if (exp < -128)
1012 out[0] = mant_h24 << 8 | (exp & 0xff);