]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/m68k/m68k.c
(build_conditional_expr): Compare using TYPE_MAIN_VARIANT.
[thirdparty/gcc.git] / gcc / config / m68k / m68k.c
CommitLineData
79e68feb
RS
1/* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21/* Some output-actions in m68k.md need these. */
22#include <stdio.h>
23#include "config.h"
24#include "rtl.h"
25#include "regs.h"
26#include "hard-reg-set.h"
27#include "real.h"
28#include "insn-config.h"
29#include "conditions.h"
30#include "insn-flags.h"
31#include "output.h"
32#include "insn-attr.h"
33
34/* Needed for use_return_insn. */
35#include "flags.h"
36
37#ifdef SUPPORT_SUN_FPA
38
39/* Index into this array by (register number >> 3) to find the
40 smallest class which contains that register. */
41enum reg_class regno_reg_class[]
42 = { DATA_REGS, ADDR_REGS, FP_REGS,
43 LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
44
45#endif /* defined SUPPORT_SUN_FPA */
46
9eb4f6fc
RS
47/* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
48 if SGS_SWITCH_TABLE. */
49int switch_table_difference_label_flag;
50
79e68feb
RS
51static rtx find_addr_reg ();
52rtx legitimize_pic_address ();
53\f
54
55/* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
56 function at any time during the compilation process. In the future
64a184e9 57 we should try and eliminate the USE if we can easily determine that
79e68feb
RS
58 all PIC references were deleted from the current function. That would
59 save an address register */
60
64a184e9 61finalize_pic ()
79e68feb
RS
62{
63 if (flag_pic && current_function_uses_pic_offset_table)
64 emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
65}
66
67\f
68/* This function generates the assembly code for function entry.
69 STREAM is a stdio stream to output the code to.
70 SIZE is an int: how many units of temporary storage to allocate.
71 Refer to the array `regs_ever_live' to determine which registers
72 to save; `regs_ever_live[I]' is nonzero if register number I
73 is ever used in the function. This function is responsible for
74 knowing which registers should not be saved even if used. */
75
76
77/* Note that the order of the bit mask for fmovem is the opposite
78 of the order for movem! */
79
80
81void
82output_function_prologue (stream, size)
83 FILE *stream;
84 int size;
85{
86 register int regno;
87 register int mask = 0;
88 int num_saved_regs = 0;
89 extern char call_used_regs[];
90 int fsize = (size + 3) & -4;
91
92
93 if (frame_pointer_needed)
94 {
95 /* Adding negative number is faster on the 68040. */
96 if (fsize < 0x8000 && !TARGET_68040)
97 {
98#ifdef MOTOROLA
338818c7 99 asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
79e68feb
RS
100 reg_names[FRAME_POINTER_REGNUM], -fsize);
101#else
338818c7 102 asm_fprintf (stream, "\tlink %s,%0I%d\n",
79e68feb
RS
103 reg_names[FRAME_POINTER_REGNUM], -fsize);
104#endif
105 }
106 else if (TARGET_68020)
107 {
108#ifdef MOTOROLA
338818c7 109 asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
79e68feb
RS
110 reg_names[FRAME_POINTER_REGNUM], -fsize);
111#else
338818c7 112 asm_fprintf (stream, "\tlink %s,%0I%d\n",
79e68feb
RS
113 reg_names[FRAME_POINTER_REGNUM], -fsize);
114#endif
115 }
116 else
117 {
118#ifdef MOTOROLA
cffd0d74 119 asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
79e68feb
RS
120 reg_names[FRAME_POINTER_REGNUM], -fsize);
121#else
cffd0d74 122 asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
79e68feb
RS
123 reg_names[FRAME_POINTER_REGNUM], -fsize);
124#endif
125 }
126 }
127 else if (fsize)
128 {
129 /* Adding negative number is faster on the 68040. */
130 if (fsize + 4 < 0x8000)
131 {
132#ifdef MOTOROLA
338818c7 133 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
79e68feb 134#else
338818c7 135 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
79e68feb
RS
136#endif
137 }
138 else
139 {
140#ifdef MOTOROLA
338818c7 141 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
79e68feb 142#else
338818c7 143 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
79e68feb
RS
144#endif
145 }
146 }
147#ifdef SUPPORT_SUN_FPA
148 for (regno = 24; regno < 56; regno++)
149 if (regs_ever_live[regno] && ! call_used_regs[regno])
150 {
151#ifdef MOTOROLA
152 asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
153 reg_names[regno]);
154#else
155 asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
156 reg_names[regno]);
157#endif
158 }
159#endif
160 for (regno = 16; regno < 24; regno++)
161 if (regs_ever_live[regno] && ! call_used_regs[regno])
162 mask |= 1 << (regno - 16);
163 if ((mask & 0xff) != 0)
164 {
165#ifdef MOTOROLA
cffd0d74 166 asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
79e68feb 167#else
cffd0d74 168 asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
79e68feb
RS
169#endif
170 }
171 mask = 0;
172 for (regno = 0; regno < 16; regno++)
173 if (regs_ever_live[regno] && ! call_used_regs[regno])
174 {
175 mask |= 1 << (15 - regno);
176 num_saved_regs++;
177 }
178 if (frame_pointer_needed)
179 {
180 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
181 num_saved_regs--;
182 }
183 if (num_saved_regs <= 2)
184 {
185 /* Store each separately in the same order moveml uses.
186 Using two movel instructions instead of a single moveml
187 is about 15% faster for the 68020 and 68030 at no expense
188 in code size */
189
190 int i;
191
192 /* Undo the work from above. */
193 for (i = 0; i< 16; i++)
194 if (mask & (1 << i))
195 asm_fprintf (stream,
196#ifdef MOTOROLA
64a184e9 197 "\t%Omove.l %s,-(%Rsp)\n",
79e68feb
RS
198#else
199 "\tmovel %s,%Rsp@-\n",
200#endif
201 reg_names[15 - i]);
202 }
203 else if (mask)
204 {
205#ifdef MOTOROLA
cffd0d74 206 asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
79e68feb 207#else
cffd0d74 208 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
79e68feb
RS
209#endif
210 }
211 if (flag_pic && current_function_uses_pic_offset_table)
212 {
213#ifdef MOTOROLA
cffd0d74 214 asm_fprintf (stream, "\t%Omove.l %0I__GLOBAL_OFFSET_TABLE_, %s\n",
79e68feb
RS
215 reg_names[PIC_OFFSET_TABLE_REGNUM]);
216 asm_fprintf (stream, "\tlea.l (%Rpc,%s.l),%s\n",
217 reg_names[PIC_OFFSET_TABLE_REGNUM],
218 reg_names[PIC_OFFSET_TABLE_REGNUM]);
219#else
cffd0d74 220 asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
79e68feb
RS
221 reg_names[PIC_OFFSET_TABLE_REGNUM]);
222 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
223 reg_names[PIC_OFFSET_TABLE_REGNUM],
224 reg_names[PIC_OFFSET_TABLE_REGNUM]);
225#endif
226 }
227}
228\f
229/* Return true if this function's epilogue can be output as RTL. */
230
231int
232use_return_insn ()
233{
234 int regno;
235
236 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
237 return 0;
238
239 /* Copied from output_function_epilogue (). We should probably create a
240 separate layout routine to perform the common work. */
241
242 for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
243 if (regs_ever_live[regno] && ! call_used_regs[regno])
244 return 0;
245
246 return 1;
247}
248
249/* This function generates the assembly code for function exit,
250 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
251
252 The function epilogue should not depend on the current stack pointer!
253 It should use the frame pointer only, if there is a frame pointer.
254 This is mandatory because of alloca; we also take advantage of it to
255 omit stack adjustments before returning. */
256
257void
258output_function_epilogue (stream, size)
259 FILE *stream;
260 int size;
261{
262 register int regno;
263 register int mask, fmask;
264 register int nregs;
265 int offset, foffset, fpoffset;
266 extern char call_used_regs[];
267 int fsize = (size + 3) & -4;
268 int big = 0;
269 rtx insn = get_last_insn ();
270
271 /* If the last insn was a BARRIER, we don't have to write any code. */
272 if (GET_CODE (insn) == NOTE)
273 insn = prev_nonnote_insn (insn);
274 if (insn && GET_CODE (insn) == BARRIER)
cffd0d74
RS
275 {
276 /* Output just a no-op so that debuggers don't get confused
277 about which function the pc is in at this address. */
278 asm_fprintf (stream, "\tnop\n");
279 return;
280 }
79e68feb
RS
281
282#ifdef FUNCTION_EXTRA_EPILOGUE
283 FUNCTION_EXTRA_EPILOGUE (stream, size);
284#endif
285 nregs = 0; fmask = 0; fpoffset = 0;
286#ifdef SUPPORT_SUN_FPA
287 for (regno = 24 ; regno < 56 ; regno++)
288 if (regs_ever_live[regno] && ! call_used_regs[regno])
289 nregs++;
290 fpoffset = nregs * 8;
291#endif
292 nregs = 0;
293 for (regno = 16; regno < 24; regno++)
294 if (regs_ever_live[regno] && ! call_used_regs[regno])
295 {
296 nregs++;
297 fmask |= 1 << (23 - regno);
298 }
299 foffset = fpoffset + nregs * 12;
300 nregs = 0; mask = 0;
301 if (frame_pointer_needed)
302 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
303 for (regno = 0; regno < 16; regno++)
304 if (regs_ever_live[regno] && ! call_used_regs[regno])
305 {
306 nregs++;
307 mask |= 1 << regno;
308 }
309 offset = foffset + nregs * 4;
310 if (offset + fsize >= 0x8000
311 && frame_pointer_needed
312 && (mask || fmask || fpoffset))
313 {
314#ifdef MOTOROLA
64a184e9 315 asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra0\n", -fsize);
79e68feb 316#else
338818c7 317 asm_fprintf (stream, "\tmovel %0I%d,%Ra0\n", -fsize);
79e68feb
RS
318#endif
319 fsize = 0, big = 1;
320 }
321 if (nregs <= 2)
322 {
323 /* Restore each separately in the same order moveml does.
324 Using two movel instructions instead of a single moveml
325 is about 15% faster for the 68020 and 68030 at no expense
326 in code size. */
327
328 int i;
329
330 /* Undo the work from above. */
331 for (i = 0; i< 16; i++)
332 if (mask & (1 << i))
333 {
334 if (big)
335 {
336#ifdef MOTOROLA
64a184e9 337 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra0.l),%s\n",
79e68feb
RS
338 offset + fsize,
339 reg_names[FRAME_POINTER_REGNUM],
340 reg_names[i]);
341#else
342 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra0:l),%s\n",
343 reg_names[FRAME_POINTER_REGNUM],
344 offset + fsize, reg_names[i]);
345#endif
346 }
347 else if (! frame_pointer_needed)
348 {
349#ifdef MOTOROLA
64a184e9 350 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
79e68feb
RS
351 reg_names[i]);
352#else
353 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
354 reg_names[i]);
355#endif
356 }
357 else
358 {
359#ifdef MOTOROLA
64a184e9 360 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
79e68feb
RS
361 offset + fsize,
362 reg_names[FRAME_POINTER_REGNUM],
363 reg_names[i]);
364#else
365 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
366 reg_names[FRAME_POINTER_REGNUM],
367 offset + fsize, reg_names[i]);
368#endif
369 }
370 offset = offset - 4;
371 }
372 }
373 else if (mask)
374 {
375 if (big)
376 {
377#ifdef MOTOROLA
cffd0d74 378 asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra0.l),%0I0x%x\n",
79e68feb
RS
379 offset + fsize,
380 reg_names[FRAME_POINTER_REGNUM],
381 mask);
382#else
cffd0d74 383 asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra0:l),%0I0x%x\n",
79e68feb
RS
384 reg_names[FRAME_POINTER_REGNUM],
385 offset + fsize, mask);
386#endif
387 }
388 else if (! frame_pointer_needed)
389 {
390#ifdef MOTOROLA
cffd0d74 391 asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
79e68feb 392#else
cffd0d74 393 asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
79e68feb
RS
394#endif
395 }
396 else
397 {
398#ifdef MOTOROLA
cffd0d74 399 asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
79e68feb
RS
400 offset + fsize,
401 reg_names[FRAME_POINTER_REGNUM],
402 mask);
403#else
cffd0d74 404 asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
79e68feb
RS
405 reg_names[FRAME_POINTER_REGNUM],
406 offset + fsize, mask);
407#endif
408 }
409 }
410 if (fmask)
411 {
412 if (big)
413 {
414#ifdef MOTOROLA
cffd0d74 415 asm_fprintf (stream, "\tfmovm -%d(%s,%Ra0.l),%0I0x%x\n",
79e68feb
RS
416 foffset + fsize,
417 reg_names[FRAME_POINTER_REGNUM],
418 fmask);
419#else
cffd0d74 420 asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra0:l),%0I0x%x\n",
79e68feb
RS
421 reg_names[FRAME_POINTER_REGNUM],
422 foffset + fsize, fmask);
423#endif
424 }
425 else if (! frame_pointer_needed)
426 {
427#ifdef MOTOROLA
cffd0d74 428 asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
79e68feb 429#else
cffd0d74 430 asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
79e68feb
RS
431#endif
432 }
433 else
434 {
435#ifdef MOTOROLA
cffd0d74 436 asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
79e68feb
RS
437 foffset + fsize,
438 reg_names[FRAME_POINTER_REGNUM],
439 fmask);
440#else
cffd0d74 441 asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
79e68feb
RS
442 reg_names[FRAME_POINTER_REGNUM],
443 foffset + fsize, fmask);
444#endif
445 }
446 }
447 if (fpoffset != 0)
448 for (regno = 55; regno >= 24; regno--)
449 if (regs_ever_live[regno] && ! call_used_regs[regno])
450 {
451 if (big)
452 {
453#ifdef MOTOROLA
454 asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra0.l), %s\n",
455 fpoffset + fsize,
456 reg_names[FRAME_POINTER_REGNUM],
457 reg_names[regno]);
458#else
459 asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra0:l), %s\n",
460 reg_names[FRAME_POINTER_REGNUM],
461 fpoffset + fsize, reg_names[regno]);
462#endif
463 }
464 else if (! frame_pointer_needed)
465 {
466#ifdef MOTOROLA
467 asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
468 reg_names[regno]);
469#else
470 asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
471 reg_names[regno]);
472#endif
473 }
474 else
475 {
476#ifdef MOTOROLA
477 asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
478 fpoffset + fsize,
479 reg_names[FRAME_POINTER_REGNUM],
480 reg_names[regno]);
481#else
482 asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
483 reg_names[FRAME_POINTER_REGNUM],
484 fpoffset + fsize, reg_names[regno]);
485#endif
486 }
487 fpoffset -= 8;
488 }
489 if (frame_pointer_needed)
490 fprintf (stream, "\tunlk %s\n",
491 reg_names[FRAME_POINTER_REGNUM]);
492 else if (fsize)
493 {
494 if (fsize + 4 < 0x8000)
495 {
496#ifdef MOTOROLA
338818c7 497 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
79e68feb 498#else
338818c7 499 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
79e68feb
RS
500#endif
501 }
502 else
503 {
504#ifdef MOTOROLA
338818c7 505 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
79e68feb 506#else
338818c7 507 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
79e68feb
RS
508#endif
509 }
510 }
511 if (current_function_pops_args)
338818c7 512 asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
79e68feb
RS
513 else
514 fprintf (stream, "\trts\n");
515}
516\f
517/* Similar to general_operand, but exclude stack_pointer_rtx. */
518
519int
520not_sp_operand (op, mode)
521 register rtx op;
522 enum machine_mode mode;
523{
524 return op != stack_pointer_rtx && general_operand (op, mode);
525}
526
64a184e9
RS
527/* Return TRUE if X is a valid comparison operator for the dbcc
528 instruction.
529
530 Note it rejects floating point comparison operators.
531 (In the future we could use Fdbcc).
532
533 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
534
535int
536valid_dbcc_comparison_p (x, mode)
537 rtx x;
538 enum machine_mode mode;
539{
540 /* We could add support for these in the future */
541 if (cc_prev_status.flags & CC_IN_68881)
542 return 0;
543
544 switch (GET_CODE (x))
545 {
546
547 case EQ: case NE: case GTU: case LTU:
548 case GEU: case LEU:
549 return 1;
550
551 /* Reject some when CC_NO_OVERFLOW is set. This may be over
552 conservative */
553 case GT: case LT: case GE: case LE:
554 return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
555 default:
556 return 0;
557 }
558}
559
560/* Output a dbCC; jCC sequence. Note we do not handle the
561 floating point version of this sequence (Fdbcc). We also
562 do not handle alternative conditions when CC_NO_OVERFLOW is
563 set. It is assumed that valid_dbcc_comparison_p will kick
564 those out before we get here. */
565
566output_dbcc_and_branch (operands)
567 rtx *operands;
568{
569
570 switch (GET_CODE (operands[3]))
571 {
572 case EQ:
573#ifdef MOTOROLA
574 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
575#else
576 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
577#endif
578 break;
579
580 case NE:
581#ifdef MOTOROLA
582 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
583#else
584 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
585#endif
586 break;
587
588 case GT:
589#ifdef MOTOROLA
590 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
591#else
592 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
593#endif
594 break;
595
596 case GTU:
597#ifdef MOTOROLA
598 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
599#else
600 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
601#endif
602 break;
603
604 case LT:
605#ifdef MOTOROLA
606 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
607#else
608 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
609#endif
610 break;
611
612 case LTU:
613#ifdef MOTOROLA
614 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
615#else
616 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
617#endif
618 break;
619
620 case GE:
621#ifdef MOTOROLA
622 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
623#else
624 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
625#endif
626 break;
627
628 case GEU:
629#ifdef MOTOROLA
630 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
631#else
632 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
633#endif
634 break;
635
636 case LE:
637#ifdef MOTOROLA
638 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
639#else
640 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
641#endif
642 break;
643
644 case LEU:
645#ifdef MOTOROLA
646 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
647#else
648 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
649#endif
650 break;
651
652 default:
653 abort ();
654 }
655
656 /* If the decrement is to be done in SImode, then we have
657 to compensate for the fact that dbcc decrements in HImode. */
658 switch (GET_MODE (operands[0]))
659 {
660 case SImode:
661#ifdef MOTOROLA
662 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
663#else
664 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
665#endif
666 break;
667
668 case HImode:
669 break;
670
671 default:
672 abort ();
673 }
674}
675
79e68feb
RS
676char *
677output_btst (operands, countop, dataop, insn, signpos)
678 rtx *operands;
679 rtx countop, dataop;
680 rtx insn;
681 int signpos;
682{
683 operands[0] = countop;
684 operands[1] = dataop;
685
686 if (GET_CODE (countop) == CONST_INT)
687 {
688 register int count = INTVAL (countop);
689 /* If COUNT is bigger than size of storage unit in use,
690 advance to the containing unit of same size. */
691 if (count > signpos)
692 {
693 int offset = (count & ~signpos) / 8;
694 count = count & signpos;
695 operands[1] = dataop = adj_offsettable_operand (dataop, offset);
696 }
697 if (count == signpos)
698 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
699 else
700 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
701
702 /* These three statements used to use next_insns_test_no...
703 but it appears that this should do the same job. */
704 if (count == 31
705 && next_insn_tests_no_inequality (insn))
706 return "tst%.l %1";
707 if (count == 15
708 && next_insn_tests_no_inequality (insn))
709 return "tst%.w %1";
710 if (count == 7
711 && next_insn_tests_no_inequality (insn))
712 return "tst%.b %1";
713
714 cc_status.flags = CC_NOT_NEGATIVE;
715 }
716 return "btst %0,%1";
717}
718\f
719/* Returns 1 if OP is either a symbol reference or a sum of a symbol
720 reference and a constant. */
721
722int
723symbolic_operand (op, mode)
724 register rtx op;
725 enum machine_mode mode;
726{
727 switch (GET_CODE (op))
728 {
729 case SYMBOL_REF:
730 case LABEL_REF:
731 return 1;
732
733 case CONST:
734 op = XEXP (op, 0);
735 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
736 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
737 && GET_CODE (XEXP (op, 1)) == CONST_INT);
738
739#if 0 /* Deleted, with corresponding change in m68k.h,
740 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
741 case CONST_DOUBLE:
742 return GET_MODE (op) == mode;
743#endif
744
745 default:
746 return 0;
747 }
748}
749
750\f
751/* Legitimize PIC addresses. If the address is already
752 position-independent, we return ORIG. Newly generated
753 position-independent addresses go to REG. If we need more
754 than one register, we lose.
755
756 An address is legitimized by making an indirect reference
757 through the Global Offset Table with the name of the symbol
758 used as an offset.
759
760 The assembler and linker are responsible for placing the
761 address of the symbol in the GOT. The function prologue
762 is responsible for initializing a5 to the starting address
763 of the GOT.
764
765 The assembler is also responsible for translating a symbol name
766 into a constant displacement from the start of the GOT.
767
768 A quick example may make things a little clearer:
769
770 When not generating PIC code to store the value 12345 into _foo
771 we would generate the following code:
772
773 movel #12345, _foo
774
775 When generating PIC two transformations are made. First, the compiler
776 loads the address of foo into a register. So the first transformation makes:
777
778 lea _foo, a0
779 movel #12345, a0@
780
781 The code in movsi will intercept the lea instruction and call this
782 routine which will transform the instructions into:
783
784 movel a5@(_foo:w), a0
785 movel #12345, a0@
786
787
788 That (in a nutshell) is how *all* symbol and label references are
789 handled. */
790
791rtx
792legitimize_pic_address (orig, mode, reg)
793 rtx orig, reg;
794 enum machine_mode mode;
795{
796 rtx pic_ref = orig;
797
798 /* First handle a simple SYMBOL_REF or LABEL_REF */
799 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
800 {
801 if (reg == 0)
802 abort ();
803
804 pic_ref = gen_rtx (MEM, Pmode,
805 gen_rtx (PLUS, Pmode,
806 pic_offset_table_rtx, orig));
807 current_function_uses_pic_offset_table = 1;
808 RTX_UNCHANGING_P (pic_ref) = 1;
809 emit_move_insn (reg, pic_ref);
810 return reg;
811 }
812 else if (GET_CODE (orig) == CONST)
813 {
814 rtx base, offset;
815
816 /* Make sure this is CONST has not already been legitimized */
817 if (GET_CODE (XEXP (orig, 0)) == PLUS
818 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
819 return orig;
820
821 if (reg == 0)
822 abort ();
823
824 /* legitimize both operands of the PLUS */
825 if (GET_CODE (XEXP (orig, 0)) == PLUS)
826 {
827 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
828 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
829 base == reg ? 0 : reg);
830 }
831 else abort ();
832
833 if (GET_CODE (orig) == CONST_INT)
834 return plus_constant_for_output (base, INTVAL (orig));
835 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
836 /* Likewise, should we set special REG_NOTEs here? */
837 }
838 return pic_ref;
839}
840
841\f
842/* Return the best assembler insn template
843 for moving operands[1] into operands[0] as a fullword. */
844
845static char *
846singlemove_string (operands)
847 rtx *operands;
848{
849#ifdef SUPPORT_SUN_FPA
850 if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
851 return "fpmoves %1,%0";
852#endif
853 if (DATA_REG_P (operands[0])
854 && GET_CODE (operands[1]) == CONST_INT
855 && INTVAL (operands[1]) < 128
856 && INTVAL (operands[1]) >= -128)
857 {
64a184e9 858#if defined (MOTOROLA) && !defined (CRDS)
79e68feb
RS
859 return "moveq%.l %1,%0";
860#else
861 return "moveq %1,%0";
862#endif
863 }
864 if (operands[1] != const0_rtx)
865 return "move%.l %1,%0";
866 if (! ADDRESS_REG_P (operands[0]))
867 return "clr%.l %0";
868 return "sub%.l %0,%0";
869}
870
871/* Output assembler code to perform a doubleword move insn
872 with operands OPERANDS. */
873
874char *
875output_move_double (operands)
876 rtx *operands;
877{
878 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
879 rtx latehalf[2];
880 rtx addreg0 = 0, addreg1 = 0;
881
882 /* First classify both operands. */
883
884 if (REG_P (operands[0]))
885 optype0 = REGOP;
886 else if (offsettable_memref_p (operands[0]))
887 optype0 = OFFSOP;
888 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
889 optype0 = POPOP;
890 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
891 optype0 = PUSHOP;
892 else if (GET_CODE (operands[0]) == MEM)
893 optype0 = MEMOP;
894 else
895 optype0 = RNDOP;
896
897 if (REG_P (operands[1]))
898 optype1 = REGOP;
899 else if (CONSTANT_P (operands[1]))
900 optype1 = CNSTOP;
901 else if (offsettable_memref_p (operands[1]))
902 optype1 = OFFSOP;
903 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
904 optype1 = POPOP;
905 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
906 optype1 = PUSHOP;
907 else if (GET_CODE (operands[1]) == MEM)
908 optype1 = MEMOP;
909 else
910 optype1 = RNDOP;
911
912 /* Check for the cases that the operand constraints are not
913 supposed to allow to happen. Abort if we get one,
914 because generating code for these cases is painful. */
915
916 if (optype0 == RNDOP || optype1 == RNDOP)
917 abort ();
918
919 /* If one operand is decrementing and one is incrementing
920 decrement the former register explicitly
921 and change that operand into ordinary indexing. */
922
923 if (optype0 == PUSHOP && optype1 == POPOP)
924 {
925 operands[0] = XEXP (XEXP (operands[0], 0), 0);
926 output_asm_insn ("subq%.l %#8,%0", operands);
927 operands[0] = gen_rtx (MEM, DImode, operands[0]);
928 optype0 = OFFSOP;
929 }
930 if (optype0 == POPOP && optype1 == PUSHOP)
931 {
932 operands[1] = XEXP (XEXP (operands[1], 0), 0);
933 output_asm_insn ("subq%.l %#8,%1", operands);
934 operands[1] = gen_rtx (MEM, DImode, operands[1]);
935 optype1 = OFFSOP;
936 }
937
938 /* If an operand is an unoffsettable memory ref, find a register
939 we can increment temporarily to make it refer to the second word. */
940
941 if (optype0 == MEMOP)
942 addreg0 = find_addr_reg (XEXP (operands[0], 0));
943
944 if (optype1 == MEMOP)
945 addreg1 = find_addr_reg (XEXP (operands[1], 0));
946
947 /* Ok, we can do one word at a time.
948 Normally we do the low-numbered word first,
949 but if either operand is autodecrementing then we
950 do the high-numbered word first.
951
952 In either case, set up in LATEHALF the operands to use
953 for the high-numbered word and in some cases alter the
954 operands in OPERANDS to be suitable for the low-numbered word. */
955
956 if (optype0 == REGOP)
957 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
958 else if (optype0 == OFFSOP)
959 latehalf[0] = adj_offsettable_operand (operands[0], 4);
960 else
961 latehalf[0] = operands[0];
962
963 if (optype1 == REGOP)
964 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
965 else if (optype1 == OFFSOP)
966 latehalf[1] = adj_offsettable_operand (operands[1], 4);
967 else if (optype1 == CNSTOP)
968 split_double (operands[1], &operands[1], &latehalf[1]);
969 else
970 latehalf[1] = operands[1];
971
972 /* If insn is effectively movd N(sp),-(sp) then we will do the
973 high word first. We should use the adjusted operand 1 (which is N+4(sp))
974 for the low word as well, to compensate for the first decrement of sp. */
975 if (optype0 == PUSHOP
976 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
977 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
978 operands[1] = latehalf[1];
979
980 /* If one or both operands autodecrementing,
981 do the two words, high-numbered first. */
982
983 /* Likewise, the first move would clobber the source of the second one,
984 do them in the other order. This happens only for registers;
985 such overlap can't happen in memory unless the user explicitly
986 sets it up, and that is an undefined circumstance. */
987
988 if (optype0 == PUSHOP || optype1 == PUSHOP
989 || (optype0 == REGOP && optype1 == REGOP
990 && REGNO (operands[0]) == REGNO (latehalf[1])))
991 {
992 /* Make any unoffsettable addresses point at high-numbered word. */
993 if (addreg0)
994 output_asm_insn ("addql %#4,%0", &addreg0);
995 if (addreg1)
996 output_asm_insn ("addql %#4,%0", &addreg1);
997
998 /* Do that word. */
999 output_asm_insn (singlemove_string (latehalf), latehalf);
1000
1001 /* Undo the adds we just did. */
1002 if (addreg0)
1003 output_asm_insn ("subql %#4,%0", &addreg0);
1004 if (addreg1)
1005 output_asm_insn ("subql %#4,%0", &addreg1);
1006
1007 /* Do low-numbered word. */
1008 return singlemove_string (operands);
1009 }
1010
1011 /* Normal case: do the two words, low-numbered first. */
1012
1013 output_asm_insn (singlemove_string (operands), operands);
1014
1015 /* Make any unoffsettable addresses point at high-numbered word. */
1016 if (addreg0)
1017 output_asm_insn ("addql %#4,%0", &addreg0);
1018 if (addreg1)
1019 output_asm_insn ("addql %#4,%0", &addreg1);
1020
1021 /* Do that word. */
1022 output_asm_insn (singlemove_string (latehalf), latehalf);
1023
1024 /* Undo the adds we just did. */
1025 if (addreg0)
1026 output_asm_insn ("subql %#4,%0", &addreg0);
1027 if (addreg1)
1028 output_asm_insn ("subql %#4,%0", &addreg1);
1029
1030 return "";
1031}
1032
1033/* Return a REG that occurs in ADDR with coefficient 1.
1034 ADDR can be effectively incremented by incrementing REG. */
1035
1036static rtx
1037find_addr_reg (addr)
1038 rtx addr;
1039{
1040 while (GET_CODE (addr) == PLUS)
1041 {
1042 if (GET_CODE (XEXP (addr, 0)) == REG)
1043 addr = XEXP (addr, 0);
1044 else if (GET_CODE (XEXP (addr, 1)) == REG)
1045 addr = XEXP (addr, 1);
1046 else if (CONSTANT_P (XEXP (addr, 0)))
1047 addr = XEXP (addr, 1);
1048 else if (CONSTANT_P (XEXP (addr, 1)))
1049 addr = XEXP (addr, 0);
1050 else
1051 abort ();
1052 }
1053 if (GET_CODE (addr) == REG)
1054 return addr;
1055 abort ();
1056}
1057\f
1058/* Store in cc_status the expressions that the condition codes will
1059 describe after execution of an instruction whose pattern is EXP.
1060 Do not alter them if the instruction would not alter the cc's. */
1061
1062/* On the 68000, all the insns to store in an address register fail to
1063 set the cc's. However, in some cases these instructions can make it
1064 possibly invalid to use the saved cc's. In those cases we clear out
1065 some or all of the saved cc's so they won't be used. */
1066
1067notice_update_cc (exp, insn)
1068 rtx exp;
1069 rtx insn;
1070{
1071 /* If the cc is being set from the fpa and the expression is not an
1072 explicit floating point test instruction (which has code to deal with
1073 this), reinit the CC. */
1074 if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1075 || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1076 && !(GET_CODE (exp) == PARALLEL
1077 && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1078 && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1079 {
1080 CC_STATUS_INIT;
1081 }
1082 else if (GET_CODE (exp) == SET)
1083 {
1084 if (GET_CODE (SET_SRC (exp)) == CALL)
1085 {
1086 CC_STATUS_INIT;
1087 }
1088 else if (ADDRESS_REG_P (SET_DEST (exp)))
1089 {
1090 if (cc_status.value1
1091 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1092 cc_status.value1 = 0;
1093 if (cc_status.value2
1094 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1095 cc_status.value2 = 0;
1096 }
1097 else if (!FP_REG_P (SET_DEST (exp))
1098 && SET_DEST (exp) != cc0_rtx
1099 && (FP_REG_P (SET_SRC (exp))
1100 || GET_CODE (SET_SRC (exp)) == FIX
1101 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1102 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
1103 {
1104 CC_STATUS_INIT;
1105 }
1106 /* A pair of move insns doesn't produce a useful overall cc. */
1107 else if (!FP_REG_P (SET_DEST (exp))
1108 && !FP_REG_P (SET_SRC (exp))
1109 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
1110 && (GET_CODE (SET_SRC (exp)) == REG
1111 || GET_CODE (SET_SRC (exp)) == MEM
1112 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
1113 {
1114 CC_STATUS_INIT;
1115 }
1116 else if (GET_CODE (SET_SRC (exp)) == CALL)
1117 {
1118 CC_STATUS_INIT;
1119 }
1120 else if (XEXP (exp, 0) != pc_rtx)
1121 {
1122 cc_status.flags = 0;
1123 cc_status.value1 = XEXP (exp, 0);
1124 cc_status.value2 = XEXP (exp, 1);
1125 }
1126 }
1127 else if (GET_CODE (exp) == PARALLEL
1128 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1129 {
1130 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
1131 CC_STATUS_INIT;
1132 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
1133 {
1134 cc_status.flags = 0;
1135 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
1136 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
1137 }
1138 }
1139 else
1140 CC_STATUS_INIT;
1141 if (cc_status.value2 != 0
1142 && ADDRESS_REG_P (cc_status.value2)
1143 && GET_MODE (cc_status.value2) == QImode)
1144 CC_STATUS_INIT;
1145 if (cc_status.value2 != 0
1146 && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
1147 switch (GET_CODE (cc_status.value2))
1148 {
1149 case PLUS: case MINUS: case MULT:
1150 case DIV: case UDIV: case MOD: case UMOD: case NEG:
1151 case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT:
1152 case ROTATE: case ROTATERT:
1153 if (GET_MODE (cc_status.value2) != VOIDmode)
1154 cc_status.flags |= CC_NO_OVERFLOW;
1155 break;
1156 case ZERO_EXTEND:
1157 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1158 ends with a move insn moving r2 in r2's mode.
1159 Thus, the cc's are set for r2.
1160 This can set N bit spuriously. */
1161 cc_status.flags |= CC_NOT_NEGATIVE;
1162 }
1163 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1164 && cc_status.value2
1165 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1166 cc_status.value2 = 0;
1167 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1168 || (cc_status.value2 && FP_REG_P (cc_status.value2)))
1169 && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
1170 || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
1171 cc_status.flags = CC_IN_68881;
1172}
1173\f
1174char *
1175output_move_const_double (operands)
1176 rtx *operands;
1177{
1178#ifdef SUPPORT_SUN_FPA
64a184e9 1179 if (TARGET_FPA && FPA_REG_P (operands[0]))
79e68feb
RS
1180 {
1181 int code = standard_sun_fpa_constant_p (operands[1]);
1182
1183 if (code != 0)
1184 {
1185 static char buf[40];
1186
1187 sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
1188 return buf;
1189 }
1190 return "fpmove%.d %1,%0";
1191 }
1192 else
1193#endif
1194 {
1195 int code = standard_68881_constant_p (operands[1]);
1196
1197 if (code != 0)
1198 {
1199 static char buf[40];
1200
1201 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1202 return buf;
1203 }
1204 return "fmove%.d %1,%0";
1205 }
1206}
1207
1208char *
1209output_move_const_single (operands)
1210 rtx *operands;
1211{
1212#ifdef SUPPORT_SUN_FPA
1213 if (TARGET_FPA)
1214 {
1215 int code = standard_sun_fpa_constant_p (operands[1]);
1216
1217 if (code != 0)
1218 {
1219 static char buf[40];
1220
1221 sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1222 return buf;
1223 }
1224 return "fpmove%.s %1,%0";
1225 }
1226 else
1227#endif /* defined SUPPORT_SUN_FPA */
1228 {
1229 int code = standard_68881_constant_p (operands[1]);
1230
1231 if (code != 0)
1232 {
1233 static char buf[40];
1234
1235 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1236 return buf;
1237 }
1238 return "fmove%.s %f1,%0";
1239 }
1240}
1241
1242/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1243 from the "fmovecr" instruction.
1244 The value, anded with 0xff, gives the code to use in fmovecr
1245 to get the desired constant. */
1246
1247/* ??? This code should be fixed for cross-compilation. */
1248
1249int
1250standard_68881_constant_p (x)
1251 rtx x;
1252{
1253 union {double d; int i[2];} u;
1254 register double d;
1255
2296cba3 1256 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
79e68feb
RS
1257 if (TARGET_68040)
1258 return 0;
1259
1260#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1261 if (! flag_pretend_float)
1262 return 0;
1263#endif
1264
1265#ifdef HOST_WORDS_BIG_ENDIAN
1266 u.i[0] = CONST_DOUBLE_LOW (x);
1267 u.i[1] = CONST_DOUBLE_HIGH (x);
1268#else
1269 u.i[0] = CONST_DOUBLE_HIGH (x);
1270 u.i[1] = CONST_DOUBLE_LOW (x);
1271#endif
1272 d = u.d;
1273
1274 if (d == 0)
1275 return 0x0f;
1276 /* Note: there are various other constants available
1277 but it is a nuisance to put in their values here. */
1278 if (d == 1)
1279 return 0x32;
1280 if (d == 10)
1281 return 0x33;
1282 if (d == 100)
1283 return 0x34;
1284 if (d == 10000)
1285 return 0x35;
1286 if (d == 1e8)
1287 return 0x36;
1288 if (GET_MODE (x) == SFmode)
1289 return 0;
1290 if (d == 1e16)
1291 return 0x37;
1292 /* larger powers of ten in the constants ram are not used
1293 because they are not equal to a `double' C constant. */
1294 return 0;
1295}
1296
1297/* If X is a floating-point constant, return the logarithm of X base 2,
1298 or 0 if X is not a power of 2. */
1299
1300int
1301floating_exact_log2 (x)
1302 rtx x;
1303{
1304 union {double d; int i[2];} u;
1305 register double d, d1;
1306 int i;
1307
1308#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1309 if (! flag_pretend_float)
1310 return 0;
1311#endif
1312
1313#ifdef HOST_WORDS_BIG_ENDIAN
1314 u.i[0] = CONST_DOUBLE_LOW (x);
1315 u.i[1] = CONST_DOUBLE_HIGH (x);
1316#else
1317 u.i[0] = CONST_DOUBLE_HIGH (x);
1318 u.i[1] = CONST_DOUBLE_LOW (x);
1319#endif
1320 d = u.d;
1321
1322 if (! (d > 0))
1323 return 0;
1324
1325 for (d1 = 1.0, i = 0; d1 < d; d1 *= 2.0, i++)
1326 ;
1327
1328 if (d == d1)
1329 return i;
1330
1331 return 0;
1332}
1333\f
1334#ifdef SUPPORT_SUN_FPA
1335/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1336 from the Sun FPA's constant RAM.
1337 The value returned, anded with 0x1ff, gives the code to use in fpmove
1338 to get the desired constant. */
1339#define S_E (2.718281745910644531)
1340#define D_E (2.718281828459045091)
1341#define S_PI (3.141592741012573242)
1342#define D_PI (3.141592653589793116)
1343#define S_SQRT2 (1.414213538169860840)
1344#define D_SQRT2 (1.414213562373095145)
1345#define S_LOG2ofE (1.442695021629333496)
1346#define D_LOG2ofE (1.442695040888963387)
1347#define S_LOG2of10 (3.321928024291992188)
1348#define D_LOG2of10 (3.321928024887362182)
1349#define S_LOGEof2 (0.6931471824645996094)
1350#define D_LOGEof2 (0.6931471805599452862)
1351#define S_LOGEof10 (2.302585124969482442)
1352#define D_LOGEof10 (2.302585092994045901)
1353#define S_LOG10of2 (0.3010300099849700928)
1354#define D_LOG10of2 (0.3010299956639811980)
1355#define S_LOG10ofE (0.4342944920063018799)
1356#define D_LOG10ofE (0.4342944819032518167)
1357
1358/* This code should be fixed for cross-compilation. */
1359
1360int
1361standard_sun_fpa_constant_p (x)
1362 rtx x;
1363{
1364 union {double d; int i[2];} u;
1365 register double d;
1366
1367#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1368 if (! flag_pretend_float)
1369 return 0;
1370#endif
1371
1372
1373 u.i[0] = CONST_DOUBLE_LOW (x);
1374 u.i[1] = CONST_DOUBLE_HIGH (x);
1375 d = u.d;
1376
1377 if (d == 0.0)
1378 return 0x200; /* 0 once 0x1ff is anded with it */
1379 if (d == 1.0)
1380 return 0xe;
1381 if (d == 0.5)
1382 return 0xf;
1383 if (d == -1.0)
1384 return 0x10;
1385 if (d == 2.0)
1386 return 0x11;
1387 if (d == 3.0)
1388 return 0xB1;
1389 if (d == 4.0)
1390 return 0x12;
1391 if (d == 8.0)
1392 return 0x13;
1393 if (d == 0.25)
1394 return 0x15;
1395 if (d == 0.125)
1396 return 0x16;
1397 if (d == 10.0)
1398 return 0x17;
1399 if (d == -(1.0/2.0))
1400 return 0x2E;
1401
1402/*
1403 * Stuff that looks different if it's single or double
1404 */
64a184e9 1405 if (GET_MODE (x) == SFmode)
79e68feb
RS
1406 {
1407 if (d == S_E)
1408 return 0x8;
1409 if (d == (2*S_PI))
1410 return 0x9;
1411 if (d == S_PI)
1412 return 0xA;
1413 if (d == (S_PI / 2.0))
1414 return 0xB;
1415 if (d == S_SQRT2)
1416 return 0xC;
1417 if (d == (1.0 / S_SQRT2))
1418 return 0xD;
1419 /* Large powers of 10 in the constant
1420 ram are not used because they are
1421 not equal to a C double constant */
1422 if (d == -(S_PI / 2.0))
1423 return 0x27;
1424 if (d == S_LOG2ofE)
1425 return 0x28;
1426 if (d == S_LOG2of10)
1427 return 0x29;
1428 if (d == S_LOGEof2)
1429 return 0x2A;
1430 if (d == S_LOGEof10)
1431 return 0x2B;
1432 if (d == S_LOG10of2)
1433 return 0x2C;
1434 if (d == S_LOG10ofE)
1435 return 0x2D;
1436 }
1437 else
1438 {
1439 if (d == D_E)
1440 return 0x8;
1441 if (d == (2*D_PI))
1442 return 0x9;
1443 if (d == D_PI)
1444 return 0xA;
1445 if (d == (D_PI / 2.0))
1446 return 0xB;
1447 if (d == D_SQRT2)
1448 return 0xC;
1449 if (d == (1.0 / D_SQRT2))
1450 return 0xD;
1451 /* Large powers of 10 in the constant
1452 ram are not used because they are
1453 not equal to a C double constant */
1454 if (d == -(D_PI / 2.0))
1455 return 0x27;
1456 if (d == D_LOG2ofE)
1457 return 0x28;
1458 if (d == D_LOG2of10)
1459 return 0x29;
1460 if (d == D_LOGEof2)
1461 return 0x2A;
1462 if (d == D_LOGEof10)
1463 return 0x2B;
1464 if (d == D_LOG10of2)
1465 return 0x2C;
1466 if (d == D_LOG10ofE)
1467 return 0x2D;
1468 }
1469 return 0x0;
1470}
1471#endif /* define SUPPORT_SUN_FPA */
1472\f
1473/* A C compound statement to output to stdio stream STREAM the
1474 assembler syntax for an instruction operand X. X is an RTL
1475 expression.
1476
1477 CODE is a value that can be used to specify one of several ways
1478 of printing the operand. It is used when identical operands
1479 must be printed differently depending on the context. CODE
1480 comes from the `%' specification that was used to request
1481 printing of the operand. If the specification was just `%DIGIT'
1482 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
1483 is the ASCII code for LTR.
1484
1485 If X is a register, this macro should print the register's name.
1486 The names can be found in an array `reg_names' whose type is
1487 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
1488
1489 When the machine description has a specification `%PUNCT' (a `%'
1490 followed by a punctuation character), this macro is called with
1491 a null pointer for X and the punctuation character for CODE.
1492
1493 The m68k specific codes are:
1494
1495 '.' for dot needed in Motorola-style opcode names.
1496 '-' for an operand pushing on the stack:
1497 sp@-, -(sp) or -(%sp) depending on the style of syntax.
1498 '+' for an operand pushing on the stack:
1499 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
1500 '@' for a reference to the top word on the stack:
1501 sp@, (sp) or (%sp) depending on the style of syntax.
1502 '#' for an immediate operand prefix (# in MIT and Motorola syntax
1503 but & in SGS syntax).
1504 '!' for the cc register (used in an `and to cc' insn).
1505 '$' for the letter `s' in an op code, but only on the 68040.
1506 '&' for the letter `d' in an op code, but only on the 68040.
1507
1508 'b' for byte insn (no effect, on the Sun; this is for the ISI).
1509 'd' to force memory addressing to be absolute, not relative.
1510 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1511 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1512 than directly). Second part of 'y' below.
1513 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1514 or print pair of registers as rx:ry.
1515 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
1516 CONST_DOUBLE's as SunFPA constant RAM registers if
1517 possible, so it should not be used except for the SunFPA.
1518
1519 */
1520
1521void
1522print_operand (file, op, letter)
1523 FILE *file; /* file to write to */
1524 rtx op; /* operand to print */
1525 int letter; /* %<letter> or 0 */
1526{
1527 int i;
1528
1529 if (letter == '.')
1530 {
1531#ifdef MOTOROLA
1532 asm_fprintf (file, ".");
1533#endif
1534 }
1535 else if (letter == '#')
1536 {
cffd0d74 1537 asm_fprintf (file, "%0I");
79e68feb
RS
1538 }
1539 else if (letter == '-')
1540 {
1541#ifdef MOTOROLA
1542 asm_fprintf (file, "-(%Rsp)");
1543#else
1544 asm_fprintf (file, "%Rsp@-");
1545#endif
1546 }
1547 else if (letter == '+')
1548 {
1549#ifdef MOTOROLA
1550 asm_fprintf (file, "(%Rsp)+");
1551#else
1552 asm_fprintf (file, "%Rsp@+");
1553#endif
1554 }
1555 else if (letter == '@')
1556 {
1557#ifdef MOTOROLA
1558 asm_fprintf (file, "(%Rsp)");
1559#else
1560 asm_fprintf (file, "%Rsp@");
1561#endif
1562 }
1563 else if (letter == '!')
1564 {
cffd0d74 1565 asm_fprintf (file, "%Rfpcr");
79e68feb
RS
1566 }
1567 else if (letter == '$')
1568 {
1569 if (TARGET_68040_ONLY)
1570 {
1571 fprintf (file, "s");
1572 }
1573 }
1574 else if (letter == '&')
1575 {
1576 if (TARGET_68040_ONLY)
1577 {
1578 fprintf (file, "d");
1579 }
1580 }
1581 else if (GET_CODE (op) == REG)
1582 {
1583 if (REGNO (op) < 16
1584 && (letter == 'y' || letter == 'x')
1585 && GET_MODE (op) == DFmode)
1586 {
1587 fprintf (file, "%s:%s", reg_names[REGNO (op)],
1588 reg_names[REGNO (op)+1]);
1589 }
1590 else
1591 {
1592 fprintf (file, "%s", reg_names[REGNO (op)]);
1593 }
1594 }
1595 else if (GET_CODE (op) == MEM)
1596 {
1597 output_address (XEXP (op, 0));
1598 if (letter == 'd' && ! TARGET_68020
1599 && CONSTANT_ADDRESS_P (XEXP (op, 0))
1600 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
1601 && INTVAL (XEXP (op, 0)) < 0x8000
1602 && INTVAL (XEXP (op, 0)) >= -0x8000))
1603 {
1604 fprintf (file, ":l");
1605 }
1606 }
1607#ifdef SUPPORT_SUN_FPA
1608 else if ((letter == 'y' || letter == 'w')
64a184e9 1609 && GET_CODE (op) == CONST_DOUBLE
79e68feb
RS
1610 && (i = standard_sun_fpa_constant_p (op)))
1611 {
1612 fprintf (file, "%%%d", i & 0x1ff);
1613 }
1614#endif
1615 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
1616 {
1617 union { double d; int i[2]; } u;
1618 union { float f; int i; } u1;
1619 PRINT_OPERAND_EXTRACT_FLOAT (op);
1620 u1.f = u.d;
1621 PRINT_OPERAND_PRINT_FLOAT (letter, file);
1622 }
1623 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode)
1624 {
1625 union { double d; int i[2]; } u;
1626 PRINT_OPERAND_EXTRACT_FLOAT (op);
1627 ASM_OUTPUT_DOUBLE_OPERAND (file, u.d);
1628 }
1629 else
1630 {
cffd0d74 1631 asm_fprintf (file, "%0I"); output_addr_const (file, op);
79e68feb
RS
1632 }
1633}
1634
1635\f
1636/* A C compound statement to output to stdio stream STREAM the
1637 assembler syntax for an instruction operand that is a memory
1638 reference whose address is ADDR. ADDR is an RTL expression.
1639
1640 Note that this contains a kludge that knows that the only reason
1641 we have an address (plus (label_ref...) (reg...)) when not generating
1642 PIC code is in the insn before a tablejump, and we know that m68k.md
1643 generates a label LInnn: on such an insn.
1644
1645 It is possible for PIC to generate a (plus (label_ref...) (reg...))
1646 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
1647
1648 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
1649 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
1650 we want. This difference can be accommodated by using an assembler
1651 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
1652 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
1653 macro. See m68ksgs.h for an example; for versions without the bug.
1654
1655 They also do not like things like "pea 1.w", so we simple leave off
1656 the .w on small constants.
1657
1658 This routine is responsible for distinguishing between -fpic and -fPIC
1659 style relocations in an address. When generating -fpic code the
1660 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
1661 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
1662
1663void
1664print_operand_address (file, addr)
1665 FILE *file;
1666 rtx addr;
1667{
1668 register rtx reg1, reg2, breg, ireg;
1669 rtx offset;
1670
1671 switch (GET_CODE (addr))
1672 {
1673 case REG:
1674#ifdef MOTOROLA
1675 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
1676#else
1677 fprintf (file, "%s@", reg_names[REGNO (addr)]);
1678#endif
1679 break;
1680 case PRE_DEC:
1681#ifdef MOTOROLA
1682 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
1683#else
1684 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
1685#endif
1686 break;
1687 case POST_INC:
1688#ifdef MOTOROLA
1689 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
1690#else
1691 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
1692#endif
1693 break;
1694 case PLUS:
1695 reg1 = reg2 = ireg = breg = offset = 0;
1696 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
1697 {
1698 offset = XEXP (addr, 0);
1699 addr = XEXP (addr, 1);
1700 }
1701 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
1702 {
1703 offset = XEXP (addr, 1);
1704 addr = XEXP (addr, 0);
1705 }
1706 if (GET_CODE (addr) != PLUS)
1707 {
1708 ;
1709 }
1710 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
1711 {
1712 reg1 = XEXP (addr, 0);
1713 addr = XEXP (addr, 1);
1714 }
1715 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
1716 {
1717 reg1 = XEXP (addr, 1);
1718 addr = XEXP (addr, 0);
1719 }
1720 else if (GET_CODE (XEXP (addr, 0)) == MULT)
1721 {
1722 reg1 = XEXP (addr, 0);
1723 addr = XEXP (addr, 1);
1724 }
1725 else if (GET_CODE (XEXP (addr, 1)) == MULT)
1726 {
1727 reg1 = XEXP (addr, 1);
1728 addr = XEXP (addr, 0);
1729 }
1730 else if (GET_CODE (XEXP (addr, 0)) == REG)
1731 {
1732 reg1 = XEXP (addr, 0);
1733 addr = XEXP (addr, 1);
1734 }
1735 else if (GET_CODE (XEXP (addr, 1)) == REG)
1736 {
1737 reg1 = XEXP (addr, 1);
1738 addr = XEXP (addr, 0);
1739 }
1740 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
1741 || GET_CODE (addr) == SIGN_EXTEND)
1742 {
1743 if (reg1 == 0)
1744 {
1745 reg1 = addr;
1746 }
1747 else
1748 {
1749 reg2 = addr;
1750 }
1751 addr = 0;
1752 }
1753#if 0 /* for OLD_INDEXING */
1754 else if (GET_CODE (addr) == PLUS)
1755 {
1756 if (GET_CODE (XEXP (addr, 0)) == REG)
1757 {
1758 reg2 = XEXP (addr, 0);
1759 addr = XEXP (addr, 1);
1760 }
1761 else if (GET_CODE (XEXP (addr, 1)) == REG)
1762 {
1763 reg2 = XEXP (addr, 1);
1764 addr = XEXP (addr, 0);
1765 }
1766 }
1767#endif
1768 if (offset != 0)
1769 {
1770 if (addr != 0)
1771 {
1772 abort ();
1773 }
1774 addr = offset;
1775 }
1776 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
1777 || GET_CODE (reg1) == MULT))
1778 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
1779 {
1780 breg = reg2;
1781 ireg = reg1;
1782 }
1783 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
1784 {
1785 breg = reg1;
1786 ireg = reg2;
1787 }
1788 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
1789 && ! (flag_pic && ireg == pic_offset_table_rtx))
1790 {
1791 int scale = 1;
1792 if (GET_CODE (ireg) == MULT)
1793 {
1794 scale = INTVAL (XEXP (ireg, 1));
1795 ireg = XEXP (ireg, 0);
1796 }
1797 if (GET_CODE (ireg) == SIGN_EXTEND)
1798 {
1799#ifdef MOTOROLA
1800#ifdef SGS
1801 asm_fprintf (file, "%LLD%d(%Rpc,%s.w",
1802 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1803 reg_names[REGNO (XEXP (ireg, 0))]);
1804#else
1805 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.w",
1806 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1807 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1808 reg_names[REGNO (XEXP (ireg, 0))]);
1809#endif
1810#else
1811 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
1812 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1813 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1814 reg_names[REGNO (XEXP (ireg, 0))]);
1815#endif
1816 }
1817 else
1818 {
1819#ifdef MOTOROLA
1820#ifdef SGS
1821 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1822 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1823 reg_names[REGNO (ireg)]);
1824#else
1825 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l",
1826 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1827 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1828 reg_names[REGNO (ireg)]);
1829#endif
1830#else
1831 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1832 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1833 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1834 reg_names[REGNO (ireg)]);
1835#endif
1836 }
1837 if (scale != 1)
1838 {
1839#ifdef MOTOROLA
1840 fprintf (file, "*%d", scale);
1841#else
1842 fprintf (file, ":%d", scale);
1843#endif
1844 }
1845 putc (')', file);
1846 break;
1847 }
1848 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
1849 && ! (flag_pic && breg == pic_offset_table_rtx))
1850 {
1851#ifdef MOTOROLA
1852#ifdef SGS
1853 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1854 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1855 reg_names[REGNO (breg)]);
1856#else
1857 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l",
1858 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1859 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1860 reg_names[REGNO (breg)]);
1861#endif
1862#else
1863 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1864 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1865 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1866 reg_names[REGNO (breg)]);
1867#endif
1868 putc (')', file);
1869 break;
1870 }
1871 if (ireg != 0 || breg != 0)
1872 {
1873 int scale = 1;
1874 if (breg == 0)
1875 {
1876 abort ();
1877 }
1878 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
1879 {
1880 abort ();
1881 }
1882#ifdef MOTOROLA
1883 if (addr != 0)
1884 {
1885 output_addr_const (file, addr);
1886 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
16ab02ac 1887 fprintf (file, ".w");
79e68feb 1888 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
16ab02ac 1889 fprintf (file, ".l");
79e68feb
RS
1890 }
1891 fprintf (file, "(%s", reg_names[REGNO (breg)]);
1892 if (ireg != 0)
1893 {
1894 putc (',', file);
1895 }
1896#else
1897 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
1898 if (addr != 0)
1899 {
1900 output_addr_const (file, addr);
1901 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
1902 fprintf (file, ":w");
1903 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
1904 fprintf (file, ":l");
1905 }
1906 if (addr != 0 && ireg != 0)
1907 {
1908 putc (',', file);
1909 }
1910#endif
1911 if (ireg != 0 && GET_CODE (ireg) == MULT)
1912 {
1913 scale = INTVAL (XEXP (ireg, 1));
1914 ireg = XEXP (ireg, 0);
1915 }
1916 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
1917 {
1918#ifdef MOTOROLA
1919 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
1920#else
1921 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
1922#endif
1923 }
1924 else if (ireg != 0)
1925 {
1926#ifdef MOTOROLA
1927 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
1928#else
1929 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
1930#endif
1931 }
1932 if (scale != 1)
1933 {
1934#ifdef MOTOROLA
1935 fprintf (file, "*%d", scale);
1936#else
1937 fprintf (file, ":%d", scale);
1938#endif
1939 }
1940 putc (')', file);
1941 break;
1942 }
1943 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
1944 && ! (flag_pic && reg1 == pic_offset_table_rtx))
1945 {
1946#ifdef MOTOROLA
1947#ifdef SGS
1948 asm_fprintf (file, "%LLD%d(%Rpc,%s.l)",
1949 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1950 reg_names[REGNO (reg1)]);
1951#else
1952 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l)",
1953 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1954 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1955 reg_names[REGNO (reg1)]);
1956#endif
1957#else
1958 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
1959 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1960 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1961 reg_names[REGNO (reg1)]);
1962#endif
1963 break;
1964 }
1965 /* FALL-THROUGH (is this really what we want? */
1966 default:
1967 if (GET_CODE (addr) == CONST_INT
1968 && INTVAL (addr) < 0x8000
1969 && INTVAL (addr) >= -0x8000)
1970 {
1971#ifdef MOTOROLA
1972#ifdef SGS
1973 /* Many SGS assemblers croak on size specifiers for constants. */
1974 fprintf (file, "%d", INTVAL (addr));
1975#else
1976 fprintf (file, "%d.w", INTVAL (addr));
1977#endif
1978#else
1979 fprintf (file, "%d:w", INTVAL (addr));
1980#endif
1981 }
1982 else
1983 {
1984 output_addr_const (file, addr);
1985 }
1986 break;
1987 }
1988}