Annotation of gcc/config/h8300/h8300.c, revision 1.1.1.2

1.1       root        1: /* Subroutines for insn-output.c for Hitachi H8/300.
1.1.1.2 ! root        2:    Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
        !             3:    Contributed by Steve Chamberlain ([email protected]),
        !             4:    Jim Wilson ([email protected]), and Doug Evans ([email protected]).
1.1       root        5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU General Public License as published by
                     10: the Free Software Foundation; either version 2, or (at your option)
                     11: any later version.
                     12: 
                     13: GNU CC is distributed in the hope that it will be useful,
                     14: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: GNU General Public License for more details.
                     17: 
                     18: You should have received a copy of the GNU General Public License
                     19: along with GNU CC; see the file COPYING.  If not, write to
                     20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     21: 
                     22: #include <stdio.h>
                     23: #include "config.h"
                     24: #include "rtl.h"
                     25: #include "regs.h"
                     26: #include "hard-reg-set.h"
                     27: #include "real.h"
                     28: #include "insn-config.h"
                     29: #include "conditions.h"
                     30: #include "insn-flags.h"
                     31: #include "output.h"
                     32: #include "insn-attr.h"
                     33: #include "flags.h"
                     34: #include "recog.h"
                     35: #include "expr.h"
                     36: #include "tree.h"
                     37: 
                     38: /* Forward declarations.  */
                     39: void print_operand_address ();
                     40: char *index ();
                     41: 
1.1.1.2 ! root       42: /* CPU_TYPE, says what cpu we're compiling for.  */
        !            43: int cpu_type;
        !            44: 
1.1       root       45: /* True if a #pragma interrupt has been seen for the current function.  */
                     46: int pragma_interrupt;
                     47: 
                     48: /* True if a #pragma saveall has been seen for the current function.  */
                     49: int pragma_saveall;
                     50: 
1.1.1.2 ! root       51: static char *names_big[] =
        !            52: {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"};
        !            53: 
        !            54: static char *names_extended[] =
        !            55: {"er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"};
        !            56: 
        !            57: static char *names_upper_extended[] =
        !            58: {"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"};
        !            59: 
        !            60: /* Points to one of the above.  */
        !            61: /* ??? The above could be put in an array indexed by CPU_TYPE.  */
        !            62: char **h8_reg_names;
        !            63: 
        !            64: /* Various operations needed by the following, indexed by CPU_TYPE.  */
        !            65: /* ??? The h8/300 assembler doesn't understand pop.w (yet).  */
        !            66: 
        !            67: static char *h8_push_ops[2] =
        !            68: {"push", "push.l"};
        !            69: static char *h8_pop_ops[2] =
        !            70: {"pop", "pop.l"};
        !            71: static char *h8_mov_ops[2] =
        !            72: {"mov.w", "mov.l"};
        !            73: 
        !            74: char *h8_push_op, *h8_pop_op, *h8_mov_op;
        !            75: 
        !            76: /* Initialize various cpu specific globals at start up.  */
        !            77: 
        !            78: void
        !            79: h8300_init_once ()
        !            80: {
        !            81:   if (TARGET_H8300)
        !            82:     {
        !            83:       cpu_type = (int) CPU_H8300;
        !            84:       h8_reg_names = names_big;
        !            85:     }
        !            86:   else
        !            87:     {
        !            88:       cpu_type = (int) CPU_H8300H;
        !            89:       h8_reg_names = names_extended;
        !            90:     }
        !            91:   h8_push_op = h8_push_ops[cpu_type];
        !            92:   h8_pop_op = h8_pop_ops[cpu_type];
        !            93:   h8_mov_op = h8_mov_ops[cpu_type];
        !            94: }
1.1       root       95: 
                     96: char *
                     97: byte_reg (x, b)
                     98:      rtx x;
                     99:      int b;
                    100: {
1.1.1.2 ! root      101:   static char *names_small[] =
        !           102:   {"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
        !           103:    "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7lBAD", "r7hBAD"};
1.1       root      104: 
                    105:   return names_small[REGNO (x) * 2 + b];
                    106: }
                    107: 
                    108: /* REGNO must be saved/restored across calls if this macro is true.  */
1.1.1.2 ! root      109: 
        !           110: #define WORD_REG_USED(regno)                                   \
        !           111:   (regno < 7 &&                                                        \
        !           112:    (pragma_interrupt                                           \
        !           113:     || pragma_saveall                                          \
        !           114:     || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])        \
        !           115:     || (regs_ever_live[regno] & !call_used_regs[regno])))
1.1       root      116: 
                    117: /* Output assembly language to FILE for the operation OP with operand size
1.1.1.2 ! root      118:    SIZE to adjust the stack pointer.  */
        !           119: /* ??? FPED is currently unused.  */
        !           120: 
1.1       root      121: static void
                    122: dosize (file, op, size, fped)
                    123:      FILE *file;
                    124:      char *op;
                    125:      unsigned int size;
                    126:      int fped;
                    127: {
                    128:   switch (size)
                    129:     {
                    130:     case 4:
1.1.1.2 ! root      131:       /* ??? TARGET_H8300H can do this in one insn.  */
1.1       root      132:     case 3:
                    133:       fprintf (file, "\t%ss\t#%d,sp\n", op, 2);
                    134:       size -= 2;
                    135:       /* Fall through...  */
                    136:     case 2:
                    137:     case 1:
                    138:       fprintf (file, "\t%ss\t#%d,sp\n", op, size);
                    139:       size = 0;
                    140:       break;
                    141:     case 0:
                    142:       break;
                    143:     default:
1.1.1.2 ! root      144:       if (TARGET_H8300)
        !           145:        fprintf (file, "\tmov.w\t#%d,r3\n\t%s.w\tr3,sp\n", size, op);
        !           146:       else
        !           147:        fprintf (file, "\t%s\t#%d,sp\n", op, size);
1.1       root      148:       size = 0;
                    149:       break;
                    150:     }
                    151: }
                    152: 
                    153: /* Output assembly language code for the function prologue.  */
1.1.1.2 ! root      154: static int push_order[FIRST_PSEUDO_REGISTER] =
        !           155: {6, 5, 4, 3, 2, 1, 0, -1, -1};
        !           156: static int pop_order[FIRST_PSEUDO_REGISTER] =
        !           157: {0, 1, 2, 3, 4, 5, 6, -1, -1};
1.1       root      158: 
                    159: /* This is what the stack looks like after the prolog of 
                    160:    a function with a frame has been set up:
                    161: 
1.1.1.2 ! root      162:    <args>
        !           163:    PC
        !           164:    FP                  <- fp
        !           165:    <locals>
        !           166:    <saved registers>   <- sp
1.1       root      167: 
                    168:    This is what the stack looks like after the prolog of
                    169:    a function which doesn't have a frame:
                    170: 
1.1.1.2 ! root      171:    <args>
        !           172:    PC
        !           173:    <locals>
        !           174:    <saved registers>           <- sp
1.1       root      175: */
                    176: 
1.1.1.2 ! root      177: int current_function_anonymous_args;
        !           178: 
        !           179: /* Extra arguments to pop, in words (IE: 2 bytes for 300, 4 for 300h */
        !           180: static int extra_pop;
        !           181: 
1.1       root      182: void
                    183: function_prologue (file, size)
                    184:      FILE *file;
                    185:      int size;
                    186: {
                    187:   register int mask = 0;
1.1.1.2 ! root      188:   int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;
1.1       root      189:   int idx;
1.1.1.2 ! root      190:   extra_pop = 0;
        !           191: 
        !           192:   if (current_function_anonymous_args && TARGET_QUICKCALL)
        !           193:     {
        !           194:       /* Push regs as if done by caller, and move around return address.  */
        !           195: 
        !           196:       switch (current_function_args_info.nbytes / UNITS_PER_WORD)
        !           197:        {
        !           198:        case 0:
        !           199:          /* get ret addr */
        !           200:          fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
        !           201:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);
        !           202:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[1]);
        !           203:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[0]);
        !           204:          /* push it again */
        !           205:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);
        !           206:          extra_pop = 3;
        !           207:          break;
        !           208:        case 1:
        !           209:          /* get ret addr */
        !           210:          fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
        !           211:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);
        !           212:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[1]);
        !           213:          /* push it again */
        !           214:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);
        !           215:          extra_pop = 2;
        !           216:          break;
        !           217:        case 2:
        !           218:          /* get ret addr */
        !           219:          fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
        !           220:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);
        !           221:          /* push it again */
        !           222:          fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);
        !           223:          extra_pop = 1;
        !           224:          break;
        !           225:        default:
        !           226:          fprintf (file, "; varargs\n");
        !           227:          break;
        !           228:        }
        !           229:     }
1.1       root      230: 
                    231:   if (frame_pointer_needed)
                    232:     {
1.1.1.2 ! root      233:       /* Push fp */
        !           234:       fprintf (file, "\t%s\t%s\n", h8_push_op,
        !           235:               h8_reg_names[FRAME_POINTER_REGNUM]);
        !           236:       fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,
        !           237:               h8_reg_names[STACK_POINTER_REGNUM],
        !           238:               h8_reg_names[FRAME_POINTER_REGNUM]);
1.1       root      239: 
1.1.1.2 ! root      240:       /* leave room for locals */
1.1       root      241:       dosize (file, "sub", fsize, 1);
                    242: 
1.1.1.2 ! root      243:       /* Push the rest of the registers */
        !           244:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
1.1       root      245:        {
                    246:          int regno = push_order[idx];
                    247: 
1.1.1.2 ! root      248:          if (regno >= 0 && WORD_REG_USED (regno) && regno != FRAME_POINTER_REGNUM)
        !           249:            fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);
1.1       root      250:        }
                    251:     }
                    252:   else
                    253:     {
                    254:       dosize (file, "sub", fsize, 0);
                    255:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
                    256:        {
                    257:          int regno = push_order[idx];
                    258: 
1.1.1.2 ! root      259:          if (regno >= 0 && WORD_REG_USED (regno))
        !           260:            fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);
1.1       root      261:        }
                    262:     }
                    263: }
                    264: 
                    265: /* Output assembly language code for the function epilogue.  */
                    266: 
                    267: void
                    268: function_epilogue (file, size)
                    269:      FILE *file;
                    270:      int size;
                    271: {
                    272:   register int regno;
                    273:   register int mask = 0;
1.1.1.2 ! root      274:   int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;
1.1       root      275:   int nregs;
                    276:   int offset;
                    277:   int idx;
                    278:   rtx insn = get_last_insn ();
                    279: 
                    280:   /* If the last insn was a BARRIER, we don't have to write any code.  */
                    281:   if (GET_CODE (insn) == NOTE)
                    282:     insn = prev_nonnote_insn (insn);
                    283:   if (insn && GET_CODE (insn) == BARRIER)
                    284:     return;
                    285: 
                    286:   nregs = 0;
                    287: 
                    288:   if (frame_pointer_needed)
                    289:     {
1.1.1.2 ! root      290:       /* Pop saved registers */
1.1       root      291:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
                    292:        {
                    293:          regno = pop_order[idx];
1.1.1.2 ! root      294:          if (regno >= 0 && regno != FRAME_POINTER_REGNUM && WORD_REG_USED (regno))
        !           295:            fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);
1.1       root      296:        }
1.1.1.2 ! root      297:       /* deallocate locals */
1.1       root      298:       dosize (file, "add", fsize, 1);
1.1.1.2 ! root      299:       /* pop frame pointer */
        !           300:       fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[FRAME_POINTER_REGNUM]);
