* Makefile.in (final.o): Depend on target.h.
[official-gcc.git] / gcc / config / 1750a / 1750a.c
blob39a0ebb0ba796a242f7e7140c2df6070591869d7
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)
11 any later version.
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. */
23 #define __datalbl
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "function.h"
29 #include "expr.h"
30 #define HAVE_cc0
31 #include "conditions.h"
32 #include "real.h"
33 #include "regs.h"
34 #include "output.h"
35 #include "flags.h"
36 #include "tm_p.h"
37 #include "target.h"
38 #include "target-def.h"
40 struct datalabel_array datalbl[DATALBL_ARRSIZ];
41 int datalbl_ndx = -1;
42 struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
43 int jmplbl_ndx = -1;
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. */
70 static void
71 output_function_prologue (file, size)
72 FILE *file;
73 HOST_WIDE_INT size;
75 if (flag_verbose_asm)
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]);
84 regs_used++;
87 if (regs_used == 0)
88 fprintf (file, "(none)");
91 if (size > 0)
93 fprintf (file, "\n\t%s\tr15,%d",
94 (size <= 16 ? "sisp" : "sim"), size);
95 if (flag_verbose_asm)
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");
110 program_counter = 0;
111 jmplbl_ndx = -1;
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. */
122 static void
123 output_function_epilogue (file, size)
124 FILE *file;
125 HOST_WIDE_INT 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");
138 if (size > 0)
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");
150 void
151 notice_update_cc (exp)
152 rtx 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)
159 return;
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))
163 return;
164 /* Function calls clobber the cc's. */
165 if (src_code == CALL)
167 CC_STATUS_INIT;
168 return;
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)
175 CC_STATUS_INIT;
176 return;
178 /* Tests and compares set the cc's in predictable ways. */
179 if (SET_DEST (exp) == cc0_rtx)
181 CC_STATUS_INIT;
182 cc_status.value1 = SET_SRC (exp);
183 return;
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);
189 return;
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)
195 return;
196 if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
198 CC_STATUS_INIT;
199 cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
200 return;
202 CC_STATUS_INIT;
204 else
206 CC_STATUS_INIT;
212 function_arg (cum, mode, type, named)
213 int cum;
214 enum machine_mode mode;
215 tree type;
216 int named ATTRIBUTE_UNUSED;
218 int size;
220 if (MUST_PASS_IN_STACK (mode, type))
221 return (rtx) 0;
222 if (mode == BLKmode)
223 size = int_size_in_bytes (type);
224 else
225 size = GET_MODE_SIZE (mode);
226 if (cum + size < 12)
227 return gen_rtx_REG (mode, cum);
228 else
229 return (rtx) 0;
233 double
234 get_double (x)
235 rtx x;
237 union
239 double d;
240 long i[2];
244 du.i[0] = CONST_DOUBLE_LOW (x);
245 du.i[1] = CONST_DOUBLE_HIGH (x);
246 return du.d;
249 char *
250 float_label (code, value)
251 int code;
252 double value;
254 static char label[32];
255 char *p;
257 label[0] = code;
258 p = label + 1;
259 sprintf (p, "%f", value);
260 while (*p)
262 *p = (*p == '+') ? 'p' :
263 (*p == '-') ? 'm' : *p;
264 p++;
266 return xstrdup (label);
270 const char *
271 movcnt_regno_adjust (op)
272 rtx *op;
274 static char outstr[80];
275 int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
276 #define dstreg op0r
277 #define srcreg op1r
278 #define cntreg op2r
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);
295 else
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);
298 return outstr;
301 const char *
302 mod_regno_adjust (instr, op)
303 const char *instr;
304 rtx *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);
315 else
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,
318 modregno_gcc);
319 return outstr;
323 /* Check if op is a valid memory operand for 1750A Load/Store instructions
324 (memory indirection permitted.) */
327 memop_valid (op)
328 rtx op;
330 static int recurred = 0;
331 int valid_operand;
333 if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
334 && GET_MODE (op) != QImode)
335 return 0;
336 switch (GET_CODE (op))
338 case MEM:
339 if (!recurred && GET_CODE (XEXP (op, 0)) == REG)
340 return 1;
341 case MINUS:
342 case MULT:
343 case DIV:
344 return 0;
345 case PLUS:
346 recurred = 1;
347 valid_operand = memop_valid (XEXP (op, 0));
348 if (valid_operand)
349 valid_operand = memop_valid (XEXP (op, 1));
350 recurred = 0;
351 return valid_operand;
352 case REG:
353 if (REGNO (op) > 0)
354 return 1;
355 return 0;
356 case CONST:
357 case CONST_INT:
358 case SYMBOL_REF:
359 case SUBREG:
360 return 1;
361 default:
362 printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
363 return 1;
368 /* predicate for the MOV instruction: */
370 mov_memory_operand (op, mode)
371 rtx op;
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)
380 rtx op;
381 enum machine_mode mode ATTRIBUTE_UNUSED;
383 if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
384 return 1;
385 return 0;
388 /* predicate for constant zero: */
390 zero_operand (op, mode)
391 rtx op;
392 enum machine_mode mode;
394 return op == CONST0_RTX (mode);
398 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
399 memory operand */
401 b_mode_operand (op)
402 rtx op;
404 if (GET_CODE (op) == MEM)
406 rtx inner = XEXP (op, 0);
407 if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
408 return 1;
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)
418 return 1;
422 return 0;
426 /* Decide whether to output a conditional jump as a "Jump Conditional"
427 or as a "Branch Conditional": */
430 find_jmplbl (labelnum)
431 int labelnum;
433 int i, found = 0;
435 for (i = 0; i <= jmplbl_ndx; i++)
436 if (labelnum == jmplbl[i].num)
438 found = 1;
439 break;
441 if (found)
442 return i;
443 return -1;
446 const char *
447 branch_or_jump (condition, targetlabel_number)
448 const char *condition;
449 int targetlabel_number;
451 static char buf[30];
452 int index;
454 if ((index = find_jmplbl (targetlabel_number)) >= 0)
455 if (program_counter - jmplbl[index].pc < 128)
457 sprintf (buf, "b%s %%l0", condition);
458 return buf;
460 sprintf (buf, "jc %s,%%l0", condition);
461 return buf;
466 unsigned_comparison_operator (insn)
467 rtx insn;
469 switch (GET_CODE (insn))
471 case GEU:
472 case GTU:
473 case LEU:
474 case LTU:
475 return 1;
476 default:
477 return 0;
482 next_cc_user_is_unsigned (insn)
483 rtx insn;
485 if ( !(insn = next_cc0_user (insn)))
486 abort ();
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)));
494 else
495 abort ();
499 static int addr_inc;
501 /* A C compound statement to output to stdio stream STREAM the
502 assembler syntax for an instruction operand X. X is an RTL
503 expression.
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)
528 'w' for int - 16
531 void
532 print_operand (file, x, letter)
533 FILE *file;
534 rtx x;
535 int letter;
537 switch (GET_CODE (x))
539 case REG:
540 if (letter == 'd')
541 fprintf (file, "%d", REGNO (x) + 1);
542 else if (letter == 't')
543 fprintf (file, "%d", REGNO (x) + 2);
544 else
545 fprintf (file, "%d", REGNO (x));
546 break;
548 case SYMBOL_REF:
549 fprintf (file, "%s", XSTR (x, 0));
550 if (letter == 'A')
551 fprintf (file, "+1");
552 break;
554 case LABEL_REF:
555 case CONST:
556 case MEM:
557 if (letter == 'Q')
559 rtx inner = XEXP (x, 0);
560 switch (GET_CODE (inner))
562 case REG:
563 fprintf (file, "r%d,0", REGNO (inner));
564 break;
565 case PLUS:
566 fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
567 INTVAL (XEXP (inner, 1)));
568 break;
569 default:
570 fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
573 else
575 addr_inc = (letter == 'A' ? 1 : 0);
576 output_address (XEXP (x, 0));
578 break;
580 case CONST_DOUBLE:
581 /* {
582 double value = get_double (x);
583 char fltstr[32];
584 sprintf (fltstr, "%f", value);
586 if (letter == 'D' || letter == 'E')
588 int i, found = 0;
589 for (i = 0; i <= datalbl_ndx; i++)
590 if (strcmp (fltstr, datalbl[i].value) == 0)
592 found = 1;
593 break;
595 if (!found)
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')
608 int i, found = 0;
609 for (i = 0; i <= datalbl_ndx; i++)
610 if (strcmp (fltstr, datalbl[i].value) == 0)
612 found = 1;
613 break;
615 if (!found)
617 fprintf (stderr,
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);
629 else
630 fprintf (file, " %s ;P_O cst_dbl ", fltstr);
633 fprintf (file, "%f", get_double (x));
634 break;
636 case CONST_INT:
637 if (letter == 'J')
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);
645 else
646 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
647 break;
649 case CODE_LABEL:
650 fprintf (file, "L%d", XINT (x, 3));
651 break;
653 case CALL:
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));
658 break;
660 case PLUS:
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)
665 switch (op0code)
667 case REG:
668 fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
669 INTVAL (op1), REGNO (op0));
670 break;
671 case SYMBOL_REF:
672 fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
673 break;
674 case MEM:
675 fprintf (file, "%d,[mem:", INTVAL (op1));
676 output_address (XEXP (op0, 0));
677 fprintf (file, "] ;P_O plus");
678 break;
679 default:
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));
686 else
687 fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
689 break;
691 default:
692 fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
695 addr_inc = 0;
698 void
699 print_operand_address (file, addr)
700 FILE *file;
701 rtx addr;
703 switch (GET_CODE (addr))
705 case REG:
706 fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
707 break;
708 case PLUS:
710 register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
711 switch (GET_CODE (x))
713 case REG:
714 switch (GET_CODE (y))
716 case CONST:
717 output_address (XEXP (y, 0));
718 fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
719 break;
720 case CONST_INT:
721 fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
722 break;
723 case SYMBOL_REF:
724 fprintf (file, "%s", XSTR (y, 0));
725 if (addr_inc)
726 fprintf (file, "+%d", addr_inc);
727 fprintf (file, ",r%d ; P_O_A reg + sym", REGNO (x));
728 break;
729 case LABEL_REF:
730 output_address (XEXP (y, 0));
731 fprintf (file, ",r%d ; P_O_A reg + label", REGNO (x));
732 break;
733 default:
734 fprintf (file, "[P_O_A reg%d+UFO code=%d]",
735 REGNO (x), GET_CODE (y));
737 break;
738 case LABEL_REF:
739 output_address (XEXP (x, 0));
740 break;
741 case SYMBOL_REF:
742 switch (GET_CODE (y))
744 case CONST_INT:
745 fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
746 break;
747 case REG:
748 fprintf (file, "%s,r%d ;P_O_A sym + reg",
749 XSTR (x, 0), REGNO (y));
750 break;
751 default:
752 fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
753 XSTR (x, 0), GET_CODE (y));
755 break;
756 case CONST:
757 output_address (XEXP (x, 0));
758 if (GET_CODE (y) == REG)
759 fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
760 else
761 fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
762 break;
763 case MEM:
764 output_address (y);
765 fprintf (file, ",[mem:");
766 output_address (XEXP (x, 0));
767 fprintf (file, "] ;P_O_A plus");
768 break;
769 default:
770 fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
771 GET_CODE (x), GET_CODE (y));
774 break;
775 case CONST_INT:
776 if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
777 fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
778 else
780 fprintf (file, "[p_o_a=ILLEGAL_CONST]");
781 output_addr_const (file, addr);
783 break;
784 case LABEL_REF:
785 case SYMBOL_REF:
786 fprintf (file, "%s", XSTR (addr, 0));
787 if (addr_inc)
788 fprintf (file, "+%d", addr_inc);
789 break;
790 case MEM:
791 fprintf (file, "[memUFO:");
792 output_address (XEXP (addr, 0));
793 fprintf (file, "]");
794 break;
795 case CONST:
796 output_address (XEXP (addr, 0));
797 fprintf (file, " ;P_O_A const");
798 break;
799 case CODE_LABEL:
800 fprintf (file, "L%d", XINT (addr, 3));
801 break;
802 default:
803 fprintf (file, " p_o_a UFO, code=%d val=0x%x",
804 (int) GET_CODE (addr), INTVAL (addr));
805 break;
807 addr_inc = 0;
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.
817 one_bit_set_p (x)
818 int x;
820 x &= 0xffff;
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.
829 static int
830 which_bit (x)
831 int x;
833 int b = 15;
835 while (b > 0 && (x & 1) == 0)
837 b--;
838 x >>= 1;
841 return b;