]> gcc.gnu.org Git - gcc.git/blame - gcc/config/arm/arm.c
Say a bit more regarding configuration triplets.
[gcc.git] / gcc / config / arm / arm.c
CommitLineData
cce8749e 1/* Output routines for GCC for ARM/RISCiX.
84ed5e79 2 Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
cce8749e
CH
3 Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 and Martin Simmons (@harleqn.co.uk).
ff9940b0 5 More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk)
cce8749e
CH
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING. If not, write to
8fb289e7
RK
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
ff9940b0 23
cce8749e 24#include <stdio.h>
f3bb6135 25#include <string.h>
e3166964 26#include "assert.h"
cce8749e
CH
27#include "config.h"
28#include "rtl.h"
29#include "regs.h"
30#include "hard-reg-set.h"
31#include "real.h"
32#include "insn-config.h"
33#include "conditions.h"
34#include "insn-flags.h"
35#include "output.h"
36#include "insn-attr.h"
37#include "flags.h"
af48348a 38#include "reload.h"
e2c671ba 39#include "tree.h"
bee06f3d 40#include "expr.h"
cce8749e
CH
41
42/* The maximum number of insns skipped which will be conditionalised if
43 possible. */
44#define MAX_INSNS_SKIPPED 5
45
46/* Some function declarations. */
cce8749e
CH
47extern FILE *asm_out_file;
48extern char *output_multi_immediate ();
cce8749e
CH
49extern void arm_increase_location ();
50
f3bb6135
RE
51HOST_WIDE_INT int_log2 PROTO ((HOST_WIDE_INT));
52static int get_prologue_size PROTO ((void));
2b835d68
RE
53static int arm_gen_constant PROTO ((enum rtx_code, enum machine_mode,
54 HOST_WIDE_INT, rtx, rtx, int, int));
f3bb6135 55
ff9940b0
RE
56/* Define the information needed to generate branch insns. This is
57 stored from the compare operation. */
58
59rtx arm_compare_op0, arm_compare_op1;
60int arm_compare_fp;
61
62/* What type of cpu are we compiling for? */
ff9940b0
RE
63enum processor_type arm_cpu;
64
ddd5a7c1 65/* What type of floating point are we compiling for? */
bee06f3d
RE
66enum floating_point_type arm_fpu;
67
2b835d68
RE
68/* What program mode is the cpu running in? 26-bit mode or 32-bit mode */
69enum prog_mode_type arm_prgmode;
70
71char *target_cpu_name = ARM_CPU_NAME;
72char *target_fpe_name = NULL;
73
74/* Nonzero if this is an "M" variant of the processor. */
75int arm_fast_multiply = 0;
76
77/* Nonzero if this chip support the ARM Architecture 4 extensions */
78int arm_arch4 = 0;
79
cce8749e
CH
80/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
81 must report the mode of the memory reference from PRINT_OPERAND to
82 PRINT_OPERAND_ADDRESS. */
f3bb6135 83enum machine_mode output_memory_reference_mode;
cce8749e
CH
84
85/* Nonzero if the prologue must setup `fp'. */
86int current_function_anonymous_args;
87
88/* Location counter of .text segment. */
89int arm_text_location = 0;
90
ff9940b0
RE
91/* Set to one if we think that lr is only saved because of subroutine calls,
92 but all of these can be `put after' return insns */
93int lr_save_eliminated;
94
cce8749e
CH
95/* A hash table is used to store text segment labels and their associated
96 offset from the start of the text segment. */
97struct label_offset
98{
99 char *name;
100 int offset;
101 struct label_offset *cdr;
102};
103
104#define LABEL_HASH_SIZE 257
105
106static struct label_offset *offset_table[LABEL_HASH_SIZE];
107
ff9940b0
RE
108/* Set to 1 when a return insn is output, this means that the epilogue
109 is not needed. */
110
111static int return_used_this_function;
112
2b835d68
RE
113static int arm_constant_limit = 3;
114
cce8749e
CH
115/* For an explanation of these variables, see final_prescan_insn below. */
116int arm_ccfsm_state;
84ed5e79 117enum arm_cond_code arm_current_cc;
cce8749e
CH
118rtx arm_target_insn;
119int arm_target_label;
9997d19d
RE
120
121/* The condition codes of the ARM, and the inverse function. */
122char *arm_condition_codes[] =
123{
124 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
125 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
126};
127
84ed5e79 128static enum arm_cond_code get_arm_condition_code ();
2b835d68
RE
129
130\f
131/* Initialization code */
132
133#define FL_CO_PROC 0x01 /* Has external co-processor bus */
134#define FL_FAST_MULT 0x02 /* Fast multiply */
135#define FL_MODE26 0x04 /* 26-bit mode support */
136#define FL_MODE32 0x08 /* 32-bit mode support */
137#define FL_ARCH4 0x10 /* Architecture rel 4 */
138#define FL_THUMB 0x20 /* Thumb aware */
139struct processors
140{
141 char *name;
142 enum processor_type type;
143 unsigned int flags;
144};
145
146/* Not all of these give usefully different compilation alternatives,
147 but there is no simple way of generalizing them. */
148static struct processors all_procs[] =
149{
150 {"arm2", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26},
151 {"arm250", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26},
152 {"arm3", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26},
153 {"arm6", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26},
154 {"arm60", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26},
155 {"arm600", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26},
156 {"arm610", PROCESSOR_ARM6, FL_MODE32 | FL_MODE26},
157 {"arm620", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26},
158 {"arm7", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
159 {"arm70", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
160 {"arm7d", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
161 {"arm7di", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
162 {"arm7dm", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
163 | FL_MODE26)},
164 {"arm7dmi", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
165 | FL_MODE26)},
166 {"arm700", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
167 {"arm700i", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
168 {"arm710", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26},
169 {"arm710c", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26},
170 {"arm7500", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26},
171 {"arm7tdmi", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
172 | FL_ARCH4 | FL_THUMB)},
173 {NULL, 0, 0}
174};
175
176/* Fix up any incompatible options that the user has specified.
177 This has now turned into a maze. */
178void
179arm_override_options ()
180{
181 int arm_thumb_aware = 0;
182
183 if (write_symbols != NO_DEBUG && flag_omit_frame_pointer)
184 warning ("-g with -fomit-frame-pointer may not give sensible debugging");
185
186 if (TARGET_POKE_FUNCTION_NAME)
187 target_flags |= ARM_FLAG_APCS_FRAME;
188
189 if (TARGET_6)
190 {
191 warning ("Option '-m6' deprecated. Use: '-mapcs-32' or -mcpu-<proc>");
192 target_flags |= ARM_FLAG_APCS_32;
193 arm_cpu = PROCESSOR_ARM6;
194 }
195
196 if (TARGET_3)
197 {
198 warning ("Option '-m3' deprecated. Use: '-mapcs-26' or -mcpu-<proc>");
199 target_flags &= ~ARM_FLAG_APCS_32;
200 arm_cpu = PROCESSOR_ARM2;
201 }
202
203 if ((TARGET_3 || TARGET_6) && target_cpu_name != NULL)
204 fatal ("Incompatible mix of old and new options. -m%d and -mcpu-%s",
205 TARGET_3 ? 3 : 6, target_cpu_name);
206
207 if (TARGET_APCS_REENT && flag_pic)
208 fatal ("-fpic and -mapcs-reent are incompatible");
209
210 if (TARGET_APCS_REENT)
211 warning ("APCS reentrant code not supported. Ignored");
212
213 if (flag_pic)
214 warning ("Position independent code not supported. Ignored");
215
216 if (TARGET_APCS_FLOAT)
217 warning ("Passing floating point arguments in fp regs not yet supported");
218
219 if (TARGET_APCS_STACK && ! TARGET_APCS)
220 {
221 warning ("-mapcs-stack-check incompatible with -mno-apcs-frame");
222 target_flags |= ARM_FLAG_APCS_FRAME;
223 }
224
225 arm_cpu = TARGET_6 ? PROCESSOR_ARM6: PROCESSOR_ARM2;
226 arm_fpu = FP_HARD;
227
228 if (target_cpu_name != NULL)
229 {
230 char *c = target_cpu_name;
231 struct processors *proc;
232
233 /* Match against the supported types. */
234 for (proc = all_procs; proc->name != NULL; proc++)
235 {
236 if (strcmp (proc->name, c) == 0)
237 break;
238 }
239
240 if (proc->name)
241 {
242 arm_cpu = proc->type;
243
244 /* Default value for floating point code... if no co-processor
245 bus, then schedule for emulated floating point. Otherwise,
246 assume the user has an FPA, unless overridden with -mfpe-... */
247 if (proc->flags & FL_CO_PROC == 0)
248 arm_fpu = FP_SOFT3;
249 else
250 arm_fpu = FP_HARD;
251 arm_fast_multiply = (proc->flags & FL_FAST_MULT) != 0;
252 arm_arch4 = (proc->flags & FL_ARCH4) != 0;
253 arm_thumb_aware = (proc->flags & FL_THUMB) != 0;
254 /* Processors with a load delay slot can load constants faster,
255 from the pool than it takes to construct them, so reduce the
256 complexity of the constant that we will try to generate
257 inline. */
258 }
259 else
260 fatal ("Unrecognized cpu type: %s", target_cpu_name);
261 }
262
263 if (target_fpe_name)
264 {
265 if (strcmp (target_fpe_name, "2") == 0)
266 arm_fpu = FP_SOFT2;
267 else if (strcmp (target_fpe_name, "3") == 0)
268 arm_fpu = FP_SOFT3;
269 else
270 fatal ("Invalid floating point emulation option: -mfpe-%s",
271 target_fpe_name);
272 }
273
274 if (TARGET_THUMB_INTERWORK && ! arm_thumb_aware)
275 {
276 warning ("This processor variant does not support Thumb interworking");
277 target_flags &= ~ARM_FLAG_THUMB;
278 }
279
280 if (TARGET_FPE && arm_fpu != FP_HARD)
281 arm_fpu = FP_SOFT2;
282
283 /* For arm2/3 there is no need to do any scheduling if there is only
284 a floating point emulator, or we are doing software floating-point. */
285 if ((TARGET_SOFT_FLOAT || arm_fpu != FP_HARD) && arm_cpu == PROCESSOR_ARM2)
286 flag_schedule_insns = flag_schedule_insns_after_reload = 0;
287
288 arm_prog_mode = TARGET_APCS_32 ? PROG_MODE_PROG32 : PROG_MODE_PROG26;
289}
290
cce8749e 291\f
ff9940b0
RE
292/* Return 1 if it is possible to return using a single instruction */
293
294int
295use_return_insn ()
296{
297 int regno;
298
299 if (!reload_completed ||current_function_pretend_args_size
300 || current_function_anonymous_args
301 || (get_frame_size () && !(TARGET_APCS || frame_pointer_needed)))
302 return 0;
303
304 /* Can't be done if any of the FPU regs are pushed, since this also
305 requires an insn */
306 for (regno = 20; regno < 24; regno++)
307 if (regs_ever_live[regno])
308 return 0;
309
31fdb4d5
DE
310 /* If a function is naked, don't use the "return" insn. */
311 if (arm_naked_function_p (current_function_decl))
312 return 0;
313
ff9940b0
RE
314 return 1;
315}
316
cce8749e
CH
317/* Return TRUE if int I is a valid immediate ARM constant. */
318
319int
320const_ok_for_arm (i)
ff9940b0 321 HOST_WIDE_INT i;
cce8749e 322{
ff9940b0 323 unsigned HOST_WIDE_INT mask = ~0xFF;
cce8749e 324
e2c671ba
RE
325 /* Fast return for 0 and powers of 2 */
326 if ((i & (i - 1)) == 0)
327 return TRUE;
328
cce8749e
CH
329 do
330 {
abaa26e5 331 if ((i & mask & (unsigned HOST_WIDE_INT) 0xffffffff) == 0)
f3bb6135 332 return TRUE;
abaa26e5
RE
333 mask =
334 (mask << 2) | ((mask & (unsigned HOST_WIDE_INT) 0xffffffff)
335 >> (32 - 2)) | ~((unsigned HOST_WIDE_INT) 0xffffffff);
cce8749e
CH
336 } while (mask != ~0xFF);
337
f3bb6135
RE
338 return FALSE;
339}
cce8749e 340
e2c671ba
RE
341/* Return true if I is a valid constant for the operation CODE. */
342int
343const_ok_for_op (i, code, mode)
344 HOST_WIDE_INT i;
345 enum rtx_code code;
346 enum machine_mode mode;
347{
348 if (const_ok_for_arm (i))
349 return 1;
350
351 switch (code)
352 {
353 case PLUS:
354 return const_ok_for_arm (ARM_SIGN_EXTEND (-i));
355
356 case MINUS: /* Should only occur with (MINUS I reg) => rsb */
357 case XOR:
358 case IOR:
359 return 0;
360
361 case AND:
362 return const_ok_for_arm (ARM_SIGN_EXTEND (~i));
363
364 default:
365 abort ();
366 }
367}
368
369/* Emit a sequence of insns to handle a large constant.
370 CODE is the code of the operation required, it can be any of SET, PLUS,
371 IOR, AND, XOR, MINUS;
372 MODE is the mode in which the operation is being performed;
373 VAL is the integer to operate on;
374 SOURCE is the other operand (a register, or a null-pointer for SET);
375 SUBTARGETS means it is safe to create scratch registers if that will
2b835d68
RE
376 either produce a simpler sequence, or we will want to cse the values.
377 Return value is the number of insns emitted. */
e2c671ba
RE
378
379int
380arm_split_constant (code, mode, val, target, source, subtargets)
381 enum rtx_code code;
382 enum machine_mode mode;
383 HOST_WIDE_INT val;
384 rtx target;
385 rtx source;
386 int subtargets;
2b835d68
RE
387{
388 if (subtargets || code == SET
389 || (GET_CODE (target) == REG && GET_CODE (source) == REG
390 && REGNO (target) != REGNO (source)))
391 {
392 rtx temp;
393
394 if (arm_gen_constant (code, mode, val, target, source, 1, 0)
395 > arm_constant_limit + (code != SET))
396 {
397 if (code == SET)
398 {
399 /* Currently SET is the only monadic value for CODE, all
400 the rest are diadic. */
401 emit_insn (gen_rtx (SET, VOIDmode, target, GEN_INT (val)));
402 return 1;
403 }
404 else
405 {
406 rtx temp = subtargets ? gen_reg_rtx (mode) : target;
407
408 emit_insn (gen_rtx (SET, VOIDmode, temp, GEN_INT (val)));
409 /* For MINUS, the value is subtracted from, since we never
410 have subtraction of a constant. */
411 if (code == MINUS)
412 emit_insn (gen_rtx (SET, VOIDmode, target,
413 gen_rtx (code, mode, temp, source)));
414 else
415 emit_insn (gen_rtx (SET, VOIDmode, target,
416 gen_rtx (code, mode, source, temp)));
417 return 2;
418 }
419 }
420 }
421
422 return arm_gen_constant (code, mode, val, target, source, subtargets, 1);
423}
424
425/* As above, but extra parameter GENERATE which, if clear, suppresses
426 RTL generation. */
427int
428arm_gen_constant (code, mode, val, target, source, subtargets, generate)
429 enum rtx_code code;
430 enum machine_mode mode;
431 HOST_WIDE_INT val;
432 rtx target;
433 rtx source;
434 int subtargets;
435 int generate;
e2c671ba
RE
436{
437 int can_add = 0;
438 int can_invert = 0;
439 int can_negate = 0;
440 int can_negate_initial = 0;
441 int can_shift = 0;
442 int i;
443 int num_bits_set = 0;
444 int set_sign_bit_copies = 0;
445 int clear_sign_bit_copies = 0;
446 int clear_zero_bit_copies = 0;
447 int set_zero_bit_copies = 0;
448 int insns = 0;
449 rtx new_src;
450 unsigned HOST_WIDE_INT temp1, temp2;
451 unsigned HOST_WIDE_INT remainder = val & 0xffffffff;
452
453 /* find out which operations are safe for a given CODE. Also do a quick
454 check for degenerate cases; these can occur when DImode operations
455 are split. */
456 switch (code)
457 {
458 case SET:
459 can_invert = 1;
460 can_shift = 1;
461 can_negate = 1;
462 break;
463
464 case PLUS:
465 can_negate = 1;
466 can_negate_initial = 1;
467 break;
468
469 case IOR:
470 if (remainder == 0xffffffff)
471 {
2b835d68
RE
472 if (generate)
473 emit_insn (gen_rtx (SET, VOIDmode, target,
474 GEN_INT (ARM_SIGN_EXTEND (val))));
e2c671ba
RE
475 return 1;
476 }
477 if (remainder == 0)
478 {
479 if (reload_completed && rtx_equal_p (target, source))
480 return 0;
2b835d68
RE
481 if (generate)
482 emit_insn (gen_rtx (SET, VOIDmode, target, source));
e2c671ba
RE
483 return 1;
484 }
485 break;
486
487 case AND:
488 if (remainder == 0)
489 {
2b835d68
RE
490 if (generate)
491 emit_insn (gen_rtx (SET, VOIDmode, target, const0_rtx));
e2c671ba
RE
492 return 1;
493 }
494 if (remainder == 0xffffffff)
495 {
496 if (reload_completed && rtx_equal_p (target, source))
497 return 0;
2b835d68
RE
498 if (generate)
499 emit_insn (gen_rtx (SET, VOIDmode, target, source));
e2c671ba
RE
500 return 1;
501 }
502 can_invert = 1;
503 break;
504
505 case XOR:
506 if (remainder == 0)
507 {
508 if (reload_completed && rtx_equal_p (target, source))
509 return 0;
2b835d68
RE
510 if (generate)
511 emit_insn (gen_rtx (SET, VOIDmode, target, source));
e2c671ba
RE
512 return 1;
513 }
514 if (remainder == 0xffffffff)
515 {
2b835d68
RE
516 if (generate)
517 emit_insn (gen_rtx (SET, VOIDmode, target,
518 gen_rtx (NOT, mode, source)));
e2c671ba
RE
519 return 1;
520 }
521
522 /* We don't know how to handle this yet below. */
523 abort ();
524
525 case MINUS:
526 /* We treat MINUS as (val - source), since (source - val) is always
527 passed as (source + (-val)). */
528 if (remainder == 0)
529 {
2b835d68
RE
530 if (generate)
531 emit_insn (gen_rtx (SET, VOIDmode, target,
532 gen_rtx (NEG, mode, source)));
e2c671ba
RE
533 return 1;
534 }
535 if (const_ok_for_arm (val))
536 {
2b835d68
RE
537 if (generate)
538 emit_insn (gen_rtx (SET, VOIDmode, target,
539 gen_rtx (MINUS, mode, GEN_INT (val), source)));
e2c671ba
RE
540 return 1;
541 }
542 can_negate = 1;
543
544 break;
545
546 default:
547 abort ();
548 }
549
550 /* If we can do it in one insn get out quickly */
551 if (const_ok_for_arm (val)
552 || (can_negate_initial && const_ok_for_arm (-val))
553 || (can_invert && const_ok_for_arm (~val)))
554 {
2b835d68
RE
555 if (generate)
556 emit_insn (gen_rtx (SET, VOIDmode, target,
557 (source ? gen_rtx (code, mode, source,
558 GEN_INT (val))
559 : GEN_INT (val))));
e2c671ba
RE
560 return 1;
561 }
562
563
564 /* Calculate a few attributes that may be useful for specific
565 optimizations. */
566
567 for (i = 31; i >= 0; i--)
568 {
569 if ((remainder & (1 << i)) == 0)
570 clear_sign_bit_copies++;
571 else
572 break;
573 }
574
575 for (i = 31; i >= 0; i--)
576 {
577 if ((remainder & (1 << i)) != 0)
578 set_sign_bit_copies++;
579 else
580 break;
581 }
582
583 for (i = 0; i <= 31; i++)
584 {
585 if ((remainder & (1 << i)) == 0)
586 clear_zero_bit_copies++;
587 else
588 break;
589 }
590
591 for (i = 0; i <= 31; i++)
592 {
593 if ((remainder & (1 << i)) != 0)
594 set_zero_bit_copies++;
595 else
596 break;
597 }
598
599 switch (code)
600 {
601 case SET:
602 /* See if we can do this by sign_extending a constant that is known
603 to be negative. This is a good, way of doing it, since the shift
604 may well merge into a subsequent insn. */
605 if (set_sign_bit_copies > 1)
606 {
607 if (const_ok_for_arm
608 (temp1 = ARM_SIGN_EXTEND (remainder
609 << (set_sign_bit_copies - 1))))
610 {
2b835d68
RE
611 if (generate)
612 {
613 new_src = subtargets ? gen_reg_rtx (mode) : target;
614 emit_insn (gen_rtx (SET, VOIDmode, new_src,
615 GEN_INT (temp1)));
616 emit_insn (gen_ashrsi3 (target, new_src,
617 GEN_INT (set_sign_bit_copies - 1)));
618 }
e2c671ba
RE
619 return 2;
620 }
621 /* For an inverted constant, we will need to set the low bits,
622 these will be shifted out of harm's way. */
623 temp1 |= (1 << (set_sign_bit_copies - 1)) - 1;
624 if (const_ok_for_arm (~temp1))
625 {
2b835d68
RE
626 if (generate)
627 {
628 new_src = subtargets ? gen_reg_rtx (mode) : target;
629 emit_insn (gen_rtx (SET, VOIDmode, new_src,
630 GEN_INT (temp1)));
631 emit_insn (gen_ashrsi3 (target, new_src,
632 GEN_INT (set_sign_bit_copies - 1)));
633 }
e2c671ba
RE
634 return 2;
635 }
636 }
637
638 /* See if we can generate this by setting the bottom (or the top)
639 16 bits, and then shifting these into the other half of the
640 word. We only look for the simplest cases, to do more would cost
641 too much. Be careful, however, not to generate this when the
642 alternative would take fewer insns. */
643 if (val & 0xffff0000)
644 {
645 temp1 = remainder & 0xffff0000;
646 temp2 = remainder & 0x0000ffff;
647
648 /* Overlaps outside this range are best done using other methods. */
649 for (i = 9; i < 24; i++)
650 {
651 if ((((temp2 | (temp2 << i)) & 0xffffffff) == remainder)
652 && ! const_ok_for_arm (temp2))
653 {
2b835d68
RE
654 insns = arm_gen_constant (code, mode, temp2,
655 new_src = (subtargets
656 ? gen_reg_rtx (mode)
657 : target),
658 source, subtargets, generate);
e2c671ba 659 source = new_src;
2b835d68
RE
660 if (generate)
661 emit_insn (gen_rtx (SET, VOIDmode, target,
662 gen_rtx (IOR, mode,
663 gen_rtx (ASHIFT, mode, source,
664 GEN_INT (i)),
665 source)));
e2c671ba
RE
666 return insns + 1;
667 }
668 }
669
670 /* Don't duplicate cases already considered. */
671 for (i = 17; i < 24; i++)
672 {
673 if (((temp1 | (temp1 >> i)) == remainder)
674 && ! const_ok_for_arm (temp1))
675 {
2b835d68
RE
676 insns = arm_gen_constant (code, mode, temp1,
677 new_src = (subtargets
678 ? gen_reg_rtx (mode)
679 : target),
680 source, subtargets, generate);
e2c671ba 681 source = new_src;
2b835d68
RE
682 if (generate)
683 emit_insn (gen_rtx (SET, VOIDmode, target,
684 gen_rtx (IOR, mode,
685 gen_rtx (LSHIFTRT, mode,
686 source, GEN_INT (i)),
687 source)));
e2c671ba
RE
688 return insns + 1;
689 }
690 }
691 }
692 break;
693
694 case IOR:
695 case XOR:
696 /* If we have IOR or XOR, and the inverse of the constant can be loaded
697 in a single instruction, and we can find a temporary to put it in,
698 then this can be done in two instructions instead of 3-4. */
699 if (subtargets
700 || (reload_completed && ! reg_mentioned_p (target, source)))
701 {
702 if (const_ok_for_arm (ARM_SIGN_EXTEND (~ val)))
703 {
2b835d68
RE
704 if (generate)
705 {
706 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
e2c671ba 707
2b835d68
RE
708 emit_insn (gen_rtx (SET, VOIDmode, sub,
709 GEN_INT (ARM_SIGN_EXTEND (~ val))));
710 emit_insn (gen_rtx (SET, VOIDmode, target,
711 gen_rtx (code, mode, source, sub)));
712 }
e2c671ba
RE
713 return 2;
714 }
715 }
716
717 if (code == XOR)
718 break;
719
720 if (set_sign_bit_copies > 8
721 && (val & (-1 << (32 - set_sign_bit_copies))) == val)
722 {
2b835d68
RE
723 if (generate)
724 {
725 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
726 rtx shift = GEN_INT (set_sign_bit_copies);
727
728 emit_insn (gen_rtx (SET, VOIDmode, sub,
729 gen_rtx (NOT, mode,
730 gen_rtx (ASHIFT, mode, source,
731 shift))));
732 emit_insn (gen_rtx (SET, VOIDmode, target,
733 gen_rtx (NOT, mode,
734 gen_rtx (LSHIFTRT, mode, sub,
735 shift))));
736 }
e2c671ba
RE
737 return 2;
738 }
739
740 if (set_zero_bit_copies > 8
741 && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)
742 {
2b835d68
RE
743 if (generate)
744 {
745 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
746 rtx shift = GEN_INT (set_zero_bit_copies);
747
748 emit_insn (gen_rtx (SET, VOIDmode, sub,
749 gen_rtx (NOT, mode,
750 gen_rtx (LSHIFTRT, mode, source,
751 shift))));
752 emit_insn (gen_rtx (SET, VOIDmode, target,
753 gen_rtx (NOT, mode,
754 gen_rtx (ASHIFT, mode, sub,
755 shift))));
756 }
e2c671ba
RE
757 return 2;
758 }
759
760 if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~ val)))
761 {
2b835d68
RE
762 if (generate)
763 {
764 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
765 emit_insn (gen_rtx (SET, VOIDmode, sub,
766 gen_rtx (NOT, mode, source)));
767 source = sub;
768 if (subtargets)
769 sub = gen_reg_rtx (mode);
770 emit_insn (gen_rtx (SET, VOIDmode, sub,
771 gen_rtx (AND, mode, source,
772 GEN_INT (temp1))));
773 emit_insn (gen_rtx (SET, VOIDmode, target,
774 gen_rtx (NOT, mode, sub)));
775 }
e2c671ba
RE
776 return 3;
777 }
778 break;
779
780 case AND:
781 /* See if two shifts will do 2 or more insn's worth of work. */
782 if (clear_sign_bit_copies >= 16 && clear_sign_bit_copies < 24)
783 {
784 HOST_WIDE_INT shift_mask = ((0xffffffff
785 << (32 - clear_sign_bit_copies))
786 & 0xffffffff);
787 rtx new_source;
2b835d68 788 rtx shift;
e2c671ba
RE
789
790 if ((remainder | shift_mask) != 0xffffffff)
791 {
2b835d68
RE
792 if (generate)
793 {
794 new_source = subtargets ? gen_reg_rtx (mode) : target;
795 insns = arm_gen_constant (AND, mode, remainder | shift_mask,
796 new_source, source, subtargets, 1);
797 source = new_source;
798 }
799 else
800 insns = arm_gen_constant (AND, mode, remainder | shift_mask,
801 new_source, source, subtargets, 0);
802 }
803
804 if (generate)
805 {
806 shift = GEN_INT (clear_sign_bit_copies);
e2c671ba 807 new_source = subtargets ? gen_reg_rtx (mode) : target;
2b835d68
RE
808 emit_insn (gen_ashlsi3 (new_source, source, shift));
809 emit_insn (gen_lshrsi3 (target, new_source, shift));
e2c671ba
RE
810 }
811
e2c671ba
RE
812 return insns + 2;
813 }
814
815 if (clear_zero_bit_copies >= 16 && clear_zero_bit_copies < 24)
816 {
817 HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1;
818 rtx new_source;
2b835d68 819 rtx shift;
e2c671ba
RE
820
821 if ((remainder | shift_mask) != 0xffffffff)
822 {
2b835d68
RE
823 if (generate)
824 {
825 new_source = subtargets ? gen_reg_rtx (mode) : target;
826 insns = arm_gen_constant (AND, mode, remainder | shift_mask,
827 new_source, source, subtargets, 1);
828 source = new_source;
829 }
830 else
831 insns = arm_gen_constant (AND, mode, remainder | shift_mask,
832 new_source, source, subtargets, 0);
833 }
834
835 if (generate)
836 {
837 shift = GEN_INT (clear_zero_bit_copies);
e2c671ba 838 new_source = subtargets ? gen_reg_rtx (mode) : target;
2b835d68
RE
839 emit_insn (gen_lshrsi3 (new_source, source, shift));
840 emit_insn (gen_ashlsi3 (target, new_source, shift));
e2c671ba
RE
841 }
842
e2c671ba
RE
843 return insns + 2;
844 }
845
846 break;
847
848 default:
849 break;
850 }
851
852 for (i = 0; i < 32; i++)
853 if (remainder & (1 << i))
854 num_bits_set++;
855
856 if (code == AND || (can_invert && num_bits_set > 16))
857 remainder = (~remainder) & 0xffffffff;
858 else if (code == PLUS && num_bits_set > 16)
859 remainder = (-remainder) & 0xffffffff;
860 else
861 {
862 can_invert = 0;
863 can_negate = 0;
864 }
865
866 /* Now try and find a way of doing the job in either two or three
867 instructions.
868 We start by looking for the largest block of zeros that are aligned on
869 a 2-bit boundary, we then fill up the temps, wrapping around to the
870 top of the word when we drop off the bottom.
871 In the worst case this code should produce no more than four insns. */
872 {
873 int best_start = 0;
874 int best_consecutive_zeros = 0;
875
876 for (i = 0; i < 32; i += 2)
877 {
878 int consecutive_zeros = 0;
879
880 if (! (remainder & (3 << i)))
881 {
882 while ((i < 32) && ! (remainder & (3 << i)))
883 {
884 consecutive_zeros += 2;
885 i += 2;
886 }
887 if (consecutive_zeros > best_consecutive_zeros)
888 {
889 best_consecutive_zeros = consecutive_zeros;
890 best_start = i - consecutive_zeros;
891 }
892 i -= 2;
893 }
894 }
895
896 /* Now start emitting the insns, starting with the one with the highest
897 bit set: we do this so that the smallest number will be emitted last;
898 this is more likely to be combinable with addressing insns. */
899 i = best_start;
900 do
901 {
902 int end;
903
904 if (i <= 0)
905 i += 32;
906 if (remainder & (3 << (i - 2)))
907 {
908 end = i - 8;
909 if (end < 0)
910 end += 32;
911 temp1 = remainder & ((0x0ff << end)
912 | ((i < end) ? (0xff >> (32 - end)) : 0));
913 remainder &= ~temp1;
914
915 if (code == SET)
916 {
2b835d68
RE
917 if (generate)
918 emit_insn (gen_rtx (SET, VOIDmode,
919 new_src = (subtargets
920 ? gen_reg_rtx (mode)
921 : target),
922 GEN_INT (can_invert ? ~temp1 : temp1)));
e2c671ba
RE
923 can_invert = 0;
924 code = PLUS;
925 }
926 else if (code == MINUS)
927 {
2b835d68
RE
928 if (generate)
929 emit_insn (gen_rtx (SET, VOIDmode,
930 new_src = (subtargets
931 ? gen_reg_rtx (mode)
932 : target),
933 gen_rtx (code, mode, GEN_INT (temp1),
934 source)));
e2c671ba
RE
935 code = PLUS;
936 }
937 else
938 {
2b835d68
RE
939 if (generate)
940 emit_insn (gen_rtx (SET, VOIDmode,
941 new_src = (remainder
942 ? (subtargets
943 ? gen_reg_rtx (mode)
944 : target)
945 : target),
946 gen_rtx (code, mode, source,
947 GEN_INT (can_invert ? ~temp1
948 : (can_negate
949 ? -temp1
950 : temp1)))));
e2c671ba
RE
951 }
952
953 insns++;
954 source = new_src;
955 i -= 6;
956 }
957 i -= 2;
958 } while (remainder);
959 }
960 return insns;
961}
962
2b835d68
RE
963/* Handle aggregates that are not laid out in a BLKmode element.
964 This is a sub-element of RETURN_IN_MEMORY. */
965int
966arm_return_in_memory (type)
967 tree type;
968{
969 if (TREE_CODE (type) == RECORD_TYPE)
970 {
971 tree field;
972
973 /* For a struct, we can return in a register if every element was a
974 bit-field. */
975 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
976 if (TREE_CODE (field) != FIELD_DECL
977 || ! DECL_BIT_FIELD_TYPE (field))
978 return 1;
979
980 return 0;
981 }
982 else if (TREE_CODE (type) == UNION_TYPE)
983 {
984 tree field;
985
986 /* Unions can be returned in registers if every element is
987 integral, or can be returned in an integer register. */
988 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
989 {
990 if (TREE_CODE (field) != FIELD_DECL
991 || (AGGREGATE_TYPE_P (TREE_TYPE (field))
992 && RETURN_IN_MEMORY (TREE_TYPE (field)))
993 || FLOAT_TYPE_P (TREE_TYPE (field)))
994 return 1;
995 }
996 return 0;
997 }
998 /* XXX Not sure what should be done for other aggregates, so put them in
999 memory. */
1000 return 1;
1001}
1002
e2c671ba
RE
1003#define REG_OR_SUBREG_REG(X) \
1004 (GET_CODE (X) == REG \
1005 || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
1006
1007#define REG_OR_SUBREG_RTX(X) \
1008 (GET_CODE (X) == REG ? (X) : SUBREG_REG (X))
1009
1010#define ARM_FRAME_RTX(X) \
1011 ((X) == frame_pointer_rtx || (X) == stack_pointer_rtx \
1012 || (X) == arg_pointer_rtx)
1013
1014int
1015arm_rtx_costs (x, code, outer_code)
1016 rtx x;
1017 enum rtx_code code, outer_code;
1018{
1019 enum machine_mode mode = GET_MODE (x);
1020 enum rtx_code subcode;
1021 int extra_cost;
1022
1023 switch (code)
1024 {
1025 case MEM:
1026 /* Memory costs quite a lot for the first word, but subsequent words
1027 load at the equivalent of a single insn each. */
1028 return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
1029 + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
1030
1031 case DIV:
1032 case MOD:
1033 return 100;
1034
1035 case ROTATE:
1036 if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
1037 return 4;
1038 /* Fall through */
1039 case ROTATERT:
1040 if (mode != SImode)
1041 return 8;
1042 /* Fall through */
1043 case ASHIFT: case LSHIFTRT: case ASHIFTRT:
1044 if (mode == DImode)
1045 return (8 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : 8)
1046 + ((GET_CODE (XEXP (x, 0)) == REG
1047 || (GET_CODE (XEXP (x, 0)) == SUBREG
1048 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
1049 ? 0 : 8));
1050 return (1 + ((GET_CODE (XEXP (x, 0)) == REG
1051 || (GET_CODE (XEXP (x, 0)) == SUBREG
1052 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
1053 ? 0 : 4)
1054 + ((GET_CODE (XEXP (x, 1)) == REG
1055 || (GET_CODE (XEXP (x, 1)) == SUBREG
1056 && GET_CODE (SUBREG_REG (XEXP (x, 1))) == REG)
1057 || (GET_CODE (XEXP (x, 1)) == CONST_INT))
1058 ? 0 : 4));
1059
1060 case MINUS:
1061 if (mode == DImode)
1062 return (4 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 8)
1063 + ((REG_OR_SUBREG_REG (XEXP (x, 0))
1064 || (GET_CODE (XEXP (x, 0)) == CONST_INT
1065 && const_ok_for_arm (INTVAL (XEXP (x, 0)))))
1066 ? 0 : 8));
1067
1068 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1069 return (2 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
1070 || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
1071 && const_double_rtx_ok_for_fpu (XEXP (x, 1))))
1072 ? 0 : 8)
1073 + ((REG_OR_SUBREG_REG (XEXP (x, 0))
1074 || (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE
1075 && const_double_rtx_ok_for_fpu (XEXP (x, 0))))
1076 ? 0 : 8));
1077
1078 if (((GET_CODE (XEXP (x, 0)) == CONST_INT
1079 && const_ok_for_arm (INTVAL (XEXP (x, 0)))
1080 && REG_OR_SUBREG_REG (XEXP (x, 1))))
1081 || (((subcode = GET_CODE (XEXP (x, 1))) == ASHIFT
1082 || subcode == ASHIFTRT || subcode == LSHIFTRT
1083 || subcode == ROTATE || subcode == ROTATERT
1084 || (subcode == MULT
1085 && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
1086 && ((INTVAL (XEXP (XEXP (x, 1), 1)) &
1087 (INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0)))
1088 && REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 0))
1089 && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 1))
1090 || GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)
1091 && REG_OR_SUBREG_REG (XEXP (x, 0))))
1092 return 1;
1093 /* Fall through */
1094
1095 case PLUS:
1096 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1097 return (2 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
1098 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
1099 || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
1100 && const_double_rtx_ok_for_fpu (XEXP (x, 1))))
1101 ? 0 : 8));
1102
1103 /* Fall through */
1104 case AND: case XOR: case IOR:
1105 extra_cost = 0;
1106
1107 /* Normally the frame registers will be spilt into reg+const during
1108 reload, so it is a bad idea to combine them with other instructions,
1109 since then they might not be moved outside of loops. As a compromise
1110 we allow integration with ops that have a constant as their second
1111 operand. */
1112 if ((REG_OR_SUBREG_REG (XEXP (x, 0))
1113 && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))
1114 && GET_CODE (XEXP (x, 1)) != CONST_INT)
1115 || (REG_OR_SUBREG_REG (XEXP (x, 0))
1116 && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))))
1117 extra_cost = 4;
1118
1119 if (mode == DImode)
1120 return (4 + extra_cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
1121 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
1122 || (GET_CODE (XEXP (x, 1)) == CONST_INT
1123 && const_ok_for_op (INTVAL (XEXP (x, 1)), code, mode)))
1124 ? 0 : 8));
1125
1126 if (REG_OR_SUBREG_REG (XEXP (x, 0)))
1127 return (1 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : extra_cost)
1128 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
1129 || (GET_CODE (XEXP (x, 1)) == CONST_INT
1130 && const_ok_for_op (INTVAL (XEXP (x, 1)), code, mode)))
1131 ? 0 : 4));
1132
1133 else if (REG_OR_SUBREG_REG (XEXP (x, 1)))
1134 return (1 + extra_cost
1135 + ((((subcode = GET_CODE (XEXP (x, 0))) == ASHIFT
1136 || subcode == LSHIFTRT || subcode == ASHIFTRT
1137 || subcode == ROTATE || subcode == ROTATERT
1138 || (subcode == MULT
1139 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
1140 && ((INTVAL (XEXP (XEXP (x, 0), 1)) &
1141 (INTVAL (XEXP (XEXP (x, 0), 1)) - 1)) == 0))
1142 && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 0)))
1143 && ((REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 1)))
1144 || GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)))
1145 ? 0 : 4));
1146
1147 return 8;
1148
1149 case MULT:
2b835d68
RE
1150 if (arm_fast_multiply && mode == DImode
1151 && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
1152 && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
1153 || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
1154 return 8;
1155
e2c671ba
RE
1156 if (GET_MODE_CLASS (mode) == MODE_FLOAT
1157 || mode == DImode)
1158 return 30;
1159
1160 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1161 {
2b835d68
RE
1162 unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
1163 & (unsigned HOST_WIDE_INT) 0xffffffff);
e2c671ba
RE
1164 int add_cost = const_ok_for_arm (i) ? 4 : 8;
1165 int j;
2b835d68
RE
1166 int booth_unit_size = (arm_fast_multiply ? 8 : 2);
1167
1168 for (j = 0; i && j < 32; j += booth_unit_size)
e2c671ba 1169 {
2b835d68 1170 i >>= booth_unit_size;
e2c671ba
RE
1171 add_cost += 2;
1172 }
1173
1174 return add_cost;
1175 }
1176
2b835d68
RE
1177 return ((arm_fast_multiply ? 8 : 30)
1178 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
e2c671ba
RE
1179 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));
1180
1181 case NEG:
1182 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1183 return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
1184 /* Fall through */
1185 case NOT:
1186 if (mode == DImode)
1187 return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
1188
1189 return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
1190
1191 case IF_THEN_ELSE:
1192 if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
1193 return 14;
1194 return 2;
1195
1196 case COMPARE:
1197 return 1;
1198
1199 case ABS:
1200 return 4 + (mode == DImode ? 4 : 0);
1201
1202 case SIGN_EXTEND:
1203 if (GET_MODE (XEXP (x, 0)) == QImode)
1204 return (4 + (mode == DImode ? 4 : 0)
1205 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
1206 /* Fall through */
1207 case ZERO_EXTEND:
1208 switch (GET_MODE (XEXP (x, 0)))
1209 {
1210 case QImode:
1211 return (1 + (mode == DImode ? 4 : 0)
1212 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
1213
1214 case HImode:
1215 return (4 + (mode == DImode ? 4 : 0)
1216 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
1217
1218 case SImode:
1219 return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
1220 }
1221 abort ();
1222
1223 default:
1224 return 99;
1225 }
1226}
1227
ff9940b0
RE
1228/* This code has been fixed for cross compilation. */
1229
1230static int fpa_consts_inited = 0;
1231
1232char *strings_fpa[8] = {
2b835d68
RE
1233 "0", "1", "2", "3",
1234 "4", "5", "0.5", "10"
1235};
ff9940b0
RE
1236
1237static REAL_VALUE_TYPE values_fpa[8];
1238
1239static void
1240init_fpa_table ()
1241{
1242 int i;
1243 REAL_VALUE_TYPE r;
1244
1245 for (i = 0; i < 8; i++)
1246 {
1247 r = REAL_VALUE_ATOF (strings_fpa[i], DFmode);
1248 values_fpa[i] = r;
1249 }
f3bb6135 1250
ff9940b0
RE
1251 fpa_consts_inited = 1;
1252}
1253
cce8749e
CH
1254/* Return TRUE if rtx X is a valid immediate FPU constant. */
1255
1256int
1257const_double_rtx_ok_for_fpu (x)
1258 rtx x;
1259{
ff9940b0
RE
1260 REAL_VALUE_TYPE r;
1261 int i;
1262
1263 if (!fpa_consts_inited)
1264 init_fpa_table ();
1265
1266 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1267 if (REAL_VALUE_MINUS_ZERO (r))
1268 return 0;
f3bb6135 1269
ff9940b0
RE
1270 for (i = 0; i < 8; i++)
1271 if (REAL_VALUES_EQUAL (r, values_fpa[i]))
1272 return 1;
f3bb6135 1273
ff9940b0 1274 return 0;
f3bb6135 1275}
ff9940b0
RE
1276
1277/* Return TRUE if rtx X is a valid immediate FPU constant. */
1278
1279int
1280neg_const_double_rtx_ok_for_fpu (x)
1281 rtx x;
1282{
1283 REAL_VALUE_TYPE r;
1284 int i;
1285
1286 if (!fpa_consts_inited)
1287 init_fpa_table ();
1288
1289 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1290 r = REAL_VALUE_NEGATE (r);
1291 if (REAL_VALUE_MINUS_ZERO (r))
1292 return 0;
f3bb6135 1293
ff9940b0
RE
1294 for (i = 0; i < 8; i++)
1295 if (REAL_VALUES_EQUAL (r, values_fpa[i]))
1296 return 1;
f3bb6135 1297
ff9940b0 1298 return 0;
f3bb6135 1299}
cce8749e
CH
1300\f
1301/* Predicates for `match_operand' and `match_operator'. */
1302
ff9940b0
RE
1303/* s_register_operand is the same as register_operand, but it doesn't accept
1304 (SUBREG (MEM)...). */
1305
1306int
1307s_register_operand (op, mode)
1308 register rtx op;
1309 enum machine_mode mode;
1310{
1311 if (GET_MODE (op) != mode && mode != VOIDmode)
1312 return 0;
1313
1314 if (GET_CODE (op) == SUBREG)
f3bb6135 1315 op = SUBREG_REG (op);
ff9940b0
RE
1316
1317 /* We don't consider registers whose class is NO_REGS
1318 to be a register operand. */
1319 return (GET_CODE (op) == REG
1320 && (REGNO (op) >= FIRST_PSEUDO_REGISTER
1321 || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
1322}
1323
e2c671ba
RE
1324/* Only accept reg, subreg(reg), const_int. */
1325
1326int
1327reg_or_int_operand (op, mode)
1328 register rtx op;
1329 enum machine_mode mode;
1330{
1331 if (GET_CODE (op) == CONST_INT)
1332 return 1;
1333
1334 if (GET_MODE (op) != mode && mode != VOIDmode)
1335 return 0;
1336
1337 if (GET_CODE (op) == SUBREG)
1338 op = SUBREG_REG (op);
1339
1340 /* We don't consider registers whose class is NO_REGS
1341 to be a register operand. */
1342 return (GET_CODE (op) == REG
1343 && (REGNO (op) >= FIRST_PSEUDO_REGISTER
1344 || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
1345}
1346
ff9940b0
RE
1347/* Return 1 if OP is an item in memory, given that we are in reload. */
1348
1349int
1350reload_memory_operand (op, mode)
1351 rtx op;
1352 enum machine_mode mode;
1353{
1354 int regno = true_regnum (op);
1355
1356 return (! CONSTANT_P (op)
1357 && (regno == -1
1358 || (GET_CODE (op) == REG
1359 && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
1360}
1361
cce8749e
CH
1362/* Return TRUE for valid operands for the rhs of an ARM instruction. */
1363
1364int
1365arm_rhs_operand (op, mode)
1366 rtx op;
1367 enum machine_mode mode;
1368{
ff9940b0 1369 return (s_register_operand (op, mode)
cce8749e 1370 || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))));
f3bb6135 1371}
cce8749e 1372
ff9940b0
RE
1373/* Return TRUE for valid operands for the rhs of an ARM instruction, or a load.
1374 */
1375
1376int
1377arm_rhsm_operand (op, mode)
1378 rtx op;
1379 enum machine_mode mode;
1380{
1381 return (s_register_operand (op, mode)
1382 || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))
1383 || memory_operand (op, mode));
f3bb6135 1384}
ff9940b0
RE
1385
1386/* Return TRUE for valid operands for the rhs of an ARM instruction, or if a
1387 constant that is valid when negated. */
1388
1389int
1390arm_add_operand (op, mode)
1391 rtx op;
1392 enum machine_mode mode;
1393{
1394 return (s_register_operand (op, mode)
1395 || (GET_CODE (op) == CONST_INT
1396 && (const_ok_for_arm (INTVAL (op))
1397 || const_ok_for_arm (-INTVAL (op)))));
f3bb6135 1398}
ff9940b0
RE
1399
1400int
1401arm_not_operand (op, mode)
1402 rtx op;
1403 enum machine_mode mode;
1404{
1405 return (s_register_operand (op, mode)
1406 || (GET_CODE (op) == CONST_INT
1407 && (const_ok_for_arm (INTVAL (op))
1408 || const_ok_for_arm (~INTVAL (op)))));
f3bb6135 1409}
ff9940b0 1410
5165176d
RE
1411/* Return TRUE if the operand is a memory reference which contains an
1412 offsettable address. */
1413int
1414offsettable_memory_operand (op, mode)
1415 register rtx op;
1416 enum machine_mode mode;
1417{
1418 if (mode == VOIDmode)
1419 mode = GET_MODE (op);
1420
1421 return (mode == GET_MODE (op)
1422 && GET_CODE (op) == MEM
1423 && offsettable_address_p (reload_completed | reload_in_progress,
1424 mode, XEXP (op, 0)));
1425}
1426
1427/* Return TRUE if the operand is a memory reference which is, or can be
1428 made word aligned by adjusting the offset. */
1429int
1430alignable_memory_operand (op, mode)
1431 register rtx op;
1432 enum machine_mode mode;
1433{
1434 rtx reg;
1435
1436 if (mode == VOIDmode)
1437 mode = GET_MODE (op);
1438
1439 if (mode != GET_MODE (op) || GET_CODE (op) != MEM)
1440 return 0;
1441
1442 op = XEXP (op, 0);
1443
1444 return ((GET_CODE (reg = op) == REG
1445 || (GET_CODE (op) == SUBREG
1446 && GET_CODE (reg = SUBREG_REG (op)) == REG)
1447 || (GET_CODE (op) == PLUS
1448 && GET_CODE (XEXP (op, 1)) == CONST_INT
1449 && (GET_CODE (reg = XEXP (op, 0)) == REG
1450 || (GET_CODE (XEXP (op, 0)) == SUBREG
1451 && GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))
1452 && REGNO_POINTER_ALIGN (REGNO (reg)) >= 4);
1453}
1454
cce8749e
CH
1455/* Return TRUE for valid operands for the rhs of an FPU instruction. */
1456
1457int
1458fpu_rhs_operand (op, mode)
1459 rtx op;
1460 enum machine_mode mode;
1461{
ff9940b0 1462 if (s_register_operand (op, mode))
f3bb6135 1463 return TRUE;
cce8749e
CH
1464 else if (GET_CODE (op) == CONST_DOUBLE)
1465 return (const_double_rtx_ok_for_fpu (op));
f3bb6135
RE
1466
1467 return FALSE;
1468}
cce8749e 1469
ff9940b0
RE
1470int
1471fpu_add_operand (op, mode)
1472 rtx op;
1473 enum machine_mode mode;
1474{
1475 if (s_register_operand (op, mode))
f3bb6135 1476 return TRUE;
ff9940b0 1477 else if (GET_CODE (op) == CONST_DOUBLE)
f3bb6135
RE
1478 return (const_double_rtx_ok_for_fpu (op)
1479 || neg_const_double_rtx_ok_for_fpu (op));
1480
1481 return FALSE;
ff9940b0
RE
1482}
1483
cce8749e
CH
1484/* Return nonzero if OP is a constant power of two. */
1485
1486int
1487power_of_two_operand (op, mode)
1488 rtx op;
1489 enum machine_mode mode;
1490{
1491 if (GET_CODE (op) == CONST_INT)
1492 {
f3bb6135
RE
1493 HOST_WIDE_INT value = INTVAL(op);
1494 return value != 0 && (value & (value - 1)) == 0;
cce8749e 1495 }
f3bb6135
RE
1496 return FALSE;
1497}
cce8749e
CH
1498
1499/* Return TRUE for a valid operand of a DImode operation.
ff9940b0
RE
1500 Either: REG, CONST_DOUBLE or MEM(DImode_address).
1501 Note that this disallows MEM(REG+REG), but allows
1502 MEM(PRE/POST_INC/DEC(REG)). */
cce8749e
CH
1503
1504int
1505di_operand (op, mode)
1506 rtx op;
1507 enum machine_mode mode;
1508{
ff9940b0 1509 if (s_register_operand (op, mode))
f3bb6135 1510 return TRUE;
cce8749e
CH
1511
1512 switch (GET_CODE (op))
1513 {
1514 case CONST_DOUBLE:
1515 case CONST_INT:
f3bb6135
RE
1516 return TRUE;
1517
cce8749e 1518 case MEM:
f3bb6135
RE
1519 return memory_address_p (DImode, XEXP (op, 0));
1520
cce8749e 1521 default:
f3bb6135 1522 return FALSE;
cce8749e 1523 }
f3bb6135 1524}
cce8749e 1525
f3139301
DE
1526/* Return TRUE for a valid operand of a DFmode operation when -msoft-float.
1527 Either: REG, CONST_DOUBLE or MEM(DImode_address).
1528 Note that this disallows MEM(REG+REG), but allows
1529 MEM(PRE/POST_INC/DEC(REG)). */
1530
1531int
1532soft_df_operand (op, mode)
1533 rtx op;
1534 enum machine_mode mode;
1535{
1536 if (s_register_operand (op, mode))
1537 return TRUE;
1538
1539 switch (GET_CODE (op))
1540 {
1541 case CONST_DOUBLE:
1542 return TRUE;
1543
1544 case MEM:
1545 return memory_address_p (DFmode, XEXP (op, 0));
1546
1547 default:
1548 return FALSE;
1549 }
1550}
1551
cce8749e
CH
1552/* Return TRUE for valid index operands. */
1553
1554int
1555index_operand (op, mode)
1556 rtx op;
1557 enum machine_mode mode;
1558{
ff9940b0
RE
1559 return (s_register_operand(op, mode)
1560 || (immediate_operand (op, mode)
1561 && INTVAL (op) < 4096 && INTVAL (op) > -4096));
f3bb6135 1562}
cce8749e 1563
ff9940b0
RE
1564/* Return TRUE for valid shifts by a constant. This also accepts any
1565 power of two on the (somewhat overly relaxed) assumption that the
1566 shift operator in this case was a mult. */
1567
1568int
1569const_shift_operand (op, mode)
1570 rtx op;
1571 enum machine_mode mode;
1572{
1573 return (power_of_two_operand (op, mode)
1574 || (immediate_operand (op, mode)
1575 && (INTVAL (op) < 32 && INTVAL (op) > 0)));
f3bb6135 1576}
ff9940b0 1577
cce8749e
CH
1578/* Return TRUE for arithmetic operators which can be combined with a multiply
1579 (shift). */
1580
1581int
1582shiftable_operator (x, mode)
1583 rtx x;
1584 enum machine_mode mode;
1585{
1586 if (GET_MODE (x) != mode)
1587 return FALSE;
1588 else
1589 {
1590 enum rtx_code code = GET_CODE (x);
1591
1592 return (code == PLUS || code == MINUS
1593 || code == IOR || code == XOR || code == AND);
1594 }
f3bb6135 1595}
cce8749e
CH
1596
1597/* Return TRUE for shift operators. */
1598
1599int
1600shift_operator (x, mode)
1601 rtx x;
1602 enum machine_mode mode;
1603{
1604 if (GET_MODE (x) != mode)
1605 return FALSE;
1606 else
1607 {
1608 enum rtx_code code = GET_CODE (x);
1609
ff9940b0
RE
1610 if (code == MULT)
1611 return power_of_two_operand (XEXP (x, 1));
f3bb6135 1612
e2c671ba
RE
1613 return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT
1614 || code == ROTATERT);
cce8749e 1615 }
f3bb6135 1616}
ff9940b0
RE
1617
1618int equality_operator (x, mode)
f3bb6135
RE
1619 rtx x;
1620 enum machine_mode mode;
ff9940b0 1621{
f3bb6135 1622 return GET_CODE (x) == EQ || GET_CODE (x) == NE;
ff9940b0
RE
1623}
1624
1625/* Return TRUE for SMIN SMAX UMIN UMAX operators. */
1626
1627int
1628minmax_operator (x, mode)
1629 rtx x;
1630 enum machine_mode mode;
1631{
1632 enum rtx_code code = GET_CODE (x);
1633
1634 if (GET_MODE (x) != mode)
1635 return FALSE;
f3bb6135 1636
ff9940b0 1637 return code == SMIN || code == SMAX || code == UMIN || code == UMAX;
f3bb6135 1638}
ff9940b0
RE
1639
1640/* return TRUE if x is EQ or NE */
1641
1642/* Return TRUE if this is the condition code register, if we aren't given
1643 a mode, accept any class CCmode register */
1644
1645int
1646cc_register (x, mode)
f3bb6135
RE
1647 rtx x;
1648 enum machine_mode mode;
ff9940b0
RE
1649{
1650 if (mode == VOIDmode)
1651 {
1652 mode = GET_MODE (x);
1653 if (GET_MODE_CLASS (mode) != MODE_CC)
1654 return FALSE;
1655 }
f3bb6135 1656
ff9940b0
RE
1657 if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24)
1658 return TRUE;
f3bb6135 1659
ff9940b0
RE
1660 return FALSE;
1661}
5bbe2d40
RE
1662
1663/* Return TRUE if this is the condition code register, if we aren't given
84ed5e79
RE
1664 a mode, accept any class CCmode register which indicates a dominance
1665 expression. */
5bbe2d40
RE
1666
1667int
84ed5e79 1668dominant_cc_register (x, mode)
5bbe2d40
RE
1669 rtx x;
1670 enum machine_mode mode;
1671{
1672 if (mode == VOIDmode)
1673 {
1674 mode = GET_MODE (x);
84ed5e79 1675 if (GET_MODE_CLASS (mode) != MODE_CC)
5bbe2d40
RE
1676 return FALSE;
1677 }
1678
84ed5e79
RE
1679 if (mode != CC_DNEmode && mode != CC_DEQmode
1680 && mode != CC_DLEmode && mode != CC_DLTmode
1681 && mode != CC_DGEmode && mode != CC_DGTmode
1682 && mode != CC_DLEUmode && mode != CC_DLTUmode
1683 && mode != CC_DGEUmode && mode != CC_DGTUmode)
1684 return FALSE;
1685
5bbe2d40
RE
1686 if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24)
1687 return TRUE;
1688
1689 return FALSE;
1690}
1691
2b835d68
RE
1692/* Return TRUE if X references a SYMBOL_REF. */
1693int
1694symbol_mentioned_p (x)
1695 rtx x;
1696{
1697 register char *fmt;
1698 register int i;
1699
1700 if (GET_CODE (x) == SYMBOL_REF)
1701 return 1;
1702
1703 fmt = GET_RTX_FORMAT (GET_CODE (x));
1704 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
1705 {
1706 if (fmt[i] == 'E')
1707 {
1708 register int j;
1709
1710 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1711 if (symbol_mentioned_p (XVECEXP (x, i, j)))
1712 return 1;
1713 }
1714 else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
1715 return 1;
1716 }
1717
1718 return 0;
1719}
1720
1721/* Return TRUE if X references a LABEL_REF. */
1722int
1723label_mentioned_p (x)
1724 rtx x;
1725{
1726 register char *fmt;
1727 register int i;
1728
1729 if (GET_CODE (x) == LABEL_REF)
1730 return 1;
1731
1732 fmt = GET_RTX_FORMAT (GET_CODE (x));
1733 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
1734 {
1735 if (fmt[i] == 'E')
1736 {
1737 register int j;
1738
1739 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1740 if (label_mentioned_p (XVECEXP (x, i, j)))
1741 return 1;
1742 }
1743 else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
1744 return 1;
1745 }
1746
1747 return 0;
1748}
1749
ff9940b0
RE
1750enum rtx_code
1751minmax_code (x)
f3bb6135 1752 rtx x;
ff9940b0
RE
1753{
1754 enum rtx_code code = GET_CODE (x);
1755
1756 if (code == SMAX)
1757 return GE;
f3bb6135 1758 else if (code == SMIN)
ff9940b0 1759 return LE;
f3bb6135 1760 else if (code == UMIN)
ff9940b0 1761 return LEU;
f3bb6135 1762 else if (code == UMAX)
ff9940b0 1763 return GEU;
f3bb6135 1764
ff9940b0
RE
1765 abort ();
1766}
1767
1768/* Return 1 if memory locations are adjacent */
1769
f3bb6135 1770int
ff9940b0
RE
1771adjacent_mem_locations (a, b)
1772 rtx a, b;
1773{
1774 int val0 = 0, val1 = 0;
1775 int reg0, reg1;
1776
1777 if ((GET_CODE (XEXP (a, 0)) == REG
1778 || (GET_CODE (XEXP (a, 0)) == PLUS
1779 && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT))
1780 && (GET_CODE (XEXP (b, 0)) == REG
1781 || (GET_CODE (XEXP (b, 0)) == PLUS
1782 && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT)))
1783 {
1784 if (GET_CODE (XEXP (a, 0)) == PLUS)
1785 {
1786 reg0 = REGNO (XEXP (XEXP (a, 0), 0));
1787 val0 = INTVAL (XEXP (XEXP (a, 0), 1));
1788 }
1789 else
1790 reg0 = REGNO (XEXP (a, 0));
1791 if (GET_CODE (XEXP (b, 0)) == PLUS)
1792 {
1793 reg1 = REGNO (XEXP (XEXP (b, 0), 0));
1794 val1 = INTVAL (XEXP (XEXP (b, 0), 1));
1795 }
1796 else
1797 reg1 = REGNO (XEXP (b, 0));
1798 return (reg0 == reg1) && ((val1 - val0) == 4 || (val0 - val1) == 4);
1799 }
1800 return 0;
1801}
1802
1803/* Return 1 if OP is a load multiple operation. It is known to be
1804 parallel and the first section will be tested. */
1805
f3bb6135 1806int
ff9940b0
RE
1807load_multiple_operation (op, mode)
1808 rtx op;
1809 enum machine_mode mode;
1810{
f3bb6135 1811 HOST_WIDE_INT count = XVECLEN (op, 0);
ff9940b0
RE
1812 int dest_regno;
1813 rtx src_addr;
f3bb6135 1814 HOST_WIDE_INT i = 1, base = 0;
ff9940b0
RE
1815 rtx elt;
1816
1817 if (count <= 1
1818 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
1819 return 0;
1820
1821 /* Check to see if this might be a write-back */
1822 if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
1823 {
1824 i++;
1825 base = 1;
1826
1827 /* Now check it more carefully */
1828 if (GET_CODE (SET_DEST (elt)) != REG
1829 || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
1830 || REGNO (XEXP (SET_SRC (elt), 0)) != REGNO (SET_DEST (elt))
1831 || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
1832 || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 2) * 4
1833 || GET_CODE (XVECEXP (op, 0, count - 1)) != CLOBBER
1834 || GET_CODE (XEXP (XVECEXP (op, 0, count - 1), 0)) != REG
1835 || REGNO (XEXP (XVECEXP (op, 0, count - 1), 0))
1836 != REGNO (SET_DEST (elt)))
1837 return 0;
f3bb6135 1838
ff9940b0
RE
1839 count--;
1840 }
1841
1842 /* Perform a quick check so we don't blow up below. */
1843 if (count <= i
1844 || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
1845 || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
1846 || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
1847 return 0;
1848
1849 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
1850 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
1851
1852 for (; i < count; i++)
1853 {
1854 rtx elt = XVECEXP (op, 0, i);
1855
1856 if (GET_CODE (elt) != SET
1857 || GET_CODE (SET_DEST (elt)) != REG
1858 || GET_MODE (SET_DEST (elt)) != SImode
1859 || REGNO (SET_DEST (elt)) != dest_regno + i - base
1860 || GET_CODE (SET_SRC (elt)) != MEM
1861 || GET_MODE (SET_SRC (elt)) != SImode
1862 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
1863 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
1864 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
1865 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
1866 return 0;
1867 }
1868
1869 return 1;
1870}
1871
1872/* Return 1 if OP is a store multiple operation. It is known to be
1873 parallel and the first section will be tested. */
1874
f3bb6135 1875int
ff9940b0
RE
1876store_multiple_operation (op, mode)
1877 rtx op;
1878 enum machine_mode mode;
1879{
f3bb6135 1880 HOST_WIDE_INT count = XVECLEN (op, 0);
ff9940b0
RE
1881 int src_regno;
1882 rtx dest_addr;
f3bb6135 1883 HOST_WIDE_INT i = 1, base = 0;
ff9940b0
RE
1884 rtx elt;
1885
1886 if (count <= 1
1887 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
1888 return 0;
1889
1890 /* Check to see if this might be a write-back */
1891 if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
1892 {
1893 i++;
1894 base = 1;
1895
1896 /* Now check it more carefully */
1897 if (GET_CODE (SET_DEST (elt)) != REG
1898 || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
1899 || REGNO (XEXP (SET_SRC (elt), 0)) != REGNO (SET_DEST (elt))
1900 || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
1901 || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 2) * 4
1902 || GET_CODE (XVECEXP (op, 0, count - 1)) != CLOBBER
1903 || GET_CODE (XEXP (XVECEXP (op, 0, count - 1), 0)) != REG
1904 || REGNO (XEXP (XVECEXP (op, 0, count - 1), 0))
1905 != REGNO (SET_DEST (elt)))
1906 return 0;
f3bb6135 1907
ff9940b0
RE
1908 count--;
1909 }
1910
1911 /* Perform a quick check so we don't blow up below. */
1912 if (count <= i
1913 || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
1914 || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
1915 || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
1916 return 0;
1917
1918 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
1919 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
1920
1921 for (; i < count; i++)
1922 {
1923 elt = XVECEXP (op, 0, i);
1924
1925 if (GET_CODE (elt) != SET
1926 || GET_CODE (SET_SRC (elt)) != REG
1927 || GET_MODE (SET_SRC (elt)) != SImode
1928 || REGNO (SET_SRC (elt)) != src_regno + i - base
1929 || GET_CODE (SET_DEST (elt)) != MEM
1930 || GET_MODE (SET_DEST (elt)) != SImode
1931 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
1932 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
1933 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
1934 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
1935 return 0;
1936 }
1937
1938 return 1;
1939}
e2c671ba 1940
84ed5e79
RE
1941int
1942load_multiple_sequence (operands, nops, regs, base, load_offset)
1943 rtx *operands;
1944 int nops;
1945 int *regs;
1946 int *base;
1947 HOST_WIDE_INT *load_offset;
1948{
1949 int unsorted_regs[4];
1950 HOST_WIDE_INT unsorted_offsets[4];
1951 int order[4];
1952 int base_reg;
1953 int i;
1954
1955 /* Can only handle 2, 3, or 4 insns at present, though could be easily
1956 extended if required. */
1957 if (nops < 2 || nops > 4)
1958 abort ();
1959
1960 /* Loop over the operands and check that the memory references are
1961 suitable (ie immediate offsets from the same base register). At
1962 the same time, extract the target register, and the memory
1963 offsets. */
1964 for (i = 0; i < nops; i++)
1965 {
1966 rtx reg;
1967 rtx offset;
1968
1969 if (GET_CODE (operands[nops + i]) != MEM)
1970 abort ();
1971
1972 /* Don't reorder volatile memory references; it doesn't seem worth
1973 looking for the case where the order is ok anyway. */
1974 if (MEM_VOLATILE_P (operands[nops + i]))
1975 return 0;
1976
1977 offset = const0_rtx;
1978
1979 if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
1980 || (GET_CODE (reg) == SUBREG
1981 && GET_CODE (reg = SUBREG_REG (reg)) == REG))
1982 || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
1983 && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
1984 == REG)
1985 || (GET_CODE (reg) == SUBREG
1986 && GET_CODE (reg = SUBREG_REG (reg)) == REG))
1987 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
1988 == CONST_INT)))
1989 {
1990 if (i == 0)
1991 {
1992 base_reg = REGNO(reg);
1993 unsorted_regs[0] = (GET_CODE (operands[i]) == REG
1994 ? REGNO (operands[i])
1995 : REGNO (SUBREG_REG (operands[i])));
1996 order[0] = 0;
1997 }
1998 else
1999 {
2000 if (base_reg != REGNO (reg))
2001 /* Not addressed from the same base register. */
2002 return 0;
2003
2004 unsorted_regs[i] = (GET_CODE (operands[i]) == REG
2005 ? REGNO (operands[i])
2006 : REGNO (SUBREG_REG (operands[i])));
2007 if (unsorted_regs[i] < unsorted_regs[order[0]])
2008 order[0] = i;
2009 }
2010
2011 /* If it isn't an integer register, or if it overwrites the
2012 base register but isn't the last insn in the list, then
2013 we can't do this. */
2014 if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
2015 || (i != nops - 1 && unsorted_regs[i] == base_reg))
2016 return 0;
2017
2018 unsorted_offsets[i] = INTVAL (offset);
2019 }
2020 else
2021 /* Not a suitable memory address. */
2022 return 0;
2023 }
2024
2025 /* All the useful information has now been extracted from the
2026 operands into unsorted_regs and unsorted_offsets; additionally,
2027 order[0] has been set to the lowest numbered register in the
2028 list. Sort the registers into order, and check that the memory
2029 offsets are ascending and adjacent. */
2030
2031 for (i = 1; i < nops; i++)
2032 {
2033 int j;
2034
2035 order[i] = order[i - 1];
2036 for (j = 0; j < nops; j++)
2037 if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
2038 && (order[i] == order[i - 1]
2039 || unsorted_regs[j] < unsorted_regs[order[i]]))
2040 order[i] = j;
2041
2042 /* Have we found a suitable register? if not, one must be used more
2043 than once. */
2044 if (order[i] == order[i - 1])
2045 return 0;
2046
2047 /* Is the memory address adjacent and ascending? */
2048 if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
2049 return 0;
2050 }
2051
2052 if (base)
2053 {
2054 *base = base_reg;
2055
2056 for (i = 0; i < nops; i++)
2057 regs[i] = unsorted_regs[order[i]];
2058
2059 *load_offset = unsorted_offsets[order[0]];
2060 }
2061
2062 if (unsorted_offsets[order[0]] == 0)
2063 return 1; /* ldmia */
2064
2065 if (unsorted_offsets[order[0]] == 4)
2066 return 2; /* ldmib */
2067
2068 if (unsorted_offsets[order[nops - 1]] == 0)
2069 return 3; /* ldmda */
2070
2071 if (unsorted_offsets[order[nops - 1]] == -4)
2072 return 4; /* ldmdb */
2073
2074 /* Can't do it without setting up the offset, only do this if it takes
2075 no more than one insn. */
2076 return (const_ok_for_arm (unsorted_offsets[order[0]])
2077 || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
2078}
2079
2080char *
2081emit_ldm_seq (operands, nops)
2082 rtx *operands;
2083 int nops;
2084{
2085 int regs[4];
2086 int base_reg;
2087 HOST_WIDE_INT offset;
2088 char buf[100];
2089 int i;
2090
2091 switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
2092 {
2093 case 1:
2094 strcpy (buf, "ldm%?ia\t");
2095 break;
2096
2097 case 2:
2098 strcpy (buf, "ldm%?ib\t");
2099 break;
2100
2101 case 3:
2102 strcpy (buf, "ldm%?da\t");
2103 break;
2104
2105 case 4:
2106 strcpy (buf, "ldm%?db\t");
2107 break;
2108
2109 case 5:
2110 if (offset >= 0)
2111 sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
2112 reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
2113 (long) offset);
2114 else
2115 sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
2116 reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
2117 (long) -offset);
2118 output_asm_insn (buf, operands);
2119 base_reg = regs[0];
2120 strcpy (buf, "ldm%?ia\t");
2121 break;
2122
2123 default:
2124 abort ();
2125 }
2126
2127 sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
2128 reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
2129
2130 for (i = 1; i < nops; i++)
2131 sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
2132 reg_names[regs[i]]);
2133
2134 strcat (buf, "}\t%@ phole ldm");
2135
2136 output_asm_insn (buf, operands);
2137 return "";
2138}
2139
2140int
2141store_multiple_sequence (operands, nops, regs, base, load_offset)
2142 rtx *operands;
2143 int nops;
2144 int *regs;
2145 int *base;
2146 HOST_WIDE_INT *load_offset;
2147{
2148 int unsorted_regs[4];
2149 HOST_WIDE_INT unsorted_offsets[4];
2150 int order[4];
2151 int base_reg;
2152 int i;
2153
2154 /* Can only handle 2, 3, or 4 insns at present, though could be easily
2155 extended if required. */
2156 if (nops < 2 || nops > 4)
2157 abort ();
2158
2159 /* Loop over the operands and check that the memory references are
2160 suitable (ie immediate offsets from the same base register). At
2161 the same time, extract the target register, and the memory
2162 offsets. */
2163 for (i = 0; i < nops; i++)
2164 {
2165 rtx reg;
2166 rtx offset;
2167
2168 if (GET_CODE (operands[nops + i]) != MEM)
2169 abort ();
2170
2171 /* Don't reorder volatile memory references; it doesn't seem worth
2172 looking for the case where the order is ok anyway. */
2173 if (MEM_VOLATILE_P (operands[nops + i]))
2174 return 0;
2175
2176 offset = const0_rtx;
2177
2178 if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
2179 || (GET_CODE (reg) == SUBREG
2180 && GET_CODE (reg = SUBREG_REG (reg)) == REG))
2181 || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
2182 && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
2183 == REG)
2184 || (GET_CODE (reg) == SUBREG
2185 && GET_CODE (reg = SUBREG_REG (reg)) == REG))
2186 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
2187 == CONST_INT)))
2188 {
2189 if (i == 0)
2190 {
2191 base_reg = REGNO(reg);
2192 unsorted_regs[0] = (GET_CODE (operands[i]) == REG
2193 ? REGNO (operands[i])
2194 : REGNO (SUBREG_REG (operands[i])));
2195 order[0] = 0;
2196 }
2197 else
2198 {
2199 if (base_reg != REGNO (reg))
2200 /* Not addressed from the same base register. */
2201 return 0;
2202
2203 unsorted_regs[i] = (GET_CODE (operands[i]) == REG
2204 ? REGNO (operands[i])
2205 : REGNO (SUBREG_REG (operands[i])));
2206 if (unsorted_regs[i] < unsorted_regs[order[0]])
2207 order[0] = i;
2208 }
2209
2210 /* If it isn't an integer register, then we can't do this. */
2211 if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
2212 return 0;
2213
2214 unsorted_offsets[i] = INTVAL (offset);
2215 }
2216 else
2217 /* Not a suitable memory address. */
2218 return 0;
2219 }
2220
2221 /* All the useful information has now been extracted from the
2222 operands into unsorted_regs and unsorted_offsets; additionally,
2223 order[0] has been set to the lowest numbered register in the
2224 list. Sort the registers into order, and check that the memory
2225 offsets are ascending and adjacent. */
2226
2227 for (i = 1; i < nops; i++)
2228 {
2229 int j;
2230
2231 order[i] = order[i - 1];
2232 for (j = 0; j < nops; j++)
2233 if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
2234 && (order[i] == order[i - 1]
2235 || unsorted_regs[j] < unsorted_regs[order[i]]))
2236 order[i] = j;
2237
2238 /* Have we found a suitable register? if not, one must be used more
2239 than once. */
2240 if (order[i] == order[i - 1])
2241 return 0;
2242
2243 /* Is the memory address adjacent and ascending? */
2244 if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
2245 return 0;
2246 }
2247
2248 if (base)
2249 {
2250 *base = base_reg;
2251
2252 for (i = 0; i < nops; i++)
2253 regs[i] = unsorted_regs[order[i]];
2254
2255 *load_offset = unsorted_offsets[order[0]];
2256 }
2257
2258 if (unsorted_offsets[order[0]] == 0)
2259 return 1; /* stmia */
2260
2261 if (unsorted_offsets[order[0]] == 4)
2262 return 2; /* stmib */
2263
2264 if (unsorted_offsets[order[nops - 1]] == 0)
2265 return 3; /* stmda */
2266
2267 if (unsorted_offsets[order[nops - 1]] == -4)
2268 return 4; /* stmdb */
2269
2270 return 0;
2271}
2272
2273char *
2274emit_stm_seq (operands, nops)
2275 rtx *operands;
2276 int nops;
2277{
2278 int regs[4];
2279 int base_reg;
2280 HOST_WIDE_INT offset;
2281 char buf[100];
2282 int i;
2283
2284 switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
2285 {
2286 case 1:
2287 strcpy (buf, "stm%?ia\t");
2288 break;
2289
2290 case 2:
2291 strcpy (buf, "stm%?ib\t");
2292 break;
2293
2294 case 3:
2295 strcpy (buf, "stm%?da\t");
2296 break;
2297
2298 case 4:
2299 strcpy (buf, "stm%?db\t");
2300 break;
2301
2302 default:
2303 abort ();
2304 }
2305
2306 sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
2307 reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
2308
2309 for (i = 1; i < nops; i++)
2310 sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
2311 reg_names[regs[i]]);
2312
2313 strcat (buf, "}\t%@ phole stm");
2314
2315 output_asm_insn (buf, operands);
2316 return "";
2317}
2318
e2c671ba
RE
2319int
2320multi_register_push (op, mode)
0a81f500
RE
2321 rtx op;
2322 enum machine_mode mode;
e2c671ba
RE
2323{
2324 if (GET_CODE (op) != PARALLEL
2325 || (GET_CODE (XVECEXP (op, 0, 0)) != SET)
2326 || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
2327 || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != 2))
2328 return 0;
2329
2330 return 1;
2331}
2332
ff9940b0 2333\f
f3bb6135
RE
2334/* Routines for use with attributes */
2335
2336int
2337const_pool_offset (symbol)
9997d19d 2338 rtx symbol;
f3bb6135
RE
2339{
2340 return get_pool_offset (symbol) - get_pool_size () - get_prologue_size ();
2341}
31fdb4d5
DE
2342
2343/* Return nonzero if ATTR is a valid attribute for DECL.
2344 ATTRIBUTES are any existing attributes and ARGS are the arguments
2345 supplied with ATTR.
2346
2347 Supported attributes:
2348
2349 naked: don't output any prologue or epilogue code, the user is assumed
2350 to do the right thing. */
2351
2352int
2353arm_valid_machine_decl_attribute (decl, attributes, attr, args)
2354 tree decl;
2355 tree attributes;
2356 tree attr;
2357 tree args;
2358{
2359 if (args != NULL_TREE)
2360 return 0;
2361
2362 if (is_attribute_p ("naked", attr))
2363 return TREE_CODE (decl) == FUNCTION_DECL;
2364 return 0;
2365}
2366
2367/* Return non-zero if FUNC is a naked function. */
2368
2369static int
2370arm_naked_function_p (func)
2371 tree func;
2372{
2373 tree a;
2374
2375 if (TREE_CODE (func) != FUNCTION_DECL)
2376 abort ();
2377
2378 a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
2379 return a != NULL_TREE;
2380}
f3bb6135 2381\f
ff9940b0
RE
2382/* Routines for use in generating RTL */
2383
f3bb6135
RE
2384rtx
2385arm_gen_load_multiple (base_regno, count, from, up, write_back)
ff9940b0
RE
2386 int base_regno;
2387 int count;
2388 rtx from;
2389 int up;
2390 int write_back;
2391{
2392 int i = 0, j;
2393 rtx result;
2394 int sign = up ? 1 : -1;
2395
2396 result = gen_rtx (PARALLEL, VOIDmode,
2397 rtvec_alloc (count + (write_back ? 2 : 0)));
2398 if (write_back)
f3bb6135 2399 {
ff9940b0 2400 XVECEXP (result, 0, 0)
f3bb6135
RE
2401 = gen_rtx (SET, GET_MODE (from), from,
2402 plus_constant (from, count * 4 * sign));
ff9940b0
RE
2403 i = 1;
2404 count++;
f3bb6135
RE
2405 }
2406
ff9940b0 2407 for (j = 0; i < count; i++, j++)
f3bb6135 2408 {
ff9940b0 2409 XVECEXP (result, 0, i)
f3bb6135
RE
2410 = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, base_regno + j),
2411 gen_rtx (MEM, SImode,
2412 plus_constant (from, j * 4 * sign)));
2413 }
2414
ff9940b0
RE
2415 if (write_back)
2416 XVECEXP (result, 0, i) = gen_rtx (CLOBBER, SImode, from);
2417
2418 return result;
2419}
2420
f3bb6135
RE
2421rtx
2422arm_gen_store_multiple (base_regno, count, to, up, write_back)
ff9940b0
RE
2423 int base_regno;
2424 int count;
2425 rtx to;
2426 int up;
2427 int write_back;
2428{
2429 int i = 0, j;
2430 rtx result;
2431 int sign = up ? 1 : -1;
2432
2433 result = gen_rtx (PARALLEL, VOIDmode,
2434 rtvec_alloc (count + (write_back ? 2 : 0)));
2435 if (write_back)
f3bb6135 2436 {
ff9940b0 2437 XVECEXP (result, 0, 0)
f3bb6135
RE
2438 = gen_rtx (SET, GET_MODE (to), to,
2439 plus_constant (to, count * 4 * sign));
ff9940b0
RE
2440 i = 1;
2441 count++;
f3bb6135
RE
2442 }
2443
ff9940b0 2444 for (j = 0; i < count; i++, j++)
f3bb6135 2445 {
ff9940b0 2446 XVECEXP (result, 0, i)
f3bb6135
RE
2447 = gen_rtx (SET, VOIDmode,
2448 gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign)),
2449 gen_rtx (REG, SImode, base_regno + j));
2450 }
2451
ff9940b0
RE
2452 if (write_back)
2453 XVECEXP (result, 0, i) = gen_rtx (CLOBBER, SImode, to);
2454
2455 return result;
2456}
2457
880e2516
RE
2458int
2459arm_gen_movstrqi (operands)
2460 rtx *operands;
2461{
2462 HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
2463 int i, r;
880e2516
RE
2464 rtx src, dst;
2465 rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
2466 rtx part_bytes_reg = NULL;
2467 extern int optimize;
2468
2469 if (GET_CODE (operands[2]) != CONST_INT
2470 || GET_CODE (operands[3]) != CONST_INT
2471 || INTVAL (operands[2]) > 64
2472 || INTVAL (operands[3]) & 3)
2473 return 0;
2474
2475 st_dst = XEXP (operands[0], 0);
2476 st_src = XEXP (operands[1], 0);
2477 fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
2478 fin_src = src = copy_to_mode_reg (SImode, st_src);
2479
2480 in_words_to_go = (INTVAL (operands[2]) + 3) / 4;
2481 out_words_to_go = INTVAL (operands[2]) / 4;
2482 last_bytes = INTVAL (operands[2]) & 3;
2483
2484 if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0)
2485 part_bytes_reg = gen_rtx (REG, SImode, (in_words_to_go - 1) & 3);
2486
2487 for (i = 0; in_words_to_go >= 2; i+=4)
2488 {
2489 emit_insn (arm_gen_load_multiple (0, (in_words_to_go > 4
2490 ? 4 : in_words_to_go),
2491 src, TRUE, TRUE));
2492 if (out_words_to_go)
2493 {
2494 if (out_words_to_go != 1)
2495 emit_insn (arm_gen_store_multiple (0, (out_words_to_go > 4
2496 ? 4 : out_words_to_go),
2497 dst, TRUE, TRUE));
2498 else
2499 {
2500 emit_move_insn (gen_rtx (MEM, SImode, dst),
2501 gen_rtx (REG, SImode, 0));
2502 emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
2503 }
2504 }
2505
2506 in_words_to_go -= in_words_to_go < 4 ? in_words_to_go : 4;
2507 out_words_to_go -= out_words_to_go < 4 ? out_words_to_go : 4;
2508 }
2509
2510 /* OUT_WORDS_TO_GO will be zero here if there are byte stores to do. */
2511 if (out_words_to_go)
2512 {
2513 rtx sreg;
2514
2515 emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
2516 emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
2517 emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
2518 emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
2519 in_words_to_go--;
2520
2521 if (in_words_to_go) /* Sanity check */
2522 abort ();
2523 }
2524
2525 if (in_words_to_go)
2526 {
2527 if (in_words_to_go < 0)
2528 abort ();
2529
2530 part_bytes_reg = copy_to_mode_reg (SImode, gen_rtx (MEM, SImode, src));
2531 emit_insn (gen_addsi3 (src, src, GEN_INT (4)));
2532 }
2533
2534 if (BYTES_BIG_ENDIAN && last_bytes)
2535 {
2536 rtx tmp = gen_reg_rtx (SImode);
2537
2538 if (part_bytes_reg == NULL)
2539 abort ();
2540
2541 /* The bytes we want are in the top end of the word */
bee06f3d
RE
2542 emit_insn (gen_lshrsi3 (tmp, part_bytes_reg,
2543 GEN_INT (8 * (4 - last_bytes))));
880e2516
RE
2544 part_bytes_reg = tmp;
2545
2546 while (last_bytes)
2547 {
2548 emit_move_insn (gen_rtx (MEM, QImode,
2549 plus_constant (dst, last_bytes - 1)),
2550 gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
2551 if (--last_bytes)
2552 {
2553 tmp = gen_reg_rtx (SImode);
2554 emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));
2555 part_bytes_reg = tmp;
2556 }
2557 }
2558
2559 }
2560 else
2561 {
2562 while (last_bytes)
2563 {
2564 if (part_bytes_reg == NULL)
2565 abort ();
2566
2567 emit_move_insn (gen_rtx (MEM, QImode, dst),
2568 gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
2569 emit_insn (gen_addsi3 (dst, dst, const1_rtx));
2570 if (--last_bytes)
2571 {
2572 rtx tmp = gen_reg_rtx (SImode);
2573 emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));
2574 part_bytes_reg = tmp;
2575 }
2576 }
2577 }
2578
2579 return 1;
2580}
2581
5165176d
RE
2582/* Generate a memory reference for a half word, such that it will be loaded
2583 into the top 16 bits of the word. We can assume that the address is
2584 known to be alignable and of the form reg, or plus (reg, const). */
2585rtx
2586gen_rotated_half_load (memref)
2587 rtx memref;
2588{
2589 HOST_WIDE_INT offset = 0;
2590 rtx base = XEXP (memref, 0);
2591
2592 if (GET_CODE (base) == PLUS)
2593 {
2594 offset = INTVAL (XEXP (base, 1));
2595 base = XEXP (base, 0);
2596 }
2597
2598 /* If we aren't allowed to generate unalligned addresses, then fail. */
2599 if (TARGET_SHORT_BY_BYTES
2600 && ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 0)))
2601 return NULL;
2602
2603 base = gen_rtx (MEM, SImode, plus_constant (base, offset & ~2));
2604
2605 if ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 2))
2606 return base;
2607
2608 return gen_rtx (ROTATE, SImode, base, GEN_INT (16));
2609}
2610
84ed5e79
RE
2611static enum machine_mode
2612select_dominance_cc_mode (op, x, y, cond_or)
2613 enum rtx_code op;
2614 rtx x;
2615 rtx y;
2616 HOST_WIDE_INT cond_or;
2617{
2618 enum rtx_code cond1, cond2;
2619 int swapped = 0;
2620
2621 /* Currently we will probably get the wrong result if the individual
2622 comparisons are not simple. This also ensures that it is safe to
2623 reverse a comparions if necessary. */
2624 if ((arm_select_cc_mode (cond1 = GET_CODE (x), XEXP (x, 0), XEXP (x, 1))
2625 != CCmode)
2626 || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1))
2627 != CCmode))
2628 return CCmode;
2629
2630 if (cond_or)
2631 cond1 = reverse_condition (cond1);
2632
2633 /* If the comparisons are not equal, and one doesn't dominate the other,
2634 then we can't do this. */
2635 if (cond1 != cond2
2636 && ! comparison_dominates_p (cond1, cond2)
2637 && (swapped = 1, ! comparison_dominates_p (cond2, cond1)))
2638 return CCmode;
2639
2640 if (swapped)
2641 {
2642 enum rtx_code temp = cond1;
2643 cond1 = cond2;
2644 cond2 = temp;
2645 }
2646
2647 switch (cond1)
2648 {
2649 case EQ:
2650 if (cond2 == EQ || ! cond_or)
2651 return CC_DEQmode;
2652
2653 switch (cond2)
2654 {
2655 case LE: return CC_DLEmode;
2656 case LEU: return CC_DLEUmode;
2657 case GE: return CC_DGEmode;
2658 case GEU: return CC_DGEUmode;
2659 }
2660
2661 break;
2662
2663 case LT:
2664 if (cond2 == LT || ! cond_or)
2665 return CC_DLTmode;
2666 if (cond2 == LE)
2667 return CC_DLEmode;
2668 if (cond2 == NE)
2669 return CC_DNEmode;
2670 break;
2671
2672 case GT:
2673 if (cond2 == GT || ! cond_or)
2674 return CC_DGTmode;
2675 if (cond2 == GE)
2676 return CC_DGEmode;
2677 if (cond2 == NE)
2678 return CC_DNEmode;
2679 break;
2680
2681 case LTU:
2682 if (cond2 == LTU || ! cond_or)
2683 return CC_DLTUmode;
2684 if (cond2 == LEU)
2685 return CC_DLEUmode;
2686 if (cond2 == NE)
2687 return CC_DNEmode;
2688 break;
2689
2690 case GTU:
2691 if (cond2 == GTU || ! cond_or)
2692 return CC_DGTUmode;
2693 if (cond2 == GEU)
2694 return CC_DGEUmode;
2695 if (cond2 == NE)
2696 return CC_DNEmode;
2697 break;
2698
2699 /* The remaining cases only occur when both comparisons are the
2700 same. */
2701 case NE:
2702 return CC_DNEmode;
2703
2704 case LE:
2705 return CC_DLEmode;
2706
2707 case GE:
2708 return CC_DGEmode;
2709
2710 case LEU:
2711 return CC_DLEUmode;
2712
2713 case GEU:
2714 return CC_DGEUmode;
2715 }
2716
2717 abort ();
2718}
2719
2720enum machine_mode
2721arm_select_cc_mode (op, x, y)
2722 enum rtx_code op;
2723 rtx x;
2724 rtx y;
2725{
2726 /* All floating point compares return CCFP if it is an equality
2727 comparison, and CCFPE otherwise. */
2728 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
2729 return (op == EQ || op == NE) ? CCFPmode : CCFPEmode;
2730
2731 /* A compare with a shifted operand. Because of canonicalization, the
2732 comparison will have to be swapped when we emit the assembler. */
2733 if (GET_MODE (y) == SImode && GET_CODE (y) == REG
2734 && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
2735 || GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE
2736 || GET_CODE (x) == ROTATERT))
2737 return CC_SWPmode;
2738
2739 /* This is a special case, that is used by combine to alow a
2740 comarison of a shifted byte load to be split into a zero-extend
2741 followed by a comparison of the shifted integer (only valid for
2742 equalities and unsigned inequalites. */
2743 if (GET_MODE (x) == SImode
2744 && GET_CODE (x) == ASHIFT
2745 && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 24
2746 && GET_CODE (XEXP (x, 0)) == SUBREG
2747 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == MEM
2748 && GET_MODE (SUBREG_REG (XEXP (x, 0))) == QImode
2749 && (op == EQ || op == NE
2750 || op == GEU || op == GTU || op == LTU || op == LEU)
2751 && GET_CODE (y) == CONST_INT)
2752 return CC_Zmode;
2753
2754 /* An operation that sets the condition codes as a side-effect, the
2755 V flag is not set correctly, so we can only use comparisons where
2756 this doesn't matter. (For LT and GE we can use "mi" and "pl"
2757 instead. */
2758 if (GET_MODE (x) == SImode
2759 && y == const0_rtx
2760 && (op == EQ || op == NE || op == LT || op == GE)
2761 && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
2762 || GET_CODE (x) == AND || GET_CODE (x) == IOR
2763 || GET_CODE (x) == XOR || GET_CODE (x) == MULT
2764 || GET_CODE (x) == NOT || GET_CODE (x) == NEG
2765 || GET_CODE (x) == LSHIFTRT
2766 || GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
2767 || GET_CODE (x) == ROTATERT || GET_CODE (x) == ZERO_EXTRACT))
2768 return CC_NOOVmode;
2769
2770 /* A construct for a conditional compare, if the false arm contains
2771 0, then both conditions must be true, otherwise either condition
2772 must be true. Not all conditions are possible, so CCmode is
2773 returned if it can't be done. */
2774 if (GET_CODE (x) == IF_THEN_ELSE
2775 && (XEXP (x, 2) == const0_rtx
2776 || XEXP (x, 2) == const1_rtx)
2777 && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
2778 && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
2779 return select_dominance_cc_mode (op, XEXP (x, 0), XEXP (x, 1),
2780 INTVAL (XEXP (x, 2)));
2781
2782 if (GET_MODE (x) == QImode && (op == EQ || op == NE))
2783 return CC_Zmode;
2784
2785 return CCmode;
2786}
2787
ff9940b0
RE
2788/* X and Y are two things to compare using CODE. Emit the compare insn and
2789 return the rtx for register 0 in the proper mode. FP means this is a
2790 floating point compare: I don't think that it is needed on the arm. */
2791
2792rtx
2793gen_compare_reg (code, x, y, fp)
2794 enum rtx_code code;
2795 rtx x, y;
2796{
2797 enum machine_mode mode = SELECT_CC_MODE (code, x, y);
2798 rtx cc_reg = gen_rtx (REG, mode, 24);
2799
2800 emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
2801 gen_rtx (COMPARE, mode, x, y)));
2802
2803 return cc_reg;
2804}
2805
0a81f500
RE
2806void
2807arm_reload_in_hi (operands)
2808 rtx *operands;
2809{
2810 rtx base = find_replacement (&XEXP (operands[1], 0));
2811
2812 emit_insn (gen_zero_extendqisi2 (operands[2], gen_rtx (MEM, QImode, base)));
2813 emit_insn (gen_zero_extendqisi2 (gen_rtx (SUBREG, SImode, operands[0], 0),
2814 gen_rtx (MEM, QImode,
2815 plus_constant (base, 1))));
2816 if (BYTES_BIG_ENDIAN)
2817 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (SUBREG, SImode,
2818 operands[0], 0),
2819 gen_rtx (IOR, SImode,
2820 gen_rtx (ASHIFT, SImode,
2821 gen_rtx (SUBREG, SImode,
2822 operands[0], 0),
2823 GEN_INT (8)),
2824 operands[2])));
2825 else
2826 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (SUBREG, SImode,
2827 operands[0], 0),
2828 gen_rtx (IOR, SImode,
2829 gen_rtx (ASHIFT, SImode,
2830 operands[2],
2831 GEN_INT (8)),
2832 gen_rtx (SUBREG, SImode, operands[0], 0))));
2833}
2834
f3bb6135 2835void
af48348a 2836arm_reload_out_hi (operands)
f3bb6135 2837 rtx *operands;
af48348a
RK
2838{
2839 rtx base = find_replacement (&XEXP (operands[0], 0));
2840
b5cc037f
RE
2841 if (BYTES_BIG_ENDIAN)
2842 {
2843 emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (base, 1)),
2844 gen_rtx (SUBREG, QImode, operands[1], 0)));
2845 emit_insn (gen_lshrsi3 (operands[2],
2846 gen_rtx (SUBREG, SImode, operands[1], 0),
2847 GEN_INT (8)));
2848 emit_insn (gen_movqi (gen_rtx (MEM, QImode, base),
2849 gen_rtx (SUBREG, QImode, operands[2], 0)));
2850 }
2851 else
2852 {
2853 emit_insn (gen_movqi (gen_rtx (MEM, QImode, base),
2854 gen_rtx (SUBREG, QImode, operands[1], 0)));
2855 emit_insn (gen_lshrsi3 (operands[2],
2856 gen_rtx (SUBREG, SImode, operands[1], 0),
2857 GEN_INT (8)));
2858 emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (base, 1)),
2859 gen_rtx (SUBREG, QImode, operands[2], 0)));
2860 }
af48348a 2861}
ff9940b0
RE
2862\f
2863/* Check to see if a branch is forwards or backwards. Return TRUE if it
2864 is backwards. */
2865
2866int
2867arm_backwards_branch (from, to)
f3bb6135 2868 int from, to;
ff9940b0 2869{
f3bb6135 2870 return insn_addresses[to] <= insn_addresses[from];
ff9940b0
RE
2871}
2872
2873/* Check to see if a branch is within the distance that can be done using
2874 an arithmetic expression. */
2875int
2876short_branch (from, to)
f3bb6135 2877 int from, to;
ff9940b0 2878{
5472d00b 2879 int delta = insn_addresses[from] + 8 - insn_addresses[to];
ff9940b0 2880
5472d00b 2881 return abs (delta) < 980; /* A small margin for safety */
ff9940b0
RE
2882}
2883
2884/* Check to see that the insn isn't the target of the conditionalizing
2885 code */
2886int
2887arm_insn_not_targeted (insn)
f3bb6135 2888 rtx insn;
ff9940b0
RE
2889{
2890 return insn != arm_target_insn;
2891}
2892
2b835d68
RE
2893\f
2894/* Routines for manipulation of the constant pool. */
2895/* This is unashamedly hacked from the version in sh.c, since the problem is
2896 extremely similar. */
2897
2898/* Arm instructions cannot load a large constant into a register,
2899 constants have to come from a pc relative load. The reference of a pc
2900 relative load instruction must be less than 1k infront of the instruction.
2901 This means that we often have to dump a constant inside a function, and
2902 generate code to branch around it.
2903
2904 It is important to minimize this, since the branches will slow things
2905 down and make things bigger.
2906
2907 Worst case code looks like:
2908
2909 ldr rn, L1
2910 b L2
2911 align
2912 L1: .long value
2913 L2:
2914 ..
2915
2916 ldr rn, L3
2917 b L4
2918 align
2919 L3: .long value
2920 L4:
2921 ..
2922
2923 We fix this by performing a scan before scheduling, which notices which
2924 instructions need to have their operands fetched from the constant table
2925 and builds the table.
2926
2927
2928 The algorithm is:
2929
2930 scan, find an instruction which needs a pcrel move. Look forward, find th
2931 last barrier which is within MAX_COUNT bytes of the requirement.
2932 If there isn't one, make one. Process all the instructions between
2933 the find and the barrier.
2934
2935 In the above example, we can tell that L3 is within 1k of L1, so
2936 the first move can be shrunk from the 2 insn+constant sequence into
2937 just 1 insn, and the constant moved to L3 to make:
2938
2939 ldr rn, L1
2940 ..
2941 ldr rn, L3
2942 b L4
2943 align
2944 L1: .long value
2945 L3: .long value
2946 L4:
2947
2948 Then the second move becomes the target for the shortening process.
2949
2950 */
2951
2952typedef struct
2953{
2954 rtx value; /* Value in table */
2955 HOST_WIDE_INT next_offset;
2956 enum machine_mode mode; /* Mode of value */
2957} pool_node;
2958
2959/* The maximum number of constants that can fit into one pool, since
2960 the pc relative range is 0...1020 bytes and constants are at least 4
2961 bytes long */
2962
2963#define MAX_POOL_SIZE (1020/4)
2964static pool_node pool_vector[MAX_POOL_SIZE];
2965static int pool_size;
2966static rtx pool_vector_label;
2967
2968/* Add a constant to the pool and return its label. */
2969static HOST_WIDE_INT
2970add_constant (x, mode)
2971 rtx x;
2972 enum machine_mode mode;
2973{
2974 int i;
2975 rtx lab;
2976 HOST_WIDE_INT offset;
2977
2978 if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
2979 && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
2980 x = get_pool_constant (XEXP (x, 0));
2981#ifndef AOF_ASSEMBLER
2982 else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == 3)
2983 x = XVECEXP (x, 0, 0);
2984#endif
2985
2986 /* First see if we've already got it */
2987 for (i = 0; i < pool_size; i++)
2988 {
2989 if (GET_CODE (x) == pool_vector[i].value->code
2990 && mode == pool_vector[i].mode)
2991 {
2992 if (GET_CODE (x) == CODE_LABEL)
2993 {
2994 if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
2995 continue;
2996 }
2997 if (rtx_equal_p (x, pool_vector[i].value))
2998 return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
2999 }
3000 }
3001
3002 /* Need a new one */
3003 pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
3004 offset = 0;
3005 if (pool_size == 0)
3006 pool_vector_label = gen_label_rtx ();
3007 else
3008 pool_vector[pool_size].next_offset
3009 += (offset = pool_vector[pool_size - 1].next_offset);
3010
3011 pool_vector[pool_size].value = x;
3012 pool_vector[pool_size].mode = mode;
3013 pool_size++;
3014 return offset;
3015}
3016
3017/* Output the literal table */
3018static void
3019dump_table (scan)
3020 rtx scan;
3021{
3022 int i;
3023
3024 scan = emit_label_after (gen_label_rtx (), scan);
3025 scan = emit_insn_after (gen_align_4 (), scan);
3026 scan = emit_label_after (pool_vector_label, scan);
3027
3028 for (i = 0; i < pool_size; i++)
3029 {
3030 pool_node *p = pool_vector + i;
3031
3032 switch (GET_MODE_SIZE (p->mode))
3033 {
3034 case 4:
3035 scan = emit_insn_after (gen_consttable_4 (p->value), scan);
3036 break;
3037
3038 case 8:
3039 scan = emit_insn_after (gen_consttable_8 (p->value), scan);
3040 break;
3041
3042 default:
3043 abort ();
3044 break;
3045 }
3046 }
3047
3048 scan = emit_insn_after (gen_consttable_end (), scan);
3049 scan = emit_barrier_after (scan);
3050 pool_size = 0;
3051}
3052
3053/* Non zero if the src operand needs to be fixed up */
3054static int
3055fixit (src, mode, destreg)
3056 rtx src;
3057 enum machine_mode mode;
3058 int destreg;
3059{
3060 if (CONSTANT_P (src))
3061 {
3062 if (GET_CODE (src) == CONST_INT)
3063 return (! const_ok_for_arm (INTVAL (src))
3064 && ! const_ok_for_arm (~INTVAL (src)));
3065 if (GET_CODE (src) == CONST_DOUBLE)
3066 return (GET_MODE (src) == VOIDmode
3067 || destreg < 16
3068 || (! const_double_rtx_ok_for_fpu (src)
3069 && ! neg_const_double_rtx_ok_for_fpu (src)));
3070 return symbol_mentioned_p (src);
3071 }
3072#ifndef AOF_ASSEMBLER
3073 else if (GET_CODE (src) == UNSPEC && XINT (src, 1) == 3)
3074 return 1;
3075#endif
3076 else
3077 return (mode == SImode && GET_CODE (src) == MEM
3078 && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
3079 && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0)));
3080}
3081
3082/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
3083static rtx
3084find_barrier (from, max_count)
3085 rtx from;
3086 int max_count;
3087{
3088 int count = 0;
3089 rtx found_barrier = 0;
3090
3091 while (from && count < max_count)
3092 {
3093 if (GET_CODE (from) == BARRIER)
3094 found_barrier = from;
3095
3096 /* Count the length of this insn */
3097 if (GET_CODE (from) == INSN
3098 && GET_CODE (PATTERN (from)) == SET
3099 && CONSTANT_P (SET_SRC (PATTERN (from)))
3100 && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
3101 {
3102 rtx src = SET_SRC (PATTERN (from));
3103 count += 2;
3104 }
3105 else
3106 count += get_attr_length (from);
3107
3108 from = NEXT_INSN (from);
3109 }
3110
3111 if (!found_barrier)
3112 {
3113 /* We didn't find a barrier in time to
3114 dump our stuff, so we'll make one */
3115 rtx label = gen_label_rtx ();
3116
3117 if (from)
3118 from = PREV_INSN (from);
3119 else
3120 from = get_last_insn ();
3121
3122 /* Walk back to be just before any jump */
3123 while (GET_CODE (from) == JUMP_INSN
3124 || GET_CODE (from) == NOTE
3125 || GET_CODE (from) == CODE_LABEL)
3126 from = PREV_INSN (from);
3127
3128 from = emit_jump_insn_after (gen_jump (label), from);
3129 JUMP_LABEL (from) = label;
3130 found_barrier = emit_barrier_after (from);
3131 emit_label_after (label, found_barrier);
3132 return found_barrier;
3133 }
3134
3135 return found_barrier;
3136}
3137
3138/* Non zero if the insn is a move instruction which needs to be fixed. */
3139static int
3140broken_move (insn)
3141 rtx insn;
3142{
3143 if (!INSN_DELETED_P (insn)
3144 && GET_CODE (insn) == INSN
3145 && GET_CODE (PATTERN (insn)) == SET)
3146 {
3147 rtx pat = PATTERN (insn);
3148 rtx src = SET_SRC (pat);
3149 rtx dst = SET_DEST (pat);
3150 int destreg;
3151 enum machine_mode mode = GET_MODE (dst);
3152 if (dst == pc_rtx)
3153 return 0;
3154
3155 if (GET_CODE (dst) == REG)
3156 destreg = REGNO (dst);
3157 else if (GET_CODE (dst) == SUBREG && GET_CODE (SUBREG_REG (dst)) == REG)
3158 destreg = REGNO (SUBREG_REG (dst));
3159
3160 return fixit (src, mode, destreg);
3161 }
3162 return 0;
3163}
3164
3165void
3166arm_reorg (first)
3167 rtx first;
3168{
3169 rtx insn;
3170 int count_size;
3171 int regno;
3172
3173#if 0
3174 /* The ldr instruction can work with up to a 4k offset, and most constants
3175 will be loaded with one of these instructions; however, the adr
3176 instruction and the ldf instructions only work with a 1k offset. This
3177 code needs to be rewritten to use the 4k offset when possible, and to
3178 adjust when a 1k offset is needed. For now we just use a 1k offset
3179 from the start. */
3180 count_size = 4000;
3181
3182 /* Floating point operands can't work further than 1024 bytes from the
3183 PC, so to make things simple we restrict all loads for such functions.
3184 */
3185 if (TARGET_HARD_FLOAT)
3186 for (regno = 16; regno < 24; regno++)
3187 if (regs_ever_live[regno])
3188 {
3189 count_size = 1000;
3190 break;
3191 }
3192#else
3193 count_size = 1000;
3194#endif /* 0 */
3195
3196 for (insn = first; insn; insn = NEXT_INSN (insn))
3197 {
3198 if (broken_move (insn))
3199 {
3200 /* This is a broken move instruction, scan ahead looking for
3201 a barrier to stick the constant table behind */
3202 rtx scan;
3203 rtx barrier = find_barrier (insn, count_size);
3204
3205 /* Now find all the moves between the points and modify them */
3206 for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
3207 {
3208 if (broken_move (scan))
3209 {
3210 /* This is a broken move instruction, add it to the pool */
3211 rtx pat = PATTERN (scan);
3212 rtx src = SET_SRC (pat);
3213 rtx dst = SET_DEST (pat);
3214 enum machine_mode mode = GET_MODE (dst);
3215 HOST_WIDE_INT offset;
3216 rtx newinsn = scan;
3217 rtx newsrc;
3218 rtx addr;
3219 int scratch;
3220
3221 /* If this is an HImode constant load, convert it into
3222 an SImode constant load. Since the register is always
3223 32 bits this is safe. We have to do this, since the
3224 load pc-relative instruction only does a 32-bit load. */
3225 if (mode == HImode)
3226 {
3227 mode = SImode;
3228 if (GET_CODE (dst) != REG)
3229 abort ();
3230 PUT_MODE (dst, SImode);
3231 }
3232
3233 offset = add_constant (src, mode);
3234 addr = plus_constant (gen_rtx (LABEL_REF, VOIDmode,
3235 pool_vector_label),
3236 offset);
3237
3238 /* For wide moves to integer regs we need to split the
3239 address calculation off into a separate insn, so that
3240 the load can then be done with a load-multiple. This is
3241 safe, since we have already noted the length of such
3242 insns to be 8, and we are immediately over-writing the
3243 scratch we have grabbed with the final result. */
3244 if (GET_MODE_SIZE (mode) > 4
3245 && (scratch = REGNO (dst)) < 16)
3246 {
3247 rtx reg = gen_rtx (REG, SImode, scratch);
3248 newinsn = emit_insn_after (gen_movaddr (reg, addr),
3249 newinsn);
3250 addr = reg;
3251 }
3252
3253 newsrc = gen_rtx (MEM, mode, addr);
3254
3255 /* Build a jump insn wrapper around the move instead
3256 of an ordinary insn, because we want to have room for
3257 the target label rtx in fld[7], which an ordinary
3258 insn doesn't have. */
3259 newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
3260 dst, newsrc),
3261 newinsn);
3262 JUMP_LABEL (newinsn) = pool_vector_label;
3263
3264 /* But it's still an ordinary insn */
3265 PUT_CODE (newinsn, INSN);
3266
3267 /* Kill old insn */
3268 delete_insn (scan);
3269 scan = newinsn;
3270 }
3271 }
3272 dump_table (barrier);
3273 insn = scan;
3274 }
3275 }
3276}
3277
cce8749e
CH
3278\f
3279/* Routines to output assembly language. */
3280
f3bb6135 3281/* If the rtx is the correct value then return the string of the number.
ff9940b0
RE
3282 In this way we can ensure that valid double constants are generated even
3283 when cross compiling. */
3284char *
3285fp_immediate_constant (x)
b5cc037f 3286 rtx x;
ff9940b0
RE
3287{
3288 REAL_VALUE_TYPE r;
3289 int i;
3290
3291 if (!fpa_consts_inited)
3292 init_fpa_table ();
3293
3294 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3295 for (i = 0; i < 8; i++)
3296 if (REAL_VALUES_EQUAL (r, values_fpa[i]))
3297 return strings_fpa[i];
f3bb6135 3298
ff9940b0
RE
3299 abort ();
3300}
3301
9997d19d
RE
3302/* As for fp_immediate_constant, but value is passed directly, not in rtx. */
3303static char *
3304fp_const_from_val (r)
3305 REAL_VALUE_TYPE *r;
3306{
3307 int i;
3308
3309 if (! fpa_consts_inited)
3310 init_fpa_table ();
3311
3312 for (i = 0; i < 8; i++)
3313 if (REAL_VALUES_EQUAL (*r, values_fpa[i]))
3314 return strings_fpa[i];
3315
3316 abort ();
3317}
ff9940b0 3318
cce8749e
CH
3319/* Output the operands of a LDM/STM instruction to STREAM.
3320 MASK is the ARM register set mask of which only bits 0-15 are important.
3321 INSTR is the possibly suffixed base register. HAT unequals zero if a hat
3322 must follow the register list. */
3323
3324void
3325print_multi_reg (stream, instr, mask, hat)
3326 FILE *stream;
3327 char *instr;
3328 int mask, hat;
3329{
3330 int i;
3331 int not_first = FALSE;
3332
1d5473cb 3333 fputc ('\t', stream);
f3139301 3334 fprintf (stream, instr, REGISTER_PREFIX);
1d5473cb 3335 fputs (", {", stream);
cce8749e
CH
3336 for (i = 0; i < 16; i++)
3337 if (mask & (1 << i))
3338 {
3339 if (not_first)
3340 fprintf (stream, ", ");
f3139301 3341 fprintf (stream, "%s%s", REGISTER_PREFIX, reg_names[i]);
cce8749e
CH
3342 not_first = TRUE;
3343 }
f3bb6135 3344
cce8749e 3345 fprintf (stream, "}%s\n", hat ? "^" : "");
f3bb6135 3346}
cce8749e
CH
3347
3348/* Output a 'call' insn. */
3349
3350char *
3351output_call (operands)
f3bb6135 3352 rtx *operands;
cce8749e 3353{
cce8749e
CH
3354 /* Handle calls to lr using ip (which may be clobbered in subr anyway). */
3355
3356 if (REGNO (operands[0]) == 14)
3357 {
3358 operands[0] = gen_rtx (REG, SImode, 12);
1d5473cb 3359 output_asm_insn ("mov%?\t%0, %|lr", operands);
cce8749e 3360 }
1d5473cb
RE
3361 output_asm_insn ("mov%?\t%|lr, %|pc", operands);
3362 output_asm_insn ("mov%?\t%|pc, %0", operands);
f3bb6135
RE
3363 return "";
3364}
cce8749e 3365
ff9940b0
RE
3366static int
3367eliminate_lr2ip (x)
f3bb6135 3368 rtx *x;
ff9940b0
RE
3369{
3370 int something_changed = 0;
3371 rtx x0 = *x;
3372 int code = GET_CODE (x0);
3373 register int i, j;
3374 register char *fmt;
3375
3376 switch (code)
3377 {
3378 case REG:
3379 if (REGNO (x0) == 14)
3380 {
3381 *x = gen_rtx (REG, SImode, 12);
3382 return 1;
3383 }
3384 return 0;
3385 default:
3386 /* Scan through the sub-elements and change any references there */
3387 fmt = GET_RTX_FORMAT (code);
3388 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3389 if (fmt[i] == 'e')
3390 something_changed |= eliminate_lr2ip (&XEXP (x0, i));
3391 else if (fmt[i] == 'E')
3392 for (j = 0; j < XVECLEN (x0, i); j++)
3393 something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
3394 return something_changed;
3395 }
3396}
3397
3398/* Output a 'call' insn that is a reference in memory. */
3399
3400char *
3401output_call_mem (operands)
f3bb6135 3402 rtx *operands;
ff9940b0
RE
3403{
3404 operands[0] = copy_rtx (operands[0]); /* Be ultra careful */
3405 /* Handle calls using lr by using ip (which may be clobbered in subr anyway).
3406 */
3407 if (eliminate_lr2ip (&operands[0]))
1d5473cb 3408 output_asm_insn ("mov%?\t%|ip, %|lr", operands);
f3bb6135 3409
1d5473cb
RE
3410 output_asm_insn ("mov%?\t%|lr, %|pc", operands);
3411 output_asm_insn ("ldr%?\t%|pc, %0", operands);
f3bb6135
RE
3412 return "";
3413}
ff9940b0
RE
3414
3415
3416/* Output a move from arm registers to an fpu registers.
3417 OPERANDS[0] is an fpu register.
3418 OPERANDS[1] is the first registers of an arm register pair. */
3419
3420char *
3421output_mov_long_double_fpu_from_arm (operands)
f3bb6135 3422 rtx *operands;
ff9940b0
RE
3423{
3424 int arm_reg0 = REGNO (operands[1]);
3425 rtx ops[3];
3426
3427 if (arm_reg0 == 12)
3428 abort();
f3bb6135 3429
ff9940b0
RE
3430 ops[0] = gen_rtx (REG, SImode, arm_reg0);
3431 ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
3432 ops[2] = gen_rtx (REG, SImode, 2 + arm_reg0);
3433
1d5473cb
RE
3434 output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops);
3435 output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands);
f3bb6135
RE
3436 return "";
3437}
ff9940b0
RE
3438
3439/* Output a move from an fpu register to arm registers.
3440 OPERANDS[0] is the first registers of an arm register pair.
3441 OPERANDS[1] is an fpu register. */
3442
3443char *
3444output_mov_long_double_arm_from_fpu (operands)
f3bb6135 3445 rtx *operands;
ff9940b0
RE
3446{
3447 int arm_reg0 = REGNO (operands[0]);
3448 rtx ops[3];
3449
3450 if (arm_reg0 == 12)
3451 abort();
f3bb6135 3452
ff9940b0
RE
3453 ops[0] = gen_rtx (REG, SImode, arm_reg0);
3454 ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
3455 ops[2] = gen_rtx (REG, SImode, 2 + arm_reg0);
3456
1d5473cb
RE
3457 output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands);
3458 output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1, %2}", ops);
f3bb6135
RE
3459 return "";
3460}
ff9940b0
RE
3461
3462/* Output a move from arm registers to arm registers of a long double
3463 OPERANDS[0] is the destination.
3464 OPERANDS[1] is the source. */
3465char *
3466output_mov_long_double_arm_from_arm (operands)
f3bb6135 3467 rtx *operands;
ff9940b0
RE
3468{
3469 /* We have to be careful here because the two might overlap */
3470 int dest_start = REGNO (operands[0]);
3471 int src_start = REGNO (operands[1]);
3472 rtx ops[2];
3473 int i;
3474
3475 if (dest_start < src_start)
3476 {
3477 for (i = 0; i < 3; i++)
3478 {
3479 ops[0] = gen_rtx (REG, SImode, dest_start + i);
3480 ops[1] = gen_rtx (REG, SImode, src_start + i);
9997d19d 3481 output_asm_insn ("mov%?\t%0, %1", ops);
ff9940b0
RE
3482 }
3483 }
3484 else
3485 {
3486 for (i = 2; i >= 0; i--)
3487 {
3488 ops[0] = gen_rtx (REG, SImode, dest_start + i);
3489 ops[1] = gen_rtx (REG, SImode, src_start + i);
9997d19d 3490 output_asm_insn ("mov%?\t%0, %1", ops);
ff9940b0
RE
3491 }
3492 }
f3bb6135 3493
ff9940b0
RE
3494 return "";
3495}
3496
3497
cce8749e
CH
3498/* Output a move from arm registers to an fpu registers.
3499 OPERANDS[0] is an fpu register.
3500 OPERANDS[1] is the first registers of an arm register pair. */
3501
3502char *
3503output_mov_double_fpu_from_arm (operands)
f3bb6135 3504 rtx *operands;
cce8749e
CH
3505{
3506 int arm_reg0 = REGNO (operands[1]);
3507 rtx ops[2];
3508
3509 if (arm_reg0 == 12)
3510 abort();
3511 ops[0] = gen_rtx (REG, SImode, arm_reg0);
3512 ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
1d5473cb
RE
3513 output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops);
3514 output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands);
f3bb6135
RE
3515 return "";
3516}
cce8749e
CH
3517
3518/* Output a move from an fpu register to arm registers.
3519 OPERANDS[0] is the first registers of an arm register pair.
3520 OPERANDS[1] is an fpu register. */
3521
3522char *
3523output_mov_double_arm_from_fpu (operands)
f3bb6135 3524 rtx *operands;
cce8749e
CH
3525{
3526 int arm_reg0 = REGNO (operands[0]);
3527 rtx ops[2];
3528
3529 if (arm_reg0 == 12)
3530 abort();
f3bb6135 3531
cce8749e
CH
3532 ops[0] = gen_rtx (REG, SImode, arm_reg0);
3533 ops[1] = gen_rtx (REG, SImode, 1 + arm_reg0);
1d5473cb
RE
3534 output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands);
3535 output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1}", ops);
f3bb6135
RE
3536 return "";
3537}
cce8749e
CH
3538
3539/* Output a move between double words.
3540 It must be REG<-REG, REG<-CONST_DOUBLE, REG<-CONST_INT, REG<-MEM
3541 or MEM<-REG and all MEMs must be offsettable addresses. */
3542
3543char *
3544output_move_double (operands)
f3bb6135 3545 rtx *operands;
cce8749e
CH
3546{
3547 enum rtx_code code0 = GET_CODE (operands[0]);
3548 enum rtx_code code1 = GET_CODE (operands[1]);
3549 rtx otherops[2];
3550
3551 if (code0 == REG)
3552 {
3553 int reg0 = REGNO (operands[0]);
3554
3555 otherops[0] = gen_rtx (REG, SImode, 1 + reg0);
3556 if (code1 == REG)
3557 {
3558 int reg1 = REGNO (operands[1]);
3559 if (reg1 == 12)
3560 abort();
f3bb6135 3561
cce8749e 3562 /* Ensure the second source is not overwritten */
c1c2bc04
RE
3563 if (reg1 == reg0 + (WORDS_BIG_ENDIAN ? -1 : 1))
3564 output_asm_insn("mov%?\t%Q0, %Q1\n\tmov%?\t%R0, %R1", operands);
cce8749e 3565 else
c1c2bc04 3566 output_asm_insn("mov%?\t%R0, %R1\n\tmov%?\t%Q0, %Q1", operands);
cce8749e
CH
3567 }
3568 else if (code1 == CONST_DOUBLE)
3569 {
226a5051
RE
3570 if (GET_MODE (operands[1]) == DFmode)
3571 {
3572 long l[2];
3573 union real_extract u;
3574
3575 bcopy ((char *) &CONST_DOUBLE_LOW (operands[1]), (char *) &u,
3576 sizeof (u));
3577 REAL_VALUE_TO_TARGET_DOUBLE (u.d, l);
3578 otherops[1] = GEN_INT(l[1]);
3579 operands[1] = GEN_INT(l[0]);
3580 }
c1c2bc04
RE
3581 else if (GET_MODE (operands[1]) != VOIDmode)
3582 abort ();
3583 else if (WORDS_BIG_ENDIAN)
3584 {
3585
3586 otherops[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
3587 operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
3588 }
226a5051
RE
3589 else
3590 {
c1c2bc04 3591
226a5051
RE
3592 otherops[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
3593 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
3594 }
c1c2bc04
RE
3595 output_mov_immediate (operands);
3596 output_mov_immediate (otherops);
cce8749e
CH
3597 }
3598 else if (code1 == CONST_INT)
3599 {
ff9940b0 3600 /* sign extend the intval into the high-order word */
c1c2bc04
RE
3601 if (WORDS_BIG_ENDIAN)
3602 {
3603 otherops[1] = operands[1];
3604 operands[1] = (INTVAL (operands[1]) < 0
3605 ? constm1_rtx : const0_rtx);
3606 }
ff9940b0 3607 else
c1c2bc04
RE
3608 otherops[1] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
3609 output_mov_immediate (otherops);
3610 output_mov_immediate (operands);
cce8749e
CH
3611 }
3612 else if (code1 == MEM)
3613 {
ff9940b0 3614 switch (GET_CODE (XEXP (operands[1], 0)))
cce8749e 3615 {
ff9940b0 3616 case REG:
9997d19d 3617 output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
ff9940b0 3618 break;
2b835d68 3619
ff9940b0 3620 case PRE_INC:
2b835d68 3621 abort (); /* Should never happen now */
ff9940b0 3622 break;
2b835d68 3623
ff9940b0 3624 case PRE_DEC:
2b835d68 3625 output_asm_insn ("ldm%?db\t%m1!, %M0", operands);
ff9940b0 3626 break;
2b835d68 3627
ff9940b0 3628 case POST_INC:
9997d19d 3629 output_asm_insn ("ldm%?ia\t%m1!, %M0", operands);
ff9940b0 3630 break;
2b835d68 3631
ff9940b0 3632 case POST_DEC:
2b835d68 3633 abort (); /* Should never happen now */
ff9940b0 3634 break;
2b835d68
RE
3635
3636 case LABEL_REF:
3637 case CONST:
3638 output_asm_insn ("adr%?\t%0, %1", operands);
3639 output_asm_insn ("ldm%?ia\t%0, %M0", operands);
3640 break;
3641
ff9940b0 3642 default:
2b835d68 3643 if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1)))
cce8749e 3644 {
2b835d68
RE
3645 otherops[0] = operands[0];
3646 otherops[1] = XEXP (XEXP (operands[1], 0), 0);
3647 otherops[2] = XEXP (XEXP (operands[1], 0), 1);
3648 if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
3649 {
3650 if (GET_CODE (otherops[2]) == CONST_INT)
3651 {
3652 switch (INTVAL (otherops[2]))
3653 {
3654 case -8:
3655 output_asm_insn ("ldm%?db\t%1, %M0", otherops);
3656 return "";
3657 case -4:
3658 output_asm_insn ("ldm%?da\t%1, %M0", otherops);
3659 return "";
3660 case 4:
3661 output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
3662 return "";
3663 }
3664 if (!(const_ok_for_arm (INTVAL (otherops[2]))))
3665 output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
3666 else
3667 output_asm_insn ("add%?\t%0, %1, %2", otherops);
3668 }
3669 else
3670 output_asm_insn ("add%?\t%0, %1, %2", otherops);
3671 }
3672 else
3673 output_asm_insn ("sub%?\t%0, %1, %2", otherops);
3674 return "ldm%?ia\t%0, %M0";
3675 }
3676 else
3677 {
3678 otherops[1] = adj_offsettable_operand (operands[1], 4);
3679 /* Take care of overlapping base/data reg. */
3680 if (reg_mentioned_p (operands[0], operands[1]))
3681 {
3682 output_asm_insn ("ldr%?\t%0, %1", otherops);
3683 output_asm_insn ("ldr%?\t%0, %1", operands);
3684 }
3685 else
3686 {
3687 output_asm_insn ("ldr%?\t%0, %1", operands);
3688 output_asm_insn ("ldr%?\t%0, %1", otherops);
3689 }
cce8749e
CH
3690 }
3691 }
3692 }
2b835d68
RE
3693 else
3694 abort(); /* Constraints should prevent this */
cce8749e
CH
3695 }
3696 else if (code0 == MEM && code1 == REG)
3697 {
3698 if (REGNO (operands[1]) == 12)
3699 abort();
2b835d68 3700
ff9940b0
RE
3701 switch (GET_CODE (XEXP (operands[0], 0)))
3702 {
3703 case REG:
9997d19d 3704 output_asm_insn ("stm%?ia\t%m0, %M1", operands);
ff9940b0 3705 break;
2b835d68 3706
ff9940b0 3707 case PRE_INC:
2b835d68 3708 abort (); /* Should never happen now */
ff9940b0 3709 break;
2b835d68 3710
ff9940b0 3711 case PRE_DEC:
2b835d68 3712 output_asm_insn ("stm%?db\t%m0!, %M1", operands);
ff9940b0 3713 break;
2b835d68 3714
ff9940b0 3715 case POST_INC:
9997d19d 3716 output_asm_insn ("stm%?ia\t%m0!, %M1", operands);
ff9940b0 3717 break;
2b835d68 3718
ff9940b0 3719 case POST_DEC:
2b835d68 3720 abort (); /* Should never happen now */
ff9940b0 3721 break;
2b835d68
RE
3722
3723 case PLUS:
3724 if (GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
3725 {
3726 switch (INTVAL (XEXP (XEXP (operands[0], 0), 1)))
3727 {
3728 case -8:
3729 output_asm_insn ("stm%?db\t%m0, %M1", operands);
3730 return "";
3731
3732 case -4:
3733 output_asm_insn ("stm%?da\t%m0, %M1", operands);
3734 return "";
3735
3736 case 4:
3737 output_asm_insn ("stm%?ib\t%m0, %M1", operands);
3738 return "";
3739 }
3740 }
3741 /* Fall through */
3742
ff9940b0 3743 default:
cce8749e
CH
3744 otherops[0] = adj_offsettable_operand (operands[0], 4);
3745 otherops[1] = gen_rtx (REG, SImode, 1 + REGNO (operands[1]));
9997d19d
RE
3746 output_asm_insn ("str%?\t%1, %0", operands);
3747 output_asm_insn ("str%?\t%1, %0", otherops);
cce8749e
CH
3748 }
3749 }
2b835d68
RE
3750 else
3751 abort(); /* Constraints should prevent this */
cce8749e 3752
9997d19d
RE
3753 return "";
3754}
cce8749e
CH
3755
3756
3757/* Output an arbitrary MOV reg, #n.
3758 OPERANDS[0] is a register. OPERANDS[1] is a const_int. */
3759
3760char *
3761output_mov_immediate (operands)
f3bb6135 3762 rtx *operands;
cce8749e 3763{
f3bb6135 3764 HOST_WIDE_INT n = INTVAL (operands[1]);
cce8749e
CH
3765 int n_ones = 0;
3766 int i;
3767
3768 /* Try to use one MOV */
cce8749e 3769 if (const_ok_for_arm (n))
f3bb6135 3770 {
9997d19d 3771 output_asm_insn ("mov%?\t%0, %1", operands);
f3bb6135
RE
3772 return "";
3773 }
cce8749e
CH
3774
3775 /* Try to use one MVN */
f3bb6135 3776 if (const_ok_for_arm (~n))
cce8749e 3777 {
f3bb6135 3778 operands[1] = GEN_INT (~n);
9997d19d 3779 output_asm_insn ("mvn%?\t%0, %1", operands);
f3bb6135 3780 return "";
cce8749e
CH
3781 }
3782
3783 /* If all else fails, make it out of ORRs or BICs as appropriate. */
3784
3785 for (i=0; i < 32; i++)
3786 if (n & 1 << i)
3787 n_ones++;
3788
3789 if (n_ones > 16) /* Shorter to use MVN with BIC in this case. */
9997d19d
RE
3790 output_multi_immediate(operands, "mvn%?\t%0, %1", "bic%?\t%0, %0, %1", 1,
3791 ~n);
cce8749e 3792 else
9997d19d
RE
3793 output_multi_immediate(operands, "mov%?\t%0, %1", "orr%?\t%0, %0, %1", 1,
3794 n);
f3bb6135
RE
3795
3796 return "";
3797}
cce8749e
CH
3798
3799
3800/* Output an ADD r, s, #n where n may be too big for one instruction. If
3801 adding zero to one register, output nothing. */
3802
3803char *
3804output_add_immediate (operands)
f3bb6135 3805 rtx *operands;
cce8749e 3806{
f3bb6135 3807 HOST_WIDE_INT n = INTVAL (operands[2]);
cce8749e
CH
3808
3809 if (n != 0 || REGNO (operands[0]) != REGNO (operands[1]))
3810 {
3811 if (n < 0)
3812 output_multi_immediate (operands,
9997d19d
RE
3813 "sub%?\t%0, %1, %2", "sub%?\t%0, %0, %2", 2,
3814 -n);
cce8749e
CH
3815 else
3816 output_multi_immediate (operands,
9997d19d
RE
3817 "add%?\t%0, %1, %2", "add%?\t%0, %0, %2", 2,
3818 n);
cce8749e 3819 }
f3bb6135
RE
3820
3821 return "";
3822}
cce8749e 3823
cce8749e
CH
3824/* Output a multiple immediate operation.
3825 OPERANDS is the vector of operands referred to in the output patterns.
3826 INSTR1 is the output pattern to use for the first constant.
3827 INSTR2 is the output pattern to use for subsequent constants.
3828 IMMED_OP is the index of the constant slot in OPERANDS.
3829 N is the constant value. */
3830
3831char *
3832output_multi_immediate (operands, instr1, instr2, immed_op, n)
f3bb6135 3833 rtx *operands;
cce8749e 3834 char *instr1, *instr2;
f3bb6135
RE
3835 int immed_op;
3836 HOST_WIDE_INT n;
cce8749e 3837{
f3bb6135
RE
3838#if HOST_BITS_PER_WIDE_INT > 32
3839 n &= 0xffffffff;
3840#endif
3841
cce8749e
CH
3842 if (n == 0)
3843 {
3844 operands[immed_op] = const0_rtx;
f3bb6135 3845 output_asm_insn (instr1, operands); /* Quick and easy output */
cce8749e
CH
3846 }
3847 else
3848 {
3849 int i;
3850 char *instr = instr1;
3851
3852 /* Note that n is never zero here (which would give no output) */
cce8749e
CH
3853 for (i = 0; i < 32; i += 2)
3854 {
3855 if (n & (3 << i))
3856 {
f3bb6135
RE
3857 operands[immed_op] = GEN_INT (n & (255 << i));
3858 output_asm_insn (instr, operands);
cce8749e
CH
3859 instr = instr2;
3860 i += 6;
3861 }
3862 }
3863 }
f3bb6135 3864 return "";
9997d19d 3865}
cce8749e
CH
3866
3867
3868/* Return the appropriate ARM instruction for the operation code.
3869 The returned result should not be overwritten. OP is the rtx of the
3870 operation. SHIFT_FIRST_ARG is TRUE if the first argument of the operator
3871 was shifted. */
3872
3873char *
3874arithmetic_instr (op, shift_first_arg)
3875 rtx op;
f3bb6135 3876 int shift_first_arg;
cce8749e 3877{
9997d19d 3878 switch (GET_CODE (op))
cce8749e
CH
3879 {
3880 case PLUS:
f3bb6135
RE
3881 return "add";
3882
cce8749e 3883 case MINUS:
f3bb6135
RE
3884 return shift_first_arg ? "rsb" : "sub";
3885
cce8749e 3886 case IOR:
f3bb6135
RE
3887 return "orr";
3888
cce8749e 3889 case XOR:
f3bb6135
RE
3890 return "eor";
3891
cce8749e 3892 case AND:
f3bb6135
RE
3893 return "and";
3894
cce8749e 3895 default:
f3bb6135 3896 abort ();
cce8749e 3897 }
f3bb6135 3898}
cce8749e
CH
3899
3900
3901/* Ensure valid constant shifts and return the appropriate shift mnemonic
3902 for the operation code. The returned result should not be overwritten.
3903 OP is the rtx code of the shift.
9997d19d
RE
3904 On exit, *AMOUNTP will be -1 if the shift is by a register, or a constant
3905 shift. */
cce8749e 3906
9997d19d
RE
3907static char *
3908shift_op (op, amountp)
3909 rtx op;
3910 HOST_WIDE_INT *amountp;
cce8749e 3911{
cce8749e 3912 char *mnem;
e2c671ba 3913 enum rtx_code code = GET_CODE (op);
cce8749e 3914
9997d19d
RE
3915 if (GET_CODE (XEXP (op, 1)) == REG || GET_CODE (XEXP (op, 1)) == SUBREG)
3916 *amountp = -1;
3917 else if (GET_CODE (XEXP (op, 1)) == CONST_INT)
3918 *amountp = INTVAL (XEXP (op, 1));
3919 else
3920 abort ();
3921
e2c671ba 3922 switch (code)
cce8749e
CH
3923 {
3924 case ASHIFT:
3925 mnem = "asl";
3926 break;
f3bb6135 3927
cce8749e
CH
3928 case ASHIFTRT:
3929 mnem = "asr";
cce8749e 3930 break;
f3bb6135 3931
cce8749e
CH
3932 case LSHIFTRT:
3933 mnem = "lsr";
cce8749e 3934 break;
f3bb6135 3935
9997d19d
RE
3936 case ROTATERT:
3937 mnem = "ror";
9997d19d
RE
3938 break;
3939
ff9940b0 3940 case MULT:
e2c671ba
RE
3941 /* We never have to worry about the amount being other than a
3942 power of 2, since this case can never be reloaded from a reg. */
9997d19d
RE
3943 if (*amountp != -1)
3944 *amountp = int_log2 (*amountp);
3945 else
3946 abort ();
f3bb6135
RE
3947 return "asl";
3948
cce8749e 3949 default:
f3bb6135 3950 abort ();
cce8749e
CH
3951 }
3952
e2c671ba
RE
3953 if (*amountp != -1)
3954 {
3955 /* This is not 100% correct, but follows from the desire to merge
3956 multiplication by a power of 2 with the recognizer for a
3957 shift. >=32 is not a valid shift for "asl", so we must try and
3958 output a shift that produces the correct arithmetical result.
ddd5a7c1 3959 Using lsr #32 is identical except for the fact that the carry bit
e2c671ba
RE
3960 is not set correctly if we set the flags; but we never use the
3961 carry bit from such an operation, so we can ignore that. */
3962 if (code == ROTATERT)
3963 *amountp &= 31; /* Rotate is just modulo 32 */
3964 else if (*amountp != (*amountp & 31))
3965 {
3966 if (code == ASHIFT)
3967 mnem = "lsr";
3968 *amountp = 32;
3969 }
3970
3971 /* Shifts of 0 are no-ops. */
3972 if (*amountp == 0)
3973 return NULL;
3974 }
3975
9997d19d
RE
3976 return mnem;
3977}
cce8749e
CH
3978
3979
3980/* Obtain the shift from the POWER of two. */
3981
f3bb6135 3982HOST_WIDE_INT
cce8749e 3983int_log2 (power)
f3bb6135 3984 HOST_WIDE_INT power;
cce8749e 3985{
f3bb6135 3986 HOST_WIDE_INT shift = 0;
cce8749e 3987
2b835d68 3988 while (((((HOST_WIDE_INT) 1) << shift) & power) == 0)
cce8749e
CH
3989 {
3990 if (shift > 31)
f3bb6135 3991 abort ();
cce8749e
CH
3992 shift++;
3993 }
f3bb6135
RE
3994
3995 return shift;
3996}
cce8749e 3997
cce8749e
CH
3998/* Output a .ascii pseudo-op, keeping track of lengths. This is because
3999 /bin/as is horribly restrictive. */
4000
4001void
4002output_ascii_pseudo_op (stream, p, len)
4003 FILE *stream;
f1b3f515 4004 unsigned char *p;
cce8749e
CH
4005 int len;
4006{
4007 int i;
4008 int len_so_far = 1000;
4009 int chars_so_far = 0;
4010
4011 for (i = 0; i < len; i++)
4012 {
4013 register int c = p[i];
4014
4015 if (len_so_far > 50)
4016 {
4017 if (chars_so_far)
4018 fputs ("\"\n", stream);
4019 fputs ("\t.ascii\t\"", stream);
4020 len_so_far = 0;
4021 arm_increase_location (chars_so_far);
4022 chars_so_far = 0;
4023 }
4024
4025 if (c == '\"' || c == '\\')
4026 {
4027 putc('\\', stream);
4028 len_so_far++;
4029 }
f3bb6135 4030
cce8749e
CH
4031 if (c >= ' ' && c < 0177)
4032 {
4033 putc (c, stream);
4034 len_so_far++;
4035 }
4036 else
4037 {
4038 fprintf (stream, "\\%03o", c);
4039 len_so_far +=4;
4040 }
f3bb6135 4041
cce8749e
CH
4042 chars_so_far++;
4043 }
f3bb6135 4044
cce8749e
CH
4045 fputs ("\"\n", stream);
4046 arm_increase_location (chars_so_far);
f3bb6135 4047}
cce8749e 4048\f
ff9940b0
RE
4049
4050/* Try to determine whether a pattern really clobbers the link register.
4051 This information is useful when peepholing, so that lr need not be pushed
0e84b556
RK
4052 if we combine a call followed by a return.
4053 NOTE: This code does not check for side-effect expressions in a SET_SRC:
4054 such a check should not be needed because these only update an existing
4055 value within a register; the register must still be set elsewhere within
4056 the function. */
ff9940b0
RE
4057
4058static int
4059pattern_really_clobbers_lr (x)
f3bb6135 4060 rtx x;
ff9940b0
RE
4061{
4062 int i;
4063
4064 switch (GET_CODE (x))
4065 {
4066 case SET:
4067 switch (GET_CODE (SET_DEST (x)))
4068 {
4069 case REG:
4070 return REGNO (SET_DEST (x)) == 14;
f3bb6135 4071
ff9940b0
RE
4072 case SUBREG:
4073 if (GET_CODE (XEXP (SET_DEST (x), 0)) == REG)
4074 return REGNO (XEXP (SET_DEST (x), 0)) == 14;
f3bb6135 4075
0e84b556
RK
4076 if (GET_CODE (XEXP (SET_DEST (x), 0)) == MEM)
4077 return 0;
ff9940b0 4078 abort ();
f3bb6135 4079
ff9940b0
RE
4080 default:
4081 return 0;
4082 }
f3bb6135 4083
ff9940b0
RE
4084 case PARALLEL:
4085 for (i = 0; i < XVECLEN (x, 0); i++)
4086 if (pattern_really_clobbers_lr (XVECEXP (x, 0, i)))
4087 return 1;
4088 return 0;
f3bb6135 4089
ff9940b0
RE
4090 case CLOBBER:
4091 switch (GET_CODE (XEXP (x, 0)))
4092 {
4093 case REG:
4094 return REGNO (XEXP (x, 0)) == 14;
f3bb6135 4095
ff9940b0
RE
4096 case SUBREG:
4097 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG)
4098 return REGNO (XEXP (XEXP (x, 0), 0)) == 14;
4099 abort ();
f3bb6135 4100
ff9940b0
RE
4101 default:
4102 return 0;
4103 }
f3bb6135 4104
ff9940b0
RE
4105 case UNSPEC:
4106 return 1;
f3bb6135 4107
ff9940b0
RE
4108 default:
4109 return 0;
4110 }
4111}
4112
4113static int
4114function_really_clobbers_lr (first)
f3bb6135 4115 rtx first;
ff9940b0
RE
4116{
4117 rtx insn, next;
4118
4119 for (insn = first; insn; insn = next_nonnote_insn (insn))
4120 {
4121 switch (GET_CODE (insn))
4122 {
4123 case BARRIER:
4124 case NOTE:
4125 case CODE_LABEL:
4126 case JUMP_INSN: /* Jump insns only change the PC (and conds) */
4127 case INLINE_HEADER:
4128 break;
f3bb6135 4129
ff9940b0
RE
4130 case INSN:
4131 if (pattern_really_clobbers_lr (PATTERN (insn)))
4132 return 1;
4133 break;
f3bb6135 4134
ff9940b0
RE
4135 case CALL_INSN:
4136 /* Don't yet know how to handle those calls that are not to a
4137 SYMBOL_REF */
4138 if (GET_CODE (PATTERN (insn)) != PARALLEL)
4139 abort ();
f3bb6135 4140
ff9940b0
RE
4141 switch (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)))
4142 {
4143 case CALL:
4144 if (GET_CODE (XEXP (XEXP (XVECEXP (PATTERN (insn), 0, 0), 0), 0))
4145 != SYMBOL_REF)
4146 return 1;
4147 break;
f3bb6135 4148
ff9940b0
RE
4149 case SET:
4150 if (GET_CODE (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn),
4151 0, 0)), 0), 0))
4152 != SYMBOL_REF)
4153 return 1;
4154 break;
f3bb6135 4155
ff9940b0
RE
4156 default: /* Don't recognize it, be safe */
4157 return 1;
4158 }
f3bb6135 4159
ff9940b0
RE
4160 /* A call can be made (by peepholing) not to clobber lr iff it is
4161 followed by a return. There may, however, be a use insn iff
4162 we are returning the result of the call.
4163 If we run off the end of the insn chain, then that means the
4164 call was at the end of the function. Unfortunately we don't
4165 have a return insn for the peephole to recognize, so we
4166 must reject this. (Can this be fixed by adding our own insn?) */
4167 if ((next = next_nonnote_insn (insn)) == NULL)
4168 return 1;
f3bb6135 4169
ff9940b0
RE
4170 if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == USE
4171 && (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
4172 && (REGNO (SET_DEST (XVECEXP (PATTERN (insn), 0, 0)))
4173 == REGNO (XEXP (PATTERN (next), 0))))
4174 if ((next = next_nonnote_insn (next)) == NULL)
4175 return 1;
f3bb6135 4176
ff9940b0
RE
4177 if (GET_CODE (next) == JUMP_INSN
4178 && GET_CODE (PATTERN (next)) == RETURN)
4179 break;
4180 return 1;
f3bb6135 4181
ff9940b0
RE
4182 default:
4183 abort ();
4184 }
4185 }
f3bb6135 4186
ff9940b0
RE
4187 /* We have reached the end of the chain so lr was _not_ clobbered */
4188 return 0;
4189}
4190
4191char *
84ed5e79 4192output_return_instruction (operand, really_return, reverse)
f3bb6135
RE
4193 rtx operand;
4194 int really_return;
84ed5e79 4195 int reverse;
ff9940b0
RE
4196{
4197 char instr[100];
4198 int reg, live_regs = 0;
e2c671ba
RE
4199 int volatile_func = (optimize > 0
4200 && TREE_THIS_VOLATILE (current_function_decl));
4201
4202 return_used_this_function = 1;
ff9940b0 4203
e2c671ba
RE
4204 if (volatile_func)
4205 {
4206 rtx ops[2];
4207 /* If this function was declared non-returning, and we have found a tail
4208 call, then we have to trust that the called function won't return. */
4209 if (! really_return)
4210 return "";
4211
4212 /* Otherwise, trap an attempted return by aborting. */
4213 ops[0] = operand;
4214 ops[1] = gen_rtx (SYMBOL_REF, Pmode, "abort");
2b835d68 4215 assemble_external_libcall (ops[1]);
84ed5e79 4216 output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
e2c671ba
RE
4217 return "";
4218 }
4219
f3bb6135 4220 if (current_function_calls_alloca && ! really_return)
ff9940b0
RE
4221 abort();
4222
f3bb6135
RE
4223 for (reg = 0; reg <= 10; reg++)
4224 if (regs_ever_live[reg] && ! call_used_regs[reg])
ff9940b0
RE
4225 live_regs++;
4226
f3bb6135 4227 if (live_regs || (regs_ever_live[14] && ! lr_save_eliminated))
ff9940b0
RE
4228 live_regs++;
4229
4230 if (frame_pointer_needed)
4231 live_regs += 4;
4232
4233 if (live_regs)
4234 {
f3bb6135 4235 if (lr_save_eliminated || ! regs_ever_live[14])
ff9940b0 4236 live_regs++;
f3bb6135 4237
ff9940b0 4238 if (frame_pointer_needed)
84ed5e79
RE
4239 strcpy (instr,
4240 reverse ? "ldm%?%D0ea\t%|fp, {" : "ldm%?%d0ea\t%|fp, {");
ff9940b0 4241 else
84ed5e79
RE
4242 strcpy (instr,
4243 reverse ? "ldm%?%D0fd\t%|sp!, {" : "ldm%?%d0fd\t%|sp!, {");
f3bb6135
RE
4244
4245 for (reg = 0; reg <= 10; reg++)
4246 if (regs_ever_live[reg] && ! call_used_regs[reg])
ff9940b0 4247 {
1d5473cb 4248 strcat (instr, "%|");
ff9940b0
RE
4249 strcat (instr, reg_names[reg]);
4250 if (--live_regs)
4251 strcat (instr, ", ");
4252 }
f3bb6135 4253
ff9940b0
RE
4254 if (frame_pointer_needed)
4255 {
1d5473cb 4256 strcat (instr, "%|");
ff9940b0
RE
4257 strcat (instr, reg_names[11]);
4258 strcat (instr, ", ");
1d5473cb 4259 strcat (instr, "%|");
ff9940b0
RE
4260 strcat (instr, reg_names[13]);
4261 strcat (instr, ", ");
1d5473cb 4262 strcat (instr, "%|");
ff9940b0
RE
4263 strcat (instr, really_return ? reg_names[15] : reg_names[14]);
4264 }
4265 else
1d5473cb
RE
4266 {
4267 strcat (instr, "%|");
4268 strcat (instr, really_return ? reg_names[15] : reg_names[14]);
4269 }
2b835d68 4270 strcat (instr, (TARGET_APCS_32 || !really_return) ? "}" : "}^");
f3bb6135 4271 output_asm_insn (instr, &operand);
ff9940b0
RE
4272 }
4273 else if (really_return)
4274 {
84ed5e79
RE
4275 sprintf (instr, "mov%%?%%%s0%s\t%%|pc, %%|lr",
4276 reverse ? "D" : "d", TARGET_APCS_32 ? "" : "s");
f3bb6135 4277 output_asm_insn (instr, &operand);
ff9940b0 4278 }
f3bb6135 4279
ff9940b0
RE
4280 return "";
4281}
4282
e82ea128
DE
4283/* Return nonzero if optimizing and the current function is volatile.
4284 Such functions never return, and many memory cycles can be saved
4285 by not storing register values that will never be needed again.
4286 This optimization was added to speed up context switching in a
4287 kernel application. */
a0b2ce4c 4288
e2c671ba
RE
4289int
4290arm_volatile_func ()
4291{
4292 return (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl));
4293}
4294
f3bb6135
RE
4295/* Return the size of the prologue. It's not too bad if we slightly
4296 over-estimate. */
4297
4298static int
4299get_prologue_size ()
4300{
e2c671ba 4301 return profile_flag ? 12 : 0;
f3bb6135
RE
4302}
4303
ff9940b0
RE
4304/* The amount of stack adjustment that happens here, in output_return and in
4305 output_epilogue must be exactly the same as was calculated during reload,
4306 or things will point to the wrong place. The only time we can safely
4307 ignore this constraint is when a function has no arguments on the stack,
4308 no stack frame requirement and no live registers execpt for `lr'. If we
4309 can guarantee that by making all function calls into tail calls and that
4310 lr is not clobbered in any other way, then there is no need to push lr
4311 onto the stack. */
4312
cce8749e 4313void
f3bb6135 4314output_func_prologue (f, frame_size)
cce8749e
CH
4315 FILE *f;
4316 int frame_size;
4317{
f3bb6135 4318 int reg, live_regs_mask = 0;
cce8749e 4319 rtx operands[3];
e2c671ba
RE
4320 int volatile_func = (optimize > 0
4321 && TREE_THIS_VOLATILE (current_function_decl));
cce8749e 4322
cce8749e
CH
4323 /* Nonzero if we must stuff some register arguments onto the stack as if
4324 they were passed there. */
4325 int store_arg_regs = 0;
4326
abaa26e5
RE
4327 if (arm_ccfsm_state || arm_target_insn)
4328 abort (); /* Sanity check */
31fdb4d5
DE
4329
4330 if (arm_naked_function_p (current_function_decl))
4331 return;
4332
ff9940b0
RE
4333 return_used_this_function = 0;
4334 lr_save_eliminated = 0;
4335
f3139301
DE
4336 fprintf (f, "\t%s args = %d, pretend = %d, frame = %d\n",
4337 ASM_COMMENT_START, current_function_args_size,
1d5473cb 4338 current_function_pretend_args_size, frame_size);
f3139301
DE
4339 fprintf (f, "\t%s frame_needed = %d, current_function_anonymous_args = %d\n",
4340 ASM_COMMENT_START, frame_pointer_needed,
1d5473cb 4341 current_function_anonymous_args);
cce8749e 4342
e2c671ba 4343 if (volatile_func)
f3139301 4344 fprintf (f, "\t%s Volatile function.\n", ASM_COMMENT_START);
e2c671ba 4345
cce8749e
CH
4346 if (current_function_anonymous_args && current_function_pretend_args_size)
4347 store_arg_regs = 1;
4348
f3bb6135
RE
4349 for (reg = 0; reg <= 10; reg++)
4350 if (regs_ever_live[reg] && ! call_used_regs[reg])
cce8749e
CH
4351 live_regs_mask |= (1 << reg);
4352
ff9940b0 4353 if (frame_pointer_needed)
e2c671ba 4354 live_regs_mask |= 0xD800;
cce8749e 4355 else if (regs_ever_live[14])
ff9940b0
RE
4356 {
4357 if (! current_function_args_size
f3bb6135 4358 && ! function_really_clobbers_lr (get_insns ()))
e2c671ba 4359 lr_save_eliminated = 1;
ff9940b0
RE
4360 else
4361 live_regs_mask |= 0x4000;
4362 }
cce8749e 4363
cce8749e
CH
4364 if (live_regs_mask)
4365 {
ff9940b0
RE
4366 /* if a di mode load/store multiple is used, and the base register
4367 is r3, then r4 can become an ever live register without lr
4368 doing so, in this case we need to push lr as well, or we
4369 will fail to get a proper return. */
4370
4371 live_regs_mask |= 0x4000;
4372 lr_save_eliminated = 0;
f3bb6135 4373
cce8749e
CH
4374 }
4375
e2c671ba 4376 if (lr_save_eliminated)
f3139301
DE
4377 fprintf (f,"\t%s I don't think this function clobbers lr\n",
4378 ASM_COMMENT_START);
f3bb6135 4379}
cce8749e
CH
4380
4381
4382void
f3bb6135 4383output_func_epilogue (f, frame_size)
cce8749e
CH
4384 FILE *f;
4385 int frame_size;
4386{
abaa26e5 4387 int reg, live_regs_mask = 0, code_size = 0;
ff9940b0
RE
4388 /* If we need this then it will always be at lesat this much */
4389 int floats_offset = 24;
cce8749e 4390 rtx operands[3];
e2c671ba
RE
4391 int volatile_func = (optimize > 0
4392 && TREE_THIS_VOLATILE (current_function_decl));
cce8749e 4393
ff9940b0 4394 if (use_return_insn() && return_used_this_function)
cce8749e 4395 {
ff9940b0
RE
4396 if (frame_size && !(frame_pointer_needed || TARGET_APCS))
4397 {
4398 abort ();
4399 }
f3bb6135 4400 goto epilogue_done;
cce8749e 4401 }
cce8749e 4402
31fdb4d5
DE
4403 /* Naked functions don't have epilogues. */
4404 if (arm_naked_function_p (current_function_decl))
4405 goto epilogue_done;
4406
e2c671ba
RE
4407 /* A volatile function should never return. Call abort. */
4408 if (volatile_func)
4409 {
4410 rtx op = gen_rtx (SYMBOL_REF, Pmode, "abort");
2b835d68 4411 assemble_external_libcall (op);
e2c671ba
RE
4412 output_asm_insn ("bl\t%a0", &op);
4413 code_size = 4;
4414 goto epilogue_done;
4415 }
4416
f3bb6135
RE
4417 for (reg = 0; reg <= 10; reg++)
4418 if (regs_ever_live[reg] && ! call_used_regs[reg])
cce8749e 4419 {
ff9940b0
RE
4420 live_regs_mask |= (1 << reg);
4421 floats_offset += 4;
cce8749e
CH
4422 }
4423
ff9940b0 4424 if (frame_pointer_needed)
cce8749e 4425 {
f3bb6135
RE
4426 for (reg = 23; reg > 15; reg--)
4427 if (regs_ever_live[reg] && ! call_used_regs[reg])
ff9940b0 4428 {
f3139301
DE
4429 fprintf (f, "\tldfe\t%s%s, [%sfp, #-%d]\n", REGISTER_PREFIX,
4430 reg_names[reg], REGISTER_PREFIX, floats_offset);
ff9940b0
RE
4431 floats_offset += 12;
4432 code_size += 4;
4433 }
4434
4435 live_regs_mask |= 0xA800;
1d5473cb 4436 print_multi_reg (f, "ldmea\t%sfp", live_regs_mask,
2b835d68 4437 TARGET_APCS_32 ? FALSE : TRUE);
cce8749e
CH
4438 code_size += 4;
4439 }
4440 else
4441 {
d2288d8d
TG
4442 /* Restore stack pointer if necessary. */
4443 if (frame_size)
4444 {
4445 operands[0] = operands[1] = stack_pointer_rtx;
4446 operands[2] = gen_rtx (CONST_INT, VOIDmode, frame_size);
4447 output_add_immediate (operands);
4448 }
4449
f3bb6135
RE
4450 for (reg = 16; reg < 24; reg++)
4451 if (regs_ever_live[reg] && ! call_used_regs[reg])
ff9940b0 4452 {
f3139301
DE
4453 fprintf (f, "\tldfe\t%s%s, [%ssp], #12\n", REGISTER_PREFIX,
4454 reg_names[reg], REGISTER_PREFIX);
ff9940b0
RE
4455 code_size += 4;
4456 }
cce8749e
CH
4457 if (current_function_pretend_args_size == 0 && regs_ever_live[14])
4458 {
1d5473cb 4459 print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask | 0x8000,
2b835d68 4460 TARGET_APCS_32 ? FALSE : TRUE);
cce8749e
CH
4461 code_size += 4;
4462 }
4463 else
4464 {
ff9940b0 4465 if (live_regs_mask || regs_ever_live[14])
cce8749e 4466 {
ff9940b0 4467 live_regs_mask |= 0x4000;
1d5473cb 4468 print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE);
cce8749e
CH
4469 code_size += 4;
4470 }
4471 if (current_function_pretend_args_size)
4472 {
4473 operands[0] = operands[1] = stack_pointer_rtx;
4474 operands[2] = gen_rtx (CONST_INT, VOIDmode,
4475 current_function_pretend_args_size);
4476 output_add_immediate (operands);
4477 }
2b835d68
RE
4478 fprintf (f, (TARGET_APCS_32 ? "\tmov\t%spc, %slr\n"
4479 : "\tmovs\t%spc, %slr\n"),
f3139301 4480 REGISTER_PREFIX, REGISTER_PREFIX, f);
cce8749e
CH
4481 code_size += 4;
4482 }
4483 }
f3bb6135
RE
4484
4485 epilogue_done:
4486
4487 /* insn_addresses isn't allocated when not optimizing */
4488
4489 if (optimize > 0)
4490 arm_increase_location (code_size
4491 + insn_addresses[INSN_UID (get_last_insn ())]
4492 + get_prologue_size ());
4493
cce8749e 4494 current_function_anonymous_args = 0;
f3bb6135 4495}
e2c671ba
RE
4496
4497static void
4498emit_multi_reg_push (mask)
4499 int mask;
4500{
4501 int num_regs = 0;
4502 int i, j;
4503 rtx par;
4504
4505 for (i = 0; i < 16; i++)
4506 if (mask & (1 << i))
4507 num_regs++;
4508
4509 if (num_regs == 0 || num_regs > 16)
4510 abort ();
4511
4512 par = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (num_regs));
4513
4514 for (i = 0; i < 16; i++)
4515 {
4516 if (mask & (1 << i))
4517 {
4518 XVECEXP (par, 0, 0)
4519 = gen_rtx (SET, VOIDmode, gen_rtx (MEM, BLKmode,
4520 gen_rtx (PRE_DEC, BLKmode,
4521 stack_pointer_rtx)),
4522 gen_rtx (UNSPEC, BLKmode,
4523 gen_rtvec (1, gen_rtx (REG, SImode, i)),
4524 2));
4525 break;
4526 }
4527 }
4528
4529 for (j = 1, i++; j < num_regs; i++)
4530 {
4531 if (mask & (1 << i))
4532 {
4533 XVECEXP (par, 0, j)
4534 = gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, i));
4535 j++;
4536 }
4537 }
4538 emit_insn (par);
4539}
4540
4541void
4542arm_expand_prologue ()
4543{
4544 int reg;
4545 rtx amount = GEN_INT (- get_frame_size ());
4546 rtx push_insn;
4547 int num_regs;
4548 int live_regs_mask = 0;
4549 int store_arg_regs = 0;
4550 int volatile_func = (optimize > 0
4551 && TREE_THIS_VOLATILE (current_function_decl));
4552
31fdb4d5
DE
4553 /* Naked functions don't have prologues. */
4554 if (arm_naked_function_p (current_function_decl))
4555 return;
4556
e2c671ba
RE
4557 if (current_function_anonymous_args && current_function_pretend_args_size)
4558 store_arg_regs = 1;
4559
4560 if (! volatile_func)
4561 for (reg = 0; reg <= 10; reg++)
4562 if (regs_ever_live[reg] && ! call_used_regs[reg])
4563 live_regs_mask |= 1 << reg;
4564
4565 if (! volatile_func && regs_ever_live[14])
4566 live_regs_mask |= 0x4000;
4567
4568 if (frame_pointer_needed)
4569 {
4570 live_regs_mask |= 0xD800;
4571 emit_insn (gen_movsi (gen_rtx (REG, SImode, 12),
4572 stack_pointer_rtx));
4573 }
4574
4575 if (current_function_pretend_args_size)
4576 {
4577 if (store_arg_regs)
4578 emit_multi_reg_push ((0xf0 >> (current_function_pretend_args_size / 4))
4579 & 0xf);
4580 else
4581 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
4582 GEN_INT (-current_function_pretend_args_size)));
4583 }
4584
4585 if (live_regs_mask)
4586 {
4587 /* If we have to push any regs, then we must push lr as well, or
ddd5a7c1 4588 we won't get a proper return. */
e2c671ba
RE
4589 live_regs_mask |= 0x4000;
4590 emit_multi_reg_push (live_regs_mask);
4591 }
4592
4593 /* For now the integer regs are still pushed in output_func_epilogue (). */
4594
4595 if (! volatile_func)
4596 for (reg = 23; reg > 15; reg--)
4597 if (regs_ever_live[reg] && ! call_used_regs[reg])
4598 emit_insn (gen_rtx (SET, VOIDmode,
4599 gen_rtx (MEM, XFmode,
4600 gen_rtx (PRE_DEC, XFmode,
4601 stack_pointer_rtx)),
4602 gen_rtx (REG, XFmode, reg)));
4603
4604 if (frame_pointer_needed)
4605 emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx (REG, SImode, 12),
4606 (GEN_INT
4607 (-(4 + current_function_pretend_args_size)))));
4608
4609 if (amount != const0_rtx)
4610 {
4611 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, amount));
4612 emit_insn (gen_rtx (CLOBBER, VOIDmode,
4613 gen_rtx (MEM, BLKmode, stack_pointer_rtx)));
4614 }
4615
4616 /* If we are profiling, make sure no instructions are scheduled before
4617 the call to mcount. */
4618 if (profile_flag || profile_block_flag)
4619 emit_insn (gen_blockage ());
4620}
4621
cce8749e 4622\f
9997d19d
RE
4623/* If CODE is 'd', then the X is a condition operand and the instruction
4624 should only be executed if the condition is true.
ddd5a7c1 4625 if CODE is 'D', then the X is a condition operand and the instruction
9997d19d
RE
4626 should only be executed if the condition is false: however, if the mode
4627 of the comparison is CCFPEmode, then always execute the instruction -- we
4628 do this because in these circumstances !GE does not necessarily imply LT;
4629 in these cases the instruction pattern will take care to make sure that
4630 an instruction containing %d will follow, thereby undoing the effects of
ddd5a7c1 4631 doing this instruction unconditionally.
9997d19d
RE
4632 If CODE is 'N' then X is a floating point operand that must be negated
4633 before output.
4634 If CODE is 'B' then output a bitwise inverted value of X (a const int).
4635 If X is a REG and CODE is `M', output a ldm/stm style multi-reg. */
4636
4637void
4638arm_print_operand (stream, x, code)
4639 FILE *stream;
4640 rtx x;
4641 int code;
4642{
4643 switch (code)
4644 {
4645 case '@':
f3139301 4646 fputs (ASM_COMMENT_START, stream);
9997d19d
RE
4647 return;
4648
4649 case '|':
f3139301 4650 fputs (REGISTER_PREFIX, stream);
9997d19d
RE
4651 return;
4652
4653 case '?':
4654 if (arm_ccfsm_state == 3 || arm_ccfsm_state == 4)
4655 fputs (arm_condition_codes[arm_current_cc], stream);
4656 return;
4657
4658 case 'N':
4659 {
4660 REAL_VALUE_TYPE r;
4661 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
4662 r = REAL_VALUE_NEGATE (r);
4663 fprintf (stream, "%s", fp_const_from_val (&r));
4664 }
4665 return;
4666
4667 case 'B':
4668 if (GET_CODE (x) == CONST_INT)
4669 fprintf (stream,
4670#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
4671 "%d",
4672#else
4673 "%ld",
4674#endif
4675 ARM_SIGN_EXTEND (~ INTVAL (x)));
4676 else
4677 {
4678 putc ('~', stream);
4679 output_addr_const (stream, x);
4680 }
4681 return;
4682
4683 case 'i':
4684 fprintf (stream, "%s", arithmetic_instr (x, 1));
4685 return;
4686
4687 case 'I':
4688 fprintf (stream, "%s", arithmetic_instr (x, 0));
4689 return;
4690
4691 case 'S':
4692 {
4693 HOST_WIDE_INT val;
e2c671ba 4694 char *shift = shift_op (x, &val);
9997d19d 4695
e2c671ba
RE
4696 if (shift)
4697 {
4698 fprintf (stream, ", %s ", shift_op (x, &val));
4699 if (val == -1)
4700 arm_print_operand (stream, XEXP (x, 1), 0);
4701 else
4702 fprintf (stream,
9997d19d 4703#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
e2c671ba 4704 "#%d",
9997d19d 4705#else
e2c671ba 4706 "#%ld",
9997d19d 4707#endif
e2c671ba
RE
4708 val);
4709 }
9997d19d
RE
4710 }
4711 return;
4712
c1c2bc04
RE
4713 case 'Q':
4714 if (REGNO (x) > 15)
4715 abort ();
4716 fputs (REGISTER_PREFIX, stream);
4717 fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], stream);
4718 return;
4719
9997d19d
RE
4720 case 'R':
4721 if (REGNO (x) > 15)
4722 abort ();
f3139301 4723 fputs (REGISTER_PREFIX, stream);
c1c2bc04 4724 fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], stream);
9997d19d
RE
4725 return;
4726
4727 case 'm':
f3139301 4728 fputs (REGISTER_PREFIX, stream);
9997d19d
RE
4729 if (GET_CODE (XEXP (x, 0)) == REG)
4730 fputs (reg_names[REGNO (XEXP (x, 0))], stream);
4731 else
4732 fputs (reg_names[REGNO (XEXP (XEXP (x, 0), 0))], stream);
4733 return;
4734
4735 case 'M':
f3139301
DE
4736 fprintf (stream, "{%s%s-%s%s}", REGISTER_PREFIX, reg_names[REGNO (x)],
4737 REGISTER_PREFIX, reg_names[REGNO (x) - 1
1d5473cb
RE
4738 + ((GET_MODE_SIZE (GET_MODE (x))
4739 + GET_MODE_SIZE (SImode) - 1)
4740 / GET_MODE_SIZE (SImode))]);
9997d19d
RE
4741 return;
4742
4743 case 'd':
4744 if (x)
4745 fputs (arm_condition_codes[get_arm_condition_code (x)],
4746 stream);
4747 return;
4748
4749 case 'D':
84ed5e79 4750 if (x)
9997d19d
RE
4751 fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
4752 (get_arm_condition_code (x))],
4753 stream);
4754 return;
4755
4756 default:
4757 if (x == 0)
4758 abort ();
4759
4760 if (GET_CODE (x) == REG)
1d5473cb 4761 {
f3139301 4762 fputs (REGISTER_PREFIX, stream);
1d5473cb
RE
4763 fputs (reg_names[REGNO (x)], stream);
4764 }
9997d19d
RE
4765 else if (GET_CODE (x) == MEM)
4766 {
4767 output_memory_reference_mode = GET_MODE (x);
4768 output_address (XEXP (x, 0));
4769 }
4770 else if (GET_CODE (x) == CONST_DOUBLE)
4771 fprintf (stream, "#%s", fp_immediate_constant (x));
4772 else if (GET_CODE (x) == NEG)
4773 abort (); /* This should never happen now. */
4774 else
4775 {
4776 fputc ('#', stream);
4777 output_addr_const (stream, x);
4778 }
4779 }
4780}
4781
cce8749e
CH
4782/* Increase the `arm_text_location' by AMOUNT if we're in the text
4783 segment. */
4784
4785void
4786arm_increase_location (amount)
4787 int amount;
4788{
4789 if (in_text_section ())
4790 arm_text_location += amount;
f3bb6135 4791}
cce8749e
CH
4792
4793
4794/* Output a label definition. If this label is within the .text segment, it
4795 is stored in OFFSET_TABLE, to be used when building `llc' instructions.
4796 Maybe GCC remembers names not starting with a `*' for a long time, but this
4797 is a minority anyway, so we just make a copy. Do not store the leading `*'
4798 if the name starts with one. */
4799
4800void
4801arm_asm_output_label (stream, name)
4802 FILE *stream;
4803 char *name;
4804{
4805 char *real_name, *s;
4806 struct label_offset *cur;
4807 int hash = 0;
4808
2b835d68 4809 ARM_OUTPUT_LABEL (stream, name);
cce8749e
CH
4810 if (! in_text_section ())
4811 return;
4812
4813 if (name[0] == '*')
4814 {
4815 real_name = xmalloc (1 + strlen (&name[1]));
4816 strcpy (real_name, &name[1]);
4817 }
4818 else
4819 {
4820 real_name = xmalloc (2 + strlen (name));
f3139301 4821 strcpy (real_name, USER_LABEL_PREFIX);
cce8749e
CH
4822 strcat (real_name, name);
4823 }
4824 for (s = real_name; *s; s++)
4825 hash += *s;
f3bb6135 4826
cce8749e 4827 hash = hash % LABEL_HASH_SIZE;
838928c2 4828 cur = (struct label_offset *) xmalloc (sizeof (struct label_offset));
cce8749e
CH
4829 cur->name = real_name;
4830 cur->offset = arm_text_location;
4831 cur->cdr = offset_table[hash];
4832 offset_table[hash] = cur;
f3bb6135 4833}
cce8749e 4834
cce8749e
CH
4835/* Output code resembling an .lcomm directive. /bin/as doesn't have this
4836 directive hence this hack, which works by reserving some `.space' in the
4837 bss segment directly.
4838
4839 XXX This is a severe hack, which is guaranteed NOT to work since it doesn't
4840 define STATIC COMMON space but merely STATIC BSS space. */
4841
4842void
4843output_lcomm_directive (stream, name, size, rounded)
4844 FILE *stream;
4845 char *name;
4846 int size, rounded;
4847{
f3139301 4848 fprintf (stream, "\n\t.bss\t%s .lcomm\n", ASM_COMMENT_START);
cce8749e
CH
4849 assemble_name (stream, name);
4850 fprintf (stream, ":\t.space\t%d\n", rounded);
4851 if (in_text_section ())
4852 fputs ("\n\t.text\n", stream);
4853 else
4854 fputs ("\n\t.data\n", stream);
f3bb6135 4855}
cce8749e
CH
4856\f
4857/* A finite state machine takes care of noticing whether or not instructions
4858 can be conditionally executed, and thus decrease execution time and code
4859 size by deleting branch instructions. The fsm is controlled by
4860 final_prescan_insn, and controls the actions of ASM_OUTPUT_OPCODE. */
4861
4862/* The state of the fsm controlling condition codes are:
4863 0: normal, do nothing special
4864 1: make ASM_OUTPUT_OPCODE not output this instruction
4865 2: make ASM_OUTPUT_OPCODE not output this instruction
4866 3: make instructions conditional
4867 4: make instructions conditional
4868
4869 State transitions (state->state by whom under condition):
4870 0 -> 1 final_prescan_insn if the `target' is a label
4871 0 -> 2 final_prescan_insn if the `target' is an unconditional branch
4872 1 -> 3 ASM_OUTPUT_OPCODE after not having output the conditional branch
4873 2 -> 4 ASM_OUTPUT_OPCODE after not having output the conditional branch
4874 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL if the `target' label is reached
4875 (the target label has CODE_LABEL_NUMBER equal to arm_target_label).
4876 4 -> 0 final_prescan_insn if the `target' unconditional branch is reached
4877 (the target insn is arm_target_insn).
4878
ff9940b0
RE
4879 If the jump clobbers the conditions then we use states 2 and 4.
4880
4881 A similar thing can be done with conditional return insns.
4882
cce8749e
CH
4883 XXX In case the `target' is an unconditional branch, this conditionalising
4884 of the instructions always reduces code size, but not always execution
4885 time. But then, I want to reduce the code size to somewhere near what
4886 /bin/cc produces. */
4887
cce8749e
CH
4888/* Returns the index of the ARM condition code string in
4889 `arm_condition_codes'. COMPARISON should be an rtx like
4890 `(eq (...) (...))'. */
4891
84ed5e79 4892static enum arm_cond_code
cce8749e
CH
4893get_arm_condition_code (comparison)
4894 rtx comparison;
4895{
5165176d 4896 enum machine_mode mode = GET_MODE (XEXP (comparison, 0));
84ed5e79
RE
4897 register int code;
4898 register enum rtx_code comp_code = GET_CODE (comparison);
5165176d
RE
4899
4900 if (GET_MODE_CLASS (mode) != MODE_CC)
84ed5e79 4901 mode = SELECT_CC_MODE (comp_code, XEXP (comparison, 0),
5165176d
RE
4902 XEXP (comparison, 1));
4903
4904 switch (mode)
cce8749e 4905 {
84ed5e79
RE
4906 case CC_DNEmode: code = ARM_NE; goto dominance;
4907 case CC_DEQmode: code = ARM_EQ; goto dominance;
4908 case CC_DGEmode: code = ARM_GE; goto dominance;
4909 case CC_DGTmode: code = ARM_GT; goto dominance;
4910 case CC_DLEmode: code = ARM_LE; goto dominance;
4911 case CC_DLTmode: code = ARM_LT; goto dominance;
4912 case CC_DGEUmode: code = ARM_CS; goto dominance;
4913 case CC_DGTUmode: code = ARM_HI; goto dominance;
4914 case CC_DLEUmode: code = ARM_LS; goto dominance;
4915 case CC_DLTUmode: code = ARM_CC;
4916
4917 dominance:
4918 if (comp_code != EQ && comp_code != NE)
4919 abort ();
4920
4921 if (comp_code == EQ)
4922 return ARM_INVERSE_CONDITION_CODE (code);
4923 return code;
4924
5165176d 4925 case CC_NOOVmode:
84ed5e79 4926 switch (comp_code)
5165176d 4927 {
84ed5e79
RE
4928 case NE: return ARM_NE;
4929 case EQ: return ARM_EQ;
4930 case GE: return ARM_PL;
4931 case LT: return ARM_MI;
5165176d
RE
4932 default: abort ();
4933 }
4934
4935 case CC_Zmode:
4936 case CCFPmode:
84ed5e79 4937 switch (comp_code)
5165176d 4938 {
84ed5e79
RE
4939 case NE: return ARM_NE;
4940 case EQ: return ARM_EQ;
5165176d
RE
4941 default: abort ();
4942 }
4943
4944 case CCFPEmode:
84ed5e79
RE
4945 switch (comp_code)
4946 {
4947 case GE: return ARM_GE;
4948 case GT: return ARM_GT;
4949 case LE: return ARM_LS;
4950 case LT: return ARM_MI;
4951 default: abort ();
4952 }
4953
4954 case CC_SWPmode:
4955 switch (comp_code)
4956 {
4957 case NE: return ARM_NE;
4958 case EQ: return ARM_EQ;
4959 case GE: return ARM_LE;
4960 case GT: return ARM_LT;
4961 case LE: return ARM_GE;
4962 case LT: return ARM_GT;
4963 case GEU: return ARM_LS;
4964 case GTU: return ARM_CC;
4965 case LEU: return ARM_CS;
4966 case LTU: return ARM_HI;
4967 default: abort ();
4968 }
4969
5165176d 4970 case CCmode:
84ed5e79 4971 switch (comp_code)
5165176d 4972 {
84ed5e79
RE
4973 case NE: return ARM_NE;
4974 case EQ: return ARM_EQ;
4975 case GE: return ARM_GE;
4976 case GT: return ARM_GT;
4977 case LE: return ARM_LE;
4978 case LT: return ARM_LT;
4979 case GEU: return ARM_CS;
4980 case GTU: return ARM_HI;
4981 case LEU: return ARM_LS;
4982 case LTU: return ARM_CC;
5165176d
RE
4983 default: abort ();
4984 }
4985
cce8749e
CH
4986 default: abort ();
4987 }
84ed5e79
RE
4988
4989 abort ();
f3bb6135 4990}
cce8749e
CH
4991
4992
4993void
4994final_prescan_insn (insn, opvec, noperands)
4995 rtx insn;
4996 rtx *opvec;
4997 int noperands;
4998{
4999 /* BODY will hold the body of INSN. */
5000 register rtx body = PATTERN (insn);
5001
5002 /* This will be 1 if trying to repeat the trick, and things need to be
5003 reversed if it appears to fail. */
5004 int reverse = 0;
5005
ff9940b0
RE
5006 /* JUMP_CLOBBERS will be one implies that the conditions if a branch is
5007 taken are clobbered, even if the rtl suggests otherwise. It also
5008 means that we have to grub around within the jump expression to find
5009 out what the conditions are when the jump isn't taken. */
5010 int jump_clobbers = 0;
5011
5012 /* If we start with a return insn, we only succeed if we find another one. */
5013 int seeking_return = 0;
5014
cce8749e
CH
5015 /* START_INSN will hold the insn from where we start looking. This is the
5016 first insn after the following code_label if REVERSE is true. */
5017 rtx start_insn = insn;
5018
5019 /* If in state 4, check if the target branch is reached, in order to
5020 change back to state 0. */
5021 if (arm_ccfsm_state == 4)
5022 {
5023 if (insn == arm_target_insn)
abaa26e5
RE
5024 {
5025 arm_target_insn = NULL;
cce8749e 5026 arm_ccfsm_state = 0;
abaa26e5 5027 }
cce8749e
CH
5028 return;
5029 }
5030
5031 /* If in state 3, it is possible to repeat the trick, if this insn is an
5032 unconditional branch to a label, and immediately following this branch
5033 is the previous target label which is only used once, and the label this
5034 branch jumps to is not too far off. */
5035 if (arm_ccfsm_state == 3)
5036 {
5037 if (simplejump_p (insn))
5038 {
5039 start_insn = next_nonnote_insn (start_insn);
5040 if (GET_CODE (start_insn) == BARRIER)
5041 {
5042 /* XXX Isn't this always a barrier? */
5043 start_insn = next_nonnote_insn (start_insn);
5044 }
5045 if (GET_CODE (start_insn) == CODE_LABEL
5046 && CODE_LABEL_NUMBER (start_insn) == arm_target_label
5047 && LABEL_NUSES (start_insn) == 1)
5048 reverse = TRUE;
5049 else
5050 return;
5051 }
ff9940b0
RE
5052 else if (GET_CODE (body) == RETURN)
5053 {
5054 start_insn = next_nonnote_insn (start_insn);
5055 if (GET_CODE (start_insn) == BARRIER)
5056 start_insn = next_nonnote_insn (start_insn);
5057 if (GET_CODE (start_insn) == CODE_LABEL
5058 && CODE_LABEL_NUMBER (start_insn) == arm_target_label
5059 && LABEL_NUSES (start_insn) == 1)
5060 {
5061 reverse = TRUE;
5062 seeking_return = 1;
5063 }
5064 else
5065 return;
5066 }
cce8749e
CH
5067 else
5068 return;
5069 }
5070
5071 if (arm_ccfsm_state != 0 && !reverse)
5072 abort ();
5073 if (GET_CODE (insn) != JUMP_INSN)
5074 return;
5075
ddd5a7c1 5076 /* This jump might be paralleled with a clobber of the condition codes
ff9940b0
RE
5077 the jump should always come first */
5078 if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
5079 body = XVECEXP (body, 0, 0);
5080
5081#if 0
5082 /* If this is a conditional return then we don't want to know */
5083 if (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
5084 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
5085 && (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN
5086 || GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN))
5087 return;
5088#endif
5089
cce8749e
CH
5090 if (reverse
5091 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
5092 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
5093 {
5094 int insns_skipped = 0, fail = FALSE, succeed = FALSE;
5095 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
5096 int then_not_else = TRUE;
ff9940b0 5097 rtx this_insn = start_insn, label = 0;
cce8749e 5098
ff9940b0 5099 if (get_attr_conds (insn) == CONDS_JUMP_CLOB)
5bbe2d40
RE
5100 {
5101 /* The code below is wrong for these, and I haven't time to
5102 fix it now. So we just do the safe thing and return. This
5103 whole function needs re-writing anyway. */
5104 jump_clobbers = 1;
5105 return;
5106 }
ff9940b0 5107
cce8749e
CH
5108 /* Register the insn jumped to. */
5109 if (reverse)
ff9940b0
RE
5110 {
5111 if (!seeking_return)
5112 label = XEXP (SET_SRC (body), 0);
5113 }
cce8749e
CH
5114 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
5115 label = XEXP (XEXP (SET_SRC (body), 1), 0);
5116 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
5117 {
5118 label = XEXP (XEXP (SET_SRC (body), 2), 0);
5119 then_not_else = FALSE;
5120 }
ff9940b0
RE
5121 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
5122 seeking_return = 1;
5123 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
5124 {
5125 seeking_return = 1;
5126 then_not_else = FALSE;
5127 }
cce8749e
CH
5128 else
5129 abort ();
5130
5131 /* See how many insns this branch skips, and what kind of insns. If all
5132 insns are okay, and the label or unconditional branch to the same
5133 label is not too far away, succeed. */
5134 for (insns_skipped = 0;
5135 !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
5136 insns_skipped++)
5137 {
5138 rtx scanbody;
5139
5140 this_insn = next_nonnote_insn (this_insn);
5141 if (!this_insn)
5142 break;
5143
5144 scanbody = PATTERN (this_insn);
5145
5146 switch (GET_CODE (this_insn))
5147 {
5148 case CODE_LABEL:
5149 /* Succeed if it is the target label, otherwise fail since
5150 control falls in from somewhere else. */
5151 if (this_insn == label)
5152 {
ff9940b0
RE
5153 if (jump_clobbers)
5154 {
5155 arm_ccfsm_state = 2;
5156 this_insn = next_nonnote_insn (this_insn);
5157 }
5158 else
5159 arm_ccfsm_state = 1;
cce8749e
CH
5160 succeed = TRUE;
5161 }
5162 else
5163 fail = TRUE;
5164 break;
5165
ff9940b0 5166 case BARRIER:
cce8749e 5167 /* Succeed if the following insn is the target label.
ff9940b0
RE
5168 Otherwise fail.
5169 If return insns are used then the last insn in a function
5170 will be a barrier. */
cce8749e 5171 this_insn = next_nonnote_insn (this_insn);
ff9940b0 5172 if (this_insn && this_insn == label)
cce8749e 5173 {
ff9940b0
RE
5174 if (jump_clobbers)
5175 {
5176 arm_ccfsm_state = 2;
5177 this_insn = next_nonnote_insn (this_insn);
5178 }
5179 else
5180 arm_ccfsm_state = 1;
cce8749e
CH
5181 succeed = TRUE;
5182 }
5183 else
5184 fail = TRUE;
5185 break;
5186
ff9940b0 5187 case CALL_INSN:
2b835d68
RE
5188 /* If using 32-bit addresses the cc is not preserved over
5189 calls */
5190 if (TARGET_APCS_32)
ff9940b0
RE
5191 fail = TRUE;
5192 break;
2b835d68 5193
cce8749e
CH
5194 case JUMP_INSN:
5195 /* If this is an unconditional branch to the same label, succeed.
5196 If it is to another label, do nothing. If it is conditional,
5197 fail. */
5198 /* XXX Probably, the test for the SET and the PC are unnecessary. */
5199
ff9940b0
RE
5200 if (GET_CODE (scanbody) == SET
5201 && GET_CODE (SET_DEST (scanbody)) == PC)
cce8749e
CH
5202 {
5203 if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
5204 && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
5205 {
5206 arm_ccfsm_state = 2;
5207 succeed = TRUE;
5208 }
5209 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
5210 fail = TRUE;
5211 }
ff9940b0
RE
5212 else if (GET_CODE (scanbody) == RETURN
5213 && seeking_return)
5214 {
5215 arm_ccfsm_state = 2;
5216 succeed = TRUE;
5217 }
5218 else if (GET_CODE (scanbody) == PARALLEL)
5219 {
5220 switch (get_attr_conds (this_insn))
5221 {
5222 case CONDS_NOCOND:
5223 break;
5224 default:
5225 fail = TRUE;
5226 break;
5227 }
5228 }
cce8749e
CH
5229 break;
5230
5231 case INSN:
ff9940b0
RE
5232 /* Instructions using or affecting the condition codes make it
5233 fail. */
5234 if ((GET_CODE (scanbody) == SET
5235 || GET_CODE (scanbody) == PARALLEL)
5236 && get_attr_conds (this_insn) != CONDS_NOCOND)
cce8749e
CH
5237 fail = TRUE;
5238 break;
5239
5240 default:
5241 break;
5242 }
5243 }
5244 if (succeed)
5245 {
ff9940b0 5246 if ((!seeking_return) && (arm_ccfsm_state == 1 || reverse))
cce8749e 5247 arm_target_label = CODE_LABEL_NUMBER (label);
ff9940b0
RE
5248 else if (seeking_return || arm_ccfsm_state == 2)
5249 {
5250 while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
5251 {
5252 this_insn = next_nonnote_insn (this_insn);
5253 if (this_insn && (GET_CODE (this_insn) == BARRIER
5254 || GET_CODE (this_insn) == CODE_LABEL))
5255 abort ();
5256 }
5257 if (!this_insn)
5258 {
5259 /* Oh, dear! we ran off the end.. give up */
5260 recog (PATTERN (insn), insn, NULL_PTR);
5261 arm_ccfsm_state = 0;
abaa26e5 5262 arm_target_insn = NULL;
ff9940b0
RE
5263 return;
5264 }
5265 arm_target_insn = this_insn;
5266 }
cce8749e
CH
5267 else
5268 abort ();
ff9940b0
RE
5269 if (jump_clobbers)
5270 {
5271 if (reverse)
5272 abort ();
5273 arm_current_cc =
5274 get_arm_condition_code (XEXP (XEXP (XEXP (SET_SRC (body),
5275 0), 0), 1));
5276 if (GET_CODE (XEXP (XEXP (SET_SRC (body), 0), 0)) == AND)
5277 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5278 if (GET_CODE (XEXP (SET_SRC (body), 0)) == NE)
5279 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5280 }
5281 else
5282 {
5283 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
5284 what it was. */
5285 if (!reverse)
5286 arm_current_cc = get_arm_condition_code (XEXP (SET_SRC (body),
5287 0));
5288 }
cce8749e 5289
cce8749e
CH
5290 if (reverse || then_not_else)
5291 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5292 }
ff9940b0
RE
5293 /* restore recog_operand (getting the attributes of other insns can
5294 destroy this array, but final.c assumes that it remains intact
ddd5a7c1 5295 across this call; since the insn has been recognized already we
ff9940b0
RE
5296 call recog direct). */
5297 recog (PATTERN (insn), insn, NULL_PTR);
cce8749e 5298 }
f3bb6135 5299}
cce8749e 5300
2b835d68
RE
5301#ifdef AOF_ASSEMBLER
5302/* Special functions only needed when producing AOF syntax assembler. */
5303
5304int arm_text_section_count = 1;
5305
5306char *
84ed5e79 5307aof_text_section ()
2b835d68
RE
5308{
5309 static char buf[100];
2b835d68
RE
5310 sprintf (buf, "\tAREA |C$$code%d|, CODE, READONLY",
5311 arm_text_section_count++);
5312 if (flag_pic)
5313 strcat (buf, ", PIC, REENTRANT");
5314 return buf;
5315}
5316
5317static int arm_data_section_count = 1;
5318
5319char *
5320aof_data_section ()
5321{
5322 static char buf[100];
5323 sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
5324 return buf;
5325}
5326
5327/* The AOF assembler is religiously strict about declarations of
5328 imported and exported symbols, so that it is impossible to declare
5329 a function as imported near the begining of the file, and then to
5330 export it later on. It is, however, possible to delay the decision
5331 until all the functions in the file have been compiled. To get
5332 around this, we maintain a list of the imports and exports, and
5333 delete from it any that are subsequently defined. At the end of
5334 compilation we spit the remainder of the list out before the END
5335 directive. */
5336
5337struct import
5338{
5339 struct import *next;
5340 char *name;
5341};
5342
5343static struct import *imports_list = NULL;
5344
5345void
5346aof_add_import (name)
5347 char *name;
5348{
5349 struct import *new;
5350
5351 for (new = imports_list; new; new = new->next)
5352 if (new->name == name)
5353 return;
5354
5355 new = (struct import *) xmalloc (sizeof (struct import));
5356 new->next = imports_list;
5357 imports_list = new;
5358 new->name = name;
5359}
5360
5361void
5362aof_delete_import (name)
5363 char *name;
5364{
5365 struct import **old;
5366
5367 for (old = &imports_list; *old; old = & (*old)->next)
5368 {
5369 if ((*old)->name == name)
5370 {
5371 *old = (*old)->next;
5372 return;
5373 }
5374 }
5375}
5376
5377int arm_main_function = 0;
5378
5379void
5380aof_dump_imports (f)
5381 FILE *f;
5382{
5383 /* The AOF assembler needs this to cause the startup code to be extracted
5384 from the library. Brining in __main causes the whole thing to work
5385 automagically. */
5386 if (arm_main_function)
5387 {
5388 text_section ();
5389 fputs ("\tIMPORT __main\n", f);
5390 fputs ("\tDCD __main\n", f);
5391 }
5392
5393 /* Now dump the remaining imports. */
5394 while (imports_list)
5395 {
5396 fprintf (f, "\tIMPORT\t");
5397 assemble_name (f, imports_list->name);
5398 fputc ('\n', f);
5399 imports_list = imports_list->next;
5400 }
5401}
5402#endif /* AOF_ASSEMBLER */
This page took 0.841561 seconds and 5 git commands to generate.