OSDN Git Service

099f7c73818b0d19ea68bd7bdbe91acbcd05b728
[pf3gnuchains/gcc-fork.git] / gcc / config / 1750a / 1750a.c
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)
5
6 This file is part of GNU CC.
7
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.
12
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.
17
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.  */
22
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"
39
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"};
48
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));
53 \f
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
63
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
68
69 struct gcc_target targetm = TARGET_INITIALIZER;
70 \f
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.
74
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.  */
79
80 static void
81 output_function_prologue (file, size)
82      FILE *file;
83      HOST_WIDE_INT size;
84 {
85   if (flag_verbose_asm)
86     {
87       int regno, regs_used = 0;
88
89       fprintf (file, "\t; registers used: ");
90       for (regno = 0; regno < 14; regno++)
91         if (regs_ever_live[regno])
92           {
93             fprintf (file, " %s", reg_names[regno]);
94             regs_used++;
95           }
96
97       if (regs_used == 0)
98         fprintf (file, "(none)");
99     }
100
101   if (size > 0)
102     {
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");
107     }
108
109   if (frame_pointer_needed)
110     {
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");
117     }
118
119   fprintf (file, "\n");
120   program_counter = 0;
121   jmplbl_ndx = -1;
122 }
123
124 /* This function generates the assembly code for function exit.
125    Args are as for output_function_prologue ().
126
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.  */
131
132 static void
133 output_function_epilogue (file, size)
134      FILE *file;
135      HOST_WIDE_INT size;
136 {
137   if (frame_pointer_needed)
138     {
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");
146     }
147
148   if (size > 0)
149     {
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");
155     }
156
157   fprintf (file, "\turs\tr15\n\n");
158 }
159
160 void
161 notice_update_cc (exp)
162      rtx exp;
163 {
164   if (GET_CODE (exp) == SET)
165     {
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)
169         return;
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))
173         return;
174       /* Function calls clobber the cc's.  */
175       if (src_code == CALL)
176         {
177           CC_STATUS_INIT;
178           return;
179         }
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)
184         {
185           CC_STATUS_INIT;
186           return;
187         }
188       /* Tests and compares set the cc's in predictable ways.  */
189       if (SET_DEST (exp) == cc0_rtx)
190         {
191           CC_STATUS_INIT;
192           cc_status.value1 = SET_SRC (exp);
193           return;
194         }
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);
199       return;
200     }
201   else if (GET_CODE (exp) == PARALLEL
202            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
203     {
204       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
205         return;
206       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
207         {
208           CC_STATUS_INIT;
209           cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
210           return;
211         }
212       CC_STATUS_INIT;
213     }
214   else
215     {
216       CC_STATUS_INIT;
217     }
218 }
219
220
221 rtx
222 function_arg (cum, mode, type, named)
223      int cum;
224      enum machine_mode mode;
225      tree type;
226      int named ATTRIBUTE_UNUSED;
227 {
228   int size;
229
230   if (MUST_PASS_IN_STACK (mode, type))
231     return (rtx) 0;
232   if (mode == BLKmode)
233     size = int_size_in_bytes (type);
234   else
235     size = GET_MODE_SIZE (mode);
236   if (cum + size < 12)
237     return gen_rtx_REG (mode, cum);
238   else
239     return (rtx) 0;
240 }
241
242
243 double
244 get_double (x)
245      rtx x;
246 {
247   union
248     {
249       double d;
250       long i[2];
251     }
252   du;
253
254   du.i[0] = CONST_DOUBLE_LOW (x);
255   du.i[1] = CONST_DOUBLE_HIGH (x);
256   return du.d;
257 }
258
259 char *
260 float_label (code, value)
261      int code;
262      double value;
263 {
264   static char label[32];
265   char *p;
266
267   label[0] = code;
268   p = label + 1;
269   sprintf (p, "%f", value);
270   while (*p)
271     {
272       *p = (*p == '+') ? 'p' :
273         (*p == '-') ? 'm' : *p;
274       p++;
275     }
276   return xstrdup (label);
277 }
278
279
280 const char *
281 movcnt_regno_adjust (op)
282      rtx *op;
283 {
284   static char outstr[80];
285   int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
286 #define dstreg op0r
287 #define srcreg op1r
288 #define cntreg op2r
289 #define cntreg_1750 (op0r + 1)
290
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);
305   else
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);
308   return outstr;
309 }
310
311 const char *
312 mod_regno_adjust (instr, op)
313      const char *instr;
314      rtx *op;
315 {
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;
319
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);
325   else
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,
328              modregno_gcc);
329   return outstr;
330 }
331
332
333 /* Check if op is a valid memory operand for 1750A Load/Store instructions
334    (memory indirection permitted.)  */
335
336 int
337 memop_valid (op)
338      rtx op;
339 {
340   static int recurred = 0;
341   int valid_operand;
342
343   if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
344       && GET_MODE (op) != QImode)
345     return 0;
346   switch (GET_CODE (op))
347     {
348     case MEM:
349       if (!recurred && GET_CODE (XEXP (op, 0)) == REG)
350         return 1;
351     case MINUS:
352     case MULT:
353     case DIV:
354       return 0;
355     case PLUS:
356       recurred = 1;
357       valid_operand = memop_valid (XEXP (op, 0));
358       if (valid_operand)
359         valid_operand = memop_valid (XEXP (op, 1));
360        recurred = 0;
361        return valid_operand;
362     case REG:
363       if (REGNO (op) > 0)
364         return 1;
365       return 0;
366     case CONST:
367     case CONST_INT:
368     case SYMBOL_REF:
369     case SUBREG:
370       return 1;
371     default:
372       printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
373       return 1;
374     }
375 }
376
377
378 /* predicate for the MOV instruction: */
379 int
380 mov_memory_operand (op, mode)
381      rtx op;
382      enum machine_mode mode ATTRIBUTE_UNUSED;
383 {
384   return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
385 }
386
387 /* predicate for the STC instruction: */
388 int
389 small_nonneg_const (op, mode)
390      rtx op;
391      enum machine_mode mode ATTRIBUTE_UNUSED;
392 {
393   if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
394     return 1;
395   return 0;
396 }
397
398 /* predicate for constant zero: */
399 int
400 zero_operand (op, mode)
401      rtx op;
402      enum machine_mode mode;
403 {
404   return op == CONST0_RTX (mode);
405 }
406
407
408 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
409    memory operand */
410 int
411 b_mode_operand (op)
412      rtx op;
413 {
414   if (GET_CODE (op) == MEM)
415     {
416       rtx inner = XEXP (op, 0);
417       if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
418         return 1;
419       if (GET_CODE (inner) == PLUS)
420         {
421           rtx plus_op0 = XEXP (inner, 0);
422           if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
423             {
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)
428                 return 1;
429             }
430         }
431     }
432   return 0;
433 }
434
435
436 /* Decide whether to output a conditional jump as a "Jump Conditional"
437    or as a "Branch Conditional": */
438
439 int
440 find_jmplbl (labelnum)
441      int labelnum;
442 {
443   int i, found = 0;
444
445   for (i = 0; i <= jmplbl_ndx; i++)
446     if (labelnum == jmplbl[i].num)
447       {
448         found = 1;
449         break;
450       }
451   if (found)
452     return i;
453   return -1;
454 }
455
456 const char *
457 branch_or_jump (condition, targetlabel_number)
458      const char *condition;
459      int targetlabel_number;
460 {
461   static char buf[30];
462   int index;
463
464   if ((index = find_jmplbl (targetlabel_number)) >= 0)
465     if (program_counter - jmplbl[index].pc < 128)
466       {
467         sprintf (buf, "b%s %%l0", condition);
468         return buf;
469       }
470   sprintf (buf, "jc %s,%%l0", condition);
471   return buf;
472 }
473
474
475 int
476 unsigned_comparison_operator (insn)
477      rtx insn;
478 {
479   switch (GET_CODE (insn))
480     {
481     case GEU:
482     case GTU:
483     case LEU:
484     case LTU:
485       return 1;
486     default:
487       return 0;
488     }
489 }
490
491 int
492 next_cc_user_is_unsigned (insn)
493      rtx insn;
494 {
495   if ( !(insn = next_cc0_user (insn)))
496     abort ();
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)));
504   else
505     abort ();
506 }
507
508
509 static int addr_inc;
510
511 /* A C compound statement to output to stdio stream STREAM the
512    assembler syntax for an instruction operand X.  X is an RTL
513    expression.
514
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.
522
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'.
526
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.
530
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)
538    'w' for int - 16
539 */
540
541 void
542 print_operand (file, x, letter)
543      FILE *file;
544      rtx x;
545      int letter;
546 {
547   switch (GET_CODE (x))
548     {
549     case REG:
550       if (letter == 'd')
551         fprintf (file, "%d", REGNO (x) + 1);
552       else if (letter == 't')
553         fprintf (file, "%d", REGNO (x) + 2);
554       else
555         fprintf (file, "%d", REGNO (x));
556       break;
557
558     case SYMBOL_REF:
559       fprintf (file, "%s", XSTR (x, 0));
560       if (letter == 'A')
561         fprintf (file, "+1");
562       break;
563
564     case LABEL_REF:
565     case CONST:
566     case MEM:
567       if (letter == 'Q')
568         {
569           rtx inner = XEXP (x, 0);
570           switch (GET_CODE (inner))
571             {
572             case REG:
573               fprintf (file, "r%d,0", REGNO (inner));
574               break;
575             case PLUS:
576               fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
577                        INTVAL (XEXP (inner, 1)));
578               break;
579             default:
580               fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
581             }
582         }
583       else
584         {
585           addr_inc = (letter == 'A' ? 1 : 0);
586           output_address (XEXP (x, 0));
587         }
588       break;
589
590     case CONST_DOUBLE:
591 /*    {
592         double value = get_double (x);
593         char fltstr[32];
594         sprintf (fltstr, "%f", value);
595
596         if (letter == 'D' || letter == 'E')
597           {
598             int i, found = 0;
599             for (i = 0; i <= datalbl_ndx; i++)
600               if (strcmp (fltstr, datalbl[i].value) == 0)
601                 {
602                   found = 1;
603                   break;
604                 }
605             if (!found)
606               {
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);
614               }
615           }
616         else if (letter == 'F' || letter == 'G')
617           {
618             int i, found = 0;
619             for (i = 0; i <= datalbl_ndx; i++)
620               if (strcmp (fltstr, datalbl[i].value) == 0)
621                 {
622                   found = 1;
623                   break;
624                 }
625             if (!found)
626               {
627                 fprintf (stderr,
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);
636               }
637             fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
638           }
639         else
640           fprintf (file, " %s  ;P_O cst_dbl ", fltstr);
641       }
642  */
643       fprintf (file, "%f", get_double (x));
644       break;
645
646     case CONST_INT:
647       if (letter == 'J')
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);
655       else
656         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
657       break;
658
659     case CODE_LABEL:
660       fprintf (file, "L%d", XINT (x, 3));
661       break;
662
663     case CALL:
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));
668       break;
669
670     case PLUS:
671       {
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)
675           switch (op0code)
676             {
677             case REG:
678               fprintf (file, "%d,r%d  ; p_o_PLUS for REG and CONST_INT",
679                        INTVAL (op1), REGNO (op0));
680               break;
681             case SYMBOL_REF:
682               fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
683               break;
684             case MEM:
685               fprintf (file, "%d,[mem:", INTVAL (op1));
686               output_address (XEXP (op0, 0));
687               fprintf (file, "] ;P_O plus");
688               break;
689             default:
690               fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
691                        (int) op0code, INTVAL (op1));
692             }
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));
696         else
697           fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
698       }
699       break;
700
701     default:
702       fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
703     }
704
705   addr_inc = 0;
706 }
707
708 void
709 print_operand_address (file, addr)
710      FILE *file;
711      rtx addr;
712 {
713   switch (GET_CODE (addr))
714     {
715     case REG:
716       fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
717       break;
718     case PLUS:
719       {
720         register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
721         switch (GET_CODE (x))
722           {
723           case REG:
724             switch (GET_CODE (y))
725               {
726               case CONST:
727                 output_address (XEXP (y, 0));
728                 fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
729                 break;
730               case CONST_INT:
731                 fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
732                 break;
733               case SYMBOL_REF:
734                 fprintf (file, "%s", XSTR (y, 0));
735                 if (addr_inc)
736                   fprintf (file, "+%d", addr_inc);
737                 fprintf (file, ",r%d  ; P_O_A reg + sym", REGNO (x));
738                 break;
739               case LABEL_REF:
740                 output_address (XEXP (y, 0));
741                 fprintf (file, ",r%d  ; P_O_A reg + label", REGNO (x));
742                 break;
743               default:
744                 fprintf (file, "[P_O_A reg%d+UFO code=%d]",
745                          REGNO (x), GET_CODE (y));
746               }
747             break;
748           case LABEL_REF:
749             output_address (XEXP (x, 0));
750             break;
751           case SYMBOL_REF:
752             switch (GET_CODE (y))
753               {
754               case CONST_INT:
755                 fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
756                 break;
757               case REG:
758                 fprintf (file, "%s,r%d ;P_O_A sym + reg",
759                          XSTR (x, 0), REGNO (y));
760                 break;
761               default:
762                 fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
763                          XSTR (x, 0), GET_CODE (y));
764               }
765             break;
766           case CONST:
767             output_address (XEXP (x, 0));
768             if (GET_CODE (y) == REG)
769               fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
770             else
771               fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
772             break;
773           case MEM:
774             output_address (y);
775             fprintf (file, ",[mem:");
776             output_address (XEXP (x, 0));
777             fprintf (file, "] ;P_O_A plus");
778             break;
779           default:
780             fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
781                      GET_CODE (x), GET_CODE (y));
782           }
783       }
784       break;
785     case CONST_INT:
786       if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
787         fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
788       else
789         {
790           fprintf (file, "[p_o_a=ILLEGAL_CONST]");
791           output_addr_const (file, addr);
792         }
793       break;
794     case LABEL_REF:
795     case SYMBOL_REF:
796       fprintf (file, "%s", XSTR (addr, 0));
797       if (addr_inc)
798         fprintf (file, "+%d", addr_inc);
799       break;
800     case MEM:
801       fprintf (file, "[memUFO:");
802       output_address (XEXP (addr, 0));
803       fprintf (file, "]");
804       break;
805     case CONST:
806       output_address (XEXP (addr, 0));
807       fprintf (file, " ;P_O_A const");
808       break;
809     case CODE_LABEL:
810       fprintf (file, "L%d", XINT (addr, 3));
811       break;
812     default:
813       fprintf (file, " p_o_a UFO, code=%d val=0x%x",
814                (int) GET_CODE (addr), INTVAL (addr));
815       break;
816     }
817   addr_inc = 0;
818 }
819
820 /* Target hook for assembling integer objects.  The 1750a version needs to
821    keep track of how many bytes have been written.  */
822
823 static bool
824 assemble_integer_1750a (x, size, aligned_p)
825      rtx x;
826      unsigned int size;
827      int aligned_p;
828 {
829   if (default_assemble_integer (x, size, aligned_p))
830     {
831       if (label_pending)
832         label_pending = 0;
833       datalbl[datalbl_ndx].size += size;
834       return true;
835     }
836   return false;
837 }
838
839
840 /*
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.
844  */
845 int
846 one_bit_set_p (x)
847      int x;
848 {
849   x &= 0xffff; 
850   return x && (x & (x - 1)) == 0;
851 }
852
853
854 /*
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.
857  */
858 static int
859 which_bit (x)
860      int x;
861 {
862   int b = 15;
863
864   while (b > 0 && (x & 1) == 0)
865     {
866       b--;
867       x >>= 1;
868     }
869
870   return b;
871 }
872
873 \f
874 /* Convert a REAL_VALUE_TYPE to the target float format:
875
876         MSB                             LSB MSB            LSB
877         ------------------------------------------------------
878         |S|                 Mantissa       |  Exponent       |
879         ------------------------------------------------------
880          0 1                             23 24             31
881
882 */
883
884 long
885 real_value_to_target_single(in)
886      REAL_VALUE_TYPE in;
887 {
888   union {
889     double d;
890     struct {
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;
896 #else
897         unsigned int mantissa1:32;
898         unsigned int mantissa0:20;
899         unsigned int exponent:11;
900         unsigned int negative:1;
901 #endif
902     } s;
903   } ieee;
904
905   unsigned int mant;
906   int exp;
907
908   if (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
909     abort ();
910
911   ieee.d = in;
912
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;
917
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)
921     {
922       mant >>= 1;
923       exp += 1;
924     }
925
926   /* Check for overflow.  Crop to FLT_MAX.  */
927   if (exp > 127)
928     {
929       exp = 127;
930       mant = (ieee.s.negative ? 0xffffff : 0x7fffff);
931     }
932   /* Underflow to zero.  */
933   else if (exp < -128)
934     {
935       exp = 0;
936       mant = 0;
937     }
938
939   return mant << 8 | (exp & 0xff);
940 }
941
942 /* Convert a REAL_VALUE_TYPE to the target 1750a extended float format:
943
944         ----------------------------------------------------
945         | |      Mantissa       |        |   Mantissa      |
946         |S|         MS          |Exponent|      LS         |
947         ----------------------------------------------------
948          0 1                  23 24    31 32             47
949
950 */
951
952 void
953 real_value_to_target_double(in, out)
954      REAL_VALUE_TYPE in;
955      long out[];
956 {
957   union {
958     double d;
959     struct {
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;
965 #else
966         unsigned int mantissa1:32;
967         unsigned int mantissa0:20;
968         unsigned int exponent:11;
969         unsigned int negative:1;
970 #endif
971     } s;
972   } ieee;
973
974   unsigned int mant_h24, mant_l16;
975   int exp;
976
977   if (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
978     abort ();
979
980   ieee.d = in;
981
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;
987
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)
991     {
992       mant_l16 = mant_l16 >> 1 | (mant_h24 & 1) << 15;
993       mant_h24 >>= 1;
994       exp += 1;
995     }
996
997   /* Check for overflow.  Crop to DBL_MAX.  */
998   if (exp > 127)
999     {
1000       exp = 127;
1001       mant_h24 = (ieee.s.negative ? 0xffffff : 0x7fffff);
1002       mant_l16 = 0xffff;
1003     }
1004   /* Underflow to zero.  */
1005   else if (exp < -128)
1006     {
1007       exp = 0;
1008       mant_h24 = 0;
1009       mant_l16 = 0;
1010     }
1011
1012   out[0] = mant_h24 << 8 | (exp & 0xff);
1013   out[1] = mant_l16;
1014 }