1.1       root      301:     }
                    302:   else
                    303:     {
1.1.1.2 ! root      304:       /* pop saved registers */
1.1       root      305:       for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
                    306:        {
                    307:          regno = pop_order[idx];
1.1.1.2 ! root      308:          if (regno >= 0 && WORD_REG_USED (regno))
        !           309:            fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);
1.1       root      310:        }
1.1.1.2 ! root      311:       /* deallocate locals */
1.1       root      312:       dosize (file, "add", fsize, 0);
                    313:     }
1.1.1.2 ! root      314: 
        !           315:   if (extra_pop)
        !           316:     {
        !           317:       fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
        !           318:       while (extra_pop)
        !           319:        {
        !           320:          fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[2]);
        !           321:          extra_pop--;
        !           322:        }
        !           323:       fprintf (file, "\tjmp    @%s\n", h8_reg_names[3]);
        !           324:     }
1.1       root      325:   else
1.1.1.2 ! root      326:     {
        !           327:       if (pragma_interrupt)
        !           328:        fprintf (file, "\trte\n");
        !           329:       else
        !           330:        fprintf (file, "\trts\n");
        !           331:     }
1.1       root      332: 
                    333:   pragma_interrupt = 0;
                    334:   pragma_saveall = 0;
1.1.1.2 ! root      335: 
        !           336:   current_function_anonymous_args = 0;
        !           337: }
        !           338: 
        !           339: /* Output assembly code for the start of the file.  */
        !           340: 
        !           341: asm_file_start (file)
        !           342:      FILE *file;
        !           343: {
        !           344:   fprintf (file, ";\tGCC For the Hitachi H8/300\n");
        !           345:   fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n");
        !           346:   fprintf (file, ";\trelease F-1\n");
        !           347:   if (optimize)
        !           348:     fprintf (file, "; -O%d\n", optimize);
        !           349:   if (TARGET_H8300H)
        !           350:     fprintf (file, "\n\t.h8300h\n");
        !           351:   else
        !           352:     fprintf (file, "\n\n");
        !           353:   output_file_directive (file, main_input_filename);
        !           354: }
        !           355: 
        !           356: /* Output assembly language code for the end of file.  */
        !           357: 
        !           358: void
        !           359: asm_file_end (file)
        !           360:      FILE *file;
        !           361: {
        !           362:   fprintf (file, "\t.end\n");
1.1       root      363: }
                    364: 
1.1.1.2 ! root      365: /* Return true if VALUE is a valid constant for constraint 'P'.
        !           366:    IE: VALUE is a power of two <= 2**15.  */
1.1       root      367: 
                    368: int
1.1.1.2 ! root      369: small_power_of_two (value)
        !           370:      int value;
1.1       root      371: {
                    372:   switch (value)
                    373:     {
                    374:     case 1:
                    375:     case 2:
                    376:     case 4:
                    377:     case 8:
                    378:     case 16:
                    379:     case 32:
                    380:     case 64:
                    381:     case 128:
                    382:     case 256:
                    383:     case 512:
                    384:     case 1024:
                    385:     case 2048:
                    386:     case 4096:
                    387:     case 8192:
                    388:     case 16384:
                    389:     case 32768:
                    390:       return 1;
                    391:     }
                    392:   return 0;
                    393: }
                    394: 
1.1.1.2 ! root      395: /* Return true if VALUE is a valid constant for constraint 'O', which
        !           396:    means that the constant would be ok to use as a bit for a bclr
        !           397:    instruction.  */
        !           398: 
        !           399: int
        !           400: ok_for_bclr (value)
        !           401:      int value;
        !           402: {
        !           403:   return small_power_of_two ((~value) & 0xff);
        !           404: }
        !           405: 
1.1       root      406: /* Return true is OP is a valid source operand for an integer move
                    407:    instruction.  */
1.1.1.2 ! root      408: 
1.1       root      409: int
                    410: general_operand_src (op, mode)
                    411:      rtx op;
                    412:      enum machine_mode mode;
                    413: {
1.1.1.2 ! root      414:   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
        !           415:     return 1;
1.1       root      416:   return general_operand (op, mode);
                    417: }
                    418: 
                    419: /* Return true if OP is a valid destination operand for an integer move
                    420:    instruction.  */
1.1.1.2 ! root      421: 
1.1       root      422: int
                    423: general_operand_dst (op, mode)
                    424:      rtx op;
                    425:      enum machine_mode mode;
                    426: {
1.1.1.2 ! root      427:   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC)
        !           428:     return 1;
1.1       root      429:   return general_operand (op, mode);
                    430: }
1.1.1.2 ! root      431: 
        !           432: /* Return true if OP is a const valid for a bit clear instruction.  */
        !           433: 
        !           434: int
        !           435: o_operand (operand, mode)
        !           436:      rtx operand;
        !           437:      enum machine_mode mode;
        !           438: {
        !           439:   return (GET_CODE (operand) == CONST_INT
        !           440:          && CONST_OK_FOR_O (INTVAL (operand)));
        !           441: }
        !           442: 
        !           443: /* Return true if OP is a const valid for a bit set or bit xor instruction.  */
        !           444: 
        !           445: int
        !           446: p_operand (operand, mode)
        !           447:      rtx operand;
        !           448:      enum machine_mode mode;
        !           449: {
        !           450:   return (GET_CODE (operand) == CONST_INT
        !           451:          && CONST_OK_FOR_P (INTVAL (operand)));
        !           452: }
        !           453: 
        !           454: /* Return true if OP is a valid call operand.  */
        !           455: 
        !           456: int
        !           457: call_insn_operand (op, mode)
        !           458:      rtx op;
        !           459:      enum machine_mode mode;
        !           460: {
        !           461:   if (GET_CODE (op) == MEM)
        !           462:     {
        !           463:       rtx inside = XEXP (op, 0);
        !           464:       if (register_operand (inside, Pmode))
        !           465:        return 1;
        !           466:       if (CONSTANT_ADDRESS_P (inside))
        !           467:        return 1;
        !           468:     }
        !           469:   return 0;
        !           470: }
        !           471: 
        !           472: /* Return true if OP is a valid jump operand.  */
        !           473: 
        !           474: int
        !           475: jump_address_operand (op, mode)
        !           476:      rtx op;
        !           477:      enum machine_mode mode;
        !           478: {
        !           479:   if (GET_CODE (op) == REG)
        !           480:     return mode == Pmode;
        !           481: 
        !           482:   if (GET_CODE (op) == MEM)
        !           483:     {
        !           484:       rtx inside = XEXP (op, 0);
        !           485:       if (register_operand (inside, Pmode))
        !           486:        return 1;
        !           487:       if (CONSTANT_ADDRESS_P (inside))
        !           488:        return 1;
        !           489:     }
        !           490:   return 0;
        !           491: }
        !           492: 
        !           493: /* Recognize valid operands for bitfield instructions.  */
        !           494: 
        !           495: extern int rtx_equal_function_value_matters;
        !           496: 
        !           497: int
        !           498: bit_operand (op, mode)
        !           499:      rtx op;
        !           500:      enum machine_mode mode;
        !           501: {
        !           502:   /* We can except any general operand, expept that MEM operands must
        !           503:      be limited to those that use addresses valid for the 'U' constraint.  */
        !           504:   if (!general_operand (op, mode))
        !           505:     return 0;
        !           506: 
        !           507:   /* Accept any mem during RTL generation.  Otherwise, the code that does
        !           508:      insv and extzv will think that we can not handle memory.  However,
        !           509:      to avoid reload problems, we only accept 'U' MEM operands after RTL
        !           510:      generation.  This means that any named pattern which uses this predicate
        !           511:      must force its operands to match 'U' before emitting RTL.  */
        !           512: 
        !           513:   if (GET_CODE (op) == REG)
        !           514:     return 1;
        !           515:   if (GET_CODE (op) == SUBREG)
        !           516:     return 1;
        !           517:   if (!rtx_equal_function_value_matters)
        !           518:     {
        !           519:       /* We're building rtl */
        !           520:       return GET_CODE (op) == MEM;
        !           521:     }
        !           522:   else
        !           523:     {
        !           524:       return (GET_CODE (op) == MEM
        !           525:              && EXTRA_CONSTRAINT (op, 'U'));
        !           526:     }
        !           527: }
        !           528: 
        !           529: /* Recognize valid operators for bit test.  */
        !           530: 
        !           531: int
        !           532: eq_operator (x, mode)
        !           533:      rtx x;
        !           534:      enum machine_mode mode;
        !           535: {
        !           536:   return (GET_CODE (x) == EQ || GET_CODE (x) == NE);
        !           537: }
        !           538: 
1.1       root      539: /* Handle machine specific pragmas for compatibility with existing
1.1.1.2 ! root      540:    compilers for the H8/300.
1.1       root      541: 
                    542:    pragma saveall generates prolog/epilog code which saves and
                    543:    restores all the registers on function entry.
1.1.1.2 ! root      544: 
1.1       root      545:    pragma interrupt saves and restores all registers, and exits with
                    546:    an rte instruction rather than an rts.  A pointer to a function
                    547:    with this attribute may be safely used in an interrupt vector.  */
