1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann (tiemann@mcc.com)
5 Currently maintained by (gcc@dg-rtp.dg.com)
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "tree.h"
35 #include "function.h"
36 #include "expr.h"
37 #include "libfuncs.h"
38 #include "c-tree.h"
39 #include "flags.h"
40 #include "recog.h"
41 #include "toplev.h"
42 #include "tm_p.h"
43 #include "target.h"
44 #include "target-def.h"
45
46 #ifdef REGISTER_PREFIX
47 const char *m88k_register_prefix = REGISTER_PREFIX;
48 #else
49 const char *m88k_register_prefix = "";
50 #endif
51 char m88k_volatile_code;
52
53 int m88k_fp_offset = 0; /* offset of frame pointer if used */
54 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
55 int m88k_case_index;
56
57 rtx m88k_compare_reg; /* cmp output pseudo register */
58 rtx m88k_compare_op0; /* cmpsi operand 0 */
59 rtx m88k_compare_op1; /* cmpsi operand 1 */
60
61 enum processor_type m88k_cpu; /* target cpu */
62
63 static void m88k_maybe_dead PARAMS ((rtx));
64 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
65 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
66
67 /* Initialize the GCC target structure. */
68 #if !defined(OBJECT_FORMAT_ELF)
69 #undef TARGET_ASM_BYTE_OP
70 #define TARGET_ASM_BYTE_OP "\tbyte\t"
71 #undef TARGET_ASM_ALIGNED_HI_OP
72 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
73 #undef TARGET_ASM_ALIGNED_SI_OP
74 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
75 #undef TARGET_ASM_UNALIGNED_HI_OP
76 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
77 #undef TARGET_ASM_UNALIGNED_SI_OP
78 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
79 #endif
80
81 #undef TARGET_ASM_FUNCTION_EPILOGUE
82 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
83
84 #undef TARGET_SCHED_ADJUST_COST
85 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
86
87 struct gcc_target targetm = TARGET_INITIALIZER;
88
89 /* Determine what instructions are needed to manufacture the integer VALUE
90 in the given MODE. */
91
92 enum m88k_instruction
classify_integer(mode,value)93 classify_integer (mode, value)
94 enum machine_mode mode;
95 register int value;
96 {
97 if (value == 0)
98 return m88k_zero;
99 else if (SMALL_INTVAL (value))
100 return m88k_or;
101 else if (SMALL_INTVAL (-value))
102 return m88k_subu;
103 else if (mode == HImode)
104 return m88k_or_lo16;
105 else if (mode == QImode)
106 return m88k_or_lo8;
107 else if (integer_ok_for_set (value))
108 return m88k_set;
109 else if ((value & 0xffff) == 0)
110 return m88k_oru_hi16;
111 else
112 return m88k_oru_or;
113 }
114
115 /* Return the bit number in a compare word corresponding to CONDITION. */
116
117 int
condition_value(condition)118 condition_value (condition)
119 rtx condition;
120 {
121 switch (GET_CODE (condition))
122 {
123 case UNORDERED:
124 return 0;
125 case ORDERED:
126 return 1;
127 case EQ:
128 return 2;
129 case NE:
130 return 3;
131 case GT:
132 return 4;
133 case LE:
134 return 5;
135 case LT:
136 return 6;
137 case GE:
138 return 7;
139 case GTU:
140 return 8;
141 case LEU:
142 return 9;
143 case LTU:
144 return 10;
145 case GEU:
146 return 11;
147 default:
148 abort ();
149 }
150 }
151
152 int
integer_ok_for_set(value)153 integer_ok_for_set (value)
154 register unsigned value;
155 {
156 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
157 a power of two or zero. */
158 register unsigned mask = (value | (value - 1));
159 return (value && POWER_OF_2_or_0 (mask + 1));
160 }
161
162 const char *
output_load_const_int(mode,operands)163 output_load_const_int (mode, operands)
164 enum machine_mode mode;
165 rtx *operands;
166 {
167 static const char *const patterns[] =
168 { "or %0,%#r0,0",
169 "or %0,%#r0,%1",
170 "subu %0,%#r0,%n1",
171 "or %0,%#r0,%h1",
172 "or %0,%#r0,%q1",
173 "set %0,%#r0,%s1",
174 "or.u %0,%#r0,%X1",
175 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
176 };
177
178 if (! REG_P (operands[0])
179 || GET_CODE (operands[1]) != CONST_INT)
180 abort ();
181 return patterns[classify_integer (mode, INTVAL (operands[1]))];
182 }
183
184 /* These next two routines assume that floating point numbers are represented
185 in a manner which is consistent between host and target machines. */
186
187 const char *
output_load_const_float(operands)188 output_load_const_float (operands)
189 rtx *operands;
190 {
191 /* These can return 0 under some circumstances when cross-compiling. */
192 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
193 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
194
195 return output_load_const_int (SImode, operands);
196 }
197
198 const char *
output_load_const_double(operands)199 output_load_const_double (operands)
200 rtx *operands;
201 {
202 rtx latehalf[2];
203
204 /* These can return zero on some cross-compilers, but there's nothing
205 we can do about it. */
206 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
207 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
208
209 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
210 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
211
212 output_asm_insn (output_load_const_int (SImode, operands), operands);
213
214 operands[0] = latehalf[0];
215 operands[1] = latehalf[1];
216
217 return output_load_const_int (SImode, operands);
218 }
219
220 const char *
output_load_const_dimode(operands)221 output_load_const_dimode (operands)
222 rtx *operands;
223 {
224 rtx latehalf[2];
225
226 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
227 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
228
229 operands[0] = operand_subword (operands[0], 0, 0, DImode);
230 operands[1] = operand_subword (operands[1], 0, 0, DImode);
231
232 output_asm_insn (output_load_const_int (SImode, operands), operands);
233
234 operands[0] = latehalf[0];
235 operands[1] = latehalf[1];
236
237 return output_load_const_int (SImode, operands);
238 }
239
240 /* Emit insns to move operands[1] into operands[0].
241
242 Return 1 if we have written out everything that needs to be done to
243 do the move. Otherwise, return 0 and the caller will emit the move
244 normally.
245
246 SCRATCH if nonzero can be used as a scratch register for the move
247 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
248
249 int
emit_move_sequence(operands,mode,scratch)250 emit_move_sequence (operands, mode, scratch)
251 rtx *operands;
252 enum machine_mode mode;
253 rtx scratch;
254 {
255 register rtx operand0 = operands[0];
256 register rtx operand1 = operands[1];
257
258 if (CONSTANT_P (operand1) && flag_pic
259 && pic_address_needs_scratch (operand1))
260 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
261
262 /* Handle most common case first: storing into a register. */
263 if (register_operand (operand0, mode))
264 {
265 if (register_operand (operand1, mode)
266 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
267 || GET_CODE (operand1) == HIGH
268 /* Only `general_operands' can come here, so MEM is ok. */
269 || GET_CODE (operand1) == MEM)
270 {
271 /* Run this case quickly. */
272 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
273 return 1;
274 }
275 }
276 else if (GET_CODE (operand0) == MEM)
277 {
278 if (register_operand (operand1, mode)
279 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
280 {
281 /* Run this case quickly. */
282 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
283 return 1;
284 }
285 if (! reload_in_progress && ! reload_completed)
286 {
287 operands[0] = validize_mem (operand0);
288 operands[1] = operand1 = force_reg (mode, operand1);
289 }
290 }
291
292 /* Simplify the source if we need to. */
293 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
294 {
295 if (GET_CODE (operand1) != CONST_INT
296 && GET_CODE (operand1) != CONST_DOUBLE)
297 {
298 rtx temp = ((reload_in_progress || reload_completed)
299 ? operand0 : 0);
300 operands[1] = legitimize_address (flag_pic
301 && symbolic_address_p (operand1),
302 operand1, temp, scratch);
303 if (mode != SImode)
304 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
305 }
306 }
307
308 /* Now have insn-emit do whatever it normally does. */
309 return 0;
310 }
311
312 /* Return a legitimate reference for ORIG (either an address or a MEM)
313 using the register REG. If PIC and the address is already
314 position-independent, use ORIG. Newly generated position-independent
315 addresses go into a reg. This is REG if nonzero, otherwise we
316 allocate register(s) as necessary. If this is called during reload,
317 and we need a second temp register, then we use SCRATCH, which is
318 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
319
320 struct rtx_def *
legitimize_address(pic,orig,reg,scratch)321 legitimize_address (pic, orig, reg, scratch)
322 int pic;
323 rtx orig;
324 rtx reg;
325 rtx scratch;
326 {
327 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
328 rtx new = orig;
329 rtx temp, insn;
330
331 if (pic)
332 {
333 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
334 {
335 if (reg == 0)
336 {
337 if (reload_in_progress || reload_completed)
338 abort ();
339 else
340 reg = gen_reg_rtx (Pmode);
341 }
342
343 if (flag_pic == 2)
344 {
345 /* If not during reload, allocate another temp reg here for
346 loading in the address, so that these instructions can be
347 optimized properly. */
348 temp = ((reload_in_progress || reload_completed)
349 ? reg : gen_reg_rtx (Pmode));
350
351 /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
352 won't get confused into thinking that these two instructions
353 are loading in the true address of the symbol. If in the
354 future a PIC rtx exists, that should be used instead. */
355 emit_insn (gen_movsi_high_pic (temp, addr));
356 emit_insn (gen_movsi_lo_sum_pic (temp, temp, addr));
357 addr = temp;
358 }
359
360 new = gen_rtx_MEM (Pmode,
361 gen_rtx_PLUS (SImode,
362 pic_offset_table_rtx, addr));
363
364 current_function_uses_pic_offset_table = 1;
365 RTX_UNCHANGING_P (new) = 1;
366 insn = emit_move_insn (reg, new);
367 /* Put a REG_EQUAL note on this insn, so that it can be optimized
368 by loop. */
369 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
370 REG_NOTES (insn));
371 new = reg;
372 }
373 else if (GET_CODE (addr) == CONST)
374 {
375 rtx base;
376
377 if (GET_CODE (XEXP (addr, 0)) == PLUS
378 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
379 return orig;
380
381 if (reg == 0)
382 {
383 if (reload_in_progress || reload_completed)
384 abort ();
385 else
386 reg = gen_reg_rtx (Pmode);
387 }
388
389 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
390
391 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
392 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
393 base == reg ? 0 : reg, 0);
394
395 if (GET_CODE (addr) == CONST_INT)
396 {
397 if (ADD_INT (addr))
398 return plus_constant (base, INTVAL (addr));
399 else if (! reload_in_progress && ! reload_completed)
400 addr = force_reg (Pmode, addr);
401 /* We can't create any new registers during reload, so use the
402 SCRATCH reg provided by the reload_insi pattern. */
403 else if (scratch)
404 {
405 emit_move_insn (scratch, addr);
406 addr = scratch;
407 }
408 else
409 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
410 macro needs to be adjusted so that a scratch reg is provided
411 for this address. */
412 abort ();
413 }
414 new = gen_rtx_PLUS (SImode, base, addr);
415 /* Should we set special REG_NOTEs here? */
416 }
417 }
418 else
419 {
420 if (reg == 0)
421 {
422 if (reload_in_progress || reload_completed)
423 abort ();
424 else
425 reg = gen_reg_rtx (Pmode);
426 }
427
428 emit_insn (gen_rtx_SET (VOIDmode,
429 reg, gen_rtx_HIGH (SImode, addr)));
430 new = gen_rtx_LO_SUM (SImode, reg, addr);
431 }
432
433 if (GET_CODE (orig) == MEM)
434 {
435 new = gen_rtx_MEM (GET_MODE (orig), new);
436 MEM_COPY_ATTRIBUTES (new, orig);
437 }
438 return new;
439 }
440
441 /* Support functions for code to emit a block move. There are four methods
442 used to perform the block move:
443 + call memcpy
444 + call the looping library function, e.g. __movstrSI64n8
445 + call a non-looping library function, e.g. __movstrHI15x11
446 + produce an inline sequence of ld/st instructions
447
448 The parameters below describe the library functions produced by
449 movstr-m88k.sh. */
450
451 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
452 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
453 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
454 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
455 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
456 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
457 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
458 __movstrSI46x46 .. __movstrSI46x10,
459 __movstrSI45x45 .. __movstrSI45x9 */
460 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
461 __movstrDI46x46 .. __movstrDI46x22,
462 __movstrDI45x45 .. __movstrDI45x21,
463 __movstrDI44x44 .. __movstrDI44x20,
464 __movstrDI43x43 .. __movstrDI43x19,
465 __movstrDI42x42 .. __movstrDI42x18,
466 __movstrDI41x41 .. __movstrDI41x17 */
467
468 /* Limits for using the non-looping movstr functions. For the m88100
469 processor, we assume the source and destination are word aligned.
470 The QImode and HImode limits are the break even points where memcpy
471 does just as well and beyond which memcpy does better. For the
472 m88110, we tend to assume double word alignment, but also analyze
473 the word aligned cases. The analysis is complicated because memcpy
474 may use the cache control instructions for better performance. */
475
476 #define MOVSTR_QI_LIMIT_88100 13
477 #define MOVSTR_HI_LIMIT_88100 38
478 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
479 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
480
481 #define MOVSTR_QI_LIMIT_88000 16
482 #define MOVSTR_HI_LIMIT_88000 38
483 #define MOVSTR_SI_LIMIT_88000 72
484 #define MOVSTR_DI_LIMIT_88000 72
485
486 #define MOVSTR_QI_LIMIT_88110 16
487 #define MOVSTR_HI_LIMIT_88110 38
488 #define MOVSTR_SI_LIMIT_88110 72
489 #define MOVSTR_DI_LIMIT_88110 72
490
491 static const enum machine_mode mode_from_align[] =
492 {VOIDmode, QImode, HImode, VOIDmode, SImode,
493 VOIDmode, VOIDmode, VOIDmode, DImode};
494 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
495 0, 0, 0, MOVSTR_DI};
496 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
497 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
498
499 static const int best_from_align[3][9] = {
500 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
501 0, 0, 0, MOVSTR_DI_LIMIT_88100},
502 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
503 0, 0, 0, MOVSTR_DI_LIMIT_88110},
504 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
505 0, 0, 0, MOVSTR_DI_LIMIT_88000}
506 };
507
508 #if 0
509 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
510 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
511 #endif
512 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
513 static void output_short_branch_defs PARAMS ((FILE *));
514
515 /* Emit code to perform a block move. Choose the best method.
516
517 OPERANDS[0] is the destination.
518 OPERANDS[1] is the source.
519 OPERANDS[2] is the size.
520 OPERANDS[3] is the alignment safe to use. */
521
522 void
expand_block_move(dest_mem,src_mem,operands)523 expand_block_move (dest_mem, src_mem, operands)
524 rtx dest_mem;
525 rtx src_mem;
526 rtx *operands;
527 {
528 int align = INTVAL (operands[3]);
529 int constp = (GET_CODE (operands[2]) == CONST_INT);
530 int bytes = (constp ? INTVAL (operands[2]) : 0);
531 #if 0
532 int target = (int) m88k_cpu;
533 #endif
534
535 if (constp && bytes <= 0)
536 return;
537
538 /* Determine machine mode to do move with. */
539 if (align > 4 && !TARGET_88110)
540 align = 4;
541 else if (align <= 0 || align == 3)
542 abort (); /* block move invalid alignment. */
543
544 if (constp && bytes <= 3 * align)
545 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
546 bytes, align, 0);
547
548 #if 0
549 else if (constp && bytes <= best_from_align[target][align] && !TARGET_MEMCPY)
550 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
551 bytes, align);
552
553 else if (constp && align == 4 && TARGET_88100 && !TARGET_MEMCPY)
554 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
555 bytes, align);
556 #endif
557
558 else
559 {
560 #ifdef TARGET_MEM_FUNCTIONS
561 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
562 VOIDmode, 3,
563 operands[0], Pmode,
564 operands[1], Pmode,
565 convert_to_mode (TYPE_MODE (sizetype), operands[2],
566 TREE_UNSIGNED (sizetype)),
567 TYPE_MODE (sizetype));
568 #else
569 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
570 VOIDmode, 3,
571 operands[1], Pmode,
572 operands[0], Pmode,
573 convert_to_mode (TYPE_MODE (integer_type_node),
574 operands[2],
575 TREE_UNSIGNED (integer_type_node)),
576 TYPE_MODE (integer_type_node));
577 #endif
578 }
579 }
580
581 #if 0
582 /* Emit code to perform a block move by calling a looping movstr library
583 function. SIZE and ALIGN are known constants. DEST and SRC are
584 registers. */
585
586 static void
587 block_move_loop (dest, dest_mem, src, src_mem, size, align)
588 rtx dest, dest_mem;
589 rtx src, src_mem;
590 int size;
591 int align;
592 {
593 enum machine_mode mode;
594 int count;
595 int units;
596 int remainder;
597 rtx offset_rtx;
598 rtx value_rtx;
599 char entry[30];
600 tree entry_name;
601
602 /* Determine machine mode to do move with. */
603 if (align != 4)
604 abort ();
605
606 /* Determine the structure of the loop. */
607 count = size / MOVSTR_LOOP;
608 units = (size - count * MOVSTR_LOOP) / align;
609
610 if (units < 2)
611 {
612 count--;
613 units += MOVSTR_LOOP / align;
614 }
615
616 if (count <= 0)
617 {
618 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
619 return;
620 }
621
622 remainder = size - count * MOVSTR_LOOP - units * align;
623
624 mode = mode_from_align[align];
625 sprintf (entry, "__movstr%s%dn%d",
626 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
627 entry_name = get_identifier (entry);
628
629 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
630
631 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
632 gen_rtx_PLUS (Pmode,
633 gen_rtx_REG (Pmode, 3),
634 offset_rtx));
635 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
636
637 emit_insn (gen_call_movstrsi_loop
638 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
639 dest, src, offset_rtx, value_rtx,
640 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
641 GEN_INT (count)));
642
643 if (remainder)
644 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
645 gen_rtx_REG (Pmode, 3), src_mem,
646 remainder, align, MOVSTR_LOOP + align);
647 }
648
649 /* Emit code to perform a block move by calling a non-looping library
650 function. SIZE and ALIGN are known constants. DEST and SRC are
651 registers. OFFSET is the known starting point for the output pattern. */
652
653 static void
654 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
655 rtx dest, dest_mem;
656 rtx src, src_mem;
657 int size;
658 int align;
659 {
660 enum machine_mode mode = mode_from_align[align];
661 int units = size / align;
662 int remainder = size - units * align;
663 int most;
664 int value_reg;
665 rtx offset_rtx;
666 rtx value_rtx;
667 char entry[30];
668 tree entry_name;
669
670 if (remainder && size <= all_from_align[align])
671 {
672 most = all_from_align[align] - (align - remainder);
673 remainder = 0;
674 }
675 else
676 {
677 most = max_from_align[align];
678 }
679
680 sprintf (entry, "__movstr%s%dx%d",
681 GET_MODE_NAME (mode), most, size - remainder);
682 entry_name = get_identifier (entry);
683
684 offset_rtx = GEN_INT (most - (size - remainder));
685
686 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
687 gen_rtx_PLUS (Pmode,
688 gen_rtx_REG (Pmode, 3),
689 offset_rtx));
690
691 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
692
693 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
694 ? (mode == DImode ? 6 : 5) : 4);
695
696 if (mode == DImode)
697 {
698 emit_insn (gen_call_block_move_DI
699 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
700 dest, src, offset_rtx, value_rtx,
701 gen_rtx_REG (mode, value_reg)));
702 }
703 else
704 {
705 emit_insn (gen_call_block_move
706 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
707 dest, src, offset_rtx, value_rtx,
708 gen_rtx_REG (mode, value_reg)));
709 }
710
711 if (remainder)
712 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
713 gen_rtx_REG (Pmode, 3), src_mem,
714 remainder, align, most);
715 }
716 #endif
717
718 /* Emit code to perform a block move with an offset sequence of ld/st
719 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
720 known constants. DEST and SRC are registers. OFFSET is the known
721 starting point for the output pattern. */
722
723 static void
block_move_sequence(dest,dest_mem,src,src_mem,size,align,offset)724 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
725 rtx dest, dest_mem;
726 rtx src, src_mem;
727 int size;
728 int align;
729 int offset;
730 {
731 rtx temp[2];
732 enum machine_mode mode[2];
733 int amount[2];
734 int active[2];
735 int phase = 0;
736 int next;
737 int offset_ld = offset;
738 int offset_st = offset;
739
740 active[0] = active[1] = FALSE;
741
742 /* Establish parameters for the first load and for the second load if
743 it is known to be the same mode as the first. */
744 amount[0] = amount[1] = align;
745 mode[0] = mode_from_align[align];
746 temp[0] = gen_reg_rtx (mode[0]);
747 if (size >= 2 * align)
748 {
749 mode[1] = mode[0];
750 temp[1] = gen_reg_rtx (mode[1]);
751 }
752
753 do
754 {
755 next = phase;
756 phase = !phase;
757
758 if (size > 0)
759 {
760 /* Change modes as the sequence tails off. */
761 if (size < amount[next])
762 {
763 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
764 mode[next] = mode_from_align[amount[next]];
765 temp[next] = gen_reg_rtx (mode[next]);
766 }
767 size -= amount[next];
768 emit_move_insn (temp[next],
769 adjust_address (src_mem, mode[next], offset_ld));
770 offset_ld += amount[next];
771 active[next] = TRUE;
772 }
773
774 if (active[phase])
775 {
776 active[phase] = FALSE;
777 emit_move_insn (adjust_address (dest_mem, mode[phase], offset_st),
778 temp[phase]);
779 offset_st += amount[phase];
780 }
781 }
782 while (active[next]);
783 }
784
785 /* Emit the code to do an AND operation. */
786
787 const char *
output_and(operands)788 output_and (operands)
789 rtx operands[];
790 {
791 unsigned int value;
792
793 if (REG_P (operands[2]))
794 return "and %0,%1,%2";
795
796 value = INTVAL (operands[2]);
797 if (SMALL_INTVAL (value))
798 return "mask %0,%1,%2";
799 else if ((value & 0xffff0000) == 0xffff0000)
800 return "and %0,%1,%x2";
801 else if ((value & 0xffff) == 0xffff)
802 return "and.u %0,%1,%X2";
803 else if ((value & 0xffff) == 0)
804 return "mask.u %0,%1,%X2";
805 else if (integer_ok_for_set (~value))
806 return "clr %0,%1,%S2";
807 else
808 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
809 }
810
811 /* Emit the code to do an inclusive OR operation. */
812
813 const char *
output_ior(operands)814 output_ior (operands)
815 rtx operands[];
816 {
817 unsigned int value;
818
819 if (REG_P (operands[2]))
820 return "or %0,%1,%2";
821
822 value = INTVAL (operands[2]);
823 if (SMALL_INTVAL (value))
824 return "or %0,%1,%2";
825 else if ((value & 0xffff) == 0)
826 return "or.u %0,%1,%X2";
827 else if (integer_ok_for_set (value))
828 return "set %0,%1,%s2";
829 else
830 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
831 }
832
833 /* Emit the instructions for doing an XOR. */
834
835 const char *
output_xor(operands)836 output_xor (operands)
837 rtx operands[];
838 {
839 unsigned int value;
840
841 if (REG_P (operands[2]))
842 return "xor %0,%1,%2";
843
844 value = INTVAL (operands[2]);
845 if (SMALL_INTVAL (value))
846 return "xor %0,%1,%2";
847 else if ((value & 0xffff) == 0)
848 return "xor.u %0,%1,%X2";
849 else
850 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
851 }
852
853 /* Output a call. Normally this is just bsr or jsr, but this also deals with
854 accomplishing a branch after the call by incrementing r1. This requires
855 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
856 requires that forward references not occur when computing the difference of
857 two labels. The [version?] Motorola assembler computes a word difference.
858 No doubt there's more to come!
859
860 It would seem the same idea could be used to tail call, but in this case,
861 the epilogue will be non-null. */
862
863 static rtx sb_name = 0;
864 static rtx sb_high = 0;
865 static rtx sb_low = 0;
866
867 const char *
output_call(operands,addr)868 output_call (operands, addr)
869 rtx operands[];
870 rtx addr;
871 {
872 operands[0] = addr;
873 if (final_sequence)
874 {
875 rtx jump;
876 rtx seq_insn;
877
878 /* This can be generalized, but there is currently no need. */
879 if (XVECLEN (final_sequence, 0) != 2)
880 abort ();
881
882 /* The address of interior insns is not computed, so use the sequence. */
883 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
884 jump = XVECEXP (final_sequence, 0, 1);
885 if (GET_CODE (jump) == JUMP_INSN)
886 {
887 #ifndef USE_GAS
888 rtx low, high;
889 #endif
890 const char *last;
891 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
892 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
893 - INSN_ADDRESSES (INSN_UID (seq_insn))
894 - 2);
895
896 /* Delete the jump. */
897 PUT_CODE (jump, NOTE);
898 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
899 NOTE_SOURCE_FILE (jump) = 0;
900
901 /* We only do this optimization if -O2, modifying the value of
902 r1 in the delay slot confuses debuggers and profilers on some
903 systems.
904
905 If we loose, we must use the non-delay form. This is unlikely
906 to ever happen. If it becomes a problem, claim that a call
907 has two delay slots and only the second can be filled with
908 a jump.
909
910 The 88110 can lose when a jsr.n r1 is issued and a page fault
911 occurs accessing the delay slot. So don't use jsr.n form when
912 jumping thru r1.
913 */
914 if (optimize < 2
915 || ! ADD_INTVAL (delta)
916 || (REG_P (addr) && REGNO (addr) == 1))
917 {
918 operands[1] = dest;
919 return (REG_P (addr)
920 ? "jsr %0\n\tbr %l1"
921 : (flag_pic
922 ? "bsr %0#plt\n\tbr %l1"
923 : "bsr %0\n\tbr %l1"));
924 }
925
926 /* Output the short branch form. */
927 output_asm_insn ((REG_P (addr)
928 ? "jsr.n %0"
929 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
930 operands);
931
932 #ifdef USE_GAS
933 last = (delta < 0
934 ? "subu %#r1,%#r1,.-%l0+4"
935 : "addu %#r1,%#r1,%l0-.-4");
936 operands[0] = dest;
937 #else
938 operands[0] = gen_label_rtx ();
939 operands[1] = gen_label_rtx ();
940 if (delta < 0)
941 {
942 low = dest;
943 high = operands[1];
944 last = "subu %#r1,%#r1,%l0\n%l1:";
945 }
946 else
947 {
948 low = operands[1];
949 high = dest;
950 last = "addu %#r1,%#r1,%l0\n%l1:";
951 }
952
953 /* Record the values to be computed later as "def name,high-low". */
954 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
955 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
956 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
957 #endif /* Don't USE_GAS */
958
959 return last;
960 }
961 }
962 return (REG_P (addr)
963 ? "jsr%. %0"
964 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
965 }
966
967 static void
output_short_branch_defs(stream)968 output_short_branch_defs (stream)
969 FILE *stream;
970 {
971 char name[256], high[256], low[256];
972
973 for (; sb_name && sb_high && sb_low;
974 sb_name = XEXP (sb_name, 1),
975 sb_high = XEXP (sb_high, 1),
976 sb_low = XEXP (sb_low, 1))
977 {
978 ASM_GENERATE_INTERNAL_LABEL
979 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
980 ASM_GENERATE_INTERNAL_LABEL
981 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
982 ASM_GENERATE_INTERNAL_LABEL
983 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
984 /* This will change as the assembler requirements become known. */
985 fprintf (stream, "%s%s,%s-%s\n",
986 SET_ASM_OP, &name[1], &high[1], &low[1]);
987 }
988 if (sb_name || sb_high || sb_low)
989 abort ();
990 }
991
992 /* Return truth value of the statement that this conditional branch is likely
993 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
994
995 int
mostly_false_jump(jump_insn,condition)996 mostly_false_jump (jump_insn, condition)
997 rtx jump_insn, condition;
998 {
999 rtx target_label = JUMP_LABEL (jump_insn);
1000 rtx insnt, insnj;
1001
1002 /* Much of this isn't computed unless we're optimizing. */
1003 if (optimize == 0)
1004 return 0;
1005
1006 /* Determine if one path or the other leads to a return. */
1007 for (insnt = NEXT_INSN (target_label);
1008 insnt;
1009 insnt = NEXT_INSN (insnt))
1010 {
1011 if (GET_CODE (insnt) == JUMP_INSN)
1012 break;
1013 else if (GET_CODE (insnt) == INSN
1014 && GET_CODE (PATTERN (insnt)) == SEQUENCE
1015 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1016 {
1017 insnt = XVECEXP (PATTERN (insnt), 0, 0);
1018 break;
1019 }
1020 }
1021 if (insnt
1022 && (GET_CODE (PATTERN (insnt)) == RETURN
1023 || (GET_CODE (PATTERN (insnt)) == SET
1024 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1025 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1026 insnt = 0;
1027
1028 for (insnj = NEXT_INSN (jump_insn);
1029 insnj;
1030 insnj = NEXT_INSN (insnj))
1031 {
1032 if (GET_CODE (insnj) == JUMP_INSN)
1033 break;
1034 else if (GET_CODE (insnj) == INSN
1035 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1036 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1037 {
1038 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1039 break;
1040 }
1041 }
1042 if (insnj
1043 && (GET_CODE (PATTERN (insnj)) == RETURN
1044 || (GET_CODE (PATTERN (insnj)) == SET
1045 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1046 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1047 insnj = 0;
1048
1049 /* Predict to not return. */
1050 if ((insnt == 0) != (insnj == 0))
1051 return (insnt == 0);
1052
1053 /* Predict loops to loop. */
1054 for (insnt = PREV_INSN (target_label);
1055 insnt && GET_CODE (insnt) == NOTE;
1056 insnt = PREV_INSN (insnt))
1057 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1058 return 1;
1059 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1060 return 0;
1061 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1062 return 0;
1063
1064 /* Predict backward branches usually take. */
1065 if (final_sequence)
1066 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1067 else
1068 insnj = jump_insn;
1069 if (INSN_ADDRESSES (INSN_UID (insnj))
1070 > INSN_ADDRESSES (INSN_UID (target_label)))
1071 return 0;
1072
1073 /* EQ tests are usually false and NE tests are usually true. Also,
1074 most quantities are positive, so we can make the appropriate guesses
1075 about signed comparisons against zero. Consider unsigned comparisons
1076 to be a range check and assume quantities to be in range. */
1077 switch (GET_CODE (condition))
1078 {
1079 case CONST_INT:
1080 /* Unconditional branch. */
1081 return 0;
1082 case EQ:
1083 return 1;
1084 case NE:
1085 return 0;
1086 case LE:
1087 case LT:
1088 case GEU:
1089 case GTU: /* Must get casesi right at least. */
1090 if (XEXP (condition, 1) == const0_rtx)
1091 return 1;
1092 break;
1093 case GE:
1094 case GT:
1095 case LEU:
1096 case LTU:
1097 if (XEXP (condition, 1) == const0_rtx)
1098 return 0;
1099 break;
1100 default:
1101 break;
1102 }
1103
1104 return 0;
1105 }
1106
1107 /* Return true if the operand is a power of two and is a floating
1108 point type (to optimize division by power of two into multiplication). */
1109
1110 int
real_power_of_2_operand(op,mode)1111 real_power_of_2_operand (op, mode)
1112 rtx op;
1113 enum machine_mode mode ATTRIBUTE_UNUSED;
1114 {
1115 REAL_VALUE_TYPE d;
1116 union {
1117 long l[2];
1118 struct { /* IEEE double precision format */
1119 unsigned sign : 1;
1120 unsigned exponent : 11;
1121 unsigned mantissa1 : 20;
1122 unsigned mantissa2;
1123 } s;
1124 struct { /* IEEE double format to quick check */
1125 unsigned sign : 1; /* if it fits in a float */
1126 unsigned exponent1 : 4;
1127 unsigned exponent2 : 7;
1128 unsigned mantissa1 : 20;
1129 unsigned mantissa2;
1130 } s2;
1131 } u;
1132
1133 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1134 return 0;
1135
1136 if (GET_CODE (op) != CONST_DOUBLE)
1137 return 0;
1138
1139 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1140 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
1141
1142 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1143 || u.s.exponent == 0 /* constant 0.0 */
1144 || u.s.exponent == 0x7ff /* NAN */
1145 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1146 return 0; /* const won't fit in float */
1147
1148 return 1;
1149 }
1150
1151 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1152 operands, putting them in registers and making CONST_DOUBLE values
1153 SFmode where possible. */
1154
1155 struct rtx_def *
legitimize_operand(op,mode)1156 legitimize_operand (op, mode)
1157 rtx op;
1158 enum machine_mode mode;
1159 {
1160 rtx temp;
1161 REAL_VALUE_TYPE r;
1162 union {
1163 long l[2];
1164 struct { /* IEEE double precision format */
1165 unsigned sign : 1;
1166 unsigned exponent : 11;
1167 unsigned mantissa1 : 20;
1168 unsigned mantissa2;
1169 } d;
1170 struct { /* IEEE double format to quick check */
1171 unsigned sign : 1; /* if it fits in a float */
1172 unsigned exponent1 : 4;
1173 unsigned exponent2 : 7;
1174 unsigned mantissa1 : 20;
1175 unsigned mantissa2;
1176 } s;
1177 } u;
1178
1179 if (GET_CODE (op) == REG || mode != DFmode)
1180 return op;
1181
1182 if (GET_CODE (op) == CONST_DOUBLE)
1183 {
1184 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1185 REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
1186 if (u.d.exponent != 0x7ff /* NaN */
1187 && u.d.mantissa2 == 0 /* Mantissa fits */
1188 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1189 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1190 op, mode)) != 0)
1191 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1192 }
1193 else if (register_operand (op, mode))
1194 return op;
1195
1196 return force_reg (mode, op);
1197 }
1198
1199 /* Return true if OP is a suitable input for a move insn. */
1200
1201 int
move_operand(op,mode)1202 move_operand (op, mode)
1203 rtx op;
1204 enum machine_mode mode;
1205 {
1206 if (register_operand (op, mode))
1207 return 1;
1208 if (GET_CODE (op) == CONST_INT)
1209 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1210 if (GET_MODE (op) != mode)
1211 return 0;
1212 if (GET_CODE (op) == SUBREG)
1213 op = SUBREG_REG (op);
1214 if (GET_CODE (op) != MEM)
1215 return 0;
1216
1217 op = XEXP (op, 0);
1218 if (GET_CODE (op) == LO_SUM)
1219 return (REG_P (XEXP (op, 0))
1220 && symbolic_address_p (XEXP (op, 1)));
1221 return memory_address_p (mode, op);
1222 }
1223
1224 /* Return true if OP is suitable for a call insn. */
1225
1226 int
call_address_operand(op,mode)1227 call_address_operand (op, mode)
1228 rtx op;
1229 enum machine_mode mode ATTRIBUTE_UNUSED;
1230 {
1231 return (REG_P (op) || symbolic_address_p (op));
1232 }
1233
1234 /* Returns true if OP is either a symbol reference or a sum of a symbol
1235 reference and a constant. */
1236
1237 int
symbolic_address_p(op)1238 symbolic_address_p (op)
1239 register rtx op;
1240 {
1241 switch (GET_CODE (op))
1242 {
1243 case SYMBOL_REF:
1244 case LABEL_REF:
1245 return 1;
1246
1247 case CONST:
1248 op = XEXP (op, 0);
1249 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1250 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1251 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1252
1253 default:
1254 return 0;
1255 }
1256 }
1257
1258 /* Return true if OP is a register or const0_rtx. */
1259
1260 int
reg_or_0_operand(op,mode)1261 reg_or_0_operand (op, mode)
1262 rtx op;
1263 enum machine_mode mode;
1264 {
1265 return (op == const0_rtx || register_operand (op, mode));
1266 }
1267
1268 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1269
1270 int
arith_operand(op,mode)1271 arith_operand (op, mode)
1272 rtx op;
1273 enum machine_mode mode;
1274 {
1275 return (register_operand (op, mode)
1276 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1277 }
1278
1279 /* Return true if OP is a register or 5 bit integer. */
1280
1281 int
arith5_operand(op,mode)1282 arith5_operand (op, mode)
1283 rtx op;
1284 enum machine_mode mode;
1285 {
1286 return (register_operand (op, mode)
1287 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1288 }
1289
1290 int
arith32_operand(op,mode)1291 arith32_operand (op, mode)
1292 rtx op;
1293 enum machine_mode mode;
1294 {
1295 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1296 }
1297
1298 int
arith64_operand(op,mode)1299 arith64_operand (op, mode)
1300 rtx op;
1301 enum machine_mode mode;
1302 {
1303 return (register_operand (op, mode)
1304 || GET_CODE (op) == CONST_INT
1305 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1306 }
1307
1308 int
int5_operand(op,mode)1309 int5_operand (op, mode)
1310 rtx op;
1311 enum machine_mode mode ATTRIBUTE_UNUSED;
1312 {
1313 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1314 }
1315
1316 int
int32_operand(op,mode)1317 int32_operand (op, mode)
1318 rtx op;
1319 enum machine_mode mode ATTRIBUTE_UNUSED;
1320 {
1321 return (GET_CODE (op) == CONST_INT);
1322 }
1323
1324 /* Return true if OP is a register or a valid immediate operand for
1325 addu or subu. */
1326
1327 int
add_operand(op,mode)1328 add_operand (op, mode)
1329 rtx op;
1330 enum machine_mode mode;
1331 {
1332 return (register_operand (op, mode)
1333 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1334 }
1335
1336 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1337 shift left combinations into a single mak instruction. */
1338
1339 int
mak_mask_p(value)1340 mak_mask_p (value)
1341 int value;
1342 {
1343 return (value && POWER_OF_2_or_0 (value + 1));
1344 }
1345
1346 int
reg_or_bbx_mask_operand(op,mode)1347 reg_or_bbx_mask_operand (op, mode)
1348 rtx op;
1349 enum machine_mode mode;
1350 {
1351 int value;
1352 if (register_operand (op, mode))
1353 return 1;
1354 if (GET_CODE (op) != CONST_INT)
1355 return 0;
1356
1357 value = INTVAL (op);
1358 if (POWER_OF_2 (value))
1359 return 1;
1360
1361 return 0;
1362 }
1363
1364 /* Return true if OP is valid to use in the context of a floating
1365 point operation. Special case 0.0, since we can use r0. */
1366
1367 int
real_or_0_operand(op,mode)1368 real_or_0_operand (op, mode)
1369 rtx op;
1370 enum machine_mode mode;
1371 {
1372 if (mode != SFmode && mode != DFmode)
1373 return 0;
1374
1375 return (register_operand (op, mode)
1376 || (GET_CODE (op) == CONST_DOUBLE
1377 && op == CONST0_RTX (mode)));
1378 }
1379
1380 /* Return true if OP is valid to use in the context of logic arithmetic
1381 on condition codes. */
1382
1383 int
partial_ccmode_register_operand(op,mode)1384 partial_ccmode_register_operand (op, mode)
1385 rtx op;
1386 enum machine_mode mode ATTRIBUTE_UNUSED;
1387 {
1388 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1389 }
1390
1391 /* Return true if OP is a relational operator. */
1392
1393 int
relop(op,mode)1394 relop (op, mode)
1395 rtx op;
1396 enum machine_mode mode ATTRIBUTE_UNUSED;
1397 {
1398 switch (GET_CODE (op))
1399 {
1400 case EQ:
1401 case NE:
1402 case LT:
1403 case LE:
1404 case GE:
1405 case GT:
1406 case LTU:
1407 case LEU:
1408 case GEU:
1409 case GTU:
1410 return 1;
1411 default:
1412 return 0;
1413 }
1414 }
1415
1416 int
even_relop(op,mode)1417 even_relop (op, mode)
1418 rtx op;
1419 enum machine_mode mode ATTRIBUTE_UNUSED;
1420 {
1421 switch (GET_CODE (op))
1422 {
1423 case EQ:
1424 case LT:
1425 case GT:
1426 case LTU:
1427 case GTU:
1428 return 1;
1429 default:
1430 return 0;
1431 }
1432 }
1433
1434 int
odd_relop(op,mode)1435 odd_relop (op, mode)
1436 rtx op;
1437 enum machine_mode mode ATTRIBUTE_UNUSED;
1438 {
1439 switch (GET_CODE (op))
1440 {
1441 case NE:
1442 case LE:
1443 case GE:
1444 case LEU:
1445 case GEU:
1446 return 1;
1447 default:
1448 return 0;
1449 }
1450 }
1451
1452 /* Return true if OP is a relational operator, and is not an unsigned
1453 relational operator. */
1454
1455 int
relop_no_unsigned(op,mode)1456 relop_no_unsigned (op, mode)
1457 rtx op;
1458 enum machine_mode mode ATTRIBUTE_UNUSED;
1459 {
1460 switch (GET_CODE (op))
1461 {
1462 case EQ:
1463 case NE:
1464 case LT:
1465 case LE:
1466 case GE:
1467 case GT:
1468 /* @@ What is this test doing? Why not use `mode'? */
1469 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1470 || GET_MODE (op) == DImode
1471 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1472 || GET_MODE (XEXP (op, 0)) == DImode
1473 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1474 || GET_MODE (XEXP (op, 1)) == DImode)
1475 return 0;
1476 return 1;
1477 default:
1478 return 0;
1479 }
1480 }
1481
1482 /* Return true if the code of this rtx pattern is EQ or NE. */
1483
1484 int
equality_op(op,mode)1485 equality_op (op, mode)
1486 rtx op;
1487 enum machine_mode mode ATTRIBUTE_UNUSED;
1488 {
1489 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1490 }
1491
1492 /* Return true if the code of this rtx pattern is pc or label_ref. */
1493
1494 int
pc_or_label_ref(op,mode)1495 pc_or_label_ref (op, mode)
1496 rtx op;
1497 enum machine_mode mode ATTRIBUTE_UNUSED;
1498 {
1499 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1500 }
1501
1502 /* Output to FILE the start of the assembler file. */
1503
1504 void
output_file_start(file)1505 output_file_start (file)
1506 FILE *file;
1507 {
1508 if (TARGET_88110)
1509 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1510
1511 output_file_directive (file, main_input_filename);
1512 }
1513
1514 #ifndef OBJECT_FORMAT_ELF
1515 /* Output an ascii string. */
1516
1517 void
output_ascii(file,opcode,max,p,size)1518 output_ascii (file, opcode, max, p, size)
1519 FILE *file;
1520 const char *opcode;
1521 int max;
1522 const char *p;
1523 int size;
1524 {
1525 int i;
1526 int in_escape = 0;
1527
1528 register int num = 0;
1529
1530 fprintf (file, "%s\"", opcode);
1531 for (i = 0; i < size; i++)
1532 {
1533 register int c = (unsigned char) p[i];
1534
1535 if (num > max)
1536 {
1537 fprintf (file, "\"\n%s\"", opcode);
1538 num = 0;
1539 }
1540
1541 if (c == '\"' || c == '\\')
1542 {
1543 escape:
1544 putc ('\\', file);
1545 putc (c, file);
1546 num += 2;
1547 in_escape = 0;
1548 }
1549 else if (in_escape && ISDIGIT (c))
1550 {
1551 /* If a digit follows an octal-escape, the VAX assembler fails
1552 to stop reading the escape after three digits. Continue to
1553 output the values as an octal-escape until a non-digit is
1554 found. */
1555 fprintf (file, "\\%03o", c);
1556 num += 4;
1557 }
1558 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1559 {
1560 putc (c, file);
1561 num++;
1562 in_escape = 0;
1563 }
1564 else
1565 {
1566 switch (c)
1567 {
1568 /* Some assemblers can't handle \a, \v, or \?. */
1569 case '\f': c = 'f'; goto escape;
1570 case '\b': c = 'b'; goto escape;
1571 case '\r': c = 'r'; goto escape;
1572 case '\n': c = 'n'; goto escape;
1573 }
1574
1575 fprintf (file, "\\%03o", c);
1576 num += 4;
1577 in_escape = 1;
1578 }
1579 }
1580 fprintf (file, "\"\n");
1581 }
1582 #endif
1583
1584 /* Output a label (allows insn-output.c to be compiled without including
1585 m88k.c or needing to include stdio.h). */
1586
1587 void
output_label(label_number)1588 output_label (label_number)
1589 int label_number;
1590 {
1591 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1592 }
1593
1594 /* Generate the assembly code for function entry.
1595
1596 The prologue is responsible for setting up the stack frame,
1597 initializing the frame pointer register, saving registers that must be
1598 saved, and allocating SIZE additional bytes of storage for the
1599 local variables. SIZE is an integer. FILE is a stdio
1600 stream to which the assembler code should be output.
1601
1602 The label for the beginning of the function need not be output by this
1603 macro. That has already been done when the macro is run.
1604
1605 To determine which registers to save, the macro can refer to the array
1606 `regs_ever_live': element R is nonzero if hard register
1607 R is used anywhere within the function. This implies the
1608 function prologue should save register R, but not if it is one
1609 of the call-used registers.
1610
1611 On machines where functions may or may not have frame-pointers, the
1612 function entry code must vary accordingly; it must set up the frame
1613 pointer if one is wanted, and not otherwise. To determine whether a
1614 frame pointer is in wanted, the macro can refer to the variable
1615 `frame_pointer_needed'. The variable's value will be 1 at run
1616 time in a function that needs a frame pointer.
1617
1618 On machines where an argument may be passed partly in registers and
1619 partly in memory, this macro must examine the variable
1620 `current_function_pretend_args_size', and allocate that many bytes
1621 of uninitialized space on the stack just underneath the first argument
1622 arriving on the stack. (This may not be at the very end of the stack,
1623 if the calling sequence has pushed anything else since pushing the stack
1624 arguments. But usually, on such machines, nothing else has been pushed
1625 yet, because the function prologue itself does all the pushing.)
1626
1627 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1628 `current_function_outgoing_args_size' contains the size in bytes
1629 required for the outgoing arguments. This macro must add that
1630 amount of uninitialized space to very bottom of the stack.
1631
1632 The stack frame we use looks like this:
1633
1634 caller callee
1635 |==============================================|
1636 | caller's frame |
1637 |==============================================|
1638 | [caller's outgoing memory arguments] |
1639 sp -> |==============================================| <- ap
1640 | [local variable space] |
1641 |----------------------------------------------|
1642 | [return address (r1)] |
1643 |----------------------------------------------|
1644 | [previous frame pointer (r30)] |
1645 |==============================================| <- fp
1646 | [preserved registers (r25..r14)] |
1647 |----------------------------------------------|
1648 | [preserved registers (x29..x22)] |
1649 |==============================================|
1650 | [dynamically allocated space (alloca)] |
1651 |==============================================|
1652 | [callee's outgoing memory arguments] |
1653 |==============================================| <- sp
1654
1655 Notes:
1656
1657 r1 and r30 must be saved if debugging.
1658
1659 fp (if present) is located two words down from the local
1660 variable space.
1661 */
1662
1663 static rtx emit_add PARAMS ((rtx, rtx, int));
1664 static void preserve_registers PARAMS ((int, int));
1665 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1666
1667 static int nregs;
1668 static int nxregs;
1669 static char save_regs[FIRST_PSEUDO_REGISTER];
1670 static int frame_laid_out;
1671 static int frame_size;
1672
1673 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1674 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1675 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1676
1677 /* Establish the position of the FP relative to the SP. This is done
1678 either during output_function_prologue() or by
1679 INITIAL_ELIMINATION_OFFSET. */
1680
1681 void
m88k_layout_frame()1682 m88k_layout_frame ()
1683 {
1684 int regno, sp_size;
1685
1686 if (frame_laid_out && reload_completed)
1687 return;
1688
1689 frame_laid_out = 1;
1690
1691 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1692 sp_size = nregs = nxregs = 0;
1693 frame_size = get_frame_size ();
1694
1695 /* Profiling requires a stack frame. */
1696 if (current_function_profile)
1697 frame_pointer_needed = 1;
1698
1699 /* If we are producing debug information, store r1 and r30 where the
1700 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1701 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1702 if (write_symbols != NO_DEBUG)
1703 save_regs[1] = 1;
1704
1705 /* If we are producing PIC, save the addressing base register and r1. */
1706 if (flag_pic && current_function_uses_pic_offset_table)
1707 {
1708 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1709 nregs++;
1710 }
1711
1712 /* If a frame is requested, save the previous FP, and the return
1713 address (r1), so that a traceback can be done without using tdesc
1714 information. Otherwise, simply save the FP if it is used as
1715 a preserve register. */
1716 if (frame_pointer_needed)
1717 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1718 else
1719 {
1720 if (regs_ever_live[FRAME_POINTER_REGNUM])
1721 save_regs[FRAME_POINTER_REGNUM] = 1;
1722 /* If there is a call, r1 needs to be saved as well. */
1723 if (regs_ever_live[1])
1724 save_regs[1] = 1;
1725 }
1726
1727 /* Figure out which extended register(s) needs to be saved. */
1728 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1729 regno++)
1730 if (regs_ever_live[regno] && ! call_used_regs[regno])
1731 {
1732 save_regs[regno] = 1;
1733 nxregs++;
1734 }
1735
1736 /* Figure out which normal register(s) needs to be saved. */
1737 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1738 if (regs_ever_live[regno] && ! call_used_regs[regno])
1739 {
1740 save_regs[regno] = 1;
1741 nregs++;
1742 }
1743
1744 /* Achieve greatest use of double memory ops. Either we end up saving
1745 r30 or we use that slot to align the registers we do save. */
1746 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1747 sp_size += 4;
1748
1749 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1750 /* if we need to align extended registers, add a word */
1751 if (nxregs > 0 && (nregs & 1) != 0)
1752 sp_size +=4;
1753 sp_size += 4 * nregs;
1754 sp_size += 8 * nxregs;
1755 sp_size += current_function_outgoing_args_size;
1756
1757 /* The first two saved registers are placed above the new frame pointer
1758 if any. In the only case this matters, they are r1 and r30. */
1759 if (frame_pointer_needed || sp_size)
1760 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1761 else
1762 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1763 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1764
1765 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1766 nonzero, align the frame size to 8 mod 16; otherwise align the
1767 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1768 up as a NOP. */
1769 {
1770 int need
1771 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1772 - (frame_size % STACK_UNIT_BOUNDARY));
1773 if (need < 0)
1774 need += STACK_UNIT_BOUNDARY;
1775 m88k_stack_size
1776 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1777 + current_function_pretend_args_size);
1778 }
1779 }
1780
1781 /* Return true if this function is known to have a null prologue. */
1782
1783 int
null_prologue()1784 null_prologue ()
1785 {
1786 if (! reload_completed)
1787 return 0;
1788 m88k_layout_frame ();
1789 return (! frame_pointer_needed
1790 && nregs == 0
1791 && nxregs == 0
1792 && m88k_stack_size == 0);
1793 }
1794
1795 static void
m88k_maybe_dead(insn)1796 m88k_maybe_dead (insn)
1797 rtx insn;
1798 {
1799 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
1800 const0_rtx,
1801 REG_NOTES (insn));
1802 }
1803
1804 void
m88k_expand_prologue()1805 m88k_expand_prologue ()
1806 {
1807 rtx insn;
1808
1809 m88k_layout_frame ();
1810
1811 if (warn_stack_larger_than && m88k_stack_size > stack_larger_than_size)
1812 warning ("stack usage is %d bytes", m88k_stack_size);
1813
1814 if (m88k_stack_size)
1815 {
1816 insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1817 RTX_FRAME_RELATED_P (insn) = 1;
1818
1819 /* If the stack pointer adjustment has required a temporary register,
1820 tell the DWARF code how to understand this sequence. */
1821 if (! ADD_INTVAL (m88k_stack_size))
1822 REG_NOTES (insn)
1823 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1824 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1825 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1826 GEN_INT (-m88k_stack_size))),
1827 REG_NOTES(insn));
1828 }
1829
1830 if (nregs || nxregs)
1831 preserve_registers (m88k_fp_offset + 4, 1);
1832
1833 if (frame_pointer_needed)
1834 {
1835 /* Be sure to emit this instruction after all register saves, DWARF
1836 information depends on this. */
1837 emit_insn (gen_blockage ());
1838 insn = emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1839 RTX_FRAME_RELATED_P (insn) = 1;
1840 }
1841
1842 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1843 {
1844 rtx return_reg = gen_rtx_REG (SImode, 1);
1845 rtx label = gen_label_rtx ();
1846 #if 0
1847 rtx temp_reg = NULL_RTX;
1848 int save_r1 = regs_ever_live[1];
1849
1850 if (save_r1)
1851 {
1852 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
1853 emit_move_insn (temp_reg, return_reg);
1854 }
1855 #endif
1856
1857 m88k_maybe_dead (emit_insn (gen_locate1 (pic_offset_table_rtx, label)));
1858 m88k_maybe_dead (emit_insn (gen_locate2 (pic_offset_table_rtx, label)));
1859 m88k_maybe_dead (emit_insn (gen_addsi3 (pic_offset_table_rtx,
1860 pic_offset_table_rtx,
1861 return_reg)));
1862
1863 #if 0
1864 if (save_r1)
1865 emit_move_insn (return_reg, temp_reg);
1866 #endif
1867 }
1868 if (current_function_profile)
1869 emit_insn (gen_blockage ());
1870 }
1871
1872 /* This function generates the assembly code for function exit,
1873 on machines that need it.
1874
1875 The function epilogue should not depend on the current stack pointer!
1876 It should use the frame pointer only, if there is a frame pointer.
1877 This is mandatory because of alloca; we also take advantage of it to
1878 omit stack adjustments before returning. */
1879
1880 static void
m88k_output_function_epilogue(stream,size)1881 m88k_output_function_epilogue (stream, size)
1882 FILE *stream;
1883 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1884 {
1885 rtx insn = get_last_insn ();
1886
1887 /* If the last insn isn't a BARRIER, we must write a return insn. This
1888 should only happen if the function has no prologue and no body. */
1889 if (GET_CODE (insn) == NOTE)
1890 insn = prev_nonnote_insn (insn);
1891 if (insn == 0 || GET_CODE (insn) != BARRIER)
1892 asm_fprintf (stream, "\tjmp\t %R%s\n", reg_names[1]);
1893
1894 /* If the last insn is a barrier, and the insn before that is a call,
1895 then add a nop instruction so that tdesc can walk the stack correctly
1896 even though there is no epilogue. (Otherwise, the label for the
1897 end of the tdesc region ends up at the start of the next function. */
1898 if (insn && GET_CODE (insn) == BARRIER)
1899 {
1900 insn = prev_nonnote_insn (insn);
1901 if (insn && GET_CODE (insn) == CALL_INSN)
1902 asm_fprintf (stream, "\tor\t %R%s,%R%s,%R%s\n",
1903 reg_names[0], reg_names[0], reg_names[0]);
1904 }
1905
1906 output_short_branch_defs (stream);
1907
1908 fprintf (stream, "\n");
1909
1910 frame_laid_out = 0;
1911 }
1912
1913 void
m88k_expand_epilogue()1914 m88k_expand_epilogue ()
1915 {
1916 if (frame_pointer_needed)
1917 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
1918
1919 if (nregs || nxregs)
1920 preserve_registers (m88k_fp_offset + 4, 0);
1921
1922 emit_insn (gen_blockage ());
1923
1924 if (m88k_stack_size)
1925 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
1926 }
1927
1928 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
1929 epilogue. */
1930
1931 static rtx
emit_add(dstreg,srcreg,amount)1932 emit_add (dstreg, srcreg, amount)
1933 rtx dstreg;
1934 rtx srcreg;
1935 int amount;
1936 {
1937 rtx incr = GEN_INT (abs (amount));
1938
1939 if (! ADD_INTVAL (amount))
1940 {
1941 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
1942 emit_move_insn (temp, incr);
1943 incr = temp;
1944 }
1945 return emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg,
1946 incr));
1947 }
1948
1949 /* Save/restore the preserve registers. base is the highest offset from
1950 r31 at which a register is stored. store_p is true if stores are to
1951 be done; otherwise loads. */
1952
1953 static void
preserve_registers(base,store_p)1954 preserve_registers (base, store_p)
1955 int base;
1956 int store_p;
1957 {
1958 int regno, offset;
1959 struct mem_op {
1960 int regno;
1961 int nregs;
1962 int offset;
1963 } mem_op[FIRST_PSEUDO_REGISTER];
1964 struct mem_op *mo_ptr = mem_op;
1965
1966 /* The 88open OCS mandates that preserved registers be stored in
1967 increasing order. For compatibility with current practice,
1968 the order is r1, r30, then the preserve registers. */
1969
1970 offset = base;
1971 if (save_regs[1])
1972 {
1973 /* An extra word is given in this case to make best use of double
1974 memory ops. */
1975 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
1976 offset -= 4;
1977 /* Do not reload r1 in the epilogue unless really necessary */
1978 if (store_p || regs_ever_live[1]
1979 || (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]))
1980 emit_ldst (store_p, 1, SImode, offset);
1981 offset -= 4;
1982 base = offset;
1983 }
1984
1985 /* Walk the registers to save recording all single memory operations. */
1986 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1987 if (save_regs[regno])
1988 {
1989 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1990 {
1991 mo_ptr->nregs = 1;
1992 mo_ptr->regno = regno;
1993 mo_ptr->offset = offset;
1994 mo_ptr++;
1995 offset -= 4;
1996 }
1997 else
1998 {
1999 regno--;
2000 offset -= 2*4;
2001 }
2002 }
2003
2004 /* Walk the registers to save recording all double memory operations.
2005 This avoids a delay in the epilogue (ld.d/ld). */
2006 offset = base;
2007 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2008 if (save_regs[regno])
2009 {
2010 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2011 {
2012 offset -= 4;
2013 }
2014 else
2015 {
2016 mo_ptr->nregs = 2;
2017 mo_ptr->regno = regno-1;
2018 mo_ptr->offset = offset-4;
2019 mo_ptr++;
2020 regno--;
2021 offset -= 2*4;
2022 }
2023 }
2024
2025 /* Walk the extended registers to record all memory operations. */
2026 /* Be sure the offset is double word aligned. */
2027 offset = (offset - 1) & ~7;
2028 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2029 regno--)
2030 if (save_regs[regno])
2031 {
2032 mo_ptr->nregs = 2;
2033 mo_ptr->regno = regno;
2034 mo_ptr->offset = offset;
2035 mo_ptr++;
2036 offset -= 2*4;
2037 }
2038
2039 mo_ptr->regno = 0;
2040
2041 /* Output the memory operations. */
2042 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2043 {
2044 if (mo_ptr->nregs)
2045 emit_ldst (store_p, mo_ptr->regno,
2046 (mo_ptr->nregs > 1 ? DImode : SImode),
2047 mo_ptr->offset);
2048 }
2049 }
2050
2051 static void
emit_ldst(store_p,regno,mode,offset)2052 emit_ldst (store_p, regno, mode, offset)
2053 int store_p;
2054 int regno;
2055 enum machine_mode mode;
2056 int offset;
2057 {
2058 rtx reg = gen_rtx_REG (mode, regno);
2059 rtx mem;
2060 rtx insn;
2061
2062 if (SMALL_INTVAL (offset))
2063 {
2064 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2065 }
2066 else
2067 {
2068 /* offset is too large for immediate index must use register */
2069
2070 rtx disp = GEN_INT (offset);
2071 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2072 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2073
2074 emit_move_insn (temp, disp);
2075 mem = gen_rtx_MEM (mode, regi);
2076 }
2077
2078 if (store_p)
2079 {
2080 insn = emit_move_insn (mem, reg);
2081 RTX_FRAME_RELATED_P (insn) = 1;
2082 }
2083 else
2084 emit_move_insn (reg, mem);
2085 }
2086
2087 /* Convert the address expression REG to a CFA offset. */
2088
2089 int
m88k_debugger_offset(reg,offset)2090 m88k_debugger_offset (reg, offset)
2091 register rtx reg;
2092 register int offset;
2093 {
2094 if (GET_CODE (reg) == PLUS)
2095 {
2096 offset = INTVAL (XEXP (reg, 1));
2097 reg = XEXP (reg, 0);
2098 }
2099
2100 /* Put the offset in terms of the CFA (arg pointer). */
2101 if (reg == frame_pointer_rtx)
2102 offset += m88k_fp_offset - m88k_stack_size;
2103 else if (reg == stack_pointer_rtx)
2104 offset -= m88k_stack_size;
2105 else if (reg != arg_pointer_rtx)
2106 return 0;
2107
2108 return offset;
2109 }
2110
2111 /* Output assembler code to FILE to increment profiler label # LABELNO
2112 for profiling a function entry. NAME is the mcount function name
2113 (varies). */
2114
2115 void
output_function_profiler(file,labelno,name)2116 output_function_profiler (file, labelno, name)
2117 FILE *file;
2118 int labelno;
2119 const char *name;
2120 {
2121 char label[256];
2122
2123 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2124
2125 asm_fprintf (file, "\tsubu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
2126 asm_fprintf (file, "\tst.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
2127 asm_fprintf (file, "\tst.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
2128 asm_fprintf (file, "\tst.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
2129 asm_fprintf (file, "\tst.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
2130
2131 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2132 if (flag_pic == 2)
2133 {
2134 asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s#got_rel)\n",
2135 reg_names[2], reg_names[0], &label[1]);
2136 asm_fprintf (file, "\tor\t %R%s,%R%s,%Rlo16(%s#got_rel)\n",
2137 reg_names[2], reg_names[2], &label[1]);
2138 asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
2139 asm_fprintf (file, "\t ld\t %R%s,%R%s,%R%s\n", reg_names[2],
2140 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[2]);
2141 }
2142 else if (flag_pic)
2143 {
2144 asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
2145 asm_fprintf (file, "\t ld\t %R%s,%R%s,%s#got_rel\n", reg_names[2],
2146 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2147 }
2148 else
2149 {
2150 asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s)\n",
2151 reg_names[2], reg_names[0], &label[1]);
2152 asm_fprintf (file, "\tbsr.n\t %s\n", name);
2153 asm_fprintf (file, "\t or\t %R%s,%R%s,%Rlo16(%s)\n",
2154 reg_names[2], reg_names[2], &label[1]);
2155 }
2156
2157 asm_fprintf (file, "\tld.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
2158 asm_fprintf (file, "\tld.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
2159 asm_fprintf (file, "\tld.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
2160 asm_fprintf (file, "\tld.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
2161 asm_fprintf (file, "\taddu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
2162 }
2163
2164 /* Determine whether a function argument is passed in a register, and
2165 which register.
2166
2167 The arguments are CUM, which summarizes all the previous
2168 arguments; MODE, the machine mode of the argument; TYPE,
2169 the data type of the argument as a tree node or 0 if that is not known
2170 (which happens for C support library functions); and NAMED,
2171 which is 1 for an ordinary argument and 0 for nameless arguments that
2172 correspond to `...' in the called function's prototype.
2173
2174 The value of the expression should either be a `reg' RTX for the
2175 hard register in which to pass the argument, or zero to pass the
2176 argument on the stack.
2177
2178 On the m88000 the first eight words of args are normally in registers
2179 and the rest are pushed. Double precision floating point must be
2180 double word aligned (and if in a register, starting on an even
2181 register). Structures and unions which are not 4 byte, and word
2182 aligned are passed in memory rather than registers, even if they
2183 would fit completely in the registers under OCS rules.
2184
2185 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2186 For structures that are passed in memory, but could have been
2187 passed in registers, we first load the structure into the
2188 register, and then when the last argument is passed, we store
2189 the registers into the stack locations. This fixes some bugs
2190 where GCC did not expect to have register arguments, followed
2191 by stack arguments, followed by register arguments. */
2192
2193 struct rtx_def *
m88k_function_arg(args_so_far,mode,type,named)2194 m88k_function_arg (args_so_far, mode, type, named)
2195 CUMULATIVE_ARGS args_so_far;
2196 enum machine_mode mode;
2197 tree type;
2198 int named ATTRIBUTE_UNUSED;
2199 {
2200 int bytes, words;
2201
2202 if (type != 0 && AGGREGATE_TYPE_P (type)) /* undo putting struct in register */
2203 mode = BLKmode;
2204
2205 if (type == 0 && mode == BLKmode)
2206 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2207
2208 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2209
2210 /* Variable-sized types get passed by reference, which can be passed
2211 in registers. */
2212 if (bytes < 0)
2213 {
2214 if (args_so_far > 8 - (POINTER_SIZE / BITS_PER_WORD))
2215 return (rtx) 0;
2216
2217 return gen_rtx_REG (Pmode, 2 + args_so_far);
2218 }
2219
2220 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2221
2222 if ((args_so_far & 1) != 0
2223 && (mode == DImode || mode == DFmode
2224 || (type != 0 && TYPE_ALIGN (type) > BITS_PER_WORD)))
2225 args_so_far++;
2226
2227 if (args_so_far + words > 8)
2228 return (rtx) 0; /* args have exhausted registers */
2229
2230 else if (mode == BLKmode
2231 && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
2232 return (rtx) 0;
2233
2234 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2235 2 + args_so_far);
2236 }
2237
2238 /* Update the summarizer variable CUM to advance past an argument in
2239 the argument list. The values MODE, TYPE and NAMED describe that
2240 argument. Once this is done, the variable CUM is suitable for
2241 analyzing the *following* argument with `FUNCTION_ARG', etc. (TYPE
2242 is null for libcalls where that information may not be available.) */
2243 void
m88k_function_arg_advance(args_so_far,mode,type,named)2244 m88k_function_arg_advance (args_so_far, mode, type, named)
2245 CUMULATIVE_ARGS *args_so_far;
2246 enum machine_mode mode;
2247 tree type;
2248 int named ATTRIBUTE_UNUSED;
2249 {
2250 int bytes, words;
2251 int asf;
2252
2253 if (type != 0 && AGGREGATE_TYPE_P (type))
2254 mode = BLKmode;
2255
2256 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2257 asf = *args_so_far;
2258
2259 /* Variable-sized types get passed by reference, which can be passed
2260 in registers. */
2261 if (bytes < 0)
2262 {
2263 if (asf <= 8 - (POINTER_SIZE / BITS_PER_WORD))
2264 *args_so_far += POINTER_SIZE / BITS_PER_WORD;
2265
2266 return;
2267 }
2268
2269 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2270
2271 /* Struct and unions which are not exactly the size of a register are to be
2272 passed on stack. */
2273 if (mode == BLKmode
2274 && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
2275 return;
2276
2277 /* Align arguments requiring more than word alignment to a double-word
2278 boundary (or an even register number if the argument will get passed
2279 in registers). */
2280 if ((asf & 1) != 0
2281 && (mode == DImode || mode == DFmode
2282 || (type != 0 && TYPE_ALIGN (type) > BITS_PER_WORD)))
2283 asf++;
2284
2285 if (asf + words > 8)
2286 return;
2287
2288 (*args_so_far) = asf + words;
2289 }
2290
2291 /* A C expression that indicates when an argument must be passed by
2292 reference. If nonzero for an argument, a copy of that argument is
2293 made in memory and a pointer to the argument is passed instead of
2294 the argument itself. The pointer is passed in whatever way is
2295 appropriate for passing a pointer to that type.
2296
2297 On m88k, only variable sized types are passed by reference. */
2298
2299 int
m88k_function_arg_pass_by_reference(cum,mode,type,named)2300 m88k_function_arg_pass_by_reference (cum, mode, type, named)
2301 CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
2302 enum machine_mode mode ATTRIBUTE_UNUSED;
2303 tree type;
2304 int named ATTRIBUTE_UNUSED;
2305 {
2306 return type != 0 && int_size_in_bytes (type) < 0;
2307 }
2308
2309 /* Perform any needed actions needed for a function that is receiving a
2310 variable number of arguments.
2311
2312 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2313 the preceding args and about the function being called.
2314
2315 MODE and TYPE are the mode and type of the current parameter.
2316
2317 PRETEND_SIZE is a variable that should be set to the amount of stack
2318 that must be pushed by the prolog to pretend that our caller pushed
2319 it.
2320
2321 Normally, this macro will push all remaining incoming registers on the
2322 stack and set PRETEND_SIZE to the length of the registers pushed. */
2323
2324 void
m88k_setup_incoming_varargs(cum,mode,type,pretend_size,no_rtl)2325 m88k_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
2326 CUMULATIVE_ARGS *cum;
2327 enum machine_mode mode;
2328 tree type;
2329 int *pretend_size;
2330 int no_rtl;
2331 {
2332 CUMULATIVE_ARGS next_cum;
2333 tree fntype;
2334 int stdarg_p;
2335 int regcnt, delta;
2336
2337 fntype = TREE_TYPE (current_function_decl);
2338 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
2339 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2340 != void_type_node));
2341
2342 /* For varargs, we do not want to skip the dummy va_dcl argument.
2343 For stdargs, we do want to skip the last named argument. */
2344 next_cum = *cum;
2345 if (stdarg_p)
2346 m88k_function_arg_advance(&next_cum, mode, type, 1);
2347
2348 regcnt = next_cum < 8 ? 8 - next_cum : 0;
2349 delta = regcnt & 1;
2350
2351 if (! no_rtl && regcnt != 0)
2352 {
2353 rtx mem, dst;
2354 int set, regno, offs;
2355
2356 set = get_varargs_alias_set ();
2357 mem = gen_rtx_MEM (BLKmode,
2358 plus_constant (virtual_incoming_args_rtx,
2359 - (regcnt + delta) * UNITS_PER_WORD));
2360 set_mem_alias_set (mem, set);
2361
2362 /* Now store the incoming registers. */
2363 /* The following is equivalent to
2364 move_block_from_reg (2 + next_cum,
2365 adjust_address (mem, Pmode,
2366 delta * UNITS_PER_WORD),
2367 regcnt, UNITS_PER_WORD * regcnt);
2368 but using double store instruction since the stack is properly
2369 aligned. */
2370 regno = 2 + next_cum;
2371 dst = mem;
2372
2373 if (delta != 0)
2374 {
2375 dst = adjust_address (dst, Pmode, UNITS_PER_WORD);
2376 emit_move_insn (operand_subword (dst, 0, 1, BLKmode),
2377 gen_rtx_REG (SImode, regno));
2378 regno++;
2379 }
2380
2381 offs = delta;
2382 while (regno < 10)
2383 {
2384 emit_move_insn (adjust_address (dst, DImode, offs * UNITS_PER_WORD),
2385 gen_rtx_REG (DImode, regno));
2386 offs += 2;
2387 regno += 2;
2388 }
2389
2390 *pretend_size = (regcnt + delta) * UNITS_PER_WORD;
2391 }
2392 }
2393
2394 /* Define the `__builtin_va_list' type for the ABI. */
2395
2396 tree
m88k_build_va_list()2397 m88k_build_va_list ()
2398 {
2399 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2400
2401 int_ptr_type_node = build_pointer_type (integer_type_node);
2402
2403 record = make_node (RECORD_TYPE);
2404
2405 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2406 integer_type_node);
2407 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2408 int_ptr_type_node);
2409 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2410 int_ptr_type_node);
2411
2412 DECL_FIELD_CONTEXT (field_arg) = record;
2413 DECL_FIELD_CONTEXT (field_stk) = record;
2414 DECL_FIELD_CONTEXT (field_reg) = record;
2415
2416 TYPE_FIELDS (record) = field_arg;
2417 TREE_CHAIN (field_arg) = field_stk;
2418 TREE_CHAIN (field_stk) = field_reg;
2419
2420 layout_type (record);
2421 return record;
2422 }
2423
2424 /* Implement `va_start' for varargs and stdarg. */
2425
2426 void
m88k_va_start(valist,nextarg)2427 m88k_va_start (valist, nextarg)
2428 tree valist;
2429 rtx nextarg ATTRIBUTE_UNUSED;
2430 {
2431 tree field_reg, field_stk, field_arg;
2432 tree reg, stk, arg, t;
2433 tree fntype;
2434 int stdarg_p;
2435 int offset;
2436
2437 if (! CONSTANT_P (current_function_arg_offset_rtx))
2438 abort ();
2439
2440 field_arg = TYPE_FIELDS (va_list_type_node);
2441 field_stk = TREE_CHAIN (field_arg);
2442 field_reg = TREE_CHAIN (field_stk);
2443
2444 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2445 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2446 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2447
2448 fntype = TREE_TYPE (current_function_decl);
2449 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
2450 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2451 != void_type_node));
2452
2453 /* Fill in the __va_arg member. */
2454 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
2455 build_int_2 (current_function_args_info, 0));
2456 TREE_SIDE_EFFECTS (t) = 1;
2457 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2458
2459 /* Store the arg pointer in the __va_stk member. */
2460 offset = XINT (current_function_arg_offset_rtx, 0);
2461 if (current_function_args_info >= 8 && ! stdarg_p)
2462 offset -= UNITS_PER_WORD;
2463 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2464 t = build (PLUS_EXPR, TREE_TYPE (stk), t, build_int_2 (offset, 0));
2465 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2466 TREE_SIDE_EFFECTS (t) = 1;
2467 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2468
2469 /* Setup __va_reg */
2470 t = make_tree (TREE_TYPE (reg), virtual_incoming_args_rtx);
2471 t = build (PLUS_EXPR, TREE_TYPE (reg), t,
2472 build_int_2 (-8 * UNITS_PER_WORD, -1));
2473 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2474 TREE_SIDE_EFFECTS (t) = 1;
2475 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2476 }
2477
2478 /* Implement `va_arg'. */
2479
2480 rtx
m88k_va_arg(valist,type)2481 m88k_va_arg (valist, type)
2482 tree valist, type;
2483 {
2484 tree field_reg, field_stk, field_arg;
2485 int indirect_p, size, wsize, align, reg_p;
2486 rtx addr_rtx;
2487 rtx lab_done;
2488
2489 field_arg = TYPE_FIELDS (va_list_type_node);
2490 field_stk = TREE_CHAIN (field_arg);
2491 field_reg = TREE_CHAIN (field_stk);
2492
2493 size = int_size_in_bytes (type);
2494 /* Variable sized types are passed by reference. */
2495 if (size < 0)
2496 {
2497 indirect_p = 1;
2498 wsize = POINTER_SIZE / BITS_PER_WORD;
2499 type = 0;
2500 reg_p = 1;
2501 }
2502 else
2503 {
2504 indirect_p = 0;
2505 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2506 reg_p = (AGGREGATE_TYPE_P (type)
2507 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2508 : size <= 2*UNITS_PER_WORD);
2509 }
2510
2511 addr_rtx = gen_reg_rtx (Pmode);
2512 lab_done = gen_label_rtx ();
2513
2514 /* Decide if we should read from stack or regs if the argument could have
2515 been passed in registers. */
2516 if (reg_p) {
2517 tree arg, arg_align, reg;
2518 rtx lab_stack;
2519 tree t;
2520 rtx r;
2521
2522 lab_stack = gen_label_rtx ();
2523
2524 /* Align __va_arg to a doubleword boundary if necessary. */
2525 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2526 align = type == 0 ? 0 : TYPE_ALIGN (type) / BITS_PER_WORD;
2527 if (align > 1)
2528 {
2529 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2530 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t,
2531 build_int_2 (-align, -1));
2532 arg_align = save_expr (arg_align);
2533 }
2534 else
2535 arg_align = arg;
2536
2537 /* Make sure the argument fits within the remainder of the saved
2538 register area, and branch to the stack logic if not. */
2539 r = expand_expr (arg_align, NULL_RTX, TYPE_MODE (TREE_TYPE (arg_align)),
2540 EXPAND_NORMAL);
2541 /* if (arg_align > 8 - wsize) goto lab_stack */
2542 emit_cmp_and_jump_insns (r, GEN_INT (8 - wsize), GTU,
2543 GEN_INT (UNITS_PER_WORD), GET_MODE (r), 1,
2544 lab_stack);
2545
2546 /* Compute the argument address. */
2547 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2548 t = build (MULT_EXPR, TREE_TYPE (reg), arg_align,
2549 build_int_2 (UNITS_PER_WORD, 0));
2550 t = build (PLUS_EXPR, TREE_TYPE (reg), reg, t);
2551 TREE_SIDE_EFFECTS (t) = 1;
2552
2553 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
2554 if (r != addr_rtx)
2555 emit_move_insn (addr_rtx, r);
2556
2557 /* Increment __va_arg. */
2558 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2559 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2560 TREE_SIDE_EFFECTS (t) = 1;
2561 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2562
2563 emit_jump_insn (gen_jump (lab_done));
2564 emit_barrier ();
2565
2566 emit_label (lab_stack);
2567 }
2568
2569 {
2570 tree stk;
2571 tree t;
2572 rtx r;
2573
2574 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2575
2576 /* Align __va_stk to the type boundary if necessary. */
2577 align = type == 0 ? 0 : TYPE_ALIGN (type) / BITS_PER_UNIT;
2578 if (align > UNITS_PER_WORD)
2579 {
2580 t = build (PLUS_EXPR, TREE_TYPE (stk), stk, build_int_2 (align - 1, 0));
2581 t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2582 TREE_SIDE_EFFECTS (t) = 1;
2583 }
2584 else
2585 t = stk;
2586
2587 /* Compute the argument address. */
2588 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
2589 if (r != addr_rtx)
2590 emit_move_insn (addr_rtx, r);
2591
2592 /* Increment __va_stk. */
2593 t = build (PLUS_EXPR, TREE_TYPE (t), t,
2594 build_int_2 (wsize * UNITS_PER_WORD, 0));
2595 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2596 TREE_SIDE_EFFECTS (t) = 1;
2597 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2598 }
2599
2600 emit_label (lab_done);
2601
2602 if (indirect_p)
2603 {
2604 rtx r = gen_rtx_MEM (Pmode, addr_rtx);
2605 set_mem_alias_set (r, get_varargs_alias_set ());
2606 emit_move_insn (addr_rtx, r);
2607 }
2608
2609 return addr_rtx;
2610 }
2611
2612 /* If cmpsi has not been generated, emit code to do the test. Return the
2613 expression describing the test of operator OP. */
2614
2615 rtx
emit_test(op,mode)2616 emit_test (op, mode)
2617 enum rtx_code op;
2618 enum machine_mode mode;
2619 {
2620 if (m88k_compare_reg == 0)
2621 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2622 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2623 }
2624
2625 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2626 operand. All tests with zero (albeit swapped) and all equality tests
2627 with a constant are done with bcnd. The remaining cases are swapped
2628 as needed. */
2629
2630 void
emit_bcnd(op,label)2631 emit_bcnd (op, label)
2632 enum rtx_code op;
2633 rtx label;
2634 {
2635 if (m88k_compare_op1 == const0_rtx)
2636 emit_jump_insn (gen_bcnd
2637 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2638 label));
2639 else if (m88k_compare_op0 == const0_rtx)
2640 emit_jump_insn (gen_bcnd
2641 (gen_rtx (swap_condition (op),
2642 VOIDmode, m88k_compare_op1, const0_rtx),
2643 label));
2644 else if (op != EQ && op != NE)
2645 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2646 else
2647 {
2648 rtx zero = gen_reg_rtx (SImode);
2649 rtx reg, constant;
2650 int value;
2651
2652 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2653 {
2654 reg = force_reg (SImode, m88k_compare_op0);
2655 constant = m88k_compare_op1;
2656 }
2657 else
2658 {
2659 reg = force_reg (SImode, m88k_compare_op1);
2660 constant = m88k_compare_op0;
2661 }
2662 value = INTVAL (constant);
2663
2664 /* Perform an arithmetic computation to make the compared-to value
2665 zero, but avoid loosing if the bcnd is later changed into sxx. */
2666 if (SMALL_INTVAL (value))
2667 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2668 else
2669 {
2670 if (SMALL_INTVAL (-value))
2671 emit_insn (gen_addsi3 (zero, reg,
2672 GEN_INT (-value)));
2673 else
2674 emit_insn (gen_xorsi3 (zero, reg, constant));
2675
2676 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2677 zero, const0_rtx),
2678 label));
2679 }
2680 }
2681 }
2682
2683 /* Print an operand. Recognize special options, documented below. */
2684
2685 void
print_operand(file,x,code)2686 print_operand (file, x, code)
2687 FILE *file;
2688 rtx x;
2689 int code;
2690 {
2691 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2692 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2693 static int sequencep;
2694 static int reversep;
2695
2696 if (sequencep)
2697 {
2698 if (code < 'B' || code > 'E')
2699 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2700 if (reversep)
2701 xc = reverse_condition (xc);
2702 sequencep = 0;
2703 }
2704
2705 switch (code)
2706 {
2707 case '#': /* register prefix character (may be empty) */
2708 fputs (m88k_register_prefix, file);
2709 return;
2710
2711 case 'V': /* Output a serializing instruction as needed if the operand
2712 (assumed to be a MEM) is a volatile load. */
2713 case 'v': /* ditto for a volatile store. */
2714 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2715 {
2716 /* The m88110 implements two FIFO queues, one for loads and
2717 one for stores. These queues mean that loads complete in
2718 their issue order as do stores. An interaction between the
2719 history buffer and the store reservation station ensures
2720 that a store will not bypass load. Finally, a load will not
2721 bypass store, but only when they reference the same address.
2722
2723 To avoid this reordering (a load bypassing a store) for
2724 volatile references, a serializing instruction is output.
2725 We choose the fldcr instruction as it does not serialize on
2726 the m88100 so that -m88000 code will not be degraded.
2727
2728 The mechanism below is completed by having CC_STATUS_INIT set
2729 the code to the unknown value. */
2730
2731 /*
2732 hassey 6/30/93
2733 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2734 this purpose undesirable. Instead we will use tb1, this will
2735 cause serialization on the 88100 but such is life.
2736 */
2737
2738 static rtx last_addr = 0;
2739 if (code == 'V' /* Only need to serialize before a load. */
2740 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2741 && !(m88k_volatile_code == 'v'
2742 && GET_CODE (XEXP (x, 0)) == LO_SUM
2743 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2744 asm_fprintf (file,
2745 #if 0
2746 #ifdef AS_BUG_FLDCR
2747 "fldcr\t %R%s,%Rcr63\n\t",
2748 #else
2749 "fldcr\t %R%s,%Rfcr63\n\t",
2750 #endif
2751 reg_names[0]);
2752 #else /* 0 */
2753 "tb1\t 1,%R%s,0xff\n\t", reg_names[0]);
2754 #endif /* 0 */
2755 m88k_volatile_code = code;
2756 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2757 ? XEXP (XEXP (x, 0), 1) : 0);
2758 }
2759 return;
2760
2761 case 'X': /* print the upper 16 bits... */
2762 value >>= 16;
2763 case 'x': /* print the lower 16 bits of the integer constant in hex */
2764 if (xc != CONST_INT)
2765 output_operand_lossage ("invalid %%x/X value");
2766 fprintf (file, "0x%x", value & 0xffff); return;
2767
2768 case 'H': /* print the low 16 bits of the negated integer constant */
2769 if (xc != CONST_INT)
2770 output_operand_lossage ("invalid %%H value");
2771 value = -value;
2772 case 'h': /* print the register or low 16 bits of the integer constant */
2773 if (xc == REG)
2774 goto reg;
2775 if (xc != CONST_INT)
2776 output_operand_lossage ("invalid %%h value");
2777 fprintf (file, "%d", value & 0xffff);
2778 return;
2779
2780 case 'Q': /* print the low 8 bits of the negated integer constant */
2781 if (xc != CONST_INT)
2782 output_operand_lossage ("invalid %%Q value");
2783 value = -value;
2784 case 'q': /* print the register or low 8 bits of the integer constant */
2785 if (xc == REG)
2786 goto reg;
2787 if (xc != CONST_INT)
2788 output_operand_lossage ("invalid %%q value");
2789 fprintf (file, "%d", value & 0xff);
2790 return;
2791
2792 case 'p': /* print the logarithm of the integer constant */
2793 if (xc != CONST_INT
2794 || (value = exact_log2 (value)) < 0)
2795 output_operand_lossage ("invalid %%p value");
2796 fprintf (file, "%d", value);
2797 return;
2798
2799 case 'S': /* complement the value and then... */
2800 value = ~value;
2801 case 's': /* print the width and offset values forming the integer
2802 constant with a SET instruction. See integer_ok_for_set. */
2803 {
2804 register unsigned mask, uval = value;
2805 register int top, bottom;
2806
2807 if (xc != CONST_INT)
2808 output_operand_lossage ("invalid %%s/S value");
2809 /* All the "one" bits must be contiguous. If so, MASK will be
2810 a power of two or zero. */
2811 mask = (uval | (uval - 1)) + 1;
2812 if (!(uval && POWER_OF_2_or_0 (mask)))
2813 output_operand_lossage ("invalid %%s/S value");
2814 top = mask ? exact_log2 (mask) : 32;
2815 bottom = exact_log2 (uval & ~(uval - 1));
2816 fprintf (file,"%d<%d>", top - bottom, bottom);
2817 return;
2818 }
2819
2820 case 'P': /* print nothing if pc_rtx; output label_ref */
2821 if (xc == LABEL_REF)
2822 output_addr_const (file, x);
2823 else if (xc != PC)
2824 output_operand_lossage ("invalid %%P operand");
2825 return;
2826
2827 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2828 fputc (xc == LABEL_REF ? '1' : '0', file);
2829 case '.': /* print .n if delay slot is used */
2830 fputs ((final_sequence
2831 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2832 ? ".n\t" : "\t", file);
2833 return;
2834
2835 case '!': /* Reverse the following condition. */
2836 sequencep++;
2837 reversep = 1;
2838 return;
2839 case 'R': /* reverse the condition of the next print_operand
2840 if operand is a label_ref. */
2841 sequencep++;
2842 reversep = (xc == LABEL_REF);
2843 return;
2844
2845 case 'B': /* bcnd branch values */
2846 if (0) /* SVR4 */
2847 fputs (m88k_register_prefix, file);
2848 switch (xc)
2849 {
2850 case EQ: fputs ("eq0", file); return;
2851 case NE: fputs ("ne0", file); return;
2852 case GT: fputs ("gt0", file); return;
2853 case LE: fputs ("le0", file); return;
2854 case LT: fputs ("lt0", file); return;
2855 case GE: fputs ("ge0", file); return;
2856 default: output_operand_lossage ("invalid %%B value");
2857 }
2858
2859 case 'C': /* bb0/bb1 branch values for comparisons */
2860 if (0) /* SVR4 */
2861 fputs (m88k_register_prefix, file);
2862 switch (xc)
2863 {
2864 case EQ: fputs ("eq", file); return;
2865 case NE: fputs ("ne", file); return;
2866 case GT: fputs ("gt", file); return;
2867 case LE: fputs ("le", file); return;
2868 case LT: fputs ("lt", file); return;
2869 case GE: fputs ("ge", file); return;
2870 case GTU: fputs ("hi", file); return;
2871 case LEU: fputs ("ls", file); return;
2872 case LTU: fputs ("lo", file); return;
2873 case GEU: fputs ("hs", file); return;
2874 default: output_operand_lossage ("invalid %%C value");
2875 }
2876
2877 case 'D': /* bcnd branch values for float comparisons */
2878 switch (xc)
2879 {
2880 case EQ: fputs ("0xa", file); return;
2881 case NE: fputs ("0x5", file); return;
2882 case GT:
2883 if (0) /* SVR4 */
2884 fputs (m88k_register_prefix, file);
2885 fputs ("gt0", file);
2886 return;
2887 case LE:
2888 if (0) /* SVR4 */
2889 fputs (m88k_register_prefix, file);
2890 fputs ("le0", file);
2891 return;
2892 case LT: fputs ("0x4", file); return;
2893 case GE: fputs ("0xb", file); return;
2894 default: output_operand_lossage ("invalid %%D value");
2895 }
2896
2897 case 'E': /* bcnd branch values for special integers */
2898 switch (xc)
2899 {
2900 case EQ: fputs ("0x8", file); return;
2901 case NE: fputs ("0x7", file); return;
2902 default: output_operand_lossage ("invalid %%E value");
2903 }
2904
2905 case 'd': /* second register of a two register pair */
2906 if (xc != REG)
2907 output_operand_lossage ("`%%d' operand isn't a register");
2908 asm_fprintf (file, "%R%s", reg_names[REGNO (x) + 1]);
2909 return;
2910
2911 case 'r': /* an immediate 0 should be represented as `r0' */
2912 if (x == const0_rtx)
2913 {
2914 asm_fprintf (file, "%R%s", reg_names[0]);
2915 return;
2916 }
2917 else if (xc != REG)
2918 output_operand_lossage ("invalid %%r value");
2919 case 0:
2920 name:
2921 if (xc == REG)
2922 {
2923 reg:
2924 if (REGNO (x) == ARG_POINTER_REGNUM)
2925 output_operand_lossage ("operand is r0");
2926 else
2927 asm_fprintf (file, "%R%s", reg_names[REGNO (x)]);
2928 }
2929 else if (xc == PLUS)
2930 output_address (x);
2931 else if (xc == MEM)
2932 output_address (XEXP (x, 0));
2933 else if (flag_pic && xc == UNSPEC)
2934 {
2935 output_addr_const (file, XVECEXP (x, 0, 0));
2936 fputs ("#got_rel", file);
2937 }
2938 else if (xc == CONST_DOUBLE)
2939 output_operand_lossage ("operand is const_double");
2940 else
2941 output_addr_const (file, x);
2942 return;
2943
2944 case 'g': /* append #got_rel as needed */
2945 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2946 {
2947 output_addr_const (file, x);
2948 fputs ("#got_rel", file);
2949 return;
2950 }
2951 goto name;
2952
2953 case 'a': /* (standard), assume operand is an address */
2954 case 'c': /* (standard), assume operand is an immediate value */
2955 case 'l': /* (standard), assume operand is a label_ref */
2956 case 'n': /* (standard), like %c, except negate first */
2957 default:
2958 output_operand_lossage ("invalid code");
2959 }
2960 }
2961
2962 void
print_operand_address(file,addr)2963 print_operand_address (file, addr)
2964 FILE *file;
2965 rtx addr;
2966 {
2967 register rtx reg0, reg1;
2968
2969 switch (GET_CODE (addr))
2970 {
2971 case REG:
2972 if (REGNO (addr) == ARG_POINTER_REGNUM)
2973 abort ();
2974 else
2975 asm_fprintf (file, "%R%s,%R%s", reg_names[0], reg_names [REGNO (addr)]);
2976 break;
2977
2978 case LO_SUM:
2979 asm_fprintf (file, "%R%s,%Rlo16(",
2980 reg_names[REGNO (XEXP (addr, 0))]);
2981 output_addr_const (file, XEXP (addr, 1));
2982 fputc (')', file);
2983 break;
2984
2985 case PLUS:
2986 reg0 = XEXP (addr, 0);
2987 reg1 = XEXP (addr, 1);
2988 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2989 {
2990 rtx tmp = reg0;
2991 reg0 = reg1;
2992 reg1 = tmp;
2993 }
2994
2995 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
2996 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
2997 abort ();
2998
2999 else if (REG_P (reg0))
3000 {
3001 if (REG_P (reg1))
3002 asm_fprintf (file, "%R%s,%R%s",
3003 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3004
3005 else if (GET_CODE (reg1) == CONST_INT)
3006 asm_fprintf (file, "%R%s,%d",
3007 reg_names [REGNO (reg0)], INTVAL (reg1));
3008
3009 else if (GET_CODE (reg1) == MULT)
3010 {
3011 rtx mreg = XEXP (reg1, 0);
3012 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3013 abort ();
3014
3015 asm_fprintf (file, "%R%s[%R%s]", reg_names[REGNO (reg0)],
3016 reg_names[REGNO (mreg)]);
3017 }
3018
3019 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3020 {
3021 asm_fprintf (file, "%R%s,%Rlo16(",
3022 reg_names[REGNO (reg0)]);
3023 output_addr_const (file, XEXP (reg1, 0));
3024 fputc (')', file);
3025 }
3026
3027 else if (flag_pic)
3028 {
3029 asm_fprintf (file, "%R%s,", reg_names[REGNO (reg0)]);
3030 output_addr_const (file, reg1);
3031 fputs ("#got_rel", file);
3032 }
3033 else abort ();
3034 }
3035
3036 else
3037 abort ();
3038 break;
3039
3040 case MULT:
3041 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3042 abort ();
3043
3044 asm_fprintf (file, "%R%s[%R%s]",
3045 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3046 break;
3047
3048 case CONST_INT:
3049 asm_fprintf (file, "%R%s,%d", reg_names[0], INTVAL (addr));
3050 break;
3051
3052 default:
3053 asm_fprintf (file, "%R%s,", reg_names[0]);
3054 output_addr_const (file, addr);
3055 }
3056 }
3057
3058 /* Return true if X is an address which needs a temporary register when
3059 reloaded while generating PIC code. */
3060
3061 int
pic_address_needs_scratch(x)3062 pic_address_needs_scratch (x)
3063 rtx x;
3064 {
3065 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3066 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3067 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3068 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3069 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3070 return 1;
3071
3072 return 0;
3073 }
3074
3075 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3076 reference and a constant. */
3077
3078 int
symbolic_operand(op,mode)3079 symbolic_operand (op, mode)
3080 register rtx op;
3081 enum machine_mode mode;
3082 {
3083 switch (GET_CODE (op))
3084 {
3085 case SYMBOL_REF:
3086 case LABEL_REF:
3087 return 1;
3088
3089 case CONST:
3090 op = XEXP (op, 0);
3091 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3092 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3093 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3094
3095 /* ??? This clause seems to be irrelevant. */
3096 case CONST_DOUBLE:
3097 return GET_MODE (op) == mode;
3098
3099 default:
3100 return 0;
3101 }
3102 }
3103
3104 /* Adjust the cost of INSN based on the relationship between INSN that
3105 is dependent on DEP_INSN through the dependence LINK. The default
3106 is to make no adjustment to COST.
3107
3108 On the m88k, ignore the cost of anti- and output-dependencies. On
3109 the m88100, a store can issue two cycles before the value (not the
3110 address) has finished computing. */
3111
3112 static int
m88k_adjust_cost(insn,link,dep,cost)3113 m88k_adjust_cost (insn, link, dep, cost)
3114 rtx insn;
3115 rtx link;
3116 rtx dep;
3117 int cost;
3118 {
3119 if (REG_NOTE_KIND (link) != 0)
3120 return 0; /* Anti or output dependence. */
3121
3122 if (! TARGET_88100
3123 && recog_memoized (insn) >= 0
3124 && get_attr_type (insn) == TYPE_STORE
3125 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3126 return cost - 4; /* 88110 store reservation station. */
3127
3128 return cost;
3129 }
3130
3131 void
m88k_override_options()3132 m88k_override_options ()
3133 {
3134 if ((target_flags & MASK_88000) == 0)
3135 target_flags |= CPU_DEFAULT;
3136
3137 if (TARGET_88110)
3138 {
3139 target_flags |= MASK_USE_DIV;
3140 target_flags &= ~MASK_CHECK_ZERO_DIV;
3141 }
3142
3143 m88k_cpu = (TARGET_88000 ? PROCESSOR_M88000
3144 : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88110));
3145
3146 if ((target_flags & MASK_EITHER_LARGE_SHIFT) == MASK_EITHER_LARGE_SHIFT)
3147 error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");
3148
3149 if (TARGET_OMIT_LEAF_FRAME_POINTER) /* keep nonleaf frame pointers */
3150 flag_omit_frame_pointer = 1;
3151
3152 /* On the m88100, it is desirable to align functions to a cache line.
3153 The m88110 cache is small, so align to an 8 byte boundary. */
3154 if (align_functions == 0)
3155 align_functions = TARGET_88100 ? 16 : 8;
3156 }
3157