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)
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"
37 struct datalabel_array datalbl
[DATALBL_ARRSIZ
];
39 struct jumplabel_array jmplbl
[JMPLBL_ARRSIZ
];
41 int label_pending
= 0, program_counter
= 0;
42 enum section current_section
= Normal
;
44 {"Init", "Normal", "Konst", "Static"};
47 notice_update_cc (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
)
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
))
60 /* Function calls clobber the cc's. */
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)
74 /* Tests and compares set the cc's in predictable ways. */
75 if (SET_DEST (exp
) == cc0_rtx
)
78 cc_status
.value1
= SET_SRC (exp
);
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
);
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
)
92 if (SET_DEST (XVECEXP (exp
, 0, 0)) == cc0_rtx
)
95 cc_status
.value1
= SET_SRC (XVECEXP (exp
, 0, 0));
108 function_arg (cum
, mode
, type
, named
)
110 enum machine_mode mode
;
116 if (MUST_PASS_IN_STACK (mode
, type
))
119 size
= int_size_in_bytes (type
);
121 size
= GET_MODE_SIZE (mode
);
123 return gen_rtx (REG
, mode
, cum
);
140 du
.i
[0] = CONST_DOUBLE_LOW (x
);
141 du
.i
[1] = CONST_DOUBLE_HIGH (x
);
146 float_label (code
, value
)
151 static char label
[32];
156 sprintf (p
, "%lf", value
);
159 *p
= (*p
== '+') ? 'p' :
160 (*p
== '-') ? 'm' : *p
;
163 return xstrdup (label
);
168 movcnt_regno_adjust (op
)
171 static char outstr
[80];
172 int op0r
= REGNO (op
[0]), op1r
= REGNO (op
[1]), op2r
= REGNO (op
[2]);
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
);
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
);
199 mod_regno_adjust (instr
, 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
);
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
,
220 /* Check if op is a valid memory operand for 1750A Load/Store instructions
221 (memory indirection permitted.) */
227 static int recurred
= 0;
230 if (GET_MODE (op
) != Pmode
&& GET_MODE (op
) != VOIDmode
231 && GET_MODE (op
) != QImode
)
233 switch (GET_CODE (op
))
236 if (!recurred
&& GET_CODE (XEXP (op
, 0)) == REG
)
244 valid
= memop_valid (XEXP (op
, 0));
246 valid
= memop_valid (XEXP (op
, 1));
259 printf ("memop_valid: code=%d\n", (int) GET_CODE (op
));
265 /* predicate for the MOV instruction: */
267 mov_memory_operand (op
, mode
)
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
)
278 enum machine_mode mode
;
280 if (GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0 && INTVAL (op
) <= 15)
285 /* predicate for constant zero: */
287 zero_operand (op
, mode
)
289 enum machine_mode mode
;
291 return op
== CONST0_RTX (mode
);
295 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
301 if (GET_CODE (op
) == MEM
)
303 rtx inner
= XEXP (op
, 0);
304 if (GET_CODE (inner
) == REG
&& REG_OK_FOR_INDEX_P (inner
))
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)
323 /* Decide whether to output a conditional jump as a "Jump Conditional"
324 or as a "Branch Conditional": */
327 find_jmplbl (labelnum
)
332 for (i
= 0; i
<= jmplbl_ndx
; i
++)
333 if (labelnum
== jmplbl
[i
].num
)
344 branch_or_jump (condition
, targetlabel_number
)
346 int targetlabel_number
;
351 if ((index
= find_jmplbl (targetlabel_number
)) >= 0)
352 if (program_counter
- jmplbl
[index
].pc
< 128)
354 sprintf (buf
, "b%s %%l0", condition
);
357 sprintf (buf
, "jc %s,%%l0", condition
);
363 unsigned_comparison_operator (insn
)
366 switch (GET_CODE (insn
))
379 next_cc_user_is_unsigned (insn
)
382 if ( !(insn
= next_cc0_user (insn
)))
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
)));
398 /* A C compound statement to output to stdio stream STREAM the
399 assembler syntax for an instruction operand X. X is an RTL
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)
428 print_operand (file
, x
, letter
)
433 switch (GET_CODE (x
))
437 fprintf (file
, "%d", REGNO (x
) + 1);
438 else if (letter
== 't')
439 fprintf (file
, "%d", REGNO (x
) + 2);
441 fprintf (file
, "%d", REGNO (x
));
445 fprintf (file
, "%s", XSTR (x
, 0));
447 fprintf (file
, "+1");
455 rtx inner
= XEXP (x
, 0);
456 switch (GET_CODE (inner
))
459 fprintf (file
, "r%d,0", REGNO (inner
));
462 fprintf (file
, "r%d,%d", REGNO (XEXP (inner
, 0)),
463 INTVAL (XEXP (inner
, 1)));
466 fprintf (file
, "[ill Q code=%d]", GET_CODE (inner
));
471 addr_inc
= (letter
== 'A' ? 1 : 0);
472 output_address (XEXP (x
, 0));
478 double value = get_double (x);
480 sprintf (fltstr, "%lf", value);
482 if (letter == 'D' || letter == 'E')
485 for (i = 0; i <= datalbl_ndx; i++)
486 if (strcmp (fltstr, datalbl[i].value) == 0)
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')
505 for (i = 0; i <= datalbl_ndx; i++)
506 if (strcmp (fltstr, datalbl[i].value) == 0)
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);
526 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
529 fprintf (file
, "%lf", get_double (x
));
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);
542 fprintf (file
, "%d", INTVAL (x
));
546 fprintf (file
, "L%d", XINT (x
, 3));
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));
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
)
562 fprintf (file
, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
563 INTVAL (op1
), REGNO (op0
));
566 fprintf (file
, "%d+%s", INTVAL (op1
), XSTR (op0
, 0));
569 fprintf (file
, "%d,[mem:", INTVAL (op1
));
570 output_address (XEXP (op0
, 0));
571 fprintf (file
, "] ;P_O plus");
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
));
581 fprintf (file
, "p_o_+: op0code=%d, op1code=%d", op0code
, op1code
);
586 fprintf (file
, "p_o_UFO code=%d", GET_CODE (x
));
592 print_operand_address (file
, addr
)
596 switch (GET_CODE (addr
))
599 fprintf (file
, "%d,r%d ; P_O_A", addr_inc
, REGNO (addr
));
603 register rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
604 switch (GET_CODE (x
))
607 switch (GET_CODE (y
))
610 output_address (XEXP (y
, 0));
611 fprintf (file
, ",r%d ;P_O_A reg + const expr", REGNO (x
));
614 fprintf (file
, "%d,r%d", INTVAL (y
) + addr_inc
, REGNO (x
));
617 fprintf (file
, "%s", XSTR (y
, 0));
619 fprintf (file
, "+%d", addr_inc
);
620 fprintf (file
, ",r%d ; P_O_A reg + sym", REGNO (x
));
623 output_address (XEXP (y
, 0));
624 fprintf (file
, ",r%d ; P_O_A reg + label", REGNO (x
));
627 fprintf (file
, "[P_O_A reg%d+UFO code=%d]",
628 REGNO (x
), GET_CODE (y
));
632 output_address (XEXP (x
, 0));
635 switch (GET_CODE (y
))
638 fprintf (file
, "%d+%s", INTVAL (y
) + addr_inc
, XSTR (x
, 0));
641 fprintf (file
, "%s,r%d ;P_O_A sym + reg",
642 XSTR (x
, 0), REGNO (y
));
645 fprintf (file
, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
646 XSTR (x
, 0), GET_CODE (y
));
650 output_address (XEXP (x
, 0));
651 if (GET_CODE (y
) == REG
)
652 fprintf (file
, ",r%d ;P_O_A const + reg", REGNO (x
));
654 fprintf (file
, "P_O_A const+UFO code(y)=%d]", GET_CODE (y
));
658 fprintf (file
, ",[mem:");
659 output_address (XEXP (x
, 0));
660 fprintf (file
, "] ;P_O_A plus");
663 fprintf (file
, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
664 GET_CODE (x
), GET_CODE (y
));
669 if (INTVAL (addr
) < 0x10000 && INTVAL (addr
) >= -0x10000)
670 fprintf (file
, "%d ; p_o_a const addr?!", INTVAL (addr
));
673 fprintf (file
, "[p_o_a=ILLEGAL_CONST]");
674 output_addr_const (file
, addr
);
679 fprintf (file
, "%s", XSTR (addr
, 0));
681 fprintf (file
, "+%d", addr_inc
);
684 fprintf (file
, "[memUFO:");
685 output_address (XEXP (addr
, 0));
689 output_address (XEXP (addr
, 0));
690 fprintf (file
, " ;P_O_A const");
693 fprintf (file
, "L%d", XINT (addr
, 3));
696 fprintf (file
, " p_o_a UFO, code=%d val=0x%x",
697 (int) GET_CODE (addr
), INTVAL (addr
));
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.
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.
728 while (b
> 0 && (x
& 1) == 0)