1.1.1.2 ! root      548: 
1.1       root      549: int
                    550: handle_pragma (file)
                    551:      FILE *file;
                    552: {
                    553:   int c;
                    554:   char pbuf[20];
1.1.1.2 ! root      555:   int psize = 0;
1.1       root      556: 
                    557:   c = getc (file);
                    558:   while (c == ' ' || c == '\t')
                    559:     c = getc (file);
                    560: 
                    561:   if (c == '\n' || c == EOF)
                    562:     return c;
                    563: 
1.1.1.2 ! root      564:   /* The only pragmas we understand are interrupt and saveall.  */
        !           565:   while (psize < sizeof (pbuf) - 1
        !           566:         && isalpha (c))
1.1       root      567:     {
1.1.1.2 ! root      568:       pbuf[psize++] = c;
1.1       root      569:       c = getc (file);
                    570:     }
                    571:   pbuf[psize] = 0;
                    572: 
                    573:   if (strcmp (pbuf, "interrupt") == 0)
                    574:     pragma_interrupt = 1;
                    575: 
                    576:   if (strcmp (pbuf, "saveall") == 0)
                    577:     pragma_saveall = 1;
                    578: 
1.1.1.2 ! root      579:   /* ??? This is deprecated.  Use section attributes.  */
        !           580:   if (strcmp (pbuf, "section") == 0)
        !           581:     {
        !           582:       while (c && !isalpha (c))
        !           583:        c = getc (file);
        !           584:       psize = 0;
        !           585:       while (psize < sizeof (pbuf) - 1
        !           586:             && isalpha (c) || isdigit (c) || c == '_')
        !           587:        {
        !           588:          pbuf[psize++] = c;
        !           589:          c = getc (file);
        !           590:        }
        !           591:       pbuf[psize] = 0;
        !           592:       named_section (pbuf);
        !           593:     }
        !           594:   ungetc (c, file);
1.1       root      595:   return c;
                    596: }
                    597: 
                    598: /* If the next arg with MODE and TYPE is to be passed in a register, return
                    599:    the rtx to represent where it is passed.  CUM represents the state after
                    600:    the last argument.  NAMED is not used.  */
                    601: 
1.1.1.2 ! root      602: static char *hand_list[] =
        !           603: {
        !           604:   "__main",
        !           605:   "__cmpsi2",
        !           606:   "__divhi3",
        !           607:   "__modhi3",
        !           608:   "__udivhi3",
        !           609:   "__umodhi3",
        !           610:   "__divsi3",
        !           611:   "__modsi3",
        !           612:   "__udivsi3",
        !           613:   "__umodsi3",
        !           614:   "__mulhi3",
        !           615:   "__mulsi3",
        !           616:   "__reg_memcpy",
        !           617:   "__reg_memset",
        !           618:   "__ucmpsi2",
        !           619:   0,
        !           620: };
        !           621: 
        !           622: /* Return an RTX to represent where a value with mode MODE will be returned
        !           623:    from a function.  If the result is 0, the argument is pushed.  */
        !           624: 
1.1       root      625: rtx
                    626: function_arg (cum, mode, type, named)
                    627:      CUMULATIVE_ARGS *cum;
                    628:      enum machine_mode mode;
                    629:      tree type;
                    630:      int named;
                    631: {
                    632:   rtx result = 0;
1.1.1.2 ! root      633:   char *fname;
        !           634:   int regpass = 0;
        !           635: 
        !           636:   /* Pass 3 regs worth of data in regs when user asked on the command line.  */
        !           637:   if (TARGET_QUICKCALL)
        !           638:     regpass = 3;
        !           639: 
        !           640:   /* If calling hand written assembler, use 4 regs of args.  */
        !           641: 
        !           642:   if (cum->libcall)
        !           643:     {
        !           644:       char **p;
        !           645: 
        !           646:       fname = XSTR (cum->libcall, 0);
        !           647: 
        !           648:       /* See if this libcall is one of the hand coded ones.  */
1.1       root      649: 
1.1.1.2 ! root      650:       for (p = hand_list; *p && strcmp (*p, fname) != 0; p++)
        !           651:        ;
1.1       root      652: 
1.1.1.2 ! root      653:       if (*p)
        !           654:        regpass = 4;
        !           655:     }
        !           656: 
        !           657:   if (regpass)
        !           658:     {
        !           659:       int size;
        !           660: 
        !           661:       if (mode == BLKmode)
        !           662:        size = int_size_in_bytes (type);
        !           663:       else
        !           664:        size = GET_MODE_SIZE (mode);
        !           665: 
        !           666:       if (size + cum->nbytes > regpass * UNITS_PER_WORD)
        !           667:        {
        !           668:          result = 0;
        !           669:        }
        !           670:       else
        !           671:        {
        !           672:          switch (cum->nbytes / UNITS_PER_WORD)
        !           673:            {
        !           674:            case 0:
        !           675:              result = gen_rtx (REG, mode, 0);
        !           676:              break;
        !           677:            case 1:
        !           678:              result = gen_rtx (REG, mode, 1);
        !           679:              break;
        !           680:            case 2:
        !           681:              result = gen_rtx (REG, mode, 2);
        !           682:              break;
        !           683:            case 3:
        !           684:              result = gen_rtx (REG, mode, 3);
        !           685:              break;
        !           686:            default:
        !           687:              result = 0;
        !           688:            }
        !           689:        }
        !           690:     }
1.1       root      691: 
1.1.1.2 ! root      692:   return result;
        !           693: }
        !           694: 
        !           695: /* Return the cost of the rtx R with code CODE.  */
1.1       root      696: 
1.1.1.2 ! root      697: int
        !           698: const_costs (r, c)
        !           699:      rtx r;
        !           700:      enum rtx_code c;
        !           701: {
        !           702:   switch (c)
1.1       root      703:     {
1.1.1.2 ! root      704:     case CONST_INT:
        !           705:       switch (INTVAL (r))
1.1       root      706:        {
                    707:        case 0:
1.1.1.2 ! root      708:        case 1:
1.1       root      709:        case 2:
1.1.1.2 ! root      710:        case -1:
        !           711:        case -2:
1.1       root      712:          return 0;
1.1.1.2 ! root      713:        default:
        !           714:          return 1;
1.1       root      715:        }
1.1.1.2 ! root      716: 
        !           717:     case CONST:
        !           718:     case LABEL_REF:
        !           719:     case SYMBOL_REF:
        !           720:       return 3;
        !           721: 
        !           722:     case CONST_DOUBLE:
        !           723:       return 20;
        !           724: 
        !           725:     default:
        !           726:       return 4;
1.1       root      727:     }
                    728: }
1.1.1.2 ! root      729: 
1.1       root      730: /* Documentation for the machine specific operand escapes:
                    731: 
1.1.1.2 ! root      732:    'A' print rn in h8/300 mode, erN in H8/300H mode
1.1       root      733:    'C' print (operand - 2).
1.1.1.2 ! root      734:    'E' like s but negative.
        !           735:    'F' like t but negative.
        !           736:    'G' constant just the negative
1.1       root      737:    'L' fake label, changed after used twice.
                    738:    'M' turn a 'M' constant into its negative mod 2.
1.1.1.2 ! root      739:    'P' if operand is incing/decing sp, print .w, otherwise .b.
        !           740:    'S' print operand as a long word
1.1       root      741:    'T' print operand as a word
1.1.1.2 ! root      742:    'U' if operand is incing/decing sp, print l, otherwise nothing.
        !           743:    'V' find the set bit, and print its number.
        !           744:    'W' find the clear bit, and print its number.
        !           745:    'X' print operand as a byte
1.1       root      746:    'Y' print either l or h depending on whether last 'Z' operand < 8 or >= 8.
1.1.1.2 ! root      747:    'Z' print int & 7.
        !           748:    'b' print the bit opcode
        !           749:    'c' print the ibit opcode
        !           750:    'd' bcc if EQ, bcs if NE
        !           751:    'e' first word of 32 bit value - if reg, then least reg. if mem
        !           752:        then least. if const then most sig word
        !           753:    'f' second word of 32 bit value - if reg, then biggest reg. if mem
        !           754:        then +2. if const then least sig word
        !           755:    'g' bcs if EQ, bcc if NE
1.1       root      756:    'j' print operand as condition code.
                    757:    'k' print operand as reverse condition code.
1.1.1.2 ! root      758:    's' print as low byte of 16 bit value
        !           759:    't' print as high byte of 16 bit value
        !           760:    'w' print as low byte of 32 bit value
        !           761:    'x' print as 2nd byte of 32 bit value
        !           762:    'y' print as 3rd byte of 32 bit value
        !           763:    'z' print as msb of 32 bit value
        !           764: */
1.1       root      765: 
                    766: /* Return assembly language string which identifies a comparison type.  */
                    767: 
