]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/1750a/1750a.c
789eedb6c589cca3f5b87217927f1d8a5c3af6cb
1 /* Subroutines for insn-output.c for MIL-STD-1750.
2 Copyright (C) 1994, 1995, 1996, 1997, 1998 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. */
31 #include "conditions.h"
35 struct datalabel_array datalbl
[DATALBL_ARRSIZ
];
37 struct jumplabel_array jmplbl
[JMPLBL_ARRSIZ
];
39 int label_pending
= 0, program_counter
= 0;
40 enum section current_section
= Normal
;
42 {"Init", "Normal", "Konst", "Static"};
45 notice_update_cc (exp
)
48 if (GET_CODE (exp
) == SET
)
50 enum rtx_code src_code
= GET_CODE (SET_SRC (exp
));
51 /* Jumps do not alter the cc's. */
52 if (SET_DEST (exp
) == pc_rtx
)
54 /* Moving a register or constant into memory doesn't alter the cc's. */
55 if (GET_CODE (SET_DEST (exp
)) == MEM
56 && (src_code
== REG
|| src_code
== CONST_INT
))
58 /* Function calls clobber the cc's. */
64 /* Emulated longword bit-ops leave cc's incorrect */
65 if (GET_MODE (SET_DEST (exp
)) == HImode
?
66 src_code
== AND
|| src_code
== IOR
||
67 src_code
== XOR
|| src_code
== NOT
: 0)
72 /* Tests and compares set the cc's in predictable ways. */
73 if (SET_DEST (exp
) == cc0_rtx
)
76 cc_status
.value1
= SET_SRC (exp
);
79 /* Anything else will set cc_status. */
80 cc_status
.flags
= CC_NO_OVERFLOW
;
81 cc_status
.value1
= SET_SRC (exp
);
82 cc_status
.value2
= SET_DEST (exp
);
85 else if (GET_CODE (exp
) == PARALLEL
86 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
88 if (SET_DEST (XVECEXP (exp
, 0, 0)) == pc_rtx
)
90 if (SET_DEST (XVECEXP (exp
, 0, 0)) == cc0_rtx
)
93 cc_status
.value1
= SET_SRC (XVECEXP (exp
, 0, 0));
106 function_arg (cum
, mode
, type
, named
)
108 enum machine_mode mode
;
114 if (MUST_PASS_IN_STACK (mode
, type
))
117 size
= int_size_in_bytes (type
);
119 size
= GET_MODE_SIZE (mode
);
121 return gen_rtx (REG
, mode
, cum
);
138 du
.i
[0] = CONST_DOUBLE_LOW (x
);
139 du
.i
[1] = CONST_DOUBLE_HIGH (x
);
144 float_label (code
, value
)
149 static char label
[32];
154 sprintf (p
, "%lf", value
);
157 *p
= (*p
== '+') ? 'p' :
158 (*p
== '-') ? 'm' : *p
;
161 return xstrdup (label
);
166 movcnt_regno_adjust (op
)
169 static char outstr
[80];
170 int op0r
= REGNO (op
[0]), op1r
= REGNO (op
[1]), op2r
= REGNO (op
[2]);
174 #define cntreg_1750 (op0r + 1)
176 if (cntreg
== cntreg_1750
)
177 sprintf (outstr
, "mov r%d,r%d", op0r
, op1r
);
178 else if (dstreg
+ 1 == srcreg
&& cntreg
> srcreg
)
179 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d", op2r
, op1r
, op0r
, op2r
);
180 else if (dstreg
== cntreg
+ 1)
181 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d", op0r
, op2r
, op2r
, op1r
);
182 else if (dstreg
== srcreg
+ 1)
183 sprintf (outstr
, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
184 op0r
, op1r
, op0r
, op2r
, op1r
, op2r
);
185 else if (cntreg
+ 1 == srcreg
)
186 sprintf (outstr
, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
187 op2r
, op1r
, op0r
, op2r
, op2r
, op0r
);
188 else if (cntreg
== srcreg
+ 1)
189 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d", op0r
, op1r
, op1r
, op0r
);
191 sprintf (outstr
, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
192 op2r
, cntreg_1750
, op0r
, op1r
, op2r
, cntreg_1750
);
197 mod_regno_adjust (instr
, op
)
201 static char outstr
[40];
202 char *r
= (!strncmp (instr
, "dvr", 3) ? "r" : "");
203 int modregno_gcc
= REGNO (op
[3]), modregno_1750
= REGNO (op
[0]) + 1;
205 if (modregno_gcc
== modregno_1750
206 || (reg_renumber
!= NULL
207 && reg_renumber
[modregno_gcc
] >= 0
208 && reg_renumber
[modregno_gcc
] == reg_renumber
[modregno_1750
]))
209 sprintf (outstr
, "%s r%%0,%s%%2", instr
, r
);
211 sprintf (outstr
, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
212 modregno_gcc
, modregno_1750
, instr
, r
, modregno_1750
,
218 /* Check if op is a valid memory operand for 1750A Load/Store instructions
219 (memory indirection permitted.) */
225 static int recurred
= 0;
228 if (GET_MODE (op
) != Pmode
&& GET_MODE (op
) != VOIDmode
229 && GET_MODE (op
) != QImode
)
231 switch (GET_CODE (op
))
234 if (!recurred
&& GET_CODE (XEXP (op
, 0)) == REG
)
242 valid_operand
= memop_valid (XEXP (op
, 0));
244 valid_operand
= memop_valid (XEXP (op
, 1));
246 return valid_operand
;
257 printf ("memop_valid: code=%d\n", (int) GET_CODE (op
));
263 /* predicate for the MOV instruction: */
265 mov_memory_operand (op
, mode
)
267 enum machine_mode mode
;
269 return (GET_CODE (op
) == MEM
&& GET_CODE (XEXP (op
, 0)) == REG
);
272 /* predicate for the STC instruction: */
274 small_nonneg_const (op
, mode
)
276 enum machine_mode mode
;
278 if (GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0 && INTVAL (op
) <= 15)
283 /* predicate for constant zero: */
285 zero_operand (op
, mode
)
287 enum machine_mode mode
;
289 return op
== CONST0_RTX (mode
);
293 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
299 if (GET_CODE (op
) == MEM
)
301 rtx inner
= XEXP (op
, 0);
302 if (GET_CODE (inner
) == REG
&& REG_OK_FOR_INDEX_P (inner
))
304 if (GET_CODE (inner
) == PLUS
)
306 rtx plus_op0
= XEXP (inner
, 0);
307 if (GET_CODE (plus_op0
) == REG
&& REG_OK_FOR_INDEX_P (plus_op0
))
309 rtx plus_op1
= XEXP (inner
, 1);
310 if (GET_CODE (plus_op1
) == CONST_INT
311 && INTVAL (plus_op1
) >= 0
312 && INTVAL (plus_op1
) <= 255)
321 /* Decide whether to output a conditional jump as a "Jump Conditional"
322 or as a "Branch Conditional": */
325 find_jmplbl (labelnum
)
330 for (i
= 0; i
<= jmplbl_ndx
; i
++)
331 if (labelnum
== jmplbl
[i
].num
)
342 branch_or_jump (condition
, targetlabel_number
)
344 int targetlabel_number
;
349 if ((index
= find_jmplbl (targetlabel_number
)) >= 0)
350 if (program_counter
- jmplbl
[index
].pc
< 128)
352 sprintf (buf
, "b%s %%l0", condition
);
355 sprintf (buf
, "jc %s,%%l0", condition
);
361 unsigned_comparison_operator (insn
)
364 switch (GET_CODE (insn
))
377 next_cc_user_is_unsigned (insn
)
380 if ( !(insn
= next_cc0_user (insn
)))
382 else if (GET_CODE (insn
) == JUMP_INSN
383 && GET_CODE (PATTERN (insn
)) == SET
384 && GET_CODE (SET_SRC (PATTERN (insn
))) == IF_THEN_ELSE
)
385 return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn
)), 0));
386 else if (GET_CODE (insn
) == INSN
387 && GET_CODE (PATTERN (insn
)) == SET
)
388 return unsigned_comparison_operator (SET_SRC (PATTERN (insn
)));
396 /* A C compound statement to output to stdio stream STREAM the
397 assembler syntax for an instruction operand X. X is an RTL
400 CODE is a value that can be used to specify one of several ways
401 of printing the operand. It is used when identical operands
402 must be printed differently depending on the context. CODE
403 comes from the `%' specification that was used to request
404 printing of the operand. If the specification was just `%DIGIT'
405 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
406 is the ASCII code for LTR.
408 If X is a register, this macro should print the register's name.
409 The names can be found in an array `reg_names' whose type is
410 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
412 When the machine description has a specification `%PUNCT' (a `%'
413 followed by a punctuation character), this macro is called with
414 a null pointer for X and the punctuation character for CODE.
416 The 1750 specific codes are:
417 'J' for the negative of a constant
418 'Q' for printing addresses in B mode syntax
419 'd' for the second register in a pair
420 't' for the third register in a triple
421 'b' for the bit number (using 1750 test bit convention)
422 'B' for the bit number of the 1's complement (for bit clear)
426 print_operand (file
, x
, letter
)
431 switch (GET_CODE (x
))
435 fprintf (file
, "%d", REGNO (x
) + 1);
436 else if (letter
== 't')
437 fprintf (file
, "%d", REGNO (x
) + 2);
439 fprintf (file
, "%d", REGNO (x
));
443 fprintf (file
, "%s", XSTR (x
, 0));
445 fprintf (file
, "+1");
453 rtx inner
= XEXP (x
, 0);
454 switch (GET_CODE (inner
))
457 fprintf (file
, "r%d,0", REGNO (inner
));
460 fprintf (file
, "r%d,%d", REGNO (XEXP (inner
, 0)),
461 INTVAL (XEXP (inner
, 1)));
464 fprintf (file
, "[ill Q code=%d]", GET_CODE (inner
));
469 addr_inc
= (letter
== 'A' ? 1 : 0);
470 output_address (XEXP (x
, 0));
476 double value = get_double (x);
478 sprintf (fltstr, "%lf", value);
480 if (letter == 'D' || letter == 'E')
483 for (i = 0; i <= datalbl_ndx; i++)
484 if (strcmp (fltstr, datalbl[i].value) == 0)
491 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
492 datalbl[i].name = float_label (letter, value);
493 datalbl[i].size = (letter == 'E') ? 3 : 2;
494 check_section (Konst);
495 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
496 (letter == 'E' ? "ef" : "f"), fltstr);
497 check_section (Normal);
500 else if (letter == 'F' || letter == 'G')
503 for (i = 0; i <= datalbl_ndx; i++)
504 if (strcmp (fltstr, datalbl[i].value) == 0)
512 "float value %lfnot found upon label reference\n", value);
513 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
514 datalbl[i].name = float_label (letter, value);
515 datalbl[i].size = (letter == 'G') ? 3 : 2;
516 check_section (Konst);
517 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
518 (letter == 'G' ? "ef" : "f"), fltstr);
519 check_section (Normal);
521 fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
524 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
527 fprintf (file
, "%lf", get_double (x
));
532 fprintf (file
, "%d", -INTVAL (x
));
533 else if (letter
== 'b')
534 fprintf (file
, "%d", which_bit (INTVAL (x
)));
535 else if (letter
== 'B')
536 fprintf (file
, "%d", which_bit (~INTVAL (x
)));
537 else if (letter
== 'w')
538 fprintf (file
, "%d", INTVAL (x
) - 16);
540 fprintf (file
, "%d", INTVAL (x
));
544 fprintf (file
, "L%d", XINT (x
, 3));
548 fprintf (file
, "CALL nargs=%d, func is either '%s' or '%s'",
549 XEXP (x
, 1), XSTR (XEXP (XEXP (x
, 0), 1), 0), XSTR (XEXP (x
, 0), 1));
554 rtx op0
= XEXP (x
, 0), op1
= XEXP (x
, 1);
555 int op0code
= GET_CODE (op0
), op1code
= GET_CODE (op1
);
556 if (op1code
== CONST_INT
)
560 fprintf (file
, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
561 INTVAL (op1
), REGNO (op0
));
564 fprintf (file
, "%d+%s", INTVAL (op1
), XSTR (op0
, 0));
567 fprintf (file
, "%d,[mem:", INTVAL (op1
));
568 output_address (XEXP (op0
, 0));
569 fprintf (file
, "] ;P_O plus");
572 fprintf (file
, "p_o_PLUS UFO, code=%d, with CONST=%d",
573 (int) op0code
, INTVAL (op1
));
575 else if (op1code
== SYMBOL_REF
&& op0code
== REG
)
576 fprintf (file
, "%s,r%d ; P_O: (plus reg sym)",
577 XSTR (op1
, 0), REGNO (op0
));
579 fprintf (file
, "p_o_+: op0code=%d, op1code=%d", op0code
, op1code
);
584 fprintf (file
, "p_o_UFO code=%d", GET_CODE (x
));
590 print_operand_address (file
, addr
)
594 switch (GET_CODE (addr
))
597 fprintf (file
, "%d,r%d ; P_O_A", addr_inc
, REGNO (addr
));
601 register rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
602 switch (GET_CODE (x
))
605 switch (GET_CODE (y
))
608 output_address (XEXP (y
, 0));
609 fprintf (file
, ",r%d ;P_O_A reg + const expr", REGNO (x
));
612 fprintf (file
, "%d,r%d", INTVAL (y
) + addr_inc
, REGNO (x
));
615 fprintf (file
, "%s", XSTR (y
, 0));
617 fprintf (file
, "+%d", addr_inc
);
618 fprintf (file
, ",r%d ; P_O_A reg + sym", REGNO (x
));
621 output_address (XEXP (y
, 0));
622 fprintf (file
, ",r%d ; P_O_A reg + label", REGNO (x
));
625 fprintf (file
, "[P_O_A reg%d+UFO code=%d]",
626 REGNO (x
), GET_CODE (y
));
630 output_address (XEXP (x
, 0));
633 switch (GET_CODE (y
))
636 fprintf (file
, "%d+%s", INTVAL (y
) + addr_inc
, XSTR (x
, 0));
639 fprintf (file
, "%s,r%d ;P_O_A sym + reg",
640 XSTR (x
, 0), REGNO (y
));
643 fprintf (file
, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
644 XSTR (x
, 0), GET_CODE (y
));
648 output_address (XEXP (x
, 0));
649 if (GET_CODE (y
) == REG
)
650 fprintf (file
, ",r%d ;P_O_A const + reg", REGNO (x
));
652 fprintf (file
, "P_O_A const+UFO code(y)=%d]", GET_CODE (y
));
656 fprintf (file
, ",[mem:");
657 output_address (XEXP (x
, 0));
658 fprintf (file
, "] ;P_O_A plus");
661 fprintf (file
, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
662 GET_CODE (x
), GET_CODE (y
));
667 if (INTVAL (addr
) < 0x10000 && INTVAL (addr
) >= -0x10000)
668 fprintf (file
, "%d ; p_o_a const addr?!", INTVAL (addr
));
671 fprintf (file
, "[p_o_a=ILLEGAL_CONST]");
672 output_addr_const (file
, addr
);
677 fprintf (file
, "%s", XSTR (addr
, 0));
679 fprintf (file
, "+%d", addr_inc
);
682 fprintf (file
, "[memUFO:");
683 output_address (XEXP (addr
, 0));
687 output_address (XEXP (addr
, 0));
688 fprintf (file
, " ;P_O_A const");
691 fprintf (file
, "L%d", XINT (addr
, 3));
694 fprintf (file
, " p_o_a UFO, code=%d val=0x%x",
695 (int) GET_CODE (addr
), INTVAL (addr
));
703 * Return non zero if the LS 16 bits of the given value has just one bit set,
704 * otherwise return zero. Note this function may be used to detect one
705 * bit clear by inverting the param.
712 return x
&& (x
& (x
- 1)) == 0;
717 * Return the number of the least significant bit set, using the same
718 * convention for bit numbering as in the MIL-STD-1750 sb instruction.
726 while (b
> 0 && (x
& 1) == 0)