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 "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "regs.h"
00031 #include "hard-reg-set.h"
00032 #include "real.h"
00033 #include "insn-config.h"
00034 #include "conditions.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "flags.h"
00038 #include "recog.h"
00039 #include "expr.h"
00040 #include "function.h"
00041 #include "optabs.h"
00042 #include "toplev.h"
00043 #include "c-pragma.h"
00044 #include "tm_p.h"
00045 #include "ggc.h"
00046 #include "target.h"
00047 #include "target-def.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 enum h8300_operand_class
00066 {
00067 H8OP_IMMEDIATE,
00068 H8OP_REGISTER,
00069 H8OP_MEM_ABSOLUTE,
00070 H8OP_MEM_BASE,
00071 H8OP_MEM_COMPLEX,
00072 NUM_H8OPS
00073 };
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 enum h8sx_shift_type
00089 {
00090 H8SX_SHIFT_NONE,
00091 H8SX_SHIFT_UNARY,
00092 H8SX_SHIFT_BINARY
00093 };
00094
00095
00096
00097
00098 typedef unsigned char h8300_length_table[NUM_H8OPS - 1][NUM_H8OPS];
00099
00100
00101 static const char *byte_reg (rtx, int);
00102 static int h8300_interrupt_function_p (tree);
00103 static int h8300_saveall_function_p (tree);
00104 static int h8300_monitor_function_p (tree);
00105 static int h8300_os_task_function_p (tree);
00106 static void h8300_emit_stack_adjustment (int, unsigned int);
00107 static int round_frame_size (int);
00108 static unsigned int compute_saved_regs (void);
00109 static void push (int);
00110 static void pop (int);
00111 static const char *cond_string (enum rtx_code);
00112 static unsigned int h8300_asm_insn_count (const char *);
00113 static tree h8300_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
00114 static tree h8300_handle_eightbit_data_attribute (tree *, tree, tree, int, bool *);
00115 static tree h8300_handle_tiny_data_attribute (tree *, tree, tree, int, bool *);
00116 #ifndef OBJECT_FORMAT_ELF
00117 static void h8300_asm_named_section (const char *, unsigned int, tree);
00118 #endif
00119 static int h8300_and_costs (rtx);
00120 static int h8300_shift_costs (rtx);
00121 static void h8300_push_pop (int, int, int, int);
00122 static int h8300_stack_offset_p (rtx, int);
00123 static int h8300_ldm_stm_regno (rtx, int, int, int);
00124 static int h8300_ldm_stm_parallel (rtvec, int, int);
00125 static void h8300_reorg (void);
00126 static unsigned int h8300_constant_length (rtx);
00127 static unsigned int h8300_displacement_length (rtx, int);
00128 static unsigned int h8300_classify_operand (rtx, int, enum h8300_operand_class *);
00129 static unsigned int h8300_length_from_table (rtx, rtx, const h8300_length_table *);
00130 static unsigned int h8300_unary_length (rtx);
00131 static unsigned int h8300_short_immediate_length (rtx);
00132 static unsigned int h8300_bitfield_length (rtx, rtx);
00133 static unsigned int h8300_binary_length (rtx, const h8300_length_table *);
00134 static bool h8300_short_move_mem_p (rtx, enum rtx_code);
00135 static unsigned int h8300_move_length (rtx *, const h8300_length_table *);
00136 enum h8sx_shift_type h8sx_classify_shift (enum machine_mode, enum rtx_code, rtx);
00137
00138
00139 int cpu_type;
00140
00141
00142 static int pragma_interrupt;
00143
00144
00145 static int pragma_saveall;
00146
00147 static const char *const names_big[] =
00148 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
00149
00150 static const char *const names_extended[] =
00151 { "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7" };
00152
00153 static const char *const names_upper_extended[] =
00154 { "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7" };
00155
00156
00157
00158 const char * const *h8_reg_names;
00159
00160
00161
00162 const char *h8_push_op, *h8_pop_op, *h8_mov_op;
00163
00164
00165 int h8300_move_ratio;
00166
00167
00168 #define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
00169 #define SYMBOL_FLAG_EIGHTBIT_DATA (SYMBOL_FLAG_MACH_DEP << 1)
00170 #define SYMBOL_FLAG_TINY_DATA (SYMBOL_FLAG_MACH_DEP << 2)
00171
00172
00173
00174 enum shift_alg
00175 {
00176 SHIFT_INLINE,
00177 SHIFT_ROT_AND,
00178 SHIFT_SPECIAL,
00179 SHIFT_LOOP
00180 };
00181
00182
00183
00184 enum shift_type
00185 {
00186 SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT
00187 };
00188
00189
00190 #define INL SHIFT_INLINE
00191 #define ROT SHIFT_ROT_AND
00192 #define LOP SHIFT_LOOP
00193 #define SPC SHIFT_SPECIAL
00194
00195
00196
00197
00198
00199
00200 static enum shift_alg shift_alg_qi[3][3][8] = {
00201 {
00202
00203
00204 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
00205 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
00206 { INL, INL, INL, INL, INL, LOP, LOP, SPC }
00207 },
00208 {
00209
00210
00211 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
00212 { INL, INL, INL, INL, INL, ROT, ROT, ROT },
00213 { INL, INL, INL, INL, INL, LOP, LOP, SPC }
00214 },
00215 {
00216
00217
00218 { INL, INL, INL, INL, INL, INL, ROT, ROT },
00219 { INL, INL, INL, INL, INL, INL, ROT, ROT },
00220 { INL, INL, INL, INL, INL, INL, INL, SPC }
00221 }
00222 };
00223
00224 static enum shift_alg shift_alg_hi[3][3][16] = {
00225 {
00226
00227
00228
00229 { INL, INL, INL, INL, INL, INL, INL, SPC,
00230 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC },
00231 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
00232 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC },
00233 { INL, INL, INL, INL, INL, LOP, LOP, SPC,
00234 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC },
00235 },
00236 {
00237
00238
00239
00240 { INL, INL, INL, INL, INL, INL, INL, SPC,
00241 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
00242 { INL, INL, INL, INL, INL, INL, INL, SPC,
00243 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
00244 { INL, INL, INL, INL, INL, INL, INL, SPC,
00245 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC },
00246 },
00247 {
00248
00249
00250
00251 { INL, INL, INL, INL, INL, INL, INL, INL,
00252 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
00253 { INL, INL, INL, INL, INL, INL, INL, INL,
00254 SPC, SPC, SPC, SPC, SPC, ROT, ROT, ROT },
00255 { INL, INL, INL, INL, INL, INL, INL, INL,
00256 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC },
00257 }
00258 };
00259
00260 static enum shift_alg shift_alg_si[3][3][32] = {
00261 {
00262
00263
00264
00265
00266
00267 { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
00268 SPC, LOP, LOP, LOP, LOP, LOP, LOP, LOP,
00269 SPC, SPC, SPC, SPC, SPC, LOP, LOP, LOP,
00270 SPC, SPC, SPC, SPC, LOP, LOP, LOP, SPC },
00271 { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
00272 SPC, SPC, LOP, LOP, LOP, LOP, LOP, SPC,
00273 SPC, SPC, SPC, LOP, LOP, LOP, LOP, LOP,
00274 SPC, SPC, SPC, SPC, SPC, LOP, LOP, SPC },
00275 { INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
00276 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
00277 SPC, SPC, LOP, LOP, LOP, LOP, LOP, LOP,
00278 SPC, SPC, SPC, LOP, LOP, LOP, LOP, SPC },
00279 },
00280 {
00281
00282
00283
00284
00285
00286 { INL, INL, INL, INL, INL, LOP, LOP, LOP,
00287 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
00288 SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
00289 SPC, LOP, LOP, LOP, SPC, SPC, SPC, SPC },
00290 { INL, INL, INL, INL, INL, LOP, LOP, LOP,
00291 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC,
00292 SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
00293 SPC, LOP, LOP, LOP, SPC, SPC, SPC, SPC },
00294 { INL, INL, INL, INL, INL, LOP, LOP, LOP,
00295 SPC, LOP, LOP, LOP, LOP, LOP, LOP, LOP,
00296 SPC, SPC, SPC, SPC, LOP, LOP, LOP, LOP,
00297 SPC, LOP, LOP, LOP, LOP, LOP, LOP, SPC },
00298 },
00299 {
00300
00301
00302
00303
00304
00305 { INL, INL, INL, INL, INL, INL, INL, INL,
00306 INL, INL, INL, LOP, LOP, LOP, LOP, SPC,
00307 SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
00308 SPC, SPC, LOP, LOP, SPC, SPC, SPC, SPC },
00309 { INL, INL, INL, INL, INL, INL, INL, INL,
00310 INL, INL, INL, LOP, LOP, LOP, LOP, SPC,
00311 SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
00312 SPC, SPC, LOP, LOP, SPC, SPC, SPC, SPC },
00313 { INL, INL, INL, INL, INL, INL, INL, INL,
00314 INL, INL, INL, LOP, LOP, LOP, LOP, LOP,
00315 SPC, SPC, SPC, SPC, SPC, SPC, LOP, LOP,
00316 SPC, SPC, LOP, LOP, LOP, LOP, LOP, SPC },
00317 }
00318 };
00319
00320 #undef INL
00321 #undef ROT
00322 #undef LOP
00323 #undef SPC
00324
00325 enum h8_cpu
00326 {
00327 H8_300,
00328 H8_300H,
00329 H8_S
00330 };
00331
00332
00333
00334 void
00335 h8300_init_once (void)
00336 {
00337 static const char *const h8_push_ops[2] = { "push" , "push.l" };
00338 static const char *const h8_pop_ops[2] = { "pop" , "pop.l" };
00339 static const char *const h8_mov_ops[2] = { "mov.w", "mov.l" };
00340
00341 if (TARGET_H8300)
00342 {
00343 cpu_type = (int) CPU_H8300;
00344 h8_reg_names = names_big;
00345 }
00346 else
00347 {
00348
00349 cpu_type = (int) CPU_H8300H;
00350 h8_reg_names = names_extended;
00351 }
00352 h8_push_op = h8_push_ops[cpu_type];
00353 h8_pop_op = h8_pop_ops[cpu_type];
00354 h8_mov_op = h8_mov_ops[cpu_type];
00355
00356 if (!TARGET_H8300S && TARGET_MAC)
00357 {
00358 error ("-ms2600 is used without -ms");
00359 target_flags |= MASK_H8300S;
00360 }
00361
00362 if (TARGET_H8300 && TARGET_NORMAL_MODE)
00363 {
00364 error ("-mn is used without -mh or -ms");
00365 target_flags ^= MASK_NORMAL_MODE;
00366 }
00367
00368
00369
00370
00371
00372 if (optimize_size)
00373 {
00374
00375 shift_alg_hi[H8_300][SHIFT_ASHIFT][5] = SHIFT_LOOP;
00376 shift_alg_hi[H8_300][SHIFT_ASHIFT][6] = SHIFT_LOOP;
00377 shift_alg_hi[H8_300][SHIFT_ASHIFT][13] = SHIFT_LOOP;
00378 shift_alg_hi[H8_300][SHIFT_ASHIFT][14] = SHIFT_LOOP;
00379
00380 shift_alg_hi[H8_300][SHIFT_LSHIFTRT][13] = SHIFT_LOOP;
00381 shift_alg_hi[H8_300][SHIFT_LSHIFTRT][14] = SHIFT_LOOP;
00382
00383 shift_alg_hi[H8_300][SHIFT_ASHIFTRT][13] = SHIFT_LOOP;
00384 shift_alg_hi[H8_300][SHIFT_ASHIFTRT][14] = SHIFT_LOOP;
00385
00386
00387 shift_alg_hi[H8_300H][SHIFT_ASHIFT][5] = SHIFT_LOOP;
00388 shift_alg_hi[H8_300H][SHIFT_ASHIFT][6] = SHIFT_LOOP;
00389
00390 shift_alg_hi[H8_300H][SHIFT_LSHIFTRT][5] = SHIFT_LOOP;
00391 shift_alg_hi[H8_300H][SHIFT_LSHIFTRT][6] = SHIFT_LOOP;
00392
00393 shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][5] = SHIFT_LOOP;
00394 shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][6] = SHIFT_LOOP;
00395 shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][13] = SHIFT_LOOP;
00396 shift_alg_hi[H8_300H][SHIFT_ASHIFTRT][14] = SHIFT_LOOP;
00397
00398
00399 shift_alg_hi[H8_S][SHIFT_ASHIFTRT][14] = SHIFT_LOOP;
00400 }
00401
00402
00403 if (!TARGET_H8300SX)
00404 {
00405
00406
00407 h8300_move_ratio = 3;
00408 }
00409 else if (flag_omit_frame_pointer)
00410 {
00411
00412
00413
00414
00415 h8300_move_ratio = 4;
00416 }
00417 else if (optimize_size)
00418 {
00419
00420
00421
00422
00423 h8300_move_ratio = 4;
00424 }
00425 else
00426 {
00427
00428
00429
00430 h8300_move_ratio = 6;
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 enum reg_class
00469 h8300_reg_class_from_letter (int c)
00470 {
00471 switch (c)
00472 {
00473 case 'a':
00474 return MAC_REGS;
00475
00476 case 'c':
00477 return COUNTER_REGS;
00478
00479 case 'd':
00480 if (!flag_omit_frame_pointer && !reload_completed)
00481 return NO_REGS;
00482 if (frame_pointer_needed && reload_in_progress)
00483 return NO_REGS;
00484 return DESTINATION_REGS;
00485
00486 case 'D':
00487
00488
00489 return GENERAL_REGS;
00490
00491 case 'f':
00492 return SOURCE_REGS;
00493
00494 default:
00495 return NO_REGS;
00496 }
00497 }
00498
00499
00500
00501
00502
00503 static const char *
00504 byte_reg (rtx x, int b)
00505 {
00506 static const char *const names_small[] = {
00507 "r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
00508 "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"
00509 };
00510
00511 if (!REG_P (x))
00512 abort ();
00513
00514 return names_small[REGNO (x) * 2 + b];
00515 }
00516
00517
00518
00519 #define WORD_REG_USED(regno) \
00520 (regno < SP_REG \
00521 \
00522 && ! TREE_THIS_VOLATILE (current_function_decl) \
00523 && (h8300_saveall_function_p (current_function_decl) \
00524 \
00525 || (regs_ever_live[regno] && !call_used_regs[regno]) \
00526 \
00527 || (regno == HARD_FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
00528 \
00529 || (h8300_current_function_interrupt_function_p () \
00530 && regs_ever_live[regno]) \
00531
00532 \
00533 || (h8300_current_function_interrupt_function_p () \
00534 && call_used_regs[regno] \
00535 && !current_function_is_leaf)))
00536
00537
00538
00539
00540 static void
00541 h8300_emit_stack_adjustment (int sign, unsigned int size)
00542 {
00543
00544 if (size == 0)
00545 return;
00546
00547
00548
00549
00550 if (TARGET_H8300
00551 && size > 4
00552 && !h8300_current_function_interrupt_function_p ()
00553 && !(cfun->static_chain_decl != NULL && sign < 0))
00554 {
00555 rtx r3 = gen_rtx_REG (Pmode, 3);
00556 emit_insn (gen_movhi (r3, GEN_INT (sign * size)));
00557 emit_insn (gen_addhi3 (stack_pointer_rtx,
00558 stack_pointer_rtx, r3));
00559 }
00560 else
00561 {
00562
00563
00564
00565
00566 if (Pmode == HImode)
00567 emit_insn (gen_addhi3 (stack_pointer_rtx,
00568 stack_pointer_rtx, GEN_INT (sign * size)));
00569 else
00570 emit_insn (gen_addsi3 (stack_pointer_rtx,
00571 stack_pointer_rtx, GEN_INT (sign * size)));
00572 }
00573 }
00574
00575
00576
00577 static int
00578 round_frame_size (int size)
00579 {
00580 return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
00581 & -STACK_BOUNDARY / BITS_PER_UNIT);
00582 }
00583
00584
00585
00586
00587 static unsigned int
00588 compute_saved_regs (void)
00589 {
00590 unsigned int saved_regs = 0;
00591 int regno;
00592
00593
00594 for (regno = 0; regno <= HARD_FRAME_POINTER_REGNUM; regno++)
00595 {
00596 if (WORD_REG_USED (regno))
00597 saved_regs |= 1 << regno;
00598 }
00599
00600
00601 if (frame_pointer_needed)
00602 saved_regs &= ~(1 << HARD_FRAME_POINTER_REGNUM);
00603
00604 return saved_regs;
00605 }
00606
00607
00608
00609 static void
00610 push (int rn)
00611 {
00612 rtx reg = gen_rtx_REG (word_mode, rn);
00613 rtx x;
00614
00615 if (TARGET_H8300)
00616 x = gen_push_h8300 (reg);
00617 else if (!TARGET_NORMAL_MODE)
00618 x = gen_push_h8300hs_advanced (reg);
00619 else
00620 x = gen_push_h8300hs_normal (reg);
00621 x = emit_insn (x);
00622 REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0);
00623 }
00624
00625
00626
00627 static void
00628 pop (int rn)
00629 {
00630 rtx reg = gen_rtx_REG (word_mode, rn);
00631 rtx x;
00632
00633 if (TARGET_H8300)
00634 x = gen_pop_h8300 (reg);
00635 else if (!TARGET_NORMAL_MODE)
00636 x = gen_pop_h8300hs_advanced (reg);
00637 else
00638 x = gen_pop_h8300hs_normal (reg);
00639 x = emit_insn (x);
00640 REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0);
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 static void
00660 h8300_push_pop (int regno, int nregs, int pop_p, int return_p)
00661 {
00662 int i, j;
00663 rtvec vec;
00664 rtx sp, offset;
00665
00666
00667 if (!return_p && nregs == 1)
00668 {
00669 if (pop_p)
00670 pop (regno);
00671 else
00672 push (regno);
00673 return;
00674 }
00675
00676
00677
00678 vec = rtvec_alloc ((return_p != 0) + nregs + 1);
00679 sp = stack_pointer_rtx;
00680 i = 0;
00681
00682
00683 if (return_p)
00684 {
00685 RTVEC_ELT (vec, i) = gen_rtx_RETURN (VOIDmode);
00686 i++;
00687 }
00688
00689
00690 for (j = 0; j < nregs; j++)
00691 {
00692 rtx lhs, rhs;
00693
00694 if (pop_p)
00695 {
00696
00697
00698 lhs = gen_rtx_REG (SImode, regno + j);
00699 rhs = gen_rtx_MEM (SImode, plus_constant (sp, (nregs - j - 1) * 4));
00700 }
00701 else
00702 {
00703
00704 lhs = gen_rtx_MEM (SImode, plus_constant (sp, (j + 1) * -4));
00705 rhs = gen_rtx_REG (SImode, regno + j);
00706 }
00707 RTVEC_ELT (vec, i + j) = gen_rtx_SET (VOIDmode, lhs, rhs);
00708 }
00709
00710
00711 offset = GEN_INT ((pop_p ? nregs : -nregs) * 4);
00712 RTVEC_ELT (vec, i + j) = gen_rtx_SET (VOIDmode, sp,
00713 gen_rtx_PLUS (Pmode, sp, offset));
00714
00715 emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
00716 }
00717
00718
00719
00720 static int
00721 h8300_stack_offset_p (rtx x, int offset)
00722 {
00723 if (offset == 0)
00724 return x == stack_pointer_rtx;
00725
00726 return (GET_CODE (x) == PLUS
00727 && XEXP (x, 0) == stack_pointer_rtx
00728 && GET_CODE (XEXP (x, 1)) == CONST_INT
00729 && INTVAL (XEXP (x, 1)) == offset);
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 static int
00743 h8300_ldm_stm_regno (rtx x, int load_p, int index, int nregs)
00744 {
00745 int regindex, memindex, offset;
00746
00747 if (load_p)
00748 regindex = 0, memindex = 1, offset = (nregs - index - 1) * 4;
00749 else
00750 memindex = 0, regindex = 1, offset = (index + 1) * -4;
00751
00752 if (GET_CODE (x) == SET
00753 && GET_CODE (XEXP (x, regindex)) == REG
00754 && GET_CODE (XEXP (x, memindex)) == MEM
00755 && h8300_stack_offset_p (XEXP (XEXP (x, memindex), 0), offset))
00756 return REGNO (XEXP (x, regindex));
00757
00758 return -1;
00759 }
00760
00761
00762
00763
00764 static int
00765 h8300_ldm_stm_parallel (rtvec vec, int load_p, int first)
00766 {
00767 rtx last;
00768 int nregs, i, regno, adjust;
00769
00770
00771
00772 if (GET_NUM_ELEM (vec) < 3)
00773 return false;
00774
00775
00776 nregs = GET_NUM_ELEM (vec) - first - 1;
00777 regno = h8300_ldm_stm_regno (RTVEC_ELT (vec, first), load_p, 0, nregs);
00778
00779
00780
00781 if (regno < 0 || regno + nregs > 8)
00782 return false;
00783
00784
00785
00786 if (!TARGET_H8300SX)
00787 {
00788 if ((regno & 1) != 0)
00789 return false;
00790 if (nregs > 2 && (regno & 3) != 0)
00791 return false;
00792 }
00793
00794
00795 for (i = 1; i < nregs; i++)
00796 if (h8300_ldm_stm_regno (RTVEC_ELT (vec, first + i), load_p, i, nregs)
00797 != regno + i)
00798 return false;
00799
00800
00801 last = RTVEC_ELT (vec, first + nregs);
00802 adjust = (load_p ? nregs : -nregs) * 4;
00803 return (GET_CODE (last) == SET
00804 && SET_DEST (last) == stack_pointer_rtx
00805 && h8300_stack_offset_p (SET_SRC (last), adjust));
00806 }
00807
00808
00809
00810 int
00811 h8300_ldm_parallel (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
00812 {
00813 return h8300_ldm_stm_parallel (XVEC (x, 0), 1, 0);
00814 }
00815
00816
00817
00818 int
00819 h8300_stm_parallel (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
00820 {
00821 return h8300_ldm_stm_parallel (XVEC (x, 0), 0, 0);
00822 }
00823
00824
00825
00826
00827 int
00828 h8300_return_parallel (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
00829 {
00830 return h8300_ldm_stm_parallel (XVEC (x, 0), 1, 1);
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 void
00854 h8300_expand_prologue (void)
00855 {
00856 int regno;
00857 int saved_regs;
00858 int n_regs;
00859
00860
00861
00862 if (h8300_os_task_function_p (current_function_decl))
00863 return;
00864
00865 if (h8300_monitor_function_p (current_function_decl))
00866
00867
00868
00869 emit_insn (gen_monitor_prologue ());
00870
00871 if (frame_pointer_needed)
00872 {
00873
00874 push (HARD_FRAME_POINTER_REGNUM);
00875 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
00876 }
00877
00878
00879 saved_regs = compute_saved_regs ();
00880 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs)
00881 {
00882 n_regs = 1;
00883 if (saved_regs & (1 << regno))
00884 {
00885 if (TARGET_H8300S)
00886 {
00887
00888 if ((!TARGET_H8300SX || (regno & 3) == 0)
00889 && ((saved_regs >> regno) & 0x0f) == 0x0f)
00890 n_regs = 4;
00891
00892 else if ((!TARGET_H8300SX || (regno & 3) == 0)
00893 && ((saved_regs >> regno) & 0x07) == 0x07)
00894 n_regs = 3;
00895
00896 else if ((!TARGET_H8300SX || (regno & 1) == 0)
00897 && ((saved_regs >> regno) & 0x03) == 0x03)
00898 n_regs = 2;
00899 }
00900
00901 h8300_push_pop (regno, n_regs, 0, 0);
00902 }
00903 }
00904
00905
00906 h8300_emit_stack_adjustment (-1, round_frame_size (get_frame_size ()));
00907 }
00908
00909
00910
00911
00912 int
00913 h8300_can_use_return_insn_p (void)
00914 {
00915 return (reload_completed
00916 && !frame_pointer_needed
00917 && get_frame_size () == 0
00918 && compute_saved_regs () == 0);
00919 }
00920
00921
00922
00923 void
00924 h8300_expand_epilogue (void)
00925 {
00926 int regno;
00927 int saved_regs;
00928 int n_regs;
00929 HOST_WIDE_INT frame_size;
00930 bool returned_p;
00931
00932 if (h8300_os_task_function_p (current_function_decl))
00933
00934
00935 return;
00936
00937 frame_size = round_frame_size (get_frame_size ());
00938 returned_p = false;
00939
00940
00941 h8300_emit_stack_adjustment (1, frame_size);
00942
00943
00944 saved_regs = compute_saved_regs ();
00945 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno -= n_regs)
00946 {
00947 n_regs = 1;
00948 if (saved_regs & (1 << regno))
00949 {
00950 if (TARGET_H8300S)
00951 {
00952
00953 if ((TARGET_H8300SX || (regno & 3) == 3)
00954 && ((saved_regs << 3 >> regno) & 0x0f) == 0x0f)
00955 n_regs = 4;
00956
00957 else if ((TARGET_H8300SX || (regno & 3) == 2)
00958 && ((saved_regs << 2 >> regno) & 0x07) == 0x07)
00959 n_regs = 3;
00960
00961 else if ((TARGET_H8300SX || (regno & 1) == 1)
00962 && ((saved_regs << 1 >> regno) & 0x03) == 0x03)
00963 n_regs = 2;
00964 }
00965
00966
00967
00968 if (TARGET_H8300SX
00969 && !frame_pointer_needed
00970 && frame_size == 0
00971 && (saved_regs & ((1 << (regno - n_regs + 1)) - 1)) == 0)
00972 returned_p = true;
00973
00974 h8300_push_pop (regno - n_regs + 1, n_regs, 1, returned_p);
00975 }
00976 }
00977
00978
00979 if (frame_pointer_needed)
00980 {
00981 if (TARGET_H8300SX)
00982 returned_p = true;
00983 h8300_push_pop (HARD_FRAME_POINTER_REGNUM, 1, 1, returned_p);
00984 }
00985
00986 if (!returned_p)
00987 emit_insn (gen_rtx_RETURN (VOIDmode));
00988 }
00989
00990
00991
00992
00993 int
00994 h8300_current_function_interrupt_function_p (void)
00995 {
00996 return (h8300_interrupt_function_p (current_function_decl)
00997 || h8300_monitor_function_p (current_function_decl));
00998 }
00999
01000
01001
01002 static void
01003 h8300_file_start (void)
01004 {
01005 default_file_start ();
01006
01007 if (TARGET_H8300H)
01008 fputs (TARGET_NORMAL_MODE ? "\t.h8300hn\n" : "\t.h8300h\n", asm_out_file);
01009 else if (TARGET_H8300SX)
01010 fputs (TARGET_NORMAL_MODE ? "\t.h8300sxn\n" : "\t.h8300sx\n", asm_out_file);
01011 else if (TARGET_H8300S)
01012 fputs (TARGET_NORMAL_MODE ? "\t.h8300sn\n" : "\t.h8300s\n", asm_out_file);
01013 }
01014
01015
01016
01017 static void
01018 h8300_file_end (void)
01019 {
01020 fputs ("\t.end\n", asm_out_file);
01021 }
01022
01023
01024
01025
01026 int
01027 general_operand_src (rtx op, enum machine_mode mode)
01028 {
01029 if (GET_MODE (op) == mode
01030 && GET_CODE (op) == MEM
01031 && GET_CODE (XEXP (op, 0)) == POST_INC)
01032 return 1;
01033 return general_operand (op, mode);
01034 }
01035
01036
01037
01038
01039 int
01040 general_operand_dst (rtx op, enum machine_mode mode)
01041 {
01042 if (GET_MODE (op) == mode
01043 && GET_CODE (op) == MEM
01044 && GET_CODE (XEXP (op, 0)) == PRE_DEC)
01045 return 1;
01046 return general_operand (op, mode);
01047 }
01048
01049
01050
01051
01052 int
01053 h8300_dst_operand (rtx op, enum machine_mode mode)
01054 {
01055 if (TARGET_H8300SX)
01056 return nonimmediate_operand (op, mode);
01057 return register_operand (op, mode);
01058 }
01059
01060
01061
01062 int
01063 h8300_src_operand (rtx op, enum machine_mode mode)
01064 {
01065 if (TARGET_H8300SX)
01066 return general_operand (op, mode);
01067 return nonmemory_operand (op, mode);
01068 }
01069
01070
01071
01072
01073 int
01074 nibble_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01075 {
01076 return (GET_CODE (op) == CONST_INT && TARGET_H8300SX
01077 && INTVAL (op) >= 0 && INTVAL (op) <= 15);
01078 }
01079
01080
01081
01082
01083 int
01084 reg_or_nibble_operand (rtx op, enum machine_mode mode)
01085 {
01086 return (nibble_operand (op, mode) || register_operand (op, mode));
01087 }
01088
01089
01090
01091
01092 int
01093 single_one_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
01094 {
01095 if (GET_CODE (operand) == CONST_INT)
01096 {
01097
01098
01099 if (exact_log2 (INTVAL (operand) & GET_MODE_MASK (mode)) >= 0)
01100 return 1;
01101 }
01102
01103 return 0;
01104 }
01105
01106
01107
01108
01109 int
01110 single_zero_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
01111 {
01112 if (GET_CODE (operand) == CONST_INT)
01113 {
01114
01115
01116 if (exact_log2 (~INTVAL (operand) & GET_MODE_MASK (mode)) >= 0)
01117 return 1;
01118 }
01119
01120 return 0;
01121 }
01122
01123
01124
01125 int
01126 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01127 {
01128 if (GET_CODE (op) == MEM)
01129 {
01130 rtx inside = XEXP (op, 0);
01131 if (register_operand (inside, Pmode))
01132 return 1;
01133 if (CONSTANT_ADDRESS_P (inside))
01134 return 1;
01135 }
01136 return 0;
01137 }
01138
01139
01140
01141
01142
01143 int
01144 two_insn_adds_subs_operand (rtx op, enum machine_mode mode)
01145 {
01146 if (TARGET_H8300SX)
01147 return 0;
01148
01149 if (GET_CODE (op) == CONST_INT)
01150 {
01151 HOST_WIDE_INT value = INTVAL (op);
01152
01153
01154
01155 if (value < 0)
01156 value = -value;
01157 if (TARGET_H8300H || TARGET_H8300S)
01158 {
01159
01160
01161
01162
01163 if (mode == SImode
01164 && (value == 2 + 1
01165 || value == 4 + 1
01166 || value == 4 + 2
01167 || value == 4 + 4))
01168 return 1;
01169 }
01170 else
01171 {
01172
01173
01174
01175
01176 if (mode == HImode
01177 && (value == 2 + 1
01178 || value == 2 + 2))
01179 return 1;
01180 }
01181 }
01182
01183 return 0;
01184 }
01185
01186
01187
01188
01189
01190
01191 void
01192 split_adds_subs (enum machine_mode mode, rtx *operands)
01193 {
01194 HOST_WIDE_INT val = INTVAL (operands[1]);
01195 rtx reg = operands[0];
01196 HOST_WIDE_INT sign = 1;
01197 HOST_WIDE_INT amount;
01198 rtx (*gen_add) (rtx, rtx, rtx);
01199
01200
01201
01202 if (val < 0)
01203 {
01204 val = -val;
01205 sign = -1;
01206 }
01207
01208 switch (mode)
01209 {
01210 case HImode:
01211 gen_add = gen_addhi3;
01212 break;
01213
01214 case SImode:
01215 gen_add = gen_addsi3;
01216 break;
01217
01218 default:
01219 abort ();
01220 }
01221
01222
01223 for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
01224 amount > 0;
01225 amount /= 2)
01226 {
01227 for (; val >= amount; val -= amount)
01228 emit_insn (gen_add (reg, reg, GEN_INT (sign * amount)));
01229 }
01230
01231 return;
01232 }
01233
01234
01235
01236
01237 int
01238 small_call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01239 {
01240 if (GET_CODE (op) == MEM)
01241 {
01242 rtx inside = XEXP (op, 0);
01243
01244
01245 if (register_operand (inside, Pmode))
01246 return 1;
01247
01248
01249 if (GET_CODE (inside) == SYMBOL_REF
01250 && (SYMBOL_REF_FLAGS (inside) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
01251 return 1;
01252 }
01253
01254 return 0;
01255 }
01256
01257
01258
01259 int
01260 jump_address_operand (rtx op, enum machine_mode mode)
01261 {
01262 if (GET_CODE (op) == REG)
01263 return mode == Pmode;
01264
01265 if (GET_CODE (op) == MEM)
01266 {
01267 rtx inside = XEXP (op, 0);
01268 if (register_operand (inside, Pmode))
01269 return 1;
01270 if (CONSTANT_ADDRESS_P (inside))
01271 return 1;
01272 }
01273 return 0;
01274 }
01275
01276
01277
01278 int
01279 bit_operand (rtx op, enum machine_mode mode)
01280 {
01281
01282
01283 if (!nonimmediate_operand (op, mode))
01284 return 0;
01285
01286
01287 if (TARGET_H8300SX)
01288 return 1;
01289
01290
01291
01292
01293
01294
01295
01296 if (GET_CODE (op) == REG)
01297 return 1;
01298 if (GET_CODE (op) == SUBREG)
01299 return 1;
01300 return (GET_CODE (op) == MEM
01301 && OK_FOR_U (op));
01302 }
01303
01304
01305
01306 int
01307 bit_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01308 {
01309 return (GET_CODE (op) == MEM
01310 && OK_FOR_U (op));
01311 }
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 void
01324 h8300_pr_interrupt (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
01325 {
01326 pragma_interrupt = 1;
01327 }
01328
01329 void
01330 h8300_pr_saveall (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
01331 {
01332 pragma_saveall = 1;
01333 }
01334
01335
01336
01337
01338
01339
01340 rtx
01341 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
01342 tree type, int named)
01343 {
01344 static const char *const hand_list[] = {
01345 "__main",
01346 "__cmpsi2",
01347 "__divhi3",
01348 "__modhi3",
01349 "__udivhi3",
01350 "__umodhi3",
01351 "__divsi3",
01352 "__modsi3",
01353 "__udivsi3",
01354 "__umodsi3",
01355 "__mulhi3",
01356 "__mulsi3",
01357 "__reg_memcpy",
01358 "__reg_memset",
01359 "__ucmpsi2",
01360 0,
01361 };
01362
01363 rtx result = NULL_RTX;
01364 const char *fname;
01365 int regpass = 0;
01366
01367
01368 if (!named)
01369 return NULL_RTX;
01370
01371
01372 if (TARGET_QUICKCALL)
01373 regpass = 3;
01374
01375
01376 if (cum->libcall)
01377 {
01378 const char * const *p;
01379
01380 fname = XSTR (cum->libcall, 0);
01381
01382
01383 for (p = hand_list; *p && strcmp (*p, fname) != 0; p++)
01384 ;
01385
01386 if (*p)
01387 regpass = 4;
01388 }
01389
01390 if (regpass)
01391 {
01392 int size;
01393
01394 if (mode == BLKmode)
01395 size = int_size_in_bytes (type);
01396 else
01397 size = GET_MODE_SIZE (mode);
01398
01399 if (size + cum->nbytes <= regpass * UNITS_PER_WORD
01400 && cum->nbytes / UNITS_PER_WORD <= 3)
01401 result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
01402 }
01403
01404 return result;
01405 }
01406
01407
01408
01409 static int
01410 h8300_and_costs (rtx x)
01411 {
01412 rtx operands[4];
01413
01414 if (GET_MODE (x) == QImode)
01415 return 1;
01416
01417 if (GET_MODE (x) != HImode
01418 && GET_MODE (x) != SImode)
01419 return 100;
01420
01421 operands[0] = NULL;
01422 operands[1] = XEXP (x, 0);
01423 operands[2] = XEXP (x, 1);
01424 operands[3] = x;
01425 return compute_logical_op_length (GET_MODE (x), operands) / 2;
01426 }
01427
01428
01429
01430 static int
01431 h8300_shift_costs (rtx x)
01432 {
01433 rtx operands[4];
01434
01435 if (GET_MODE (x) != QImode
01436 && GET_MODE (x) != HImode
01437 && GET_MODE (x) != SImode)
01438 return 100;
01439
01440 operands[0] = NULL;
01441 operands[1] = NULL;
01442 operands[2] = XEXP (x, 1);
01443 operands[3] = x;
01444 return compute_a_shift_length (NULL, operands) / 2;
01445 }
01446
01447
01448
01449 static bool
01450 h8300_rtx_costs (rtx x, int code, int outer_code, int *total)
01451 {
01452 if (TARGET_H8300SX && outer_code == MEM)
01453 {
01454
01455
01456 if (register_operand (x, VOIDmode)
01457 || GET_CODE (x) == POST_INC
01458 || GET_CODE (x) == POST_DEC
01459 || CONSTANT_P (x))
01460 *total = 0;
01461 else
01462 *total = COSTS_N_INSNS (1);
01463 return true;
01464 }
01465
01466 switch (code)
01467 {
01468 case CONST_INT:
01469 {
01470 HOST_WIDE_INT n = INTVAL (x);
01471
01472 if (TARGET_H8300SX)
01473 {
01474
01475
01476
01477
01478 *total = 0;
01479 return true;
01480 }
01481 if (-4 <= n || n <= 4)
01482 {
01483 switch ((int) n)
01484 {
01485 case 0:
01486 *total = 0;
01487 return true;
01488 case 1:
01489 case 2:
01490 case -1:
01491 case -2:
01492 *total = 0 + (outer_code == SET);
01493 return true;
01494 case 4:
01495 case -4:
01496 if (TARGET_H8300H || TARGET_H8300S)
01497 *total = 0 + (outer_code == SET);
01498 else
01499 *total = 1;
01500 return true;
01501 }
01502 }
01503 *total = 1;
01504 return true;
01505 }
01506
01507 case CONST:
01508 case LABEL_REF:
01509 case SYMBOL_REF:
01510 if (TARGET_H8300SX)
01511 {
01512
01513 *total = 0;
01514 return true;
01515 }
01516 *total = 3;
01517 return true;
01518
01519 case CONST_DOUBLE:
01520 *total = 20;
01521 return true;
01522
01523 case AND:
01524 if (!h8300_dst_operand (XEXP (x, 0), VOIDmode)
01525 || !h8300_src_operand (XEXP (x, 1), VOIDmode))
01526 return false;
01527 *total = COSTS_N_INSNS (h8300_and_costs (x));
01528 return true;
01529
01530
01531
01532 case MOD:
01533 case DIV:
01534 case UMOD:
01535 case UDIV:
01536 if (TARGET_H8300SX)
01537 switch (GET_MODE (x))
01538 {
01539 case QImode:
01540 case HImode:
01541 *total = COSTS_N_INSNS (optimize_size ? 4 : 10);
01542 return false;
01543
01544 case SImode:
01545 *total = COSTS_N_INSNS (optimize_size ? 4 : 18);
01546 return false;
01547
01548 default:
01549 break;
01550 }
01551 *total = COSTS_N_INSNS (12);
01552 return true;
01553
01554 case MULT:
01555 if (TARGET_H8300SX)
01556 switch (GET_MODE (x))
01557 {
01558 case QImode:
01559 case HImode:
01560 *total = COSTS_N_INSNS (2);
01561 return false;
01562
01563 case SImode:
01564 *total = COSTS_N_INSNS (5);
01565 return false;
01566
01567 default:
01568 break;
01569 }
01570 *total = COSTS_N_INSNS (4);
01571 return true;
01572
01573 case ASHIFT:
01574 case ASHIFTRT:
01575 case LSHIFTRT:
01576 if (h8sx_binary_shift_operator (x, VOIDmode))
01577 {
01578 *total = COSTS_N_INSNS (2);
01579 return false;
01580 }
01581 else if (h8sx_unary_shift_operator (x, VOIDmode))
01582 {
01583 *total = COSTS_N_INSNS (1);
01584 return false;
01585 }
01586 *total = COSTS_N_INSNS (h8300_shift_costs (x));
01587 return true;
01588
01589 case ROTATE:
01590 case ROTATERT:
01591 if (GET_MODE (x) == HImode)
01592 *total = 2;
01593 else
01594 *total = 8;
01595 return true;
01596
01597 default:
01598 *total = COSTS_N_INSNS (1);
01599 return false;
01600 }
01601 }
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637 static const char *
01638 cond_string (enum rtx_code code)
01639 {
01640 switch (code)
01641 {
01642 case NE:
01643 return "ne";
01644 case EQ:
01645 return "eq";
01646 case GE:
01647 return "ge";
01648 case GT:
01649 return "gt";
01650 case LE:
01651 return "le";
01652 case LT:
01653 return "lt";
01654 case GEU:
01655 return "hs";
01656 case GTU:
01657 return "hi";
01658 case LEU:
01659 return "ls";
01660 case LTU:
01661 return "lo";
01662 default:
01663 abort ();
01664 }
01665 }
01666
01667
01668
01669
01670 void
01671 print_operand (FILE *file, rtx x, int code)
01672 {
01673
01674 static int bitint;
01675
01676 switch (code)
01677 {
01678 case 'E':
01679 switch (GET_CODE (x))
01680 {
01681 case REG:
01682 fprintf (file, "%sl", names_big[REGNO (x)]);
01683 break;
01684 case CONST_INT:
01685 fprintf (file, "#%ld", (-INTVAL (x)) & 0xff);
01686 break;
01687 default:
01688 abort ();
01689 }
01690 break;
01691 case 'F':
01692 switch (GET_CODE (x))
01693 {
01694 case REG:
01695 fprintf (file, "%sh", names_big[REGNO (x)]);
01696 break;
01697 case CONST_INT:
01698 fprintf (file, "#%ld", ((-INTVAL (x)) & 0xff00) >> 8);
01699 break;
01700 default:
01701 abort ();
01702 }
01703 break;
01704 case 'G':
01705 if (GET_CODE (x) != CONST_INT)
01706 abort ();
01707 fprintf (file, "#%ld", 0xff & (-INTVAL (x)));
01708 break;
01709 case 'S':
01710 if (GET_CODE (x) == REG)
01711 fprintf (file, "%s", names_extended[REGNO (x)]);
01712 else
01713 goto def;
01714 break;
01715 case 'T':
01716 if (GET_CODE (x) == REG)
01717 fprintf (file, "%s", names_big[REGNO (x)]);
01718 else
01719 goto def;
01720 break;
01721 case 'V':
01722 bitint = exact_log2 (INTVAL (x) & 0xff);
01723 if (bitint == -1)
01724 abort ();
01725 fprintf (file, "#%d", bitint);
01726 break;
01727 case 'W':
01728 bitint = exact_log2 ((~INTVAL (x)) & 0xff);
01729 if (bitint == -1)
01730 abort ();
01731 fprintf (file, "#%d", bitint);
01732 break;
01733 case 'R':
01734 case 'X':
01735 if (GET_CODE (x) == REG)
01736 fprintf (file, "%s", byte_reg (x, 0));
01737 else
01738 goto def;
01739 break;
01740 case 'Y':
01741 if (bitint == -1)
01742 abort ();
01743 if (GET_CODE (x) == REG)
01744 fprintf (file, "%s%c", names_big[REGNO (x)], bitint > 7 ? 'h' : 'l');
01745 else
01746 print_operand (file, x, 'R');
01747 bitint = -1;
01748 break;
01749 case 'Z':
01750 bitint = INTVAL (x);
01751 fprintf (file, "#%d", bitint & 7);
01752 break;
01753 case 'c':
01754 switch (GET_CODE (x))
01755 {
01756 case IOR:
01757 fprintf (file, "or");
01758 break;
01759 case XOR:
01760 fprintf (file, "xor");
01761 break;
01762 case AND:
01763 fprintf (file, "and");
01764 break;
01765 default:
01766 break;
01767 }
01768 break;
01769 case 'e':
01770 switch (GET_CODE (x))
01771 {
01772 case REG:
01773 if (TARGET_H8300)
01774 fprintf (file, "%s", names_big[REGNO (x)]);
01775 else
01776 fprintf (file, "%s", names_upper_extended[REGNO (x)]);
01777 break;
01778 case MEM:
01779 print_operand (file, x, 0);
01780 break;
01781 case CONST_INT:
01782 fprintf (file, "#%ld", ((INTVAL (x) >> 16) & 0xffff));
01783 break;
01784 case CONST_DOUBLE:
01785 {
01786 long val;
01787 REAL_VALUE_TYPE rv;
01788 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01789 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01790 fprintf (file, "#%ld", ((val >> 16) & 0xffff));
01791 break;
01792 }
01793 default:
01794 abort ();
01795 break;
01796 }
01797 break;
01798 case 'f':
01799 switch (GET_CODE (x))
01800 {
01801 case REG:
01802 if (TARGET_H8300)
01803 fprintf (file, "%s", names_big[REGNO (x) + 1]);
01804 else
01805 fprintf (file, "%s", names_big[REGNO (x)]);
01806 break;
01807 case MEM:
01808 x = adjust_address (x, HImode, 2);
01809 print_operand (file, x, 0);
01810 break;
01811 case CONST_INT:
01812 fprintf (file, "#%ld", INTVAL (x) & 0xffff);
01813 break;
01814 case CONST_DOUBLE:
01815 {
01816 long val;
01817 REAL_VALUE_TYPE rv;
01818 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01819 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01820 fprintf (file, "#%ld", (val & 0xffff));
01821 break;
01822 }
01823 default:
01824 abort ();
01825 }
01826 break;
01827 case 'j':
01828 fputs (cond_string (GET_CODE (x)), file);
01829 break;
01830 case 'k':
01831 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
01832 break;
01833 case 'm':
01834 if (GET_CODE (x) != CONST_INT)
01835 abort ();
01836 if (INTVAL (x) == 1)
01837 fputs (".b", file);
01838 else if (INTVAL (x) == 2)
01839 fputs (".w", file);
01840 else if (INTVAL (x) == 4)
01841 fputs (".l", file);
01842 else
01843 abort ();
01844 break;
01845 case 'o':
01846 print_operand_address (file, x);
01847 break;
01848 case 's':
01849 if (GET_CODE (x) == CONST_INT)
01850 fprintf (file, "#%ld", (INTVAL (x)) & 0xff);
01851 else
01852 fprintf (file, "%s", byte_reg (x, 0));
01853 break;
01854 case 't':
01855 if (GET_CODE (x) == CONST_INT)
01856 fprintf (file, "#%ld", (INTVAL (x) >> 8) & 0xff);
01857 else
01858 fprintf (file, "%s", byte_reg (x, 1));
01859 break;
01860 case 'w':
01861 if (GET_CODE (x) == CONST_INT)
01862 fprintf (file, "#%ld", INTVAL (x) & 0xff);
01863 else
01864 fprintf (file, "%s",
01865 byte_reg (x, TARGET_H8300 ? 2 : 0));
01866 break;
01867 case 'x':
01868 if (GET_CODE (x) == CONST_INT)
01869 fprintf (file, "#%ld", (INTVAL (x) >> 8) & 0xff);
01870 else
01871 fprintf (file, "%s",
01872 byte_reg (x, TARGET_H8300 ? 3 : 1));
01873 break;
01874 case 'y':
01875 if (GET_CODE (x) == CONST_INT)
01876 fprintf (file, "#%ld", (INTVAL (x) >> 16) & 0xff);
01877 else
01878 fprintf (file, "%s", byte_reg (x, 0));
01879 break;
01880 case 'z':
01881 if (GET_CODE (x) == CONST_INT)
01882 fprintf (file, "#%ld", (INTVAL (x) >> 24) & 0xff);
01883 else
01884 fprintf (file, "%s", byte_reg (x, 1));
01885 break;
01886
01887 default:
01888 def:
01889 switch (GET_CODE (x))
01890 {
01891 case REG:
01892 switch (GET_MODE (x))
01893 {
01894 case QImode:
01895 #if 0
01896 fprintf (file, "%s", byte_reg (x, 0));
01897 #else
01898 fprintf (file, "%s", names_big[REGNO (x)]);
01899 #endif
01900 break;
01901 case HImode:
01902 fprintf (file, "%s", names_big[REGNO (x)]);
01903 break;
01904 case SImode:
01905 case SFmode:
01906 fprintf (file, "%s", names_extended[REGNO (x)]);
01907 break;
01908 default:
01909 abort ();
01910 }
01911 break;
01912
01913 case MEM:
01914 {
01915 rtx addr = XEXP (x, 0);
01916
01917 fprintf (file, "@");
01918 output_address (addr);
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928 if (CONSTANT_P (addr))
01929 switch (code)
01930 {
01931 case 'R':
01932
01933 if (h8300_eightbit_constant_address_p (addr))
01934 {
01935 fprintf (file, ":8");
01936 break;
01937 }
01938
01939
01940
01941
01942
01943
01944 case 'X':
01945 case 'T':
01946 case 'S':
01947 if (h8300_constant_length (addr) == 2)
01948 fprintf (file, ":16");
01949 else
01950 fprintf (file, ":32");
01951 break;
01952 default:
01953 break;
01954 }
01955 }
01956 break;
01957
01958 case CONST_INT:
01959 case SYMBOL_REF:
01960 case CONST:
01961 case LABEL_REF:
01962 fprintf (file, "#");
01963 print_operand_address (file, x);
01964 break;
01965 case CONST_DOUBLE:
01966 {
01967 long val;
01968 REAL_VALUE_TYPE rv;
01969 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01970 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01971 fprintf (file, "#%ld", val);
01972 break;
01973 }
01974 default:
01975 break;
01976 }
01977 }
01978 }
01979
01980
01981
01982 void
01983 print_operand_address (FILE *file, rtx addr)
01984 {
01985 rtx index;
01986 int size;
01987
01988 switch (GET_CODE (addr))
01989 {
01990 case REG:
01991 fprintf (file, "%s", h8_reg_names[REGNO (addr)]);
01992 break;
01993
01994 case PRE_DEC:
01995 fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]);
01996 break;
01997
01998 case POST_INC:
01999 fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]);
02000 break;
02001
02002 case PRE_INC:
02003 fprintf (file, "+%s", h8_reg_names[REGNO (XEXP (addr, 0))]);
02004 break;
02005
02006 case POST_DEC:
02007 fprintf (file, "%s-", h8_reg_names[REGNO (XEXP (addr, 0))]);
02008 break;
02009
02010 case PLUS:
02011 fprintf (file, "(");
02012
02013 index = h8300_get_index (XEXP (addr, 0), VOIDmode, &size);
02014 if (GET_CODE (index) == REG)
02015 {
02016
02017 print_operand_address (file, XEXP (addr, 1));
02018 fprintf (file, ",");
02019 switch (size)
02020 {
02021 case 0:
02022 print_operand_address (file, index);
02023 break;
02024
02025 case 1:
02026 print_operand (file, index, 'X');
02027 fputs (".b", file);
02028 break;
02029
02030 case 2:
02031 print_operand (file, index, 'T');
02032 fputs (".w", file);
02033 break;
02034
02035 case 4:
02036 print_operand (file, index, 'S');
02037 fputs (".l", file);
02038 break;
02039 }
02040
02041 }
02042 else
02043 {
02044
02045 print_operand_address (file, XEXP (addr, 0));
02046 fprintf (file, "+");
02047 print_operand_address (file, XEXP (addr, 1));
02048 }
02049 fprintf (file, ")");
02050 break;
02051
02052 case CONST_INT:
02053 {
02054
02055
02056
02057
02058
02059 int n = INTVAL (addr);
02060 if (TARGET_H8300)
02061 n = (int) (short) n;
02062 fprintf (file, "%d", n);
02063 break;
02064 }
02065
02066 default:
02067 output_addr_const (file, addr);
02068 break;
02069 }
02070 }
02071
02072
02073
02074
02075
02076
02077 void
02078 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
02079 int num_operands ATTRIBUTE_UNUSED)
02080 {
02081
02082 static int last_insn_address = 0;
02083
02084 const int uid = INSN_UID (insn);
02085
02086 if (TARGET_ADDRESSES)
02087 {
02088 fprintf (asm_out_file, "; 0x%x %d\n", INSN_ADDRESSES (uid),
02089 INSN_ADDRESSES (uid) - last_insn_address);
02090 last_insn_address = INSN_ADDRESSES (uid);
02091 }
02092 }
02093
02094
02095
02096 int
02097 h8300_expand_movsi (rtx operands[])
02098 {
02099 rtx src = operands[1];
02100 rtx dst = operands[0];
02101 if (!reload_in_progress && !reload_completed)
02102 {
02103 if (!register_operand (dst, GET_MODE (dst)))
02104 {
02105 rtx tmp = gen_reg_rtx (GET_MODE (dst));
02106 emit_move_insn (tmp, src);
02107 operands[1] = tmp;
02108 }
02109 }
02110 return 0;
02111 }
02112
02113
02114
02115
02116
02117 int
02118 h8300_initial_elimination_offset (int from, int to)
02119 {
02120
02121 int pc_size = POINTER_SIZE / BITS_PER_UNIT;
02122
02123
02124 int fp_size = frame_pointer_needed * UNITS_PER_WORD;
02125
02126
02127
02128 int saved_regs_size = 0;
02129
02130
02131 int frame_size = round_frame_size (get_frame_size ());
02132
02133 int regno;
02134
02135 for (regno = 0; regno <= HARD_FRAME_POINTER_REGNUM; regno++)
02136 if (WORD_REG_USED (regno))
02137 saved_regs_size += UNITS_PER_WORD;
02138
02139
02140
02141 saved_regs_size -= fp_size;
02142
02143 if (to == HARD_FRAME_POINTER_REGNUM)
02144 {
02145 switch (from)
02146 {
02147 case ARG_POINTER_REGNUM:
02148 return pc_size + fp_size;
02149 case RETURN_ADDRESS_POINTER_REGNUM:
02150 return fp_size;
02151 case FRAME_POINTER_REGNUM:
02152 return -saved_regs_size;
02153 default:
02154 abort ();
02155 }
02156 }
02157 else if (to == STACK_POINTER_REGNUM)
02158 {
02159 switch (from)
02160 {
02161 case ARG_POINTER_REGNUM:
02162 return pc_size + saved_regs_size + frame_size;
02163 case RETURN_ADDRESS_POINTER_REGNUM:
02164 return saved_regs_size + frame_size;
02165 case FRAME_POINTER_REGNUM:
02166 return frame_size;
02167 default:
02168 abort ();
02169 }
02170 }
02171 else
02172 abort ();
02173 }
02174
02175
02176
02177 rtx
02178 h8300_return_addr_rtx (int count, rtx frame)
02179 {
02180 rtx ret;
02181
02182 if (count == 0)
02183 ret = gen_rtx_MEM (Pmode,
02184 gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM));
02185 else if (flag_omit_frame_pointer)
02186 return (rtx) 0;
02187 else
02188 ret = gen_rtx_MEM (Pmode,
02189 memory_address (Pmode,
02190 plus_constant (frame, UNITS_PER_WORD)));
02191 set_mem_alias_set (ret, get_frame_alias_set ());
02192 return ret;
02193 }
02194
02195
02196
02197 void
02198 notice_update_cc (rtx body, rtx insn)
02199 {
02200 rtx set;
02201
02202 switch (get_attr_cc (insn))
02203 {
02204 case CC_NONE:
02205
02206 break;
02207
02208 case CC_NONE_0HIT:
02209
02210 if (cc_status.value1 != 0
02211 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
02212 cc_status.value1 = 0;
02213 if (cc_status.value2 != 0
02214 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))
02215 cc_status.value2 = 0;
02216 break;
02217
02218 case CC_SET_ZN:
02219
02220
02221
02222 CC_STATUS_INIT;
02223 cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
02224 set = single_set (insn);
02225 cc_status.value1 = SET_SRC (set);
02226 if (SET_DEST (set) != cc0_rtx)
02227 cc_status.value2 = SET_DEST (set);
02228 break;
02229
02230 case CC_SET_ZNV:
02231
02232
02233
02234 CC_STATUS_INIT;
02235 cc_status.flags |= CC_NO_CARRY;
02236 set = single_set (insn);
02237 cc_status.value1 = SET_SRC (set);
02238 if (SET_DEST (set) != cc0_rtx)
02239 {
02240
02241
02242 if (GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
02243 cc_status.value2 = XEXP (SET_DEST (set), 0);
02244 else
02245 cc_status.value2 = SET_DEST (set);
02246 }
02247 break;
02248
02249 case CC_COMPARE:
02250
02251 CC_STATUS_INIT;
02252 cc_status.value1 = SET_SRC (body);
02253 break;
02254
02255 case CC_CLOBBER:
02256
02257 CC_STATUS_INIT;
02258 break;
02259 }
02260 }
02261
02262
02263
02264 int
02265 stack_pointer_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02266 {
02267 return x == stack_pointer_rtx;
02268 }
02269
02270
02271
02272
02273 int
02274 const_int_gt_2_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02275 {
02276 return (GET_CODE (x) == CONST_INT
02277 && abs (INTVAL (x)) > 2);
02278 }
02279
02280
02281
02282
02283 int
02284 const_int_ge_8_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02285 {
02286 return (GET_CODE (x) == CONST_INT
02287 && abs (INTVAL (x)) >= 8);
02288 }
02289
02290
02291
02292 int
02293 const_int_qi_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02294 {
02295 return (GET_CODE (x) == CONST_INT
02296 && (INTVAL (x) & 0xff) == INTVAL (x));
02297 }
02298
02299
02300
02301 int
02302 const_int_hi_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02303 {
02304 return (GET_CODE (x) == CONST_INT
02305 && (INTVAL (x) & 0xffff) == INTVAL (x));
02306 }
02307
02308
02309
02310 int
02311 incdec_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02312 {
02313 return (GET_CODE (x) == CONST_INT
02314 && (CONST_OK_FOR_M (INTVAL (x))
02315 || CONST_OK_FOR_O (INTVAL (x))));
02316 }
02317
02318
02319
02320 int
02321 eqne_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02322 {
02323 enum rtx_code code = GET_CODE (x);
02324
02325 return (code == EQ || code == NE);
02326 }
02327
02328
02329
02330 int
02331 gtle_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02332 {
02333 enum rtx_code code = GET_CODE (x);
02334
02335 return (code == GT || code == LE);
02336 }
02337
02338
02339
02340 int
02341 gtuleu_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02342 {
02343 enum rtx_code code = GET_CODE (x);
02344
02345 return (code == GTU || code == LEU);
02346 }
02347
02348
02349
02350 int
02351 iorxor_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02352 {
02353 enum rtx_code code = GET_CODE (x);
02354
02355 return (code == IOR || code == XOR);
02356 }
02357
02358
02359
02360 int
02361 bit_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
02362 {
02363 enum rtx_code code = GET_CODE (x);
02364
02365 return (code == XOR
02366 || code == AND
02367 || code == IOR);
02368 }
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386 rtx
02387 h8300_get_index (rtx x, enum machine_mode mode, int *size)
02388 {
02389 int dummy, factor;
02390
02391 if (size == 0)
02392 size = &dummy;
02393
02394 factor = (mode == VOIDmode ? 0 : GET_MODE_SIZE (mode));
02395 if (TARGET_H8300SX
02396 && factor <= 4
02397 && (mode == VOIDmode
02398 || GET_MODE_CLASS (mode) == MODE_INT
02399 || GET_MODE_CLASS (mode) == MODE_FLOAT))
02400 {
02401 if (factor <= 1 && GET_CODE (x) == ZERO_EXTEND)
02402 {
02403
02404
02405 *size = GET_MODE_SIZE (GET_MODE (XEXP (x, 0)));
02406 return XEXP (x, 0);
02407 }
02408 else
02409 {
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421 rtx index;
02422
02423 if (GET_CODE (x) == AND
02424 && GET_CODE (XEXP (x, 1)) == CONST_INT
02425 && (factor == 0
02426 || INTVAL (XEXP (x, 1)) == 0xff * factor
02427 || INTVAL (XEXP (x, 1)) == 0xffff * factor))
02428 {
02429 index = XEXP (x, 0);
02430 *size = (INTVAL (XEXP (x, 1)) >= 0xffff ? 2 : 1);
02431 }
02432 else
02433 {
02434 index = x;
02435 *size = 4;
02436 }
02437
02438 if (GET_CODE (index) == MULT
02439 && GET_CODE (XEXP (index, 1)) == CONST_INT
02440 && (factor == 0 || factor == INTVAL (XEXP (index, 1))))
02441 return XEXP (index, 0);
02442 }
02443 }
02444 *size = 0;
02445 return x;
02446 }
02447
02448 static const h8300_length_table addb_length_table =
02449 {
02450
02451 { 2, 2, 4, 4, 4 },
02452 { 4, 4, 4, 4, 6 },
02453 { 4, 4, 4, 4, 6 },
02454 { 6, 4, 4, 4, 6 }
02455 };
02456
02457 static const h8300_length_table addw_length_table =
02458 {
02459
02460 { 2, 2, 4, 4, 4 },
02461 { 4, 4, 4, 4, 6 },
02462 { 4, 4, 4, 4, 6 },
02463 { 4, 4, 4, 4, 6 }
02464 };
02465
02466 static const h8300_length_table addl_length_table =
02467 {
02468
02469 { 2, 2, 4, 4, 4 },
02470 { 4, 4, 6, 6, 6 },
02471 { 4, 4, 6, 6, 6 },
02472 { 4, 4, 6, 6, 6 }
02473 };
02474
02475 #define logicb_length_table addb_length_table
02476 #define logicw_length_table addw_length_table
02477
02478 static const h8300_length_table logicl_length_table =
02479 {
02480
02481 { 2, 4, 4, 4, 4 },
02482 { 4, 4, 6, 6, 6 },
02483 { 4, 4, 6, 6, 6 },
02484 { 4, 4, 6, 6, 6 }
02485 };
02486
02487 static const h8300_length_table movb_length_table =
02488 {
02489
02490 { 2, 2, 2, 2, 4 },
02491 { 4, 2, 4, 4, 4 },
02492 { 4, 2, 4, 4, 4 },
02493 { 4, 4, 4, 4, 4 }
02494 };
02495
02496 #define movw_length_table movb_length_table
02497
02498 static const h8300_length_table movl_length_table =
02499 {
02500
02501 { 2, 2, 4, 4, 4 },
02502 { 4, 4, 4, 4, 4 },
02503 { 4, 4, 4, 4, 4 },
02504 { 4, 4, 4, 4, 4 }
02505 };
02506
02507
02508
02509 static unsigned int
02510 h8300_constant_length (rtx constant)
02511 {
02512
02513 if (GET_CODE (constant) == CONST_INT
02514 && IN_RANGE (INTVAL (constant), -0x8000, 0x7fff))
02515 return 2;
02516
02517
02518
02519 if (Pmode == HImode || h8300_tiny_constant_address_p (constant))
02520 return 2;
02521
02522 return 4;
02523 }
02524
02525
02526
02527
02528
02529 static unsigned int
02530 h8300_displacement_length (rtx addr, int size)
02531 {
02532 rtx offset;
02533
02534 offset = XEXP (addr, 1);
02535
02536
02537 if (register_operand (XEXP (addr, 0), VOIDmode)
02538 && GET_CODE (offset) == CONST_INT
02539 && (INTVAL (offset) == size
02540 || INTVAL (offset) == size * 2
02541 || INTVAL (offset) == size * 3))
02542 return 0;
02543
02544 return h8300_constant_length (offset);
02545 }
02546
02547
02548
02549
02550
02551 static unsigned int
02552 h8300_classify_operand (rtx op, int size, enum h8300_operand_class *class)
02553 {
02554 enum h8300_operand_class dummy;
02555
02556 if (class == 0)
02557 class = &dummy;
02558
02559 if (CONSTANT_P (op))
02560 {
02561 *class = H8OP_IMMEDIATE;
02562
02563
02564 if (size == 1)
02565 return 0;
02566
02567
02568
02569 if (TARGET_H8300SX
02570 && size == 4
02571 && GET_CODE (op) == CONST_INT
02572 && IN_RANGE (INTVAL (op), 0, 0xffff))
02573 return 2;
02574
02575 return size;
02576 }
02577 else if (GET_CODE (op) == MEM)
02578 {
02579 op = XEXP (op, 0);
02580 if (CONSTANT_P (op))
02581 {
02582 *class = H8OP_MEM_ABSOLUTE;
02583 return h8300_constant_length (op);
02584 }
02585 else if (GET_CODE (op) == PLUS && CONSTANT_P (XEXP (op, 1)))
02586 {
02587 *class = H8OP_MEM_COMPLEX;
02588 return h8300_displacement_length (op, size);
02589 }
02590 else if (GET_RTX_CLASS (GET_CODE (op)) == RTX_AUTOINC)
02591 {
02592 *class = H8OP_MEM_COMPLEX;
02593 return 0;
02594 }
02595 else if (register_operand (op, VOIDmode))
02596 {
02597 *class = H8OP_MEM_BASE;
02598 return 0;
02599 }
02600 }
02601 else if (register_operand (op, VOIDmode))
02602 {
02603 *class = H8OP_REGISTER;
02604 return 0;
02605 }
02606 abort ();
02607 }
02608
02609
02610
02611
02612
02613 static unsigned int
02614 h8300_length_from_table (rtx op1, rtx op2, const h8300_length_table *table)
02615 {
02616 enum h8300_operand_class op1_class, op2_class;
02617 unsigned int size, immediate_length;
02618
02619 size = GET_MODE_SIZE (GET_MODE (op1));
02620 immediate_length = (h8300_classify_operand (op1, size, &op1_class)
02621 + h8300_classify_operand (op2, size, &op2_class));
02622 return immediate_length + (*table)[op1_class - 1][op2_class];
02623 }
02624
02625
02626
02627
02628 unsigned int
02629 h8300_unary_length (rtx op)
02630 {
02631 enum h8300_operand_class class;
02632 unsigned int size, operand_length;
02633
02634 size = GET_MODE_SIZE (GET_MODE (op));
02635 operand_length = h8300_classify_operand (op, size, &class);
02636 switch (class)
02637 {
02638 case H8OP_REGISTER:
02639 return 2;
02640
02641 case H8OP_MEM_BASE:
02642 return (size == 4 ? 6 : 4);
02643
02644 case H8OP_MEM_ABSOLUTE:
02645 return operand_length + (size == 4 ? 6 : 4);
02646
02647 case H8OP_MEM_COMPLEX:
02648 return operand_length + 6;
02649
02650 default:
02651 abort ();
02652 }
02653 }
02654
02655
02656
02657 static unsigned int
02658 h8300_short_immediate_length (rtx op)
02659 {
02660 enum h8300_operand_class class;
02661 unsigned int size, operand_length;
02662
02663 size = GET_MODE_SIZE (GET_MODE (op));
02664 operand_length = h8300_classify_operand (op, size, &class);
02665
02666 switch (class)
02667 {
02668 case H8OP_REGISTER:
02669 return 2;
02670
02671 case H8OP_MEM_BASE:
02672 case H8OP_MEM_ABSOLUTE:
02673 case H8OP_MEM_COMPLEX:
02674 return 4 + operand_length;
02675
02676 default:
02677 abort ();
02678 }
02679 }
02680
02681
02682
02683 static unsigned int
02684 h8300_bitfield_length (rtx op, rtx op2)
02685 {
02686 enum h8300_operand_class class;
02687 unsigned int size, operand_length;
02688
02689 if (GET_CODE (op) == REG)
02690 op = op2;
02691 if (GET_CODE (op) == REG)
02692 abort ();
02693
02694 size = GET_MODE_SIZE (GET_MODE (op));
02695 operand_length = h8300_classify_operand (op, size, &class);
02696
02697 switch (class)
02698 {
02699 case H8OP_MEM_BASE:
02700 case H8OP_MEM_ABSOLUTE:
02701 case H8OP_MEM_COMPLEX:
02702 return 4 + operand_length;
02703
02704 default:
02705 abort ();
02706 }
02707 }
02708
02709
02710
02711 static unsigned int
02712 h8300_binary_length (rtx insn, const h8300_length_table *table)
02713 {
02714 rtx set;
02715
02716 set = single_set (insn);
02717 if (set == 0)
02718 abort ();
02719
02720 if (BINARY_P (SET_SRC (set)))
02721 return h8300_length_from_table (XEXP (SET_SRC (set), 0),
02722 XEXP (SET_SRC (set), 1), table);
02723 else if (GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == RTX_TERNARY)
02724 return h8300_length_from_table (XEXP (XEXP (SET_SRC (set), 1), 0),
02725 XEXP (XEXP (SET_SRC (set), 1), 1),
02726 table);
02727 else
02728 abort ();
02729 }
02730
02731
02732
02733
02734
02735 static bool
02736 h8300_short_move_mem_p (rtx op, enum rtx_code inc_code)
02737 {
02738 rtx addr;
02739 unsigned int size;
02740
02741 if (GET_CODE (op) != MEM)
02742 return false;
02743
02744 addr = XEXP (op, 0);
02745 size = GET_MODE_SIZE (GET_MODE (op));
02746 if (size != 1 && size != 2)
02747 return false;
02748
02749 return (GET_CODE (addr) == inc_code
02750 || (GET_CODE (addr) == PLUS
02751 && GET_CODE (XEXP (addr, 0)) == REG
02752 && h8300_displacement_length (addr, size) == 2));
02753 }
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767 static unsigned int
02768 h8300_move_length (rtx *operands, const h8300_length_table *table)
02769 {
02770 unsigned int size;
02771
02772 size = h8300_length_from_table (operands[0], operands[1], table);
02773 if (REG_P (operands[0]) && h8300_short_move_mem_p (operands[1], POST_INC))
02774 size -= 2;
02775 if (REG_P (operands[1]) && h8300_short_move_mem_p (operands[0], PRE_DEC))
02776 size -= 2;
02777 return size;
02778 }
02779
02780
02781
02782
02783
02784 static unsigned int
02785 h8300_mova_length (rtx dest, rtx src, rtx offset)
02786 {
02787 unsigned int size;
02788
02789 size = (2
02790 + h8300_constant_length (offset)
02791 + h8300_classify_operand (src, GET_MODE_SIZE (GET_MODE (src)), 0));
02792 if (!REG_P (dest) || !REG_P (src) || REGNO (src) != REGNO (dest))
02793 size += 2;
02794 return size;
02795 }
02796
02797
02798
02799
02800 unsigned int
02801 h8300_insn_length_from_table (rtx insn, rtx * operands)
02802 {
02803 switch (get_attr_length_table (insn))
02804 {
02805 case LENGTH_TABLE_NONE:
02806 abort ();
02807
02808 case LENGTH_TABLE_ADDB:
02809 return h8300_binary_length (insn, &addb_length_table);
02810
02811 case LENGTH_TABLE_ADDW:
02812 return h8300_binary_length (insn, &addw_length_table);
02813
02814 case LENGTH_TABLE_ADDL:
02815 return h8300_binary_length (insn, &addl_length_table);
02816
02817 case LENGTH_TABLE_LOGICB:
02818 return h8300_binary_length (insn, &logicb_length_table);
02819
02820 case LENGTH_TABLE_MOVB:
02821 return h8300_move_length (operands, &movb_length_table);
02822
02823 case LENGTH_TABLE_MOVW:
02824 return h8300_move_length (operands, &movw_length_table);
02825
02826 case LENGTH_TABLE_MOVL:
02827 return h8300_move_length (operands, &movl_length_table);
02828
02829 case LENGTH_TABLE_MOVA:
02830 return h8300_mova_length (operands[0], operands[1], operands[2]);
02831
02832 case LENGTH_TABLE_MOVA_ZERO:
02833 return h8300_mova_length (operands[0], operands[1], const0_rtx);
02834
02835 case LENGTH_TABLE_UNARY:
02836 return h8300_unary_length (operands[0]);
02837
02838 case LENGTH_TABLE_MOV_IMM4:
02839 return 2 + h8300_classify_operand (operands[0], 0, 0);
02840
02841 case LENGTH_TABLE_SHORT_IMMEDIATE:
02842 return h8300_short_immediate_length (operands[0]);
02843
02844 case LENGTH_TABLE_BITFIELD:
02845 return h8300_bitfield_length (operands[0], operands[1]);
02846
02847 case LENGTH_TABLE_BITBRANCH:
02848 return h8300_bitfield_length (operands[1], operands[2]) - 2;
02849
02850 }
02851 abort ();
02852 }
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864 bool
02865 h8sx_mergeable_memrefs_p (rtx lhs, rtx rhs)
02866 {
02867 if (GET_CODE (rhs) == MEM && GET_CODE (lhs) == MEM)
02868 {
02869 rhs = XEXP (rhs, 0);
02870 lhs = XEXP (lhs, 0);
02871
02872 if (GET_CODE (rhs) == PRE_INC || GET_CODE (rhs) == PRE_DEC)
02873 return rtx_equal_p (XEXP (rhs, 0), lhs);
02874
02875 if (GET_CODE (lhs) == POST_INC || GET_CODE (lhs) == POST_DEC)
02876 return rtx_equal_p (rhs, XEXP (lhs, 0));
02877
02878 if (rtx_equal_p (rhs, lhs))
02879 return true;
02880 }
02881 return false;
02882 }
02883
02884
02885
02886
02887 bool
02888 h8300_operands_match_p (rtx *operands)
02889 {
02890 if (register_operand (operands[0], VOIDmode)
02891 && register_operand (operands[1], VOIDmode))
02892 return true;
02893
02894 if (h8sx_mergeable_memrefs_p (operands[0], operands[1]))
02895 return true;
02896
02897 return false;
02898 }
02899
02900
02901
02902
02903 int
02904 h8sx_binary_memory_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02905 {
02906 if (!TARGET_H8300SX)
02907 return false;
02908
02909 if (GET_MODE (op) != QImode
02910 && GET_MODE (op) != HImode
02911 && GET_MODE (op) != SImode)
02912 return false;
02913
02914 switch (GET_CODE (op))
02915 {
02916 case PLUS:
02917 case MINUS:
02918 case AND:
02919 case IOR:
02920 case XOR:
02921 return true;
02922
02923 default:
02924 return h8sx_unary_shift_operator (op, mode);
02925 }
02926 }
02927
02928
02929
02930 int
02931 h8sx_unary_memory_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02932 {
02933 if (!TARGET_H8300SX)
02934 return false;
02935
02936 if (GET_MODE (op) != QImode
02937 && GET_MODE (op) != HImode
02938 && GET_MODE (op) != SImode)
02939 return false;
02940
02941 switch (GET_CODE (op))
02942 {
02943 case NEG:
02944 case NOT:
02945 return true;
02946
02947 default:
02948 return false;
02949 }
02950 }
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983 bool
02984 h8sx_emit_movmd (rtx dest, rtx src, rtx length,
02985 HOST_WIDE_INT alignment)
02986 {
02987 if (!flag_omit_frame_pointer && optimize_size)
02988 return false;
02989
02990 if (GET_CODE (length) == CONST_INT)
02991 {
02992 rtx dest_reg, src_reg, first_dest, first_src;
02993 HOST_WIDE_INT n;
02994 int factor;
02995
02996
02997
02998 factor = (alignment >= 2 ? 4 : 1);
02999
03000
03001
03002
03003 n = INTVAL (length);
03004 if (n <= 0 || n / factor > 65536)
03005 return false;
03006
03007
03008
03009 dest_reg = copy_addr_to_reg (XEXP (dest, 0));
03010 src_reg = copy_addr_to_reg (XEXP (src, 0));
03011
03012
03013 first_dest = replace_equiv_address (dest, dest_reg);
03014 first_src = replace_equiv_address (src, src_reg);
03015
03016 set_mem_size (first_dest, GEN_INT (n & -factor));
03017 set_mem_size (first_src, GEN_INT (n & -factor));
03018
03019 length = copy_to_mode_reg (HImode, gen_int_mode (n / factor, HImode));
03020 emit_insn (gen_movmd (first_dest, first_src, length, GEN_INT (factor)));
03021
03022 if ((n & -factor) != n)
03023 {
03024
03025
03026 dest = adjust_address (dest, BLKmode, n & -factor);
03027 src = adjust_address (src, BLKmode, n & -factor);
03028
03029
03030
03031 dest = replace_equiv_address (dest, dest_reg);
03032 src = replace_equiv_address (src, src_reg);
03033
03034
03035 if (n & 2)
03036 emit_move_insn (adjust_address (dest, HImode, 0),
03037 adjust_address (src, HImode, 0));
03038 if (n & 1)
03039 emit_move_insn (adjust_address (dest, QImode, n & 2),
03040 adjust_address (src, QImode, n & 2));
03041 }
03042 return true;
03043 }
03044 return false;
03045 }
03046
03047
03048
03049 void
03050 h8300_swap_into_er6 (rtx addr)
03051 {
03052 push (HARD_FRAME_POINTER_REGNUM);
03053 emit_move_insn (hard_frame_pointer_rtx, addr);
03054 if (REGNO (addr) == SP_REG)
03055 emit_move_insn (hard_frame_pointer_rtx,
03056 plus_constant (hard_frame_pointer_rtx,
03057 GET_MODE_SIZE (word_mode)));
03058 }
03059
03060
03061
03062
03063 void
03064 h8300_swap_out_of_er6 (rtx addr)
03065 {
03066 if (REGNO (addr) != SP_REG)
03067 emit_move_insn (addr, hard_frame_pointer_rtx);
03068 pop (HARD_FRAME_POINTER_REGNUM);
03069 }
03070
03071
03072
03073 unsigned int
03074 compute_mov_length (rtx *operands)
03075 {
03076
03077
03078
03079
03080 enum machine_mode mode = GET_MODE (operands[0]);
03081 rtx dest = operands[0];
03082 rtx src = operands[1];
03083 rtx addr;
03084
03085 if (GET_CODE (src) == MEM)
03086 addr = XEXP (src, 0);
03087 else if (GET_CODE (dest) == MEM)
03088 addr = XEXP (dest, 0);
03089 else
03090 addr = NULL_RTX;
03091
03092 if (TARGET_H8300)
03093 {
03094 unsigned int base_length;
03095
03096 switch (mode)
03097 {
03098 case QImode:
03099 if (addr == NULL_RTX)
03100 return 2;
03101
03102
03103
03104 if (h8300_eightbit_constant_address_p (addr))
03105 return 2;
03106
03107 base_length = 4;
03108 break;
03109
03110 case HImode:
03111 if (addr == NULL_RTX)
03112 {
03113 if (REG_P (src))
03114 return 2;
03115
03116 if (src == const0_rtx)
03117 return 2;
03118
03119 return 4;
03120 }
03121
03122 base_length = 4;
03123 break;
03124
03125 case SImode:
03126 if (addr == NULL_RTX)
03127 {
03128 if (REG_P (src))
03129 return 4;
03130
03131 if (GET_CODE (src) == CONST_INT)
03132 {
03133 if (src == const0_rtx)
03134 return 4;
03135
03136 if ((INTVAL (src) & 0xffff) == 0)
03137 return 6;
03138
03139 if ((INTVAL (src) & 0xffff) == 0)
03140 return 6;
03141
03142 if ((INTVAL (src) & 0xffff)
03143 == ((INTVAL (src) >> 16) & 0xffff))
03144 return 6;
03145 }
03146 return 8;
03147 }
03148
03149 base_length = 8;
03150 break;
03151
03152 case SFmode:
03153 if (addr == NULL_RTX)
03154 {
03155 if (REG_P (src))
03156 return 4;
03157
03158 if (CONST_DOUBLE_OK_FOR_LETTER_P (src, 'G'))
03159 return 4;
03160
03161 return 8;
03162 }
03163
03164 base_length = 8;
03165 break;
03166
03167 default:
03168 abort ();
03169 }
03170
03171
03172
03173
03174
03175
03176
03177
03178 if (GET_CODE (addr) == PRE_DEC
03179 || GET_CODE (addr) == POST_INC)
03180 {
03181 if (mode == QImode || mode == HImode)
03182 return base_length - 2;
03183 else
03184
03185
03186 return base_length - 4;
03187 }
03188
03189
03190
03191
03192
03193 if (GET_CODE (addr) == REG)
03194 return base_length - 2;
03195
03196 return base_length;
03197 }
03198 else
03199 {
03200 unsigned int base_length;
03201
03202 switch (mode)
03203 {
03204 case QImode:
03205 if (addr == NULL_RTX)
03206 return 2;
03207
03208
03209
03210 if (h8300_eightbit_constant_address_p (addr))
03211 return 2;
03212
03213 base_length = 8;
03214 break;
03215
03216 case HImode:
03217 if (addr == NULL_RTX)
03218 {
03219 if (REG_P (src))
03220 return 2;
03221
03222 if (src == const0_rtx)
03223 return 2;
03224
03225 return 4;
03226 }
03227
03228 base_length = 8;
03229 break;
03230
03231 case SImode:
03232 if (addr == NULL_RTX)
03233 {
03234 if (REG_P (src))
03235 {
03236 if (REGNO (src) == MAC_REG || REGNO (dest) == MAC_REG)
03237 return 4;
03238 else
03239 return 2;
03240 }
03241
03242 if (GET_CODE (src) == CONST_INT)
03243 {
03244 int val = INTVAL (src);
03245
03246 if (val == 0)
03247 return 2;
03248
03249 if (val == (val & 0x00ff) || val == (val & 0xff00))
03250 return 4;
03251
03252 switch (val & 0xffffffff)
03253 {
03254 case 0xffffffff:
03255 case 0xfffffffe:
03256 case 0xfffffffc:
03257 case 0x0000ffff:
03258 case 0x0000fffe:
03259 case 0xffff0000:
03260 case 0xfffe0000:
03261 case 0x00010000:
03262 case 0x00020000:
03263 return 4;
03264 }
03265 }
03266 return 6;
03267 }
03268
03269 base_length = 10;
03270 break;
03271
03272 case SFmode:
03273 if (addr == NULL_RTX)
03274 {
03275 if (REG_P (src))
03276 return 2;
03277
03278 if (CONST_DOUBLE_OK_FOR_LETTER_P (src, 'G'))
03279 return 2;
03280
03281 return 6;
03282 }
03283
03284 base_length = 10;
03285 break;
03286
03287 default:
03288 abort ();
03289 }
03290
03291
03292
03293
03294
03295
03296 if (GET_CODE (addr) == PRE_DEC
03297 || GET_CODE (addr) == POST_INC)
03298 return base_length - 6;
03299
03300
03301 if (GET_CODE (addr) == REG)
03302 return base_length - 6;
03303
03304
03305
03306 if (GET_CODE (addr) == PLUS
03307 && GET_CODE (XEXP (addr, 0)) == REG
03308 && GET_CODE (XEXP (addr, 1)) == CONST_INT
03309 && INTVAL (XEXP (addr, 1)) > -32768
03310 && INTVAL (XEXP (addr, 1)) < 32767)
03311 return base_length - 4;
03312
03313
03314 if (h8300_tiny_constant_address_p (addr))
03315 return base_length - 4;
03316
03317
03318 if (CONSTANT_P (addr))
03319 return base_length - 2;
03320
03321 return base_length;
03322 }
03323 }
03324
03325
03326
03327 const char *
03328 output_plussi (rtx *operands)
03329 {
03330 enum machine_mode mode = GET_MODE (operands[0]);
03331
03332 if (mode != SImode)
03333 abort ();
03334
03335 if (TARGET_H8300)
03336 {
03337 if (GET_CODE (operands[2]) == REG)
03338 return "add.w\t%f2,%f0\n\taddx\t%y2,%y0\n\taddx\t%z2,%z0";
03339
03340 if (GET_CODE (operands[2]) == CONST_INT)
03341 {
03342 HOST_WIDE_INT n = INTVAL (operands[2]);
03343
03344 if ((n & 0xffffff) == 0)
03345 return "add\t%z2,%z0";
03346 if ((n & 0xffff) == 0)
03347 return "add\t%y2,%y0\n\taddx\t%z2,%z0";
03348 if ((n & 0xff) == 0)
03349 return "add\t%x2,%x0\n\taddx\t%y2,%y0\n\taddx\t%z2,%z0";
03350 }
03351
03352 return "add\t%w2,%w0\n\taddx\t%x2,%x0\n\taddx\t%y2,%y0\n\taddx\t%z2,%z0";
03353 }
03354 else
03355 {
03356 if (GET_CODE (operands[2]) == CONST_INT
03357 && register_operand (operands[1], VOIDmode))
03358 {
03359 HOST_WIDE_INT intval = INTVAL (operands[2]);
03360
03361 if (TARGET_H8300SX && (intval >= 1 && intval <= 7))
03362 return "add.l\t%S2,%S0";
03363 if (TARGET_H8300SX && (intval >= -7 && intval <= -1))
03364 return "sub.l\t%G2,%S0";
03365
03366
03367
03368 switch ((unsigned int) intval & 0xffffffff)
03369 {
03370 case 0x00000001:
03371 case 0x00000002:
03372 case 0x00000004:
03373 return "adds\t%2,%S0";
03374
03375 case 0xffffffff:
03376 case 0xfffffffe:
03377 case 0xfffffffc:
03378 return "subs\t%G2,%S0";
03379
03380 case 0x00010000:
03381 case 0x00020000:
03382 operands[2] = GEN_INT (intval >> 16);
03383 return "inc.w\t%2,%e0";
03384
03385 case 0xffff0000:
03386 case 0xfffe0000:
03387 operands[2] = GEN_INT (intval >> 16);
03388 return "dec.w\t%G2,%e0";
03389 }
03390
03391
03392 if ((intval & 0xffff) == 0)
03393 {
03394 operands[2] = GEN_INT (intval >> 16);
03395 return "add.w\t%2,%e0";
03396 }
03397 }
03398
03399 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
03400 {
03401 operands[2] = GEN_INT (-INTVAL (operands[2]));
03402 return "sub.l\t%S2,%S0";
03403 }
03404 return "add.l\t%S2,%S0";
03405 }
03406 }
03407
03408
03409
03410
03411
03412 unsigned int
03413 compute_plussi_length (rtx *operands)
03414 {
03415 enum machine_mode mode = GET_MODE (operands[0]);
03416
03417 if (mode != SImode)
03418 abort ();
03419
03420 if (TARGET_H8300)
03421 {
03422 if (GET_CODE (operands[2]) == REG)
03423 return 6;
03424
03425 if (GET_CODE (operands[2]) == CONST_INT)
03426 {
03427 HOST_WIDE_INT n = INTVAL (operands[2]);
03428
03429 if ((n & 0xffffff) == 0)
03430 return 2;
03431 if ((n & 0xffff) == 0)
03432 return 4;
03433 if ((n & 0xff) == 0)
03434 return 6;
03435 }
03436
03437 return 8;
03438 }
03439 else
03440 {
03441 if (GET_CODE (operands[2]) == CONST_INT
03442 && register_operand (operands[1], VOIDmode))
03443 {
03444 HOST_WIDE_INT intval = INTVAL (operands[2]);
03445
03446 if (TARGET_H8300SX && (intval >= 1 && intval <= 7))
03447 return 2;
03448 if (TARGET_H8300SX && (intval >= -7 && intval <= -1))
03449 return 2;
03450
03451
03452
03453 switch ((unsigned int) intval & 0xffffffff)
03454 {
03455 case 0x00000001:
03456 case 0x00000002:
03457 case 0x00000004:
03458 return 2;
03459
03460 case 0xffffffff:
03461 case 0xfffffffe:
03462 case 0xfffffffc:
03463 return 2;
03464
03465 case 0x00010000:
03466 case 0x00020000:
03467 return 2;
03468
03469 case 0xffff0000:
03470 case 0xfffe0000:
03471 return 2;
03472 }
03473
03474
03475 if ((intval & 0xffff) == 0)
03476 return 4;
03477 }
03478
03479 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
03480 return h8300_length_from_table (operands[0],
03481 GEN_INT (-INTVAL (operands[2])),
03482 &addl_length_table);
03483 else
03484 return h8300_length_from_table (operands[0], operands[2],
03485 &addl_length_table);
03486 return 6;
03487 }
03488 }
03489
03490
03491
03492 int
03493 compute_plussi_cc (rtx *operands)
03494 {
03495 enum machine_mode mode = GET_MODE (operands[0]);
03496
03497 if (mode != SImode)
03498 abort ();
03499
03500 if (TARGET_H8300)
03501 {
03502 return CC_CLOBBER;
03503 }
03504 else
03505 {
03506 if (GET_CODE (operands[2]) == CONST_INT
03507 && register_operand (operands[1], VOIDmode))
03508 {
03509 HOST_WIDE_INT intval = INTVAL (operands[2]);
03510
03511 if (TARGET_H8300SX && (intval >= 1 && intval <= 7))
03512 return CC_SET_ZN;
03513 if (TARGET_H8300SX && (intval >= -7 && intval <= -1))
03514 return CC_SET_ZN;
03515
03516
03517
03518 switch ((unsigned int) intval & 0xffffffff)
03519 {
03520 case 0x00000001:
03521 case 0x00000002:
03522 case 0x00000004:
03523 return CC_NONE_0HIT;
03524
03525 case 0xffffffff:
03526 case 0xfffffffe:
03527 case 0xfffffffc:
03528 return CC_NONE_0HIT;
03529
03530 case 0x00010000:
03531 case 0x00020000:
03532 return CC_CLOBBER;
03533
03534 case 0xffff0000:
03535 case 0xfffe0000:
03536 return CC_CLOBBER;
03537 }
03538
03539
03540 if ((intval & 0xffff) == 0)
03541 return CC_CLOBBER;
03542 }
03543
03544 return CC_SET_ZN;
03545 }
03546 }
03547
03548
03549
03550 const char *
03551 output_logical_op (enum machine_mode mode, rtx *operands)
03552 {
03553
03554 enum rtx_code code = GET_CODE (operands[3]);
03555
03556 const unsigned HOST_WIDE_INT intval =
03557 (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
03558
03559
03560
03561
03562 && register_operand (operands[1], VOIDmode)
03563 ? INTVAL (operands[2]) : 0x55555555);
03564
03565
03566 const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
03567
03568 const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff;
03569 const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff;
03570 const unsigned HOST_WIDE_INT b2 = (det >> 16) & 0xff;
03571 const unsigned HOST_WIDE_INT b3 = (det >> 24) & 0xff;
03572 const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff;
03573 const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff;
03574 int lower_half_easy_p = 0;
03575 int upper_half_easy_p = 0;
03576
03577 const char *opname;
03578 char insn_buf[100];
03579
03580 switch (code)
03581 {
03582 case AND:
03583 opname = "and";
03584 break;
03585 case IOR:
03586 opname = "or";
03587 break;
03588 case XOR:
03589 opname = "xor";
03590 break;
03591 default:
03592 abort ();
03593 }
03594
03595 switch (mode)
03596 {
03597 case HImode:
03598
03599 if ((TARGET_H8300H || TARGET_H8300S)
03600 && b0 != 0
03601 && b1 != 0)
03602 {
03603 sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname);
03604 output_asm_insn (insn_buf, operands);
03605 }
03606 else
03607 {
03608
03609 if (b0 != 0)
03610 {
03611 sprintf (insn_buf, "%s\t%%s2,%%s0", opname);
03612 output_asm_insn (insn_buf, operands);
03613 }
03614
03615 if (b1 != 0)
03616 {
03617 sprintf (insn_buf, "%s\t%%t2,%%t0", opname);
03618 output_asm_insn (insn_buf, operands);
03619 }
03620 }
03621 break;
03622 case SImode:
03623 if (TARGET_H8300H || TARGET_H8300S)
03624 {
03625
03626
03627 lower_half_easy_p = (b0 == 0
03628 || b1 == 0
03629 || (code != IOR && w0 == 0xffff));
03630
03631
03632
03633 upper_half_easy_p = ((code != IOR && w1 == 0xffff)
03634 || (code == AND && w1 == 0xff00));
03635 }
03636
03637
03638
03639 if ((TARGET_H8300H || TARGET_H8300S)
03640 && w0 != 0 && w1 != 0
03641 && !(lower_half_easy_p && upper_half_easy_p)
03642 && !(code == IOR && w1 == 0xffff
03643 && (w0 & 0x8000) != 0 && lower_half_easy_p))
03644 {
03645 sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname);
03646 output_asm_insn (insn_buf, operands);
03647 }
03648 else
03649 {
03650
03651
03652
03653
03654
03655
03656 if (w0 == 0xffff
03657 && (TARGET_H8300 ? (code == AND) : (code != IOR)))
03658 output_asm_insn ((code == AND)
03659 ? "sub.w\t%f0,%f0" : "not.w\t%f0",
03660 operands);
03661 else if ((TARGET_H8300H || TARGET_H8300S)
03662 && (b0 != 0)
03663 && (b1 != 0))
03664 {
03665 sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname);
03666 output_asm_insn (insn_buf, operands);
03667 }
03668 else
03669 {
03670 if (b0 != 0)
03671 {
03672 sprintf (insn_buf, "%s\t%%w2,%%w0", opname);
03673 output_asm_insn (insn_buf, operands);
03674 }
03675 if (b1 != 0)
03676 {
03677 sprintf (insn_buf, "%s\t%%x2,%%x0", opname);
03678 output_asm_insn (insn_buf, operands);
03679 }
03680 }
03681
03682 if ((w1 == 0xffff)
03683 && (TARGET_H8300 ? (code == AND) : (code != IOR)))
03684 output_asm_insn ((code == AND)
03685 ? "sub.w\t%e0,%e0" : "not.w\t%e0",
03686 operands);
03687 else if ((TARGET_H8300H || TARGET_H8300S)
03688 && code == IOR
03689 && w1 == 0xffff
03690 && (w0 & 0x8000) != 0)
03691 {
03692 output_asm_insn ("exts.l\t%S0", operands);
03693 }
03694 else if ((TARGET_H8300H || TARGET_H8300S)
03695 && code == AND
03696 && w1 == 0xff00)
03697 {
03698 output_asm_insn ("extu.w\t%e0", operands);
03699 }
03700 else if (TARGET_H8300H || TARGET_H8300S)
03701 {
03702 if (w1 != 0)
03703 {
03704 sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname);
03705 output_asm_insn (insn_buf, operands);
03706 }
03707 }
03708 else
03709 {
03710 if (b2 != 0)
03711 {
03712 sprintf (insn_buf, "%s\t%%y2,%%y0", opname);
03713 output_asm_insn (insn_buf, operands);
03714 }
03715 if (b3 != 0)
03716 {
03717 sprintf (insn_buf, "%s\t%%z2,%%z0", opname);
03718 output_asm_insn (insn_buf, operands);
03719 }
03720 }
03721 }
03722 break;
03723 default:
03724 abort ();
03725 }
03726 return "";
03727 }
03728
03729
03730
03731 unsigned int
03732 compute_logical_op_length (enum machine_mode mode, rtx *operands)
03733 {
03734
03735 enum rtx_code code = GET_CODE (operands[3]);
03736
03737 const unsigned HOST_WIDE_INT intval =
03738 (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
03739
03740
03741
03742
03743 && register_operand (operands[1], VOIDmode)
03744 ? INTVAL (operands[2]) : 0x55555555);
03745
03746
03747 const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
03748
03749 const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff;
03750 const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff;
03751 const unsigned HOST_WIDE_INT b2 = (det >> 16) & 0xff;
03752 const unsigned HOST_WIDE_INT b3 = (det >> 24) & 0xff;
03753 const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff;
03754 const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff;
03755 int lower_half_easy_p = 0;
03756 int upper_half_easy_p = 0;
03757
03758 unsigned int length = 0;
03759
03760 switch (mode)
03761 {
03762 case HImode:
03763
03764 if ((TARGET_H8300H || TARGET_H8300S)
03765 && b0 != 0
03766 && b1 != 0)
03767 {
03768 length = h8300_length_from_table (operands[1], operands[2],
03769 &logicw_length_table);
03770 }
03771 else
03772 {
03773
03774 if (b0 != 0)
03775 length += 2;
03776
03777
03778 if (b1 != 0)
03779 length += 2;
03780 }
03781 break;
03782 case SImode:
03783 if (TARGET_H8300H || TARGET_H8300S)
03784 {
03785
03786
03787 lower_half_easy_p = (b0 == 0
03788 || b1 == 0
03789 || (code != IOR && w0 == 0xffff));
03790
03791
03792
03793 upper_half_easy_p = ((code != IOR && w1 == 0xffff)
03794 || (code == AND && w1 == 0xff00));
03795 }
03796
03797
03798
03799 if ((TARGET_H8300H || TARGET_H8300S)
03800 && w0 != 0 && w1 != 0
03801 && !(lower_half_easy_p && upper_half_easy_p)
03802 && !(code == IOR && w1 == 0xffff
03803 && (w0 & 0x8000) != 0 && lower_half_easy_p))
03804 {
03805 length = h8300_length_from_table (operands[1], operands[2],
03806 &logicl_length_table);
03807 }
03808 else
03809 {
03810
03811
03812
03813
03814
03815
03816 if (w0 == 0xffff
03817 && (TARGET_H8300 ? (code == AND) : (code != IOR)))
03818 {
03819 length += 2;
03820 }
03821 else if ((TARGET_H8300H || TARGET_H8300S)
03822 && (b0 != 0)
03823 && (b1 != 0))
03824 {
03825 length += 4;
03826 }
03827 else
03828 {
03829 if (b0 != 0)
03830 length += 2;
03831
03832 if (b1 != 0)
03833 length += 2;
03834 }
03835
03836 if (w1 == 0xffff
03837 && (TARGET_H8300 ? (code == AND) : (code != IOR)))
03838 {
03839 length += 2;
03840 }
03841 else if ((TARGET_H8300H || TARGET_H8300S)
03842 && code == IOR
03843 && w1 == 0xffff
03844 && (w0 & 0x8000) != 0)
03845 {
03846 length += 2;
03847 }
03848 else if ((TARGET_H8300H || TARGET_H8300S)
03849 && code == AND
03850 && w1 == 0xff00)
03851 {
03852 length += 2;
03853 }
03854 else if (TARGET_H8300H || TARGET_H8300S)
03855 {
03856 if (w1 != 0)
03857 length += 4;
03858 }
03859 else
03860 {
03861 if (b2 != 0)
03862 length += 2;
03863
03864 if (b3 != 0)
03865 length += 2;
03866 }
03867 }
03868 break;
03869 default:
03870 abort ();
03871 }
03872 return length;
03873 }
03874
03875
03876
03877 int
03878 compute_logical_op_cc (enum machine_mode mode, rtx *operands)
03879 {
03880
03881 enum rtx_code code = GET_CODE (operands[3]);
03882
03883 const unsigned HOST_WIDE_INT intval =
03884 (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
03885
03886
03887
03888
03889 && register_operand (operands[1], VOIDmode)
03890 ? INTVAL (operands[2]) : 0x55555555);
03891
03892
03893 const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
03894
03895 const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff;
03896 const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff;
03897 const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff;
03898 const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff;
03899 int lower_half_easy_p = 0;
03900 int upper_half_easy_p = 0;
03901
03902 enum attr_cc cc = CC_CLOBBER;
03903
03904 switch (mode)
03905 {
03906 case HImode:
03907
03908 if ((TARGET_H8300H || TARGET_H8300S)
03909 && b0 != 0
03910 && b1 != 0)
03911 {
03912 cc = CC_SET_ZNV;
03913 }
03914 break;
03915 case SImode:
03916 if (TARGET_H8300H || TARGET_H8300S)
03917 {
03918
03919
03920 lower_half_easy_p = (b0 == 0
03921 || b1 == 0
03922 || (code != IOR && w0 == 0xffff));
03923
03924
03925
03926 upper_half_easy_p = ((code != IOR && w1 == 0xffff)
03927 || (code == AND && w1 == 0xff00));
03928 }
03929
03930
03931
03932 if ((TARGET_H8300H || TARGET_H8300S)
03933 && w0 != 0 && w1 != 0
03934 && !(lower_half_easy_p && upper_half_easy_p)
03935 && !(code == IOR && w1 == 0xffff
03936 && (w0 & 0x8000) != 0 && lower_half_easy_p))
03937 {
03938 cc = CC_SET_ZNV;
03939 }
03940 else
03941 {
03942 if ((TARGET_H8300H || TARGET_H8300S)
03943 && code == IOR
03944 && w1 == 0xffff
03945 && (w0 & 0x8000) != 0)
03946 {
03947 cc = CC_SET_ZNV;
03948 }
03949 }
03950 break;
03951 default:
03952 abort ();
03953 }
03954 return cc;
03955 }
03956
03957
03958
03959 void
03960 h8300_expand_branch (enum rtx_code code, rtx label)
03961 {
03962 rtx tmp;
03963
03964 tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
03965 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
03966 gen_rtx_LABEL_REF (VOIDmode, label),
03967 pc_rtx);
03968 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
03969 }
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009 enum h8sx_shift_type
04010 h8sx_classify_shift (enum machine_mode mode, enum rtx_code code, rtx op)
04011 {
04012 if (!TARGET_H8300SX)
04013 return H8SX_SHIFT_NONE;
04014
04015 switch (code)
04016 {
04017 case ASHIFT:
04018 case LSHIFTRT:
04019
04020 if (GET_CODE (op) != CONST_INT)
04021 return H8SX_SHIFT_BINARY;
04022
04023
04024 if (INTVAL (op) <= 0 || INTVAL (op) >= GET_MODE_BITSIZE (mode))
04025 return H8SX_SHIFT_NONE;
04026
04027
04028 if (exact_log2 (INTVAL (op)) >= 0)
04029 return H8SX_SHIFT_UNARY;
04030
04031 return H8SX_SHIFT_BINARY;
04032
04033 case ASHIFTRT:
04034 if (op == const1_rtx || op == const2_rtx)
04035 return H8SX_SHIFT_UNARY;
04036 return H8SX_SHIFT_NONE;
04037
04038 case ROTATE:
04039 if (GET_CODE (op) == CONST_INT
04040 && (INTVAL (op) == 1
04041 || INTVAL (op) == 2
04042 || INTVAL (op) == GET_MODE_BITSIZE (mode) - 2
04043 || INTVAL (op) == GET_MODE_BITSIZE (mode) - 1))
04044 return H8SX_SHIFT_UNARY;
04045 return H8SX_SHIFT_NONE;
04046
04047 default:
04048 return H8SX_SHIFT_NONE;
04049 }
04050 }
04051
04052
04053
04054 int
04055 h8sx_unary_shift_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
04056 {
04057 return (BINARY_P (x) && NON_COMMUTATIVE_P (x)
04058 && (h8sx_classify_shift (GET_MODE (x), GET_CODE (x), XEXP (x, 1))
04059 == H8SX_SHIFT_UNARY));
04060 }
04061
04062
04063
04064 int
04065 h8sx_binary_shift_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
04066 {
04067 return (BINARY_P (x) && NON_COMMUTATIVE_P (x)
04068 && (h8sx_classify_shift (GET_MODE (x), GET_CODE (x), XEXP (x, 1))
04069 == H8SX_SHIFT_BINARY));
04070 }
04071
04072
04073
04074
04075
04076
04077
04078 const char *
04079 output_h8sx_shift (rtx *operands, int suffix, int optype)
04080 {
04081 static char buffer[16];
04082 const char *stem;
04083
04084 switch (GET_CODE (operands[3]))
04085 {
04086 case ASHIFT:
04087 stem = "shll";
04088 break;
04089
04090 case ASHIFTRT:
04091 stem = "shar";
04092 break;
04093
04094 case LSHIFTRT:
04095 stem = "shlr";
04096 break;
04097
04098 case ROTATE:
04099 stem = "rotl";
04100 if (INTVAL (operands[2]) > 2)
04101 {
04102
04103 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[0]))
04104 - INTVAL (operands[2]));
04105 stem = "rotr";
04106 }
04107 break;
04108
04109 default:
04110 abort ();
04111 }
04112 if (operands[2] == const1_rtx)
04113 sprintf (buffer, "%s.%c\t%%%c0", stem, suffix, optype);
04114 else
04115 sprintf (buffer, "%s.%c\t%%X2,%%%c0", stem, suffix, optype);
04116 return buffer;
04117 }
04118 int
04119 nshift_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
04120 {
04121 switch (GET_CODE (x))
04122 {
04123 case ASHIFTRT:
04124 case LSHIFTRT:
04125 case ASHIFT:
04126 return 1;
04127
04128 default:
04129 return 0;
04130 }
04131 }
04132
04133
04134
04135 bool
04136 expand_a_shift (enum machine_mode mode, int code, rtx operands[])
04137 {
04138 switch (h8sx_classify_shift (mode, code, operands[2]))
04139 {
04140 case H8SX_SHIFT_BINARY:
04141 operands[1] = force_reg (mode, operands[1]);
04142 return false;
04143
04144 case H8SX_SHIFT_UNARY:
04145 return false;
04146
04147 case H8SX_SHIFT_NONE:
04148 break;
04149 }
04150
04151 emit_move_insn (operands[0], operands[1]);
04152
04153
04154
04155
04156 emit_insn (gen_rtx_PARALLEL
04157 (VOIDmode,
04158 gen_rtvec (2,
04159 gen_rtx_SET (VOIDmode, operands[0],
04160 gen_rtx_fmt_ee (code, mode,
04161 operands[0], operands[2])),
04162 gen_rtx_CLOBBER (VOIDmode,
04163 gen_rtx_SCRATCH (QImode)))));
04164 return true;
04165 }
04166
04167
04168
04169 enum shift_mode
04170 {
04171 QIshift, HIshift, SIshift
04172 };
04173
04174
04175
04176
04177
04178 struct shift_insn
04179 {
04180 const char *const assembler;
04181 const int cc_valid;
04182 };
04183
04184
04185
04186
04187
04188
04189 static const struct shift_insn shift_one[2][3][3] =
04190 {
04191
04192 {
04193
04194 {
04195 { "shll\t%X0", CC_SET_ZNV },
04196 { "add.w\t%T0,%T0", CC_SET_ZN },
04197 { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", CC_CLOBBER }
04198 },
04199
04200 {
04201 { "shlr\t%X0", CC_SET_ZNV },
04202 { "shlr\t%t0\n\trotxr\t%s0", CC_CLOBBER },
04203 { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", CC_CLOBBER }
04204 },
04205
04206 {
04207 { "shar\t%X0", CC_SET_ZNV },
04208 { "shar\t%t0\n\trotxr\t%s0", CC_CLOBBER },
04209 { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", CC_CLOBBER }
04210 }
04211 },
04212
04213 {
04214
04215 {
04216 { "shll.b\t%X0", CC_SET_ZNV },
04217 { "shll.w\t%T0", CC_SET_ZNV },
04218 { "shll.l\t%S0", CC_SET_ZNV }
04219 },
04220
04221 {
04222 { "shlr.b\t%X0", CC_SET_ZNV },
04223 { "shlr.w\t%T0", CC_SET_ZNV },
04224 { "shlr.l\t%S0", CC_SET_ZNV }
04225 },
04226
04227 {
04228 { "shar.b\t%X0", CC_SET_ZNV },
04229 { "shar.w\t%T0", CC_SET_ZNV },
04230 { "shar.l\t%S0", CC_SET_ZNV }
04231 }
04232 }
04233 };
04234
04235 static const struct shift_insn shift_two[3][3] =
04236 {
04237
04238 {
04239 { "shll.b\t#2,%X0", CC_SET_ZNV },
04240 { "shll.w\t#2,%T0", CC_SET_ZNV },
04241 { "shll.l\t#2,%S0", CC_SET_ZNV }
04242 },
04243
04244 {
04245 { "shlr.b\t#2,%X0", CC_SET_ZNV },
04246 { "shlr.w\t#2,%T0", CC_SET_ZNV },
04247 { "shlr.l\t#2,%S0", CC_SET_ZNV }
04248 },
04249
04250 {
04251 { "shar.b\t#2,%X0", CC_SET_ZNV },
04252 { "shar.w\t#2,%T0", CC_SET_ZNV },
04253 { "shar.l\t#2,%S0", CC_SET_ZNV }
04254 }
04255 };
04256
04257
04258
04259
04260
04261 static const char *const rotate_one[2][3][3] =
04262 {
04263
04264 {
04265
04266 {
04267 "rotr\t%X0",
04268 "shlr\t%t0\n\trotxr\t%s0\n\tbst\t#7,%t0",
04269 0
04270 },
04271
04272 {
04273 "rotl\t%X0",
04274 "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
04275 0
04276 },
04277
04278 {
04279 "rotl\t%X0",
04280 "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
04281 0
04282 }
04283 },
04284
04285 {
04286
04287 {
04288 "rotr.b\t%X0",
04289 "rotr.w\t%T0",
04290 "rotr.l\t%S0"
04291 },
04292
04293 {
04294 "rotl.b\t%X0",
04295 "rotl.w\t%T0",
04296 "rotl.l\t%S0"
04297 },
04298
04299 {
04300 "rotl.b\t%X0",
04301 "rotl.w\t%T0",
04302 "rotl.l\t%S0"
04303 }
04304 }
04305 };
04306
04307 static const char *const rotate_two[3][3] =
04308 {
04309
04310 {
04311 "rotr.b\t#2,%X0",
04312 "rotr.w\t#2,%T0",
04313 "rotr.l\t#2,%S0"
04314 },
04315
04316 {
04317 "rotl.b\t#2,%X0",
04318 "rotl.w\t#2,%T0",
04319 "rotl.l\t#2,%S0"
04320 },
04321
04322 {
04323 "rotl.b\t#2,%X0",
04324 "rotl.w\t#2,%T0",
04325 "rotl.l\t#2,%S0"
04326 }
04327 };
04328
04329 struct shift_info {
04330
04331 enum shift_alg alg;
04332
04333
04334
04335 unsigned int remainder;
04336
04337
04338 const char *special;
04339
04340
04341
04342 const char *shift1;
04343
04344
04345
04346 const char *shift2;
04347
04348
04349 int cc_inline;
04350
04351
04352 int cc_special;
04353 };
04354
04355 static void get_shift_alg (enum shift_type,
04356 enum shift_mode, unsigned int,
04357 struct shift_info *);
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371 static void
04372 get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
04373 unsigned int count, struct shift_info *info)
04374 {
04375 enum h8_cpu cpu;
04376
04377
04378 if (TARGET_H8300)
04379 cpu = H8_300;
04380 else if (TARGET_H8300H)
04381 cpu = H8_300H;
04382 else
04383 cpu = H8_S;
04384
04385
04386 info->alg = SHIFT_LOOP;
04387 switch (shift_mode)
04388 {
04389 case QIshift:
04390 if (count < GET_MODE_BITSIZE (QImode))
04391 info->alg = shift_alg_qi[cpu][shift_type][count];
04392 break;
04393
04394 case HIshift:
04395 if (count < GET_MODE_BITSIZE (HImode))
04396 info->alg = shift_alg_hi[cpu][shift_type][count];
04397 break;
04398
04399 case SIshift:
04400 if (count < GET_MODE_BITSIZE (SImode))
04401 info->alg = shift_alg_si[cpu][shift_type][count];
04402 break;
04403
04404 default:
04405 abort ();
04406 }
04407
04408
04409 switch (info->alg)
04410 {
04411 case SHIFT_INLINE:
04412 info->remainder = count;
04413
04414
04415 case SHIFT_LOOP:
04416
04417 info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
04418 info->shift2 = shift_two[shift_type][shift_mode].assembler;
04419 info->cc_inline = shift_one[cpu_type][shift_type][shift_mode].cc_valid;
04420 goto end;
04421
04422 case SHIFT_ROT_AND:
04423 info->shift1 = rotate_one[cpu_type][shift_type][shift_mode];
04424 info->shift2 = rotate_two[shift_type][shift_mode];
04425 info->cc_inline = CC_CLOBBER;
04426 goto end;
04427
04428 case SHIFT_SPECIAL:
04429
04430 info->remainder = 0;
04431 info->shift1 = shift_one[cpu_type][shift_type][shift_mode].assembler;
04432 info->shift2 = shift_two[shift_type][shift_mode].assembler;
04433 info->cc_inline = shift_one[cpu_type][shift_type][shift_mode].cc_valid;
04434 info->cc_special = CC_CLOBBER;
04435 break;
04436 }
04437
04438
04439 switch (shift_mode)
04440 {
04441 case QIshift:
04442
04443
04444 if (shift_type == SHIFT_ASHIFTRT && count == 7)
04445 {
04446 info->special = "shll\t%X0\n\tsubx\t%X0,%X0";
04447 goto end;
04448 }
04449 abort ();
04450
04451 case HIshift:
04452 if (count == 7)
04453 {
04454 switch (shift_type)
04455 {
04456 case SHIFT_ASHIFT:
04457 if (TARGET_H8300)
04458 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";
04459 else
04460 info->special = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.w\t%T0\n\tand.b\t#0x80,%s0";
04461 goto end;
04462 case SHIFT_LSHIFTRT:
04463 if (TARGET_H8300)
04464 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";
04465 else
04466 info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.w\t%T0\n\tand.b\t#0x01,%t0";
04467 goto end;
04468 case SHIFT_ASHIFTRT:
04469 info->special = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\tsubx\t%t0,%t0";
04470 goto end;
04471 }
04472 }
04473 else if ((8 <= count && count <= 13)
04474 || (TARGET_H8300S && count == 14))
04475 {
04476 info->remainder = count - 8;
04477
04478 switch (shift_type)
04479 {
04480 case SHIFT_ASHIFT:
04481 info->special = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0";
04482 goto end;
04483 case SHIFT_LSHIFTRT:
04484 if (TARGET_H8300)
04485 {
04486 info->special = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0";
04487 info->shift1 = "shlr.b\t%s0";
04488 info->cc_inline = CC_SET_ZNV;
04489 }
04490 else
04491 {
04492 info->special = "mov.b\t%t0,%s0\n\textu.w\t%T0";
04493 info->cc_special = CC_SET_ZNV;
04494 }
04495 goto end;
04496 case SHIFT_ASHIFTRT:
04497 if (TARGET_H8300)
04498 {
04499 info->special = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0";
04500 info->shift1 = "shar.b\t%s0";
04501 }
04502 else
04503 {
04504 info->special = "mov.b\t%t0,%s0\n\texts.w\t%T0";
04505 info->cc_special = CC_SET_ZNV;
04506 }
04507 goto end;
04508 }
04509 }
04510 else if (count == 14)
04511 {
04512 switch (shift_type)
04513 {
04514 case SHIFT_ASHIFT:
04515 if (TARGET_H8300)
04516 info->special = "mov.b\t%s0,%t0\n\trotr.b\t%t0\n\trotr.b\t%t0\n\tand.b\t#0xC0,%t0\n\tsub.b\t%s0,%s0";
04517 goto end;
04518 case SHIFT_LSHIFTRT:
04519 if (TARGET_H8300)
04520 info->special = "mov.b\t%t0,%s0\n\trotl.b\t%s0\n\trotl.b\t%s0\n\tand.b\t#3,%s0\n\tsub.b\t%t0,%t0";
04521 goto end;
04522 case SHIFT_ASHIFTRT:
04523 if (TARGET_H8300)
04524 info->special = "mov.b\t%t0,%s0\n\tshll.b\t%s0\n\tsubx.b\t%t0,%t0\n\tshll.b\t%s0\n\tmov.b\t%t0,%s0\n\tbst.b\t#0,%s0";
04525 else if (TARGET_H8300H)
04526 {
04527 info->special = "shll.b\t%t0\n\tsubx.b\t%s0,%s0\n\tshll.b\t%t0\n\trotxl.b\t%s0\n\texts.w\t%T0";
04528 info->cc_special = CC_SET_ZNV;
04529 }
04530 else
04531 abort ();
04532 goto end;
04533 }
04534 }
04535 else if (count == 15)
04536 {
04537 switch (shift_type)
04538 {
04539 case SHIFT_ASHIFT:
04540 info->special = "bld\t#0,%s0\n\txor\t%s0,%s0\n\txor\t%t0,%t0\n\tbst\t#7,%t0";
04541 goto end;
04542 case SHIFT_LSHIFTRT:
04543 info->special = "bld\t#7,%t0\n\txor\t%s0,%s0\n\txor\t%t0,%t0\n\tbst\t#0,%s0";
04544 goto end;
04545 case SHIFT_ASHIFTRT:
04546 info->special = "shll\t%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0";
04547 goto end;
04548 }
04549 }
04550 abort ();
04551
04552 case SIshift:
04553 if (TARGET_H8300 && 8 <= count && count <= 9)
04554 {
04555 info->remainder = count - 8;
04556
04557 switch (shift_type)
04558 {
04559 case SHIFT_ASHIFT:
04560 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";
04561 goto end;
04562 case SHIFT_LSHIFTRT:
04563 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";
04564 info->shift1 = "shlr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0";
04565 goto end;
04566 case SHIFT_ASHIFTRT:
04567 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";
04568 goto end;
04569 }
04570 }
04571 else if (count == 8 && !TARGET_H8300)
04572 {
04573 switch (shift_type)
04574 {
04575 case SHIFT_ASHIFT:
04576 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";
04577 goto end;
04578 case SHIFT_LSHIFTRT:
04579 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";
04580 goto end;
04581 case SHIFT_ASHIFTRT:
04582 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";
04583 goto end;
04584 }
04585 }
04586 else if (count == 15 && TARGET_H8300)
04587 {
04588 switch (shift_type)
04589 {
04590 case SHIFT_ASHIFT:
04591 abort ();
04592 case SHIFT_LSHIFTRT:
04593 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\n\trotxl\t%x0\n\trotxl\t%y0";
04594 goto end;
04595 case SHIFT_ASHIFTRT:
04596 info->special = "bld\t#7,%z0\n\tmov.w\t%e0,%f0\n\trotxl\t%w0\n\trotxl\t%x0\n\tsubx\t%y0,%y0\n\tsubx\t%z0,%z0";
04597 goto end;
04598 }
04599 }
04600 else if (count == 15 && !TARGET_H8300)
04601 {
04602 switch (shift_type)
04603 {
04604 case SHIFT_ASHIFT:
04605 info->special = "shlr.w\t%e0\n\tmov.w\t%f0,%e0\n\txor.w\t%f0,%f0\n\trotxr.l\t%S0";
04606 info->cc_special = CC_SET_ZNV;
04607 goto end;
04608 case SHIFT_LSHIFTRT:
04609 info->special = "shll.w\t%f0\n\tmov.w\t%e0,%f0\n\txor.w\t%e0,%e0\n\trotxl.l\t%S0";
04610 info->cc_special = CC_SET_ZNV;
04611 goto end;
04612 case SHIFT_ASHIFTRT:
04613 abort ();
04614 }
04615 }
04616 else if ((TARGET_H8300 && 16 <= count && count <= 20)
04617 || (TARGET_H8300H && 16 <= count && count <= 19)
04618 || (TARGET_H8300S && 16 <= count && count <= 21))
04619 {
04620 info->remainder = count - 16;
04621
04622 switch (shift_type)
04623 {
04624 case SHIFT_ASHIFT:
04625 info->special = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0";
04626 if (TARGET_H8300)
04627 info->shift1 = "add.w\t%e0,%e0";
04628 goto end;
04629 case SHIFT_LSHIFTRT:
04630 if (TARGET_H8300)
04631 {
04632 info->special = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0";
04633 info->shift1 = "shlr\t%x0\n\trotxr\t%w0";
04634 }
04635 else
04636 {
04637 info->special = "mov.w\t%e0,%f0\n\textu.l\t%S0";
04638 info->cc_special = CC_SET_ZNV;
04639 }
04640 goto end;
04641 case SHIFT_ASHIFTRT:
04642 if (TARGET_H8300)
04643 {
04644 info->special = "mov.w\t%e0,%f0\n\tshll\t%z0\n\tsubx\t%z0,%z0\n\tmov.b\t%z0,%y0";
04645 info->shift1 = "shar\t%x0\n\trotxr\t%w0";
04646 }
04647 else
04648 {
04649 info->special = "mov.w\t%e0,%f0\n\texts.l\t%S0";
04650 info->cc_special = CC_SET_ZNV;
04651 }
04652 goto end;
04653 }
04654 }
04655 else if (TARGET_H8300 && 24 <= count && count <= 28)
04656 {
04657 info->remainder = count - 24;
04658
04659 switch (shift_type)
04660 {
04661 case SHIFT_ASHIFT:
04662 info->special = "mov.b\t%w0,%z0\n\tsub.b\t%y0,%y0\n\tsub.w\t%f0,%f0";
04663 info->shift1 = "shll.b\t%z0";
04664 info->cc_inline = CC_SET_ZNV;
04665 goto end;
04666 case SHIFT_LSHIFTRT:
04667 info->special = "mov.b\t%z0,%w0\n\tsub.b\t%x0,%x0\n\tsub.w\t%e0,%e0";
04668 info->shift1 = "shlr.b\t%w0";
04669 info->cc_inline = CC_SET_ZNV;
04670 goto end;
04671 case SHIFT_ASHIFTRT:
04672 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";
04673 info->shift1 = "shar.b\t%w0";
04674 info->cc_inline = CC_SET_ZNV;
04675 goto end;
04676 }
04677 }
04678 else if ((TARGET_H8300H && count == 24)
04679 || (TARGET_H8300S && 24 <= count && count <= 25))
04680 {
04681 info->remainder = count - 24;
04682
04683 switch (shift_type)
04684 {
04685 case SHIFT_ASHIFT:
04686 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";
04687 goto end;
04688 case SHIFT_LSHIFTRT:
04689 info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\textu.w\t%f0\n\textu.l\t%S0";
04690 info->cc_special = CC_SET_ZNV;
04691 goto end;
04692 case SHIFT_ASHIFTRT:
04693 info->special = "mov.w\t%e0,%f0\n\tmov.b\t%t0,%s0\n\texts.w\t%f0\n\texts.l\t%S0";
04694 info->cc_special = CC_SET_ZNV;
04695 goto end;
04696 }
04697 }
04698 else if (!TARGET_H8300 && count == 28)
04699 {
04700 switch (shift_type)
04701 {
04702 case SHIFT_ASHIFT:
04703 if (TARGET_H8300H)
04704 info->special = "sub.w\t%e0,%e0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
04705 else
04706 info->special = "sub.w\t%e0,%e0\n\trotr.l\t#2,%S0\n\trotr.l\t#2,%S0\n\tsub.w\t%f0,%f0";
04707 goto end;
04708 case SHIFT_LSHIFTRT:
04709 if (TARGET_H8300H)
04710 {
04711 info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
04712 info->cc_special = CC_SET_ZNV;
04713 }
04714 else
04715 info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\trotl.l\t#2,%S0\n\textu.l\t%S0";
04716 goto end;
04717 case SHIFT_ASHIFTRT:
04718 abort ();
04719 }
04720 }
04721 else if (!TARGET_H8300 && count == 29)
04722 {
04723 switch (shift_type)
04724 {
04725 case SHIFT_ASHIFT:
04726 if (TARGET_H8300H)
04727 info->special = "sub.w\t%e0,%e0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
04728 else
04729 info->special = "sub.w\t%e0,%e0\n\trotr.l\t#2,%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
04730 goto end;
04731 case SHIFT_LSHIFTRT:
04732 if (TARGET_H8300H)
04733 {
04734 info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
04735 info->cc_special = CC_SET_ZNV;
04736 }
04737 else
04738 {
04739 info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
04740 info->cc_special = CC_SET_ZNV;
04741 }
04742 goto end;
04743 case SHIFT_ASHIFTRT:
04744 abort ();
04745 }
04746 }
04747 else if (!TARGET_H8300 && count == 30)
04748 {
04749 switch (shift_type)
04750 {
04751 case SHIFT_ASHIFT:
04752 if (TARGET_H8300H)
04753 info->special = "sub.w\t%e0,%e0\n\trotr.l\t%S0\n\trotr.l\t%S0\n\tsub.w\t%f0,%f0";
04754 else
04755 info->special = "sub.w\t%e0,%e0\n\trotr.l\t#2,%S0\n\tsub.w\t%f0,%f0";
04756 goto end;
04757 case SHIFT_LSHIFTRT:
04758 if (TARGET_H8300H)
04759 info->special = "sub.w\t%f0,%f0\n\trotl.l\t%S0\n\trotl.l\t%S0\n\textu.l\t%S0";
04760 else
04761 info->special = "sub.w\t%f0,%f0\n\trotl.l\t#2,%S0\n\textu.l\t%S0";
04762 goto end;
04763 case SHIFT_ASHIFTRT:
04764 abort ();
04765 }
04766 }
04767 else if (count == 31)
04768 {
04769 if (TARGET_H8300)
04770 {
04771 switch (shift_type)
04772 {
04773 case SHIFT_ASHIFT:
04774 info->special = "sub.w\t%e0,%e0\n\tshlr\t%w0\n\tmov.w\t%e0,%f0\n\trotxr\t%z0";
04775 goto end;
04776 case SHIFT_LSHIFTRT:
04777 info->special = "sub.w\t%f0,%f0\n\tshll\t%z0\n\tmov.w\t%f0,%e0\n\trotxl\t%w0";
04778 goto end;
04779 case SHIFT_ASHIFTRT:
04780 info->special = "shll\t%z0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
04781 goto end;
04782 }
04783 }
04784 else
04785 {
04786 switch (shift_type)
04787 {
04788 case SHIFT_ASHIFT:
04789 info->special = "shlr.l\t%S0\n\txor.l\t%S0,%S0\n\trotxr.l\t%S0";
04790 info->cc_special = CC_SET_ZNV;
04791 goto end;
04792 case SHIFT_LSHIFTRT:
04793 info->special = "shll.l\t%S0\n\txor.l\t%S0,%S0\n\trotxl.l\t%S0";
04794 info->cc_special = CC_SET_ZNV;
04795 goto end;
04796 case SHIFT_ASHIFTRT:
04797 info->special = "shll\t%e0\n\tsubx\t%w0,%w0\n\texts.w\t%T0\n\texts.l\t%S0";
04798 info->cc_special = CC_SET_ZNV;
04799 goto end;
04800 }
04801 }
04802 }
04803 abort ();
04804
04805 default:
04806 abort ();
04807 }
04808
04809 end:
04810 if (!TARGET_H8300S)
04811 info->shift2 = NULL;
04812 }
04813
04814
04815
04816
04817 int
04818 h8300_shift_needs_scratch_p (int count, enum machine_mode mode)
04819 {
04820 enum h8_cpu cpu;
04821 int a, lr, ar;
04822
04823 if (GET_MODE_BITSIZE (mode) <= count)
04824 return 1;
04825
04826
04827 if (TARGET_H8300)
04828 cpu = H8_300;
04829 else if (TARGET_H8300H)
04830 cpu = H8_300H;
04831 else
04832 cpu = H8_S;
04833
04834
04835 switch (mode)
04836 {
04837 case QImode:
04838 a = shift_alg_qi[cpu][SHIFT_ASHIFT][count];
04839 lr = shift_alg_qi[cpu][SHIFT_LSHIFTRT][count];
04840 ar = shift_alg_qi[cpu][SHIFT_ASHIFTRT][count];
04841 break;
04842
04843 case HImode:
04844 a = shift_alg_hi[cpu][SHIFT_ASHIFT][count];
04845 lr = shift_alg_hi[cpu][SHIFT_LSHIFTRT][count];
04846 ar = shift_alg_hi[cpu][SHIFT_ASHIFTRT][count];
04847 break;
04848
04849 case SImode:
04850 a = shift_alg_si[cpu][SHIFT_ASHIFT][count];
04851 lr = shift_alg_si[cpu][SHIFT_LSHIFTRT][count];
04852 ar = shift_alg_si[cpu][SHIFT_ASHIFTRT][count];
04853 break;
04854
04855 default:
04856 abort ();
04857 }
04858
04859
04860 return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
04861 || (TARGET_H8300H && mode == SImode && count == 8));
04862 }
04863
04864
04865
04866 const char *
04867 output_a_shift (rtx *operands)
04868 {
04869 static int loopend_lab;
04870 rtx shift = operands[3];
04871 enum machine_mode mode = GET_MODE (shift);
04872 enum rtx_code code = GET_CODE (shift);
04873 enum shift_type shift_type;
04874 enum shift_mode shift_mode;
04875 struct shift_info info;
04876
04877 loopend_lab++;
04878
04879 switch (mode)
04880 {
04881 case QImode:
04882 shift_mode = QIshift;
04883 break;
04884 case HImode:
04885 shift_mode = HIshift;
04886 break;
04887 case SImode:
04888 shift_mode = SIshift;
04889 break;
04890 default:
04891 abort ();
04892 }
04893
04894 switch (code)
04895 {
04896 case ASHIFTRT:
04897 shift_type = SHIFT_ASHIFTRT;
04898 break;
04899 case LSHIFTRT:
04900 shift_type = SHIFT_LSHIFTRT;
04901 break;
04902 case ASHIFT:
04903 shift_type = SHIFT_ASHIFT;
04904 break;
04905 default:
04906 abort ();
04907 }
04908
04909 if (GET_CODE (operands[2]) != CONST_INT)
04910 {
04911
04912
04913 abort ();
04914 }
04915 else
04916 {
04917 int n = INTVAL (operands[2]);
04918
04919
04920 if (n < 0)
04921 n = 0;
04922
04923
04924
04925 else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
04926 n = GET_MODE_BITSIZE (mode);
04927
04928 get_shift_alg (shift_type, shift_mode, n, &info);
04929
04930 switch (info.alg)
04931 {
04932 case SHIFT_SPECIAL:
04933 output_asm_insn (info.special, operands);
04934
04935
04936 case SHIFT_INLINE:
04937 n = info.remainder;
04938
04939
04940 if (info.shift2 != NULL)
04941 {
04942 for (; n > 1; n -= 2)
04943 output_asm_insn (info.shift2, operands);
04944 }
04945
04946
04947 for (; n > 0; n--)
04948 output_asm_insn (info.shift1, operands);
04949 return "";
04950
04951 case SHIFT_ROT_AND:
04952 {
04953 int m = GET_MODE_BITSIZE (mode) - n;
04954 const int mask = (shift_type == SHIFT_ASHIFT
04955 ? ((1 << m) - 1) << n
04956 : (1 << m) - 1);
04957 char insn_buf[200];
04958
04959
04960
04961 if (info.shift1 == 0)
04962 abort ();
04963
04964
04965 if (info.shift2 != NULL)
04966 {
04967 for (; m > 1; m -= 2)
04968 output_asm_insn (info.shift2, operands);
04969 }
04970
04971
04972 for (; m > 0; m--)
04973 output_asm_insn (info.shift1, operands);
04974
04975
04976 if (mode == QImode)
04977 sprintf (insn_buf, "and\t#%d,%%X0", mask);
04978 else if (mode == HImode && (TARGET_H8300H || TARGET_H8300S))
04979 sprintf (insn_buf, "and.w\t#%d,%%T0", mask);
04980 else
04981 abort ();
04982
04983 output_asm_insn (insn_buf, operands);
04984 return "";
04985 }
04986
04987 case SHIFT_LOOP:
04988
04989
04990 if (info.shift2 != NULL)
04991 {
04992 fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n / 2,
04993 names_big[REGNO (operands[4])]);
04994 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
04995 output_asm_insn (info.shift2, operands);
04996 output_asm_insn ("add #0xff,%X4", operands);
04997 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
04998 if (n % 2)
04999 output_asm_insn (info.shift1, operands);
05000 }
05001 else
05002 {
05003 fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n,
05004 names_big[REGNO (operands[4])]);
05005 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
05006 output_asm_insn (info.shift1, operands);
05007 output_asm_insn ("add #0xff,%X4", operands);
05008 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
05009 }
05010 return "";
05011
05012 default:
05013 abort ();
05014 }
05015 }
05016 }
05017
05018
05019
05020 static unsigned int
05021 h8300_asm_insn_count (const char *template)
05022 {
05023 unsigned int count = 1;
05024
05025 for (; *template; template++)
05026 if (*template == '\n')
05027 count++;
05028
05029 return count;
05030 }
05031
05032
05033
05034 unsigned int
05035 compute_a_shift_length (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
05036 {
05037 rtx shift = operands[3];
05038 enum machine_mode mode = GET_MODE (shift);
05039 enum rtx_code code = GET_CODE (shift);
05040 enum shift_type shift_type;
05041 enum shift_mode shift_mode;
05042 struct shift_info info;
05043 unsigned int wlength = 0;
05044
05045 switch (mode)
05046 {
05047 case QImode:
05048 shift_mode = QIshift;
05049 break;
05050 case HImode:
05051 shift_mode = HIshift;
05052 break;
05053 case SImode:
05054 shift_mode = SIshift;
05055 break;
05056 default:
05057 abort ();
05058 }
05059
05060 switch (code)
05061 {
05062 case ASHIFTRT:
05063 shift_type = SHIFT_ASHIFTRT;
05064 break;
05065 case LSHIFTRT:
05066 shift_type = SHIFT_LSHIFTRT;
05067 break;
05068 case ASHIFT:
05069 shift_type = SHIFT_ASHIFT;
05070 break;
05071 default:
05072 abort ();
05073 }
05074
05075 if (GET_CODE (operands[2]) != CONST_INT)
05076 {
05077
05078 get_shift_alg (shift_type, shift_mode, 1, &info);
05079
05080 return (4 + h8300_asm_insn_count (info.shift1)) * 2;
05081 }
05082 else
05083 {
05084 int n = INTVAL (operands[2]);
05085
05086
05087 if (n < 0)
05088 n = 0;
05089
05090
05091
05092 else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
05093 n = GET_MODE_BITSIZE (mode);
05094
05095 get_shift_alg (shift_type, shift_mode, n, &info);
05096
05097 switch (info.alg)
05098 {
05099 case SHIFT_SPECIAL:
05100 wlength += h8300_asm_insn_count (info.special);
05101
05102
05103
05104
05105
05106 if (strstr (info.special, "xor.l") != NULL)
05107 wlength++;
05108
05109
05110
05111 case SHIFT_INLINE:
05112 n = info.remainder;
05113
05114 if (info.shift2 != NULL)
05115 {
05116 wlength += h8300_asm_insn_count (info.shift2) * (n / 2);
05117 n = n % 2;
05118 }
05119
05120 wlength += h8300_asm_insn_count (info.shift1) * n;
05121
05122 return 2 * wlength;
05123
05124 case SHIFT_ROT_AND:
05125 {
05126 int m = GET_MODE_BITSIZE (mode) - n;
05127
05128
05129
05130 if (info.shift1 == 0)
05131 abort ();
05132
05133 if (info.shift2 != NULL)
05134 {
05135 wlength += h8300_asm_insn_count (info.shift2) * (m / 2);
05136 m = m % 2;
05137 }
05138
05139 wlength += h8300_asm_insn_count (info.shift1) * m;
05140
05141
05142 switch (mode)
05143 {
05144 case QImode:
05145 wlength += 1;
05146 break;
05147 case HImode:
05148 wlength += 2;
05149 break;
05150 case SImode:
05151 if (TARGET_H8300)
05152 abort ();
05153 wlength += 3;
05154 break;
05155 default:
05156 abort ();
05157 }
05158 return 2 * wlength;
05159 }
05160
05161 case SHIFT_LOOP:
05162
05163
05164 if (info.shift2 != NULL)
05165 {
05166 wlength += 3 + h8300_asm_insn_count (info.shift2);
05167 if (n % 2)
05168 wlength += h8300_asm_insn_count (info.shift1);
05169 }
05170 else
05171 {
05172 wlength += 3 + h8300_asm_insn_count (info.shift1);
05173 }
05174 return 2 * wlength;
05175
05176 default:
05177 abort ();
05178 }
05179 }
05180 }
05181
05182
05183
05184 int
05185 compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
05186 {
05187 rtx shift = operands[3];
05188 enum machine_mode mode = GET_MODE (shift);
05189 enum rtx_code code = GET_CODE (shift);
05190 enum shift_type shift_type;
05191 enum shift_mode shift_mode;
05192 struct shift_info info;
05193
05194 switch (mode)
05195 {
05196 case QImode:
05197 shift_mode = QIshift;
05198 break;
05199 case HImode:
05200 shift_mode = HIshift;
05201 break;
05202 case SImode:
05203 shift_mode = SIshift;
05204 break;
05205 default:
05206 abort ();
05207 }
05208
05209 switch (code)
05210 {
05211 case ASHIFTRT:
05212 shift_type = SHIFT_ASHIFTRT;
05213 break;
05214 case LSHIFTRT:
05215 shift_type = SHIFT_LSHIFTRT;
05216 break;
05217 case ASHIFT:
05218 shift_type = SHIFT_ASHIFT;
05219 break;
05220 default:
05221 abort ();
05222 }
05223
05224 if (GET_CODE (operands[2]) != CONST_INT)
05225 {
05226
05227
05228 abort ();
05229 }
05230 else
05231 {
05232 int n = INTVAL (operands[2]);
05233
05234
05235 if (n < 0)
05236 n = 0;
05237
05238
05239
05240 else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
05241 n = GET_MODE_BITSIZE (mode);
05242
05243 get_shift_alg (shift_type, shift_mode, n, &info);
05244
05245 switch (info.alg)
05246 {
05247 case SHIFT_SPECIAL:
05248 if (info.remainder == 0)
05249 return info.cc_special;
05250
05251
05252
05253 case SHIFT_INLINE:
05254 return info.cc_inline;
05255
05256 case SHIFT_ROT_AND:
05257
05258 return CC_SET_ZNV;
05259
05260 case SHIFT_LOOP:
05261
05262
05263 if (info.shift2 != NULL)
05264 {
05265 if (n % 2)
05266 return info.cc_inline;
05267 }
05268 return CC_CLOBBER;
05269
05270 default:
05271 abort ();
05272 }
05273 }
05274 }
05275
05276
05277
05278
05279
05280
05281 int
05282 expand_a_rotate (rtx operands[])
05283 {
05284 rtx dst = operands[0];
05285 rtx src = operands[1];
05286 rtx rotate_amount = operands[2];
05287 enum machine_mode mode = GET_MODE (dst);
05288
05289 if (h8sx_classify_shift (mode, ROTATE, rotate_amount) == H8SX_SHIFT_UNARY)
05290 return false;
05291
05292
05293 emit_move_insn (dst, src);
05294
05295 if (GET_CODE (rotate_amount) != CONST_INT)
05296 {
05297 rtx counter = gen_reg_rtx (QImode);
05298 rtx start_label = gen_label_rtx ();
05299 rtx end_label = gen_label_rtx ();
05300
05301
05302
05303 emit_cmp_and_jump_insns (rotate_amount, const0_rtx, LE, NULL_RTX,
05304 QImode, 0, end_label);
05305
05306
05307 emit_move_insn (counter, rotate_amount);
05308
05309 emit_label (start_label);
05310
05311
05312 switch (mode)
05313 {
05314 case QImode:
05315 emit_insn (gen_rotlqi3_1 (dst, dst, const1_rtx));
05316 break;
05317 case HImode:
05318 emit_insn (gen_rotlhi3_1 (dst, dst, const1_rtx));
05319 break;
05320 case SImode:
05321 emit_insn (gen_rotlsi3_1 (dst, dst, const1_rtx));
05322 break;
05323 default:
05324 abort ();
05325 }
05326
05327
05328 emit_insn (gen_addqi3 (counter, counter, constm1_rtx));
05329
05330
05331
05332 emit_cmp_and_jump_insns (counter, const0_rtx, NE, NULL_RTX, QImode, 1,
05333 start_label);
05334
05335 emit_label (end_label);
05336 }
05337 else
05338 {
05339
05340 switch (mode)
05341 {
05342 case QImode:
05343 emit_insn (gen_rotlqi3_1 (dst, dst, rotate_amount));
05344 break;
05345 case HImode:
05346 emit_insn (gen_rotlhi3_1 (dst, dst, rotate_amount));
05347 break;
05348 case SImode:
05349 emit_insn (gen_rotlsi3_1 (dst, dst, rotate_amount));
05350 break;
05351 default:
05352 abort ();
05353 }
05354 }
05355
05356 return 1;
05357 }
05358
05359
05360
05361 const char *
05362 output_a_rotate (enum rtx_code code, rtx *operands)
05363 {
05364 rtx dst = operands[0];
05365 rtx rotate_amount = operands[2];
05366 enum shift_mode rotate_mode;
05367 enum shift_type rotate_type;
05368 const char *insn_buf;
05369 int bits;
05370 int amount;
05371 enum machine_mode mode = GET_MODE (dst);
05372
05373 if (GET_CODE (rotate_amount) != CONST_INT)
05374 abort ();
05375
05376 switch (mode)
05377 {
05378 case QImode:
05379 rotate_mode = QIshift;
05380 break;
05381 case HImode:
05382 rotate_mode = HIshift;
05383 break;
05384 case SImode:
05385 rotate_mode = SIshift;
05386 break;
05387 default:
05388 abort ();
05389 }
05390
05391 switch (code)
05392 {
05393 case ROTATERT:
05394 rotate_type = SHIFT_ASHIFT;
05395 break;
05396 case ROTATE:
05397 rotate_type = SHIFT_LSHIFTRT;
05398 break;
05399 default:
05400 abort ();
05401 }
05402
05403 amount = INTVAL (rotate_amount);
05404
05405
05406 if (amount < 0)
05407 amount = 0;
05408 if ((unsigned int) amount > GET_MODE_BITSIZE (mode))
05409 amount = GET_MODE_BITSIZE (mode);
05410
05411
05412
05413 if ((unsigned int) amount > GET_MODE_BITSIZE (mode) / (unsigned) 2)
05414 {
05415
05416 amount = GET_MODE_BITSIZE (mode) - amount;
05417 rotate_type =
05418 (rotate_type == SHIFT_ASHIFT) ? SHIFT_LSHIFTRT : SHIFT_ASHIFT;
05419 }
05420
05421
05422
05423 if ((mode == HImode && TARGET_H8300 && amount >= 5)
05424 || (mode == HImode && TARGET_H8300H && amount >= 6)
05425 || (mode == HImode && TARGET_H8300S && amount == 8)
05426 || (mode == SImode && TARGET_H8300H && amount >= 10)
05427 || (mode == SImode && TARGET_H8300S && amount >= 13))
05428 {
05429 switch (mode)
05430 {
05431 case HImode:
05432
05433 insn_buf = "xor.b\t%s0,%t0\n\txor.b\t%t0,%s0\n\txor.b\t%s0,%t0";
05434 output_asm_insn (insn_buf, operands);
05435 break;
05436
05437 case SImode:
05438
05439 insn_buf = "xor.w\t%e0,%f0\n\txor.w\t%f0,%e0\n\txor.w\t%e0,%f0";
05440 output_asm_insn (insn_buf, operands);
05441 break;
05442
05443 default:
05444 abort ();
05445 }
05446
05447
05448 amount = GET_MODE_BITSIZE (mode) / 2 - amount;
05449 rotate_type =
05450 (rotate_type == SHIFT_ASHIFT) ? SHIFT_LSHIFTRT : SHIFT_ASHIFT;
05451 }
05452
05453
05454 for (bits = TARGET_H8300S ? 2 : 1; bits > 0; bits /= 2)
05455 {
05456 if (bits == 2)
05457 insn_buf = rotate_two[rotate_type][rotate_mode];
05458 else
05459 insn_buf = rotate_one[cpu_type][rotate_type][rotate_mode];
05460
05461 for (; amount >= bits; amount -= bits)
05462 output_asm_insn (insn_buf, operands);
05463 }
05464
05465 return "";
05466 }
05467
05468
05469
05470 unsigned int
05471 compute_a_rotate_length (rtx *operands)
05472 {
05473 rtx src = operands[1];
05474 rtx amount_rtx = operands[2];
05475 enum machine_mode mode = GET_MODE (src);
05476 int amount;
05477 unsigned int length = 0;
05478
05479 if (GET_CODE (amount_rtx) != CONST_INT)
05480 abort ();
05481
05482 amount = INTVAL (amount_rtx);
05483
05484
05485 if (amount < 0)
05486 amount = 0;
05487 if ((unsigned int) amount > GET_MODE_BITSIZE (mode))
05488 amount = GET_MODE_BITSIZE (mode);
05489
05490
05491
05492 if ((unsigned int) amount > GET_MODE_BITSIZE (mode) / (unsigned) 2)
05493
05494 amount = GET_MODE_BITSIZE (mode) - amount;
05495
05496
05497
05498 if ((mode == HImode && TARGET_H8300 && amount >= 5)
05499 || (mode == HImode && TARGET_H8300H && amount >= 6)
05500 || (mode == HImode && TARGET_H8300S && amount == 8)
05501 || (mode == SImode && TARGET_H8300H && amount >= 10)
05502 || (mode == SImode && TARGET_H8300S && amount >= 13))
05503 {
05504
05505 amount = GET_MODE_BITSIZE (mode) / 2 - amount;
05506 length += 6;
05507 }
05508
05509
05510 if (TARGET_H8300S)
05511 amount = amount / 2 + amount % 2;
05512
05513
05514
05515 length += amount * ((TARGET_H8300 && mode == HImode) ? 6 : 2);
05516
05517 return length;
05518 }
05519
05520
05521
05522
05523 int
05524 fix_bit_operand (rtx *operands, enum rtx_code code)
05525 {
05526
05527
05528
05529
05530 if (code == AND
05531 ? single_zero_operand (operands[2], QImode)
05532 : single_one_operand (operands[2], QImode))
05533 {
05534
05535 if (GET_CODE (operands[0]) == MEM
05536 && !OK_FOR_U (operands[0]))
05537 {
05538 rtx mem = gen_rtx_MEM (GET_MODE (operands[0]),
05539 copy_to_mode_reg (Pmode,
05540 XEXP (operands[0], 0)));
05541 MEM_COPY_ATTRIBUTES (mem, operands[0]);
05542 operands[0] = mem;
05543 }
05544
05545 if (GET_CODE (operands[1]) == MEM
05546 && !OK_FOR_U (operands[1]))
05547 {
05548 rtx mem = gen_rtx_MEM (GET_MODE (operands[1]),
05549 copy_to_mode_reg (Pmode,
05550 XEXP (operands[1], 0)));
05551 MEM_COPY_ATTRIBUTES (mem, operands[0]);
05552 operands[1] = mem;
05553 }
05554 return 0;
05555 }
05556
05557
05558
05559 operands[1] = force_reg (QImode, operands[1]);
05560 {
05561 rtx res = gen_reg_rtx (QImode);
05562 switch (code)
05563 {
05564 case AND:
05565 emit_insn (gen_andqi3_1 (res, operands[1], operands[2]));
05566 break;
05567 case IOR:
05568 emit_insn (gen_iorqi3_1 (res, operands[1], operands[2]));
05569 break;
05570 case XOR:
05571 emit_insn (gen_xorqi3_1 (res, operands[1], operands[2]));
05572 break;
05573 default:
05574 abort ();
05575 }
05576 emit_insn (gen_movqi (operands[0], res));
05577 }
05578 return 1;
05579 }
05580
05581
05582
05583
05584 static int
05585 h8300_interrupt_function_p (tree func)
05586 {
05587 tree a;
05588
05589 if (TREE_CODE (func) != FUNCTION_DECL)
05590 return 0;
05591
05592 a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
05593 return a != NULL_TREE;
05594 }
05595
05596
05597
05598
05599 static int
05600 h8300_saveall_function_p (tree func)
05601 {
05602 tree a;
05603
05604 if (TREE_CODE (func) != FUNCTION_DECL)
05605 return 0;
05606
05607 a = lookup_attribute ("saveall", DECL_ATTRIBUTES (func));
05608 return a != NULL_TREE;
05609 }
05610
05611
05612
05613
05614 static int
05615 h8300_os_task_function_p (tree func)
05616 {
05617 tree a;
05618
05619 if (TREE_CODE (func) != FUNCTION_DECL)
05620 return 0;
05621
05622 a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
05623 return a != NULL_TREE;
05624 }
05625
05626
05627
05628
05629 static int
05630 h8300_monitor_function_p (tree func)
05631 {
05632 tree a;
05633
05634 if (TREE_CODE (func) != FUNCTION_DECL)
05635 return 0;
05636
05637 a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
05638 return a != NULL_TREE;
05639 }
05640
05641
05642
05643
05644 int
05645 h8300_funcvec_function_p (tree func)
05646 {
05647 tree a;
05648
05649 if (TREE_CODE (func) != FUNCTION_DECL)
05650 return 0;
05651
05652 a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
05653 return a != NULL_TREE;
05654 }
05655
05656
05657
05658
05659 int
05660 h8300_eightbit_data_p (tree decl)
05661 {
05662 tree a;
05663
05664 if (TREE_CODE (decl) != VAR_DECL)
05665 return 0;
05666
05667 a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
05668 return a != NULL_TREE;
05669 }
05670
05671
05672
05673
05674 int
05675 h8300_tiny_data_p (tree decl)
05676 {
05677 tree a;
05678
05679 if (TREE_CODE (decl) != VAR_DECL)
05680 return 0;
05681
05682 a = lookup_attribute ("tiny_data", DECL_ATTRIBUTES (decl));
05683 return a != NULL_TREE;
05684 }
05685
05686
05687
05688
05689 static void
05690 h8300_insert_attributes (tree node, tree *attributes)
05691 {
05692 if (TREE_CODE (node) == FUNCTION_DECL)
05693 {
05694 if (pragma_interrupt)
05695 {
05696 pragma_interrupt = 0;
05697
05698
05699 *attributes = tree_cons (get_identifier ("interrupt_handler"),
05700 NULL, *attributes);
05701 }
05702
05703 if (pragma_saveall)
05704 {
05705 pragma_saveall = 0;
05706
05707
05708 *attributes = tree_cons (get_identifier ("saveall"),
05709 NULL, *attributes);
05710 }
05711 }
05712 }
05713
05714
05715
05716
05717
05718
05719
05720
05721
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731 const struct attribute_spec h8300_attribute_table[] =
05732 {
05733
05734 { "interrupt_handler", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
05735 { "saveall", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
05736 { "OS_Task", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
05737 { "monitor", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
05738 { "function_vector", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
05739 { "eightbit_data", 0, 0, true, false, false, h8300_handle_eightbit_data_attribute },
05740 { "tiny_data", 0, 0, true, false, false, h8300_handle_tiny_data_attribute },
05741 { NULL, 0, 0, false, false, false, NULL }
05742 };
05743
05744
05745
05746
05747 static tree
05748 h8300_handle_fndecl_attribute (tree *node, tree name,
05749 tree args ATTRIBUTE_UNUSED,
05750 int flags ATTRIBUTE_UNUSED,
05751 bool *no_add_attrs)
05752 {
05753 if (TREE_CODE (*node) != FUNCTION_DECL)
05754 {
05755 warning ("%qs attribute only applies to functions",
05756 IDENTIFIER_POINTER (name));
05757 *no_add_attrs = true;
05758 }
05759
05760 return NULL_TREE;
05761 }
05762
05763
05764
05765 static tree
05766 h8300_handle_eightbit_data_attribute (tree *node, tree name,
05767 tree args ATTRIBUTE_UNUSED,
05768 int flags ATTRIBUTE_UNUSED,
05769 bool *no_add_attrs)
05770 {
05771 tree decl = *node;
05772
05773 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
05774 {
05775 DECL_SECTION_NAME (decl) = build_string (7, ".eight");
05776 }
05777 else
05778 {
05779 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
05780 *no_add_attrs = true;
05781 }
05782
05783 return NULL_TREE;
05784 }
05785
05786
05787
05788 static tree
05789 h8300_handle_tiny_data_attribute (tree *node, tree name,
05790 tree args ATTRIBUTE_UNUSED,
05791 int flags ATTRIBUTE_UNUSED,
05792 bool *no_add_attrs)
05793 {
05794 tree decl = *node;
05795
05796 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
05797 {
05798 DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
05799 }
05800 else
05801 {
05802 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
05803 *no_add_attrs = true;
05804 }
05805
05806 return NULL_TREE;
05807 }
05808
05809
05810
05811 static void
05812 h8300_encode_section_info (tree decl, rtx rtl, int first)
05813 {
05814 int extra_flags = 0;
05815
05816 default_encode_section_info (decl, rtl, first);
05817
05818 if (TREE_CODE (decl) == FUNCTION_DECL
05819 && h8300_funcvec_function_p (decl))
05820 extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
05821 else if (TREE_CODE (decl) == VAR_DECL
05822 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
05823 {
05824 if (h8300_eightbit_data_p (decl))
05825 extra_flags = SYMBOL_FLAG_EIGHTBIT_DATA;
05826 else if (first && h8300_tiny_data_p (decl))
05827 extra_flags = SYMBOL_FLAG_TINY_DATA;
05828 }
05829
05830 if (extra_flags)
05831 SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
05832 }
05833
05834
05835
05836 const char *
05837 output_simode_bld (int bild, rtx operands[])
05838 {
05839 if (TARGET_H8300)
05840 {
05841
05842 output_asm_insn ("sub.w\t%e0,%e0\n\tsub.w\t%f0,%f0", operands);
05843
05844
05845
05846 if (bild)
05847 output_asm_insn ("bild\t%Z2,%Y1", operands);
05848 else
05849 output_asm_insn ("bld\t%Z2,%Y1", operands);
05850
05851 output_asm_insn ("bst\t#0,%w0", operands);
05852 }
05853 else
05854 {
05855
05856 int clear_first = (REG_P (operands[0]) && REG_P (operands[1])
05857 && REGNO (operands[0]) != REGNO (operands[1]));
05858
05859 if (clear_first)
05860 output_asm_insn ("sub.l\t%S0,%S0", operands);
05861
05862
05863 if (bild)
05864 output_asm_insn ("bild\t%Z2,%Y1", operands);
05865 else
05866 output_asm_insn ("bld\t%Z2,%Y1", operands);
05867
05868 if (!clear_first)
05869 output_asm_insn ("xor.l\t%S0,%S0", operands);
05870
05871
05872 output_asm_insn ("rotxl.l\t%S0", operands);
05873 }
05874
05875
05876 return "";
05877 }
05878
05879
05880
05881
05882
05883 static void
05884 h8300_reorg (void)
05885 {
05886 if (flag_delayed_branch)
05887 shorten_branches (get_insns ());
05888 }
05889
05890 #ifndef OBJECT_FORMAT_ELF
05891 static void
05892 h8300_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED,
05893 tree decl)
05894 {
05895
05896 fprintf (asm_out_file, "\t.section %s\n", name);
05897 }
05898 #endif
05899
05900
05901
05902
05903 int
05904 h8300_eightbit_constant_address_p (rtx x)
05905 {
05906
05907 const unsigned HOST_WIDE_INT n1 = trunc_int_for_mode (0xff00, HImode);
05908 const unsigned HOST_WIDE_INT n2 = trunc_int_for_mode (0xffff, HImode);
05909 const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode (0x00ffff00, SImode);
05910 const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode (0x00ffffff, SImode);
05911 const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode (0xffffff00, SImode);
05912 const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode (0xffffffff, SImode);
05913
05914 unsigned HOST_WIDE_INT addr;
05915
05916
05917 if (GET_CODE (x) == SYMBOL_REF)
05918 return (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_EIGHTBIT_DATA) != 0;
05919
05920 if (GET_CODE (x) != CONST_INT)
05921 return 0;
05922
05923 addr = INTVAL (x);
05924
05925 return (0
05926 || ((TARGET_H8300 || TARGET_NORMAL_MODE) && IN_RANGE (addr, n1, n2))
05927 || (TARGET_H8300H && IN_RANGE (addr, h1, h2))
05928 || (TARGET_H8300S && IN_RANGE (addr, s1, s2)));
05929 }
05930
05931
05932
05933
05934 int
05935 h8300_tiny_constant_address_p (rtx x)
05936 {
05937
05938 const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode (0x00000000, SImode);
05939 const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode (0x00007fff, SImode);
05940 const unsigned HOST_WIDE_INT h3 = trunc_int_for_mode (0x00ff8000, SImode);
05941 const unsigned HOST_WIDE_INT h4 = trunc_int_for_mode (0x00ffffff, SImode);
05942 const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode (0x00000000, SImode);
05943 const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode (0x00007fff, SImode);
05944 const unsigned HOST_WIDE_INT s3 = trunc_int_for_mode (0xffff8000, SImode);
05945 const unsigned HOST_WIDE_INT s4 = trunc_int_for_mode (0xffffffff, SImode);
05946
05947 unsigned HOST_WIDE_INT addr;
05948
05949 switch (GET_CODE (x))
05950 {
05951 case SYMBOL_REF:
05952
05953
05954
05955 return (TARGET_NORMAL_MODE
05956 || (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_TINY_DATA) != 0);
05957
05958 case CONST_INT:
05959 addr = INTVAL (x);
05960 return (TARGET_NORMAL_MODE
05961 || (TARGET_H8300H
05962 && (IN_RANGE (addr, h1, h2) || IN_RANGE (addr, h3, h4)))
05963 || (TARGET_H8300S
05964 && (IN_RANGE (addr, s1, s2) || IN_RANGE (addr, s3, s4))));
05965
05966 case CONST:
05967 return TARGET_NORMAL_MODE;
05968
05969 default:
05970 return 0;
05971 }
05972
05973 }
05974
05975
05976
05977
05978 int
05979 byte_accesses_mergeable_p (rtx addr1, rtx addr2)
05980 {
05981 HOST_WIDE_INT offset1, offset2;
05982 rtx reg1, reg2;
05983
05984 if (REG_P (addr1))
05985 {
05986 reg1 = addr1;
05987 offset1 = 0;
05988 }
05989 else if (GET_CODE (addr1) == PLUS
05990 && REG_P (XEXP (addr1, 0))
05991 && GET_CODE (XEXP (addr1, 1)) == CONST_INT)
05992 {
05993 reg1 = XEXP (addr1, 0);
05994 offset1 = INTVAL (XEXP (addr1, 1));
05995 }
05996 else
05997 return 0;
05998
05999 if (REG_P (addr2))
06000 {
06001 reg2 = addr2;
06002 offset2 = 0;
06003 }
06004 else if (GET_CODE (addr2) == PLUS
06005 && REG_P (XEXP (addr2, 0))
06006 && GET_CODE (XEXP (addr2, 1)) == CONST_INT)
06007 {
06008 reg2 = XEXP (addr2, 0);
06009 offset2 = INTVAL (XEXP (addr2, 1));
06010 }
06011 else
06012 return 0;
06013
06014 if (((reg1 == stack_pointer_rtx && reg2 == stack_pointer_rtx)
06015 || (reg1 == frame_pointer_rtx && reg2 == frame_pointer_rtx))
06016 && offset1 % 2 == 0
06017 && offset1 + 1 == offset2)
06018 return 1;
06019
06020 return 0;
06021 }
06022
06023
06024
06025
06026 int
06027 same_cmp_preceding_p (rtx i3)
06028 {
06029 rtx i1, i2;
06030
06031
06032 i2 = prev_nonnote_insn (i3);
06033 if (i2 == NULL_RTX)
06034 return 0;
06035 i1 = prev_nonnote_insn (i2);
06036 if (i1 == NULL_RTX)
06037 return 0;
06038
06039 return (INSN_P (i1) && rtx_equal_p (PATTERN (i1), PATTERN (i3))
06040 && any_condjump_p (i2) && onlyjump_p (i2));
06041 }
06042
06043
06044
06045
06046 int
06047 same_cmp_following_p (rtx i1)
06048 {
06049 rtx i2, i3;
06050
06051
06052 i2 = next_nonnote_insn (i1);
06053 if (i2 == NULL_RTX)
06054 return 0;
06055 i3 = next_nonnote_insn (i2);
06056 if (i3 == NULL_RTX)
06057 return 0;
06058
06059 return (INSN_P (i3) && rtx_equal_p (PATTERN (i1), PATTERN (i3))
06060 && any_condjump_p (i2) && onlyjump_p (i2));
06061 }
06062
06063
06064
06065
06066
06067 int
06068 h8300_regs_ok_for_stm (int n, rtx operands[])
06069 {
06070 switch (n)
06071 {
06072 case 2:
06073 return ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
06074 || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
06075 || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5));
06076 case 3:
06077 return ((REGNO (operands[0]) == 0
06078 && REGNO (operands[1]) == 1
06079 && REGNO (operands[2]) == 2)
06080 || (REGNO (operands[0]) == 4
06081 && REGNO (operands[1]) == 5
06082 && REGNO (operands[2]) == 6));
06083
06084 case 4:
06085 return (REGNO (operands[0]) == 0
06086 && REGNO (operands[1]) == 1
06087 && REGNO (operands[2]) == 2
06088 && REGNO (operands[3]) == 3);
06089 }
06090
06091 abort ();
06092 }
06093
06094
06095
06096 int
06097 h8300_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
06098 unsigned int new_reg)
06099 {
06100
06101
06102
06103
06104 if (h8300_current_function_interrupt_function_p ()
06105 && !regs_ever_live[new_reg])
06106 return 0;
06107
06108 return 1;
06109 }
06110
06111
06112
06113 int
06114 h8300_legitimate_constant_p (rtx x ATTRIBUTE_UNUSED)
06115 {
06116 return 1;
06117 }
06118
06119
06120
06121 static int
06122 h8300_rtx_ok_for_base_p (rtx x, int strict)
06123 {
06124
06125 if (GET_CODE (x) == SUBREG)
06126 x = SUBREG_REG (x);
06127
06128 return (REG_P (x)
06129 && (strict
06130 ? REG_OK_FOR_BASE_STRICT_P (x)
06131 : REG_OK_FOR_BASE_NONSTRICT_P (x)));
06132 }
06133
06134
06135
06136
06137
06138 int
06139 h8300_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
06140 {
06141
06142 if (h8300_rtx_ok_for_base_p (x, strict))
06143 return 1;
06144
06145 if (CONSTANT_ADDRESS_P (x))
06146 return 1;
06147
06148 if (TARGET_H8300SX
06149 && ( GET_CODE (x) == PRE_INC
06150 || GET_CODE (x) == PRE_DEC
06151 || GET_CODE (x) == POST_INC
06152 || GET_CODE (x) == POST_DEC)
06153 && h8300_rtx_ok_for_base_p (XEXP (x, 0), strict))
06154 return 1;
06155
06156 if (GET_CODE (x) == PLUS
06157 && CONSTANT_ADDRESS_P (XEXP (x, 1))
06158 && h8300_rtx_ok_for_base_p (h8300_get_index (XEXP (x, 0),
06159 mode, 0), strict))
06160 return 1;
06161
06162 return 0;
06163 }
06164
06165
06166
06167
06168
06169
06170 int
06171 h8300_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, enum machine_mode mode)
06172 {
06173 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
06174 }
06175
06176
06177
06178 int
06179 h8300_hard_regno_mode_ok (int regno, enum machine_mode mode)
06180 {
06181 if (TARGET_H8300)
06182
06183
06184 return ((regno & 1) == 0) || (mode == HImode) || (mode == QImode);
06185 else
06186
06187
06188 return regno == MAC_REG ? mode == SImode : 1;
06189 }
06190
06191
06192 static void
06193 h8300_init_libfuncs (void)
06194 {
06195 set_optab_libfunc (smul_optab, HImode, "__mulhi3");
06196 set_optab_libfunc (sdiv_optab, HImode, "__divhi3");
06197 set_optab_libfunc (udiv_optab, HImode, "__udivhi3");
06198 set_optab_libfunc (smod_optab, HImode, "__modhi3");
06199 set_optab_libfunc (umod_optab, HImode, "__umodhi3");
06200 }
06201
06202
06203
06204 static bool
06205 h8300_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
06206 {
06207 return (TYPE_MODE (type) == BLKmode
06208 || GET_MODE_SIZE (TYPE_MODE (type)) > (TARGET_H8300 ? 4 : 8));
06209 }
06210
06211
06212 #undef TARGET_ATTRIBUTE_TABLE
06213 #define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
06214
06215 #undef TARGET_ASM_ALIGNED_HI_OP
06216 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
06217
06218 #undef TARGET_ASM_FILE_START
06219 #define TARGET_ASM_FILE_START h8300_file_start
06220 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
06221 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
06222
06223 #undef TARGET_ASM_FILE_END
06224 #define TARGET_ASM_FILE_END h8300_file_end
06225
06226 #undef TARGET_ENCODE_SECTION_INFO
06227 #define TARGET_ENCODE_SECTION_INFO h8300_encode_section_info
06228
06229 #undef TARGET_INSERT_ATTRIBUTES
06230 #define TARGET_INSERT_ATTRIBUTES h8300_insert_attributes
06231
06232 #undef TARGET_RTX_COSTS
06233 #define TARGET_RTX_COSTS h8300_rtx_costs
06234
06235 #undef TARGET_INIT_LIBFUNCS
06236 #define TARGET_INIT_LIBFUNCS h8300_init_libfuncs
06237
06238 #undef TARGET_RETURN_IN_MEMORY
06239 #define TARGET_RETURN_IN_MEMORY h8300_return_in_memory
06240
06241 #undef TARGET_MACHINE_DEPENDENT_REORG
06242 #define TARGET_MACHINE_DEPENDENT_REORG h8300_reorg
06243
06244 struct gcc_target targetm = TARGET_INITIALIZER;