1.1.1.2 ! root      768: static char *
1.1       root      769: cond_string (code)
                    770:      enum rtx_code code;
                    771: {
                    772:   switch (code)
                    773:     {
                    774:     case NE:
1.1.1.2 ! root      775:       if (cc_prev_status.flags & CC_DONE_CBIT)
        !           776:        return "cs";
1.1       root      777:       return "ne";
                    778:     case EQ:
1.1.1.2 ! root      779:       if (cc_prev_status.flags & CC_DONE_CBIT)
        !           780:        return "cc";
1.1       root      781:       return "eq";
                    782:     case GE:
                    783:       return "ge";
                    784:     case GT:
                    785:       return "gt";
                    786:     case LE:
                    787:       return "le";
                    788:     case LT:
                    789:       return "lt";
                    790:     case GEU:
                    791:       return "hs";
                    792:     case GTU:
                    793:       return "hi";
                    794:     case LEU:
                    795:       return "ls";
                    796:     case LTU:
                    797:       return "lo";
                    798:     default:
                    799:       abort ();
                    800:     }
                    801: }
                    802: 
                    803: /* Print operand X using operand code CODE to assembly language output file
                    804:    FILE.  */
                    805: 
                    806: void
                    807: print_operand (file, x, code)
                    808:      FILE *file;
                    809:      rtx x;
                    810:      int code;
                    811: {
                    812:   /* This is used to general unique labels for the 'L' code.  */
                    813:   static int lab = 1000;
                    814: 
                    815:   /* This is used for communication between the 'P' and 'U' codes.  */
                    816:   static char *last_p;
                    817: 
                    818:   /* This is used for communication between the 'Z' and 'Y' codes.  */
1.1.1.2 ! root      819:   /* ??? 'V' and 'W' use it too.  */
1.1       root      820:   static int bitint;
                    821: 
                    822:   switch (code)
                    823:     {
1.1.1.2 ! root      824:     case 'A':
1.1       root      825:       if (GET_CODE (x) == REG)
1.1.1.2 ! root      826:        fprintf (file, "%s", h8_reg_names[REGNO (x)]);
1.1       root      827:       else
                    828:        goto def;
                    829:       break;
1.1.1.2 ! root      830:     case 'C':
        !           831:       fprintf (file, "#%d", INTVAL (x) - 2);
        !           832:       break;
        !           833:     case 'E':
        !           834:       switch (GET_CODE (x))
        !           835:        {
        !           836:        case REG:
        !           837:          fprintf (file, "%sl", names_big[REGNO (x)]);
        !           838:          break;
        !           839:        case CONST_INT:
        !           840:          fprintf (file, "#%d", (-INTVAL (x)) & 0xff);
        !           841:          break;
        !           842:        default:
        !           843:          abort ();
        !           844:        }
        !           845:       break;
        !           846:     case 'F':
        !           847:       switch (GET_CODE (x))
        !           848:        {
        !           849:        case REG:
        !           850:          fprintf (file, "%sh", names_big[REGNO (x)]);
        !           851:          break;
        !           852:        case CONST_INT:
        !           853:          fprintf (file, "#%d", ((-INTVAL (x)) & 0xff00) >> 8);
        !           854:          break;
        !           855:        default:
        !           856:          abort ();
        !           857:        }
        !           858:       break;
1.1       root      859:     case 'G':
                    860:       if (GET_CODE (x) != CONST_INT)
                    861:        abort ();
                    862:       fprintf (file, "#%d", 0xff & (-INTVAL (x)));
                    863:       break;
1.1.1.2 ! root      864:     case 'L':
        !           865:       /* 'L' must always be used twice in a single pattern.  It generates
        !           866:         the same lable twice, and then will generate a unique label the
        !           867:         next time it is used.  */
        !           868:       asm_fprintf (file, "tl%d", (lab++) / 2);
1.1       root      869:       break;
1.1.1.2 ! root      870:     case 'M':
        !           871:       /* For 3/-3 and 4/-4, the other 2 is handled separately.  */
        !           872:       switch (INTVAL (x))
        !           873:        {
        !           874:        case 2:
        !           875:        case 4:
        !           876:        case -2:
        !           877:        case -4:
        !           878:          fprintf (file, "#2");
        !           879:          break;
        !           880:        case 1:
        !           881:        case 3:
        !           882:        case -1:
        !           883:        case -3:
        !           884:          fprintf (file, "#1");
        !           885:          break;
        !           886:        default:
        !           887:          abort ();
        !           888:        }
1.1       root      889:       break;
1.1.1.2 ! root      890:     case 'P':
        !           891:       if (REGNO (XEXP (XEXP (x, 0), 0)) == STACK_POINTER_REGNUM)
        !           892:        {
        !           893:          last_p = "";
        !           894:          fprintf (file, ".w");
        !           895:        }
1.1       root      896:       else
1.1.1.2 ! root      897:        {
        !           898:          last_p = "l";
        !           899:          fprintf (file, ".b");
        !           900:        }
1.1       root      901:       break;
1.1.1.2 ! root      902:     case 'S':
        !           903:       if (GET_CODE (x) == REG)
        !           904:        fprintf (file, "%s", names_extended[REGNO (x)]);
1.1       root      905:       else
1.1.1.2 ! root      906:        goto def;
1.1       root      907:       break;
1.1.1.2 ! root      908:     case 'T':
        !           909:       if (GET_CODE (x) == REG)
        !           910:        fprintf (file, "%s", names_big[REGNO (x)]);
1.1       root      911:       else
1.1.1.2 ! root      912:        goto def;
1.1       root      913:       break;
1.1.1.2 ! root      914:     case 'U':
        !           915:       fprintf (file, "%s%s", names_big[REGNO (x)], last_p);
1.1       root      916:       break;
1.1.1.2 ! root      917:     case 'V':
        !           918:       bitint = exact_log2 (INTVAL (x));
        !           919:       if (bitint == -1)
1.1       root      920:        abort ();
                    921:       fprintf (file, "#%d", bitint & 7);
                    922:       break;
1.1.1.2 ! root      923:     case 'W':
1.1       root      924:       bitint = exact_log2 ((~INTVAL (x)) & 0xff);
                    925:       if (bitint == -1)
                    926:        abort ();
                    927:       fprintf (file, "#%d", bitint & 7);
                    928:       break;
1.1.1.2 ! root      929:     case 'X':
        !           930:       if (GET_CODE (x) == REG)
        !           931:        fprintf (file, "%s", byte_reg (x, 0));
        !           932:       else
        !           933:        goto def;
        !           934:       break;
        !           935:     case 'Y':
1.1       root      936:       if (bitint == -1)
                    937:        abort ();
1.1.1.2 ! root      938:       if (GET_CODE (x) == REG)
        !           939:        fprintf (file, "%s%c", names_big[REGNO (x)], bitint > 7 ? 'h' : 'l');
        !           940:       else
        !           941:        print_operand (file, x, 0);
        !           942:       bitint = -1;
        !           943:       break;
        !           944:     case 'Z':
        !           945:       bitint = INTVAL (x);
1.1       root      946:       fprintf (file, "#%d", bitint & 7);
                    947:       break;
1.1.1.2 ! root      948:     case 'b':
        !           949:       switch (GET_CODE (x))
1.1       root      950:        {
1.1.1.2 ! root      951:        case IOR:
        !           952:          fprintf (file, "bor");
        !           953:          break;
        !           954:        case XOR:
        !           955:          fprintf (file, "bxor");
        !           956:          break;
        !           957:        case AND:
        !           958:          fprintf (file, "band");
        !           959:          break;
1.1       root      960:        }
1.1.1.2 ! root      961:       break;
        !           962:     case 'c':
        !           963:       switch (GET_CODE (x))
1.1       root      964:        {
1.1.1.2 ! root      965:        case IOR:
        !           966:          fprintf (file, "bior");
        !           967:          break;
        !           968:        case XOR:
        !           969:          fprintf (file, "bixor");
        !           970:          break;
        !           971:        case AND:
        !           972:          fprintf (file, "biand");
        !           973:          break;
1.1       root      974:        }
                    975:       break;
1.1.1.2 ! root      976:     case 'd':
        !           977:       switch (GET_CODE (x))
1.1       root      978:        {
1.1.1.2 ! root      979:        case EQ:
        !           980:          fprintf (file, "bcc");
1.1       root      981:          break;
1.1.1.2 ! root      982:        case NE:
        !           983:          fprintf (file, "bcs");
1.1       root      984:          break;
                    985:        default:
                    986:          abort ();
                    987:        }
                    988:       break;
                    989:     case 'e':
                    990:       switch (GET_CODE (x))
                    991:        {
                    992:        case REG:
1.1.1.2 ! root      993:          if (TARGET_H8300)
        !           994:            fprintf (file, "%s", names_big[REGNO (x)]);
        !           995:          else
        !           996:            fprintf (file, "%s", names_upper_extended[REGNO (x)]);
1.1       root      997:          break;
                    998:        case MEM:
                    999:          x = adj_offsettable_operand (x, 0);
                   1000:          print_operand (file, x, 0);
                   1001:          break;
                   1002:        case CONST_INT:
                   1003:          fprintf (file, "#%d", ((INTVAL (x) >> 16) & 0xffff));
                   1004:          break;
                   1005:        default:
                   1006:          abort ();
                   1007:          break;
                   1008:        }
                   1009:       break;
                   1010:     case 'f':
                   1011:       switch (GET_CODE (x))
                   1012:        {
                   1013:        case REG:
1.1.1.2 ! root     1014:          if (TARGET_H8300)
        !          1015:            fprintf (file, "%s", names_big[REGNO (x) + 1]);
        !          1016:          else
        !          1017:            fprintf (file, "%s", names_big[REGNO (x)]);
1.1       root     1018:          break;
                   1019:        case MEM:
                   1020:          x = adj_offsettable_operand (x, 2);
                   1021:          print_operand (file, x, 0);
                   1022:          break;
                   1023:        case CONST_INT:
                   1024:          fprintf (file, "#%d", INTVAL (x) & 0xffff);
                   1025:          break;
                   1026:        default:
                   1027:          abort ();
                   1028:        }
                   1029:       break;
1.1.1.2 ! root     1030:     case 'g':
1.1       root     1031:       switch (GET_CODE (x))
                   1032:        {
1.1.1.2 ! root     1033:        case NE:
        !          1034:          fprintf (file, "bcc");
1.1       root     1035:          break;
1.1.1.2 ! root     1036:        case EQ:
        !          1037:          fprintf (file, "bcs");
1.1       root     1038:          break;
                   1039:        default:
                   1040:          abort ();
                   1041:        }
                   1042:       break;
                   1043:     case 'j':
                   1044:       asm_fprintf (file, cond_string (GET_CODE (x)));
                   1045:       break;
                   1046:     case 'k':
                   1047:       asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
                   1048:       break;
1.1.1.2 ! root     1049:     case 's':
        !          1050:       if (GET_CODE (x) == CONST_INT)
        !          1051:        fprintf (file, "#%d", (INTVAL (x)) & 0xff);
        !          1052:       else
        !          1053:        fprintf (file, "%s", byte_reg (x, 0));
        !          1054:       break;
        !          1055:     case 't':
        !          1056:       if (GET_CODE (x) == CONST_INT)
        !          1057:        fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
        !          1058:       else
        !          1059:        fprintf (file, "%s", byte_reg (x, 1));
        !          1060:       break;
        !          1061:     case 'u':
        !          1062:       if (GET_CODE (x) != CONST_INT)
        !          1063:        abort ();
        !          1064:       fprintf (file, "%d", INTVAL (x));
        !          1065:       break;
        !          1066:     case 'w':
        !          1067:       if (GET_CODE (x) == CONST_INT)
        !          1068:        fprintf (file, "#%d", INTVAL (x) & 0xff);
        !          1069:       else
        !          1070:        fprintf (file, "%s", byte_reg (x, TARGET_H8300 ? 2 : 0));
        !          1071:       break;
        !          1072:     case 'x':
        !          1073:       if (GET_CODE (x) == CONST_INT)
        !          1074:        fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
        !          1075:       else
        !          1076:        fprintf (file, "%s", byte_reg (x, TARGET_H8300 ? 3 : 1));
        !          1077:       break;
        !          1078:     case 'y':
        !          1079:       if (GET_CODE (x) == CONST_INT)
        !          1080:        fprintf (file, "#%d", (INTVAL (x) >> 16) & 0xff);
        !          1081:       else
        !          1082:        fprintf (file, "%s", byte_reg (x, 0));
        !          1083:       break;
        !          1084:     case 'z':
        !          1085:       if (GET_CODE (x) == CONST_INT)
        !          1086:        fprintf (file, "#%d", (INTVAL (x) >> 24) & 0xff);
        !          1087:       else
        !          1088:        fprintf (file, "%s", byte_reg (x, 1));
        !          1089:       break;
        !          1090: 
1.1       root     1091:     default:
1.1.1.2 ! root     1092:     def:
1.1       root     1093:       switch (GET_CODE (x))
                   1094:        {
                   1095:        case REG:
1.1.1.2 ! root     1096:          switch (GET_MODE (x))
        !          1097:            {
        !          1098:            case QImode:
        !          1099: #if 0                          /* Is it asm ("mov.b %0,r2l", ...) */
        !          1100:              fprintf (file, "%s", byte_reg (x, 0));
        !          1101: #else /* ... or is it asm ("mov.b %0l,r2l", ...) */
        !          1102:              fprintf (file, "%s", names_big[REGNO (x)]);
        !          1103: #endif
        !          1104:              break;
        !          1105:            case HImode:
        !          1106:              fprintf (file, "%s", names_big[REGNO (x)]);
        !          1107:              break;
        !          1108:            case SImode:
        !          1109:            case SFmode:
        !          1110:              fprintf (file, "%s", names_extended[REGNO (x)]);
        !          1111:              break;
        !          1112:            default:
        !          1113:              abort ();
        !          1114:            }
1.1       root     1115:          break;
                   1116: 
                   1117:        case MEM:
                   1118:          fprintf (file, "@");
                   1119:          output_address (XEXP (x, 0));
                   1120:          break;
                   1121: 
                   1122:        case CONST_INT:
                   1123:        case SYMBOL_REF:
                   1124:        case CONST:
                   1125:        case LABEL_REF:
                   1126:          fprintf (file, "#");
                   1127:          print_operand_address (file, x);
                   1128:          break;
                   1129:        }
                   1130:     }
                   1131: }
                   1132: 
                   1133: /* Output assembly language output for the address ADDR to FILE.  */
                   1134: 
                   1135: void
                   1136: print_operand_address (file, addr)
                   1137:      FILE *file;
                   1138:      rtx addr;
                   1139: {
                   1140:   switch (GET_CODE (addr))
                   1141:     {
                   1142:     case REG:
1.1.1.2 ! root     1143:       fprintf (file, "%s", h8_reg_names[REGNO (addr)]);
1.1       root     1144:       break;
                   1145: 
                   1146:     case PRE_DEC:
1.1.1.2 ! root     1147:       fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]);
1.1       root     1148:       break;
                   1149: 
                   1150:     case POST_INC:
