00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "recog.h"
00037 #include "expr.h"
00038 #include "function.h"
00039 #include "toplev.h"
00040 #include "c-pragma.h"
00041 #include "tm_p.h"
00042 #include "ggc.h"
00043 #include "target.h"
00044 #include "target-def.h"
00045
00046
00047 static const char *byte_reg PARAMS ((rtx, int));
00048 static int h8300_interrupt_function_p PARAMS ((tree));
00049 static int h8300_monitor_function_p PARAMS ((tree));
00050 static int h8300_os_task_function_p PARAMS ((tree));
00051 static void dosize PARAMS ((FILE *, const char *, unsigned int));
00052 static int round_frame_size PARAMS ((int));
00053 static unsigned int compute_saved_regs PARAMS ((void));
00054 static void push PARAMS ((FILE *, int));
00055 static void pop PARAMS ((FILE *, int));
00056 static const char *cond_string PARAMS ((enum rtx_code));
00057 const struct attribute_spec h8300_attribute_table[];
00058 static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
00059 static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
00060 static tree h8300_handle_tiny_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
00061 static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00062 static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00063 #ifndef OBJECT_FORMAT_ELF
00064 static void h8300_asm_named_section PARAMS ((const char *, unsigned int));
00065 #endif
00066
00067
00068 int cpu_type;
00069
00070
00071
00072 static int interrupt_handler;
00073
00074
00075
00076 static int os_task;
00077
00078
00079
00080 static int monitor;
00081
00082
00083 static int pragma_saveall;
00084
00085 static const char *const names_big[] =
00086 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
00087
00088 static const char *const names_extended[] =
00089 { "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7" };
00090
00091 static const char *const names_upper_extended[] =
00092 { "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7" };
00093
00094
00095
00096 const char * const *h8_reg_names;
00097
00098
00099
00100 const char *h8_push_op, *h8_pop_op, *h8_mov_op;
00101
00102
00103 #undef TARGET_ATTRIBUTE_TABLE
00104 #define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
00105
00106 #undef TARGET_ASM_ALIGNED_HI_OP
00107 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00108
00109 #undef TARGET_ASM_FUNCTION_PROLOGUE
00110 #define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
00111 #undef TARGET_ASM_FUNCTION_EPILOGUE
00112 #define TARGET_ASM_FUNCTION_EPILOGUE h8300_output_function_epilogue
00113
00114 struct gcc_target targetm = TARGET_INITIALIZER;
00115
00116
00117
00118 void
00119 h8300_init_once ()
00120 {
00121 static const char *const h8_push_ops[2] = { "push" , "push.l" };
00122 static const char *const h8_pop_ops[2] = { "pop" , "pop.l" };
00123 static const char *const h8_mov_ops[2] = { "mov.w", "mov.l" };
00124
00125 if (TARGET_H8300)
00126 {
00127 cpu_type = (int) CPU_H8300;
00128 h8_reg_names = names_big;
00129 }
00130 else
00131 {
00132
00133 cpu_type = (int) CPU_H8300H;
00134 h8_reg_names = names_extended;
00135 }
00136 h8_push_op = h8_push_ops[cpu_type];
00137 h8_pop_op = h8_pop_ops[cpu_type];
00138 h8_mov_op = h8_mov_ops[cpu_type];
00139
00140 if (!TARGET_H8300S && TARGET_MAC)
00141 {
00142 error ("-ms2600 is used without -ms");
00143 target_flags |= 1;
00144 }
00145 }
00146
00147 static const char *
00148 byte_reg (x, b)
00149 rtx x;
00150 int b;
00151 {
00152 static const char *const names_small[] = {
00153 "r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
00154 "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"
00155 };
00156
00157 return names_small[REGNO (x) * 2 + b];
00158 }
00159
00160
00161
00162 #define WORD_REG_USED(regno) \
00163 (regno < 7 \
00164 \
00165 && ! TREE_THIS_VOLATILE (current_function_decl) \
00166 && (pragma_saveall \
00167 \
00168 || (regs_ever_live[regno] && !call_used_regs[regno]) \
00169 \
00170 || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
00171 \
00172 || (interrupt_handler && regs_ever_live[regno]) \
00173
00174 \
00175 || (interrupt_handler \
00176 && call_used_regs[regno] \
00177 && !current_function_is_leaf)))
00178
00179
00180
00181
00182 static void
00183 dosize (file, op, size)
00184 FILE *file;
00185 const char *op;
00186 unsigned int size;
00187 {
00188
00189
00190
00191
00192
00193
00194
00195 if ((TARGET_H8300 && size <= 4)
00196 || ((TARGET_H8300H || TARGET_H8300S) && size <= 8)
00197 || (TARGET_H8300 && interrupt_handler)
00198 || (TARGET_H8300 && current_function_needs_context
00199 && ! strcmp (op, "sub")))
00200 {
00201 unsigned HOST_WIDE_INT amount;
00202
00203
00204 for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
00205 amount > 0;
00206 amount /= 2)
00207 {
00208 for (; size >= amount; size -= amount)
00209 fprintf (file, "\t%ss\t#%d,sp\n", op, amount);
00210 }
00211 }
00212 else
00213 {
00214 if (TARGET_H8300)
00215 fprintf (file, "\tmov.w\t#%d,r3\n\t%s.w\tr3,sp\n", size, op);
00216 else
00217 fprintf (file, "\t%s.l\t#%d,sp\n", op, size);
00218 }
00219 }
00220
00221
00222
00223 static int
00224 round_frame_size (size)
00225 int size;
00226 {
00227 return (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;
00228 }
00229
00230
00231
00232
00233 static unsigned int
00234 compute_saved_regs ()
00235 {
00236 unsigned int saved_regs = 0;
00237 int regno;
00238
00239
00240 for (regno = 0; regno <= 6; regno++)
00241 {
00242 if (WORD_REG_USED (regno))
00243 saved_regs |= 1 << regno;
00244 }
00245
00246
00247 if (frame_pointer_needed)
00248 saved_regs &= ~(1 << FRAME_POINTER_REGNUM);
00249
00250 return saved_regs;
00251 }
00252
00253
00254
00255 static void
00256 push (file, rn)
00257 FILE *file;
00258 int rn;
00259 {
00260 fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[rn]);
00261 }
00262
00263
00264
00265 static void
00266 pop (file, rn)
00267 FILE *file;
00268 int rn;
00269 {
00270 fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[rn]);
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 static void
00294 h8300_output_function_prologue (file, size)
00295 FILE *file;
00296 HOST_WIDE_INT size;
00297 {
00298 int fsize = round_frame_size (size);
00299 int idx;
00300 int saved_regs;
00301 int n_regs;
00302
00303
00304
00305 if (h8300_interrupt_function_p (current_function_decl))
00306 interrupt_handler = 1;
00307
00308
00309
00310 if (h8300_os_task_function_p (current_function_decl))
00311 {
00312 fprintf (file, ";OS_Task prologue\n");
00313 os_task = 1;
00314 return;
00315 }
00316
00317 if (h8300_monitor_function_p (current_function_decl))
00318 {
00319
00320
00321
00322 fprintf (file, ";monitor prologue\n");
00323 interrupt_handler = 1;
00324 monitor = 1;
00325 if (TARGET_H8300)
00326 {
00327 fprintf (file, "\tsubs\t#2,sp\n");
00328 push (file, 0);
00329 fprintf (file, "\tstc\tccr,r0l\n");
00330 fprintf (file, "\tmov.b\tr0l,@(2,sp)\n");
00331 pop (file, 0);
00332 fprintf (file, "\torc\t#128,ccr\n");
00333 }
00334 else if (TARGET_H8300H)
00335 {
00336 push (file, 0);
00337 fprintf (file, "\tstc\tccr,r0l\n");
00338 fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");
00339 pop (file, 0);
00340 fprintf (file, "\torc\t#128,ccr\n");
00341 }
00342 else if (TARGET_H8300S)
00343 {
00344 fprintf (file, "\tstc\texr,@-sp\n");
00345 push (file, 0);
00346 fprintf (file, "\tstc\tccr,r0l\n");
00347 fprintf (file, "\tmov.b\tr0l,@(6,sp)\n");
00348 pop (file, 0);
00349 fprintf (file, "\torc\t#128,ccr\n");
00350 }
00351 else
00352 abort ();
00353 }
00354
00355 if (frame_pointer_needed)
00356 {
00357
00358 push (file, FRAME_POINTER_REGNUM);
00359 fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,
00360 h8_reg_names[STACK_POINTER_REGNUM],
00361 h8_reg_names[FRAME_POINTER_REGNUM]);
00362 }
00363
00364
00365 dosize (file, "sub", fsize);
00366
00367
00368 saved_regs = compute_saved_regs ();
00369 for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx += n_regs)
00370 {
00371 int regno = idx;
00372
00373 n_regs = 1;
00374 if (saved_regs & (1 << regno))
00375 {
00376 if (TARGET_H8300S)
00377 {
00378
00379 if ((regno == 0 || regno == 4)
00380 && ((saved_regs >> regno) & 0x0f) == 0x0f)
00381 n_regs = 4;
00382
00383 else if ((regno == 0 || regno == 4)
00384 && ((saved_regs >> regno) & 0x07) == 0x07)
00385 n_regs = 3;
00386
00387 else if ((regno == 0 || regno == 2 || regno == 4 || regno == 6)
00388 && ((saved_regs >> regno) & 0x03) == 0x03)
00389 n_regs = 2;
00390 }
00391
00392 if (n_regs == 1)
00393 push (file, regno);
00394 else
00395 fprintf (file, "\tstm.l\t%s-%s,@-sp\n",
00396 h8_reg_names[regno],
00397 h8_reg_names[regno + (n_regs - 1)]);
00398 }
00399 }
00400 }
00401
00402
00403
00404 static void
00405 h8300_output_function_epilogue (file, size)
00406 FILE *file;
00407 HOST_WIDE_INT size;
00408 {
00409 int fsize = round_frame_size (size);
00410 int idx;
00411 rtx insn = get_last_insn ();
00412 int saved_regs;
00413 int n_regs;
00414
00415 if (os_task)
00416 {
00417
00418
00419 fprintf (file, ";OS_task epilogue\n");
00420 fprintf (file, "\trts\n");
00421 goto out;
00422 }
00423
00424
00425
00426 if (monitor)
00427 fprintf (file, ";monitor epilogue\n");
00428
00429
00430 if (GET_CODE (insn) == NOTE)
00431 insn = prev_nonnote_insn (insn);
00432 if (insn && GET_CODE (insn) == BARRIER)
00433 goto out;
00434
00435
00436 saved_regs = compute_saved_regs ();
00437 for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx += n_regs)
00438 {
00439 int regno = (FIRST_PSEUDO_REGISTER - 1) - idx;
00440
00441 n_regs = 1;
00442 if (saved_regs & (1 << regno))
00443 {
00444 if (TARGET_H8300S)
00445 {
00446
00447 if ((regno == 7 || regno == 3)
00448 && ((saved_regs >> (regno - 3)) & 0x0f) == 0x0f)
00449 n_regs = 4;
00450
00451 else if ((regno == 6 || regno == 2)
00452 && ((saved_regs >> (regno - 2)) & 0x07) == 0x07)
00453 n_regs = 3;
00454
00455 else if ((regno == 7 || regno == 5 || regno == 3 || regno == 1)
00456 && ((saved_regs >> (regno - 1)) & 0x03) == 0x03)
00457 n_regs = 2;
00458 }
00459
00460 if (n_regs == 1)
00461 pop (file, regno);
00462 else
00463 fprintf (file, "\tldm.l\t@sp+,%s-%s\n",
00464 h8_reg_names[regno - (n_regs - 1)],
00465 h8_reg_names[regno]);
00466 }
00467 }
00468
00469
00470 dosize (file, "add", fsize);
00471
00472
00473 if (frame_pointer_needed)
00474 pop (file, FRAME_POINTER_REGNUM);
00475
00476 if (interrupt_handler)
00477 fprintf (file, "\trte\n");
00478 else
00479 fprintf (file, "\trts\n");
00480
00481 out:
00482 interrupt_handler = 0;
00483 os_task = 0;
00484 monitor = 0;
00485 pragma_saveall = 0;
00486 }
00487
00488
00489
00490 void
00491 asm_file_start (file)
00492 FILE *file;
00493 {
00494 fprintf (file, ";\tGCC For the Hitachi H8/300\n");
00495 fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n");
00496 if (optimize)
00497 fprintf (file, "; -O%d\n", optimize);
00498 if (TARGET_H8300H)
00499 fprintf (file, "\n\t.h8300h\n");
00500 else if (TARGET_H8300S)
00501 fprintf (file, "\n\t.h8300s\n");
00502 else
00503 fprintf (file, "\n\n");
00504 output_file_directive (file, main_input_filename);
00505 }
00506
00507
00508
00509 void
00510 asm_file_end (file)
00511 FILE *file;
00512 {
00513 fprintf (file, "\t.end\n");
00514 }
00515
00516
00517
00518
00519 int
00520 small_power_of_two (value)
00521 HOST_WIDE_INT value;
00522 {
00523 int power = exact_log2 (value);
00524 return power >= 0 && power <= 15;
00525 }
00526
00527
00528
00529
00530
00531 int
00532 ok_for_bclr (value)
00533 HOST_WIDE_INT value;
00534 {
00535 return small_power_of_two ((~value) & 0xff);
00536 }
00537
00538
00539
00540
00541 int
00542 general_operand_src (op, mode)
00543 rtx op;
00544 enum machine_mode mode;
00545 {
00546 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
00547 return 1;
00548 return general_operand (op, mode);
00549 }
00550
00551
00552
00553
00554 int
00555 general_operand_dst (op, mode)
00556 rtx op;
00557 enum machine_mode mode;
00558 {
00559 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC)
00560 return 1;
00561 return general_operand (op, mode);
00562 }
00563
00564
00565
00566 int
00567 o_operand (operand, mode)
00568 rtx operand;
00569 enum machine_mode mode ATTRIBUTE_UNUSED;
00570 {
00571 return (GET_CODE (operand) == CONST_INT
00572 && CONST_OK_FOR_O (INTVAL (operand)));
00573 }
00574
00575
00576
00577 int
00578 call_insn_operand (op, mode)
00579 rtx op;
00580 enum machine_mode mode ATTRIBUTE_UNUSED;
00581 {
00582 if (GET_CODE (op) == MEM)
00583 {
00584 rtx inside = XEXP (op, 0);
00585 if (register_operand (inside, Pmode))
00586 return 1;
00587 if (CONSTANT_ADDRESS_P (inside))
00588 return 1;
00589 }
00590 return 0;
00591 }
00592
00593
00594
00595
00596
00597 int
00598 two_insn_adds_subs_operand (op, mode)
00599 rtx op;
00600 enum machine_mode mode;
00601 {
00602 if (GET_CODE (op) == CONST_INT)
00603 {
00604 HOST_WIDE_INT value = INTVAL (op);
00605
00606
00607
00608 if (value < 0)
00609 value = -value;
00610 if (TARGET_H8300H || TARGET_H8300S)
00611 {
00612
00613
00614
00615
00616 if (mode == SImode
00617 && (value == 2 + 1
00618 || value == 4 + 1
00619 || value == 4 + 2
00620 || value == 4 + 4))
00621 return 1;
00622 }
00623 else
00624 {
00625
00626
00627
00628
00629 if (mode == HImode
00630 && (value == 2 + 1
00631 || value == 2 + 2))
00632 return 1;
00633 }
00634 }
00635
00636 return 0;
00637 }
00638
00639
00640
00641 void
00642 split_adds_subs (mode, operands)
00643 enum machine_mode mode;
00644 rtx *operands;
00645 {
00646 HOST_WIDE_INT val = INTVAL (operands[1]);
00647 rtx reg = operands[0];
00648 HOST_WIDE_INT sign = 1;
00649 HOST_WIDE_INT amount;
00650
00651
00652
00653 if (val < 0)
00654 {
00655 val = -val;
00656 sign = -1;
00657 }
00658
00659
00660 for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
00661 amount > 0;
00662 amount /= 2)
00663 {
00664 for (; val >= amount; val -= amount)
00665 {
00666 rtx tmp = gen_rtx_PLUS (mode, reg, GEN_INT (sign * amount));
00667 emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
00668 }
00669 }
00670
00671 return;
00672 }
00673
00674
00675
00676
00677 int
00678 small_call_insn_operand (op, mode)
00679 rtx op;
00680 enum machine_mode mode ATTRIBUTE_UNUSED;
00681 {
00682 if (GET_CODE (op) == MEM)
00683 {
00684 rtx inside = XEXP (op, 0);
00685
00686
00687 if (register_operand (inside, Pmode))
00688 return 1;
00689
00690
00691
00692 if (GET_CODE (inside) == SYMBOL_REF
00693 && SYMBOL_REF_FLAG (inside))
00694 return 1;
00695 }
00696
00697 return 0;
00698 }
00699
00700
00701
00702 int
00703 jump_address_operand (op, mode)
00704 rtx op;
00705 enum machine_mode mode;
00706 {
00707 if (GET_CODE (op) == REG)
00708 return mode == Pmode;
00709
00710 if (GET_CODE (op) == MEM)
00711 {
00712 rtx inside = XEXP (op, 0);
00713 if (register_operand (inside, Pmode))
00714 return 1;
00715 if (CONSTANT_ADDRESS_P (inside))
00716 return 1;
00717 }
00718 return 0;
00719 }
00720
00721
00722
00723 extern int rtx_equal_function_value_matters;
00724
00725 int
00726 bit_operand (op, mode)
00727 rtx op;
00728 enum machine_mode mode;
00729 {
00730
00731
00732 if (!general_operand (op, mode))
00733 return 0;
00734
00735
00736
00737
00738
00739
00740
00741 if (GET_CODE (op) == REG)
00742 return 1;
00743 if (GET_CODE (op) == SUBREG)
00744 return 1;
00745 if (!rtx_equal_function_value_matters)
00746
00747 return GET_CODE (op) == MEM;
00748 else
00749 return (GET_CODE (op) == MEM
00750 && EXTRA_CONSTRAINT (op, 'U'));
00751 }
00752
00753 int
00754 bit_memory_operand (op, mode)
00755 rtx op;
00756 enum machine_mode mode ATTRIBUTE_UNUSED;
00757 {
00758 return (GET_CODE (op) == MEM
00759 && EXTRA_CONSTRAINT (op, 'U'));
00760 }
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 void
00773 h8300_pr_interrupt (pfile)
00774 cpp_reader *pfile ATTRIBUTE_UNUSED;
00775 {
00776 interrupt_handler = 1;
00777 }
00778
00779 void
00780 h8300_pr_saveall (pfile)
00781 cpp_reader *pfile ATTRIBUTE_UNUSED;
00782 {
00783 pragma_saveall = 1;
00784 }
00785
00786
00787
00788
00789
00790
00791 rtx
00792 function_arg (cum, mode, type, named)
00793 CUMULATIVE_ARGS *cum;
00794 enum machine_mode mode;
00795 tree type;
00796 int named;
00797 {
00798 static const char *const hand_list[] = {
00799 "__main",
00800 "__cmpsi2",
00801 "__divhi3",
00802 "__modhi3",
00803 "__udivhi3",
00804 "__umodhi3",
00805 "__divsi3",
00806 "__modsi3",
00807 "__udivsi3",
00808 "__umodsi3",
00809 "__mulhi3",
00810 "__mulsi3",
00811 "__reg_memcpy",
00812 "__reg_memset",
00813 "__ucmpsi2",
00814 0,
00815 };
00816
00817 rtx result = NULL_RTX;
00818 const char *fname;
00819 int regpass = 0;
00820
00821
00822 if (!named)
00823 return NULL_RTX;
00824
00825
00826 if (TARGET_QUICKCALL)
00827 regpass = 3;
00828
00829
00830 if (cum->libcall)
00831 {
00832 const char * const *p;
00833
00834 fname = XSTR (cum->libcall, 0);
00835
00836
00837 for (p = hand_list; *p && strcmp (*p, fname) != 0; p++)
00838 ;
00839
00840 if (*p)
00841 regpass = 4;
00842 }
00843
00844 if (regpass)
00845 {
00846 int size;
00847
00848 if (mode == BLKmode)
00849 size = int_size_in_bytes (type);
00850 else
00851 size = GET_MODE_SIZE (mode);
00852
00853 if (size + cum->nbytes <= regpass * UNITS_PER_WORD
00854 && cum->nbytes / UNITS_PER_WORD <= 3)
00855 result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
00856 }
00857
00858 return result;
00859 }
00860
00861
00862
00863 int
00864 const_costs (r, c, outer_code)
00865 rtx r;
00866 enum rtx_code c;
00867 enum rtx_code outer_code;
00868 {
00869 switch (c)
00870 {
00871 case CONST_INT:
00872 switch (INTVAL (r))
00873 {
00874 case 0:
00875 return 0;
00876 case 1:
00877 case 2:
00878 case -1:
00879 case -2:
00880 return 0 + (outer_code == SET);
00881 case 4:
00882 case -4:
00883 if (TARGET_H8300H || TARGET_H8300S)
00884 return 0 + (outer_code == SET);
00885 else
00886 return 1;
00887 default:
00888 return 1;
00889 }
00890
00891 case CONST:
00892 case LABEL_REF:
00893 case SYMBOL_REF:
00894 return 3;
00895
00896 case CONST_DOUBLE:
00897 return 20;
00898
00899 default:
00900 return 4;
00901 }
00902 }
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 static const char *
00937 cond_string (code)
00938 enum rtx_code code;
00939 {
00940 switch (code)
00941 {
00942 case NE:
00943 return "ne";
00944 case EQ:
00945 return "eq";
00946 case GE:
00947 return "ge";
00948 case GT:
00949 return "gt";
00950 case LE:
00951 return "le";
00952 case LT:
00953 return "lt";
00954 case GEU:
00955 return "hs";
00956 case GTU:
00957 return "hi";
00958 case LEU:
00959 return "ls";
00960 case LTU:
00961 return "lo";
00962 default:
00963 abort ();
00964 }
00965 }
00966
00967
00968
00969
00970 void
00971 print_operand (file, x, code)
00972 FILE *file;
00973 rtx x;
00974 int code;
00975 {
00976
00977 static int bitint;
00978
00979 switch (code)
00980 {
00981 case 'E':
00982 switch (GET_CODE (x))
00983 {
00984 case REG:
00985 fprintf (file, "%sl", names_big[REGNO (x)]);
00986 break;
00987 case CONST_INT:
00988 fprintf (file, "#%d", (-INTVAL (x)) & 0xff);
00989 break;
00990 default:
00991 abort ();
00992 }
00993 break;
00994 case 'F':
00995 switch (GET_CODE (x))
00996 {
00997 case REG:
00998 fprintf (file, "%sh", names_big[REGNO (x)]);
00999 break;
01000 case CONST_INT:
01001 fprintf (file, "#%d", ((-INTVAL (x)) & 0xff00) >> 8);
01002 break;
01003 default:
01004 abort ();
01005 }
01006 break;
01007 case 'G':
01008 if (GET_CODE (x) != CONST_INT)
01009 abort ();
01010 fprintf (file, "#%d", 0xff & (-INTVAL (x)));
01011 break;
01012 case 'S':
01013 if (GET_CODE (x) == REG)
01014 fprintf (file, "%s", names_extended[REGNO (x)]);
01015 else
01016 goto def;
01017 break;
01018 case 'T':
01019 if (GET_CODE (x) == REG)
01020 fprintf (file, "%s", names_big[REGNO (x)]);
01021 else
01022 goto def;
01023 break;
01024 case 'V':
01025 bitint = exact_log2 (INTVAL (x));
01026 if (bitint == -1)
01027 abort ();
01028 fprintf (file, "#%d", bitint & 7);
01029 break;
01030 case 'W':
01031 bitint = exact_log2 ((~INTVAL (x)) & 0xff);
01032 if (bitint == -1)
01033 abort ();
01034 fprintf (file, "#%d", bitint & 7);
01035 break;
01036 case 'R':
01037 case 'X':
01038 if (GET_CODE (x) == REG)
01039 fprintf (file, "%s", byte_reg (x, 0));
01040 else
01041 goto def;
01042 break;
01043 case 'Y':
01044 if (bitint == -1)
01045 abort ();
01046 if (GET_CODE (x) == REG)
01047 fprintf (file, "%s%c", names_big[REGNO (x)], bitint > 7 ? 'h' : 'l');
01048 else
01049 print_operand (file, x, 'R');
01050 bitint = -1;
01051 break;
01052 case 'Z':
01053 bitint = INTVAL (x);
01054 fprintf (file, "#%d", bitint & 7);
01055 break;
01056 case 'b':
01057 switch (GET_CODE (x))
01058 {
01059 case IOR:
01060 fprintf (file, "bor");
01061 break;
01062 case XOR:
01063 fprintf (file, "bxor");
01064 break;
01065 case AND:
01066 fprintf (file, "band");
01067 break;
01068 default:
01069 break;
01070 }
01071 break;
01072 case 'e':
01073 switch (GET_CODE (x))
01074 {
01075 case REG:
01076 if (TARGET_H8300)
01077 fprintf (file, "%s", names_big[REGNO (x)]);
01078 else
01079 fprintf (file, "%s", names_upper_extended[REGNO (x)]);
01080 break;
01081 case MEM:
01082 print_operand (file, x, 0);
01083 break;
01084 case CONST_INT:
01085 fprintf (file, "#%d", ((INTVAL (x) >> 16) & 0xffff));
01086 break;
01087 case CONST_DOUBLE:
01088 {
01089 long val;
01090 REAL_VALUE_TYPE rv;
01091 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01092 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01093 fprintf (file, "#%ld", ((val >> 16) & 0xffff));
01094 break;
01095 }
01096 default:
01097 abort ();
01098 break;
01099 }
01100 break;
01101 case 'f':
01102 switch (GET_CODE (x))
01103 {
01104 case REG:
01105 if (TARGET_H8300)
01106 fprintf (file, "%s", names_big[REGNO (x) + 1]);
01107 else
01108 fprintf (file, "%s", names_big[REGNO (x)]);
01109 break;
01110 case MEM:
01111 x = adjust_address (x, HImode, 2);
01112 print_operand (file, x, 0);
01113 break;
01114 case CONST_INT:
01115 fprintf (file, "#%d", INTVAL (x) & 0xffff);
01116 break;
01117 case CONST_DOUBLE:
01118 {
01119 long val;
01120 REAL_VALUE_TYPE rv;
01121 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01122 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01123 fprintf (file, "#%ld", (val & 0xffff));
01124 break;
01125 }
01126 default:
01127 abort ();
01128 }
01129 break;
01130 case 'j':
01131 asm_fprintf (file, cond_string (GET_CODE (x)));
01132 break;
01133 case 'k':
01134 asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
01135 break;
01136 case 's':
01137 if (GET_CODE (x) == CONST_INT)
01138 fprintf (file, "#%d", (INTVAL (x)) & 0xff);
01139 else
01140 fprintf (file, "%s", byte_reg (x, 0));
01141 break;
01142 case 't':
01143 if (GET_CODE (x) == CONST_INT)
01144 fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
01145 else
01146 fprintf (file, "%s", byte_reg (x, 1));
01147 break;
01148 case 'u':
01149 if (GET_CODE (x) != CONST_INT)
01150 abort ();
01151 fprintf (file, "%d", INTVAL (x));
01152 break;
01153 case 'w':
01154 if (GET_CODE (x) == CONST_INT)
01155 fprintf (file, "#%d", INTVAL (x) & 0xff);
01156 else
01157 fprintf (file, "%s",
01158 byte_reg (x, TARGET_H8300 ? 2 : 0));
01159 break;
01160 case 'x':
01161 if (GET_CODE (x) == CONST_INT)
01162 fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
01163 else
01164 fprintf (file, "%s",
01165 byte_reg (x, TARGET_H8300 ? 3 : 1));
01166 break;
01167 case 'y':
01168 if (GET_CODE (x) == CONST_INT)
01169 fprintf (file, "#%d", (INTVAL (x) >> 16) & 0xff);
01170 else
01171 fprintf (file, "%s", byte_reg (x, 0));
01172 break;
01173 case 'z':
01174 if (GET_CODE (x) == CONST_INT)
01175 fprintf (file, "#%d", (INTVAL (x) >> 24) & 0xff);
01176 else
01177 fprintf (file, "%s", byte_reg (x, 1));
01178 break;
01179
01180 default:
01181 def:
01182 switch (GET_CODE (x))
01183 {
01184 case REG:
01185 switch (GET_MODE (x))
01186 {
01187 case QImode:
01188 #if 0
01189 fprintf (file, "%s", byte_reg (x, 0));
01190 #else
01191 fprintf (file, "%s", names_big[REGNO (x)]);
01192 #endif
01193 break;
01194 case HImode:
01195 fprintf (file, "%s", names_big[REGNO (x)]);
01196 break;
01197 case SImode:
01198 case SFmode:
01199 fprintf (file, "%s", names_extended[REGNO (x)]);
01200 break;
01201 default:
01202 abort ();
01203 }
01204 break;
01205
01206 case MEM:
01207 {
01208 rtx addr = XEXP (x, 0);
01209
01210 fprintf (file, "@");
01211 output_address (addr);
01212
01213
01214
01215
01216
01217 if (GET_CODE (addr) == SYMBOL_REF
01218 && SYMBOL_REF_FLAG (addr))
01219 fprintf (file, (code == 'R' ? ":8" : ":16"));
01220 else if (GET_CODE (addr) == SYMBOL_REF
01221 && TINY_DATA_NAME_P (XSTR (addr, 0)))
01222 fprintf (file, ":16");
01223 else if ((code == 'R')
01224 && EIGHTBIT_CONSTANT_ADDRESS_P (addr))
01225 fprintf (file, ":8");
01226 }
01227 break;
01228
01229 case CONST_INT:
01230 case SYMBOL_REF:
01231 case CONST:
01232 case LABEL_REF:
01233 fprintf (file, "#");
01234 print_operand_address (file, x);
01235 break;
01236 case CONST_DOUBLE:
01237 {
01238 long val;
01239 REAL_VALUE_TYPE rv;
01240 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01241 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01242 fprintf (file, "#%ld", val);
01243 break;
01244 }
01245 default:
01246 break;
01247 }
01248 }
01249 }
01250
01251
01252
01253 void
01254 print_operand_address (file, addr)
01255 FILE *file;
01256 rtx addr;
01257 {
01258 switch (GET_CODE (addr))
01259 {
01260 case REG:
01261 fprintf (file, "%s", h8_reg_names[REGNO (addr)]);
01262 break;
01263
01264 case PRE_DEC:
01265 fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]);
01266 break;
01267
01268 case POST_INC:
01269 fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]);
01270 break;
01271
01272 case PLUS:
01273 fprintf (file, "(");
01274 if (GET_CODE (XEXP (addr, 0)) == REG)
01275 {
01276
01277 print_operand_address (file, XEXP (addr, 1));
01278 fprintf (file, ",");
01279 print_operand_address (file, XEXP (addr, 0));
01280 }
01281 else
01282 {
01283
01284 print_operand_address (file, XEXP (addr, 0));
01285 fprintf (file, "+");
01286 print_operand_address (file, XEXP (addr, 1));
01287 }
01288 fprintf (file, ")");
01289 break;
01290
01291 case CONST_INT:
01292 {
01293
01294
01295
01296
01297
01298 int n = INTVAL (addr);
01299 if (TARGET_H8300)
01300 n = (int) (short) n;
01301 if (n < 0)
01302
01303 fprintf (file, "-%d", -n);
01304 else
01305 fprintf (file, "%d", n);
01306 break;
01307 }
01308
01309 default:
01310 output_addr_const (file, addr);
01311 break;
01312 }
01313 }
01314
01315
01316
01317
01318
01319
01320 void
01321 final_prescan_insn (insn, operand, num_operands)
01322 rtx insn, *operand ATTRIBUTE_UNUSED;
01323 int num_operands ATTRIBUTE_UNUSED;
01324 {
01325
01326 static int last_insn_address = 0;
01327
01328 int uid = INSN_UID (insn);
01329
01330 if (TARGET_RTL_DUMP)
01331 {
01332 fprintf (asm_out_file, "\n****************");
01333 print_rtl (asm_out_file, PATTERN (insn));
01334 fprintf (asm_out_file, "\n");
01335 }
01336
01337 if (TARGET_ADDRESSES)
01338 {
01339 fprintf (asm_out_file, "; 0x%x %d\n", INSN_ADDRESSES (uid),
01340 INSN_ADDRESSES (uid) - last_insn_address);
01341 last_insn_address = INSN_ADDRESSES (uid);
01342 }
01343 }
01344
01345
01346
01347 int
01348 do_movsi (operands)
01349 rtx operands[];
01350 {
01351 rtx src = operands[1];
01352 rtx dst = operands[0];
01353 if (!reload_in_progress && !reload_completed)
01354 {
01355 if (!register_operand (dst, GET_MODE (dst)))
01356 {
01357 rtx tmp = gen_reg_rtx (GET_MODE (dst));
01358 emit_move_insn (tmp, src);
01359 operands[1] = tmp;
01360 }
01361 }
01362 return 0;
01363 }
01364
01365
01366
01367
01368
01369 int
01370 initial_offset (from, to)
01371 int from, to;
01372 {
01373 int offset = 0;
01374
01375 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
01376 offset = UNITS_PER_WORD + frame_pointer_needed * UNITS_PER_WORD;
01377 else if (from == RETURN_ADDRESS_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
01378 offset = frame_pointer_needed * UNITS_PER_WORD;
01379 else
01380 {
01381 int regno;
01382
01383 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01384 if (WORD_REG_USED (regno))
01385 offset += UNITS_PER_WORD;
01386
01387
01388
01389
01390 offset += ((get_frame_size () + STACK_BOUNDARY / BITS_PER_UNIT - 1)
01391 & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
01392
01393 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
01394 offset += UNITS_PER_WORD;
01395 }
01396 return offset;
01397 }
01398
01399 rtx
01400 h8300_return_addr_rtx (count, frame)
01401 int count;
01402 rtx frame;
01403 {
01404 rtx ret;
01405
01406 if (count == 0)
01407 ret = gen_rtx_MEM (Pmode,
01408 gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM));
01409 else if (flag_omit_frame_pointer)
01410 return (rtx) 0;
01411 else
01412 ret = gen_rtx_MEM (Pmode,
01413 memory_address (Pmode,
01414 plus_constant (frame, UNITS_PER_WORD)));
01415 set_mem_alias_set (ret, get_frame_alias_set ());
01416 return ret;
01417 }
01418
01419
01420
01421 void
01422 notice_update_cc (body, insn)
01423 rtx body;
01424 rtx insn;
01425 {
01426 switch (get_attr_cc (insn))
01427 {
01428 case CC_NONE:
01429
01430 break;
01431
01432 case CC_NONE_0HIT:
01433
01434 if (cc_status.value1 != 0
01435 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
01436 cc_status.value1 = 0;
01437 if (cc_status.value2 != 0
01438 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))
01439 cc_status.value2 = 0;
01440 break;
01441
01442 case CC_SET_ZN:
01443
01444
01445
01446 CC_STATUS_INIT;
01447 cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
01448 cc_status.value1 = recog_data.operand[0];
01449 break;
01450
01451 case CC_SET_ZNV:
01452
01453
01454
01455 CC_STATUS_INIT;
01456 cc_status.flags |= CC_NO_CARRY;
01457 cc_status.value1 = recog_data.operand[0];
01458 if (GET_CODE (body) == SET && REG_P (SET_SRC (body)))
01459 cc_status.value2 = SET_SRC (body);
01460 break;
01461
01462 case CC_COMPARE:
01463
01464 CC_STATUS_INIT;
01465 cc_status.value1 = SET_SRC (body);
01466 break;
01467
01468 case CC_CLOBBER:
01469
01470 CC_STATUS_INIT;
01471 break;
01472 }
01473 }
01474
01475
01476
01477 int
01478 bit_operator (x, mode)
01479 rtx x;
01480 enum machine_mode mode ATTRIBUTE_UNUSED;
01481 {
01482 enum rtx_code code = GET_CODE (x);
01483
01484 return (code == XOR
01485 || code == AND
01486 || code == IOR);
01487 }
01488
01489 const char *
01490 output_logical_op (mode, code, operands)
01491 enum machine_mode mode;
01492 int code;
01493 rtx *operands;
01494 {
01495
01496 unsigned HOST_WIDE_INT intval =
01497 (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
01498 ? INTVAL (operands[2]) : 0x55555555);
01499
01500
01501 unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
01502
01503 const char *opname;
01504 char insn_buf[100];
01505
01506 switch (code)
01507 {
01508 case AND:
01509 opname = "and";
01510 break;
01511 case IOR:
01512 opname = "or";
01513 break;
01514 case XOR:
01515 opname = "xor";
01516 break;
01517 default:
01518 abort ();
01519 }
01520
01521 switch (mode)
01522 {
01523 case HImode:
01524
01525 if ((TARGET_H8300H || TARGET_H8300S)
01526 && ((det & 0x00ff) != 0)
01527 && ((det & 0xff00) != 0))
01528 {
01529 sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname);
01530 output_asm_insn (insn_buf, operands);
01531 }
01532 else
01533 {
01534
01535 if ((det & 0x00ff) != 0)
01536 {
01537 sprintf (insn_buf, "%s\t%%s2,%%s0", opname);
01538 output_asm_insn (insn_buf, operands);
01539 }
01540
01541 if ((det & 0xff00) != 0)
01542 {
01543 sprintf (insn_buf, "%s\t%%t2,%%t0", opname);
01544 output_asm_insn (insn_buf, operands);
01545 }
01546 }
01547 break;
01548 case SImode:
01549
01550
01551
01552
01553
01554 if ((TARGET_H8300H || TARGET_H8300S)
01555 && ((det & 0x0000ffff) != 0)
01556 && ((det & 0xffff0000) != 0)
01557 && (code == IOR || det != 0xffffff00)
01558 && (code == IOR || det != 0xffff00ff))
01559 {
01560 sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname);
01561 output_asm_insn (insn_buf, operands);
01562 }
01563 else
01564 {
01565
01566
01567
01568
01569
01570
01571 if ((det & 0x0000ffff) == 0x0000ffff
01572 && (TARGET_H8300 ? (code == AND) : (code != IOR)))
01573 output_asm_insn ((code == AND)
01574 ? "sub.w\t%f0,%f0" : "not.w\t%f0",
01575 operands);
01576 else if ((TARGET_H8300H || TARGET_H8300S)
01577 && ((det & 0x000000ff) != 0)
01578 && ((det & 0x0000ff00) != 0))
01579 {
01580 sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname);
01581 output_asm_insn (insn_buf, operands);
01582 }
01583 else
01584 {
01585 if ((det & 0x000000ff) != 0)
01586 {
01587 sprintf (insn_buf, "%s\t%%w2,%%w0", opname);
01588 output_asm_insn (insn_buf, operands);
01589 }
01590 if ((det & 0x0000ff00) != 0)
01591 {
01592 sprintf (insn_buf, "%s\t%%x2,%%x0", opname);
01593 output_asm_insn (insn_buf, operands);
01594 }
01595 }
01596
01597 if ((det & 0xffff0000) == 0xffff0000
01598 && (TARGET_H8300 ? (code == AND) : (code != IOR)))
01599 output_asm_insn ((code == AND)
01600 ? "sub.w\t%e0,%e0" : "not.w\t%e0",
01601 operands);
01602 else if (TARGET_H8300H || TARGET_H8300S)
01603 {
01604 if ((det & 0xffff0000) != 0)
01605 {
01606 sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname);
01607 output_asm_insn (insn_buf, operands);
01608 }
01609 }
01610 else
01611 {
01612 if ((det & 0x00ff0000) != 0)
01613 {
01614 sprintf (insn_buf, "%s\t%%y2,%%y0", opname);
01615 output_asm_insn (insn_buf, operands);
01616 }
01617 if ((det & 0xff000000) != 0)
01618 {
01619 sprintf (insn_buf, "%s\t%%z2,%%z0", opname);
01620 output_asm_insn (insn_buf, operands);
01621 }
01622 }
01623 }
01624 break;
01625 default:
01626 abort ();
01627 }
01628 return "";
01629 }
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747 int
01748 nshift_operator (x, mode)
01749 rtx x;
01750 enum machine_mode mode ATTRIBUTE_UNUSED;
01751 {
01752 switch (GET_CODE (x))
01753 {
01754 case ASHIFTRT:
01755 case LSHIFTRT:
01756 case ASHIFT:
01757 return 1;
01758
01759 default:
01760 return 0;
01761 }
01762 }
01763
01764
01765
01766
01767
01768 int
01769 expand_a_shift (mode, code, operands)
01770 enum machine_mode mode;
01771 int code;
01772 rtx operands[];
01773 {
01774 emit_move_insn (operands[0], operands[1]);
01775
01776
01777
01778
01779 emit_insn (gen_rtx_PARALLEL
01780 (VOIDmode,
01781 gen_rtvec (2,
01782 gen_rtx_SET (VOIDmode, operands[0],
01783 gen_rtx (code, mode, operands[0],
01784 operands[2])),
01785 gen_rtx_CLOBBER (VOIDmode,
01786 gen_rtx_SCRATCH (QImode)))));
01787
01788 return 1;
01789 }
01790
01791
01792
01793 enum shift_alg
01794 {
01795 SHIFT_INLINE,
01796 SHIFT_ROT_AND,
01797 SHIFT_SPECIAL,
01798 SHIFT_LOOP
01799 };
01800
01801
01802
01803 enum shift_type
01804 {
01805 SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT
01806 };
01807
01808
01809
01810 enum shift_mode
01811 {
01812 QIshift, HIshift, SIshift
01813 };
01814
01815
01816
01817
01818
01819 struct shift_insn
01820 {
01821 const char *const assembler;
01822 const int cc_valid;
01823 };
01824
01825
01826
01827
01828
01829
01830 static const struct shift_insn shift_one[2][3][3] =
01831 {
01832
01833 {
01834
01835 {
01836 { "shll\t%X0", CC_NO_CARRY },
01837 { "add.w\t%T0,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01838 { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", 0 }
01839 },
01840
01841 {
01842 { "shlr\t%X0", CC_NO_CARRY },
01843 { "shlr\t%t0\n\trotxr\t%s0", 0 },
01844 { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 }
01845 },
01846
01847 {
01848 { "shar\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01849 { "shar\t%t0\n\trotxr\t%s0", 0 },
01850 { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 }
01851 }
01852 },
01853
01854 {
01855
01856 {
01857 { "shll.b\t%X0", CC_NO_CARRY },
01858 { "shll.w\t%T0", CC_NO_CARRY },
01859 { "shll.l\t%S0", CC_NO_CARRY }
01860 },
01861
01862 {
01863 { "shlr.b\t%X0", CC_NO_CARRY },
01864 { "shlr.w\t%T0", CC_NO_CARRY },
01865 { "shlr.l\t%S0", CC_NO_CARRY }
01866 },
01867
01868 {
01869 { "shar.b\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01870 { "shar.w\t%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01871 { "shar.l\t%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }
01872 }
01873 }
01874 };
01875
01876 static const struct shift_insn shift_two[3][3] =
01877 {
01878
01879 {
01880 { "shll.b\t#2,%X0", CC_NO_CARRY },
01881 { "shll.w\t#2,%T0", CC_NO_CARRY },
01882 { "shll.l\t#2,%S0", CC_NO_CARRY }
01883 },
01884
01885 {
01886 { "shlr.b\t#2,%X0", CC_NO_CARRY },
01887 { "shlr.w\t#2,%T0", CC_NO_CARRY },
01888 { "shlr.l\t#2,%S0", CC_NO_CARRY }
01889 },
01890
01891 {
01892 { "shar.b\t#2,%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01893 { "shar.w\t#2,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01894 { "shar.l\t#2,%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }
01895 }
01896 };
01897
01898
01899
01900
01901
01902 static const char *const rotate_one[2][3][3] =
01903 {
01904
01905 {
01906
01907 {
01908 "rotr\t%X0",
01909 "shlr\t%t0\n\trotxr\t%s0\n\tbst\t#7,%t0",
01910 0
01911 },
01912
01913 {
01914 "rotl\t%X0",
01915 "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
01916 0
01917 },
01918
01919 {
01920 "rotl\t%X0",
01921 "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
01922 0
01923 }
01924 },
01925
01926 {
01927
01928 {
01929 "rotr.b\t%X0",
01930 "rotr.w\t%T0",
01931 "rotr.l\t%S0"
01932 },
01933
01934 {
01935 "rotl.b\t%X0",
01936 "rotl.w\t%T0",
01937 "rotl.l\t%S0"
01938 },
01939
01940 {
01941 "rotl.b\t%X0",
01942 "rotl.w\t%T0",
01943 "rotl.l\t%S0"
01944 }
01945 }
01946 };
01947
01948 static const char *const rotate_two[3][3] =
01949 {
01950
01951 {
01952 "rotr.b\t#2,%X0",
01953 "rotr.w\t#2,%T0",
01954 "rotr.l\t#2,%S0"
01955 },
01956
01957 {
01958 "rotl.b\t#2,%X0",
01959 "rotl.w\t#2,%T0",
01960 "rotl.l\t#2,%S0"
01961 },
01962
01963 {
01964 "rotl.b\t#2,%X0",
01965 "rotl.w\t#2,%T0",
01966 "rotl.l\t#2,%S0"
01967 }
01968 };
01969
01970
01971 #define INL SHIFT_INLINE
01972 #define ROT SHIFT_ROT_AND
01973 #define LOP SHIFT_LOOP
01974 #define SPC SHIFT_SPECIAL
01975
01976
01977
01978
01979
01980
01981 static const enum shift_alg shift_alg_qi[3][3][8] = {
01982 {
01983
01984
01985 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
01986 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
01987 { INL, INL, INL, INL, INL, LOP, LOP, SPC }
01988 },
01989 {
01990
01991
01992 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
01993 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
01994 { INL, INL, INL, INL, INL, LOP, LOP, SPC }
01995 },
01996 {
01997
01998
01999 { INL, INL, INL, INL, INL, INL, ROT, ROT },
02000 { INL, INL, INL, INL, INL, INL, ROT, ROT },
02001 { INL, INL, INL, INL, INL, INL, INL, SPC }
02002 }
02003 };
02004
02005 static const enum shift_alg shift_alg_hi[3][3][16] = {
02006 {
02007
02008
02009
02010 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
02011 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
02012 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
02013 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
02014 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
02015 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
02016 },
02017 {
02018
02019
02020
02021 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
02022 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
02023 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
02024 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
02025 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
02026 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
02027 },
02028 {
02029
02030
02031
02032 { INL, INL, INL, INL, INL, INL, INL, INL,
02033 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
02034 { INL, INL, INL, INL, INL, INL, INL, INL,
02035 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
02036 { INL, INL, INL, INL, INL, INL, INL, INL,
02037 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
02038 }
02039 };
02040
02041 static const enum shift_alg shift_alg_si[3][3][32] = {
02042 {
02043
02044
02045
02046
02047
02048 { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
02049 SPC, LOP, LOP, LOP, LOP, LOP, LOP, LOP,
02050 SPC, SPC, SPC, SPC, SPC, LOP, LOP, LOP,
02051 SPC, SPC, SPC, SPC, LOP, LOP, LOP, SPC },
02052 { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
02053 SPC, SPC, LOP, LOP, LOP, LOP, LOP, SPC,
02054 SPC, SPC, SPC, LOP, LOP, LOP, LOP, LOP,
02055 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
02056 { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
02057 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
02058 SPC, SPC, LOP, LOP, LOP, LOP, LOP, LOP,
02059 SPC, SPC, SPC, LOP, LOP, LOP, LOP, SPC },
02060 },
02061 {
02062
02063
02064
02065
02066
02067 { INL, INL, INL, INL, INL, LOP, LOP, LOP,
02068 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
02069 SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
02070 SPC, LOP, LOP, LOP, ROT, ROT, ROT, SPC },
02071 { INL, INL, INL, INL, INL, LOP, LOP, LOP,
02072 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
02073 SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
02074 SPC, LOP, LOP, LOP, ROT, ROT, ROT, SPC },
02075 { INL, INL, INL, INL, INL, LOP, LOP, LOP,
02076 SPC, LOP, LOP, LOP, LOP, LOP, LOP, LOP,
02077 SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
02078 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC },
02079 },
02080 {
02081
02082
02083
02084
02085
02086 { INL, INL, INL, INL, INL, INL, INL, INL,
02087 INL, INL, INL, LOP, LOP, LOP, LOP, SPC,
02088 SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
02089 SPC, SPC, LOP, LOP, ROT, ROT, ROT, SPC },
02090 { INL, INL, INL, INL, INL, INL, INL, INL,
02091 INL, INL, INL, LOP, LOP, LOP, LOP, SPC,
02092 SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
02093 SPC, SPC, LOP, LOP, ROT, ROT, ROT, SPC },
02094 { INL, INL, INL, INL, INL, INL, INL, INL,
02095 INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
02096 SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
02097 SPC, SPC, LOP, LOP, LOP, LOP, LOP, SPC },
02098 }
02099 };
02100
02101 #undef INL
02102 #undef ROT
02103 #undef LOP
02104 #undef SPC
02105
02106 struct shift_info {
02107
02108 enum shift_alg alg;
02109
02110
02111
02112 unsigned int remainder;
02113
02114
02115 const char *special;
02116
02117
02118
02119 const char *shift1;
02120
02121
02122
02123 const char *shift2;
02124
02125
02126 int cc_valid_p;
02127 };
02128
02129 static void get_shift_alg PARAMS ((enum shift_type,
02130 enum shift_mode, unsigned int,
02131 struct shift_info *));
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 static void
02147 get_shift_alg (shift_type, shift_mode, count, info)
02148 enum shift_type shift_type;
02149 enum shift_mode shift_mode;
02150 unsigned int count;
02151 struct shift_info *info;
02152 {
02153 int cpu;
02154
02155
02156 if (TARGET_H8300)
02157 cpu = 0;
02158 else if (TARGET_H8300H)
02159 cpu = 1;
02160 else
02161 cpu = 2;
02162
02163
02164 switch (shift_mode)
02165 {
02166 case QIshift:
02167 if (GET_MODE_BITSIZE (QImode) <= count)
02168 info->alg = SHIFT_LOOP;
02169 else
02170 info->alg = shift_alg_qi[cpu][shift_type][count];
02171 break;
02172
02173 case HIshift:
02174 if (GET_MODE_BITSIZE (HImode) <= count)
02175 info->alg = SHIFT_LOOP;
02176 else
02177 info->alg = shift_alg_hi[cpu][shift_type][count];
02178 break;
02179
02180 case SIshift:
02181 if (GET_MODE_BITSIZE (SImode) <= count)
02182 info->alg = SHIFT_LOOP;
02183 else
02184 info->alg = shift_alg_si[cpu][shift_type][count];
02185 break;
02186
02187 default:
02188 abort ();
02189 }
02190
02191
02192 switch (info->alg)
02193 {
02194 case SHIFT_INLINE:
02195 info->remainder = count;
02196
02197
02198 case SHIFT_LOOP:
02199
02200 info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
02201 info->shift2 = shift_two[shift_type][shift_mode].assembler;
02202 info->cc_valid_p = shift_one[cpu_type][shift_type][shift_mode].cc_valid;
02203 goto end;
02204
02205 case SHIFT_ROT_AND:
02206 info->shift1 = rotate_one[cpu_type][shift_type][shift_mode];
02207 info->shift2 = rotate_two[shift_type][shift_mode];
02208 info->cc_valid_p = 0;
02209 goto end;
02210
02211 case SHIFT_SPECIAL:
02212
02213 info->remainder = 0;
02214 info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
02215 info->shift2 = shift_two[shift_type][shift_mode].assembler;
02216 info->cc_valid_p = 0;
02217 break;
02218 }
02219
02220
02221 switch (shift_mode)
02222 {
02223 case QIshift:
02224
02225
02226 if (shift_type == SHIFT_ASHIFTRT && count == 7)
02227 {
02228 info->special = "shll\t%X0\n\tsubx\t%X0,%X0";
02229 goto end;
02230 }
02231 abort ();
02232
02233 case HIshift:
02234 if (count == 7)
02235 {
02236 switch (shift_type)
02237 {
02238 case SHIFT_ASHIFT:
02239 if (TARGET_H8300)
02240 info->special = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.b\t%t0\n\trotr.b\t%s0\n\tand.b\t#0x80,%s0";
02241 else
02242 info->special = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.w\t%T0\n\tand.b\t#0x80,%s0";
02243 goto end;
02244 case SHIFT_LSHIFTRT:
02245 if (TARGET_H8300)
02246 info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\trotl.b\t%t0\n\tand.b\t#0x01,%t0";
02247 else
02248 info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.w\t%T0\n\tand.b\t#0x01,%t0";
02249 goto end;
02250 case SHIFT_ASHIFTRT:
02251 info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\tsubx\t%t0,%t0";
02252 goto end;
02253 }
02254 }
02255 else if (8 <= count && count <= 12)
02256 {
02257 info->remainder = count - 8;
02258
02259 switch (shift_type)
02260 {
02261 case SHIFT_ASHIFT:
02262 info->special = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0";
02263 info->shift1 = "shal.b\t%t0";
02264 info->shift2 = "shal.b\t#2,%t0";
02265 goto end;
02266 case SHIFT_LSHIFTRT:
02267 info->special = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0";
02268 info->shift1 = "shlr.b\t%s0";
02269 info->shift2 = "shlr.b\t#2,%s0";
02270 goto end;
02271 case SHIFT_ASHIFTRT:
02272 if (TARGET_H8300)
02273 info->special = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0";
02274 else
02275 info->special = "mov.b\t%t0,%s0\n\texts.w\t%T0";
02276 info->shift1 = "shar.b\t%s0";
02277 info->shift2 = "shar.b\t#2,%s0";
02278 goto end;
02279 }
02280 }
02281 else if (count == 15)
02282 {
02283 switch (shift_type)
02284 {
02285 case SHIFT_ASHIFT:
02286 info->special = "bld\t#0,%s0\n\txor\t%s0,%s0\n\txor\t%t0,%t0\n\tbst\t#7,%t0";
02287 goto end;
02288 case SHIFT_LSHIFTRT:
02289 info->special = "bld\t#7,%t0\n\txor\t%s0,%s0\n\txor\t%t0,%t0\n\tbst\t#0,%s0";
02290 goto end;
02291 case SHIFT_ASHIFTRT:
02292 info->special = "shll\t%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0";
02293 goto end;
02294 }
02295 }
02296 abort ();
02297
02298 case SIshift:
02299 if (TARGET_H8300 && 8 <= count && count <= 9)
02300 {
02301 info->remainder = count - 8;
02302
02303 switch (shift_type)
02304 {
02305 case SHIFT_ASHIFT:
02306 info->special = "mov.b\t%y0,%z0\n\tmov.b\t%x0,%y0\n\tmov.b\t%w0,%x0\n\tsub.b\t%w0,%w0";
02307 goto end;
02308 case SHIFT_LSHIFTRT:
02309 info->special = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tsub.b\t%z0,%z0";
02310 info->shift1 = "shlr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0";
02311 goto end;
02312 case SHIFT_ASHIFTRT:
02313 info->special = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tshll\t%z0\n\tsubx\t%z0,%z0";
02314 goto end;
02315 }
02316 }
02317 else if (count == 8 && !TARGET_H8300)
02318 {
02319 switch (shift_type)
02320 {
02321 case SHIFT_ASHIFT:
02322 info->special = "mov.w\t%e0,%f4\n\tmov.b\t%s4,%t4\n\tmov.b\t%t0,%s4\n\tmov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f4,%e0";
02323 goto end;
02324 case SHIFT_LSHIFTRT:
02325 info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\textu.w\t%f4\n\tmov.w\t%f4,%e0";
02326 goto end;
02327 case SHIFT_ASHIFTRT:
02328 info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\texts.w\t%f4\n\tmov.w\t%f4,%e0";
02329 goto end;
02330 }
02331 }
02332 else if (count == 15 && TARGET_H8300)
02333 {
02334 switch (shift_type)
02335 {
02336 case SHIFT_ASHIFT:
02337 abort ();
02338 case SHIFT_LSHIFTRT:
02339 info->special = "bld\t#7,%z0\n\tmov.w\t%e0,%f0\n\txor\t%y0,%y0\n\txor\t%z0,%z0\n\trotxl\t%w0,%w0\n\trotxl\t%x0,%x0\n\trotxl\t%y0,%y0";
02340 goto end;
02341 case SHIFT_ASHIFTRT:
02342 info->special = "bld\t#7,%z0\n\tmov.w\t%e0,%f0\n\trotxl\t%w0,%w0\n\trotxl\t%x0,%x0\n\tsubx\t%y0,%y0\n\tsubx\t%z0,%z0";
02343 goto end;
02344 }
02345 }
02346 else if (count == 15 && !TARGET_H8300)
02347 {
02348 switch (shift_type)
02349 {
02350 case SHIFT_ASHIFT:
02351 info->special = "shlr.w\t%e0\n\tmov.w\t%f0,%e0\n\txor.w\t%f0,%f0\n\trotxr.l\t%S0";
02352 goto end;
02353 case SHIFT_LSHIFTRT:
02354 info->special = "shll.w\t%f0\n\tmov.w\t%e0,%f0\n\txor.w\t%e0,%e0\n\trotxl.l\t%S0";
02355 goto end;
02356 case SHIFT_ASHIFTRT:
02357 abort ();
02358 }
02359 }
02360 else if ((TARGET_H8300 && 16 <= count && count <= 20)
02361 || (TARGET_H8300H && 16 <= count && count <= 19)
02362 || (TARGET_H8300S && 16 <= count && count <= 21))
02363 {
02364 info->remainder = count - 16;
02365
02366 switch (shift_type)
02367 {
02368 case SHIFT_ASHIFT:
02369 info->special = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0";
02370 if (TARGET_H8300)
02371 {
02372 info->shift1 = "add.w\t%e0,%e0";
02373 }
02374 else
02375 {
02376 info->shift1 = "shll.l\t%S0";
02377 info->shift2 = "shll.l\t#2,%S0";
02378 }
02379 goto end;
02380 case SHIFT_LSHIFTRT:
02381 info->special = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0";
02382 if (TARGET_H8300)
02383 {
02384 info->shift1 = "shlr\t%x0\n\trotxr\t%w0";
02385 }
02386 else
02387 {
02388 info->shift1 = "shlr.l\t%S0";
02389 info->shift2 = "shlr.l\t#2,%S0";
02390 }
02391 goto end;
02392 case SHIFT_ASHIFTRT:
02393 if (TARGET_H8300)
02394 {
02395 info->special = "mov.w\t%e0,%f0\n\tshll\t%z0\n\tsubx\t%z0,%z0\n\tmov.b\t%z0,%y0";
02396 info->shift1 = "shar\t%x0\n\trotxr\t%w0";
02397 }
02398 else
02399 {
02400 info->special = "mov.w\t%e0,%f0\n\texts.l\t%S0";
02401 info->shift1 = "shar.l\t%S0";
02402 info->shift2 = "shar.l\t#2,%S0";
02403 }
02404 goto end;
02405 }
02406 }
02407 else if (TARGET_H8300 && 24 <= count && count <= 28)
02408 {
02409 info->remainder = count - 24;
02410
02411 switch (shift_type)
02412 {
02413 case SHIFT_ASHIFT:
02414 info->special = "mov.b\t%w0,%z0\n\tsub.b\t%y0,%y0\n\tsub.w\t%f0,%f0";
02415 info->shift1 = "shll.b\t%z0";
02416 goto end;
02417 case SHIFT_LSHIFTRT:
02418 info->special = "mov.b\t%z0,%w0\n\tsub.b\t%x0,%x0\n\tsub.w\t%e0,%e0";
02419 info->shift1 = "shlr.b\t%w0";
02420 goto end;
02421 case SHIFT_ASHIFTRT:
02422 info->special = "mov.b\t%z0,%w0\n\tbld\t#7,%w0\n\tsubx\t%x0,%x0\n\tsubx\t%x0,%x0\n\tsubx\t%x0,%x0";
02423 info->shift1 = "shar.b\t%w0";
02424 goto end;
02425 }
02426 }
02427 else if ((TARGET_H8300H && count == 24)
02428 || (TARGET_H8300S && 24 <= count && count <= 25))
02429 {
02430 info->remainder = count - 24;
02431
02432 switch (shift_type)
02433 {
02434 case SHIFT_ASHIFT:
02435 info->special = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f0,%e0\n\tsub.w\t%f0,%f0";
02436 info->shift1 = "shll.l\t%S0";
02437 info->shift2 = "shll.l\t#2,%S0";
02438 goto end;
02439 case SHIFT_LSHIFTRT:
02440 info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\textu.w\t%f0\n\textu.l\t%S0";
02441 info->shift1 = "shlr.l\t%S0";
02442 info->shift2 = "shlr.l\t#2,%S0";
02443 goto end;
02444 case SHIFT_ASHIFTRT:
02445 info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\texts.w\t%f0\n\texts.l\t%S0";
02446 info->shift1 = "shar.l\t%S0";
02447 info->shift2 = "shar.l\t#2,%S0";
02448 goto end;
02449 }
02450 }
02451 else if (count == 31)
02452 {
02453 if (TARGET_H8300)
02454 {
02455 switch (shift_type)
02456 {
02457 case SHIFT_ASHIFT:
02458 info->special = "sub.w\t%e0,%e0\n\tshlr\t%w0\n\tmov.w\t%e0,%f0\n\trotxr\t%z0";
02459 goto end;
02460 case SHIFT_LSHIFTRT:
02461 info->special = "sub.w\t%f0,%f0\n\tshll\t%z0\n\tmov.w\t%f0,%e0\n\trotxl\t%w0";
02462 goto end;
02463 case SHIFT_ASHIFTRT:
02464 info->special = "shll\t%z0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
02465 goto end;
02466 }
02467 }
02468 else
02469 {
02470 switch (shift_type)
02471 {
02472 case SHIFT_ASHIFT:
02473 info->special = "shlr.l\t%S0\n\txor.l\t%S0,%S0\n\trotxr.l\t%S0";
02474 goto end;
02475 case SHIFT_LSHIFTRT:
02476 info->special = "shll.l\t%S0\n\txor.l\t%S0,%S0\n\trotxl.l\t%S0";
02477 goto end;
02478 case SHIFT_ASHIFTRT:
02479 info->special = "shll\t%e0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
02480 goto end;
02481 }
02482 }
02483 }
02484 abort ();
02485
02486 default:
02487 abort ();
02488 }
02489
02490 end:
02491 if (!TARGET_H8300S)
02492 info->shift2 = NULL;
02493 }
02494
02495
02496
02497 const char *
02498 output_a_shift (operands)
02499 rtx *operands;
02500 {
02501 static int loopend_lab;
02502 rtx shift = operands[3];
02503 enum machine_mode mode = GET_MODE (shift);
02504 enum rtx_code code = GET_CODE (shift);
02505 enum shift_type shift_type;
02506 enum shift_mode shift_mode;
02507 struct shift_info info;
02508
02509 loopend_lab++;
02510
02511 switch (mode)
02512 {
02513 case QImode:
02514 shift_mode = QIshift;
02515 break;
02516 case HImode:
02517 shift_mode = HIshift;
02518 break;
02519 case SImode:
02520 shift_mode = SIshift;
02521 break;
02522 default:
02523 abort ();
02524 }
02525
02526 switch (code)
02527 {
02528 case ASHIFTRT:
02529 shift_type = SHIFT_ASHIFTRT;
02530 break;
02531 case LSHIFTRT:
02532 shift_type = SHIFT_LSHIFTRT;
02533 break;
02534 case ASHIFT:
02535 shift_type = SHIFT_ASHIFT;
02536 break;
02537 default:
02538 abort ();
02539 }
02540
02541 if (GET_CODE (operands[2]) != CONST_INT)
02542 {
02543
02544 output_asm_insn ("mov.b %X2,%X4", operands);
02545 fprintf (asm_out_file, "\tble .Lle%d\n", loopend_lab);
02546
02547
02548 get_shift_alg (shift_type, shift_mode, 1, &info);
02549
02550 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
02551 output_asm_insn (info.shift1, operands);
02552 output_asm_insn ("add #0xff,%X4", operands);
02553 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
02554 fprintf (asm_out_file, ".Lle%d:\n", loopend_lab);
02555
02556 return "";
02557 }
02558 else
02559 {
02560 int n = INTVAL (operands[2]);
02561
02562
02563 if (n < 0)
02564 n = 0;
02565
02566
02567
02568 else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
02569 n = GET_MODE_BITSIZE (mode);
02570
02571 get_shift_alg (shift_type, shift_mode, n, &info);
02572
02573 switch (info.alg)
02574 {
02575 case SHIFT_SPECIAL:
02576 output_asm_insn (info.special, operands);
02577
02578
02579 case SHIFT_INLINE:
02580 n = info.remainder;
02581
02582
02583 if (info.shift2 != NULL)
02584 {
02585 for (; n > 1; n -= 2)
02586 output_asm_insn (info.shift2, operands);
02587 }
02588
02589
02590 for (; n > 0; n--)
02591 output_asm_insn (info.shift1, operands);
02592
02593
02594 if (info.cc_valid_p)
02595 {
02596 cc_status.value1 = operands[0];
02597 cc_status.flags |= info.cc_valid_p;
02598 }
02599 return "";
02600
02601 case SHIFT_ROT_AND:
02602 {
02603 int m = GET_MODE_BITSIZE (mode) - n;
02604 int mask = (shift_type == SHIFT_ASHIFT
02605 ? ((1 << m) - 1) << n
02606 : (1 << m) - 1);
02607 char insn_buf[200];
02608
02609
02610
02611 if (info.shift1 == 0)
02612 abort ();
02613
02614
02615 if (info.shift2 != NULL)
02616 {
02617 for (; m > 1; m -= 2)
02618 output_asm_insn (info.shift2, operands);
02619 }
02620
02621
02622 for (; m > 0; m--)
02623 output_asm_insn (info.shift1, operands);
02624
02625
02626 if (TARGET_H8300)
02627 {
02628 switch (mode)
02629 {
02630 case QImode:
02631 sprintf (insn_buf, "and\t#%d,%%X0", mask);
02632 cc_status.value1 = operands[0];
02633 cc_status.flags |= CC_NO_CARRY;
02634 break;
02635 case HImode:
02636 sprintf (insn_buf, "and\t#%d,%%s0\n\tand\t#%d,%%t0",
02637 mask & 255, mask >> 8);
02638 break;
02639 default:
02640 abort ();
02641 }
02642 }
02643 else
02644 {
02645 sprintf (insn_buf, "and.%c\t#%d,%%%c0",
02646 "bwl"[shift_mode], mask,
02647 mode == QImode ? 'X' : mode == HImode ? 'T' : 'S');
02648 cc_status.value1 = operands[0];
02649 cc_status.flags |= CC_NO_CARRY;
02650 }
02651 output_asm_insn (insn_buf, operands);
02652 return "";
02653 }
02654
02655 case SHIFT_LOOP:
02656
02657
02658 if (info.shift2 != NULL)
02659 {
02660 fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n / 2,
02661 names_big[REGNO (operands[4])]);
02662 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
02663 output_asm_insn (info.shift2, operands);
02664 output_asm_insn ("add #0xff,%X4", operands);
02665 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
02666 if (n % 2)
02667 output_asm_insn (info.shift1, operands);
02668 }
02669 else
02670 {
02671 fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n,
02672 names_big[REGNO (operands[4])]);
02673 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
02674 output_asm_insn (info.shift1, operands);
02675 output_asm_insn ("add #0xff,%X4", operands);
02676 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
02677 }
02678 return "";
02679
02680 default:
02681 abort ();
02682 }
02683 }
02684 }
02685
02686
02687
02688
02689
02690
02691 int
02692 expand_a_rotate (code, operands)
02693 enum rtx_code code;
02694 rtx operands[];
02695 {
02696 rtx dst = operands[0];
02697 rtx src = operands[1];
02698 rtx rotate_amount = operands[2];
02699 enum machine_mode mode = GET_MODE (dst);
02700 rtx tmp;
02701
02702
02703 emit_move_insn (dst, src);
02704
02705 if (GET_CODE (rotate_amount) != CONST_INT)
02706 {
02707 rtx counter = gen_reg_rtx (QImode);
02708 rtx start_label = gen_label_rtx ();
02709 rtx end_label = gen_label_rtx ();
02710
02711
02712
02713 emit_cmp_and_jump_insns (rotate_amount, GEN_INT (0), LE, NULL_RTX,
02714 QImode, 0, end_label);
02715
02716
02717 emit_move_insn (counter, rotate_amount);
02718
02719 emit_label (start_label);
02720
02721
02722 tmp = gen_rtx (code, mode, dst, GEN_INT (1));
02723 emit_insn (gen_rtx_SET (mode, dst, tmp));
02724
02725
02726 tmp = gen_rtx_PLUS (QImode, counter, GEN_INT (-1));
02727 emit_insn (gen_rtx_SET (VOIDmode, counter, tmp));
02728
02729
02730
02731 emit_cmp_and_jump_insns (counter, GEN_INT (0), NE, NULL_RTX, QImode, 1,
02732 start_label);
02733
02734 emit_label (end_label);
02735 }
02736 else
02737 {
02738
02739 tmp = gen_rtx (code, mode, dst, rotate_amount);
02740 emit_insn (gen_rtx_SET (mode, dst, tmp));
02741 }
02742
02743 return 1;
02744 }
02745
02746
02747
02748 const char *
02749 emit_a_rotate (code, operands)
02750 enum rtx_code code;
02751 rtx *operands;
02752 {
02753 rtx dst = operands[0];
02754 rtx rotate_amount = operands[2];
02755 enum shift_mode rotate_mode;
02756 enum shift_type rotate_type;
02757 const char *insn_buf;
02758 int bits;
02759 int amount;
02760 enum machine_mode mode = GET_MODE (dst);
02761
02762 if (GET_CODE (rotate_amount) != CONST_INT)
02763 abort ();
02764
02765 switch (mode)
02766 {
02767 case QImode:
02768 rotate_mode = QIshift;
02769 break;
02770 case HImode:
02771 rotate_mode = HIshift;
02772 break;
02773 case SImode:
02774 rotate_mode = SIshift;
02775 break;
02776 default:
02777 abort ();
02778 }
02779
02780 switch (code)
02781 {
02782 case ROTATERT:
02783 rotate_type = SHIFT_ASHIFT;
02784 break;
02785 case ROTATE:
02786 rotate_type = SHIFT_LSHIFTRT;
02787 break;
02788 default:
02789 abort ();
02790 }
02791
02792 amount = INTVAL (rotate_amount);
02793
02794
02795 if (amount < 0)
02796 amount = 0;
02797 if ((unsigned int) amount > GET_MODE_BITSIZE (mode))
02798 amount = GET_MODE_BITSIZE (mode);
02799
02800
02801
02802 if ((unsigned int) amount > GET_MODE_BITSIZE (mode) / 2U)
02803 {
02804
02805 amount = GET_MODE_BITSIZE (mode) - amount;
02806 rotate_type =
02807 (rotate_type == SHIFT_ASHIFT) ? SHIFT_LSHIFTRT : SHIFT_ASHIFT;
02808 }
02809
02810
02811
02812 if ((mode == HImode && TARGET_H8300 && amount >= 5)
02813 || (mode == HImode && TARGET_H8300H && amount >= 6)
02814 || (mode == HImode && TARGET_H8300S && amount == 8)
02815 || (mode == SImode && TARGET_H8300H && amount >= 10)
02816 || (mode == SImode && TARGET_H8300S && amount >= 13))
02817 {
02818 switch (mode)
02819 {
02820 case HImode:
02821
02822 insn_buf = "xor.b\t%s0,%t0\n\txor.b\t%t0,%s0\n\txor.b\t%s0,%t0";
02823 output_asm_insn (insn_buf, operands);
02824 break;
02825
02826 case SImode:
02827
02828 insn_buf = "xor.w\t%e0,%f0\n\txor.w\t%f0,%e0\n\txor.w\t%e0,%f0";
02829 output_asm_insn (insn_buf, operands);
02830 break;
02831
02832 default:
02833 abort ();
02834 }
02835
02836
02837 amount = GET_MODE_BITSIZE (mode) / 2 - amount;
02838 rotate_type =
02839 (rotate_type == SHIFT_ASHIFT) ? SHIFT_LSHIFTRT : SHIFT_ASHIFT;
02840 }
02841
02842
02843 for (bits = TARGET_H8300S ? 2 : 1; bits > 0; bits /= 2)
02844 {
02845 if (bits == 2)
02846 insn_buf = rotate_two[rotate_type][rotate_mode];
02847 else
02848 insn_buf = rotate_one[cpu_type][rotate_type][rotate_mode];
02849
02850 for (; amount >= bits; amount -= bits)
02851 output_asm_insn (insn_buf, operands);
02852 }
02853
02854 return "";
02855 }
02856
02857
02858
02859
02860 int
02861 fix_bit_operand (operands, what, type)
02862 rtx *operands;
02863 int what;
02864 enum rtx_code type;
02865 {
02866
02867
02868
02869
02870 if (GET_CODE (operands[2]) == CONST_INT)
02871 {
02872 if (CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), what))
02873 {
02874
02875 if (GET_CODE (operands[0]) == MEM
02876 && !EXTRA_CONSTRAINT (operands[0], 'U'))
02877 {
02878 rtx mem = gen_rtx_MEM (GET_MODE (operands[0]),
02879 copy_to_mode_reg (Pmode,
02880 XEXP (operands[0], 0)));
02881 MEM_COPY_ATTRIBUTES (mem, operands[0]);
02882 operands[0] = mem;
02883 }
02884
02885 if (GET_CODE (operands[1]) == MEM
02886 && !EXTRA_CONSTRAINT (operands[1], 'U'))
02887 {
02888 rtx mem = gen_rtx_MEM (GET_MODE (operands[1]),
02889 copy_to_mode_reg (Pmode,
02890 XEXP (operands[1], 0)));
02891 MEM_COPY_ATTRIBUTES (mem, operands[0]);
02892 operands[1] = mem;
02893 }
02894 return 0;
02895 }
02896 }
02897
02898
02899
02900 operands[1] = force_reg (QImode, operands[1]);
02901 {
02902 rtx res = gen_reg_rtx (QImode);
02903 emit_insn (gen_rtx_SET (VOIDmode, res,
02904 gen_rtx (type, QImode, operands[1], operands[2])));
02905 emit_insn (gen_rtx_SET (VOIDmode, operands[0], res));
02906 }
02907 return 1;
02908 }
02909
02910
02911
02912
02913 static int
02914 h8300_interrupt_function_p (func)
02915 tree func;
02916 {
02917 tree a;
02918
02919 if (TREE_CODE (func) != FUNCTION_DECL)
02920 return 0;
02921
02922 a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
02923 return a != NULL_TREE;
02924 }
02925
02926
02927
02928
02929 static int
02930 h8300_os_task_function_p (func)
02931 tree func;
02932 {
02933 tree a;
02934
02935 if (TREE_CODE (func) != FUNCTION_DECL)
02936 return 0;
02937
02938 a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
02939 return a != NULL_TREE;
02940 }
02941
02942
02943
02944
02945 static int
02946 h8300_monitor_function_p (func)
02947 tree func;
02948 {
02949 tree a;
02950
02951 if (TREE_CODE (func) != FUNCTION_DECL)
02952 return 0;
02953
02954 a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
02955 return a != NULL_TREE;
02956 }
02957
02958
02959
02960
02961 int
02962 h8300_funcvec_function_p (func)
02963 tree func;
02964 {
02965 tree a;
02966
02967 if (TREE_CODE (func) != FUNCTION_DECL)
02968 return 0;
02969
02970 a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
02971 return a != NULL_TREE;
02972 }
02973
02974
02975
02976
02977 int
02978 h8300_eightbit_data_p (decl)
02979 tree decl;
02980 {
02981 tree a;
02982
02983 if (TREE_CODE (decl) != VAR_DECL)
02984 return 0;
02985
02986 a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
02987 return a != NULL_TREE;
02988 }
02989
02990
02991
02992
02993 int
02994 h8300_tiny_data_p (decl)
02995 tree decl;
02996 {
02997 tree a;
02998
02999 if (TREE_CODE (decl) != VAR_DECL)
03000 return 0;
03001
03002 a = lookup_attribute ("tiny_data", DECL_ATTRIBUTES (decl));
03003 return a != NULL_TREE;
03004 }
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020 const struct attribute_spec h8300_attribute_table[] =
03021 {
03022
03023 { "interrupt_handler", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
03024 { "OS_Task", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
03025 { "monitor", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
03026 { "function_vector", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
03027 { "eightbit_data", 0, 0, true, false, false, h8300_handle_eightbit_data_attribute },
03028 { "tiny_data", 0, 0, true, false, false, h8300_handle_tiny_data_attribute },
03029 { NULL, 0, 0, false, false, false, NULL }
03030 };
03031
03032
03033
03034
03035 static tree
03036 h8300_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
03037 tree *node;
03038 tree name;
03039 tree args ATTRIBUTE_UNUSED;
03040 int flags ATTRIBUTE_UNUSED;
03041 bool *no_add_attrs;
03042 {
03043 if (TREE_CODE (*node) != FUNCTION_DECL)
03044 {
03045 warning ("`%s' attribute only applies to functions",
03046 IDENTIFIER_POINTER (name));
03047 *no_add_attrs = true;
03048 }
03049
03050 return NULL_TREE;
03051 }
03052
03053
03054
03055 static tree
03056 h8300_handle_eightbit_data_attribute (node, name, args, flags, no_add_attrs)
03057 tree *node;
03058 tree name;
03059 tree args ATTRIBUTE_UNUSED;
03060 int flags ATTRIBUTE_UNUSED;
03061 bool *no_add_attrs;
03062 {
03063 tree decl = *node;
03064
03065 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
03066 {
03067 DECL_SECTION_NAME (decl) = build_string (7, ".eight");
03068 }
03069 else
03070 {
03071 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
03072 *no_add_attrs = true;
03073 }
03074
03075 return NULL_TREE;
03076 }
03077
03078
03079
03080 static tree
03081 h8300_handle_tiny_data_attribute (node, name, args, flags, no_add_attrs)
03082 tree *node;
03083 tree name;
03084 tree args ATTRIBUTE_UNUSED;
03085 int flags ATTRIBUTE_UNUSED;
03086 bool *no_add_attrs;
03087 {
03088 tree decl = *node;
03089
03090 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
03091 {
03092 DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
03093 }
03094 else
03095 {
03096 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
03097 *no_add_attrs = true;
03098 }
03099
03100 return NULL_TREE;
03101 }
03102
03103 void
03104 h8300_encode_label (decl)
03105 tree decl;
03106 {
03107 const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
03108 int len = strlen (str);
03109 char *newstr = alloca (len + 2);
03110
03111 newstr[0] = '&';
03112 strcpy (&newstr[1], str);
03113
03114 XSTR (XEXP (DECL_RTL (decl), 0), 0) =
03115 ggc_alloc_string (newstr, len + 1);
03116 }
03117
03118 const char *
03119 output_simode_bld (bild, operands)
03120 int bild;
03121 rtx operands[];
03122 {
03123 if (TARGET_H8300)
03124 {
03125
03126 output_asm_insn ("sub.w\t%e0,%e0\n\tsub.w\t%f0,%f0", operands);
03127
03128
03129
03130 if (bild)
03131 output_asm_insn ("bild\t%Z2,%Y1", operands);
03132 else
03133 output_asm_insn ("bld\t%Z2,%Y1", operands);
03134
03135 output_asm_insn ("bst\t#0,%w0", operands);
03136 }
03137 else
03138 {
03139
03140 if (bild)
03141 output_asm_insn ("bild\t%Z2,%Y1", operands);
03142 else
03143 output_asm_insn ("bld\t%Z2,%Y1", operands);
03144
03145
03146 output_asm_insn ("xor.l\t%S0,%S0\n\tbst\t#0,%w0", operands);
03147 }
03148
03149
03150 return "";
03151 }
03152
03153
03154
03155
03156
03157
03158 int
03159 h8300_adjust_insn_length (insn, length)
03160 rtx insn;
03161 int length ATTRIBUTE_UNUSED;
03162 {
03163 rtx pat = PATTERN (insn);
03164
03165
03166 if (GET_CODE (pat) == USE
03167 || GET_CODE (pat) == CLOBBER
03168 || GET_CODE (pat) == SEQUENCE
03169 || GET_CODE (pat) == ADDR_VEC
03170 || GET_CODE (pat) == ADDR_DIFF_VEC)
03171 return 0;
03172
03173 if (get_attr_adjust_length (insn) == ADJUST_LENGTH_NO)
03174 return 0;
03175
03176
03177 if (GET_CODE (pat) == SET
03178 && (GET_CODE (SET_SRC (pat)) == MEM
03179 || GET_CODE (SET_DEST (pat)) == MEM))
03180 {
03181
03182 rtx addr;
03183
03184 if (GET_CODE (SET_SRC (pat)) == MEM)
03185 addr = XEXP (SET_SRC (pat), 0);
03186 else
03187 addr = XEXP (SET_DEST (pat), 0);
03188
03189
03190
03191
03192 if (TARGET_H8300 && GET_CODE (addr) == REG)
03193 return -2;
03194
03195
03196
03197 if ((TARGET_H8300H || TARGET_H8300S)
03198 && GET_CODE (addr) == REG)
03199 return -6;
03200
03201
03202
03203 if ((TARGET_H8300H || TARGET_H8300S)
03204 && GET_CODE (addr) == PLUS
03205 && GET_CODE (XEXP (addr, 0)) == REG
03206 && GET_CODE (XEXP (addr, 1)) == CONST_INT
03207 && INTVAL (XEXP (addr, 1)) > -32768
03208 && INTVAL (XEXP (addr, 1)) < 32767)
03209 return -4;
03210
03211
03212
03213 if ((TARGET_H8300H || TARGET_H8300S)
03214 && GET_CODE (addr) == SYMBOL_REF
03215 && TINY_DATA_NAME_P (XSTR (addr, 0)))
03216 return -2;
03217 }
03218
03219
03220 if (GET_CODE (pat) == SET
03221 && GET_CODE (SET_SRC (pat)) == CONST_INT
03222 && GET_MODE (SET_DEST (pat)) == SImode
03223 && INTVAL (SET_SRC (pat)) != 0)
03224 {
03225 int val = INTVAL (SET_SRC (pat));
03226
03227 if (TARGET_H8300
03228 && ((val & 0xffff) == 0
03229 || ((val >> 16) & 0xffff) == 0))
03230 return -2;
03231
03232 if (TARGET_H8300H || TARGET_H8300S)
03233 {
03234 if (val == (val & 0xff)
03235 || val == (val & 0xff00))
03236 return 4 - 6;
03237
03238 switch (val & 0xffffffff)
03239 {
03240 case 0xffffffff:
03241 case 0xfffffffe:
03242 case 0xfffffffc:
03243 case 0x0000ffff:
03244 case 0x0000fffe:
03245 case 0xffff0000:
03246 case 0xfffe0000:
03247 case 0x00010000:
03248 case 0x00020000:
03249 return 4 - 6;
03250 }
03251 }
03252 }
03253
03254
03255 if (GET_CODE (pat) == PARALLEL
03256 && GET_CODE (XVECEXP (pat, 0, 0)) == SET
03257 && (GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFTRT
03258 || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == LSHIFTRT
03259 || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFT))
03260 {
03261 rtx src = SET_SRC (XVECEXP (pat, 0, 0));
03262 enum machine_mode mode = GET_MODE (src);
03263 int shift;
03264
03265 if (GET_CODE (XEXP (src, 1)) != CONST_INT)
03266 return 0;
03267
03268 shift = INTVAL (XEXP (src, 1));
03269
03270
03271
03272 if (shift < 0)
03273 shift = 0;
03274
03275
03276
03277
03278 if (mode == QImode && shift <= 4)
03279 return -(20 - shift * 2);
03280
03281
03282
03283 if ((TARGET_H8300H || TARGET_H8300S)
03284 && (mode == HImode || mode == SImode) && shift <= 4)
03285 return -(20 - shift * 2);
03286
03287
03288 if (mode == HImode && shift <= 4)
03289 return -(20 - (shift * (GET_CODE (src) == ASHIFT ? 2 : 4)));
03290
03291
03292 if (mode == SImode && shift <= 2)
03293 return -(20 - (shift * (GET_CODE (src) == ASHIFT ? 6 : 8)));
03294
03295
03296 }
03297
03298
03299 if (GET_CODE (pat) == SET
03300 && (GET_CODE (SET_SRC (pat)) == ROTATE
03301 || GET_CODE (SET_SRC (pat)) == ROTATERT))
03302 {
03303 rtx src = SET_SRC (pat);
03304 enum machine_mode mode = GET_MODE (src);
03305 int amount;
03306 int states = 0;
03307
03308 if (GET_CODE (XEXP (src, 1)) != CONST_INT)
03309 return 0;
03310
03311 amount = INTVAL (XEXP (src, 1));
03312
03313
03314 if (amount < 0)
03315 amount = 0;
03316 if ((unsigned int) amount > GET_MODE_BITSIZE (mode))
03317 amount = GET_MODE_BITSIZE (mode);
03318
03319
03320
03321 if ((unsigned int) amount > GET_MODE_BITSIZE (mode) / 2U)
03322
03323 amount = GET_MODE_BITSIZE (mode) - amount;
03324
03325
03326
03327 if ((mode == HImode && TARGET_H8300 && amount >= 5)
03328 || (mode == HImode && TARGET_H8300H && amount >= 6)
03329 || (mode == HImode && TARGET_H8300S && amount == 8)
03330 || (mode == SImode && TARGET_H8300H && amount >= 10)
03331 || (mode == SImode && TARGET_H8300S && amount >= 13))
03332 {
03333
03334 amount = GET_MODE_BITSIZE (mode) / 2 - amount;
03335 states += 6;
03336 }
03337
03338
03339 if (TARGET_H8300S)
03340 amount = amount / 2 + amount % 2;
03341
03342
03343
03344 states += amount * ((TARGET_H8300 && mode == HImode) ? 6 : 2);
03345
03346 return -(20 - states);
03347 }
03348
03349 return 0;
03350 }
03351
03352 #ifndef OBJECT_FORMAT_ELF
03353 static void
03354 h8300_asm_named_section (name, flags)
03355 const char *name;
03356 unsigned int flags ATTRIBUTE_UNUSED;
03357 {
03358
03359 fprintf (asm_out_file, "\t.section %s\n", name);
03360 }
03361 #endif