Annotation of GNUtools/cc/config/arm/arm.h, revision 1.1

1.1     ! root        1: /* Definitions of target machine for GNU compiler, for Acorn RISC Machine.
        !             2:    Copyright (C) 1991, 1993 Free Software Foundation, Inc.
        !             3:    Contributed by Pieter `Tiggr' Schoenmakers ([email protected])
        !             4:               and Martin Simmons (@harleqn.co.uk).
        !             5:    More major hacks by Richard Earnshaw ([email protected])
        !             6:    
        !             7: This file is part of GNU CC.
        !             8: 
        !             9: GNU CC is free software; you can redistribute it and/or modify
        !            10: it under the terms of the GNU General Public License as published by
        !            11: the Free Software Foundation; either version 2, or (at your option)
        !            12: any later version.
        !            13: 
        !            14: GNU CC is distributed in the hope that it will be useful,
        !            15: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            17: GNU General Public License for more details.
        !            18: 
        !            19: You should have received a copy of the GNU General Public License
        !            20: along with GNU CC; see the file COPYING.  If not, write to
        !            21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            22: 
        !            23: /* Sometimes the directive `riscos' is checked.  This does not imply that this
        !            24:    tm file can be used unchanged to build a GCC for RISC OS.
        !            25:    (Since in fact, it can't.)  */
        !            26: 
        !            27: extern void output_prologue ();
        !            28: extern void output_epilogue ();
        !            29: extern char *arm_output_asm_insn ();
        !            30: extern char *arm_output_llc ();
        !            31: extern char *arithmetic_instr ();
        !            32: extern char *output_add_immediate ();
        !            33: extern char *output_call ();
        !            34: extern char *output_call_mem ();
        !            35: extern char *output_move_double ();
        !            36: extern char *output_mov_double_fpu_from_arm ();
        !            37: extern char *output_mov_double_arm_from_fpu ();
        !            38: extern char *output_mov_long_double_fpu_from_arm ();
        !            39: extern char *output_mov_long_double_arm_from_fpu ();
        !            40: extern char *output_mov_long_double_arm_from_arm ();
        !            41: extern char *output_mov_immediate ();
        !            42: extern char *output_multi_immediate ();
        !            43: extern char *output_shifted_move ();
        !            44: extern char *output_shift_compare ();
        !            45: extern char *output_arithmetic_with_immediate_multiply ();
        !            46: extern char *output_arithmetic_with_shift ();
        !            47: extern char *output_return_instruction ();
        !            48: extern char *output_load_symbol ();
        !            49: extern char *fp_immediate_constant ();
        !            50: extern char *shift_instr ();
        !            51: extern struct rtx_def *gen_compare_reg ();
        !            52: extern struct rtx_def *arm_gen_store_multiple ();
        !            53: extern struct rtx_def *arm_gen_load_multiple ();
        !            54: 
        !            55: extern char *arm_condition_codes[];
        !            56: 
        !            57: /* This is needed by the tail-calling peepholes */
        !            58: extern int frame_pointer_needed;
        !            59: 
        !            60: 
        !            61: #ifndef CPP_PREDEFINES
        !            62: #define CPP_PREDEFINES  "-Darm -Acpu(arm) -Amachine(arm)"
        !            63: #endif
        !            64: 
        !            65: #ifndef CPP_SPEC
        !            66: #define CPP_SPEC "%{m6:-D__arm6__}"
        !            67: #endif
        !            68: 
        !            69: /* Run-time Target Specification.  */
        !            70: #ifndef TARGET_VERSION
        !            71: #define TARGET_VERSION  \
        !            72:   fputs (" (ARM/generic)", stderr);
        !            73: #endif
        !            74: 
        !            75: /* Run-time compilation parameters selecting different hardware subsets.
        !            76:    On the ARM, misuse it in a different way.  */
        !            77: extern int target_flags;
        !            78: 
        !            79: /* Nonzero if the function prologue (and epilogue) should obey
        !            80:    the ARM Procedure Call Standard.  */
        !            81: #define TARGET_APCS    (target_flags & 1)
        !            82: 
        !            83: /* Nonzero if the function prologue should output the function name to enable
        !            84:    the post mortem debugger to print a backtrace (very useful on RISCOS,
        !            85:    unused on RISCiX).  Specifying this flag also enables -mapcs.
        !            86:    XXX Must still be implemented in the prologue.  */
        !            87: #define TARGET_POKE_FUNCTION_NAME      (target_flags & 2)
        !            88: 
        !            89: /* Nonzero if floating point instructions are emulated by the FPE, in which
        !            90:    case instruction scheduling becomes very uninteresting.  */
        !            91: #define TARGET_FPE     (target_flags & 4)
        !            92: 
        !            93: /* Nonzero if destined for an ARM6xx.  Takes out bits that assume restoration
        !            94:    of condition flags when returning from a branch & link (ie. a function) */
        !            95: #define TARGET_6        (target_flags & 8)
        !            96: 
        !            97: /* ARM_EXTRA_TARGET_SWITCHES is used in riscix.h to define some options which
        !            98:    are passed to the preprocessor and the assembler post-processor.  They
        !            99:    aren't needed in the main pass of the compiler, but if we don't define
        !           100:    them in target switches cc1 complains about them.  For the sake of
        !           101:    argument lets allocate bit 31 of target flags for such options. */
        !           102: 
        !           103: #ifndef ARM_EXTRA_TARGET_SWITCHES
        !           104: #define ARM_EXTRA_TARGET_SWITCHES
        !           105: #endif
        !           106: 
        !           107: #define TARGET_SWITCHES  \
        !           108: {                                              \
        !           109:   {"apcs",              1},                    \
        !           110:   {"poke-function-name", 2},                   \
        !           111:   {"fpe",               4},                    \
        !           112:   {"6",                         8},                    \
        !           113:   {"2",                        -8},                    \
        !           114:   {"3",                        -8},                    \
        !           115:   ARM_EXTRA_TARGET_SWITCHES                    \
        !           116:   {"",                  TARGET_DEFAULT }       \
        !           117: }
        !           118: 
        !           119: /* Which processor we are running on.  Currently this is only used to
        !           120:    get the condition code clobbering attribute right when we are running on
        !           121:    an arm 6 */
        !           122: 
        !           123: enum processor_type 
        !           124: {
        !           125:   PROCESSOR_ARM2,
        !           126:   PROCESSOR_ARM3,
        !           127:   PROCESSOR_ARM6
        !           128: };
        !           129: 
        !           130: /* Recast the cpu class to be the cpu attribute. */
        !           131: 
        !           132: /* Recast the cpu class to be the cpu attribute.  */
        !           133: #define arm_cpu_attr ((enum attr_cpu)arm_cpu)
        !           134: 
        !           135: extern enum processor_type arm_cpu;
        !           136: 
        !           137: #define TARGET_DEFAULT  0
        !           138: 
        !           139: #define TARGET_MEM_FUNCTIONS 1
        !           140: 
        !           141: /* OVERRIDE_OPTIONS takes care of the following:
        !           142:    - if -mpoke-function-name, then -mapcs.
        !           143:    - if doing debugging, then -mapcs; if RISCOS, then -mpoke-function-name.
        !           144:    - if floating point is done by emulation, forget about instruction
        !           145:      scheduling.  Note that this only saves compilation time; it doesn't
        !           146:      matter for the final code.  */
        !           147: #ifndef TARGET_WHEN_DEBUGGING
        !           148: #define TARGET_WHEN_DEBUGGING  1
        !           149: #endif
        !           150: 
        !           151: #define OVERRIDE_OPTIONS  \
        !           152: {                                                              \
        !           153:   if (write_symbols != NO_DEBUG && flag_omit_frame_pointer)    \
        !           154:     warning ("-g without a frame pointer may not give sensible debugging");\
        !           155:   if (TARGET_POKE_FUNCTION_NAME)                               \
        !           156:     target_flags |= 1;                                         \
        !           157:   if (TARGET_FPE)                                              \
        !           158:     flag_schedule_insns = flag_schedule_insns_after_reload = 0;        \
        !           159:   arm_cpu = TARGET_6 ? PROCESSOR_ARM6: PROCESSOR_ARM2;         \
        !           160: }
        !           161: 
        !           162: /* Omitting the frame pointer is a very good idea on the ARM, especially if
        !           163:    not TARGET_APCS, in which case all that pushing on function entry isn't
        !           164:    mandatory anymore.  Unfortunately this is not permitted since we mustn't
        !           165:    change the flags when -g is enabled and without a frame pointer debugging
        !           166:    using dbx is impossible.
        !           167:    Forcing loads to be explicit allows cse to work better */
        !           168: 
        !           169: #define OPTIMIZATION_OPTIONS(OPTIMIZE)  \
        !           170: {                                      \
        !           171:   if (OPTIMIZE)                                \
        !           172:     flag_force_mem = 1;                        \
        !           173: }
        !           174: 
        !           175: /* Target machine storage Layout.  */
        !           176: 
        !           177: 
        !           178: /* Define this macro if it is advisable to hold scalars in registers
        !           179:    in a wider mode than that declared by the program.  In such cases,
        !           180:    the value is constrained to be within the bounds of the declared
        !           181:    type, but kept valid in the wider mode.  The signedness of the
        !           182:    extension may differ from that of the type.  */
        !           183: 
        !           184: /* It is far faster to zero extend chars than to sign extend them */
        !           185: 
        !           186: #define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE)  \
        !           187:   if (GET_MODE_CLASS (MODE) == MODE_INT \
        !           188:       && GET_MODE_SIZE (MODE) < 4)      \
        !           189:     {                                  \
        !           190:       if (MODE == QImode)              \
        !           191:        UNSIGNEDP = 1;                  \
        !           192:       (MODE) = SImode;                 \
        !           193:     }
        !           194: 
        !           195: /* Define for XFmode extended real floating point support.
        !           196:    This will automatically cause REAL_ARITHMETIC to be defined.  */
        !           197: /* For the ARM:
        !           198:    I think I have added all the code to make this work.  Unfortunately,
        !           199:    early releases of the floating point emulation code on RISCiX used a
        !           200:    different format for extended precision numbers.  On my RISCiX box there
        !           201:    is a bug somewhere which causes the machine to lock up when running enquire
        !           202:    with long doubles.  There is the additional aspect that Norcroft C
        !           203:    treats long doubles as doubles and we ought to remain compatible.
        !           204:    Perhaps someone with an FPA coprocessor and not running RISCiX would like
        !           205:    to try this someday. */
        !           206: /* #define LONG_DOUBLE_TYPE_SIZE 96 */
        !           207: 
        !           208: /* Disable XFmode patterns in md file */
        !           209: #define ENABLE_XF_PATTERNS 0
        !           210: 
        !           211: /* Define if you don't want extended real, but do want to use the
        !           212:    software floating point emulator for REAL_ARITHMETIC and
        !           213:    decimal <-> binary conversion. */
        !           214: /* See comment above */
        !           215: #define REAL_ARITHMETIC
        !           216: 
        !           217: /* Define this if most significant bit is lowest numbered
        !           218:    in instructions that operate on numbered bit-fields.  */
        !           219: #define BITS_BIG_ENDIAN  0
        !           220: 
        !           221: /* Define this if most significant byte of a word is the lowest numbered.  */
        !           222: #define BYTES_BIG_ENDIAN  0
        !           223: 
        !           224: /* Define this if most significant word of a multiword number is the lowest
        !           225:    numbered.  */
        !           226: #define WORDS_BIG_ENDIAN  0
        !           227: 
        !           228: /* Define this if most significant word of doubles is the lowest numbered */
        !           229: #define FLOAT_WORDS_BIG_ENDIAN 1
        !           230: 
        !           231: /* Number of bits in an addressable storage unit */
        !           232: #define BITS_PER_UNIT  8
        !           233: 
        !           234: #define BITS_PER_WORD  32
        !           235: 
        !           236: #define UNITS_PER_WORD 4
        !           237: 
        !           238: #define POINTER_SIZE  32
        !           239: 
        !           240: #define PARM_BOUNDARY          32
        !           241: 
        !           242: #define STACK_BOUNDARY  32
        !           243: 
        !           244: #define FUNCTION_BOUNDARY  32
        !           245: 
        !           246: #define EMPTY_FIELD_BOUNDARY  32
        !           247: 
        !           248: #define BIGGEST_ALIGNMENT  32
        !           249: 
        !           250: /* Make strings word-aligned so strcpy from constants will be faster.  */
        !           251: #define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
        !           252:   (TREE_CODE (EXP) == STRING_CST        \
        !           253:    && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
        !           254: 
        !           255: /* Every structures size must be a multiple of 32 bits.  */
        !           256: #define STRUCTURE_SIZE_BOUNDARY 32
        !           257: 
        !           258: /* Non-zero if move instructions will actually fail to work
        !           259:    when given unaligned data.  */
        !           260: #define STRICT_ALIGNMENT 1
        !           261: 
        !           262: #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
        !           263: 
        !           264: /* Define number of bits in most basic integer type.
        !           265:    (If undefined, default is BITS_PER_WORD).  */
        !           266: /* #define INT_TYPE_SIZE */
        !           267: 
        !           268: /* Standard register usage.  */
        !           269: 
        !           270: /* Register allocation in ARM Procedure Call Standard (as used on RISCiX):
        !           271:    (S - saved over call).
        !           272: 
        !           273:        r0         *    argument word/integer result
        !           274:        r1-r3           argument word
        !           275: 
        !           276:        r4-r8        S  register variable
        !           277:        r9           S  (rfp) register variable (real frame pointer)
        !           278: 
        !           279:        r10        F S  (sl) stack limit (not currently used)
        !           280:        r11        F S  (fp) argument pointer
        !           281:        r12             (ip) temp workspace
        !           282:        r13        F S  (sp) lower end of current stack frame
        !           283:        r14             (lr) link address/workspace
        !           284:        r15        F    (pc) program counter
        !           285: 
        !           286:        f0              floating point result
        !           287:        f1-f3           floating point scratch
        !           288: 
        !           289:        f4-f7        S  floating point variable
        !           290: 
        !           291:        cc              This is NOT a real register, but is used internally
        !           292:                        to represent things that use or set the condition
        !           293:                        codes.
        !           294:        sfp             This isn't either.  It is used during rtl generation
        !           295:                        since the offset between the frame pointer and the
        !           296:                        auto's isn't known until after register allocation.
        !           297:        afp             Nor this, we only need this because of non-local
        !           298:                        goto.  Without it fp appears to be used and the
        !           299:                        elimination code won't get rid of sfp.  It tracks
        !           300:                        fp exactly at all times.
        !           301: 
        !           302:    *: See CONDITIONAL_REGISTER_USAGE  */
        !           303: 
        !           304: /* The stack backtrace structure is as follows:
        !           305:   fp points to here:  |  save code pointer  |      [fp]
        !           306:                       |  return link value  |      [fp, #-4]
        !           307:                       |  return sp value    |      [fp, #-8]
        !           308:                       |  return fp value    |      [fp, #-12]
        !           309:                      [|  saved r10 value    |]
        !           310:                      [|  saved r9 value     |]
        !           311:                      [|  saved r8 value     |]
        !           312:                      [|  saved r7 value     |]
        !           313:                      [|  saved r6 value     |]
        !           314:                      [|  saved r5 value     |]
        !           315:                      [|  saved r4 value     |]
        !           316:                      [|  saved r3 value     |]
        !           317:                      [|  saved r2 value     |]
        !           318:                      [|  saved r1 value     |]
        !           319:                      [|  saved r0 value     |]
        !           320:                      [|  saved f7 value     |]     three words
        !           321:                      [|  saved f6 value     |]     three words
        !           322:                      [|  saved f5 value     |]     three words
        !           323:                      [|  saved f4 value     |]     three words
        !           324:   r0-r3 are not normally saved in a C function.  */
        !           325: 
        !           326: /* The number of hard registers is 16 ARM + 8 FPU + 1 CC + 1 SFP.  */
        !           327: #define FIRST_PSEUDO_REGISTER  27
        !           328: 
        !           329: /* 1 for registers that have pervasive standard uses
        !           330:    and are not available for the register allocator.  */
        !           331: #define FIXED_REGISTERS  \
        !           332: {                        \
        !           333:   0,0,0,0,0,0,0,0,      \
        !           334:   0,0,1,1,0,1,0,1,      \
        !           335:   0,0,0,0,0,0,0,0,      \
        !           336:   1,1,1                         \
        !           337: }
        !           338: 
        !           339: /* 1 for registers not available across function calls.
        !           340:    These must include the FIXED_REGISTERS and also any
        !           341:    registers that can be used without being saved.
        !           342:    The latter must include the registers where values are returned
        !           343:    and the register where structure-value addresses are passed.
        !           344:    Aside from that, you can include as many other registers as you like.
        !           345:    The CC is not preserved over function calls on the ARM 6, so it is 
        !           346:    easier to assume this for all.  SFP is preserved, since FP is. */
        !           347: #define CALL_USED_REGISTERS  \
        !           348: {                            \
        !           349:   1,1,1,1,0,0,0,0,          \
        !           350:   0,0,1,1,1,1,1,1,          \
        !           351:   1,1,1,1,0,0,0,0,          \
        !           352:   1,1,1                             \
        !           353: }
        !           354: 
        !           355: /* If doing stupid life analysis, avoid a bug causing a return value r0 to be
        !           356:    trampled.  This effectively reduces the number of available registers by 1.
        !           357:    XXX It is a hack, I know.
        !           358:    XXX Is this still needed?  */
        !           359: #define CONDITIONAL_REGISTER_USAGE  \
        !           360: {                      \
        !           361:   if (obey_regdecls)   \
        !           362:     fixed_regs[0] = 1; \
        !           363: }
        !           364: 
        !           365: /* Return number of consecutive hard regs needed starting at reg REGNO
        !           366:    to hold something of mode MODE.
        !           367:    This is ordinarily the length in words of a value of mode MODE
        !           368:    but can be less for certain modes in special long registers.
        !           369: 
        !           370:    On the ARM regs are UNITS_PER_WORD bits wide; FPU regs can hold any FP
        !           371:    mode.  */
        !           372: #define HARD_REGNO_NREGS(REGNO, MODE)                                          \
        !           373:     (((REGNO) >= 16 && REGNO != FRAME_POINTER_REGNUM                   \
        !           374:       && (REGNO) != ARG_POINTER_REGNUM) ? 1                            \
        !           375:      : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
        !           376: 
        !           377: /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
        !           378:    This is TRUE for ARM regs since they can hold anything, and TRUE for FPU
        !           379:    regs holding FP.  */
        !           380: #define HARD_REGNO_MODE_OK(REGNO, MODE)                        \
        !           381:   ((GET_MODE_CLASS (MODE) == MODE_CC) ? (REGNO == CC_REGNUM) : \
        !           382:   ((REGNO) < 16 || REGNO == FRAME_POINTER_REGNUM               \
        !           383:    || REGNO == ARG_POINTER_REGNUM                              \
        !           384:    || GET_MODE_CLASS (MODE) == MODE_FLOAT))
        !           385: 
        !           386: /* Value is 1 if it is a good idea to tie two pseudo registers
        !           387:    when one has mode MODE1 and one has mode MODE2.
        !           388:    If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
        !           389:    for any hard reg, then this must be 0 for correct output.  */
        !           390: #define MODES_TIEABLE_P(MODE1, MODE2)  \
        !           391:   (((MODE1) == SFmode || (MODE1) == DFmode)      \
        !           392:    == ((MODE2) == SFmode || (MODE2) == DFmode))
        !           393: 
        !           394: /* Specify the registers used for certain standard purposes.
        !           395:    The values of these macros are register numbers.  */
        !           396: 
        !           397: /* Define this if the program counter is overloaded on a register.  */
        !           398: #define PC_REGNUM              15
        !           399: 
        !           400: /* Register to use for pushing function arguments.  */
        !           401: #define STACK_POINTER_REGNUM   13
        !           402: 
        !           403: /* Base register for access to local variables of the function.  */
        !           404: #define FRAME_POINTER_REGNUM   25
        !           405: 
        !           406: /* Define this to be where the real frame pointer is if it is not possible to
        !           407:    work out the offset between the frame pointer and the automatic variables
        !           408:    until after register allocation has taken place.  FRAME_POINTER_REGNUM
        !           409:    should point to a special register that we will make sure is eliminated. */
        !           410: #define HARD_FRAME_POINTER_REGNUM 11
        !           411: 
        !           412: /* Value should be nonzero if functions must have frame pointers.
        !           413:    Zero means the frame pointer need not be set up (and parms may be accessed
        !           414:    via the stack pointer) in functions that seem suitable.  
        !           415:    If we have to have a frame pointer we might as well make use of it.
        !           416:    APCS says that the frame pointer does not need to be pushed in leaf
        !           417:    functions.  */
        !           418: #define FRAME_POINTER_REQUIRED (TARGET_APCS && !leaf_function_p ())
        !           419: 
        !           420: /* Base register for access to arguments of the function.  */
        !           421: #define ARG_POINTER_REGNUM     26
        !           422: 
        !           423: /* The native (Norcroft) Pascal compiler for the ARM passes the static chain
        !           424:    as an invisible last argument (possible since varargs don't exist in
        !           425:    Pascal), so the following is not true.  */
        !           426: #define STATIC_CHAIN_REGNUM    8
        !           427: 
        !           428: /* Register in which address to store a structure value
        !           429:    is passed to a function.  */
        !           430: #define STRUCT_VALUE_REGNUM    0
        !           431: 
        !           432: /* Internal, so that we don't need to refer to a raw number */
        !           433: #define CC_REGNUM              24
        !           434: 
        !           435: /* The order in which register should be allocated.  It is good to use ip
        !           436:    since no saving is required (though calls clobber it) and it never contains
        !           437:    function parameters.  It is quite good to use lr since other calls may
        !           438:    clobber it anyway.  Allocate r0 through r3 in reverse order since r3 is 
        !           439:    least likely to contain a function parameter; in addition results are
        !           440:    returned in r0.
        !           441:    */
        !           442: #define REG_ALLOC_ORDER  \
        !           443: {                                   \
        !           444:     3, 2, 1, 0, 12, 14,        4, 5,       \
        !           445:     6, 7, 8, 10, 9, 11, 13, 15,     \
        !           446:     16, 17, 18, 19, 20, 21, 22, 23, \
        !           447:     24, 25                         \
        !           448: }
        !           449: 
        !           450: /* Register and constant classes.  */
        !           451: 
        !           452: /* Register classes: all ARM regs or all FPU regs---simple! */
        !           453: enum reg_class
        !           454: {
        !           455:   NO_REGS,
        !           456:   FPU_REGS,
        !           457:   GENERAL_REGS,
        !           458:   ALL_REGS,
        !           459:   LIM_REG_CLASSES
        !           460: };
        !           461: 
        !           462: #define N_REG_CLASSES  (int) LIM_REG_CLASSES
        !           463: 
        !           464: /* Give names of register classes as strings for dump file.   */
        !           465: #define REG_CLASS_NAMES  \
        !           466: {                      \
        !           467:   "NO_REGS",           \
        !           468:   "FPU_REGS",          \
        !           469:   "GENERAL_REGS",      \
        !           470:   "ALL_REGS",          \
        !           471: }
        !           472: 
        !           473: /* Define which registers fit in which classes.
        !           474:    This is an initializer for a vector of HARD_REG_SET
        !           475:    of length N_REG_CLASSES.  */
        !           476: #define REG_CLASS_CONTENTS  \
        !           477: {                              \
        !           478:   0x0000000, /* NO_REGS  */    \
        !           479:   0x0FF0000, /* FPU_REGS */    \
        !           480:   0x200FFFF, /* GENERAL_REGS */        \
        !           481:   0x2FFFFFF  /* ALL_REGS */    \
        !           482: }
        !           483: 
        !           484: /* The same information, inverted:
        !           485:    Return the class number of the smallest class containing
        !           486:    reg number REGNO.  This could be a conditional expression
        !           487:    or could index an array.  */
        !           488: #define REGNO_REG_CLASS(REGNO)                         \
        !           489:   (((REGNO) < 16 || REGNO == FRAME_POINTER_REGNUM      \
        !           490:     || REGNO == ARG_POINTER_REGNUM)                    \
        !           491:    ? GENERAL_REGS : (REGNO) == CC_REGNUM               \
        !           492:    ? NO_REGS : FPU_REGS)
        !           493: 
        !           494: /* The class value for index registers, and the one for base regs.  */
        !           495: #define INDEX_REG_CLASS  GENERAL_REGS
        !           496: #define BASE_REG_CLASS GENERAL_REGS
        !           497: 
        !           498: /* Get reg_class from a letter such as appears in the machine description.
        !           499:    We only need constraint `f' for FPU_REGS (`r' == GENERAL_REGS).  */
        !           500: #define REG_CLASS_FROM_LETTER(C)  \
        !           501:   ((C)=='f' ? FPU_REGS : NO_REGS)
        !           502: 
        !           503: /* The letters I, J, K, L and M in a register constraint string
        !           504:    can be used to stand for particular ranges of immediate operands.
        !           505:    This macro defines what the ranges are.
        !           506:    C is the letter, and VALUE is a constant value.
        !           507:    Return 1 if VALUE is in the range specified by C.
        !           508:        I: immediate arithmetic operand (i.e. 8 bits shifted as required).
        !           509:        J: valid indexing constants.  
        !           510:        K: as I but also (not (value)) ok.
        !           511:        L: as I but also (neg (value)) ok.*/
        !           512: #define CONST_OK_FOR_LETTER_P(VALUE, C)                                      \
        !           513:   ((C) == 'I' ? const_ok_for_arm (VALUE) :                                   \
        !           514:    (C) == 'J' ? ((VALUE) < 4096 && (VALUE) > -4096) :                        \
        !           515:    (C) == 'K' ? (const_ok_for_arm (VALUE) || const_ok_for_arm (~(VALUE))) :   \
        !           516:    (C) == 'L' ? (const_ok_for_arm (VALUE) || const_ok_for_arm (-(VALUE))) : 0)
        !           517: 
        !           518: /* For the ARM, `Q' means that this is a memory operand that is just
        !           519:    an offset from a register.  
        !           520:    `S' means any symbol that has the SYMBOL_REF_FLAG set or a CONSTANT_POOL
        !           521:    address.  This means that the symbol is in the text segment and can be
        !           522:    accessed without using a load. */
        !           523: 
        !           524: #define EXTRA_CONSTRAINT(OP, C)                                         \
        !           525:   ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG  \
        !           526:    : (C) == 'S' ? CONSTANT_ADDRESS_P (OP) : 0)
        !           527: 
        !           528: /* Constant letter 'G' for the FPU immediate constants. 
        !           529:    'H' means the same constant negated.  */
        !           530: #define CONST_DOUBLE_OK_FOR_LETTER_P(X,C)                      \
        !           531:     ((C) == 'G' ? const_double_rtx_ok_for_fpu (X)              \
        !           532:      : (C) == 'H' ? neg_const_double_rtx_ok_for_fpu (X) : 0)
        !           533: 
        !           534: /* Given an rtx X being reloaded into a reg required to be
        !           535:    in class CLASS, return the class of reg to actually use.
        !           536:    In general this is just CLASS; but on some machines
        !           537:    in some cases it is preferable to use a more restrictive class.  */
        !           538: #define PREFERRED_RELOAD_CLASS(X, CLASS)  (CLASS)
        !           539: 
        !           540: /* Return the register class of a scratch register needed to copy IN into
        !           541:    or out of a register in CLASS in MODE.  If it can be done directly,
        !           542:    NO_REGS is returned.  */
        !           543: #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X)    \
        !           544:   (((MODE) == DFmode && (CLASS) == GENERAL_REGS                \
        !           545:     && true_regnum (X) == -1) ? GENERAL_REGS           \
        !           546:    : ((MODE) == HImode && true_regnum (X) == -1) ? GENERAL_REGS : NO_REGS)
        !           547: 
        !           548: /* Return the maximum number of consecutive registers
        !           549:    needed to represent mode MODE in a register of class CLASS.
        !           550:    ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */
        !           551: #define CLASS_MAX_NREGS(CLASS, MODE)  \
        !           552:     ((CLASS) == FPU_REGS ? 1                                          \
        !           553:      : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
        !           554: 
        !           555: /* Moves between FPU_REGS and GENERAL_REGS are two memory insns.  */
        !           556: #define REGISTER_MOVE_COST(CLASS1, CLASS2)  \
        !           557:   ((((CLASS1) == FPU_REGS && (CLASS2) != FPU_REGS)     \
        !           558:     || ((CLASS2) == FPU_REGS && (CLASS1) != FPU_REGS)) \
        !           559:    ? 20 : 2)
        !           560: 
        !           561: /* Stack layout; function entry, exit and calling.  */
        !           562: 
        !           563: /* Define this if pushing a word on the stack
        !           564:    makes the stack pointer a smaller address.  */
        !           565: #define STACK_GROWS_DOWNWARD  1
        !           566: 
        !           567: /* Define this if the nominal address of the stack frame
        !           568:    is at the high-address end of the local variables;
        !           569:    that is, each additional local variable allocated
        !           570:    goes at a more negative offset in the frame.  */
        !           571: #define FRAME_GROWS_DOWNWARD 1
        !           572: 
        !           573: /* Offset within stack frame to start allocating local variables at.
        !           574:    If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
        !           575:    first local allocated.  Otherwise, it is the offset to the BEGINNING
        !           576:    of the first local allocated.  */
        !           577: #define STARTING_FRAME_OFFSET  0
        !           578: 
        !           579: /* If we generate an insn to push BYTES bytes,
        !           580:    this says how many the stack pointer really advances by.  */
        !           581: #define PUSH_ROUNDING(NPUSHED)  (((NPUSHED) + 3) & ~3)
        !           582: 
        !           583: /* Offset of first parameter from the argument pointer register value.  */
        !           584: #define FIRST_PARM_OFFSET(FNDECL)  4
        !           585: 
        !           586: /* Value is the number of byte of arguments automatically
        !           587:    popped when returning from a subroutine call.
        !           588:    FUNTYPE is the data type of the function (as a tree),
        !           589:    or for a library call it is an identifier node for the subroutine name.
        !           590:    SIZE is the number of bytes of arguments passed on the stack.
        !           591: 
        !           592:    On the ARM, the caller does not pop any of its arguments that were passed
        !           593:    on the stack.  */
        !           594: #define RETURN_POPS_ARGS(FUNTYPE, SIZE)  0
        !           595: 
        !           596: /* Define how to find the value returned by a function.
        !           597:    VALTYPE is the data type of the value (as a tree).
        !           598:    If the precise function being called is known, FUNC is its FUNCTION_DECL;
        !           599:    otherwise, FUNC is 0.  */
        !           600: #define FUNCTION_VALUE(VALTYPE, FUNC)  \
        !           601:   (GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT  \
        !           602:    ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16)            \
        !           603:    : gen_rtx (REG, TYPE_MODE (VALTYPE), 0))
        !           604: 
        !           605: /* Define how to find the value returned by a library function
        !           606:    assuming the value has mode MODE.  */
        !           607: #define LIBCALL_VALUE(MODE)  \
        !           608:   (GET_MODE_CLASS (MODE) == MODE_FLOAT  \
        !           609:    ? gen_rtx (REG, MODE, 16)           \
        !           610:    : gen_rtx (REG, MODE, 0))
        !           611: 
        !           612: /* 1 if N is a possible register number for a function value.
        !           613:    On the ARM, only r0 and f0 can return results.  */
        !           614: #define FUNCTION_VALUE_REGNO_P(REGNO)  \
        !           615:   ((REGNO) == 0 || (REGNO) == 16)
        !           616: 
        !           617: /* Define where to put the arguments to a function.
        !           618:    Value is zero to push the argument on the stack,
        !           619:    or a hard register in which to store the argument.
        !           620: 
        !           621:    MODE is the argument's machine mode.
        !           622:    TYPE is the data type of the argument (as a tree).
        !           623:     This is null for libcalls where that information may
        !           624:     not be available.
        !           625:    CUM is a variable of type CUMULATIVE_ARGS which gives info about
        !           626:     the preceding args and about the function being called.
        !           627:    NAMED is nonzero if this argument is a named parameter
        !           628:     (otherwise it is an extra parameter matching an ellipsis).
        !           629: 
        !           630:    On the ARM, normally the first 16 bytes are passed in registers r0-r3; all
        !           631:    other arguments are passed on the stack.  If (NAMED == 0) (which happens
        !           632:    only in assign_parms, since SETUP_INCOMING_VARARGS is defined), say it is
        !           633:    passed in the stack (function_prologue will indeed make it pass in the
        !           634:    stack if necessary).  */
        !           635: #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)  \
        !           636:   ((NAMED)                                             \
        !           637:    ? ((CUM) >= 16 ? 0 : gen_rtx (REG, MODE, (CUM) / 4))        \
        !           638:    : 0)
        !           639: 
        !           640: /* For an arg passed partly in registers and partly in memory,
        !           641:    this is the number of registers used.
        !           642:    For args passed entirely in registers or entirely in memory, zero.  */
        !           643: #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED)  \
        !           644:   ((CUM) < 16 && 16 < (CUM) + ((MODE) != BLKmode            \
        !           645:                               ? GET_MODE_SIZE (MODE)       \
        !           646:                               : int_size_in_bytes (TYPE))  \
        !           647:    ? 4 - (CUM) / 4 : 0)
        !           648: 
        !           649: /* A C type for declaring a variable that is used as the first argument of
        !           650:    `FUNCTION_ARG' and other related values.  For some target machines, the
        !           651:    type `int' suffices and can hold the number of bytes of argument so far.
        !           652: 
        !           653:    On the ARM, this is the number of bytes of arguments scanned so far.  */
        !           654: #define CUMULATIVE_ARGS  int
        !           655: 
        !           656: /* Initialize a variable CUM of type CUMULATIVE_ARGS
        !           657:    for a call to a function whose data type is FNTYPE.
        !           658:    For a library call, FNTYPE is 0.
        !           659:    On the ARM, the offset starts at 0.  */
        !           660: #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME)  \
        !           661:   ((CUM) = (((FNTYPE) && aggregate_value_p (TREE_TYPE ((FNTYPE)))) ? 4 : 0))
        !           662: 
        !           663: /* Update the data in CUM to advance over an argument
        !           664:    of mode MODE and data type TYPE.
        !           665:    (TYPE is null for libcalls where that information may not be available.)  */
        !           666: #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)  \
        !           667:   (CUM) += ((MODE) != BLKmode                       \
        !           668:            ? (GET_MODE_SIZE (MODE) + 3) & ~3       \
        !           669:            : (int_size_in_bytes (TYPE) + 3) & ~3)  \
        !           670: 
        !           671: /* 1 if N is a possible register number for function argument passing.
        !           672:    On the ARM, r0-r3 are used to pass args.  */
        !           673: #define FUNCTION_ARG_REGNO_P(REGNO)  \
        !           674:   ((REGNO) >= 0 && (REGNO) <= 3)
        !           675: 
        !           676: /* Perform any actions needed for a function that is receiving a variable
        !           677:    number of arguments.  CUM is as above.  MODE and TYPE are the mode and type
        !           678:    of the current parameter.  PRETEND_SIZE is a variable that should be set to
        !           679:    the amount of stack that must be pushed by the prolog to pretend that our
        !           680:    caller pushed it.
        !           681: 
        !           682:    Normally, this macro will push all remaining incoming registers on the
        !           683:    stack and set PRETEND_SIZE to the length of the registers pushed.
        !           684: 
        !           685:    On the ARM, PRETEND_SIZE is set in order to have the prologue push the last
        !           686:    named arg and all anonymous args onto the stack.
        !           687:    XXX I know the prologue shouldn't be pushing registers, but it is faster
        !           688:    that way.  */
        !           689: #define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PRETEND_SIZE, NO_RTL)  \
        !           690: {                                                                      \
        !           691:   extern int current_function_anonymous_args;                          \
        !           692:   current_function_anonymous_args = 1;                                 \
        !           693:   if ((CUM) < 16)                                                      \
        !           694:     (PRETEND_SIZE) = 16 - (CUM);                                       \
        !           695: }
        !           696: 
        !           697: /* Generate assembly output for the start of a function.  */
        !           698: #define FUNCTION_PROLOGUE(STREAM, SIZE)  \
        !           699:   output_prologue ((STREAM), (SIZE))
        !           700: 
        !           701: /* Call the function profiler with a given profile label.  The Acorn compiler
        !           702:    puts this BEFORE the prolog but gcc pust it afterwards.  The ``mov ip,lr''
        !           703:    seems like a good idea to stick with cc convention.  ``prof'' doesn't seem
        !           704:    to mind about this!  */
        !           705: #define FUNCTION_PROFILER(STREAM,LABELNO)  \
        !           706: {                                                      \
        !           707:     fprintf(STREAM, "\tmov\tip, lr\n");                        \
        !           708:     fprintf(STREAM, "\tbl\tmcount\n");                 \
        !           709:     fprintf(STREAM, "\t.word\tLP%d\n", (LABELNO));     \
        !           710:     arm_increase_location (12);                                \
        !           711: }
        !           712: 
        !           713: /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
        !           714:    the stack pointer does not matter.  The value is tested only in
        !           715:    functions that have frame pointers.
        !           716:    No definition is equivalent to always zero.
        !           717: 
        !           718:    On the ARM, the function epilogue recovers the stack pointer from the
        !           719:    frame.  */
        !           720: #define EXIT_IGNORE_STACK 1
        !           721: 
        !           722: /* Generate the assembly code for function exit. */
        !           723: #define FUNCTION_EPILOGUE(STREAM, SIZE)  \
        !           724:   output_epilogue ((STREAM), (SIZE))
        !           725: 
        !           726: /* Determine if the epilogue should be output as RTL.
        !           727:    You should override this if you define FUNCTION_EXTRA_EPILOGUE.  */
        !           728: #define USE_RETURN_INSN use_return_insn ()
        !           729: 
        !           730: /* Definitions for register eliminations.
        !           731: 
        !           732:    This is an array of structures.  Each structure initializes one pair
        !           733:    of eliminable registers.  The "from" register number is given first,
        !           734:    followed by "to".  Eliminations of the same "from" register are listed
        !           735:    in order of preference.
        !           736: 
        !           737:    We have two registers that can be eliminated on the ARM.  First, the
        !           738:    arg pointer register can often be eliminated in favor of the stack
        !           739:    pointer register.  Secondly, the pseudo frame pointer register can always
        !           740:    be eliminated; it is replaced with either the stack or the real frame
        !           741:    pointer. */
        !           742: 
        !           743: #define ELIMINABLE_REGS                                        \
        !           744: {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},           \
        !           745:  {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},      \
        !           746:  {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},         \
        !           747:  {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
        !           748: 
        !           749: /* Given FROM and TO register numbers, say whether this elimination is allowed.
        !           750:    Frame pointer elimination is automatically handled.
        !           751: 
        !           752:    All eliminations are permissible.  Note that ARG_POINTER_REGNUM and
        !           753:    HARD_FRAME_POINTER_REGNUM are infact the same thing.  If we need a frame
        !           754:    pointer, we must eliminate FRAME_POINTER_REGNUM into
        !           755:    HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM.  */
        !           756: #define CAN_ELIMINATE(FROM, TO)                \
        !           757:   (((TO) == STACK_POINTER_REGNUM && frame_pointer_needed) ? 0 : 1)
        !           758: 
        !           759: /* Define the offset between two registers, one to be eliminated, and the other
        !           760:    its replacement, at the start of a routine.  */
        !           761: #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
        !           762: {                                                                      \
        !           763:   if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\
        !           764:     (OFFSET) = 0;                                                      \
        !           765:   else if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)\
        !           766:     (OFFSET) = (get_frame_size () + 3 & ~3);                           \
        !           767:   else                                                                 \
        !           768:     {                                                                  \
        !           769:       int regno;                                                       \
        !           770:       int offset = 12;                                                 \
        !           771:                                                                        \
        !           772:       for (regno = 4; regno <= 10; regno++)                            \
        !           773:        if (regs_ever_live[regno])                                      \
        !           774:          offset += 4;                                                  \
        !           775:       for (regno = 20; regno <=23; regno++)                            \
        !           776:        if (regs_ever_live[regno])                                      \
        !           777:          offset += 12;                                                 \
        !           778:       if ((FROM) == FRAME_POINTER_REGNUM)                              \
        !           779:        (OFFSET) = -offset;                                             \
        !           780:       else                                                             \
        !           781:        {                                                               \
        !           782:           if (! regs_ever_live[HARD_FRAME_POINTER_REGNUM])             \
        !           783:             offset -= 16;                                              \
        !           784:           if (regs_ever_live[14])                                      \
        !           785:             offset += 4;                                               \
        !           786:           (OFFSET) = (get_frame_size () + 3 & ~3) + offset;            \
        !           787:          }                                                             \
        !           788:     }                                                                  \
        !           789: }
        !           790: 
        !           791: #if 0
        !           792: /* Store in the variable DEPTH the initial difference between the frame
        !           793:    pointer reg contents and the stack pointer reg contents, as of the start of
        !           794:    the function body.  This depends on the layout of the fixed parts of the
        !           795:    stack frame and on how registers are saved.  */
        !           796: #define INITIAL_FRAME_POINTER_OFFSET(DEPTH)                    \
        !           797: {                                                              \
        !           798:   int regno;                                                   \
        !           799:   int offset = 12;                                             \
        !           800:                                                                \
        !           801:   for (regno = 0; regno < FRAME_POINTER_REGNUM; regno++)       \
        !           802:     if (regs_ever_live[regno])                                 \
        !           803:       offset += 4;                                             \
        !           804:   for (regno = 20; regno < 24; regno++)                                \
        !           805:     if (regs_ever_live[regno])                                 \
        !           806:       offset += 12;                                            \
        !           807:   (DEPTH) = offset + (get_frame_size () + 3 & ~3);             \
        !           808: }
        !           809: 
        !           810: #define INITIAL_FRAME_POINTER_OFFSET(DEPTH)  \
        !           811:   (DEPTH) = (get_frame_size () + 3) & ~3;
        !           812: #endif
        !           813: /* Output assembler code for a block containing the constant parts
        !           814:    of a trampoline, leaving space for the variable parts.
        !           815: 
        !           816:    On the ARM, (if r8 is the static chain regnum, and remembering that
        !           817:    referencing pc adds an offset of 8) the trampoline looks like:
        !           818:           ldr          r8, [pc, #0]
        !           819:           ldr          pc, [pc]
        !           820:           .word        static chain value
        !           821:           .word        function's address  */
        !           822: #define TRAMPOLINE_TEMPLATE(FILE)  \
        !           823: {                                              \
        !           824:   fprintf ((FILE), "\tldr\tr8, [pc, #0]\n");   \
        !           825:   fprintf ((FILE), "\tldr\tpc, [pc, #0]\n");   \
        !           826:   fprintf ((FILE), "\t.word\t0\n");            \
        !           827:   fprintf ((FILE), "\t.word\t0\n");            \
        !           828: }
        !           829: 
        !           830: /* Length in units of the trampoline for entering a nested function.  */
        !           831: #define TRAMPOLINE_SIZE  16
        !           832: 
        !           833: /* Alignment required for a trampoline in units.  */
        !           834: #define TRAMPOLINE_ALIGN  4
        !           835: 
        !           836: /* Emit RTL insns to initialize the variable parts of a trampoline.
        !           837:    FNADDR is an RTX for the address of the function's pure code.
        !           838:    CXT is an RTX for the static chain value for the function.  */
        !           839: #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)  \
        !           840: {                                                                      \
        !           841:   emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)),   \
        !           842:                  (CXT));                                               \
        !           843:   emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)),  \
        !           844:                  (FNADDR));                                            \
        !           845: }
        !           846: 
        !           847: /* Call the function profiler with a given profile label.  The Acorn compiler
        !           848:    puts this BEFORE the prolog but gcc pust it afterwards.  The ``mov ip,lr''
        !           849:    seems like a good idea to stick with cc convention.  ``prof'' doesn't seem
        !           850:    to mind about this!  */
        !           851: #define FUNCTION_PROFILER(STREAM,LABELNO)  \
        !           852: {                                                      \
        !           853:     fprintf(STREAM, "\tmov\tip, lr\n");                        \
        !           854:     fprintf(STREAM, "\tbl\tmcount\n");                 \
        !           855:     fprintf(STREAM, "\t.word\tLP%d\n", (LABELNO));     \
        !           856:     arm_increase_location (12);                                \
        !           857: }
        !           858: 
        !           859: /* Addressing modes, and classification of registers for them.  */
        !           860: 
        !           861: #define HAVE_POST_INCREMENT  1
        !           862: #define HAVE_PRE_INCREMENT  1
        !           863: #define HAVE_POST_DECREMENT  1
        !           864: #define HAVE_PRE_DECREMENT  1
        !           865: 
        !           866: /* Macros to check register numbers against specific register classes.  */
        !           867: 
        !           868: /* These assume that REGNO is a hard or pseudo reg number.
        !           869:    They give nonzero only if REGNO is a hard reg of the suitable class
        !           870:    or a pseudo reg currently allocated to a suitable hard reg.
        !           871:    Since they use reg_renumber, they are safe only once reg_renumber
        !           872:    has been allocated, which happens in local-alloc.c.
        !           873: 
        !           874:    On the ARM, don't allow the pc to be used.  */
        !           875: #define REGNO_OK_FOR_BASE_P(REGNO)                             \
        !           876:   ((REGNO) < 15 || (REGNO) == FRAME_POINTER_REGNUM             \
        !           877:    || (REGNO) == ARG_POINTER_REGNUM                            \
        !           878:    || (unsigned) reg_renumber[(REGNO)] < 15                    \
        !           879:    || (unsigned) reg_renumber[(REGNO)] == FRAME_POINTER_REGNUM \
        !           880:    || (unsigned) reg_renumber[(REGNO)] == ARG_POINTER_REGNUM)
        !           881: #define REGNO_OK_FOR_INDEX_P(REGNO) \
        !           882:   REGNO_OK_FOR_BASE_P(REGNO)
        !           883: 
        !           884: /* Maximum number of registers that can appear in a valid memory address.
        !           885:    Shifts in addresses can't be by a register. */
        !           886: 
        !           887: #define MAX_REGS_PER_ADDRESS 2
        !           888: 
        !           889: /* Recognize any constant value that is a valid address.  */
        !           890: /* XXX We can address any constant, eventually...  */
        !           891: #if 0
        !           892: #define CONSTANT_ADDRESS_P(X)  \
        !           893:     ( GET_CODE(X) == LABEL_REF \
        !           894:   ||  GET_CODE(X) == SYMBOL_REF \
        !           895:   ||  GET_CODE(X) == CONST_INT \
        !           896:   ||  GET_CODE(X) == CONST )
        !           897: #endif
        !           898: 
        !           899: #define CONSTANT_ADDRESS_P(X)                                          \
        !           900:   (GET_CODE (X) == SYMBOL_REF                                  \
        !           901:    && (CONSTANT_POOL_ADDRESS_P (X) || SYMBOL_REF_FLAG (X)))
        !           902: 
        !           903: /* Nonzero if the constant value X is a legitimate general operand.
        !           904:    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
        !           905: 
        !           906:    On the ARM, allow any integer (invalid ones are removed later by insn
        !           907:    patterns), nice doubles and symbol_refs which refer to the function's
        !           908:    constant pool XXX.  */
        !           909: #define LEGITIMATE_CONSTANT_P(X)                               \
        !           910:   (GET_CODE (X) == CONST_INT                                   \
        !           911:    || (GET_CODE (X) == CONST_DOUBLE                            \
        !           912:        && (const_double_rtx_ok_for_fpu (X)                     \
        !           913:           || neg_const_double_rtx_ok_for_fpu (X)))             \
        !           914:    || CONSTANT_ADDRESS_P (X))
        !           915: 
        !           916: /* Symbols in the text segment can be accessed without indirecting via the
        !           917:    constant pool; it may take an extra binary operation, but this is still
        !           918:    faster than indirecting via memory.  */
        !           919: 
        !           920: #define ENCODE_SECTION_INFO(decl)                                      \
        !           921: {                                                                      \
        !           922:   if (TREE_CONSTANT (decl)                                             \
        !           923:       && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))   \
        !           924:     {                                                                  \
        !           925:       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'             \
        !           926:                  ? TREE_CST_RTL (decl) : DECL_RTL (decl));             \
        !           927:       SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;                             \
        !           928:     }                                                                  \
        !           929: }
        !           930: 
        !           931: /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
        !           932:    and check its validity for a certain class.
        !           933:    We have two alternate definitions for each of them.
        !           934:    The usual definition accepts all pseudo regs; the other rejects
        !           935:    them unless they have been allocated suitable hard regs.
        !           936:    The symbol REG_OK_STRICT causes the latter definition to be used.  */
        !           937: #ifndef REG_OK_STRICT
        !           938: 
        !           939: /* Nonzero if X is a hard reg that can be used as a base reg
        !           940:    or if it is a pseudo reg.  */
        !           941: #define REG_OK_FOR_BASE_P(X)                           \
        !           942:   (REGNO (X) < 16 || REGNO (X) >= FIRST_PSEUDO_REGISTER \
        !           943:    || REGNO (X) == FRAME_POINTER_REGNUM || REGNO (X) == ARG_POINTER_REGNUM)
        !           944: 
        !           945: /* Nonzero if X is a hard reg that can be used as an index
        !           946:    or if it is a pseudo reg.  */
        !           947: #define REG_OK_FOR_INDEX_P(X)  \
        !           948:   REG_OK_FOR_BASE_P(X)
        !           949: 
        !           950: #define REG_OK_FOR_PRE_POST_P(X)                       \
        !           951:   (REGNO (X) < 16 || REGNO (X) >= FIRST_PSEUDO_REGISTER        \
        !           952:    || REGNO (X) == FRAME_POINTER_REGNUM || REGNO (X) == ARG_POINTER_REGNUM)
        !           953: 
        !           954: #else
        !           955: 
        !           956: /* Nonzero if X is a hard reg that can be used as a base reg.  */
        !           957: #define REG_OK_FOR_BASE_P(X)  REGNO_OK_FOR_BASE_P (REGNO (X))
        !           958: 
        !           959: /* Nonzero if X is a hard reg that can be used as an index.  */
        !           960: #define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P (REGNO (X))
        !           961: 
        !           962: #define REG_OK_FOR_PRE_POST_P(X)                                          \
        !           963:   (REGNO (X) < 16 || (unsigned) reg_renumber[REGNO (X)] < 16              \
        !           964:    || REGNO (X) == FRAME_POINTER_REGNUM || REGNO (X) == ARG_POINTER_REGNUM \
        !           965:    || (unsigned) reg_renumber[REGNO (X)] == FRAME_POINTER_REGNUM          \
        !           966:    || (unsigned) reg_renumber[REGNO (X)] == ARG_POINTER_REGNUM)
        !           967: 
        !           968: #endif
        !           969: 
        !           970: /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
        !           971:    that is a valid memory address for an instruction.
        !           972:    The MODE argument is the machine mode for the MEM expression
        !           973:    that wants to use this address.
        !           974: 
        !           975:    The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS.  */
        !           976: #define BASE_REGISTER_RTX_P(X)  \
        !           977:   (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
        !           978: 
        !           979: #define INDEX_REGISTER_RTX_P(X)  \
        !           980:   (GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))
        !           981: 
        !           982: /* A C statement (sans semicolon) to jump to LABEL for legitimate index RTXs
        !           983:    used by the macro GO_IF_LEGITIMATE_ADDRESS.  Floating point indices can
        !           984:    only be small constants. */
        !           985: #define GO_IF_LEGITIMATE_INDEX(MODE, BASE_REGNO, INDEX, LABEL)         \
        !           986: do                                                                     \
        !           987: {                                                                      \
        !           988:   int range;                                                           \
        !           989:   int code = GET_CODE (INDEX);                                         \
        !           990:                                                                        \
        !           991:   if (GET_MODE_CLASS (MODE) == MODE_FLOAT)                             \
        !           992:     {                                                                  \
        !           993:       if (code == CONST_INT && INTVAL (INDEX) < 1024                   \
        !           994:          && INTVAL (INDEX) > -1024                                     \
        !           995:          && (INTVAL (INDEX) & 3) == 0)                                 \
        !           996:        goto LABEL;                                                     \
        !           997:     }                                                                  \
        !           998:   else                                                                 \
        !           999:     {                                                                  \
        !          1000:       if (INDEX_REGISTER_RTX_P (INDEX) && GET_MODE_SIZE (MODE) <= 4)   \
        !          1001:        goto LABEL;                                                     \
        !          1002:       if (GET_MODE_SIZE (MODE) <= 4  && code == MULT)                  \
        !          1003:        {                                                               \
        !          1004:          rtx xiop0 = XEXP (INDEX, 0);                                  \
        !          1005:          rtx xiop1 = XEXP (INDEX, 1);                                  \
        !          1006:          if (INDEX_REGISTER_RTX_P (xiop0)                              \
        !          1007:              && power_of_two_operand (xiop1, SImode))                  \
        !          1008:            goto LABEL;                                                 \
        !          1009:          if (INDEX_REGISTER_RTX_P (xiop1)                              \
        !          1010:              && power_of_two_operand (xiop0, SImode))                  \
        !          1011:            goto LABEL;                                                 \
        !          1012:        }                                                               \
        !          1013:       if (GET_MODE_SIZE (MODE) <= 4                                    \
        !          1014:          && (code == LSHIFTRT || code == ASHIFTRT || code == LSHIFT    \
        !          1015:              || code == ASHIFT || code == ROTATERT))                   \
        !          1016:        {                                                               \
        !          1017:          rtx op = XEXP (INDEX, 1);                                     \
        !          1018:          if (INDEX_REGISTER_RTX_P (XEXP (INDEX, 0))                    \
        !          1019:              && GET_CODE (op) == CONST_INT && INTVAL (op) > 0          \
        !          1020:              && INTVAL (op) <= 31)                                     \
        !          1021:            goto LABEL;                                                 \
        !          1022:         }                                                              \
        !          1023:       range = (MODE) == HImode ? 4095 : 4096;                          \
        !          1024:       if (code == CONST_INT && INTVAL (INDEX) < range                  \
        !          1025:          && INTVAL (INDEX) > -range)                                   \
        !          1026:         goto LABEL;                                                    \
        !          1027:     }                                                                  \
        !          1028: } while (0)
        !          1029: 
        !          1030: /* Jump to LABEL if X is a valid address RTX.  This must also take
        !          1031:    REG_OK_STRICT into account when deciding about valid registers, but it uses
        !          1032:    the above macros so we are in luck.  Allow REG, REG+REG, REG+INDEX,
        !          1033:    INDEX+REG, REG-INDEX, and non floating SYMBOL_REF to the constant pool.
        !          1034:    Allow REG-only and AUTINC-REG if handling TImode or HImode.  Other symbol
        !          1035:    refs must be forced though a static cell to ensure addressability.  */
        !          1036: #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)  \
        !          1037: {                                                                      \
        !          1038:   if (BASE_REGISTER_RTX_P (X))                                         \
        !          1039:     goto LABEL;                                                                \
        !          1040:   else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC)       \
        !          1041:           && GET_CODE (XEXP (X, 0)) == REG                             \
        !          1042:           && REG_OK_FOR_PRE_POST_P (XEXP (X, 0)))                      \
        !          1043:     goto LABEL;                                                                \
        !          1044:   else if ((MODE) == TImode)                                           \
        !          1045:     ;                                                                  \
        !          1046:   else if (GET_CODE (X) == PLUS)                                       \
        !          1047:     {                                                                  \
        !          1048:       rtx xop0 = XEXP(X,0);                                            \
        !          1049:       rtx xop1 = XEXP(X,1);                                            \
        !          1050:                                                                        \
        !          1051:       if (BASE_REGISTER_RTX_P (xop0))                                  \
        !          1052:        GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL);       \
        !          1053:       else if (BASE_REGISTER_RTX_P (xop1))                             \
        !          1054:        GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL);       \
        !          1055:     }                                                                  \
        !          1056:   else if (GET_CODE (X) == MINUS)                                      \
        !          1057:     {                                                                  \
        !          1058:       rtx xop0 = XEXP (X,0);                                           \
        !          1059:       rtx xop1 = XEXP (X,1);                                           \
        !          1060:                                                                        \
        !          1061:       if (BASE_REGISTER_RTX_P (xop0))                                  \
        !          1062:        GO_IF_LEGITIMATE_INDEX (MODE, -1, xop1, LABEL);                 \
        !          1063:     }                                                                  \
        !          1064:   else if (GET_MODE_CLASS (MODE) != MODE_FLOAT                         \
        !          1065:           && GET_CODE (X) == SYMBOL_REF                                \
        !          1066:           && CONSTANT_POOL_ADDRESS_P (X))                              \
        !          1067:     goto LABEL;                                                                \
        !          1068:   else if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_DEC)       \
        !          1069:           && GET_CODE (XEXP (X, 0)) == REG                             \
        !          1070:           && REG_OK_FOR_PRE_POST_P (XEXP (X, 0)))                      \
        !          1071:     goto LABEL;                                                                \
        !          1072: }
        !          1073: 
        !          1074: /* Try machine-dependent ways of modifying an illegitimate address
        !          1075:    to be legitimate.  If we find one, return the new, valid address.
        !          1076:    This macro is used in only one place: `memory_address' in explow.c.
        !          1077: 
        !          1078:    OLDX is the address as it was before break_out_memory_refs was called.
        !          1079:    In some cases it is useful to look at this to decide what needs to be done.
        !          1080: 
        !          1081:    MODE and WIN are passed so that this macro can use
        !          1082:    GO_IF_LEGITIMATE_ADDRESS.
        !          1083: 
        !          1084:    It is always safe for this macro to do nothing.  It exists to recognize
        !          1085:    opportunities to optimize the output.
        !          1086: 
        !          1087:    On the ARM, try to convert [REG, #BIGCONST]
        !          1088:    into ADD BASE, REG, #UPPERCONST and [BASE, #VALIDCONST],
        !          1089:    where VALIDCONST == 0 in case of TImode.  */
        !          1090: #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)  \
        !          1091: {                                                                           \
        !          1092:   if (GET_CODE (X) == PLUS)                                                 \
        !          1093:     {                                                                       \
        !          1094:       rtx xop0 = XEXP (X, 0);                                               \
        !          1095:       rtx xop1 = XEXP (X, 1);                                               \
        !          1096:                                                                             \
        !          1097:       if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT)       \
        !          1098:        {                                                                    \
        !          1099:          int n = INTVAL (xop1);                                             \
        !          1100:          int low_n = ((MODE) == TImode ? 0                                  \
        !          1101:                       : n >= 0 ? (n & 0xFFF) : -((-n) & 0xFFF));            \
        !          1102:          rtx base_reg = gen_reg_rtx (SImode);                               \
        !          1103:          rtx val = force_operand (gen_rtx (PLUS, SImode, xop0,              \
        !          1104:                                            gen_rtx (CONST_INT,              \
        !          1105:                                                     VOIDmode, n - low_n)),  \
        !          1106:                                   0);                                       \
        !          1107:           emit_move_insn (base_reg, val);                                   \
        !          1108:          (X) = (low_n == 0 ? base_reg                                       \
        !          1109:                 : gen_rtx (PLUS, SImode, base_reg,                          \
        !          1110:                            gen_rtx (CONST_INT, VOIDmode, low_n)));          \
        !          1111:        }                                                                    \
        !          1112:       else if (BASE_REGISTER_RTX_P (xop1) && GET_CODE (xop0) == CONST_INT)   \
        !          1113:        {                                                                    \
        !          1114:          int n = INTVAL (xop0);                                             \
        !          1115:          int low_n = ((MODE) == TImode ? 0                                  \
        !          1116:                       : n >= 0 ? (n & 0xFFF) : -((-n) & 0xFFF));            \
        !          1117:          rtx base_reg = gen_reg_rtx (SImode);                               \
        !          1118:          rtx val = force_operand (gen_rtx (PLUS, SImode, xop1,              \
        !          1119:                                            gen_rtx (CONST_INT,              \
        !          1120:                                                     VOIDmode, n - low_n)),  \
        !          1121:                                   0);                                       \
        !          1122:          emit_move_insn (base_reg, val);                                    \
        !          1123:          (X) = (low_n == 0 ? base_reg                                       \
        !          1124:                 : gen_rtx (PLUS, SImode, base_reg,                          \
        !          1125:                            gen_rtx (CONST_INT, VOIDmode, low_n)));          \
        !          1126:        }                                                                    \
        !          1127:     }                                                                       \
        !          1128:   if (memory_address_p (MODE, X))                                           \
        !          1129:     goto win;                                                               \
        !          1130: }
        !          1131: 
        !          1132: /* Go to LABEL if ADDR (a legitimate address expression)
        !          1133:    has an effect that depends on the machine mode it is used for.  */
        !          1134: #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)  \
        !          1135: {                                                                      \
        !          1136:   if (GET_CODE(ADDR) == PRE_DEC || GET_CODE(ADDR) == POST_DEC          \
        !          1137:       || GET_CODE(ADDR) == PRE_INC || GET_CODE(ADDR) == POST_INC)      \
        !          1138:     goto LABEL;                                                                \
        !          1139: }
        !          1140: 
        !          1141: /* Specify the machine mode that this machine uses
        !          1142:    for the index in the tablejump instruction.  */
        !          1143: #define CASE_VECTOR_MODE SImode
        !          1144: 
        !          1145: /* Define this if the tablejump instruction expects the table
        !          1146:    to contain offsets from the address of the table.
        !          1147:    Do not define this if the table should contain absolute addresses.  */
        !          1148: /* #define CASE_VECTOR_PC_RELATIVE */
        !          1149: 
        !          1150: /* Specify the tree operation to be used to convert reals to integers.  */
        !          1151: #define IMPLICIT_FIX_EXPR  FIX_ROUND_EXPR
        !          1152: 
        !          1153: /* This is the kind of divide that is easiest to do in the general case.  */
        !          1154: #define EASY_DIV_EXPR  TRUNC_DIV_EXPR
        !          1155: 
        !          1156: /* signed 'char' is most compatible, but RISC OS wants it unsigned.
        !          1157:    unsigned is probably best, but may break some code.  */
        !          1158: #ifndef DEFAULT_SIGNED_CHAR
        !          1159: #define DEFAULT_SIGNED_CHAR  1
        !          1160: #endif
        !          1161: 
        !          1162: /* Don't cse the address of the function being compiled.  */
        !          1163: #define NO_RECURSIVE_FUNCTION_CSE 1
        !          1164: 
        !          1165: /* Max number of bytes we can move from memory to memory
        !          1166:    in one reasonably fast instruction.  */
        !          1167: #define MOVE_MAX 4
        !          1168: 
        !          1169: /* Define if operations between registers always perform the operation
        !          1170:    on the full register even if a narrower mode is specified.  */
        !          1171: #define WORD_REGISTER_OPERATIONS
        !          1172: 
        !          1173: /* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
        !          1174:    will either zero-extend or sign-extend.  The value of this macro should
        !          1175:    be the code that says which one of the two operations is implicitly
        !          1176:    done, NIL if none.  */
        !          1177: #define LOAD_EXTEND_OP(MODE) \
        !          1178:   ((MODE) == QImode ? ZERO_EXTEND : NIL)
        !          1179: 
        !          1180: /* Define this if zero-extension is slow (more than one real instruction).
        !          1181:    On the ARM, it is more than one instruction only if not fetching from
        !          1182:    memory.  */
        !          1183: /* #define SLOW_ZERO_EXTEND */
        !          1184: 
        !          1185: /* Nonzero if access to memory by bytes is slow and undesirable.  */
        !          1186: #define SLOW_BYTE_ACCESS 0
        !          1187: 
        !          1188: /* Immediate shift counts are truncated by the output routines (or was it
        !          1189:    the assembler?).  Shift counts in a register are truncated by ARM.  Note
        !          1190:    that the native compiler puts too large (> 32) immediate shift counts
        !          1191:    into a register and shifts by the register, letting the ARM decide what
        !          1192:    to do instead of doing that itself.  */
        !          1193: /* This is all wrong.  Defining SHIFT_COUNT_TRUNCATED tells combine that
        !          1194:    code like (X << (Y % 32)) for register X, Y is equivalent to (X << Y).
        !          1195:    On the arm, Y in a register is used modulo 256 for the shift. Only for
        !          1196:    rotates is modulo 32 used. */
        !          1197: /* #define SHIFT_COUNT_TRUNCATED 1 */
        !          1198: 
        !          1199: /* XX This is not true, is it?  */
        !          1200: /* All integers have the same format so truncation is easy.  */
        !          1201: #define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC)  1
        !          1202: 
        !          1203: /* Calling from registers is a massive pain.  */
        !          1204: #define NO_FUNCTION_CSE 1
        !          1205: 
        !          1206: /* Chars and shorts should be passed as ints.  */
        !          1207: #define PROMOTE_PROTOTYPES 1
        !          1208: 
        !          1209: /* The machine modes of pointers and functions */
        !          1210: #define Pmode  SImode
        !          1211: #define FUNCTION_MODE  Pmode
        !          1212: 
        !          1213: /* The structure type of the machine dependent info field of insns
        !          1214:    No uses for this yet.  */
        !          1215: /* #define INSN_MACHINE_INFO  struct machine_info  */
        !          1216: 
        !          1217: /* The relative costs of various types of constants.  Note that cse.c defines
        !          1218:    REG = 1, SUBREG = 2, any node = (2 + sum of subnodes).  */
        !          1219: #define CONST_COSTS(RTX, CODE, OUTER_CODE)                     \
        !          1220:   case CONST_INT:                                              \
        !          1221:     if (const_ok_for_arm (INTVAL (RTX)))                       \
        !          1222:       return (OUTER_CODE) == SET ? 2 : -1;                     \
        !          1223:     else if (OUTER_CODE == AND                                 \
        !          1224:              && const_ok_for_arm (~INTVAL (RTX)))              \
        !          1225:       return -1;                                               \
        !          1226:     else if ((OUTER_CODE == COMPARE                            \
        !          1227:               || OUTER_CODE == PLUS || OUTER_CODE == MINUS)     \
        !          1228:              && const_ok_for_arm (-INTVAL (RTX)))              \
        !          1229:       return -1;                                               \
        !          1230:     else                                                       \
        !          1231:       return 5;                                                        \
        !          1232:   case CONST:                                                  \
        !          1233:   case LABEL_REF:                                              \
        !          1234:   case SYMBOL_REF:                                             \
        !          1235:     return 6;                                                  \
        !          1236:   case CONST_DOUBLE:                                           \
        !          1237:     if (const_double_rtx_ok_for_fpu (RTX))                     \
        !          1238:       return (OUTER_CODE) == SET ? 2 : -1;                     \
        !          1239:     else if (((OUTER_CODE) == COMPARE || (OUTER_CODE) == PLUS) \
        !          1240:             && neg_const_double_rtx_ok_for_fpu (RTX))          \
        !          1241:        return -1;                                              \
        !          1242:     return(7);
        !          1243: 
        !          1244: #define RTX_COSTS(X,CODE,OUTER_CODE)                                    \
        !          1245:   case MEM:                                                             \
        !          1246:     {                                                                   \
        !          1247:       int num_words = (GET_MODE_SIZE (GET_MODE (X)) > UNITS_PER_WORD) ? 2 : 1;\
        !          1248:       return (COSTS_N_INSNS (10*num_words));                             \
        !          1249:     }                                                                   \
        !          1250:   case MULT:                                                            \
        !          1251:     if (GET_CODE (XEXP (X, 1)) == CONST_INT                             \
        !          1252:         && exact_log2 (INTVAL (XEXP (X, 1))) >= 0)                      \
        !          1253:       return rtx_cost (XEXP (X, 0), GET_CODE (X))+1;                    \
        !          1254:     return COSTS_N_INSNS (9);                                           \
        !          1255:   case LSHIFT:                                                         \
        !          1256:   case ASHIFT:                                                         \
        !          1257:   case LSHIFTRT:                                                       \
        !          1258:   case ASHIFTRT:                                                       \
        !          1259:     if (GET_CODE (XEXP (X, 1)) == CONST_INT)                           \
        !          1260:       return rtx_cost (XEXP (X, 0), GET_CODE (X))+1;                   \
        !          1261:     break;                                                             \
        !          1262:   case MINUS:                                                          \
        !          1263:   {                                                                    \
        !          1264:     enum rtx_code code = GET_CODE (XEXP (X, 1));                       \
        !          1265:     if (code == MULT)                                                  \
        !          1266:       {                                                                        \
        !          1267:        if (GET_CODE (XEXP (XEXP (X, 1), 1)) == CONST_INT               \
        !          1268:            && exact_log2 (INTVAL (XEXP (XEXP (X, 0), 1))) >= 0)        \
        !          1269:          return COSTS_N_INSNS (1);                                     \
        !          1270:        break;                                                          \
        !          1271:       }                                                                        \
        !          1272:     else if (code == ASHIFT || code == LSHIFT || code == ASHIFTRT      \
        !          1273:             || code == LSHIFTRT)                                       \
        !          1274:       return COSTS_N_INSNS (1);                                                \
        !          1275:   } /* fall through */                                                 \
        !          1276:   case PLUS:                                                           \
        !          1277:   case IOR:                                                            \
        !          1278:   case XOR:                                                            \
        !          1279:   case AND:                                                            \
        !          1280:   {                                                                    \
        !          1281:     enum rtx_code code = GET_CODE (XEXP (X, 0));                       \
        !          1282:     if (code == MULT)                                                  \
        !          1283:       {                                                                        \
        !          1284:        if (GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT               \
        !          1285:            && exact_log2 (INTVAL (XEXP (XEXP (X, 0), 1))) >= 0)        \
        !          1286:          return COSTS_N_INSNS (1);                                     \
        !          1287:        if (GET_CODE (X) == PLUS)                                       \
        !          1288:          return COSTS_N_INSNS (12);                                    \
        !          1289:        break;                                                          \
        !          1290:       }                                                                        \
        !          1291:     else if (code == ASHIFT || code == LSHIFT || code == ASHIFTRT      \
        !          1292:             || code == LSHIFTRT)                                       \
        !          1293:       return COSTS_N_INSNS (1);                                                \
        !          1294:     break;                                                             \
        !          1295:   }                                                                    \
        !          1296:   case NOT:                                                            \
        !          1297:     return rtx_cost (XEXP (X, 0), GET_CODE (XEXP (X, 0)));             \
        !          1298:   case IF_THEN_ELSE:                                                    \
        !          1299:     {                                                                   \
        !          1300:       if (GET_CODE (XEXP(X,1)) == PC || GET_CODE (XEXP(X,2)) == PC)     \
        !          1301:         return COSTS_N_INSNS (4);                                       \
        !          1302:       return COSTS_N_INSNS (1);                                        \
        !          1303:     }                                                                   \
        !          1304:   case SIGN_EXTEND:                                                     \
        !          1305:     return COSTS_N_INSNS (2);                                          \
        !          1306:   case ZERO_EXTEND:                                                    \
        !          1307:     if (GET_MODE (XEXP (X, 0)) == QImode)                              \
        !          1308:       {                                                                        \
        !          1309:        if (GET_CODE (XEXP (X, 0)) == MEM)                              \
        !          1310:          return COSTS_N_INSNS (10);                                    \
        !          1311:        return COSTS_N_INSNS (1);                                       \
        !          1312:       }                                                                        \
        !          1313:     break;                                                             \
        !          1314:   case COMPARE:                                                                \
        !          1315:     if (GET_CODE (XEXP (X, 1)) == REG)                                 \
        !          1316:       return 4;                                                                \
        !          1317:   case SMIN:                                                           \
        !          1318:   case SMAX:                                                           \
        !          1319:   case UMIN:                                                           \
        !          1320:   case UMAX:                                                           \
        !          1321:     return COSTS_N_INSNS (3);                                          \
        !          1322:   case ABS:                                                            \
        !          1323:     if (GET_MODE (X) == SImode)                                                \
        !          1324:       return COSTS_N_INSNS (2);                                                \
        !          1325:     return COSTS_N_INSNS (1);
        !          1326: 
        !          1327: /* Moves to and from memory are quite expensive */
        !          1328: #define MEMORY_MOVE_COST(MODE)  10
        !          1329: 
        !          1330: /* All address computations that can be done are free */
        !          1331: #define ADDRESS_COST(x) 2
        !          1332: 
        !          1333: /* Try to generate sequences that don't involve branches, we can then use
        !          1334:    conditional instructions */
        !          1335: #define BRANCH_COST 4
        !          1336: 
        !          1337: /* Condition code information. */
        !          1338: /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
        !          1339:    return the mode to be used for the comparison. 
        !          1340:    CCFPEmode should be used with floating inequalites,
        !          1341:    CCFPmode should be used with floating equalities.
        !          1342:    CC_NOOVmode should be used with SImode integer equalites
        !          1343:    CCmode should be used otherwise. */
        !          1344: 
        !          1345: #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode, CCFPEmode
        !          1346: 
        !          1347: #define EXTRA_CC_NAMES "CC_NOOV", "CCFP", "CCFPE"
        !          1348: 
        !          1349: #define SELECT_CC_MODE(OP,X,Y)                                         \
        !          1350:   (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT                         \
        !          1351:    ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode)                   \
        !          1352:    : ((GET_MODE (X) == SImode)                                         \
        !          1353:       && ((OP) == EQ || (OP) == NE)                                    \
        !          1354:       && (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS                        \
        !          1355:          || GET_CODE (X) == AND || GET_CODE (X) == IOR                 \
        !          1356:          || GET_CODE (X) == XOR || GET_CODE (X) == MULT                \
        !          1357:          || GET_CODE (X) == NOT || GET_CODE (X) == NEG                 \
        !          1358:          || GET_CODE (X) == LSHIFT || GET_CODE (X) == LSHIFTRT         \
        !          1359:          || GET_CODE (X) == ASHIFT || GET_CODE (X) == ASHIFTRT         \
        !          1360:          || GET_CODE (X) == ROTATERT || GET_CODE (X) == ZERO_EXTRACT)  \
        !          1361:       ? CC_NOOVmode                                                    \
        !          1362:       : GET_MODE (X) == QImode ? CC_NOOVmode : CCmode))
        !          1363: 
        !          1364: #define STORE_FLAG_VALUE 1
        !          1365: 
        !          1366: /* Define the information needed to generate branch insns.  This is
        !          1367:    stored from the compare operation.  Note that we can't use "rtx" here
        !          1368:    since it hasn't been defined!  */
        !          1369: 
        !          1370: extern struct rtx_def *arm_compare_op0, *arm_compare_op1;
        !          1371: extern int arm_compare_fp;
        !          1372: 
        !          1373: /* Define the codes that are matched by predicates in arm.c */
        !          1374: #define PREDICATE_CODES                                                        \
        !          1375:   {"s_register_operand", {SUBREG, REG}},                               \
        !          1376:   {"arm_add_operand", {SUBREG, REG, CONST_INT}},                       \
        !          1377:   {"fpu_add_operand", {SUBREG, REG, CONST_DOUBLE}},                    \
        !          1378:   {"arm_rhs_operand", {SUBREG, REG, CONST_INT}},                       \
        !          1379:   {"fpu_rhs_operand", {SUBREG, REG, CONST_DOUBLE}},                    \
        !          1380:   {"arm_not_operand", {SUBREG, REG, CONST_INT}},                       \
        !          1381:   {"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}},                        \
        !          1382:   {"minmax_operator", {SMIN, SMAX, UMIN, UMAX}},                       \
        !          1383:   {"shift_operator", {ASHIFT, LSHIFT, ASHIFTRT, LSHIFTRT, MULT}},      \
        !          1384:   {"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}},         \
        !          1385:   {"load_multiple_operation", {PARALLEL}},                             \
        !          1386:   {"store_multiple_operation", {PARALLEL}},                            \
        !          1387:   {"equality_operator", {EQ, NE}},                                     \
        !          1388:   {"arm_rhsm_operand", {SUBREG, REG, CONST_INT, MEM}},                 \
        !          1389:   {"const_shift_operand", {CONST_INT}},                                        \
        !          1390:   {"index_operand", {SUBREG, REG, CONST_INT}},                         \
        !          1391:   {"cc_register", {REG}},
        !          1392: 
        !          1393: 
        !          1394: /* Assembler output control */
        !          1395: 
        !          1396: #ifndef ARM_OS_NAME
        !          1397: #define ARM_OS_NAME "(generic)"
        !          1398: #endif
        !          1399: 
        !          1400: /* The text to go at the start of the assembler file */
        !          1401: #define ASM_FILE_START(STREAM)  \
        !          1402: {                                                                             \
        !          1403:   extern char *version_string;                                                \
        !          1404:                                                                              \
        !          1405:   fprintf (STREAM,"@ Generated by gcc %s for ARM/%s\n", version_string,              \
        !          1406:           ARM_OS_NAME);                                                      \
        !          1407:   fprintf (STREAM,"rfp\t.req\tr9\n");                                         \
        !          1408:   fprintf (STREAM,"fp\t.req\tr11\n");                                        \
        !          1409:   fprintf (STREAM,"ip\t.req\tr12\n");                                        \
        !          1410:   fprintf (STREAM,"sp\t.req\tr13\n");                                        \
        !          1411:   fprintf (STREAM,"lr\t.req\tr14\n");                                        \
        !          1412:   fprintf (STREAM,"pc\t.req\tr15\n");                                        \
        !          1413: }
        !          1414: 
        !          1415: #define ASM_APP_ON  ""
        !          1416: #define ASM_APP_OFF  ""
        !          1417: 
        !          1418: /* Switch to the text or data segment.  */
        !          1419: #define TEXT_SECTION_ASM_OP  ".text"
        !          1420: #define DATA_SECTION_ASM_OP  ".data"
        !          1421: 
        !          1422: /* The assembler's names for the registers.  RFP need not always be used as
        !          1423:    the Real framepointer; it can also be used as a normal general register.
        !          1424:    Note that the name `fp' is horribly misleading since `fp' is in fact only
        !          1425:    the argument-and-return-context pointer.  */
        !          1426: #define REGISTER_NAMES  \
        !          1427: {                                                 \
        !          1428:   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",  \
        !          1429:   "r8","rfp", "sl", "fp", "ip", "sp", "lr", "pc",  \
        !          1430:   "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",  \
        !          1431:   "cc", "sfp", "afp"                              \
        !          1432: }
        !          1433: 
        !          1434: /* Arm Assembler barfs on dollars */
        !          1435: #define DOLLARS_IN_IDENTIFIERS 0
        !          1436: 
        !          1437: #define NO_DOLLAR_IN_LABEL
        !          1438: 
        !          1439: /* DBX register number for a given compiler register number */
        !          1440: #define DBX_REGISTER_NUMBER(REGNO)  (REGNO)
        !          1441: 
        !          1442: /* Generate DBX debugging information.  riscix.h will undefine this because
        !          1443:    the native assembler does not support stabs. */
        !          1444: #define DBX_DEBUGGING_INFO  1
        !          1445: 
        !          1446: /* Acorn dbx moans about continuation chars, so don't use any.  */
        !          1447: #define DBX_CONTIN_LENGTH  0
        !          1448: 
        !          1449: /* Output a source filename for the debugger. RISCiX dbx insists that the
        !          1450:    ``desc'' field is set to compiler version number >= 315 (sic).  */
        !          1451: #define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM,NAME)                   \
        !          1452: do {                                                                   \
        !          1453:   fprintf (STREAM, ".stabs \"%s\",%d,0,315,%s\n", (NAME), N_SO,                \
        !          1454:           &ltext_label_name[1]);                                       \
        !          1455:   text_section ();                                                     \
        !          1456:   ASM_OUTPUT_INTERNAL_LABEL (STREAM, "Ltext", 0);                      \
        !          1457: } while (0)
        !          1458:   
        !          1459: /* Output a label definition.  */
        !          1460: #define ASM_OUTPUT_LABEL(STREAM,NAME)  \
        !          1461:   arm_asm_output_label ((STREAM), (NAME))
        !          1462: 
        !          1463: /* Output a function label definition.  */
        !          1464: #define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
        !          1465:     ASM_OUTPUT_LABEL(STREAM, NAME)
        !          1466: 
        !          1467: /* Output a globalising directive for a label.  */
        !          1468: #define ASM_GLOBALIZE_LABEL(STREAM,NAME)  \
        !          1469:   (fprintf (STREAM, "\t.global\t"),      \
        !          1470:    assemble_name (STREAM, NAME),         \
        !          1471:    fputc ('\n',STREAM))                   \
        !          1472: 
        !          1473: /* Output a reference to a label.  */
        !          1474: #define ASM_OUTPUT_LABELREF(STREAM,NAME)  \
        !          1475:   fprintf (STREAM, "_%s", NAME)
        !          1476: 
        !          1477: /* Make an internal label into a string.  */
        !          1478: #define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM)  \
        !          1479:   sprintf (STRING, "*%s%d", PREFIX, NUM)
        !          1480: 
        !          1481: /* Output an internal label definition.  */
        !          1482: #define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM)  \
        !          1483:   do                                                                   \
        !          1484:     {                                                                  \
        !          1485:       char *s = (char *) alloca (11 + strlen (PREFIX));                        \
        !          1486:       extern int arm_target_label, arm_ccfsm_state;                    \
        !          1487:       extern rtx arm_target_insn;                                      \
        !          1488:                                                                        \
        !          1489:       if (arm_ccfsm_state == 3 && arm_target_label == (NUM)            \
        !          1490:        && !strcmp (PREFIX, "L"))                                       \
        !          1491:        {                                                               \
        !          1492:          arm_ccfsm_state = 0;                                          \
        !          1493:          arm_target_insn = NULL;                                       \
        !          1494:        }                                                               \
        !          1495:        strcpy (s, "*");                                                \
        !          1496:        sprintf (&s[strlen (s)], "%s%d", (PREFIX), (NUM));              \
        !          1497:        arm_asm_output_label (STREAM, s);                               \
        !          1498:     } while (0)
        !          1499: 
        !          1500: /* Nothing special is done about jump tables */
        !          1501: /* #define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE)   */
        !          1502: /* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE)           */
        !          1503: 
        !          1504: /* Construct a private name.  */
        !          1505: #define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER)  \
        !          1506:   ((OUTVAR) = (char *) alloca (strlen (NAME) + 10),  \
        !          1507:    sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
        !          1508: 
        !          1509: /* Output a push or a pop instruction (only used when profiling).  */
        !          1510: #define ASM_OUTPUT_REG_PUSH(STREAM,REGNO)   \
        !          1511:   (arm_increase_location (4)                                   \
        !          1512:    , fprintf(STREAM,"\tstmfd\tsp!,{%s}\n", reg_names[REGNO]))
        !          1513: 
        !          1514: #define ASM_OUTPUT_REG_POP(STREAM,REGNO)   \
        !          1515:   (arm_increase_location (4)                                   \
        !          1516:    , fprintf(STREAM,"\tldmfd\tsp!,{%s}\n", reg_names[REGNO]))
        !          1517: 
        !          1518: /* Output a relative address. Not needed since jump tables are absolute
        !          1519:    but we must define it anyway.  */
        !          1520: #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL)  \
        !          1521:   fputs ("- - - ASM_OUTPUT_ADDR_DIFF_ELT called!\n", STREAM)
        !          1522: 
        !          1523: /* Output an element of a dispatch table.  */
        !          1524: #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)  \
        !          1525:   (arm_increase_location (4)                     \
        !          1526:    , fprintf (STREAM, "\t.word\tL%d\n", VALUE))
        !          1527: 
        !          1528: /* Output various types of constants.  For real numbers we output hex, with
        !          1529:    a comment containing the "human" value, this allows us to pass NaN's which
        !          1530:    the riscix assembler doesn't understand (it also makes cross-assembling
        !          1531:    less likely to fail). */
        !          1532: 
        !          1533: #define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE)                           \
        !          1534: do { char dstr[30];                                                    \
        !          1535:      long l[3];                                                                \
        !          1536:      arm_increase_location (12);                                       \
        !          1537:      REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);                      \
        !          1538:      REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);                     \
        !          1539:      if (sizeof (int) == sizeof (long))                                        \
        !          1540:        fprintf (STREAM, "\t.long 0x%x,0x%x,0x%x\t@ long double %s\n",  \
        !          1541:                l[2], l[1], l[0], dstr);                                \
        !          1542:      else                                                              \
        !          1543:        fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t@ long double %s\n",\
        !          1544:                l[0], l[1], l[2], dstr);                                \
        !          1545:    } while (0)
        !          1546: 
        !          1547:     
        !          1548: #define ASM_OUTPUT_DOUBLE(STREAM, VALUE)                               \
        !          1549: do { char dstr[30];                                                    \
        !          1550:      long l[2];                                                                \
        !          1551:      arm_increase_location (8);                                                \
        !          1552:      REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l);                           \
        !          1553:      REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr);                     \
        !          1554:      if (sizeof (int) == sizeof (long))                                        \
        !          1555:        fprintf (STREAM, "\t.long 0x%x, 0x%x\t@ double %s\n", l[0], l[1],\
        !          1556:                dstr);                                                  \
        !          1557:      else                                                              \
        !          1558:        fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t@ double %s\n", l[0],   \
        !          1559:                l[1], dstr);                                            \
        !          1560:    } while (0)
        !          1561: 
        !          1562: #define ASM_OUTPUT_FLOAT(STREAM, VALUE)                                        \
        !          1563: do { char dstr[30];                                                    \
        !          1564:      long l;                                                           \
        !          1565:      arm_increase_location (4);                                                \
        !          1566:      REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);                           \
        !          1567:      REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr);                      \
        !          1568:      if (sizeof (int) == sizeof (long))                                        \
        !          1569:        fprintf (STREAM, "\t.word 0x%x\t@ float %s\n", l, dstr);                \
        !          1570:      else                                                              \
        !          1571:        fprintf (STREAM, "\t.word 0x%lx\t@ float %s\n", l, dstr);       \
        !          1572:    } while (0);
        !          1573: 
        !          1574: #define ASM_OUTPUT_INT(STREAM, EXP)    \
        !          1575:   (fprintf (STREAM, "\t.word\t"),      \
        !          1576:    output_addr_const (STREAM, (EXP)),  \
        !          1577:    arm_increase_location (4),          \
        !          1578:    fputc ('\n', STREAM))
        !          1579: 
        !          1580: #define ASM_OUTPUT_SHORT(STREAM, EXP)  \
        !          1581:   (fprintf (STREAM, "\t.short\t"),     \
        !          1582:    output_addr_const (STREAM, (EXP)),  \
        !          1583:    arm_increase_location (2),          \
        !          1584:    fputc ('\n', STREAM))
        !          1585: 
        !          1586: #define ASM_OUTPUT_CHAR(STREAM, EXP)  \
        !          1587:   (fprintf (STREAM, "\t.byte\t"),      \
        !          1588:    output_addr_const (STREAM, (EXP)),  \
        !          1589:    arm_increase_location (1),          \
        !          1590:    fputc ('\n', STREAM))
        !          1591: 
        !          1592: #define ASM_OUTPUT_BYTE(STREAM, VALUE)  \
        !          1593:   (fprintf (STREAM, "\t.byte\t%d\n", VALUE),  \
        !          1594:    arm_increase_location (1))
        !          1595: 
        !          1596: #define ASM_OUTPUT_ASCII(STREAM, PTR, LEN)  \
        !          1597:   output_ascii_pseudo_op ((STREAM), (unsigned char *)(PTR), (LEN))
        !          1598: 
        !          1599: /* Output a gap.  In fact we fill it with nulls.  */
        !          1600: #define ASM_OUTPUT_SKIP(STREAM, NBYTES)  \
        !          1601:   (arm_increase_location (NBYTES),              \
        !          1602:    fprintf (STREAM, "\t.space\t%d\n", NBYTES))
        !          1603: 
        !          1604: /* Align output to a power of two.  Horrible /bin/as.  */
        !          1605: #define ASM_OUTPUT_ALIGN(STREAM, POWER)  \
        !          1606:   do                                                           \
        !          1607:     {                                                          \
        !          1608:       register int amount = 1 << (POWER);                      \
        !          1609:       extern int arm_text_location;                           \
        !          1610:                                                                \
        !          1611:       if (amount == 2)                                         \
        !          1612:        fprintf (STREAM, "\t.even\n");                         \
        !          1613:       else                                                     \
        !          1614:        fprintf (STREAM, "\t.align\t%d\n", amount - 4);        \
        !          1615:                                                                \
        !          1616:       if (in_text_section ())                                  \
        !          1617:        arm_text_location = ((arm_text_location + amount - 1)  \
        !          1618:                             & ~(amount - 1));                 \
        !          1619:     } while (0)
        !          1620: 
        !          1621: /* Output a common block */
        !          1622: #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)  \
        !          1623:   (fprintf (STREAM, "\t.comm\t"),                   \
        !          1624:    assemble_name ((STREAM), (NAME)),                \
        !          1625:    fprintf(STREAM, ", %d\t@%d\n", ROUNDED, SIZE))
        !          1626: 
        !          1627: /* Output a local common block.  /bin/as can't do this, so hack a `.space' into
        !          1628:    the bss segment.  Note that this is *bad* practice.  */
        !          1629: #define ASM_OUTPUT_LOCAL(STREAM,NAME,SIZE,ROUNDED)  \
        !          1630:   output_lcomm_directive (STREAM, NAME, SIZE, ROUNDED)
        !          1631: 
        !          1632: /* Output a source filename for the debugger. RISCiX dbx insists that the
        !          1633:    ``desc'' field is set to compiler version number >= 315 (sic).  */
        !          1634: #if 0
        !          1635: #define ASM_OUTPUT_SOURCE_FILENAME(STREAM,NAME)         \
        !          1636:   fprintf (STREAM, "\t.stabs\t\"%s\", %d, 0, 315, Ltext\n", (NAME), N_SOL)
        !          1637: #endif
        !          1638: 
        !          1639: /* Output a source line for the debugger.  */
        !          1640: /* #define ASM_OUTPUT_SOURCE_LINE(STREAM,LINE) */
        !          1641: 
        !          1642: /* Output a #ident directive.  */
        !          1643: #define ASM_OUTPUT_IDENT(STREAM,STRING)  \
        !          1644:   fprintf (STREAM,"- - - ident %s\n",STRING)
        !          1645: 
        !          1646: /* The assembler's parentheses characters.  */
        !          1647: #define ASM_OPEN_PAREN "("
        !          1648: #define ASM_CLOSE_PAREN ")"
        !          1649: 
        !          1650: /* Target characters.  */
        !          1651: #define TARGET_BELL    007
        !          1652: #define TARGET_BS      010
        !          1653: #define TARGET_TAB     011
        !          1654: #define TARGET_NEWLINE 012
        !          1655: #define TARGET_VT      013
        !          1656: #define TARGET_FF      014
        !          1657: #define TARGET_CR      015
        !          1658: 
        !          1659: /* FINAL_PRESCAN_INSN is used to take a look at the insns, in order to delete
        !          1660:    small-distance conditional branches and have ASM_OUTPUT_OPCODE make the
        !          1661:    instructions conditional.  Suffixes like s (affect flags) and b (bytewise
        !          1662:    load/store) need to stay suffixes, so the possible condition code comes
        !          1663:    before these suffixes.  %d<n> or %D<n> may appear in the opcode if
        !          1664:    it can take a condition; a null rtx will cause no condition to be added,
        !          1665:    this is what we expect to happen if arm_ccfsm_state is non-zero. */
        !          1666: #define ASM_OUTPUT_OPCODE(STREAM, PTR)  \
        !          1667:   {                                                                  \
        !          1668:     extern int arm_ccfsm_state, arm_current_cc;                              \
        !          1669:     extern char *arm_condition_codes[];                                      \
        !          1670:     int i;                                                           \
        !          1671:                                                                      \
        !          1672:     fflush (STREAM);       /* XXX for debugging only.  */            \
        !          1673:     if (arm_ccfsm_state == 3 || arm_ccfsm_state == 4)                  \
        !          1674:       {                                                                             \
        !          1675:        for (i = 0; *(PTR) != ' ' && *(PTR) != '\t' && *(PTR) != '%' && i < 3;\
        !          1676:             i++, (PTR)++)                                                   \
        !          1677:          putc (*(PTR), STREAM);                                             \
        !          1678:        fprintf (STREAM, "%s", arm_condition_codes[arm_current_cc]);         \
        !          1679:        for (; *(PTR) != ' ' && *(PTR) != '\t' && *(PTR) != '%'; (PTR)++)    \
        !          1680:          putc (*(PTR), STREAM);                                             \
        !          1681:       }                                                                             \
        !          1682:   }
        !          1683: 
        !          1684: /* Only perform branch elimination (by making instructions conditional) if
        !          1685:    we're optimising.  Otherwise it's of no use anyway.  */
        !          1686: #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS)  \
        !          1687:   if (optimize)                                            \
        !          1688:     final_prescan_insn (INSN, OPVEC, NOPERANDS)
        !          1689: 
        !          1690: /* Output an operand of an instruction.  If X is a REG and CODE is `M', output
        !          1691:    a ldm/stm style multi-reg.  */
        !          1692: #define PRINT_OPERAND(STREAM, X, CODE)  \
        !          1693: {                                                                      \
        !          1694:   if ((CODE) == 'd')                                                   \
        !          1695:     {                                                                  \
        !          1696:       if (X)                                                           \
        !          1697:         fputs (arm_condition_codes[get_arm_condition_code (X)],                \
        !          1698:               (STREAM));                                               \
        !          1699:     }                                                                  \
        !          1700:   else if ((CODE) == 'D')                                              \
        !          1701:     {                                                                  \
        !          1702:       if (X)                                                           \
        !          1703:         fputs (arm_condition_codes[get_arm_condition_code (X) ^ 1],    \
        !          1704:               (STREAM));                                               \
        !          1705:     }                                                                  \
        !          1706:   else if ((CODE) == 'R')                                              \
        !          1707:     fputs (reg_names[REGNO (X) + 1], (STREAM));                                \
        !          1708:   else if (GET_CODE (X) == REG)                                                \
        !          1709:     {                                                                  \
        !          1710:       if ((CODE) != 'M')                                               \
        !          1711:        fputs (reg_names[REGNO (X)], (STREAM));                         \
        !          1712:       else                                                             \
        !          1713:        fprintf ((STREAM), "{%s-%s}",                                   \
        !          1714:                 reg_names[REGNO (X)],                                  \
        !          1715:                 reg_names[REGNO (X) - 1                                \
        !          1716:                           + ((GET_MODE_SIZE (GET_MODE (X))             \
        !          1717:                               + GET_MODE_SIZE (SImode) - 1)            \
        !          1718:                              / GET_MODE_SIZE (SImode))]);              \
        !          1719:     }                                                                  \
        !          1720:   else if (GET_CODE (X) == MEM)                                                \
        !          1721:     {                                                                  \
        !          1722:       extern int output_memory_reference_mode;                         \
        !          1723:       output_memory_reference_mode = GET_MODE (X);                     \
        !          1724:       output_address (XEXP (X, 0));                                    \
        !          1725:     }                                                                  \
        !          1726:   else if (GET_CODE(X) == CONST_DOUBLE)                                        \
        !          1727:     fprintf(STREAM,"#%s", fp_immediate_constant(X));                   \
        !          1728:   else if (GET_CODE (X) == NEG)                                                \
        !          1729:     {                                                                  \
        !          1730:       fputc ('-', (STREAM));                                           \
        !          1731:       output_operand ((X), 0);                                         \
        !          1732:     }                                                                  \
        !          1733:   else                                                                 \
        !          1734:     {                                                                  \
        !          1735:       fputc('#', STREAM);                                              \
        !          1736:       output_addr_const(STREAM, X);                                    \
        !          1737:     }                                                                  \
        !          1738: }
        !          1739: 
        !          1740: /* Output the address of an operand.  */
        !          1741: #define PRINT_OPERAND_ADDRESS(STREAM,X)  \
        !          1742: {                                                                      \
        !          1743:     int is_minus = GET_CODE (X) == MINUS;                              \
        !          1744:                                                                        \
        !          1745:     if (GET_CODE (X) == REG)                                           \
        !          1746:        fprintf (STREAM, "[%s, #0]", reg_names[REGNO (X)]);             \
        !          1747:     else if (GET_CODE (X) == PLUS || is_minus)                         \
        !          1748:       {                                                                        \
        !          1749:        rtx base = XEXP (X, 0);                                         \
        !          1750:        rtx index = XEXP (X, 1);                                        \
        !          1751:        char *base_reg_name;                                            \
        !          1752:        int offset = 0;                                                 \
        !          1753:        int shift;                                                      \
        !          1754:        if (GET_CODE (base) != REG)                                     \
        !          1755:          {                                                             \
        !          1756:            /* Ensure that BASE is a register (one of them must be). */ \
        !          1757:            rtx temp = base;                                            \
        !          1758:            base = index;                                               \
        !          1759:            index = temp;                                               \
        !          1760:          }                                                             \
        !          1761:        base_reg_name = reg_names[REGNO (base)];                        \
        !          1762:        switch (GET_CODE (index))                                       \
        !          1763:          {                                                             \
        !          1764:          case CONST_INT:                                               \
        !          1765:            offset = INTVAL (index);                                    \
        !          1766:            if (is_minus)                                               \
        !          1767:              offset = -offset;                                         \
        !          1768:            fprintf (STREAM, "[%s, #%d]", base_reg_name, offset);       \
        !          1769:            break;                                                      \
        !          1770:                                                                        \
        !          1771:          case REG:                                                     \
        !          1772:            fprintf (STREAM, "[%s, %s%s]", base_reg_name,               \
        !          1773:                     is_minus ? "-" : "", reg_names[REGNO (index)] );   \
        !          1774:            break;                                                      \
        !          1775:                                                                        \
        !          1776:          case MULT:                                                    \
        !          1777:            if (GET_CODE (XEXP (index,0)) == CONST_INT)                 \
        !          1778:              {                                                         \
        !          1779:                shift = int_log2 (INTVAL (XEXP (index, 0)));            \
        !          1780:                index = XEXP (index, 1);                                \
        !          1781:              }                                                         \
        !          1782:            else if (GET_CODE(XEXP(index,1)) == CONST_INT)              \
        !          1783:              {                                                         \
        !          1784:                shift = int_log2 (INTVAL (XEXP (index, 1)));            \
        !          1785:                index = XEXP (index, 0);                                \
        !          1786:              }                                                         \
        !          1787:            else                                                        \
        !          1788:                abort();                                                \
        !          1789:            fprintf (STREAM, "[%s, %s%s, asl #%d]", base_reg_name,      \
        !          1790:                     is_minus ? "-" : "", reg_names[REGNO (index)],     \
        !          1791:                     shift);                                            \
        !          1792:            break;                                                      \
        !          1793:          case ASHIFTRT:                                                \
        !          1794:          case LSHIFTRT:                                                \
        !          1795:          case ASHIFT:                                                  \
        !          1796:          case LSHIFT:                                                  \
        !          1797:          case ROTATERT:                                                \
        !          1798:          {                                                             \
        !          1799:            char *shift_type = shift_instr (GET_CODE (index),           \
        !          1800:                                            &XEXP (index, 1));          \
        !          1801:            shift = INTVAL (XEXP (index, 1));                           \
        !          1802:            index = XEXP (index, 0);                                    \
        !          1803:            fprintf (STREAM, "[%s, %s%s, %s #%d]", base_reg_name,       \
        !          1804:                     is_minus ? "-" : "", reg_names[REGNO (index)],     \
        !          1805:                     shift_type, shift);                                \
        !          1806:            break;                                                      \
        !          1807:          }                                                             \
        !          1808:                                                                        \
        !          1809:          default:                                                      \
        !          1810:            abort();                                                    \
        !          1811:        }                                                               \
        !          1812:     }                                                                  \
        !          1813:   else if (GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_INC         \
        !          1814:           || GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_DEC)      \
        !          1815:     {                                                                  \
        !          1816:       extern int output_memory_reference_mode;                         \
        !          1817:                                                                        \
        !          1818:       if (GET_CODE (XEXP (X, 0)) != REG)                               \
        !          1819:        abort ();                                                       \
        !          1820:                                                                        \
        !          1821:       if (GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC)          \
        !          1822:        fprintf (STREAM, "[%s, #%s%d]!", reg_names[REGNO (XEXP (X, 0))],\
        !          1823:                 GET_CODE (X) == PRE_DEC ? "-" : "",                    \
        !          1824:                 GET_MODE_SIZE (output_memory_reference_mode));         \
        !          1825:       else                                                             \
        !          1826:        fprintf (STREAM, "[%s], #%s%d", reg_names[REGNO (XEXP (X, 0))], \
        !          1827:                 GET_CODE (X) == POST_DEC ? "-" : "",                   \
        !          1828:                 GET_MODE_SIZE (output_memory_reference_mode));         \
        !          1829:     }                                                                  \
        !          1830:   else output_addr_const(STREAM, X);                                   \
        !          1831: }
        !          1832: 
        !          1833: /* EOF arm.h */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.