1.1.1.2 ! root     1151:       fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]);
1.1       root     1152:       break;
                   1153: 
                   1154:     case PLUS:
                   1155:       fprintf (file, "(");
                   1156:       if (GET_CODE (XEXP (addr, 0)) == REG)
                   1157:        {
                   1158:          /* reg,foo */
                   1159:          print_operand_address (file, XEXP (addr, 1));
                   1160:          fprintf (file, ",");
                   1161:          print_operand_address (file, XEXP (addr, 0));
                   1162:        }
                   1163:       else
                   1164:        {
                   1165:          /* foo+k */
                   1166:          print_operand_address (file, XEXP (addr, 0));
                   1167:          fprintf (file, "+");
                   1168:          print_operand_address (file, XEXP (addr, 1));
                   1169:        }
                   1170:       fprintf (file, ")");
                   1171:       break;
                   1172: 
                   1173:     case CONST_INT:
1.1.1.2 ! root     1174:       {
        !          1175:        /* Since the h8/300 only has 16 bit pointers, negative values are also
        !          1176:           those >= 32768.  This happens for example with pointer minus a
        !          1177:           constant.  We don't want to turn (char *p - 2) into
        !          1178:           (char *p + 65534) because loop unrolling can build upon this
        !          1179:           (IE: char *p + 131068).  */
        !          1180:        int n = INTVAL (addr);
        !          1181:        if (TARGET_H8300)
        !          1182:          n = (int) (short) n;
        !          1183:        if (n < 0)
        !          1184:          /* ??? Why the special case for -ve values? */
        !          1185:          fprintf (file, "-%d", -n);
        !          1186:        else
        !          1187:          fprintf (file, "%d", n);
        !          1188:        break;
        !          1189:       }
1.1       root     1190: 
                   1191:     default:
                   1192:       output_addr_const (file, addr);
                   1193:       break;
                   1194:     }
                   1195: }
                   1196: 
                   1197: /* Output all insn addresses and their sizes into the assembly language
                   1198:    output file.  This is helpful for debugging whether the length attributes
                   1199:    in the md file are correct.  This is not meant to be a user selectable
                   1200:    option.  */
                   1201: 
                   1202: void
                   1203: final_prescan_insn (insn, operand, num_operands)
                   1204:      rtx insn, *operand;
                   1205:      int num_operands;
                   1206: {
                   1207:   /* This holds the last insn address.  */
                   1208:   static int last_insn_address = 0;
                   1209: 
                   1210:   int uid = INSN_UID (insn);
                   1211: 
1.1.1.2 ! root     1212:   if (TARGET_RTL_DUMP)
        !          1213:     {
        !          1214:       fprintf (asm_out_file, "\n****************");
        !          1215:       print_rtl (asm_out_file, PATTERN (insn));
        !          1216:       fprintf (asm_out_file, "\n");
        !          1217:     }
        !          1218: 
1.1       root     1219:   if (TARGET_ADDRESSES)
                   1220:     {
1.1.1.2 ! root     1221:       fprintf (asm_out_file, "; 0x%x %d\n", insn_addresses[uid],
1.1       root     1222:               insn_addresses[uid] - last_insn_address);
                   1223:       last_insn_address = insn_addresses[uid];
                   1224:     }
                   1225: }
                   1226: 
1.1.1.2 ! root     1227: /* Prepare for an SI sized move.  */
        !          1228: 
        !          1229: int
        !          1230: do_movsi (operands)
        !          1231:      rtx operands[];
        !          1232: {
        !          1233:   rtx src = operands[1];
        !          1234:   rtx dst = operands[0];
        !          1235:   if (!reload_in_progress && !reload_completed)
        !          1236:     {
        !          1237:       if (!register_operand (dst, GET_MODE (dst)))
        !          1238:        {
        !          1239:          rtx tmp = gen_reg_rtx (GET_MODE (dst));
        !          1240:          emit_move_insn (tmp, src);
        !          1241:          operands[1] = tmp;
        !          1242:        }
        !          1243:     }
        !          1244:   return 0;
        !          1245: }
        !          1246: 
        !          1247: /* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).
        !          1248:    Define the offset between two registers, one to be eliminated, and the other
        !          1249:    its replacement, at the start of a routine.  */
        !          1250: 
        !          1251: int
        !          1252: initial_offset (from, to)
1.1       root     1253: {
1.1.1.2 ! root     1254:   int offset = 0;
1.1       root     1255: 
1.1.1.2 ! root     1256:   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
        !          1257:     offset = UNITS_PER_WORD + frame_pointer_needed * UNITS_PER_WORD;
        !          1258:   else
1.1       root     1259:     {
1.1.1.2 ! root     1260:       int regno;
        !          1261: 
        !          1262:       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
        !          1263:        if ((regs_ever_live[regno]
        !          1264:             && (!call_used_regs[regno] || regno == FRAME_POINTER_REGNUM)))
        !          1265:          offset += UNITS_PER_WORD;
        !          1266: 
        !          1267:       /* See the comments for get_frame_size.  We need to round it up to
        !          1268:         STACK_BOUNDARY.  */
        !          1269: 
        !          1270:       offset += ((get_frame_size () + STACK_BOUNDARY / BITS_PER_UNIT - 1)
        !          1271:                 & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
        !          1272: 
        !          1273:       if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
        !          1274:        offset += UNITS_PER_WORD;       /* Skip saved PC */
1.1       root     1275:     }
1.1.1.2 ! root     1276:   return offset;
        !          1277: }
1.1       root     1278: 
1.1.1.2 ! root     1279: /* Update the condition code from the insn.  */
        !          1280: 
        !          1281: int
        !          1282: notice_update_cc (body, insn)
        !          1283:      rtx body;
        !          1284:      rtx insn;
        !          1285: {
        !          1286:   switch (get_attr_cc (insn))
        !          1287:     {
        !          1288:     case CC_NONE:
        !          1289:       /* Insn does not affect the CC at all */
        !          1290:       break;
        !          1291: 
        !          1292:     case CC_NONE_0HIT:
        !          1293:       /* Insn does not change the CC, but the 0't operand has been changed.  */
        !          1294: 
        !          1295:       if (cc_status.value1 != 0
        !          1296:          && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
        !          1297:        cc_status.value1 = 0;
        !          1298: 
        !          1299:       if (cc_status.value2 != 0
        !          1300:          && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
        !          1301:        cc_status.value2 = 0;
        !          1302: 
        !          1303:       break;
        !          1304: 
        !          1305:     case CC_SET:
        !          1306:       /* Insn sets CC to recog_operand[0], but overflow is impossible.  */
        !          1307:       CC_STATUS_INIT;
        !          1308:       cc_status.flags |= CC_NO_OVERFLOW;
        !          1309:       cc_status.value1 = recog_operand[0];
        !          1310:       break;
        !          1311: 
        !          1312:     case CC_COMPARE:
        !          1313:       /* The insn is a compare instruction */
        !          1314:       CC_STATUS_INIT;
        !          1315:       cc_status.value1 = SET_SRC (body);
        !          1316:       break;
        !          1317: 
        !          1318:     case CC_CBIT:
        !          1319:       CC_STATUS_INIT;
        !          1320:       cc_status.flags |= CC_DONE_CBIT;
        !          1321:       cc_status.value1 = 0;
        !          1322:       break;
        !          1323: 
        !          1324:     case CC_WHOOPS:
        !          1325:     case CC_CLOBBER:
        !          1326:       /* Insn clobbers CC. */
        !          1327:       CC_STATUS_INIT;
        !          1328:       break;
        !          1329:     }
1.1       root     1330: }
                   1331: 
1.1.1.2 ! root     1332: /* Recognize valid operators for bit instructions */
        !          1333: 
1.1       root     1334: int
1.1.1.2 ! root     1335: bit_operator (x, mode)
        !          1336:      rtx x;
        !          1337:      enum machine_mode mode;
        !          1338: {
        !          1339:   enum rtx_code code = GET_CODE (x);
        !          1340: 
        !          1341:   return (code == XOR
        !          1342:          || code == AND
        !          1343:          || code == IOR);
        !          1344: }
        !          1345: 
        !          1346: /* Shifts.
        !          1347: 
        !          1348:    We devote a fair bit of code to getting efficient shifts since we can only
        !          1349:    shift one bit at a time.  See the .md file for more comments.
        !          1350: 
        !          1351:    Here are some thoughts on what the absolutely positively best code is.
        !          1352:    "Best" here means some rational trade-off between code size and speed,
        !          1353:    where speed is more preferred but not at the expense of generating 20 insns.
        !          1354: 
        !          1355:    H8/300 QImode shifts
        !          1356:    1-4   - do them inline
        !          1357:    5-6   - ASHIFT | LSHIFTRT: rotate, mask off other bits
        !          1358:            ASHIFTRT: loop
        !          1359:    7     - ASHIFT | LSHIFTRT: rotate, mask off other bits
        !          1360:            ASHIFTRT: shll, subx (propagate carry bit to all bits)
        !          1361: 
        !          1362:    H8/300 HImode shifts
        !          1363:    1-4   - do them inline
        !          1364:    5-6   - loop
        !          1365:    7     - shift other way once, move byte into place, move carry bit into place
        !          1366:    8     - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
        !          1367:    9     - inline shift 1-4, move byte, set other byte
        !          1368:    13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
        !          1369:          - ASHIFTRT: loop
        !          1370:    15    - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
        !          1371:          - ASHIFTRT: shll, subx, set other byte
        !          1372: 
        !          1373:    H8/300 SImode shifts
        !          1374:    1-2   - do them inline
        !          1375:    3-6   - loop
        !          1376:    7     - shift other way once, move bytes into place,
        !          1377:            move carry into place (possibly with sign extension)
        !          1378:    8     - move bytes into place, zero or sign extend other
        !          1379:    9-14  - loop
        !          1380:    15    - shift other way once, move word into place, move carry into place
        !          1381:    16    - move word, zero or sign extend other
        !          1382:    17-23 - loop
        !          1383:    24    - move bytes into place, zero or sign extend other
        !          1384:    25-27 - loop
        !          1385:    28-30 - ASHIFT | LSHIFTRT: rotate top byte, mask, move byte into place,
        !          1386:                               zero others
        !          1387:            ASHIFTRT: loop
        !          1388:    31    - ASHIFT | LSHIFTRT: rotate top byte, mask, byte byte into place,
        !          1389:                               zero others
        !          1390:            ASHIFTRT: shll top byte, subx, copy to other bytes
        !          1391: 
        !          1392:    H8/300H QImode shifts
        !          1393:    - same as H8/300
        !          1394: 
        !          1395:    H8/300H HImode shifts
        !          1396:    - same as H8/300
        !          1397: 
        !          1398:    H8/300H SImode shifts
        !          1399:    (These are complicated by the fact that we don't have byte level access to
        !          1400:    the top word.)
        !          1401:    A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw)
        !          1402:    1-4   - do them inline
        !          1403:    5-14  - loop
        !          1404:    15    - shift other way once, move word into place, move carry into place
        !          1405:            (with sign extension for ASHIFTRT)
        !          1406:    16    - move word into place, zero or sign extend other
        !          1407:    17-23 - loop
        !          1408:    24    - ASHIFT: move byte 0(msb) to byte 1, zero byte 0,
        !          1409:                    move word 0 to word 1, zero word 0
        !          1410:            LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
        !          1411:                      zero word 1, zero byte 1
        !          1412:            ASHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
        !          1413:                      sign extend byte 0, sign extend word 0
        !          1414:    25-27 - either loop, or
        !          1415:            do 24 bit shift, inline rest
        !          1416:    28-30 - ASHIFT: rotate 4/3/2, mask
        !          1417:            LSHIFTRT: rotate 4/3/2, mask
        !          1418:            ASHIFTRT: loop
        !          1419:    31    - shll, subx byte 0, sign extend byte 0, sign extend word 0
        !          1420: 
        !          1421:    Don't Panic!!!
        !          1422: 
        !          1423:    All of these haven't been implemented.  I've just documented them and
        !          1424:    provided hooks so they can be.
        !          1425: */
        !          1426: 
        !          1427: int
        !          1428: nshift_operator (x, mode)
        !          1429:      rtx x;
        !          1430:      enum machine_mode mode;
        !          1431: {
        !          1432:   switch (GET_CODE (x))
        !          1433:     {
        !          1434:     case ASHIFTRT:
        !          1435:     case LSHIFTRT:
        !          1436:     case ASHIFT:
        !          1437:       return 1;
        !          1438: 
        !          1439:     default:
        !          1440:       return 0;
        !          1441:     }
        !          1442: }
        !          1443: 
        !          1444: /* Called from the .md file to emit code to do shifts.
        !          1445:    Returns a boolean indicating success
        !          1446:    (currently this is always TRUE).  */
        !          1447: 
        !          1448: int
        !          1449: expand_a_shift (mode, code, operands)
        !          1450:      enum machine_mode mode;
1.1       root     1451:      int code;
                   1452:      rtx operands[];
                   1453: {
                   1454:   extern int rtx_equal_function_value_matters;
                   1455: 
                   1456:   emit_move_insn (operands[0], operands[1]);
                   1457: 
1.1.1.2 ! root     1458:   /* need a loop to get all the bits we want  - we generate the
        !          1459:      code at emit time, but need to allocate a scratch reg now  */
1.1       root     1460: 
1.1.1.2 ! root     1461:   emit_insn (gen_rtx
        !          1462:             (PARALLEL, VOIDmode,
        !          1463:              gen_rtvec (2,
        !          1464:                         gen_rtx (SET, VOIDmode, operands[0],
        !          1465:                                  gen_rtx (code, mode, operands[0], operands[2])),
        !          1466:                         gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)))));
        !          1467: 
        !          1468:   return 1;
        !          1469: }
1.1       root     1470: 
1.1.1.2 ! root     1471: /* Shift algorithm determination.
1.1       root     1472: 
1.1.1.2 ! root     1473:    There are various ways of doing a shift:
        !          1474:    SHIFT_INLINE: If the amount is small enough, just generate as many one-bit
        !          1475:                  shifts as we need.
        !          1476:    SHIFT_ROT_AND: If the amount is large but close to either end, rotate the
        !          1477:                   necessary bits into position and then set the rest to zero.
        !          1478:    SHIFT_SPECIAL: Hand crafted assembler.
        !          1479:    SHIFT_LOOP:    If the above methods fail, just loop.  */
        !          1480: 
        !          1481: enum shift_alg
        !          1482: {
        !          1483:   SHIFT_INLINE,
        !          1484:   SHIFT_ROT_AND,
        !          1485:   SHIFT_SPECIAL,
        !          1486:   SHIFT_LOOP,
        !          1487:   SHIFT_MAX
        !          1488: };
        !          1489: 
        !          1490: /* Symbols of the various shifts which can be used as indices.  */
        !          1491: 
        !          1492: enum shift_type
        !          1493:   {
        !          1494:     SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT
        !          1495:   };
        !          1496: 
        !          1497: /* Symbols of the various modes which can be used as indices.  */
        !          1498: 
        !          1499: enum shift_mode
        !          1500:   {
        !          1501:     QIshift, HIshift, SIshift
        !          1502:   };
        !          1503: 
        !          1504: /* For single bit shift insns, record assembler and whether the condition code
        !          1505:    is valid afterwards.  */
        !          1506: 
        !          1507: struct shift_insn
        !          1508: {
        !          1509:   char *assembler;
        !          1510:   int cc_valid;
        !          1511: };
        !          1512: 
        !          1513: /* Assembler instruction shift table.
        !          1514: 
        !          1515:    These tables are used to look up the basic shifts.
        !          1516:    They are indexed by cpu, shift_type, and mode.
        !          1517: */
        !          1518: 
        !          1519: static const struct shift_insn shift_one[2][3][3] =
        !          1520: {
        !          1521: /* H8/300 */
        !          1522:   {
        !          1523: /* SHIFT_ASHIFT */
        !          1524:     {
        !          1525:       { "shal %X0", 1 },
        !          1526:       { "add.w %T0,%T0\t; shal.w", 1 },
        !          1527:       { "add.w %f0,%f0\t; shal.l\n\taddx %y0,%y0\n\taddx %z0,%z0\t; end shal.l", 0 }
        !          1528:     },
        !          1529: /* SHIFT_LSHIFTRT */
        !          1530:     {
        !          1531:       { "shlr %X0", 1 },
        !          1532:       { "shlr %t0\t; shlr.w\n\trotxr %s0\t; end shlr.w", 0 },
        !          1533:       { "shlr %z0\t; shlr.l\n\trotxr %y0\n\trotxr %x0\n\trotxr %w0\t; end shlr.l", 0 }
        !          1534:     },
        !          1535: /* SHIFT_ASHIFTRT */
        !          1536:     {
        !          1537:       { "shar %X0", 1 },
        !          1538:       { "shar %t0\t; shar.w\n\trotxr %s0\t; end shar.w", 0 },
        !          1539:       { "shar %z0\t; shar.l\n\trotxr %y0\n\trotxr %x0\n\trotxr %w0\t; end shar.l", 0 }
1.1       root     1540:     }
1.1.1.2 ! root     1541:   },
        !          1542: /* H8/300H */
        !          1543:   {
        !          1544: /* SHIFT_ASHIFT */
        !          1545:     {
        !          1546:       { "shal.b %X0", 1 },
        !          1547:       { "shal.w %T0", 1 },
        !          1548:       { "shal.l %S0", 1 }
        !          1549:     },
        !          1550: /* SHIFT_LSHIFTRT */
1.1       root     1551:     {
1.1.1.2 ! root     1552:       { "shlr.b %X0", 1 },
        !          1553:       { "shlr.w %T0", 1 },
        !          1554:       { "shlr.l %S0", 1 }
        !          1555:     },
        !          1556: /* SHIFT_ASHIFTRT */
        !          1557:     {
        !          1558:       { "shar.b %X0", 1 },
        !          1559:       { "shar.w %T0", 1 },
        !          1560:       { "shar.l %S0", 1 }
        !          1561:     }
        !          1562:   }
        !          1563: };
1.1       root     1564: 
1.1.1.2 ! root     1565: /* Rotates are organized by which shift they'll be used in implementing.
        !          1566:    There's no need to record whether the cc is valid afterwards because
        !          1567:    it is the AND insn that will decide this.  */
1.1       root     1568: 
1.1.1.2 ! root     1569: static const char *const rotate_one[2][3][3] =
        !          1570: {
        !          1571: /* H8/300 */
        !          1572:   {
        !          1573: /* SHIFT_ASHIFT */
        !          1574:     {
        !          1575:       "rotr %X0",
        !          1576:       "shlr %t0\t; rotr.w\n\trotxr %s0\n\tbst #7,%t0\t; end rotr.w",
        !          1577:       0
        !          1578:     },
        !          1579: /* SHIFT_LSHIFTRT */
        !          1580:     {
        !          1581:       "rotl %X0",
        !          1582:       "shll %s0\t; rotl.w\n\trotxl %t0\n\tbst #0,%s0\t; end rotl.w",
        !          1583:       0
        !          1584:     },
        !          1585: /* SHIFT_ASHIFTRT */
        !          1586:     {
        !          1587:       "rotl %X0",
        !          1588:       "shll %s0\t; rotl.w\n\trotxl %t0\n\tbst #0,%s0\t; end rotl.w",
        !          1589:       0
        !          1590:     }
        !          1591:   },
        !          1592: /* H8/300H */
        !          1593:   {
        !          1594: /* SHIFT_ASHIFT */
        !          1595:     {
        !          1596:       "rotr.b %X0",
        !          1597:       "rotr.w %T0",
        !          1598:       "rotr.l %S0"
        !          1599:     },
        !          1600: /* SHIFT_LSHIFTRT */
        !          1601:     {
        !          1602:       "rotl.b %X0",
        !          1603:       "rotl.w %T0",
        !          1604:       "rotl.l %S0"
        !          1605:     },
        !          1606: /* SHIFT_ASHIFTRT */
        !          1607:     {
        !          1608:       "rotl.b %X0",
        !          1609:       "rotl.w %T0",
        !          1610:       "rotl.l %S0"
        !          1611:     }
        !          1612:   }
        !          1613: };
        !          1614: 
        !          1615: /* Given CPU, MODE, SHIFT_TYPE, and shift count COUNT, determine the best
        !          1616:    algorithm for doing the shift.  The assembler code is stored in ASSEMBLER.
        !          1617:    We don't achieve maximum efficiency in all cases, but the hooks are here
        !          1618:    to do so.
        !          1619: 
        !          1620:    For now we just use lots of switch statements.  Since we don't even come
        !          1621:    close to supporting all the cases, this is simplest.  If this function ever
        !          1622:    gets too big, perhaps resort to a more table based lookup.  Of course,
        !          1623:    at this point you may just wish to do it all in rtl.
        !          1624: 
        !          1625:    WARNING: The constraints on insns shiftbyn_QI/HI/SI assume shifts of
        !          1626:    1,2,3,4 will be inlined (1,2 for SI).  */
        !          1627: 
        !          1628: static enum shift_alg
        !          1629: get_shift_alg (cpu, shift_type, mode, count, assembler_p, cc_valid_p)
        !          1630:      enum attr_cpu cpu;
        !          1631:      enum shift_type shift_type;
        !          1632:      enum machine_mode mode;
        !          1633:      int count;
        !          1634:      const char **assembler_p;
        !          1635:      int *cc_valid_p;
        !          1636: {
        !          1637:   /* The default is to loop.  */
        !          1638:   enum shift_alg alg = SHIFT_LOOP;
        !          1639:   enum shift_mode shift_mode;
        !          1640: 
        !          1641:   /* We don't handle negative shifts or shifts greater than the word size,
        !          1642:      they should have been handled already.  */
        !          1643: 
        !          1644:   if (count < 0 || count > GET_MODE_BITSIZE (mode))
        !          1645:     abort ();
        !          1646: 
        !          1647:   switch (mode)
        !          1648:     {
        !          1649:     case QImode:
        !          1650:       shift_mode = QIshift;
        !          1651:       break;
        !          1652:     case HImode:
        !          1653:       shift_mode = HIshift;
        !          1654:       break;
        !          1655:     case SImode:
        !          1656:       shift_mode = SIshift;
        !          1657:       break;
        !          1658:     default:
        !          1659:       abort ();
        !          1660:     }
        !          1661: 
        !          1662:   /* Assume either SHIFT_LOOP or SHIFT_INLINE.
        !          1663:      It is up to the caller to know that looping clobbers cc.  */
        !          1664:   *assembler_p = shift_one[cpu][shift_type][shift_mode].assembler;
        !          1665:   *cc_valid_p = shift_one[cpu][shift_type][shift_mode].cc_valid;
        !          1666: 
        !          1667:   /* Now look for cases we want to optimize.  */
        !          1668: 
        !          1669:   switch (shift_mode)
        !          1670:     {
        !          1671:     case QIshift:
        !          1672:       if (count <= 4)
        !          1673:        return SHIFT_INLINE;
        !          1674:       else if (count <= 6)
        !          1675:        {
        !          1676:          if (shift_type == SHIFT_ASHIFTRT)
        !          1677:            {
        !          1678:              return SHIFT_LOOP;
        !          1679:            }
        !          1680:          else
        !          1681:            {
        !          1682:              *assembler_p = rotate_one[cpu][shift_type][shift_mode];
        !          1683:              *cc_valid_p = 0;
        !          1684:              return SHIFT_ROT_AND;
        !          1685:            }
        !          1686:        }
        !          1687:       else if (count == 7)
        !          1688:        {
        !          1689:          if (shift_type == SHIFT_ASHIFTRT)
        !          1690:            {
        !          1691:              *assembler_p = "shll %X0\t; shar.b(7)\n\tsubx %X0,%X0\t; end shar.b(7)";
        !          1692:              *cc_valid_p = 0;
        !          1693:              return SHIFT_SPECIAL;
        !          1694:            }
        !          1695:          else
        !          1696:            {
        !          1697:              *assembler_p = rotate_one[cpu][shift_type][shift_mode];
        !          1698:              *cc_valid_p = 0;
        !          1699:              return SHIFT_ROT_AND;
        !          1700:            }
        !          1701:        }
        !          1702:       break;
        !          1703:     case HIshift:
        !          1704:       if (count <= 4)
        !          1705:        return SHIFT_INLINE;
        !          1706:       else if (count == 8)
        !          1707:        {
        !          1708:          switch (shift_type)
        !          1709:            {
        !          1710:            case SHIFT_ASHIFT:
        !          1711:              *assembler_p = "mov.b %s0,%t0\t; shal.w(8)\n\tsub.b %s0,%s0\t; end shal.w(8)";
        !          1712:              *cc_valid_p = 0;
        !          1713:              return SHIFT_SPECIAL;
        !          1714:            case SHIFT_LSHIFTRT:
        !          1715:              *assembler_p = "mov.b %t0,%s0\t; shlr.w(8)\n\tsub.b %t0,%t0\t; end shlr.w(8)";
        !          1716:              *cc_valid_p = 0;
        !          1717:              return SHIFT_SPECIAL;
        !          1718:            case SHIFT_ASHIFTRT:
        !          1719:              if (cpu == CPU_H8300)
        !          1720:                *assembler_p = "mov.b %t0,%s0\t; shar.w(8)\n\tshll %t0\n\tsubx %t0,%t0\t; end shar.w(8)";
        !          1721:              else
        !          1722:                *assembler_p = "mov.b %t0,%s0\t; shar.w(8)\n\texts.w %T0\t; end shar.w(8)";
        !          1723:              *cc_valid_p = 0;
        !          1724:              return SHIFT_SPECIAL;
        !          1725:            }
        !          1726:          abort ();
1.1       root     1727:        }
1.1.1.2 ! root     1728:       else if (count == 15)
1.1       root     1729:        {
1.1.1.2 ! root     1730:          if (shift_type == SHIFT_ASHIFTRT)
        !          1731:            {
        !          1732:              *assembler_p = "shll %t0,%t0\t; shar.w(15)\n\tsubx %t0,%t0\n\tmov.b %t0,%s0\t; end shar.w(15)";
        !          1733:              *cc_valid_p = 0;
        !          1734:              return SHIFT_SPECIAL;
        !          1735:            }
        !          1736:          else
        !          1737:            {
        !          1738:              *assembler_p = rotate_one[cpu][shift_type][shift_mode];
        !          1739:              *cc_valid_p = 0;
        !          1740:              return SHIFT_ROT_AND;
        !          1741:            }
        !          1742:        }
        !          1743:       break;
        !          1744:     case SIshift:
        !          1745:       if (count <= (cpu == CPU_H8300 ? 2 : 4))
        !          1746:        return SHIFT_INLINE;
        !          1747:       else if (count == 8)
        !          1748:        {
        !          1749:          if (cpu == CPU_H8300)
        !          1750:            {
        !          1751:              switch (shift_type)
        !          1752:                {
        !          1753:                case SHIFT_ASHIFT:
        !          1754:                  *assembler_p = "mov.b %y0,%z0\t; shal.l(8)\n\tmov.b %x0,%y0\n\tmov.b %w0,%x0\n\tsub.b %w0,%w0\t; end shal.l(8)";
        !          1755:                  *cc_valid_p = 0;
        !          1756:                  return SHIFT_SPECIAL;
        !          1757:                case SHIFT_LSHIFTRT:
        !          1758:                  *assembler_p = "mov.b %x0,%w0\t; shlr.l(8)\n\tmov.b %y0,%x0\n\tmov.b %z0,%y0\n\tsub.b %z0,%z0\t; end shlr.l(8)";
        !          1759:                  *cc_valid_p = 0;
        !          1760:                  return SHIFT_SPECIAL;
        !          1761:                case SHIFT_ASHIFTRT:
        !          1762:                  *assembler_p = "mov.b %x0,%w0\t; shar.l(8)\n\tmov.b %y0,%x0\n\tmov.b %z0,%y0\n\tshll %z0\n\tsubx %z0,%z0; end shar.l(8)";
        !          1763:                  *cc_valid_p = 0;
        !          1764:                  return SHIFT_SPECIAL;
        !          1765:                }
        !          1766:            }
        !          1767:          else                  /* CPU_H8300H */
        !          1768:            /* We don't have byte level access to the high word so this isn't
        !          1769:               easy to do.  For now, just loop.  */
        !          1770:            ;
        !          1771:        }
        !          1772:       else if (count == 16)
        !          1773:        {
        !          1774:          switch (shift_type)
        !          1775:            {
        !          1776:            case SHIFT_ASHIFT:
        !          1777:              *assembler_p = "mov.w %f0,%e0\t; shal.l(16)\n\tsub.w %f0,%f0\t; end shal.l(16)";
        !          1778:              *cc_valid_p = 0;
        !          1779:              return SHIFT_SPECIAL;
        !          1780:            case SHIFT_LSHIFTRT:
        !          1781:              *assembler_p = "mov.w %e0,%f0\t; shlr.l(16)\n\tsub.w %e0,%e0\t; end shlr.l(16)";
        !          1782:              *cc_valid_p = 0;
        !          1783:              return SHIFT_SPECIAL;
        !          1784:            case SHIFT_ASHIFTRT:
        !          1785:              if (cpu == CPU_H8300)
        !          1786:                *assembler_p = "mov.w %e0,%f0\t; shar.l(16)\n\tshll %z0\n\tsubx %z0,%z0\n\tmov.b %z0,%y0\t; end shar.l(16)";
        !          1787:              else
        !          1788:                *assembler_p = "mov.w %e0,%f0\t; shar.l(16)\n\texts.l %S0\t; end shar.l(16)";
        !          1789:              *cc_valid_p = 0;
        !          1790:              return SHIFT_SPECIAL;
        !          1791:            }
        !          1792:        }
        !          1793:       else if (count >= 28 && count <= 30)
        !          1794:        {
        !          1795:          if (shift_type == SHIFT_ASHIFTRT)
        !          1796:            {
        !          1797:              return SHIFT_LOOP;
        !          1798:            }
        !          1799:          else
        !          1800:            {
        !          1801:              if (cpu == CPU_H8300)
        !          1802:                return SHIFT_LOOP;
        !          1803:              else
        !          1804:                {
        !          1805:                  *assembler_p = rotate_one[cpu][shift_type][shift_mode];
        !          1806:                  *cc_valid_p = 0;
        !          1807:                  return SHIFT_ROT_AND;
        !          1808:                }
        !          1809:            }
        !          1810:        }
        !          1811:       else if (count == 31)
        !          1812:        {
        !          1813:          if (shift_type == SHIFT_ASHIFTRT)
        !          1814:            {
        !          1815:              if (cpu == CPU_H8300)
        !          1816:                *assembler_p = "shll %z0\t; shar.l(31)\n\tsubx %w0,%w0\n\tmov.b %w0,%x0\n\tmov.w %f0,%e0\t; end shar.l(31)";
        !          1817:              else
        !          1818:                *assembler_p = "shll %e0\t; shar.l(31)\n\tsubx %w0,%w0\n\tmov.b %w0,%x0\n\tmov.w %f0,%e0\t; end shar.l(31)";
        !          1819:              *cc_valid_p = 0;
        !          1820:              return SHIFT_SPECIAL;
        !          1821:            }
        !          1822:          else
        !          1823:            {
        !          1824:              if (cpu == CPU_H8300)
        !          1825:                {
        !          1826:                  if (shift_type == SHIFT_ASHIFT)
        !          1827:                    *assembler_p = "sub.w %e0,%e0\t; shal.l(31)\n\tshlr %w0\n\tmov.w %e0,%f0\n\trotxr %z0\t; end shal.l(31)";
        !          1828:                  else
        !          1829:                    *assembler_p = "sub.w %f0,%f0\t; shlr.l(31)\n\tshll %z0\n\tmov.w %f0,%e0\n\trotxl %w0\t; end shlr.l(31)";
        !          1830:                  *cc_valid_p = 0;
        !          1831:                  return SHIFT_SPECIAL;
        !          1832:                }
        !          1833:              else
        !          1834:                {
        !          1835:                  *assembler_p = rotate_one[cpu][shift_type][shift_mode];
        !          1836:                  *cc_valid_p = 0;
        !          1837:                  return SHIFT_ROT_AND;
        !          1838:                }
        !          1839:            }
1.1       root     1840:        }
1.1.1.2 ! root     1841:       break;
        !          1842:     default:
        !          1843:       abort ();
1.1       root     1844:     }
1.1.1.2 ! root     1845: 
        !          1846:   return alg;
1.1       root     1847: }
                   1848: 
1.1.1.2 ! root     1849: /* Emit the assembler code for doing shifts.  */
        !          1850: 
        !          1851: char *
        !          1852: emit_a_shift (insn, operands)
        !          1853:      rtx insn;
        !          1854:      rtx *operands;
1.1       root     1855: {
1.1.1.2 ! root     1856:   static int loopend_lab;
        !          1857:   char *assembler;
        !          1858:   int cc_valid;
        !          1859:   rtx inside = PATTERN (insn);
        !          1860:   rtx shift = operands[3];
        !          1861:   enum machine_mode mode = GET_MODE (shift);
        !          1862:   enum rtx_code code = GET_CODE (shift);
        !          1863:   enum shift_type shift_type;
        !          1864:   enum shift_mode shift_mode;
        !          1865: 
        !          1866:   loopend_lab++;
1.1       root     1867: 
1.1.1.2 ! root     1868:   switch (mode)
1.1       root     1869:     {
1.1.1.2 ! root     1870:     case QImode:
        !          1871:       shift_mode = QIshift;
        !          1872:       break;
        !          1873:     case HImode:
        !          1874:       shift_mode = HIshift;
        !          1875:       break;
        !          1876:     case SImode:
        !          1877:       shift_mode = SIshift;
        !          1878:       break;
        !          1879:     default:
        !          1880:       abort ();
        !          1881:     }
1.1       root     1882: 
1.1.1.2 ! root     1883:   switch (code)
        !          1884:     {
        !          1885:     case ASHIFTRT:
        !          1886:       shift_type = SHIFT_ASHIFTRT;
        !          1887:       break;
        !          1888:     case LSHIFTRT:
        !          1889:       shift_type = SHIFT_LSHIFTRT;
        !          1890:       break;
        !          1891:     case ASHIFT:
        !          1892:       shift_type = SHIFT_ASHIFT;
        !          1893:       break;
        !          1894:     default:
        !          1895:       abort ();
        !          1896:     }
        !          1897: 
        !          1898:   if (GET_CODE (operands[2]) != CONST_INT)
        !          1899:     {
        !          1900:       /* Indexing by reg, so have to loop and test at top */
        !          1901:       output_asm_insn ("mov.b  %X2,%X4", operands);
        !          1902:       fprintf (asm_out_file, "\tble    .Lle%d\n", loopend_lab);
        !          1903: 
        !          1904:       /* Get the assembler code to do one shift.  */
        !          1905:       get_shift_alg (cpu_type, shift_type, mode, 1, &assembler, &cc_valid);
        !          1906:     }
        !          1907:   else
        !          1908:     {
        !          1909:       int n = INTVAL (operands[2]);
        !          1910:       enum shift_alg alg;
        !          1911: 
        !          1912:       /* If the count is negative, make it 0.  */
        !          1913:       if (n < 0)
        !          1914:        n = 0;
        !          1915:       /* If the count is too big, truncate it.
        !          1916:          ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
        !          1917:         do the intuitive thing.  */
        !          1918:       else if (n > GET_MODE_BITSIZE (mode))
        !          1919:        n = GET_MODE_BITSIZE (mode);
        !          1920: 
        !          1921:       alg = get_shift_alg (cpu_type, shift_type, mode, n, &assembler, &cc_valid);
        !          1922: 
        !          1923:       switch (alg)
        !          1924:        {
        !          1925:        case SHIFT_INLINE:
        !          1926:          while (--n >= 0)
        !          1927:            output_asm_insn (assembler, operands);
        !          1928:          if (cc_valid)
        !          1929:            cc_status.value1 = operands[0];
        !          1930:          return "";
        !          1931:        case SHIFT_ROT_AND:
        !          1932:          {
        !          1933:            int m = GET_MODE_BITSIZE (mode) - n;
        !          1934:            int mask = (shift_type == SHIFT_ASHIFT
        !          1935:                        ? ((1 << GET_MODE_BITSIZE (mode) - n) - 1) << n
        !          1936:                        : (1 << GET_MODE_BITSIZE (mode) - n) - 1);
        !          1937:            char insn_buf[200];
        !          1938:            /* Not all possibilities of rotate are supported.  They shouldn't
        !          1939:               be generated, but let's watch for 'em.  */
        !          1940:            if (assembler == 0)
        !          1941:              abort ();
        !          1942:            while (--m >= 0)
        !          1943:              output_asm_insn (assembler, operands);
        !          1944:            if (TARGET_H8300)
        !          1945:              {
        !          1946:                switch (mode)
        !          1947:                  {
        !          1948:                  case QImode:
        !          1949:                    sprintf (insn_buf, "and #%d,%%X0\t; end shift %d via rotate+and",
        !          1950:                             mask, n);
        !          1951:                    cc_status.value1 = operands[0];
        !          1952:                    break;
        !          1953:                  case HImode:
        !          1954:                    sprintf (insn_buf, "and #%d,%%s0\n\tand #%d,%%t0\t; end shift %d via rotate+and",
        !          1955:                             mask & 255, mask >> 8, n);
        !          1956:                    break;
        !          1957:                  case SImode:
        !          1958:                    abort ();
        !          1959:                  }
        !          1960:              }
        !          1961:            else
        !          1962:              {
        !          1963:                sprintf (insn_buf, "and.%c #%d,%%%c0",
        !          1964:                         "bwl"[shift_mode], mask,
        !          1965:                         mode == QImode ? 'X' : mode == HImode ? 'T' : 'S');
        !          1966:                cc_status.value1 = operands[0];
        !          1967:              }
        !          1968:            output_asm_insn (insn_buf, operands);
        !          1969:            return "";
        !          1970:          }
        !          1971:        case SHIFT_SPECIAL:
        !          1972:          output_asm_insn (assembler, operands);
        !          1973:          return "";
1.1       root     1974:        }
1.1.1.2 ! root     1975: 
        !          1976:       /* Need a loop, move limit to tmp reg */
        !          1977:       fprintf (asm_out_file, "\tmov.b  #%d,%sl\n", n, names_big[REGNO (operands[4])]);
1.1       root     1978:     }
1.1.1.2 ! root     1979: 
        !          1980:   fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
        !          1981:   output_asm_insn (assembler, operands);
        !          1982:   output_asm_insn ("add        #0xff,%X4", operands);
        !          1983:   fprintf (asm_out_file, "\tbne        .Llt%d\n", loopend_lab);
        !          1984:   fprintf (asm_out_file, ".Lle%d:\n", loopend_lab);
        !          1985: 
        !          1986:   return "";
1.1       root     1987: }
1.1.1.2 ! root     1988: 
        !          1989: /* Fix the operands of a gen_xxx so that it could become a bit
        !          1990:   operating insn.  */
1.1       root     1991: 
                   1992: int
1.1.1.2 ! root     1993: fix_bit_operand (operands, what, type)
        !          1994:      rtx *operands;
        !          1995:      char what;
        !          1996:      enum rtx_code type;
1.1       root     1997: {
1.1.1.2 ! root     1998:   /* The bit_operand predicate accepts any memory durint RTL generation, but
        !          1999:      only 'U' memory afterwards, so if this is a MEM operand, we must force
        !          2000:      it to be valid for 'U' by reloading the address.  */
1.1       root     2001: 
1.1.1.2 ! root     2002:   if (GET_CODE (operands[2]) == CONST_INT)
1.1       root     2003:     {
1.1.1.2 ! root     2004:       if (CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), what))
        !          2005:        {
        !          2006:          /* Ok to have a memory dest.  */
        !          2007:          if (GET_CODE (operands[0]) == MEM && !EXTRA_CONSTRAINT (operands[0], 'U'))
        !          2008:            {
        !          2009:              rtx mem;
        !          2010:              mem = gen_rtx (MEM, GET_MODE (operands[0]),
        !          2011:                           copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
        !          2012:              RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[0]);
        !          2013:              MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[0]);
        !          2014:              MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[0]);
        !          2015:              operands[0] = mem;
        !          2016:            }
        !          2017: 
        !          2018:          if (GET_CODE (operands[1]) == MEM && !EXTRA_CONSTRAINT (operands[1], 'U'))
        !          2019:            {
        !          2020:              rtx mem;
        !          2021:              mem = gen_rtx (MEM, GET_MODE (operands[1]),
        !          2022:                           copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
        !          2023:              RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[1]);
        !          2024:              MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[1]);
        !          2025:              MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[1]);
        !          2026:              operands[1] = mem;
        !          2027:            }
        !          2028:          return 0;
        !          2029:        }
        !          2030:     }
1.1       root     2031: 
1.1.1.2 ! root     2032:   /* Dest and src op must be register.  */
1.1       root     2033: 
1.1.1.2 ! root     2034:   operands[1] = force_reg (QImode, operands[1]);
        !          2035:   {
        !          2036:     rtx res = gen_reg_rtx (QImode);
        !          2037:     emit_insn (gen_rtx (SET, VOIDmode, res, gen_rtx (type, QImode, operands[1], operands[2])));
        !          2038:     emit_insn (gen_rtx (SET, VOIDmode, operands[0], res));
        !          2039:   }
        !          2040:   return 1;
1.1       root     2041: }

unix.superglobalmegacorp.com

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