00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include "config.h"
00038 #include "system.h"
00039 #include "coretypes.h"
00040 #include "tm.h"
00041 #include "rtl.h"
00042 #include "tree.h"
00043 #include "tm_p.h"
00044 #include "regs.h"
00045 #include "hard-reg-set.h"
00046 #include "real.h"
00047 #include "insn-config.h"
00048 #include "conditions.h"
00049 #include "output.h"
00050 #include "insn-attr.h"
00051 #include "flags.h"
00052 #include "recog.h"
00053 #include "expr.h"
00054 #include "libfuncs.h"
00055 #include "toplev.h"
00056 #include "basic-block.h"
00057 #include "function.h"
00058 #include "ggc.h"
00059 #include "reload.h"
00060 #include "target.h"
00061 #include "target-def.h"
00062
00063 static void emit_move_after_reload (rtx, rtx, rtx);
00064 static rtx simplify_logical (enum machine_mode, int, rtx, rtx *);
00065 static void m68hc11_emit_logical (enum machine_mode, int, rtx *);
00066 static void m68hc11_reorg (void);
00067 static int go_if_legitimate_address_internal (rtx, enum machine_mode, int);
00068 static int register_indirect_p (rtx, enum machine_mode, int);
00069 static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);
00070 static int must_parenthesize (rtx);
00071 static int m68hc11_address_cost (rtx);
00072 static int m68hc11_shift_cost (enum machine_mode, rtx, int);
00073 static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
00074 static bool m68hc11_rtx_costs (rtx, int, int, int *);
00075 static int m68hc11_auto_inc_p (rtx);
00076 static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);
00077 const struct attribute_spec m68hc11_attribute_table[];
00078
00079 void create_regs_rtx (void);
00080
00081 static void asm_print_register (FILE *, int);
00082 static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT);
00083 static void m68hc11_asm_out_constructor (rtx, int);
00084 static void m68hc11_asm_out_destructor (rtx, int);
00085 static void m68hc11_file_start (void);
00086 static void m68hc11_encode_section_info (tree, rtx, int);
00087 static const char *m68hc11_strip_name_encoding (const char* str);
00088 static unsigned int m68hc11_section_type_flags (tree, const char*, int);
00089 static int autoinc_mode (rtx);
00090 static int m68hc11_make_autoinc_notes (rtx *, void *);
00091 static void m68hc11_init_libfuncs (void);
00092 static rtx m68hc11_struct_value_rtx (tree, int);
00093 static bool m68hc11_return_in_memory (tree, tree);
00094
00095
00096 int debug_m6811 = 0;
00097
00098 extern FILE *asm_out_file;
00099
00100 rtx ix_reg;
00101 rtx iy_reg;
00102 rtx d_reg;
00103 rtx m68hc11_soft_tmp_reg;
00104 static GTY(()) rtx stack_push_word;
00105 static GTY(()) rtx stack_pop_word;
00106 static GTY(()) rtx z_reg;
00107 static GTY(()) rtx z_reg_qi;
00108 static int regs_inited = 0;
00109
00110
00111 int current_function_interrupt;
00112
00113
00114 int current_function_trap;
00115
00116
00117
00118 int current_function_far;
00119
00120
00121 HOST_WIDE_INT m68hc11_min_offset = 0;
00122
00123
00124 HOST_WIDE_INT m68hc11_max_offset = 256;
00125
00126
00127 enum reg_class m68hc11_base_reg_class = A_REGS;
00128
00129
00130 enum reg_class m68hc11_index_reg_class = NO_REGS;
00131
00132 enum reg_class m68hc11_tmp_regs_class = NO_REGS;
00133
00134
00135
00136
00137 unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];
00138 unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
00139
00140
00141
00142 int m68hc11_sp_correction;
00143
00144 #define ADDR_STRICT 0x01
00145 #define ADDR_INCDEC 0x02
00146 #define ADDR_INDEXED 0x04
00147 #define ADDR_OFFSET 0x08
00148 #define ADDR_INDIRECT 0x10
00149 #define ADDR_CONST 0x20
00150
00151 int m68hc11_addr_mode;
00152 int m68hc11_mov_addr_mode;
00153
00154
00155 rtx m68hc11_compare_op0;
00156 rtx m68hc11_compare_op1;
00157
00158
00159 const struct processor_costs *m68hc11_cost;
00160
00161
00162 static const struct processor_costs m6811_cost = {
00163
00164 COSTS_N_INSNS (2),
00165
00166 COSTS_N_INSNS (2),
00167
00168 COSTS_N_INSNS (20),
00169
00170 { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
00171 COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
00172 COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
00173
00174
00175 { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),
00176 COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
00177 COSTS_N_INSNS (4), COSTS_N_INSNS (2),
00178 COSTS_N_INSNS (2), COSTS_N_INSNS (4),
00179 COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (10),
00180 COSTS_N_INSNS (8), COSTS_N_INSNS (6), COSTS_N_INSNS (4)
00181 },
00182
00183 COSTS_N_INSNS (20),
00184
00185 COSTS_N_INSNS (20 * 4),
00186
00187 COSTS_N_INSNS (20 * 16),
00188
00189 COSTS_N_INSNS (20),
00190
00191 COSTS_N_INSNS (80),
00192
00193 COSTS_N_INSNS (100)
00194 };
00195
00196
00197 static const struct processor_costs m6812_cost = {
00198
00199 COSTS_N_INSNS (2),
00200
00201 COSTS_N_INSNS (2),
00202
00203 COSTS_N_INSNS (20),
00204
00205 { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
00206 COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
00207 COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
00208
00209
00210 { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),
00211 COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
00212 COSTS_N_INSNS (4), COSTS_N_INSNS (2),
00213 COSTS_N_INSNS (2), COSTS_N_INSNS (4), COSTS_N_INSNS (6),
00214 COSTS_N_INSNS (8), COSTS_N_INSNS (10), COSTS_N_INSNS (8),
00215 COSTS_N_INSNS (6), COSTS_N_INSNS (4)
00216 },
00217
00218 COSTS_N_INSNS (3),
00219
00220 COSTS_N_INSNS (3),
00221
00222 COSTS_N_INSNS (3 * 4),
00223
00224 COSTS_N_INSNS (12),
00225
00226 COSTS_N_INSNS (12),
00227
00228 COSTS_N_INSNS (100)
00229 };
00230
00231
00232
00233 const char *m68hc11_regparm_string;
00234 const char *m68hc11_reg_alloc_order;
00235 const char *m68hc11_soft_reg_count;
00236
00237 static int nb_soft_regs;
00238
00239
00240 #undef TARGET_ATTRIBUTE_TABLE
00241 #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
00242
00243 #undef TARGET_ASM_ALIGNED_HI_OP
00244 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00245
00246 #undef TARGET_ASM_FUNCTION_EPILOGUE
00247 #define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
00248
00249 #undef TARGET_ASM_FILE_START
00250 #define TARGET_ASM_FILE_START m68hc11_file_start
00251 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
00252 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
00253
00254 #undef TARGET_ENCODE_SECTION_INFO
00255 #define TARGET_ENCODE_SECTION_INFO m68hc11_encode_section_info
00256
00257 #undef TARGET_SECTION_TYPE_FLAGS
00258 #define TARGET_SECTION_TYPE_FLAGS m68hc11_section_type_flags
00259
00260 #undef TARGET_RTX_COSTS
00261 #define TARGET_RTX_COSTS m68hc11_rtx_costs
00262 #undef TARGET_ADDRESS_COST
00263 #define TARGET_ADDRESS_COST m68hc11_address_cost
00264
00265 #undef TARGET_MACHINE_DEPENDENT_REORG
00266 #define TARGET_MACHINE_DEPENDENT_REORG m68hc11_reorg
00267
00268 #undef TARGET_INIT_LIBFUNCS
00269 #define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs
00270
00271 #undef TARGET_STRUCT_VALUE_RTX
00272 #define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx
00273 #undef TARGET_RETURN_IN_MEMORY
00274 #define TARGET_RETURN_IN_MEMORY m68hc11_return_in_memory
00275 #undef TARGET_CALLEE_COPIES
00276 #define TARGET_CALLEE_COPIES hook_callee_copies_named
00277
00278 #undef TARGET_STRIP_NAME_ENCODING
00279 #define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encoding
00280
00281 struct gcc_target targetm = TARGET_INITIALIZER;
00282
00283 int
00284 m68hc11_override_options (void)
00285 {
00286 memset (m68hc11_reg_valid_for_index, 0,
00287 sizeof (m68hc11_reg_valid_for_index));
00288 memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base));
00289
00290
00291 if (flag_pic)
00292 {
00293 warning ("-f%s ignored for 68HC11/68HC12 (not supported)",
00294 (flag_pic > 1) ? "PIC" : "pic");
00295 flag_pic = 0;
00296 }
00297
00298
00299
00300
00301 flag_web = 0;
00302
00303
00304 if (TARGET_M6811)
00305 {
00306
00307
00308 if (TARGET_DEFAULT != MASK_M6811)
00309 target_flags &= ~TARGET_DEFAULT;
00310
00311 if (!TARGET_M6812)
00312 target_flags &= ~(TARGET_AUTO_INC_DEC | TARGET_MIN_MAX);
00313 m68hc11_cost = &m6811_cost;
00314 m68hc11_min_offset = 0;
00315 m68hc11_max_offset = 256;
00316 m68hc11_index_reg_class = NO_REGS;
00317 m68hc11_base_reg_class = A_REGS;
00318 m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;
00319 m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;
00320 m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
00321 m68hc11_sp_correction = 1;
00322 m68hc11_tmp_regs_class = D_REGS;
00323 m68hc11_addr_mode = ADDR_OFFSET;
00324 m68hc11_mov_addr_mode = 0;
00325 if (m68hc11_soft_reg_count == 0 && !TARGET_M6812)
00326 m68hc11_soft_reg_count = "4";
00327 }
00328
00329
00330 if (TARGET_M6812)
00331 {
00332 m68hc11_cost = &m6812_cost;
00333 m68hc11_min_offset = -65536;
00334 m68hc11_max_offset = 65536;
00335 m68hc11_index_reg_class = D_REGS;
00336 m68hc11_base_reg_class = A_OR_SP_REGS;
00337 m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;
00338 m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;
00339 m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
00340 m68hc11_reg_valid_for_base[HARD_SP_REGNUM] = 1;
00341 m68hc11_reg_valid_for_index[HARD_D_REGNUM] = 1;
00342 m68hc11_sp_correction = 0;
00343 m68hc11_tmp_regs_class = TMP_REGS;
00344 m68hc11_addr_mode = ADDR_INDIRECT | ADDR_OFFSET | ADDR_CONST
00345 | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
00346 m68hc11_mov_addr_mode = ADDR_OFFSET | ADDR_CONST
00347 | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
00348 target_flags &= ~MASK_M6811;
00349 target_flags |= MASK_NO_DIRECT_MODE;
00350 if (m68hc11_soft_reg_count == 0)
00351 m68hc11_soft_reg_count = "0";
00352
00353 if (TARGET_LONG_CALLS)
00354 current_function_far = 1;
00355 }
00356 return 0;
00357 }
00358
00359
00360 void
00361 m68hc11_conditional_register_usage (void)
00362 {
00363 int i;
00364 int cnt = atoi (m68hc11_soft_reg_count);
00365
00366 if (cnt < 0)
00367 cnt = 0;
00368 if (cnt > SOFT_REG_LAST - SOFT_REG_FIRST)
00369 cnt = SOFT_REG_LAST - SOFT_REG_FIRST;
00370
00371 nb_soft_regs = cnt;
00372 for (i = SOFT_REG_FIRST + cnt; i < SOFT_REG_LAST; i++)
00373 {
00374 fixed_regs[i] = 1;
00375 call_used_regs[i] = 1;
00376 }
00377
00378
00379
00380
00381 if (TARGET_M6812 && flag_omit_frame_pointer && optimize)
00382 {
00383 fixed_regs[HARD_Z_REGNUM] = 1;
00384 }
00385 }
00386
00387
00388
00389
00390
00391 void
00392 create_regs_rtx (void)
00393 {
00394
00395 ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);
00396 iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);
00397 d_reg = gen_rtx_REG (HImode, HARD_D_REGNUM);
00398 m68hc11_soft_tmp_reg = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
00399
00400 stack_push_word = gen_rtx_MEM (HImode,
00401 gen_rtx_PRE_DEC (HImode,
00402 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
00403 stack_pop_word = gen_rtx_MEM (HImode,
00404 gen_rtx_POST_INC (HImode,
00405 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
00406
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 int
00418 hard_regno_mode_ok (int regno, enum machine_mode mode)
00419 {
00420 switch (GET_MODE_SIZE (mode))
00421 {
00422 case 8:
00423 return S_REGNO_P (regno) && nb_soft_regs >= 4;
00424
00425 case 4:
00426 return X_REGNO_P (regno) || (S_REGNO_P (regno) && nb_soft_regs >= 2);
00427
00428 case 2:
00429 return G_REGNO_P (regno);
00430
00431 case 1:
00432
00433
00434
00435
00436
00437
00438 return G_REGNO_P (regno) && !SP_REGNO_P (regno);
00439
00440 default:
00441 return 0;
00442 }
00443 }
00444
00445 int
00446 m68hc11_hard_regno_rename_ok (int reg1, int reg2)
00447 {
00448
00449
00450 if (reg2 == HARD_Z_REGNUM)
00451 return 0;
00452
00453
00454 if (TARGET_M6811 && reg2 == HARD_Y_REGNUM
00455 && (D_REGNO_P (reg1) || X_REGNO_P (reg1)))
00456 return 0;
00457
00458 return 1;
00459 }
00460
00461 enum reg_class
00462 preferred_reload_class (rtx operand, enum reg_class class)
00463 {
00464 enum machine_mode mode;
00465
00466 mode = GET_MODE (operand);
00467
00468 if (debug_m6811)
00469 {
00470 printf ("Preferred reload: (class=%s): ", reg_class_names[class]);
00471 }
00472
00473 if (class == D_OR_A_OR_S_REGS && SP_REG_P (operand))
00474 return m68hc11_base_reg_class;
00475
00476 if (class >= S_REGS && (GET_CODE (operand) == MEM
00477 || GET_CODE (operand) == CONST_INT))
00478 {
00479
00480
00481
00482 switch (class)
00483 {
00484 default:
00485 case G_REGS:
00486 case D_OR_A_OR_S_REGS:
00487 class = A_OR_D_REGS;
00488 break;
00489 case A_OR_S_REGS:
00490 class = A_REGS;
00491 break;
00492 case D_OR_SP_OR_S_REGS:
00493 class = D_OR_SP_REGS;
00494 break;
00495 case D_OR_Y_OR_S_REGS:
00496 class = D_OR_Y_REGS;
00497 break;
00498 case D_OR_X_OR_S_REGS:
00499 class = D_OR_X_REGS;
00500 break;
00501 case SP_OR_S_REGS:
00502 class = SP_REGS;
00503 break;
00504 case Y_OR_S_REGS:
00505 class = Y_REGS;
00506 break;
00507 case X_OR_S_REGS:
00508 class = X_REGS;
00509 break;
00510 case D_OR_S_REGS:
00511 class = D_REGS;
00512 }
00513 }
00514 else if (class == Y_REGS && GET_CODE (operand) == MEM)
00515 {
00516 class = Y_REGS;
00517 }
00518 else if (class == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4)
00519 {
00520 class = D_OR_X_REGS;
00521 }
00522 else if (class >= S_REGS && S_REG_P (operand))
00523 {
00524 switch (class)
00525 {
00526 default:
00527 case G_REGS:
00528 case D_OR_A_OR_S_REGS:
00529 class = A_OR_D_REGS;
00530 break;
00531 case A_OR_S_REGS:
00532 class = A_REGS;
00533 break;
00534 case D_OR_SP_OR_S_REGS:
00535 class = D_OR_SP_REGS;
00536 break;
00537 case D_OR_Y_OR_S_REGS:
00538 class = D_OR_Y_REGS;
00539 break;
00540 case D_OR_X_OR_S_REGS:
00541 class = D_OR_X_REGS;
00542 break;
00543 case SP_OR_S_REGS:
00544 class = SP_REGS;
00545 break;
00546 case Y_OR_S_REGS:
00547 class = Y_REGS;
00548 break;
00549 case X_OR_S_REGS:
00550 class = X_REGS;
00551 break;
00552 case D_OR_S_REGS:
00553 class = D_REGS;
00554 }
00555 }
00556 else if (class >= S_REGS)
00557 {
00558 if (debug_m6811)
00559 {
00560 printf ("Class = %s for: ", reg_class_names[class]);
00561 fflush (stdout);
00562 debug_rtx (operand);
00563 }
00564 }
00565
00566 if (debug_m6811)
00567 {
00568 printf (" => class=%s\n", reg_class_names[class]);
00569 fflush (stdout);
00570 debug_rtx (operand);
00571 }
00572
00573 return class;
00574 }
00575
00576
00577
00578
00579 static int
00580 register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode)
00581 {
00582 rtx base, offset;
00583
00584 switch (GET_CODE (operand))
00585 {
00586 case MEM:
00587 if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
00588 return register_indirect_p (XEXP (operand, 0), mode,
00589 addr_mode & (ADDR_STRICT | ADDR_OFFSET));
00590 return 0;
00591
00592 case POST_INC:
00593 case PRE_INC:
00594 case POST_DEC:
00595 case PRE_DEC:
00596 if (addr_mode & ADDR_INCDEC)
00597 return register_indirect_p (XEXP (operand, 0), mode,
00598 addr_mode & ADDR_STRICT);
00599 return 0;
00600
00601 case PLUS:
00602 base = XEXP (operand, 0);
00603 if (GET_CODE (base) == MEM)
00604 return 0;
00605
00606 offset = XEXP (operand, 1);
00607 if (GET_CODE (offset) == MEM)
00608 return 0;
00609
00610
00611 if (GET_CODE (base) == REG && GET_CODE (offset) == REG)
00612 {
00613 if (!(addr_mode & ADDR_INDEXED))
00614 return 0;
00615
00616 addr_mode &= ADDR_STRICT;
00617 if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode)
00618 && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode))
00619 return 1;
00620
00621 if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode)
00622 && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode))
00623 return 1;
00624
00625 return 0;
00626 }
00627
00628 if (!(addr_mode & ADDR_OFFSET))
00629 return 0;
00630
00631 if (GET_CODE (base) == REG)
00632 {
00633 if (!VALID_CONSTANT_OFFSET_P (offset, mode))
00634 return 0;
00635
00636 if (!(addr_mode & ADDR_STRICT))
00637 return 1;
00638
00639 return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1);
00640 }
00641
00642 if (GET_CODE (offset) == REG)
00643 {
00644 if (!VALID_CONSTANT_OFFSET_P (base, mode))
00645 return 0;
00646
00647 if (!(addr_mode & ADDR_STRICT))
00648 return 1;
00649
00650 return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1);
00651 }
00652 return 0;
00653
00654 case REG:
00655 return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT);
00656
00657 case CONST_INT:
00658 if (addr_mode & ADDR_CONST)
00659 return VALID_CONSTANT_OFFSET_P (operand, mode);
00660 return 0;
00661
00662 default:
00663 return 0;
00664 }
00665 }
00666
00667
00668
00669 int
00670 m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
00671 {
00672 rtx base, offset;
00673 int addr_mode;
00674
00675 if (GET_CODE (operand) == REG && reload_in_progress
00676 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
00677 && reg_equiv_memory_loc[REGNO (operand)])
00678 {
00679 operand = reg_equiv_memory_loc[REGNO (operand)];
00680 operand = eliminate_regs (operand, 0, NULL_RTX);
00681 }
00682
00683 if (GET_CODE (operand) != MEM)
00684 return 0;
00685
00686 operand = XEXP (operand, 0);
00687 if (CONSTANT_ADDRESS_P (operand))
00688 return 1;
00689
00690 if (PUSH_POP_ADDRESS_P (operand))
00691 return 1;
00692
00693 addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
00694 if (!register_indirect_p (operand, mode, addr_mode))
00695 return 0;
00696
00697 if (TARGET_M6812 && GET_CODE (operand) == PLUS
00698 && (reload_completed | reload_in_progress))
00699 {
00700 base = XEXP (operand, 0);
00701 offset = XEXP (operand, 1);
00702
00703
00704
00705 if (GET_CODE (base) != CONST_INT && GET_CODE (offset) != CONST_INT)
00706 return 0;
00707
00708 if (GET_CODE (base) == CONST_INT)
00709 offset = base;
00710
00711 switch (GET_MODE_SIZE (mode))
00712 {
00713 case 8:
00714 if (INTVAL (offset) < -16 + 6 || INTVAL (offset) > 15 - 6)
00715 return 0;
00716 break;
00717
00718 case 4:
00719 if (INTVAL (offset) < -16 + 2 || INTVAL (offset) > 15 - 2)
00720 return 0;
00721 break;
00722
00723 default:
00724 if (INTVAL (offset) < -16 || INTVAL (offset) > 15)
00725 return 0;
00726 break;
00727 }
00728 }
00729 return 1;
00730 }
00731
00732 int
00733 m68hc11_register_indirect_p (rtx operand, enum machine_mode mode)
00734 {
00735 int addr_mode;
00736
00737 if (GET_CODE (operand) == REG && reload_in_progress
00738 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
00739 && reg_equiv_memory_loc[REGNO (operand)])
00740 {
00741 operand = reg_equiv_memory_loc[REGNO (operand)];
00742 operand = eliminate_regs (operand, 0, NULL_RTX);
00743 }
00744 if (GET_CODE (operand) != MEM)
00745 return 0;
00746
00747 operand = XEXP (operand, 0);
00748 addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
00749 return register_indirect_p (operand, mode, addr_mode);
00750 }
00751
00752 static int
00753 go_if_legitimate_address_internal (rtx operand, enum machine_mode mode,
00754 int strict)
00755 {
00756 int addr_mode;
00757
00758 if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812)
00759 {
00760
00761
00762 if (GET_MODE_SIZE (mode) == 8)
00763 return 0;
00764
00765 return 1;
00766 }
00767 addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
00768 if (register_indirect_p (operand, mode, addr_mode))
00769 {
00770 return 1;
00771 }
00772 if (PUSH_POP_ADDRESS_P (operand))
00773 {
00774 return 1;
00775 }
00776 if (symbolic_memory_operand (operand, mode))
00777 {
00778 return 1;
00779 }
00780 return 0;
00781 }
00782
00783 int
00784 m68hc11_go_if_legitimate_address (rtx operand, enum machine_mode mode,
00785 int strict)
00786 {
00787 int result;
00788
00789 if (debug_m6811)
00790 {
00791 printf ("Checking: ");
00792 fflush (stdout);
00793 debug_rtx (operand);
00794 }
00795
00796 result = go_if_legitimate_address_internal (operand, mode, strict);
00797
00798 if (debug_m6811)
00799 {
00800 printf (" -> %s\n", result == 0 ? "NO" : "YES");
00801 }
00802
00803 if (result == 0)
00804 {
00805 if (debug_m6811)
00806 {
00807 printf ("go_if_legitimate%s, ret 0: %d:",
00808 (strict ? "_strict" : ""), mode);
00809 fflush (stdout);
00810 debug_rtx (operand);
00811 }
00812 }
00813 return result;
00814 }
00815
00816 int
00817 m68hc11_legitimize_address (rtx *operand ATTRIBUTE_UNUSED,
00818 rtx old_operand ATTRIBUTE_UNUSED,
00819 enum machine_mode mode ATTRIBUTE_UNUSED)
00820 {
00821 return 0;
00822 }
00823
00824
00825 int
00826 m68hc11_reload_operands (rtx operands[])
00827 {
00828 enum machine_mode mode;
00829
00830 if (regs_inited == 0)
00831 create_regs_rtx ();
00832
00833 mode = GET_MODE (operands[1]);
00834
00835
00836 if (A_REG_P (operands[0]) && memory_reload_operand (operands[1], mode))
00837 {
00838 rtx big_offset = XEXP (XEXP (operands[1], 0), 1);
00839 rtx base = XEXP (XEXP (operands[1], 0), 0);
00840
00841 if (GET_CODE (base) != REG)
00842 {
00843 rtx tmp = base;
00844 base = big_offset;
00845 big_offset = tmp;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 if (!VALID_CONSTANT_OFFSET_P (big_offset, mode))
00869 {
00870 int vh, vl;
00871 rtx reg = operands[0];
00872 rtx offset;
00873 int val = INTVAL (big_offset);
00874
00875
00876
00877
00878 if (!rtx_equal_p (base, operands[0]))
00879 {
00880 emit_move_insn (reg, base);
00881 }
00882
00883 if (val > 0)
00884 {
00885 vh = val >> 8;
00886 vl = val & 0x0FF;
00887 }
00888 else
00889 {
00890 vh = (val >> 8) & 0x0FF;
00891 vl = val & 0x0FF;
00892 }
00893
00894
00895
00896 offset = GEN_INT (vl);
00897 if (!VALID_CONSTANT_OFFSET_P (offset, mode))
00898 {
00899 emit_insn (gen_rtx_SET (VOIDmode, reg,
00900 gen_rtx_PLUS (HImode, reg, big_offset)));
00901 offset = const0_rtx;
00902 }
00903 else
00904 {
00905 emit_insn (gen_rtx_SET (VOIDmode, reg,
00906 gen_rtx_PLUS (HImode, reg,
00907 GEN_INT (vh << 8))));
00908 }
00909 emit_move_insn (operands[0],
00910 gen_rtx_MEM (GET_MODE (operands[1]),
00911 gen_rtx_PLUS (Pmode, reg, offset)));
00912 return 1;
00913 }
00914 }
00915
00916
00917 return 0;
00918 }
00919
00920 void
00921 m68hc11_emit_libcall (const char *name, enum rtx_code code,
00922 enum machine_mode dmode, enum machine_mode smode,
00923 int noperands, rtx *operands)
00924 {
00925 rtx ret;
00926 rtx insns;
00927 rtx libcall;
00928 rtx equiv;
00929
00930 start_sequence ();
00931 libcall = gen_rtx_SYMBOL_REF (Pmode, name);
00932 switch (noperands)
00933 {
00934 case 2:
00935 ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
00936 dmode, 1, operands[1], smode);
00937 equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
00938 break;
00939
00940 case 3:
00941 ret = emit_library_call_value (libcall, NULL_RTX,
00942 LCT_CONST, dmode, 2,
00943 operands[1], smode, operands[2],
00944 smode);
00945 equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
00946 break;
00947
00948 default:
00949 abort ();
00950 }
00951
00952 insns = get_insns ();
00953 end_sequence ();
00954 emit_libcall_block (insns, operands[0], ret, equiv);
00955 }
00956
00957
00958
00959
00960 static int
00961 m68hc11_auto_inc_p (rtx x)
00962 {
00963 return GET_CODE (x) == PRE_DEC
00964 || GET_CODE (x) == POST_INC
00965 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_INC;
00966 }
00967
00968
00969
00970
00971 int
00972 memory_reload_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
00973 {
00974 return GET_CODE (operand) == MEM
00975 && GET_CODE (XEXP (operand, 0)) == PLUS
00976 && ((GET_CODE (XEXP (XEXP (operand, 0), 0)) == REG
00977 && GET_CODE (XEXP (XEXP (operand, 0), 1)) == CONST_INT)
00978 || (GET_CODE (XEXP (XEXP (operand, 0), 1)) == REG
00979 && GET_CODE (XEXP (XEXP (operand, 0), 0)) == CONST_INT));
00980 }
00981
00982 int
00983 tst_operand (rtx operand, enum machine_mode mode)
00984 {
00985 if (GET_CODE (operand) == MEM && reload_completed == 0)
00986 {
00987 rtx addr = XEXP (operand, 0);
00988 if (m68hc11_auto_inc_p (addr))
00989 return 0;
00990 }
00991 return nonimmediate_operand (operand, mode);
00992 }
00993
00994 int
00995 cmp_operand (rtx operand, enum machine_mode mode)
00996 {
00997 if (GET_CODE (operand) == MEM)
00998 {
00999 rtx addr = XEXP (operand, 0);
01000 if (m68hc11_auto_inc_p (addr))
01001 return 0;
01002 }
01003 return general_operand (operand, mode);
01004 }
01005
01006 int
01007 non_push_operand (rtx operand, enum machine_mode mode)
01008 {
01009 if (general_operand (operand, mode) == 0)
01010 return 0;
01011
01012 if (push_operand (operand, mode) == 1)
01013 return 0;
01014 return 1;
01015 }
01016
01017 int
01018 splitable_operand (rtx operand, enum machine_mode mode)
01019 {
01020 if (general_operand (operand, mode) == 0)
01021 return 0;
01022
01023 if (push_operand (operand, mode) == 1)
01024 return 0;
01025
01026
01027
01028
01029 if (mode != QImode && GET_CODE (operand) == MEM
01030 && GET_CODE (XEXP (operand, 0)) == MEM)
01031 return 0;
01032 return 1;
01033 }
01034
01035 int
01036 reg_or_some_mem_operand (rtx operand, enum machine_mode mode)
01037 {
01038 if (GET_CODE (operand) == MEM)
01039 {
01040 rtx op = XEXP (operand, 0);
01041 int addr_mode;
01042
01043 if (symbolic_memory_operand (op, mode))
01044 return 1;
01045
01046 if (IS_STACK_PUSH (operand))
01047 return 1;
01048
01049 if (GET_CODE (operand) == REG && reload_in_progress
01050 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
01051 && reg_equiv_memory_loc[REGNO (operand)])
01052 {
01053 operand = reg_equiv_memory_loc[REGNO (operand)];
01054 operand = eliminate_regs (operand, 0, NULL_RTX);
01055 }
01056 if (GET_CODE (operand) != MEM)
01057 return 0;
01058
01059 operand = XEXP (operand, 0);
01060 addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
01061 addr_mode &= ~ADDR_INDIRECT;
01062 return register_indirect_p (operand, mode, addr_mode);
01063 }
01064
01065 return register_operand (operand, mode);
01066 }
01067
01068 int
01069 m68hc11_symbolic_p (rtx operand, enum machine_mode mode)
01070 {
01071 if (GET_CODE (operand) == MEM)
01072 {
01073 rtx op = XEXP (operand, 0);
01074
01075 if (symbolic_memory_operand (op, mode))
01076 return 1;
01077 }
01078 return 0;
01079 }
01080
01081 int
01082 m68hc11_indirect_p (rtx operand, enum machine_mode mode)
01083 {
01084 if (GET_CODE (operand) == MEM && GET_MODE (operand) == mode)
01085 {
01086 rtx op = XEXP (operand, 0);
01087 int addr_mode;
01088
01089 if (m68hc11_page0_symbol_p (op))
01090 return 1;
01091
01092 if (symbolic_memory_operand (op, mode))
01093 return TARGET_M6812;
01094
01095 if (reload_in_progress)
01096 return 1;
01097
01098 operand = XEXP (operand, 0);
01099 addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
01100 return register_indirect_p (operand, mode, addr_mode);
01101 }
01102 return 0;
01103 }
01104
01105 int
01106 stack_register_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
01107 {
01108 return SP_REG_P (operand);
01109 }
01110
01111 int
01112 d_register_operand (rtx operand, enum machine_mode mode)
01113 {
01114 if (GET_MODE (operand) != mode && mode != VOIDmode)
01115 return 0;
01116
01117 if (GET_CODE (operand) == SUBREG)
01118 operand = XEXP (operand, 0);
01119
01120 return GET_CODE (operand) == REG
01121 && (REGNO (operand) >= FIRST_PSEUDO_REGISTER
01122 || REGNO (operand) == HARD_D_REGNUM
01123 || (mode == QImode && REGNO (operand) == HARD_B_REGNUM));
01124 }
01125
01126 int
01127 hard_addr_reg_operand (rtx operand, enum machine_mode mode)
01128 {
01129 if (GET_MODE (operand) != mode && mode != VOIDmode)
01130 return 0;
01131
01132 if (GET_CODE (operand) == SUBREG)
01133 operand = XEXP (operand, 0);
01134
01135 return GET_CODE (operand) == REG
01136 && (REGNO (operand) == HARD_X_REGNUM
01137 || REGNO (operand) == HARD_Y_REGNUM
01138 || REGNO (operand) == HARD_Z_REGNUM);
01139 }
01140
01141 int
01142 hard_reg_operand (rtx operand, enum machine_mode mode)
01143 {
01144 if (GET_MODE (operand) != mode && mode != VOIDmode)
01145 return 0;
01146
01147 if (GET_CODE (operand) == SUBREG)
01148 operand = XEXP (operand, 0);
01149
01150 return GET_CODE (operand) == REG
01151 && (REGNO (operand) >= FIRST_PSEUDO_REGISTER
01152 || H_REGNO_P (REGNO (operand)));
01153 }
01154
01155 int
01156 memory_indexed_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
01157 {
01158 if (GET_CODE (operand) != MEM)
01159 return 0;
01160
01161 operand = XEXP (operand, 0);
01162 if (GET_CODE (operand) == PLUS)
01163 {
01164 if (GET_CODE (XEXP (operand, 0)) == REG)
01165 operand = XEXP (operand, 0);
01166 else if (GET_CODE (XEXP (operand, 1)) == REG)
01167 operand = XEXP (operand, 1);
01168 }
01169 return GET_CODE (operand) == REG
01170 && (REGNO (operand) >= FIRST_PSEUDO_REGISTER
01171 || A_REGNO_P (REGNO (operand)));
01172 }
01173
01174 int
01175 push_pop_operand_p (rtx operand)
01176 {
01177 if (GET_CODE (operand) != MEM)
01178 {
01179 return 0;
01180 }
01181 operand = XEXP (operand, 0);
01182 return PUSH_POP_ADDRESS_P (operand);
01183 }
01184
01185
01186
01187
01188 int
01189 symbolic_memory_operand (rtx op, enum machine_mode mode)
01190 {
01191 switch (GET_CODE (op))
01192 {
01193 case SYMBOL_REF:
01194 case LABEL_REF:
01195 return 1;
01196
01197 case CONST:
01198 op = XEXP (op, 0);
01199 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
01200 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
01201 && GET_CODE (XEXP (op, 1)) == CONST_INT);
01202
01203
01204 case CONST_DOUBLE:
01205 return GET_MODE (op) == mode;
01206
01207 case PLUS:
01208 return symbolic_memory_operand (XEXP (op, 0), mode)
01209 && symbolic_memory_operand (XEXP (op, 1), mode);
01210
01211 default:
01212 return 0;
01213 }
01214 }
01215
01216 int
01217 m68hc11_eq_compare_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01218 {
01219 return GET_CODE (op) == EQ || GET_CODE (op) == NE;
01220 }
01221
01222 int
01223 m68hc11_logical_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01224 {
01225 return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR;
01226 }
01227
01228 int
01229 m68hc11_arith_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01230 {
01231 return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR
01232 || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS
01233 || GET_CODE (op) == ASHIFT || GET_CODE (op) == ASHIFTRT
01234 || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ROTATE
01235 || GET_CODE (op) == ROTATERT;
01236 }
01237
01238 int
01239 m68hc11_non_shift_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01240 {
01241 return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR
01242 || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS;
01243 }
01244
01245
01246 int
01247 m68hc11_shift_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01248 {
01249 return GET_CODE (op) == ROTATE || GET_CODE (op) == ROTATERT
01250 || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFT
01251 || GET_CODE (op) == ASHIFTRT;
01252 }
01253
01254 int
01255 m68hc11_unary_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01256 {
01257 return GET_CODE (op) == NEG || GET_CODE (op) == NOT
01258 || GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
01259 }
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 void
01271 m68hc11_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
01272 {
01273 const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];
01274
01275
01276 if (*static_chain_reg == '*')
01277 static_chain_reg++;
01278 if (TARGET_M6811)
01279 {
01280 emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x18ce));
01281 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
01282 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),
01283 GEN_INT (0x18df));
01284 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),
01285 gen_rtx_CONST (QImode,
01286 gen_rtx_SYMBOL_REF (Pmode,
01287 static_chain_reg)));
01288 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 7)),
01289 GEN_INT (0x7e));
01290 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 8)), fnaddr);
01291 }
01292 else
01293 {
01294 emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x1803));
01295 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
01296 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),
01297 gen_rtx_CONST (HImode,
01298 gen_rtx_SYMBOL_REF (Pmode,
01299 static_chain_reg)));
01300 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),
01301 GEN_INT (0x06));
01302 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 7)), fnaddr);
01303 }
01304 }
01305
01306
01307
01308
01309
01310 static tree
01311 m68hc11_handle_page0_attribute (tree *node, tree name,
01312 tree args ATTRIBUTE_UNUSED,
01313 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
01314 {
01315 tree decl = *node;
01316
01317 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
01318 {
01319 DECL_SECTION_NAME (decl) = build_string (6, ".page0");
01320 }
01321 else
01322 {
01323 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
01324 *no_add_attrs = true;
01325 }
01326
01327 return NULL_TREE;
01328 }
01329
01330 const struct attribute_spec m68hc11_attribute_table[] =
01331 {
01332
01333 { "interrupt", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
01334 { "trap", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
01335 { "far", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
01336 { "near", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
01337 { "page0", 0, 0, false, false, false, m68hc11_handle_page0_attribute },
01338 { NULL, 0, 0, false, false, false, NULL }
01339 };
01340
01341
01342
01343
01344 static rtx trap_handler_symbol = 0;
01345
01346
01347
01348 static tree
01349 m68hc11_handle_fntype_attribute (tree *node, tree name,
01350 tree args ATTRIBUTE_UNUSED,
01351 int flags ATTRIBUTE_UNUSED,
01352 bool *no_add_attrs)
01353 {
01354 if (TREE_CODE (*node) != FUNCTION_TYPE
01355 && TREE_CODE (*node) != METHOD_TYPE
01356 && TREE_CODE (*node) != FIELD_DECL
01357 && TREE_CODE (*node) != TYPE_DECL)
01358 {
01359 warning ("%qs attribute only applies to functions",
01360 IDENTIFIER_POINTER (name));
01361 *no_add_attrs = true;
01362 }
01363
01364 return NULL_TREE;
01365 }
01366
01367
01368 static const char *
01369 m68hc11_strip_name_encoding (const char *str)
01370 {
01371 return str + (*str == '*' || *str == '@' || *str == '&');
01372 }
01373
01374 static void
01375 m68hc11_encode_label (tree decl)
01376 {
01377 const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
01378 int len = strlen (str);
01379 char *newstr = alloca (len + 2);
01380
01381 newstr[0] = '@';
01382 strcpy (&newstr[1], str);
01383
01384 XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 1);
01385 }
01386
01387
01388 int
01389 m68hc11_page0_symbol_p (rtx x)
01390 {
01391 switch (GET_CODE (x))
01392 {
01393 case SYMBOL_REF:
01394 return XSTR (x, 0) != 0 && XSTR (x, 0)[0] == '@';
01395
01396 case CONST:
01397 return m68hc11_page0_symbol_p (XEXP (x, 0));
01398
01399 case PLUS:
01400 if (!m68hc11_page0_symbol_p (XEXP (x, 0)))
01401 return 0;
01402
01403 return GET_CODE (XEXP (x, 1)) == CONST_INT
01404 && INTVAL (XEXP (x, 1)) < 256
01405 && INTVAL (XEXP (x, 1)) >= 0;
01406
01407 default:
01408 return 0;
01409 }
01410 }
01411
01412
01413
01414
01415
01416 static void
01417 m68hc11_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
01418 {
01419 tree func_attr;
01420 int trap_handler;
01421 int is_far = 0;
01422
01423 if (TREE_CODE (decl) == VAR_DECL)
01424 {
01425 if (lookup_attribute ("page0", DECL_ATTRIBUTES (decl)) != 0)
01426 m68hc11_encode_label (decl);
01427 return;
01428 }
01429
01430 if (TREE_CODE (decl) != FUNCTION_DECL)
01431 return;
01432
01433 func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
01434
01435
01436 if (lookup_attribute ("far", func_attr) != NULL_TREE)
01437 is_far = 1;
01438 else if (lookup_attribute ("near", func_attr) == NULL_TREE)
01439 is_far = TARGET_LONG_CALLS != 0;
01440
01441 trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
01442 if (trap_handler && is_far)
01443 {
01444 warning ("%<trap%> and %<far%> attributes are not compatible, ignoring %<far%>");
01445 trap_handler = 0;
01446 }
01447 if (trap_handler)
01448 {
01449 if (trap_handler_symbol != 0)
01450 warning ("%<trap%> attribute is already used");
01451 else
01452 trap_handler_symbol = XEXP (rtl, 0);
01453 }
01454 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = is_far;
01455 }
01456
01457 static unsigned int
01458 m68hc11_section_type_flags (tree decl, const char *name, int reloc)
01459 {
01460 unsigned int flags = default_section_type_flags (decl, name, reloc);
01461
01462 if (strncmp (name, ".eeprom", 7) == 0)
01463 {
01464 flags |= SECTION_WRITE | SECTION_CODE | SECTION_OVERRIDE;
01465 }
01466
01467 return flags;
01468 }
01469
01470 int
01471 m68hc11_is_far_symbol (rtx sym)
01472 {
01473 if (GET_CODE (sym) == MEM)
01474 sym = XEXP (sym, 0);
01475
01476 return SYMBOL_REF_FLAG (sym);
01477 }
01478
01479 int
01480 m68hc11_is_trap_symbol (rtx sym)
01481 {
01482 if (GET_CODE (sym) == MEM)
01483 sym = XEXP (sym, 0);
01484
01485 return trap_handler_symbol != 0 && rtx_equal_p (trap_handler_symbol, sym);
01486 }
01487
01488
01489
01490
01491
01492
01493 int
01494 m68hc11_initial_elimination_offset (int from, int to)
01495 {
01496 int trap_handler;
01497 tree func_attr;
01498 int size;
01499 int regno;
01500
01501
01502
01503 func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
01504 current_function_interrupt = lookup_attribute ("interrupt",
01505 func_attr) != NULL_TREE;
01506 trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
01507
01508 if (lookup_attribute ("far", func_attr) != 0)
01509 current_function_far = 1;
01510 else if (lookup_attribute ("near", func_attr) != 0)
01511 current_function_far = 0;
01512 else
01513 current_function_far = (TARGET_LONG_CALLS != 0
01514 && !current_function_interrupt
01515 && !trap_handler);
01516
01517 if (trap_handler && from == ARG_POINTER_REGNUM)
01518 size = 7;
01519
01520
01521
01522 else if (current_function_far && from == ARG_POINTER_REGNUM)
01523 size = 1;
01524 else
01525 size = 0;
01526
01527 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
01528 {
01529
01530
01531 return get_frame_size () + 2 + m68hc11_sp_correction + size;
01532 }
01533
01534 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
01535 {
01536 return m68hc11_sp_correction;
01537 }
01538
01539
01540 for (regno = SOFT_REG_FIRST; regno < SOFT_REG_LAST; regno++)
01541 {
01542 if (regs_ever_live[regno] && !call_used_regs[regno])
01543 {
01544 size += 2;
01545 }
01546 }
01547
01548 if (from == ARG_POINTER_REGNUM && to == HARD_SP_REGNUM)
01549 {
01550 return get_frame_size () + size;
01551 }
01552
01553 if (from == FRAME_POINTER_REGNUM && to == HARD_SP_REGNUM)
01554 {
01555 return size;
01556 }
01557 return 0;
01558 }
01559
01560
01561
01562
01563
01564 void
01565 m68hc11_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
01566 {
01567 tree ret_type;
01568
01569 z_replacement_completed = 0;
01570 cum->words = 0;
01571 cum->nregs = 0;
01572
01573
01574
01575
01576
01577
01578
01579 if (fntype == 0)
01580 {
01581 const char *name;
01582 size_t len;
01583
01584 if (libname == 0 || GET_CODE (libname) != SYMBOL_REF)
01585 return;
01586
01587
01588
01589 name = XSTR (libname, 0);
01590 len = strlen (name);
01591 if (len > 3
01592 && ((name[len - 2] == 'd'
01593 && (name[len - 1] == 'f' || name[len - 1] == 'i'))
01594 || (name[len - 3] == 'd'
01595 && (name[len - 2] == 'i' || name[len - 2] == 'f'))))
01596 {
01597
01598 cum->words = 1;
01599 cum->nregs = 1;
01600 }
01601 return;
01602 }
01603
01604 ret_type = TREE_TYPE (fntype);
01605
01606 if (ret_type && aggregate_value_p (ret_type, fntype))
01607 {
01608 cum->words = 1;
01609 cum->nregs = 1;
01610 }
01611 }
01612
01613
01614
01615
01616
01617 void
01618 m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
01619 tree type, int named ATTRIBUTE_UNUSED)
01620 {
01621 if (mode != BLKmode)
01622 {
01623 if (cum->words == 0 && GET_MODE_SIZE (mode) == 4)
01624 {
01625 cum->nregs = 2;
01626 cum->words = GET_MODE_SIZE (mode);
01627 }
01628 else
01629 {
01630 cum->words += GET_MODE_SIZE (mode);
01631 if (cum->words <= HARD_REG_SIZE)
01632 cum->nregs = 1;
01633 }
01634 }
01635 else
01636 {
01637 cum->words += int_size_in_bytes (type);
01638 }
01639 return;
01640 }
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 struct rtx_def *
01656 m68hc11_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
01657 tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
01658 {
01659 if (cum->words != 0)
01660 {
01661 return NULL_RTX;
01662 }
01663
01664 if (mode != BLKmode)
01665 {
01666 if (GET_MODE_SIZE (mode) == 2 * HARD_REG_SIZE)
01667 return gen_rtx_REG (mode, HARD_X_REGNUM);
01668
01669 if (GET_MODE_SIZE (mode) > HARD_REG_SIZE)
01670 {
01671 return NULL_RTX;
01672 }
01673 return gen_rtx_REG (mode, HARD_D_REGNUM);
01674 }
01675 return NULL_RTX;
01676 }
01677
01678
01679
01680
01681
01682
01683
01684 int
01685 m68hc11_function_arg_padding (enum machine_mode mode, tree type)
01686 {
01687 if (type != 0 && AGGREGATE_TYPE_P (type))
01688 return upward;
01689
01690
01691 return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
01692 }
01693
01694
01695
01696
01697
01698
01699 static void
01700 emit_move_after_reload (rtx to, rtx from, rtx scratch)
01701 {
01702 rtx insn;
01703
01704 if (TARGET_M6812 || H_REG_P (to) || H_REG_P (from))
01705 {
01706 insn = emit_move_insn (to, from);
01707 }
01708 else
01709 {
01710 emit_move_insn (scratch, from);
01711 insn = emit_move_insn (to, scratch);
01712 }
01713
01714
01715
01716 if (IS_STACK_PUSH (to))
01717 {
01718 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
01719 XEXP (XEXP (to, 0), 0),
01720 REG_NOTES (insn));
01721 }
01722 else if (IS_STACK_POP (from))
01723 {
01724 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
01725 XEXP (XEXP (from, 0), 0),
01726 REG_NOTES (insn));
01727 }
01728
01729
01730
01731
01732
01733 else if (TARGET_M6811 && SP_REG_P (from))
01734 {
01735 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
01736 from,
01737 REG_NOTES (insn));
01738 }
01739 }
01740
01741 int
01742 m68hc11_total_frame_size (void)
01743 {
01744 int size;
01745 int regno;
01746
01747 size = get_frame_size ();
01748 if (current_function_interrupt)
01749 {
01750 size += 3 * HARD_REG_SIZE;
01751 }
01752 if (frame_pointer_needed)
01753 size += HARD_REG_SIZE;
01754
01755 for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
01756 if (regs_ever_live[regno] && !call_used_regs[regno])
01757 size += HARD_REG_SIZE;
01758
01759 return size;
01760 }
01761
01762 static void
01763 m68hc11_output_function_epilogue (FILE *out ATTRIBUTE_UNUSED,
01764 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
01765 {
01766
01767
01768 z_replacement_completed = 0;
01769 }
01770
01771 void
01772 expand_prologue (void)
01773 {
01774 tree func_attr;
01775 int size;
01776 int regno;
01777 rtx scratch;
01778
01779 if (reload_completed != 1)
01780 abort ();
01781
01782 size = get_frame_size ();
01783
01784 create_regs_rtx ();
01785
01786
01787 func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
01788 current_function_interrupt = lookup_attribute ("interrupt",
01789 func_attr) != NULL_TREE;
01790 current_function_trap = lookup_attribute ("trap", func_attr) != NULL_TREE;
01791 if (lookup_attribute ("far", func_attr) != NULL_TREE)
01792 current_function_far = 1;
01793 else if (lookup_attribute ("near", func_attr) != NULL_TREE)
01794 current_function_far = 0;
01795 else
01796 current_function_far = (TARGET_LONG_CALLS != 0
01797 && !current_function_interrupt
01798 && !current_function_trap);
01799
01800
01801
01802
01803
01804 if (current_function_args_info.nregs == 2)
01805 scratch = iy_reg;
01806 else
01807 scratch = ix_reg;
01808
01809
01810 if (frame_pointer_needed)
01811 emit_move_after_reload (stack_push_word, hard_frame_pointer_rtx, scratch);
01812
01813
01814
01815
01816
01817 if (current_function_interrupt)
01818 {
01819 emit_move_after_reload (stack_push_word, m68hc11_soft_tmp_reg, scratch);
01820 emit_move_after_reload (stack_push_word,
01821 gen_rtx_REG (HImode, SOFT_Z_REGNUM), scratch);
01822 emit_move_after_reload (stack_push_word,
01823 gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),
01824 scratch);
01825 }
01826
01827
01828 if (TARGET_M6812 && (size > 4 || size == 3))
01829 {
01830 emit_insn (gen_addhi3 (stack_pointer_rtx,
01831 stack_pointer_rtx, GEN_INT (-size)));
01832 }
01833 else if ((!optimize_size && size > 8) || (optimize_size && size > 10))
01834 {
01835 rtx insn;
01836
01837 insn = gen_rtx_PARALLEL
01838 (VOIDmode,
01839 gen_rtvec (2,
01840 gen_rtx_SET (VOIDmode,
01841 stack_pointer_rtx,
01842 gen_rtx_PLUS (HImode,
01843 stack_pointer_rtx,
01844 GEN_INT (-size))),
01845 gen_rtx_CLOBBER (VOIDmode, scratch)));
01846 emit_insn (insn);
01847 }
01848 else
01849 {
01850 int i;
01851
01852
01853 for (i = 2; i <= size; i += 2)
01854 emit_move_after_reload (stack_push_word, ix_reg, 0);
01855
01856 if (size & 1)
01857 emit_insn (gen_addhi3 (stack_pointer_rtx,
01858 stack_pointer_rtx, constm1_rtx));
01859 }
01860
01861
01862 if (frame_pointer_needed)
01863 emit_move_after_reload (hard_frame_pointer_rtx,
01864 stack_pointer_rtx, scratch);
01865
01866
01867 for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
01868 {
01869 if (regs_ever_live[regno] && !call_used_regs[regno])
01870 {
01871 emit_move_after_reload (stack_push_word,
01872 gen_rtx_REG (HImode, regno), scratch);
01873 }
01874 }
01875 }
01876
01877 void
01878 expand_epilogue (void)
01879 {
01880 int size;
01881 register int regno;
01882 int return_size;
01883 rtx scratch;
01884
01885 if (reload_completed != 1)
01886 abort ();
01887
01888 size = get_frame_size ();
01889
01890
01891
01892
01893 if (current_function_return_rtx == 0)
01894 return_size = 0;
01895 else if (GET_CODE (current_function_return_rtx) == MEM)
01896 return_size = HARD_REG_SIZE;
01897 else
01898 return_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
01899
01900 if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE)
01901 scratch = iy_reg;
01902 else
01903 scratch = ix_reg;
01904
01905
01906 for (regno = SOFT_REG_LAST; regno >= SOFT_REG_FIRST; regno--)
01907 {
01908 if (regs_ever_live[regno] && !call_used_regs[regno])
01909 {
01910 emit_move_after_reload (gen_rtx_REG (HImode, regno),
01911 stack_pop_word, scratch);
01912 }
01913 }
01914
01915
01916 if (TARGET_M6812 && (size > 4 || size == 3))
01917 {
01918 emit_insn (gen_addhi3 (stack_pointer_rtx,
01919 stack_pointer_rtx, GEN_INT (size)));
01920 }
01921 else if ((!optimize_size && size > 8) || (optimize_size && size > 10))
01922 {
01923 rtx insn;
01924
01925 insn = gen_rtx_PARALLEL
01926 (VOIDmode,
01927 gen_rtvec (2,
01928 gen_rtx_SET (VOIDmode,
01929 stack_pointer_rtx,
01930 gen_rtx_PLUS (HImode,
01931 stack_pointer_rtx,
01932 GEN_INT (size))),
01933 gen_rtx_CLOBBER (VOIDmode, scratch)));
01934 emit_insn (insn);
01935 }
01936 else
01937 {
01938 int i;
01939
01940 for (i = 2; i <= size; i += 2)
01941 emit_move_after_reload (scratch, stack_pop_word, scratch);
01942 if (size & 1)
01943 emit_insn (gen_addhi3 (stack_pointer_rtx,
01944 stack_pointer_rtx, const1_rtx));
01945 }
01946
01947
01948 if (current_function_interrupt)
01949 {
01950 emit_move_after_reload (gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),
01951 stack_pop_word, scratch);
01952 emit_move_after_reload (gen_rtx_REG (HImode, SOFT_Z_REGNUM),
01953 stack_pop_word, scratch);
01954 emit_move_after_reload (m68hc11_soft_tmp_reg, stack_pop_word, scratch);
01955 }
01956
01957
01958 if (frame_pointer_needed)
01959 emit_move_after_reload (hard_frame_pointer_rtx, stack_pop_word, scratch);
01960
01961
01962
01963
01964 else if (current_function_trap && return_size != 0)
01965 {
01966 rtx addr_reg = stack_pointer_rtx;
01967
01968 if (!TARGET_M6812)
01969 {
01970 emit_move_after_reload (scratch, stack_pointer_rtx, 0);
01971 addr_reg = scratch;
01972 }
01973 emit_move_after_reload (gen_rtx_MEM (HImode,
01974 gen_rtx_PLUS (HImode, addr_reg,
01975 const1_rtx)), d_reg, 0);
01976 if (return_size > HARD_REG_SIZE)
01977 emit_move_after_reload (gen_rtx_MEM (HImode,
01978 gen_rtx_PLUS (HImode, addr_reg,
01979 GEN_INT (3))), ix_reg, 0);
01980 }
01981
01982 emit_jump_insn (gen_return ());
01983 }
01984
01985
01986
01987
01988
01989
01990 rtx
01991 m68hc11_gen_lowpart (enum machine_mode mode, rtx x)
01992 {
01993
01994
01995
01996 if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))
01997 {
01998 return gen_rtx_MEM (mode, XEXP (x, 0));
01999 }
02000
02001
02002
02003
02004
02005 if (GET_CODE (x) == CONST_DOUBLE)
02006 {
02007 long l[2];
02008
02009 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02010 {
02011 REAL_VALUE_TYPE r;
02012
02013 if (GET_MODE (x) == SFmode)
02014 {
02015 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02016 REAL_VALUE_TO_TARGET_SINGLE (r, l[0]);
02017 }
02018 else
02019 {
02020 rtx first, second;
02021
02022 split_double (x, &first, &second);
02023 return second;
02024 }
02025 if (mode == SImode)
02026 return GEN_INT (l[0]);
02027
02028 return gen_int_mode (l[0], HImode);
02029 }
02030 else
02031 {
02032 l[0] = CONST_DOUBLE_LOW (x);
02033 }
02034 if (mode == SImode)
02035 return GEN_INT (l[0]);
02036 else if (mode == HImode && GET_MODE (x) == SFmode)
02037 return gen_int_mode (l[0], HImode);
02038 else
02039 abort ();
02040 }
02041
02042 if (mode == QImode && D_REG_P (x))
02043 return gen_rtx_REG (mode, HARD_B_REGNUM);
02044
02045
02046 if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
02047 {
02048 if (mode == SImode)
02049 return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4);
02050 else if (mode == HImode)
02051 return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
02052 else
02053 abort ();
02054 }
02055 x = gen_lowpart (mode, x);
02056
02057
02058
02059
02060 if (GET_CODE (x) == MEM)
02061 x = copy_rtx (x);
02062 return x;
02063 }
02064
02065 rtx
02066 m68hc11_gen_highpart (enum machine_mode mode, rtx x)
02067 {
02068
02069
02070
02071 if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))
02072 {
02073 return gen_rtx_MEM (mode, XEXP (x, 0));
02074 }
02075
02076
02077
02078
02079
02080 if (GET_CODE (x) == CONST_DOUBLE)
02081 {
02082 long l[2];
02083
02084 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02085 {
02086 REAL_VALUE_TYPE r;
02087
02088 if (GET_MODE (x) == SFmode)
02089 {
02090 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02091 REAL_VALUE_TO_TARGET_SINGLE (r, l[1]);
02092 }
02093 else
02094 {
02095 rtx first, second;
02096
02097 split_double (x, &first, &second);
02098 return first;
02099 }
02100 if (mode == SImode)
02101 return GEN_INT (l[1]);
02102
02103 return gen_int_mode ((l[1] >> 16), HImode);
02104 }
02105 else
02106 {
02107 l[1] = CONST_DOUBLE_HIGH (x);
02108 }
02109
02110 if (mode == SImode)
02111 return GEN_INT (l[1]);
02112 else if (mode == HImode && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02113 return gen_int_mode ((l[0] >> 16), HImode);
02114 else
02115 abort ();
02116 }
02117 if (GET_CODE (x) == CONST_INT)
02118 {
02119 HOST_WIDE_INT val = INTVAL (x);
02120
02121 if (mode == QImode)
02122 {
02123 return gen_int_mode (val >> 8, QImode);
02124 }
02125 else if (mode == HImode)
02126 {
02127 return gen_int_mode (val >> 16, HImode);
02128 }
02129 else if (mode == SImode)
02130 {
02131 return gen_int_mode (val >> 32, SImode);
02132 }
02133 }
02134 if (mode == QImode && D_REG_P (x))
02135 return gen_rtx_REG (mode, HARD_A_REGNUM);
02136
02137
02138
02139
02140
02141 if (mode == QImode && S_REG_P (x))
02142 {
02143 int pos;
02144
02145
02146
02147 pos = TARGET_NO_DIRECT_MODE ? 1 : 0;
02148 return gen_rtx_MEM (QImode,
02149 gen_rtx_SYMBOL_REF (Pmode,
02150 ®_names[REGNO (x)][pos]));
02151 }
02152
02153
02154 if (GET_CODE (x) == SUBREG)
02155 {
02156 return gen_rtx_SUBREG (mode, XEXP (x, 0), XEXP (x, 1));
02157 }
02158 if (GET_CODE (x) == REG)
02159 {
02160 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
02161 return gen_rtx_REG (mode, REGNO (x));
02162 else
02163 return gen_rtx_SUBREG (mode, x, 0);
02164 }
02165
02166 if (GET_CODE (x) == MEM)
02167 {
02168 x = change_address (x, mode, 0);
02169
02170
02171
02172
02173 if (GET_CODE (x) == MEM)
02174 x = copy_rtx (x);
02175 return x;
02176 }
02177 abort ();
02178 }
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188 int
02189 dead_register_here (rtx x, rtx reg)
02190 {
02191 rtx x_reg;
02192 rtx p;
02193
02194 if (D_REG_P (reg))
02195 x_reg = gen_rtx_REG (SImode, HARD_X_REGNUM);
02196 else
02197 x_reg = 0;
02198
02199 for (p = PREV_INSN (x); p && GET_CODE (p) != CODE_LABEL; p = PREV_INSN (p))
02200 if (INSN_P (p))
02201 {
02202 rtx body;
02203
02204 body = PATTERN (p);
02205
02206 if (GET_CODE (body) == CALL_INSN)
02207 break;
02208 if (GET_CODE (body) == JUMP_INSN)
02209 break;
02210
02211 if (GET_CODE (body) == SET)
02212 {
02213 rtx dst = XEXP (body, 0);
02214
02215 if (GET_CODE (dst) == REG && REGNO (dst) == REGNO (reg))
02216 break;
02217 if (x_reg && rtx_equal_p (dst, x_reg))
02218 break;
02219
02220 if (find_regno_note (p, REG_DEAD, REGNO (reg)))
02221 return 1;
02222 }
02223 else if (reg_mentioned_p (reg, p)
02224 || (x_reg && reg_mentioned_p (x_reg, p)))
02225 break;
02226 }
02227
02228
02229
02230 for (p = x ; p; p = NEXT_INSN (p))
02231 {
02232 rtx body;
02233
02234 if (GET_CODE (p) == CODE_LABEL
02235 || GET_CODE (p) == JUMP_INSN
02236 || GET_CODE (p) == CALL_INSN || GET_CODE (p) == BARRIER)
02237 break;
02238
02239 if (GET_CODE (p) != INSN)
02240 continue;
02241
02242 body = PATTERN (p);
02243 if (GET_CODE (body) == SET)
02244 {
02245 rtx src = XEXP (body, 1);
02246 rtx dst = XEXP (body, 0);
02247
02248 if (GET_CODE (dst) == REG
02249 && REGNO (dst) == REGNO (reg) && !reg_mentioned_p (reg, src))
02250 return 1;
02251 }
02252
02253
02254 if (reg_mentioned_p (reg, p)
02255 || (x_reg != 0 && GET_MODE (p) == SImode
02256 && reg_mentioned_p (x_reg, p)))
02257 break;
02258 }
02259 return p == 0 ? 1 : 0;
02260 }
02261
02262
02263
02264
02265
02266 static void
02267 asm_print_register (FILE *file, int regno)
02268 {
02269 const char *name = reg_names[regno];
02270
02271 if (TARGET_NO_DIRECT_MODE && name[0] == '*')
02272 name++;
02273
02274 fprintf (file, "%s", name);
02275 }
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309 void
02310 print_operand (FILE *file, rtx op, int letter)
02311 {
02312 if (letter == 't')
02313 {
02314 asm_print_register (file, SOFT_TMP_REGNUM);
02315 return;
02316 }
02317 else if (letter == 'T')
02318 {
02319 asm_print_register (file, SOFT_TMP_REGNUM);
02320 fprintf (file, "+1");
02321 return;
02322 }
02323 else if (letter == '#')
02324 {
02325 asm_fprintf (file, "%I");
02326 }
02327
02328 if (GET_CODE (op) == REG)
02329 {
02330 if (letter == 'b' && S_REG_P (op))
02331 {
02332 asm_print_register (file, REGNO (op));
02333 fprintf (file, "+1");
02334 }
02335 else if (letter == 'b' && D_REG_P (op))
02336 {
02337 asm_print_register (file, HARD_B_REGNUM);
02338 }
02339 else
02340 {
02341 asm_print_register (file, REGNO (op));
02342 }
02343 return;
02344 }
02345
02346 if (GET_CODE (op) == SYMBOL_REF && (letter == 'b' || letter == 'h'))
02347 {
02348 if (letter == 'b')
02349 asm_fprintf (file, "%I%%lo(");
02350 else
02351 asm_fprintf (file, "%I%%hi(");
02352
02353 output_addr_const (file, op);
02354 fprintf (file, ")");
02355 return;
02356 }
02357
02358
02359
02360 if (GET_MODE (op) == HImode || GET_MODE (op) == VOIDmode)
02361 {
02362 if (letter == 'b')
02363 {
02364 op = m68hc11_gen_lowpart (QImode, op);
02365 }
02366 else if (letter == 'h')
02367 {
02368 op = m68hc11_gen_highpart (QImode, op);
02369 }
02370 }
02371
02372 if (GET_CODE (op) == MEM)
02373 {
02374 rtx base = XEXP (op, 0);
02375 switch (GET_CODE (base))
02376 {
02377 case PRE_DEC:
02378 if (TARGET_M6812)
02379 {
02380 fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op)));
02381 asm_print_register (file, REGNO (XEXP (base, 0)));
02382 }
02383 else
02384 abort ();
02385 break;
02386
02387 case POST_DEC:
02388 if (TARGET_M6812)
02389 {
02390 fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
02391 asm_print_register (file, REGNO (XEXP (base, 0)));
02392 fprintf (file, "-");
02393 }
02394 else
02395 abort ();
02396 break;
02397
02398 case POST_INC:
02399 if (TARGET_M6812)
02400 {
02401 fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
02402 asm_print_register (file, REGNO (XEXP (base, 0)));
02403 fprintf (file, "+");
02404 }
02405 else
02406 abort ();
02407 break;
02408
02409 case PRE_INC:
02410 if (TARGET_M6812)
02411 {
02412 fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op)));
02413 asm_print_register (file, REGNO (XEXP (base, 0)));
02414 }
02415 else
02416 abort ();
02417 break;
02418
02419 case MEM:
02420 if (TARGET_M6812)
02421 {
02422 fprintf (file, "[");
02423 print_operand_address (file, XEXP (base, 0));
02424 fprintf (file, "]");
02425 }
02426 else
02427 abort ();
02428 break;
02429
02430 default:
02431 if (m68hc11_page0_symbol_p (base))
02432 fprintf (file, "*");
02433
02434 output_address (base);
02435 break;
02436 }
02437 }
02438 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
02439 {
02440 REAL_VALUE_TYPE r;
02441 long l;
02442
02443 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
02444 REAL_VALUE_TO_TARGET_SINGLE (r, l);
02445 asm_fprintf (file, "%I0x%lx", l);
02446 }
02447 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
02448 {
02449 char dstr[30];
02450
02451 real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (op),
02452 sizeof (dstr), 0, 1);
02453 asm_fprintf (file, "%I0r%s", dstr);
02454 }
02455 else
02456 {
02457 int need_parenthesize = 0;
02458
02459 if (letter != 'i')
02460 asm_fprintf (file, "%I");
02461 else
02462 need_parenthesize = must_parenthesize (op);
02463
02464 if (need_parenthesize)
02465 fprintf (file, "(");
02466
02467 output_addr_const (file, op);
02468 if (need_parenthesize)
02469 fprintf (file, ")");
02470 }
02471 }
02472
02473
02474
02475
02476 static int
02477 must_parenthesize (rtx op)
02478 {
02479 const char *name;
02480
02481 switch (GET_CODE (op))
02482 {
02483 case SYMBOL_REF:
02484 name = XSTR (op, 0);
02485
02486
02487 return (strcasecmp (name, "a") == 0
02488 || strcasecmp (name, "b") == 0
02489 || strcasecmp (name, "d") == 0
02490 || strcasecmp (name, "x") == 0
02491 || strcasecmp (name, "y") == 0
02492 || strcasecmp (name, "ix") == 0
02493 || strcasecmp (name, "iy") == 0
02494 || strcasecmp (name, "pc") == 0
02495 || strcasecmp (name, "sp") == 0
02496 || strcasecmp (name, "ccr") == 0) ? 1 : 0;
02497
02498 case PLUS:
02499 case MINUS:
02500 return must_parenthesize (XEXP (op, 0))
02501 || must_parenthesize (XEXP (op, 1));
02502
02503 case MEM:
02504 case CONST:
02505 case ZERO_EXTEND:
02506 case SIGN_EXTEND:
02507 return must_parenthesize (XEXP (op, 0));
02508
02509 case CONST_DOUBLE:
02510 case CONST_INT:
02511 case LABEL_REF:
02512 case CODE_LABEL:
02513 default:
02514 return 0;
02515 }
02516 }
02517
02518
02519
02520
02521
02522 void
02523 print_operand_address (FILE *file, rtx addr)
02524 {
02525 rtx base;
02526 rtx offset;
02527 int need_parenthesis = 0;
02528
02529 switch (GET_CODE (addr))
02530 {
02531 case REG:
02532 if (!REG_P (addr) || !REG_OK_FOR_BASE_STRICT_P (addr))
02533 abort ();
02534
02535 fprintf (file, "0,");
02536 asm_print_register (file, REGNO (addr));
02537 break;
02538
02539 case MEM:
02540 base = XEXP (addr, 0);
02541 switch (GET_CODE (base))
02542 {
02543 case PRE_DEC:
02544 if (TARGET_M6812)
02545 {
02546 fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr)));
02547 asm_print_register (file, REGNO (XEXP (base, 0)));
02548 }
02549 else
02550 abort ();
02551 break;
02552
02553 case POST_DEC:
02554 if (TARGET_M6812)
02555 {
02556 fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
02557 asm_print_register (file, REGNO (XEXP (base, 0)));
02558 fprintf (file, "-");
02559 }
02560 else
02561 abort ();
02562 break;
02563
02564 case POST_INC:
02565 if (TARGET_M6812)
02566 {
02567 fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
02568 asm_print_register (file, REGNO (XEXP (base, 0)));
02569 fprintf (file, "+");
02570 }
02571 else
02572 abort ();
02573 break;
02574
02575 case PRE_INC:
02576 if (TARGET_M6812)
02577 {
02578 fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr)));
02579 asm_print_register (file, REGNO (XEXP (base, 0)));
02580 }
02581 else
02582 abort ();
02583 break;
02584
02585 default:
02586 need_parenthesis = must_parenthesize (base);
02587 if (need_parenthesis)
02588 fprintf (file, "(");
02589
02590 output_addr_const (file, base);
02591 if (need_parenthesis)
02592 fprintf (file, ")");
02593 break;
02594 }
02595 break;
02596
02597 case PLUS:
02598 base = XEXP (addr, 0);
02599 offset = XEXP (addr, 1);
02600 if (!G_REG_P (base) && G_REG_P (offset))
02601 {
02602 base = XEXP (addr, 1);
02603 offset = XEXP (addr, 0);
02604 }
02605 if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset)))
02606 {
02607 need_parenthesis = must_parenthesize (addr);
02608
02609 if (need_parenthesis)
02610 fprintf (file, "(");
02611
02612 output_addr_const (file, base);
02613 fprintf (file, "+");
02614 output_addr_const (file, offset);
02615 if (need_parenthesis)
02616 fprintf (file, ")");
02617 }
02618 else if (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base))
02619 {
02620 if (REG_P (offset))
02621 {
02622 if (TARGET_M6812)
02623 {
02624 asm_print_register (file, REGNO (offset));
02625 fprintf (file, ",");
02626 asm_print_register (file, REGNO (base));
02627 }
02628 else
02629 abort ();
02630 }
02631 else
02632 {
02633 need_parenthesis = must_parenthesize (offset);
02634 if (need_parenthesis)
02635 fprintf (file, "(");
02636
02637 output_addr_const (file, offset);
02638 if (need_parenthesis)
02639 fprintf (file, ")");
02640 fprintf (file, ",");
02641 asm_print_register (file, REGNO (base));
02642 }
02643 }
02644 else
02645 {
02646 abort ();
02647 }
02648 break;
02649
02650 default:
02651 if (GET_CODE (addr) == CONST_INT
02652 && INTVAL (addr) < 0x8000 && INTVAL (addr) >= -0x8000)
02653 {
02654 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
02655 }
02656 else
02657 {
02658 need_parenthesis = must_parenthesize (addr);
02659 if (need_parenthesis)
02660 fprintf (file, "(");
02661
02662 output_addr_const (file, addr);
02663 if (need_parenthesis)
02664 fprintf (file, ")");
02665 }
02666 break;
02667 }
02668 }
02669
02670
02671
02672
02673 static rtx
02674 m68hc11_expand_compare (enum rtx_code code, rtx op0, rtx op1)
02675 {
02676 rtx ret = 0;
02677
02678 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
02679 abort ();
02680 else
02681 {
02682 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
02683 gen_rtx_COMPARE (VOIDmode, op0, op1)));
02684 ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
02685 }
02686
02687 return ret;
02688 }
02689
02690 rtx
02691 m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1,
02692 rtx label)
02693 {
02694 rtx tmp;
02695
02696 switch (GET_MODE (op0))
02697 {
02698 case QImode:
02699 case HImode:
02700 tmp = m68hc11_expand_compare (code, op0, op1);
02701 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
02702 gen_rtx_LABEL_REF (VOIDmode, label),
02703 pc_rtx);
02704 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
02705 return 0;
02706 #if 0
02707
02708
02709 case SFmode:
02710 case DFmode:
02711
02712
02713 {
02714 rtvec vec;
02715 int use_fcomi;
02716
02717 code = m68hc11_prepare_fp_compare_args (code, &m68hc11_compare_op0,
02718 &m68hc11_compare_op1);
02719
02720 tmp = gen_rtx_fmt_ee (code, m68hc11_fp_compare_mode (code),
02721 m68hc11_compare_op0, m68hc11_compare_op1);
02722 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
02723 gen_rtx_LABEL_REF (VOIDmode, label),
02724 pc_rtx);
02725 tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
02726
02727 use_fcomi = ix86_use_fcomi_compare (code);
02728 vec = rtvec_alloc (3 + !use_fcomi);
02729 RTVEC_ELT (vec, 0) = tmp;
02730 RTVEC_ELT (vec, 1)
02731 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
02732 RTVEC_ELT (vec, 2)
02733 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
02734 if (!use_fcomi)
02735 RTVEC_ELT (vec, 3)
02736 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
02737
02738 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
02739 return;
02740 }
02741 #endif
02742
02743 case SImode:
02744
02745 {
02746 rtx lo[2], hi[2], label2;
02747 enum rtx_code code1, code2, code3;
02748
02749 if (CONSTANT_P (op0) && !CONSTANT_P (op1))
02750 {
02751 tmp = op0;
02752 op0 = op1;
02753 op1 = tmp;
02754 code = swap_condition (code);
02755 }
02756 lo[0] = m68hc11_gen_lowpart (HImode, op0);
02757 lo[1] = m68hc11_gen_lowpart (HImode, op1);
02758 hi[0] = m68hc11_gen_highpart (HImode, op0);
02759 hi[1] = m68hc11_gen_highpart (HImode, op1);
02760
02761
02762
02763
02764 if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
02765 && (code == LT || code == LTU))
02766 {
02767 return m68hc11_expand_compare_and_branch (code, hi[0], hi[1],
02768 label);
02769 }
02770
02771
02772
02773 label2 = gen_label_rtx ();
02774
02775 code1 = code;
02776 code2 = swap_condition (code);
02777 code3 = unsigned_condition (code);
02778
02779 switch (code)
02780 {
02781 case LT:
02782 case GT:
02783 case LTU:
02784 case GTU:
02785 break;
02786
02787 case LE:
02788 code1 = LT;
02789 code2 = GT;
02790 break;
02791 case GE:
02792 code1 = GT;
02793 code2 = LT;
02794 break;
02795 case LEU:
02796 code1 = LTU;
02797 code2 = GTU;
02798 break;
02799 case GEU:
02800 code1 = GTU;
02801 code2 = LTU;
02802 break;
02803
02804 case EQ:
02805 code1 = UNKNOWN;
02806 code2 = NE;
02807 break;
02808 case NE:
02809 code2 = UNKNOWN;
02810 break;
02811
02812 default:
02813 abort ();
02814 }
02815
02816
02817
02818
02819
02820
02821
02822
02823 if (code1 != UNKNOWN)
02824 m68hc11_expand_compare_and_branch (code1, hi[0], hi[1], label);
02825 if (code2 != UNKNOWN)
02826 m68hc11_expand_compare_and_branch (code2, hi[0], hi[1], label2);
02827
02828 m68hc11_expand_compare_and_branch (code3, lo[0], lo[1], label);
02829
02830 if (code2 != UNKNOWN)
02831 emit_label (label2);
02832 return 0;
02833 }
02834
02835 default:
02836 abort ();
02837 }
02838 return 0;
02839 }
02840
02841
02842
02843 static int
02844 autoinc_mode (rtx x)
02845 {
02846 if (GET_CODE (x) != MEM)
02847 return CONST;
02848
02849 x = XEXP (x, 0);
02850 if (GET_CODE (x) == PRE_INC
02851 || GET_CODE (x) == PRE_DEC
02852 || GET_CODE (x) == POST_INC
02853 || GET_CODE (x) == POST_DEC)
02854 return GET_CODE (x);
02855
02856 return CONST;
02857 }
02858
02859 static int
02860 m68hc11_make_autoinc_notes (rtx *x, void *data)
02861 {
02862 rtx insn;
02863
02864 switch (GET_CODE (*x))
02865 {
02866 case PRE_DEC:
02867 case PRE_INC:
02868 case POST_DEC:
02869 case POST_INC:
02870 insn = (rtx) data;
02871 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (*x, 0),
02872 REG_NOTES (insn));
02873 return -1;
02874
02875 default:
02876 return 0;
02877 }
02878 }
02879
02880
02881
02882
02883 void
02884 m68hc11_split_move (rtx to, rtx from, rtx scratch)
02885 {
02886 rtx low_to, low_from;
02887 rtx high_to, high_from;
02888 rtx insn;
02889 enum machine_mode mode;
02890 int offset = 0;
02891 int autoinc_from = autoinc_mode (from);
02892 int autoinc_to = autoinc_mode (to);
02893
02894 mode = GET_MODE (to);
02895
02896
02897
02898
02899 if (TARGET_M6812 && GET_MODE_SIZE (mode) > 2)
02900 {
02901 rtx reg;
02902 int code;
02903
02904
02905
02906 if (autoinc_from == PRE_INC || autoinc_from == POST_DEC)
02907 {
02908 code = GET_CODE (XEXP (from, 0));
02909 reg = XEXP (XEXP (from, 0), 0);
02910 offset = GET_MODE_SIZE (GET_MODE (from));
02911 if (code == POST_DEC)
02912 offset = -offset;
02913
02914 if (code == PRE_INC)
02915 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02916
02917 m68hc11_split_move (to, gen_rtx_MEM (GET_MODE (from), reg), scratch);
02918 if (code == POST_DEC)
02919 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02920 return;
02921 }
02922
02923
02924 if (autoinc_to == PRE_INC || autoinc_to == POST_DEC)
02925 {
02926 code = GET_CODE (XEXP (to, 0));
02927 reg = XEXP (XEXP (to, 0), 0);
02928 offset = GET_MODE_SIZE (GET_MODE (to));
02929 if (code == POST_DEC)
02930 offset = -offset;
02931
02932 if (code == PRE_INC)
02933 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02934
02935 m68hc11_split_move (gen_rtx_MEM (GET_MODE (to), reg), from, scratch);
02936 if (code == POST_DEC)
02937 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02938 return;
02939 }
02940
02941
02942
02943 if ((autoinc_to != autoinc_from
02944 && autoinc_to != CONST && autoinc_from != CONST)
02945
02946
02947
02948 || (autoinc_to != CONST
02949 && reg_mentioned_p (XEXP (XEXP (to, 0), 0), from)
02950 && !IS_STACK_PUSH (to)))
02951 {
02952
02953 code = GET_CODE (XEXP (to, 0));
02954 reg = XEXP (XEXP (to, 0), 0);
02955 offset = GET_MODE_SIZE (GET_MODE (to));
02956 if (code == PRE_DEC || code == POST_DEC)
02957 offset = -offset;
02958
02959 if (code == PRE_DEC || code == PRE_INC)
02960 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02961 m68hc11_split_move (gen_rtx_MEM (GET_MODE (to), reg), from, scratch);
02962 if (code == POST_DEC || code == POST_INC)
02963 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02964
02965 return;
02966 }
02967
02968
02969
02970 if (autoinc_from != CONST
02971 && reg_mentioned_p (XEXP (XEXP (from, 0), 0), to)
02972 && !IS_STACK_PUSH (to))
02973 {
02974
02975 code = GET_CODE (XEXP (from, 0));
02976 reg = XEXP (XEXP (from, 0), 0);
02977 offset = GET_MODE_SIZE (GET_MODE (from));
02978 if (code == PRE_DEC || code == POST_DEC)
02979 offset = -offset;
02980
02981 if (code == PRE_DEC || code == PRE_INC)
02982 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02983 m68hc11_split_move (to, gen_rtx_MEM (GET_MODE (from), reg), scratch);
02984 if (code == POST_DEC || code == POST_INC)
02985 emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
02986
02987 return;
02988 }
02989 }
02990
02991 if (GET_MODE_SIZE (mode) == 8)
02992 mode = SImode;
02993 else if (GET_MODE_SIZE (mode) == 4)
02994 mode = HImode;
02995 else
02996 mode = QImode;
02997
02998 if (TARGET_M6812
02999 && IS_STACK_PUSH (to)
03000 && reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM), from))
03001 {
03002 if (mode == SImode)
03003 {
03004 offset = 4;
03005 }
03006 else if (mode == HImode)
03007 {
03008 offset = 2;
03009 }
03010 else
03011 offset = 0;
03012 }
03013
03014 low_to = m68hc11_gen_lowpart (mode, to);
03015 high_to = m68hc11_gen_highpart (mode, to);
03016
03017 low_from = m68hc11_gen_lowpart (mode, from);
03018 high_from = m68hc11_gen_highpart (mode, from);
03019
03020 if (offset)
03021 {
03022 high_from = adjust_address (high_from, mode, offset);
03023 low_from = high_from;
03024 }
03025
03026
03027
03028
03029 if (TARGET_M6812
03030 && GET_MODE_SIZE (mode) >= 2
03031 && autoinc_from != autoinc_to
03032 && (autoinc_from == POST_INC || autoinc_to == POST_INC))
03033 {
03034 rtx swap;
03035
03036 swap = low_to;
03037 low_to = high_to;
03038 high_to = swap;
03039
03040 swap = low_from;
03041 low_from = high_from;
03042 high_from = swap;
03043 }
03044 if (mode == SImode)
03045 {
03046 m68hc11_split_move (low_to, low_from, scratch);
03047 m68hc11_split_move (high_to, high_from, scratch);
03048 }
03049 else if (H_REG_P (to) || H_REG_P (from)
03050 || (low_from == const0_rtx
03051 && high_from == const0_rtx
03052 && ! push_operand (to, GET_MODE (to))
03053 && ! H_REG_P (scratch))
03054 || (TARGET_M6812
03055 && (!m68hc11_register_indirect_p (from, GET_MODE (from))
03056 || m68hc11_small_indexed_indirect_p (from,
03057 GET_MODE (from)))
03058 && (!m68hc11_register_indirect_p (to, GET_MODE (to))
03059 || m68hc11_small_indexed_indirect_p (to, GET_MODE (to)))))
03060 {
03061 insn = emit_move_insn (low_to, low_from);
03062 for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
03063
03064 insn = emit_move_insn (high_to, high_from);
03065 for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
03066 }
03067 else
03068 {
03069 insn = emit_move_insn (scratch, low_from);
03070 for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
03071 insn = emit_move_insn (low_to, scratch);
03072 for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
03073
03074 insn = emit_move_insn (scratch, high_from);
03075 for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
03076 insn = emit_move_insn (high_to, scratch);
03077 for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
03078 }
03079 }
03080
03081 static rtx
03082 simplify_logical (enum machine_mode mode, int code, rtx operand, rtx *result)
03083 {
03084 int val;
03085 int mask;
03086
03087 *result = 0;
03088 if (GET_CODE (operand) != CONST_INT)
03089 return operand;
03090
03091 if (mode == HImode)
03092 mask = 0x0ffff;
03093 else
03094 mask = 0x0ff;
03095
03096 val = INTVAL (operand);
03097 switch (code)
03098 {
03099 case IOR:
03100 if ((val & mask) == 0)
03101 return 0;
03102 if ((val & mask) == mask)
03103 *result = constm1_rtx;
03104 break;
03105
03106 case AND:
03107 if ((val & mask) == 0)
03108 *result = const0_rtx;
03109 if ((val & mask) == mask)
03110 return 0;
03111 break;
03112
03113 case XOR:
03114 if ((val & mask) == 0)
03115 return 0;
03116 break;
03117 }
03118 return operand;
03119 }
03120
03121 static void
03122 m68hc11_emit_logical (enum machine_mode mode, int code, rtx *operands)
03123 {
03124 rtx result;
03125 int need_copy;
03126
03127 need_copy = (rtx_equal_p (operands[0], operands[1])
03128 || rtx_equal_p (operands[0], operands[2])) ? 0 : 1;
03129
03130 operands[1] = simplify_logical (mode, code, operands[1], &result);
03131 operands[2] = simplify_logical (mode, code, operands[2], &result);
03132
03133 if (result && GET_CODE (result) == CONST_INT)
03134 {
03135 if (!H_REG_P (operands[0]) && operands[3]
03136 && (INTVAL (result) != 0 || IS_STACK_PUSH (operands[0])))
03137 {
03138 emit_move_insn (operands[3], result);
03139 emit_move_insn (operands[0], operands[3]);
03140 }
03141 else
03142 {
03143 emit_move_insn (operands[0], result);
03144 }
03145 }
03146 else if (operands[1] != 0 && operands[2] != 0)
03147 {
03148 rtx insn;
03149
03150 if (!H_REG_P (operands[0]) && operands[3])
03151 {
03152 emit_move_insn (operands[3], operands[1]);
03153 emit_insn (gen_rtx_SET (mode,
03154 operands[3],
03155 gen_rtx_fmt_ee (code, mode,
03156 operands[3], operands[2])));
03157 insn = emit_move_insn (operands[0], operands[3]);
03158 }
03159 else
03160 {
03161 insn = emit_insn (gen_rtx_SET (mode,
03162 operands[0],
03163 gen_rtx_fmt_ee (code, mode,
03164 operands[0],
03165 operands[2])));
03166 }
03167 }
03168
03169
03170 else if (need_copy)
03171 {
03172 rtx src;
03173
03174 if (GET_CODE (operands[1]) == CONST_INT)
03175 src = operands[2];
03176 else
03177 src = operands[1];
03178
03179 if (!H_REG_P (operands[0]) && !H_REG_P (src))
03180 {
03181 emit_move_insn (operands[3], src);
03182 emit_move_insn (operands[0], operands[3]);
03183 }
03184 else
03185 {
03186 emit_move_insn (operands[0], src);
03187 }
03188 }
03189 }
03190
03191 void
03192 m68hc11_split_logical (enum machine_mode mode, int code, rtx *operands)
03193 {
03194 rtx low[4];
03195 rtx high[4];
03196
03197 low[0] = m68hc11_gen_lowpart (mode, operands[0]);
03198 low[1] = m68hc11_gen_lowpart (mode, operands[1]);
03199 low[2] = m68hc11_gen_lowpart (mode, operands[2]);
03200
03201 high[0] = m68hc11_gen_highpart (mode, operands[0]);
03202 high[1] = m68hc11_gen_highpart (mode, operands[1]);
03203 high[2] = m68hc11_gen_highpart (mode, operands[2]);
03204
03205 low[3] = operands[3];
03206 high[3] = operands[3];
03207 if (mode == SImode)
03208 {
03209 m68hc11_split_logical (HImode, code, low);
03210 m68hc11_split_logical (HImode, code, high);
03211 return;
03212 }
03213
03214 m68hc11_emit_logical (mode, code, low);
03215 m68hc11_emit_logical (mode, code, high);
03216 }
03217
03218
03219
03220
03221 void
03222 m68hc11_output_swap (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
03223 {
03224
03225
03226
03227
03228
03229
03230 if (X_REG_P (operands[1]) || X_REG_P (operands[0]))
03231 {
03232 if (cc_prev_status.value1 != 0
03233 && (D_REG_P (cc_prev_status.value1)
03234 || X_REG_P (cc_prev_status.value1)))
03235 {
03236 cc_status = cc_prev_status;
03237 if (D_REG_P (cc_status.value1))
03238 cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
03239 HARD_X_REGNUM);
03240 else
03241 cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
03242 HARD_D_REGNUM);
03243 }
03244 else
03245 CC_STATUS_INIT;
03246
03247 output_asm_insn ("xgdx", operands);
03248 }
03249 else
03250 {
03251 if (cc_prev_status.value1 != 0
03252 && (D_REG_P (cc_prev_status.value1)
03253 || Y_REG_P (cc_prev_status.value1)))
03254 {
03255 cc_status = cc_prev_status;
03256 if (D_REG_P (cc_status.value1))
03257 cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
03258 HARD_Y_REGNUM);
03259 else
03260 cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
03261 HARD_D_REGNUM);
03262 }
03263 else
03264 CC_STATUS_INIT;
03265
03266 output_asm_insn ("xgdy", operands);
03267 }
03268 }
03269
03270
03271
03272
03273 int
03274 next_insn_test_reg (rtx insn, rtx reg)
03275 {
03276 rtx body;
03277
03278 insn = next_nonnote_insn (insn);
03279 if (GET_CODE (insn) != INSN)
03280 return 0;
03281
03282 body = PATTERN (insn);
03283 if (sets_cc0_p (body) != 1)
03284 return 0;
03285
03286 if (rtx_equal_p (XEXP (body, 1), reg) == 0)
03287 return 0;
03288
03289 return 1;
03290 }
03291
03292
03293
03294 void
03295 m68hc11_gen_movhi (rtx insn, rtx *operands)
03296 {
03297 int reg;
03298
03299
03300
03301
03302 if (operands[0] == operands[1] || rtx_equal_p (operands[0], operands[1]))
03303 {
03304 cc_status = cc_prev_status;
03305 return;
03306 }
03307
03308 if (TARGET_M6812)
03309 {
03310 rtx from = operands[1];
03311 rtx to = operands[0];
03312
03313 if (IS_STACK_PUSH (to) && H_REG_P (from))
03314 {
03315 cc_status = cc_prev_status;
03316 switch (REGNO (from))
03317 {
03318 case HARD_X_REGNUM:
03319 case HARD_Y_REGNUM:
03320 case HARD_D_REGNUM:
03321 output_asm_insn ("psh%1", operands);
03322 break;
03323 case HARD_SP_REGNUM:
03324 output_asm_insn ("sts\t2,-sp", operands);
03325 break;
03326 default:
03327 abort ();
03328 }
03329 return;
03330 }
03331 if (IS_STACK_POP (from) && H_REG_P (to))
03332 {
03333 cc_status = cc_prev_status;
03334 switch (REGNO (to))
03335 {
03336 case HARD_X_REGNUM:
03337 case HARD_Y_REGNUM:
03338 case HARD_D_REGNUM:
03339 output_asm_insn ("pul%0", operands);
03340 break;
03341 default:
03342 abort ();
03343 }
03344 return;
03345 }
03346 if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
03347 {
03348 m68hc11_notice_keep_cc (operands[0]);
03349 output_asm_insn ("tfr\t%1,%0", operands);
03350 }
03351 else if (H_REG_P (operands[0]))
03352 {
03353 if (SP_REG_P (operands[0]))
03354 output_asm_insn ("lds\t%1", operands);
03355 else
03356 output_asm_insn ("ld%0\t%1", operands);
03357 }
03358 else if (H_REG_P (operands[1]))
03359 {
03360 if (SP_REG_P (operands[1]))
03361 output_asm_insn ("sts\t%0", operands);
03362 else
03363 output_asm_insn ("st%1\t%0", operands);
03364 }
03365
03366
03367
03368
03369 else if (GET_CODE (to) == MEM && GET_CODE (XEXP (to, 0)) == MEM)
03370 {
03371 rtx ops[4];
03372
03373 ops[0] = to;
03374 ops[2] = from;
03375 ops[3] = 0;
03376 if (dead_register_here (insn, d_reg))
03377 ops[1] = d_reg;
03378 else if (dead_register_here (insn, ix_reg))
03379 ops[1] = ix_reg;
03380 else if (dead_register_here (insn, iy_reg))
03381 ops[1] = iy_reg;
03382 else
03383 {
03384 ops[1] = d_reg;
03385 ops[3] = d_reg;
03386 output_asm_insn ("psh%3", ops);
03387 }
03388
03389 ops[0] = to;
03390 ops[2] = from;
03391 output_asm_insn ("ld%1\t%2", ops);
03392 output_asm_insn ("st%1\t%0", ops);
03393 if (ops[3])
03394 output_asm_insn ("pul%3", ops);
03395 }
03396
03397
03398
03399
03400
03401 else if (GET_CODE (from) == CONST_INT
03402 && INTVAL (from) == 0
03403 && (MEM_VOLATILE_P (to) == 0
03404 || m68hc11_small_indexed_indirect_p (to, HImode) == 0))
03405 {
03406 output_asm_insn ("clr\t%h0", operands);
03407 output_asm_insn ("clr\t%b0", operands);
03408 }
03409 else
03410 {
03411 if ((m68hc11_register_indirect_p (from, GET_MODE (from))
03412 && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
03413 || (m68hc11_register_indirect_p (to, GET_MODE (to))
03414 && !m68hc11_small_indexed_indirect_p (to, GET_MODE (to))))
03415 {
03416 rtx ops[3];
03417
03418 if (operands[2])
03419 {
03420 ops[0] = operands[2];
03421 ops[1] = from;
03422 ops[2] = 0;
03423 m68hc11_gen_movhi (insn, ops);
03424 ops[0] = to;
03425 ops[1] = operands[2];
03426 m68hc11_gen_movhi (insn, ops);
03427 return;
03428 }
03429 else
03430 {
03431
03432 fatal_insn ("move insn not handled", insn);
03433 }
03434 }
03435 else
03436 {
03437 m68hc11_notice_keep_cc (operands[0]);
03438 output_asm_insn ("movw\t%1,%0", operands);
03439 }
03440 }
03441 return;
03442 }
03443
03444 if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
03445 {
03446 cc_status = cc_prev_status;
03447 switch (REGNO (operands[0]))
03448 {
03449 case HARD_X_REGNUM:
03450 case HARD_Y_REGNUM:
03451 output_asm_insn ("pul%0", operands);
03452 break;
03453 case HARD_D_REGNUM:
03454 output_asm_insn ("pula", operands);
03455 output_asm_insn ("pulb", operands);
03456 break;
03457 default:
03458 abort ();
03459 }
03460 return;
03461 }
03462
03463
03464
03465 if (H_REG_P (operands[0]))
03466 {
03467 switch (REGNO (operands[0]))
03468 {
03469 case HARD_D_REGNUM:
03470 if (X_REG_P (operands[1]))
03471 {
03472 if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM))
03473 {
03474 m68hc11_output_swap (insn, operands);
03475 }
03476 else if (next_insn_test_reg (insn, operands[0]))
03477 {
03478 output_asm_insn ("stx\t%t0\n\tldd\t%t0", operands);
03479 }
03480 else
03481 {
03482 m68hc11_notice_keep_cc (operands[0]);
03483 output_asm_insn ("pshx\n\tpula\n\tpulb", operands);
03484 }
03485 }
03486 else if (Y_REG_P (operands[1]))
03487 {
03488 if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM))
03489 {
03490 m68hc11_output_swap (insn, operands);
03491 }
03492 else
03493 {
03494
03495 output_asm_insn ("sty\t%t1", operands);
03496 output_asm_insn ("ldd\t%t1", operands);
03497 }
03498 }
03499 else if (SP_REG_P (operands[1]))
03500 {
03501 CC_STATUS_INIT;
03502 if (ix_reg == 0)
03503 create_regs_rtx ();
03504 if (optimize == 0 || dead_register_here (insn, ix_reg) == 0)
03505 output_asm_insn ("xgdx", operands);
03506 output_asm_insn ("tsx", operands);
03507 output_asm_insn ("xgdx", operands);
03508 }
03509 else if (IS_STACK_POP (operands[1]))
03510 {
03511 output_asm_insn ("pula\n\tpulb", operands);
03512 }
03513 else if (GET_CODE (operands[1]) == CONST_INT
03514 && INTVAL (operands[1]) == 0)
03515 {
03516 output_asm_insn ("clra\n\tclrb", operands);
03517 }
03518 else
03519 {
03520 output_asm_insn ("ldd\t%1", operands);
03521 }
03522 break;
03523
03524 case HARD_X_REGNUM:
03525 if (D_REG_P (operands[1]))
03526 {
03527 if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
03528 {
03529 m68hc11_output_swap (insn, operands);
03530 }
03531 else if (next_insn_test_reg (insn, operands[0]))
03532 {
03533 output_asm_insn ("std\t%t0\n\tldx\t%t0", operands);
03534 }
03535 else
03536 {
03537 m68hc11_notice_keep_cc (operands[0]);
03538 output_asm_insn ("pshb", operands);
03539 output_asm_insn ("psha", operands);
03540 output_asm_insn ("pulx", operands);
03541 }
03542 }
03543 else if (Y_REG_P (operands[1]))
03544 {
03545
03546
03547 if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM)
03548 && dead_register_here (insn, d_reg))
03549 {
03550 output_asm_insn ("xgdy", operands);
03551 output_asm_insn ("xgdx", operands);
03552 CC_STATUS_INIT;
03553 }
03554 else if (!optimize_size)
03555 {
03556 output_asm_insn ("sty\t%t1", operands);
03557 output_asm_insn ("ldx\t%t1", operands);
03558 }
03559 else
03560 {
03561 CC_STATUS_INIT;
03562 output_asm_insn ("pshy", operands);
03563 output_asm_insn ("pulx", operands);
03564 }
03565 }
03566 else if (SP_REG_P (operands[1]))
03567 {
03568
03569 cc_status = cc_prev_status;
03570 output_asm_insn ("tsx", operands);
03571 }
03572 else
03573 {
03574 output_asm_insn ("ldx\t%1", operands);
03575 }
03576 break;
03577
03578 case HARD_Y_REGNUM:
03579 if (D_REG_P (operands[1]))
03580 {
03581 if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
03582 {
03583 m68hc11_output_swap (insn, operands);
03584 }
03585 else
03586 {
03587 output_asm_insn ("std\t%t1", operands);
03588 output_asm_insn ("ldy\t%t1", operands);
03589 }
03590 }
03591 else if (X_REG_P (operands[1]))
03592 {
03593
03594
03595 if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM)
03596 && dead_register_here (insn, d_reg))
03597 {
03598 output_asm_insn ("xgdx", operands);
03599 output_asm_insn ("xgdy", operands);
03600 CC_STATUS_INIT;
03601 }
03602 else if (!optimize_size)
03603 {
03604 output_asm_insn ("stx\t%t1", operands);
03605 output_asm_insn ("ldy\t%t1", operands);
03606 }
03607 else
03608 {
03609 CC_STATUS_INIT;
03610 output_asm_insn ("pshx", operands);
03611 output_asm_insn ("puly", operands);
03612 }
03613 }
03614 else if (SP_REG_P (operands[1]))
03615 {
03616
03617 cc_status = cc_prev_status;
03618 output_asm_insn ("tsy", operands);
03619 }
03620 else
03621 {
03622 output_asm_insn ("ldy\t%1", operands);
03623 }
03624 break;
03625
03626 case HARD_SP_REGNUM:
03627 if (D_REG_P (operands[1]))
03628 {
03629 m68hc11_notice_keep_cc (operands[0]);
03630 output_asm_insn ("xgdx", operands);
03631 output_asm_insn ("txs", operands);
03632 output_asm_insn ("xgdx", operands);
03633 }
03634 else if (X_REG_P (operands[1]))
03635 {
03636
03637 cc_status = cc_prev_status;
03638 output_asm_insn ("txs", operands);
03639 }
03640 else if (Y_REG_P (operands[1]))
03641 {
03642
03643 cc_status = cc_prev_status;
03644 output_asm_insn ("tys", operands);
03645 }
03646 else
03647 {
03648
03649 CC_STATUS_INIT;
03650 output_asm_insn ("lds\t%1", operands);
03651 output_asm_insn ("des", operands);
03652 }
03653 break;
03654
03655 default:
03656 fatal_insn ("invalid register in the move instruction", insn);
03657 break;
03658 }
03659 return;
03660 }
03661 if (SP_REG_P (operands[1]) && REG_P (operands[0])
03662 && REGNO (operands[0]) == HARD_FRAME_POINTER_REGNUM)
03663 {
03664 output_asm_insn ("sts\t%0", operands);
03665 return;
03666 }
03667
03668 if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
03669 {
03670 cc_status = cc_prev_status;
03671 switch (REGNO (operands[1]))
03672 {
03673 case HARD_X_REGNUM:
03674 case HARD_Y_REGNUM:
03675 output_asm_insn ("psh%1", operands);
03676 break;
03677 case HARD_D_REGNUM:
03678 output_asm_insn ("pshb", operands);
03679 output_asm_insn ("psha", operands);
03680 break;
03681 default:
03682 abort ();
03683 }
03684 return;
03685 }
03686
03687
03688 if (!H_REG_P (operands[1]))
03689 {
03690 fatal_insn ("invalid operand in the instruction", insn);
03691 }
03692
03693 reg = REGNO (operands[1]);
03694 switch (reg)
03695 {
03696 case HARD_D_REGNUM:
03697 output_asm_insn ("std\t%0", operands);
03698 break;
03699
03700 case HARD_X_REGNUM:
03701 output_asm_insn ("stx\t%0", operands);
03702 break;
03703
03704 case HARD_Y_REGNUM:
03705 output_asm_insn ("sty\t%0", operands);
03706 break;
03707
03708 case HARD_SP_REGNUM:
03709 if (ix_reg == 0)
03710 create_regs_rtx ();
03711
03712 if (REG_P (operands[0]) && REGNO (operands[0]) == SOFT_TMP_REGNUM)
03713 {
03714 output_asm_insn ("pshx", operands);
03715 output_asm_insn ("tsx", operands);
03716 output_asm_insn ("inx", operands);
03717 output_asm_insn ("inx", operands);
03718 output_asm_insn ("stx\t%0", operands);
03719 output_asm_insn ("pulx", operands);
03720 }
03721
03722 else if (reg_mentioned_p (ix_reg, operands[0]))
03723 {
03724 output_asm_insn ("sty\t%t0", operands);
03725 output_asm_insn ("tsy", operands);
03726 output_asm_insn ("sty\t%0", operands);
03727 output_asm_insn ("ldy\t%t0", operands);
03728 }
03729 else
03730 {
03731 output_asm_insn ("stx\t%t0", operands);
03732 output_asm_insn ("tsx", operands);
03733 output_asm_insn ("stx\t%0", operands);
03734 output_asm_insn ("ldx\t%t0", operands);
03735 }
03736 CC_STATUS_INIT;
03737 break;
03738
03739 default:
03740 fatal_insn ("invalid register in the move instruction", insn);
03741 break;
03742 }
03743 }
03744
03745 void
03746 m68hc11_gen_movqi (rtx insn, rtx *operands)
03747 {
03748
03749
03750
03751 if (operands[0] == operands[1] || rtx_equal_p (operands[0], operands[1]))
03752 {
03753 cc_status = cc_prev_status;
03754 return;
03755 }
03756
03757 if (TARGET_M6812)
03758 {
03759 if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
03760 {
03761 m68hc11_notice_keep_cc (operands[0]);
03762 output_asm_insn ("tfr\t%1,%0", operands);
03763 }
03764 else if (H_REG_P (operands[0]))
03765 {
03766 if (IS_STACK_POP (operands[1]))
03767 output_asm_insn ("pul%b0", operands);
03768 else if (Q_REG_P (operands[0]))
03769 output_asm_insn ("lda%0\t%b1", operands);
03770 else if (D_REG_P (operands[0]))
03771 output_asm_insn ("ldab\t%b1", operands);
03772 else
03773 goto m6811_move;
03774 }
03775 else if (H_REG_P (operands[1]))
03776 {
03777 if (Q_REG_P (operands[1]))
03778 output_asm_insn ("sta%1\t%b0", operands);
03779 else if (D_REG_P (operands[1]))
03780 output_asm_insn ("stab\t%b0", operands);
03781 else
03782 goto m6811_move;
03783 }
03784 else
03785 {
03786 rtx from = operands[1];
03787 rtx to = operands[0];
03788
03789 if ((m68hc11_register_indirect_p (from, GET_MODE (from))
03790 && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
03791 || (m68hc11_register_indirect_p (to, GET_MODE (to))
03792 && !m68hc11_small_indexed_indirect_p (to, GET_MODE (to))))
03793 {
03794 rtx ops[3];
03795
03796 if (operands[2])
03797 {
03798 ops[0] = operands[2];
03799 ops[1] = from;
03800 ops[2] = 0;
03801 m68hc11_gen_movqi (insn, ops);
03802 ops[0] = to;
03803 ops[1] = operands[2];
03804 m68hc11_gen_movqi (insn, ops);
03805 }
03806 else
03807 {
03808
03809 fatal_insn ("move insn not handled", insn);
03810 }
03811 }
03812 else
03813 {
03814 if (GET_CODE (from) == CONST_INT && INTVAL (from) == 0)
03815 {
03816 output_asm_insn ("clr\t%b0", operands);
03817 }
03818 else
03819 {
03820 m68hc11_notice_keep_cc (operands[0]);
03821 output_asm_insn ("movb\t%b1,%b0", operands);
03822 }
03823 }
03824 }
03825 return;
03826 }
03827
03828 m6811_move:
03829 if (H_REG_P (operands[0]))
03830 {
03831 switch (REGNO (operands[0]))
03832 {
03833 case HARD_B_REGNUM:
03834 case HARD_D_REGNUM:
03835 if (X_REG_P (operands[1]))
03836 {
03837 if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM))
03838 {
03839 m68hc11_output_swap (insn, operands);
03840 }
03841 else
03842 {
03843 output_asm_insn ("stx\t%t1", operands);
03844 output_asm_insn ("ldab\t%T0", operands);
03845 }
03846 }
03847 else if (Y_REG_P (operands[1]))
03848 {
03849 if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM))
03850 {
03851 m68hc11_output_swap (insn, operands);
03852 }
03853 else
03854 {
03855 output_asm_insn ("sty\t%t1", operands);
03856 output_asm_insn ("ldab\t%T0", operands);
03857 }
03858 }
03859 else if (!DB_REG_P (operands[1]) && !D_REG_P (operands[1])
03860 && !DA_REG_P (operands[1]))
03861 {
03862 output_asm_insn ("ldab\t%b1", operands);
03863 }
03864 else if (DA_REG_P (operands[1]))
03865 {
03866 output_asm_insn ("tab", operands);
03867 }
03868 else
03869 {
03870 cc_status = cc_prev_status;
03871 return;
03872 }
03873 break;
03874
03875 case HARD_A_REGNUM:
03876 if (X_REG_P (operands[1]))
03877 {
03878 output_asm_insn ("stx\t%t1", operands);
03879 output_asm_insn ("ldaa\t%T0", operands);
03880 }
03881 else if (Y_REG_P (operands[1]))
03882 {
03883 output_asm_insn ("sty\t%t1", operands);
03884 output_asm_insn ("ldaa\t%T0", operands);
03885 }
03886 else if (!DB_REG_P (operands[1]) && !D_REG_P (operands[1])
03887 && !DA_REG_P (operands[1]))
03888 {
03889 output_asm_insn ("ldaa\t%b1", operands);
03890 }
03891 else if (!DA_REG_P (operands[1]))
03892 {
03893 output_asm_insn ("tba", operands);
03894 }
03895 else
03896 {
03897 cc_status = cc_prev_status;
03898 }
03899 break;
03900
03901 case HARD_X_REGNUM:
03902 if (D_REG_P (operands[1]))
03903 {
03904 if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
03905 {
03906 m68hc11_output_swap (insn, operands);
03907 }
03908 else
03909 {
03910 output_asm_insn ("stab\t%T1", operands);
03911 output_asm_insn ("ldx\t%t1", operands);
03912 }
03913 CC_STATUS_INIT;
03914 }
03915 else if (Y_REG_P (operands[1]))
03916 {
03917 output_asm_insn ("sty\t%t0", operands);
03918 output_asm_insn ("ldx\t%t0", operands);
03919 }
03920 else if (GET_CODE (operands[1]) == CONST_INT)
03921 {
03922 output_asm_insn ("ldx\t%1", operands);
03923 }
03924 else if (dead_register_here (insn, d_reg))
03925 {
03926 output_asm_insn ("ldab\t%b1", operands);
03927 output_asm_insn ("xgdx", operands);
03928 }
03929 else if (!reg_mentioned_p (operands[0], operands[1]))
03930 {
03931 output_asm_insn ("xgdx", operands);
03932 output_asm_insn ("ldab\t%b1", operands);
03933 output_asm_insn ("xgdx", operands);
03934 }
03935 else
03936 {
03937 output_asm_insn ("pshb", operands);
03938 output_asm_insn ("ldab\t%b1", operands);
03939 output_asm_insn ("stab\t%T1", operands);
03940 output_asm_insn ("ldx\t%t1", operands);
03941 output_asm_insn ("pulb", operands);
03942 CC_STATUS_INIT;
03943 }
03944 break;
03945
03946 case HARD_Y_REGNUM:
03947 if (D_REG_P (operands[1]))
03948 {
03949 output_asm_insn ("stab\t%T1", operands);
03950 output_asm_insn ("ldy\t%t1", operands);
03951 CC_STATUS_INIT;
03952 }
03953 else if (X_REG_P (operands[1]))
03954 {
03955 output_asm_insn ("stx\t%t1", operands);
03956 output_asm_insn ("ldy\t%t1", operands);
03957 CC_STATUS_INIT;
03958 }
03959 else if (GET_CODE (operands[1]) == CONST_INT)
03960 {
03961 output_asm_insn ("ldy\t%1", operands);
03962 }
03963 else if (dead_register_here (insn, d_reg))
03964 {
03965 output_asm_insn ("ldab\t%b1", operands);
03966 output_asm_insn ("xgdy", operands);
03967 }
03968 else if (!reg_mentioned_p (operands[0], operands[1]))
03969 {
03970 output_asm_insn ("xgdy", operands);
03971 output_asm_insn ("ldab\t%b1", operands);
03972 output_asm_insn ("xgdy", operands);
03973 }
03974 else
03975 {
03976 output_asm_insn ("pshb", operands);
03977 output_asm_insn ("ldab\t%b1", operands);
03978 output_asm_insn ("stab\t%T1", operands);
03979 output_asm_insn ("ldy\t%t1", operands);
03980 output_asm_insn ("pulb", operands);
03981 CC_STATUS_INIT;
03982 }
03983 break;
03984
03985 default:
03986 fatal_insn ("invalid register in the instruction", insn);
03987 break;
03988 }
03989 }
03990 else if (H_REG_P (operands[1]))
03991 {
03992 switch (REGNO (operands[1]))
03993 {
03994 case HARD_D_REGNUM:
03995 case HARD_B_REGNUM:
03996 output_asm_insn ("stab\t%b0", operands);
03997 break;
03998
03999 case HARD_A_REGNUM:
04000 output_asm_insn ("staa\t%b0", operands);
04001 break;
04002
04003 case HARD_X_REGNUM:
04004 output_asm_insn ("xgdx\n\tstab\t%b0\n\txgdx", operands);
04005 break;
04006
04007 case HARD_Y_REGNUM:
04008 output_asm_insn ("xgdy\n\tstab\t%b0\n\txgdy", operands);
04009 break;
04010
04011 default:
04012 fatal_insn ("invalid register in the move instruction", insn);
04013 break;
04014 }
04015 return;
04016 }
04017 else
04018 {
04019 fatal_insn ("operand 1 must be a hard register", insn);
04020 }
04021 }
04022
04023
04024
04025
04026 void
04027 m68hc11_gen_rotate (enum rtx_code code, rtx insn, rtx operands[])
04028 {
04029 int val;
04030
04031 if (GET_CODE (operands[2]) != CONST_INT
04032 || (!D_REG_P (operands[0]) && !DA_REG_P (operands[0])))
04033 fatal_insn ("invalid rotate insn", insn);
04034
04035 val = INTVAL (operands[2]);
04036 if (code == ROTATERT)
04037 val = GET_MODE_SIZE (GET_MODE (operands[0])) * BITS_PER_UNIT - val;
04038
04039 if (GET_MODE (operands[0]) != QImode)
04040 CC_STATUS_INIT;
04041
04042
04043 if (val >= 5 && val <= 11)
04044 {
04045 if (TARGET_M6812)
04046 output_asm_insn ("exg\ta,b", operands);
04047 else
04048 {
04049 output_asm_insn ("psha", operands);
04050 output_asm_insn ("tba", operands);
04051 output_asm_insn ("pulb", operands);
04052 }
04053 val -= 8;
04054 }
04055
04056
04057 else if (val >= 12)
04058 {
04059 val = val - 16;
04060 }
04061
04062 if (val > 0)
04063 {
04064 while (--val >= 0)
04065 {
04066
04067 if (GET_MODE (operands[0]) != QImode)
04068 {
04069 output_asm_insn ("asra", operands);
04070 output_asm_insn ("rola", operands);
04071 }
04072
04073
04074 if (D_REG_P (operands[0]))
04075 output_asm_insn ("rolb", operands);
04076
04077 if (GET_MODE (operands[0]) != QImode || DA_REG_P (operands[0]))
04078 output_asm_insn ("rola", operands);
04079 }
04080 }
04081 else
04082 {
04083 while (++val <= 0)
04084 {
04085
04086 if (GET_MODE (operands[0]) != QImode)
04087 output_asm_insn ("tap", operands);
04088
04089
04090 if (D_REG_P (operands[0]))
04091 output_asm_insn ("rorb", operands);
04092
04093 if (GET_MODE (operands[0]) != QImode || DA_REG_P (operands[0]))
04094 output_asm_insn ("rora", operands);
04095 }
04096 }
04097 }
04098
04099
04100
04101
04102
04103
04104
04105 void
04106 m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
04107 {
04108
04109 if (GET_CODE (exp) == SET)
04110 {
04111
04112 if (SET_DEST (exp) == pc_rtx)
04113 ;
04114
04115
04116
04117
04118
04119
04120 else if (GET_CODE (SET_SRC (exp)) == CALL)
04121 {
04122 CC_STATUS_INIT;
04123 }
04124
04125
04126 else if (SET_DEST (exp) == cc0_rtx)
04127 {
04128 cc_status.flags = 0;
04129 cc_status.value1 = XEXP (exp, 0);
04130 cc_status.value2 = XEXP (exp, 1);
04131 }
04132 else
04133 {
04134
04135 cc_status.flags = 0;
04136 cc_status.value1 = XEXP (exp, 0);
04137 cc_status.value2 = XEXP (exp, 1);
04138 }
04139 }
04140 else
04141 {
04142
04143
04144 CC_STATUS_INIT;
04145 }
04146
04147 if (cc_status.value2 != 0)
04148 switch (GET_CODE (cc_status.value2))
04149 {
04150
04151
04152 case IOR:
04153 case XOR:
04154 case AND:
04155 break;
04156
04157
04158
04159 case NOT:
04160 if (GET_MODE (cc_status.value2) != QImode)
04161 CC_STATUS_INIT;
04162 break;
04163
04164 case PLUS:
04165 case MINUS:
04166 case MULT:
04167 case DIV:
04168 case UDIV:
04169 case MOD:
04170 case UMOD:
04171 case NEG:
04172 if (GET_MODE (cc_status.value2) != VOIDmode)
04173 cc_status.flags |= CC_NO_OVERFLOW;
04174 break;
04175
04176
04177
04178 case ASHIFT:
04179 case ROTATE:
04180 case ROTATERT:
04181 if (GET_MODE (cc_status.value2) != VOIDmode)
04182 cc_status.flags |= CC_NO_OVERFLOW;
04183 break;
04184
04185
04186 case MEM:
04187 case SYMBOL_REF:
04188 case REG:
04189 case CONST_INT:
04190 cc_status.flags |= CC_NO_OVERFLOW;
04191 break;
04192
04193 default:
04194 break;
04195 }
04196 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
04197 && cc_status.value2
04198 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
04199 cc_status.value2 = 0;
04200
04201 else if (cc_status.value1 && side_effects_p (cc_status.value1))
04202 cc_status.value1 = 0;
04203
04204 else if (cc_status.value2 && side_effects_p (cc_status.value2))
04205 cc_status.value2 = 0;
04206 }
04207
04208
04209
04210
04211 void
04212 m68hc11_notice_keep_cc (rtx reg)
04213 {
04214 if (reg == 0
04215 || cc_prev_status.value1 == 0
04216 || rtx_equal_p (reg, cc_prev_status.value1)
04217 || (cc_prev_status.value2
04218 && reg_mentioned_p (reg, cc_prev_status.value2)))
04219 CC_STATUS_INIT;
04220 else
04221 cc_status = cc_prev_status;
04222 }
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265 struct replace_info
04266 {
04267 rtx first;
04268 rtx replace_reg;
04269 int need_save_z;
04270 int must_load_z;
04271 int must_save_reg;
04272 int must_restore_reg;
04273 rtx last;
04274 int regno;
04275 int x_used;
04276 int y_used;
04277 int can_use_d;
04278 int found_call;
04279 int z_died;
04280 int z_set_count;
04281 rtx z_value;
04282 int must_push_reg;
04283 int save_before_last;
04284 int z_loaded_with_sp;
04285 };
04286
04287 static int m68hc11_check_z_replacement (rtx, struct replace_info *);
04288 static void m68hc11_find_z_replacement (rtx, struct replace_info *);
04289 static void m68hc11_z_replacement (rtx);
04290 static void m68hc11_reassign_regs (rtx);
04291
04292 int z_replacement_completed = 0;
04293
04294
04295
04296
04297
04298
04299 static int
04300 m68hc11_check_z_replacement (rtx insn, struct replace_info *info)
04301 {
04302 int this_insn_uses_ix;
04303 int this_insn_uses_iy;
04304 int this_insn_uses_z;
04305 int this_insn_uses_z_in_dst;
04306 int this_insn_uses_d;
04307 rtx body;
04308 int z_dies_here;
04309
04310
04311
04312
04313 if (GET_CODE (insn) == CALL_INSN)
04314 {
04315 body = PATTERN (insn);
04316
04317 info->can_use_d = 0;
04318
04319
04320
04321
04322 if (reg_mentioned_p (z_reg, body))
04323 {
04324 insn = NEXT_INSN (insn);
04325 info->x_used = 1;
04326 info->y_used = 0;
04327 info->found_call = 1;
04328 info->must_restore_reg = 0;
04329 info->last = NEXT_INSN (insn);
04330 }
04331 info->need_save_z = 0;
04332 return 0;
04333 }
04334 if (GET_CODE (insn) == CODE_LABEL
04335 || GET_CODE (insn) == BARRIER || GET_CODE (insn) == ASM_INPUT)
04336 return 0;
04337
04338 if (GET_CODE (insn) == JUMP_INSN)
04339 {
04340 if (reg_mentioned_p (z_reg, insn) == 0)
04341 return 0;
04342
04343 info->can_use_d = 0;
04344 info->must_save_reg = 0;
04345 info->must_restore_reg = 0;
04346 info->need_save_z = 0;
04347 info->last = NEXT_INSN (insn);
04348 return 0;
04349 }
04350 if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
04351 {
04352 return 1;
04353 }
04354
04355
04356 z_dies_here = find_regno_note (insn, REG_DEAD, HARD_Z_REGNUM) != NULL;
04357
04358 body = PATTERN (insn);
04359 if (GET_CODE (body) == SET)
04360 {
04361 rtx src = XEXP (body, 1);
04362 rtx dst = XEXP (body, 0);
04363
04364
04365
04366
04367
04368
04369 if (dst == cc0_rtx)
04370 {
04371 if ((GET_CODE (src) == REG && REGNO (src) == HARD_Z_REGNUM)
04372 || (GET_CODE (src) == COMPARE &&
04373 ((rtx_equal_p (XEXP (src, 0), z_reg)
04374 && H_REG_P (XEXP (src, 1)))
04375 || (rtx_equal_p (XEXP (src, 1), z_reg)
04376 && H_REG_P (XEXP (src, 0))))))
04377 {
04378 if (insn == info->first)
04379 {
04380 info->must_load_z = 0;
04381 info->must_save_reg = 0;
04382 info->must_restore_reg = 0;
04383 info->need_save_z = 0;
04384 info->found_call = 1;
04385 info->regno = SOFT_Z_REGNUM;
04386 info->last = NEXT_INSN (insn);
04387 }
04388 return 0;
04389 }
04390 if (reg_mentioned_p (z_reg, src) == 0)
04391 {
04392 info->can_use_d = 0;
04393 return 0;
04394 }
04395
04396 if (insn != info->first)
04397 return 0;
04398
04399
04400
04401
04402 info->must_push_reg = 1;
04403 info->last = insn;
04404 }
04405
04406
04407 if (Z_REG_P (dst))
04408 {
04409 if (!reg_mentioned_p (z_reg, src))
04410 {
04411
04412
04413 if (insn != info->first)
04414 {
04415 return 0;
04416 }
04417 info->must_load_z = 0;
04418 }
04419 info->z_set_count++;
04420 info->z_value = src;
04421 if (SP_REG_P (src))
04422 info->z_loaded_with_sp = 1;
04423 }
04424 else if (reg_mentioned_p (z_reg, dst))
04425 info->can_use_d = 0;
04426
04427 this_insn_uses_d = reg_mentioned_p (d_reg, src)
04428 | reg_mentioned_p (d_reg, dst);
04429 this_insn_uses_ix = reg_mentioned_p (ix_reg, src)
04430 | reg_mentioned_p (ix_reg, dst);
04431 this_insn_uses_iy = reg_mentioned_p (iy_reg, src)
04432 | reg_mentioned_p (iy_reg, dst);
04433 this_insn_uses_z = reg_mentioned_p (z_reg, src);
04434
04435
04436
04437 if (this_insn_uses_z && !Z_REG_P (src)
04438 && !(m68hc11_arith_operator (src, GET_MODE (src))
04439 && Z_REG_P (XEXP (src, 0))
04440 && !reg_mentioned_p (z_reg, XEXP (src, 1))
04441 && insn == info->first
04442 && dead_register_here (insn, d_reg)))
04443 info->can_use_d = 0;
04444
04445 this_insn_uses_z_in_dst = reg_mentioned_p (z_reg, dst);
04446 if (TARGET_M6812 && !z_dies_here
04447 && ((this_insn_uses_z && side_effects_p (src))
04448 || (this_insn_uses_z_in_dst && side_effects_p (dst))))
04449 {
04450 info->need_save_z = 1;
04451 info->z_set_count++;
04452 }
04453 this_insn_uses_z |= this_insn_uses_z_in_dst;
04454
04455 if (this_insn_uses_z && this_insn_uses_ix && this_insn_uses_iy)
04456 {
04457 fatal_insn ("registers IX, IY and Z used in the same INSN", insn);
04458 }
04459
04460 if (this_insn_uses_d)
04461 info->can_use_d = 0;
04462
04463
04464
04465 if (this_insn_uses_ix && this_insn_uses_iy)
04466 {
04467 return 0;
04468 }
04469
04470 if (this_insn_uses_ix && X_REG_P (dst) && GET_MODE (dst) == SImode)
04471 info->can_use_d = 0;
04472
04473 if (info->x_used == 0 && this_insn_uses_ix)
04474 {
04475 if (info->y_used)
04476 {
04477
04478
04479
04480
04481 if (X_REG_P (dst) && rtx_equal_p (src, z_reg))
04482 {
04483 if (z_dies_here)
04484 {
04485 info->need_save_z = 0;
04486 info->z_died = 1;
04487 }
04488 info->must_save_reg = 0;
04489 info->must_restore_reg = 0;
04490 info->found_call = 1;
04491 info->can_use_d = 0;
04492 PUT_CODE (insn, NOTE);
04493 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
04494 NOTE_SOURCE_FILE (insn) = 0;
04495 info->last = NEXT_INSN (insn);
04496 return 0;
04497 }
04498
04499 if (X_REG_P (dst)
04500 && (rtx_equal_p (src, z_reg)
04501 || (z_dies_here && !reg_mentioned_p (ix_reg, src))))
04502 {
04503 if (z_dies_here)
04504 {
04505 info->need_save_z = 0;
04506 info->z_died = 1;
04507 }
04508 info->last = NEXT_INSN (insn);
04509 info->must_save_reg = 0;
04510 info->must_restore_reg = 0;
04511 }
04512 else if (X_REG_P (dst) && reg_mentioned_p (z_reg, src)
04513 && !reg_mentioned_p (ix_reg, src))
04514 {
04515 if (z_dies_here)
04516 {
04517 info->z_died = 1;
04518 info->need_save_z = 0;
04519 }
04520 else if (TARGET_M6812 && side_effects_p (src))
04521 {
04522 info->last = 0;
04523 info->must_restore_reg = 0;
04524 return 0;
04525 }
04526 else
04527 {
04528 info->save_before_last = 1;
04529 }
04530 info->must_restore_reg = 0;
04531 info->last = NEXT_INSN (insn);
04532 }
04533 else if (info->can_use_d)
04534 {
04535 info->last = NEXT_INSN (insn);
04536 info->x_used = 1;
04537 }
04538 return 0;
04539 }
04540 info->x_used = 1;
04541 if (z_dies_here && !reg_mentioned_p (ix_reg, src)
04542 && GET_CODE (dst) == REG && REGNO (dst) == HARD_X_REGNUM)
04543 {
04544 info->need_save_z = 0;
04545 info->z_died = 1;
04546 info->last = NEXT_INSN (insn);
04547 info->regno = HARD_X_REGNUM;
04548 info->must_save_reg = 0;
04549 info->must_restore_reg = 0;
04550 return 0;
04551 }
04552 if (rtx_equal_p (src, z_reg) && rtx_equal_p (dst, ix_reg))
04553 {
04554 info->regno = HARD_X_REGNUM;
04555 info->must_restore_reg = 0;
04556 info->must_save_reg = 0;
04557 return 0;
04558 }
04559 }
04560 if (info->y_used == 0 && this_insn_uses_iy)
04561 {
04562 if (info->x_used)
04563 {
04564 if (Y_REG_P (dst) && rtx_equal_p (src, z_reg))
04565 {
04566 if (z_dies_here)
04567 {
04568 info->need_save_z = 0;
04569 info->z_died = 1;
04570 }
04571 info->must_save_reg = 0;
04572 info->must_restore_reg = 0;
04573 info->found_call = 1;
04574 info->can_use_d = 0;
04575 PUT_CODE (insn, NOTE);
04576 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
04577 NOTE_SOURCE_FILE (insn) = 0;
04578 info->last = NEXT_INSN (insn);
04579 return 0;
04580 }
04581
04582 if (Y_REG_P (dst)
04583 && (rtx_equal_p (src, z_reg)
04584 || (z_dies_here && !reg_mentioned_p (iy_reg, src))))
04585 {
04586 if (z_dies_here)
04587 {
04588 info->z_died = 1;
04589 info->need_save_z = 0;
04590 }
04591 info->last = NEXT_INSN (insn);
04592 info->must_save_reg = 0;
04593 info->must_restore_reg = 0;
04594 }
04595 else if (Y_REG_P (dst) && reg_mentioned_p (z_reg, src)
04596 && !reg_mentioned_p (iy_reg, src))
04597 {
04598 if (z_dies_here)
04599 {
04600 info->z_died = 1;
04601 info->need_save_z = 0;
04602 }
04603 else if (TARGET_M6812 && side_effects_p (src))
04604 {
04605 info->last = 0;
04606 info->must_restore_reg = 0;
04607 return 0;
04608 }
04609 else
04610 {
04611 info->save_before_last = 1;
04612 }
04613 info->must_restore_reg = 0;
04614 info->last = NEXT_INSN (insn);
04615 }
04616 else if (info->can_use_d)
04617 {
04618 info->last = NEXT_INSN (insn);
04619 info->y_used = 1;
04620 }
04621
04622 return 0;
04623 }
04624 info->y_used = 1;
04625 if (z_dies_here && !reg_mentioned_p (iy_reg, src)
04626 && GET_CODE (dst) == REG && REGNO (dst) == HARD_Y_REGNUM)
04627 {
04628 info->need_save_z = 0;
04629 info->z_died = 1;
04630 info->last = NEXT_INSN (insn);
04631 info->regno = HARD_Y_REGNUM;
04632 info->must_save_reg = 0;
04633 info->must_restore_reg = 0;
04634 return 0;
04635 }
04636 if (rtx_equal_p (src, z_reg) && rtx_equal_p (dst, iy_reg))
04637 {
04638 info->regno = HARD_Y_REGNUM;
04639 info->must_restore_reg = 0;
04640 info->must_save_reg = 0;
04641 return 0;
04642 }
04643 }
04644 if (z_dies_here)
04645 {
04646 info->need_save_z = 0;
04647 info->z_died = 1;
04648 if (info->last == 0)
04649 info->last = NEXT_INSN (insn);
04650 return 0;
04651 }
04652 return info->last != NULL_RTX ? 0 : 1;
04653 }
04654 if (GET_CODE (body) == PARALLEL)
04655 {
04656 int i;
04657 char ix_clobber = 0;
04658 char iy_clobber = 0;
04659 char z_clobber = 0;
04660 this_insn_uses_iy = 0;
04661 this_insn_uses_ix = 0;
04662 this_insn_uses_z = 0;
04663
04664 for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
04665 {
04666 rtx x;
04667 int uses_ix, uses_iy, uses_z;
04668
04669 x = XVECEXP (body, 0, i);
04670
04671 if (info->can_use_d && reg_mentioned_p (d_reg, x))
04672 info->can_use_d = 0;
04673
04674 uses_ix = reg_mentioned_p (ix_reg, x);
04675 uses_iy = reg_mentioned_p (iy_reg, x);
04676 uses_z = reg_mentioned_p (z_reg, x);
04677 if (GET_CODE (x) == CLOBBER)
04678 {
04679 ix_clobber |= uses_ix;
04680 iy_clobber |= uses_iy;
04681 z_clobber |= uses_z;
04682 }
04683 else
04684 {
04685 this_insn_uses_ix |= uses_ix;
04686 this_insn_uses_iy |= uses_iy;
04687 this_insn_uses_z |= uses_z;
04688 }
04689 if (uses_z && GET_CODE (x) == SET)
04690 {
04691 rtx dst = XEXP (x, 0);
04692
04693 if (Z_REG_P (dst))
04694 info->z_set_count++;
04695 }
04696 if (TARGET_M6812 && uses_z && side_effects_p (x))
04697 info->need_save_z = 1;
04698
04699 if (z_clobber)
04700 info->need_save_z = 0;
04701 }
04702 if (debug_m6811)
04703 {
04704 printf ("Uses X:%d Y:%d Z:%d CX:%d CY:%d CZ:%d\n",
04705 this_insn_uses_ix, this_insn_uses_iy,
04706 this_insn_uses_z, ix_clobber, iy_clobber, z_clobber);
04707 debug_rtx (insn);
04708 }
04709 if (this_insn_uses_z)
04710 info->can_use_d = 0;
04711
04712 if (z_clobber && info->first != insn)
04713 {
04714 info->need_save_z = 0;
04715 info->last = insn;
04716 return 0;
04717 }
04718 if (z_clobber && info->x_used == 0 && info->y_used == 0)
04719 {
04720 if (this_insn_uses_z == 0 && insn == info->first)
04721 {
04722 info->must_load_z = 0;
04723 }
04724 if (dead_register_here (insn, d_reg))
04725 {
04726 info->regno = HARD_D_REGNUM;
04727 info->must_save_reg = 0;
04728 info->must_restore_reg = 0;
04729 }
04730 else if (dead_register_here (insn, ix_reg))
04731 {
04732 info->regno = HARD_X_REGNUM;
04733 info->must_save_reg = 0;
04734 info->must_restore_reg = 0;
04735 }
04736 else if (dead_register_here (insn, iy_reg))
04737 {
04738 info->regno = HARD_Y_REGNUM;
04739 info->must_save_reg = 0;
04740 info->must_restore_reg = 0;
04741 }
04742 if (info->regno >= 0)
04743 {
04744 info->last = NEXT_INSN (insn);
04745 return 0;
04746 }
04747 if (this_insn_uses_ix == 0)
04748 {
04749 info->regno = HARD_X_REGNUM;
04750 info->must_save_reg = 1;
04751 info->must_restore_reg = 1;
04752 }
04753 else if (this_insn_uses_iy == 0)
04754 {
04755 info->regno = HARD_Y_REGNUM;
04756 info->must_save_reg = 1;
04757 info->must_restore_reg = 1;
04758 }
04759 else
04760 {
04761 info->regno = HARD_D_REGNUM;
04762 info->must_save_reg = 1;
04763 info->must_restore_reg = 1;
04764 }
04765 info->last = NEXT_INSN (insn);
04766 return 0;
04767 }
04768
04769 if (((info->x_used || this_insn_uses_ix) && iy_clobber)
04770 || ((info->y_used || this_insn_uses_iy) && ix_clobber))
04771 {
04772 if (this_insn_uses_z)
04773 {
04774 if (info->y_used == 0 && iy_clobber)
04775 {
04776 info->regno = HARD_Y_REGNUM;
04777 info->must_save_reg = 0;
04778 info->must_restore_reg = 0;
04779 }
04780 if (info->first != insn
04781 && ((info->y_used && ix_clobber)
04782 || (info->x_used && iy_clobber)))
04783 info->last = insn;
04784 else
04785 info->last = NEXT_INSN (insn);
04786 info->save_before_last = 1;
04787 }
04788 return 0;
04789 }
04790 if (this_insn_uses_ix && this_insn_uses_iy)
04791 {
04792 if (this_insn_uses_z)
04793 {
04794 fatal_insn ("cannot do z-register replacement", insn);
04795 }
04796 return 0;
04797 }
04798 if (info->x_used == 0 && (this_insn_uses_ix || ix_clobber))
04799 {
04800 if (info->y_used)
04801 {
04802 return 0;
04803 }
04804 info->x_used = 1;
04805 if (iy_clobber || z_clobber)
04806 {
04807 info->last = NEXT_INSN (insn);
04808 info->save_before_last = 1;
04809 return 0;
04810 }
04811 }
04812
04813 if (info->y_used == 0 && (this_insn_uses_iy || iy_clobber))
04814 {
04815 if (info->x_used)
04816 {
04817 return 0;
04818 }
04819 info->y_used = 1;
04820 if (ix_clobber || z_clobber)
04821 {
04822 info->last = NEXT_INSN (insn);
04823 info->save_before_last = 1;
04824 return 0;
04825 }
04826 }
04827 if (z_dies_here)
04828 {
04829 info->z_died = 1;
04830 info->need_save_z = 0;
04831 }
04832 return 1;
04833 }
04834 if (GET_CODE (body) == CLOBBER)
04835 {
04836
04837
04838
04839 if (this_insn_uses_ix && this_insn_uses_iy)
04840 {
04841 return 0;
04842 }
04843 if (info->x_used == 0 && this_insn_uses_ix)
04844 {
04845 if (info->y_used)
04846 {
04847 return 0;
04848 }
04849 info->x_used = 1;
04850 }
04851 if (info->y_used == 0 && this_insn_uses_iy)
04852 {
04853 if (info->x_used)
04854 {
04855 return 0;
04856 }
04857 info->y_used = 1;
04858 }
04859 return 1;
04860 }
04861 return 1;
04862 }
04863
04864 static void
04865 m68hc11_find_z_replacement (rtx insn, struct replace_info *info)
04866 {
04867 int reg;
04868
04869 info->replace_reg = NULL_RTX;
04870 info->must_load_z = 1;
04871 info->need_save_z = 1;
04872 info->must_save_reg = 1;
04873 info->must_restore_reg = 1;
04874 info->first = insn;
04875 info->x_used = 0;
04876 info->y_used = 0;
04877 info->can_use_d = TARGET_M6811 ? 1 : 0;
04878 info->found_call = 0;
04879 info->z_died = 0;
04880 info->last = 0;
04881 info->regno = -1;
04882 info->z_set_count = 0;
04883 info->z_value = NULL_RTX;
04884 info->must_push_reg = 0;
04885 info->save_before_last = 0;
04886 info->z_loaded_with_sp = 0;
04887
04888
04889
04890
04891
04892
04893
04894
04895 for (; insn && info->z_died == 0; insn = NEXT_INSN (insn))
04896 {
04897 if (m68hc11_check_z_replacement (insn, info) == 0)
04898 break;
04899 }
04900
04901
04902
04903 if (info->z_set_count == 1)
04904 {
04905 rtx p = info->first;
04906 rtx v = 0;
04907
04908 if (info->x_used)
04909 {
04910 v = find_last_value (iy_reg, &p, insn, 1);
04911 }
04912 else if (info->y_used)
04913 {
04914 v = find_last_value (ix_reg, &p, insn, 1);
04915 }
04916 if (v && (v != iy_reg && v != ix_reg) && rtx_equal_p (v, info->z_value))
04917 {
04918 if (info->x_used)
04919 info->regno = HARD_Y_REGNUM;
04920 else
04921 info->regno = HARD_X_REGNUM;
04922 info->must_load_z = 0;
04923 info->must_save_reg = 0;
04924 info->must_restore_reg = 0;
04925 info->found_call = 1;
04926 }
04927 }
04928 if (info->z_set_count == 0)
04929 info->need_save_z = 0;
04930
04931 if (insn == 0)
04932 info->need_save_z = 0;
04933
04934 if (info->last == 0)
04935 info->last = insn;
04936
04937 if (info->regno >= 0)
04938 {
04939 reg = info->regno;
04940 info->replace_reg = gen_rtx_REG (HImode, reg);
04941 }
04942 else if (info->can_use_d)
04943 {
04944 reg = HARD_D_REGNUM;
04945 info->replace_reg = d_reg;
04946 }
04947 else if (info->x_used)
04948 {
04949 reg = HARD_Y_REGNUM;
04950 info->replace_reg = iy_reg;
04951 }
04952 else
04953 {
04954 reg = HARD_X_REGNUM;
04955 info->replace_reg = ix_reg;
04956 }
04957 info->regno = reg;
04958
04959 if (info->must_save_reg && info->must_restore_reg)
04960 {
04961 if (insn && dead_register_here (insn, info->replace_reg))
04962 {
04963 info->must_save_reg = 0;
04964 info->must_restore_reg = 0;
04965 }
04966 }
04967 }
04968
04969
04970
04971
04972
04973
04974
04975 static void
04976 m68hc11_z_replacement (rtx insn)
04977 {
04978 rtx replace_reg_qi;
04979 rtx replace_reg;
04980 struct replace_info info;
04981
04982
04983
04984 if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET)
04985 {
04986 rtx body = PATTERN (insn);
04987 rtx src = XEXP (body, 1);
04988 rtx dst = XEXP (body, 0);
04989
04990 if (Z_REG_P (dst) && (H_REG_P (src) && !SP_REG_P (src)))
04991 {
04992 XEXP (body, 0) = gen_rtx_REG (GET_MODE (dst), SOFT_Z_REGNUM);
04993 return;
04994 }
04995 else if (Z_REG_P (src)
04996 && ((H_REG_P (dst) && !SP_REG_P (src)) || dst == cc0_rtx))
04997 {
04998 XEXP (body, 1) = gen_rtx_REG (GET_MODE (src), SOFT_Z_REGNUM);
04999 return;
05000 }
05001 else if (D_REG_P (dst)
05002 && m68hc11_arith_operator (src, GET_MODE (src))
05003 && D_REG_P (XEXP (src, 0)) && Z_REG_P (XEXP (src, 1)))
05004 {
05005 XEXP (src, 1) = gen_rtx_REG (GET_MODE (src), SOFT_Z_REGNUM);
05006 return;
05007 }
05008 else if (Z_REG_P (dst) && GET_CODE (src) == CONST_INT
05009 && INTVAL (src) == 0)
05010 {
05011 XEXP (body, 0) = gen_rtx_REG (GET_MODE (dst), SOFT_Z_REGNUM);
05012
05013 INSN_CODE (insn) = -1;
05014 return;
05015 }
05016 }
05017
05018 m68hc11_find_z_replacement (insn, &info);
05019
05020 replace_reg = info.replace_reg;
05021 replace_reg_qi = NULL_RTX;
05022
05023
05024 if (info.must_save_reg && !info.must_push_reg)
05025 {
05026 rtx dst;
05027
05028 if (info.must_push_reg && 0)
05029 dst = gen_rtx_MEM (HImode,
05030 gen_rtx_PRE_DEC (HImode,
05031 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
05032 else
05033 dst = gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM);
05034
05035 emit_insn_before (gen_movhi (dst,
05036 gen_rtx_REG (HImode, info.regno)), insn);
05037 }
05038 if (info.must_load_z && !info.must_push_reg)
05039 {
05040 emit_insn_before (gen_movhi (gen_rtx_REG (HImode, info.regno),
05041 gen_rtx_REG (HImode, SOFT_Z_REGNUM)),
05042 insn);
05043 }
05044
05045
05046
05047
05048
05049
05050
05051 for (; insn && insn != info.last; insn = NEXT_INSN (insn))
05052 {
05053 rtx body;
05054
05055 if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
05056 break;
05057
05058 if (GET_CODE (insn) != INSN
05059 && GET_CODE (insn) != CALL_INSN && GET_CODE (insn) != JUMP_INSN)
05060 continue;
05061
05062 body = PATTERN (insn);
05063 if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
05064 || GET_CODE (body) == ASM_OPERANDS
05065 || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
05066 {
05067 rtx note;
05068
05069 if (debug_m6811 && reg_mentioned_p (replace_reg, body))
05070 {
05071 printf ("Reg mentioned here...:\n");
05072 fflush (stdout);
05073 debug_rtx (insn);
05074 }
05075
05076
05077
05078 if (info.must_push_reg
05079 && info.z_loaded_with_sp && GET_CODE (body) == SET)
05080 {
05081 rtx src, dst;
05082
05083 src = SET_SRC (body);
05084 dst = SET_DEST (body);
05085 if (SP_REG_P (src) && Z_REG_P (dst))
05086 emit_insn_after (gen_addhi3 (dst, dst, const2_rtx), insn);
05087 }
05088
05089
05090 if (!validate_replace_rtx (z_reg, replace_reg, insn))
05091 {
05092 INSN_CODE (insn) = -1;
05093 if (!validate_replace_rtx (z_reg, replace_reg, insn))
05094 fatal_insn ("cannot do z-register replacement", insn);
05095 }
05096
05097
05098 if (reg_mentioned_p (z_reg, insn))
05099 {
05100 if (replace_reg_qi == NULL_RTX)
05101 replace_reg_qi = gen_rtx_REG (QImode, REGNO (replace_reg));
05102 validate_replace_rtx (z_reg_qi, replace_reg_qi, insn);
05103 }
05104
05105
05106
05107
05108
05109 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
05110 {
05111 if (REG_NOTE_KIND (note) == REG_INC
05112 && GET_CODE (XEXP (note, 0)) == REG
05113 && REGNO (XEXP (note, 0)) == REGNO (z_reg))
05114 {
05115 XEXP (note, 0) = replace_reg;
05116 }
05117 }
05118 }
05119 if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
05120 break;
05121 }
05122
05123
05124 if (insn && info.need_save_z && !info.must_push_reg)
05125 {
05126 rtx save_pos_insn = insn;
05127
05128
05129
05130 if (info.save_before_last)
05131 save_pos_insn = PREV_INSN (save_pos_insn);
05132
05133
05134
05135 emit_insn_after (gen_movhi (gen_rtx_REG (HImode, SOFT_Z_REGNUM),
05136 gen_rtx_REG (HImode, info.regno)),
05137 PREV_INSN (save_pos_insn));
05138 }
05139
05140 if (info.must_push_reg && info.last)
05141 {
05142 rtx new_body, body;
05143
05144 body = PATTERN (info.last);
05145 new_body = gen_rtx_PARALLEL (VOIDmode,
05146 gen_rtvec (3, body,
05147 gen_rtx_USE (VOIDmode,
05148 replace_reg),
05149 gen_rtx_USE (VOIDmode,
05150 gen_rtx_REG (HImode,
05151 SOFT_Z_REGNUM))));
05152 PATTERN (info.last) = new_body;
05153
05154
05155 INSN_CODE (insn) = -1;
05156
05157 if (!validate_replace_rtx (z_reg, replace_reg, info.last))
05158 {
05159 fatal_insn ("invalid Z register replacement for insn", insn);
05160 }
05161 insn = NEXT_INSN (info.last);
05162 }
05163
05164
05165 if (insn && info.must_restore_reg && !info.must_push_reg)
05166 {
05167 rtx dst;
05168
05169 if (info.must_push_reg && 0)
05170 dst = gen_rtx_MEM (HImode,
05171 gen_rtx_POST_INC (HImode,
05172 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
05173 else
05174 dst = gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM);
05175
05176 emit_insn_after (gen_movhi (gen_rtx_REG (HImode, info.regno),
05177 dst), PREV_INSN (insn));
05178 }
05179
05180 }
05181
05182
05183
05184
05185
05186
05187 static void
05188 m68hc11_reassign_regs (rtx first)
05189 {
05190 rtx insn;
05191
05192 ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);
05193 iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);
05194 z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
05195 z_reg_qi = gen_rtx_REG (QImode, HARD_Z_REGNUM);
05196
05197
05198
05199
05200 for (insn = first; insn; insn = NEXT_INSN (insn))
05201 {
05202 rtx body;
05203
05204 if (GET_CODE (insn) == CODE_LABEL
05205 || GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER)
05206 continue;
05207
05208 if (!INSN_P (insn))
05209 continue;
05210
05211 body = PATTERN (insn);
05212 if (GET_CODE (body) == CLOBBER || GET_CODE (body) == USE)
05213 continue;
05214
05215 if (GET_CODE (body) == CONST_INT || GET_CODE (body) == ASM_INPUT
05216 || GET_CODE (body) == ASM_OPERANDS
05217 || GET_CODE (body) == UNSPEC || GET_CODE (body) == UNSPEC_VOLATILE)
05218 continue;
05219
05220 if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
05221 || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
05222 {
05223
05224
05225
05226
05227
05228 if (reg_mentioned_p (z_reg, body))
05229 {
05230 m68hc11_z_replacement (insn);
05231 }
05232 }
05233 else
05234 {
05235 printf ("insn not handled by Z replacement:\n");
05236 fflush (stdout);
05237 debug_rtx (insn);
05238 }
05239 }
05240 }
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251 static void
05252 m68hc11_reorg (void)
05253 {
05254 int split_done = 0;
05255 rtx insn, first;
05256
05257 z_replacement_completed = 0;
05258 z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
05259 first = get_insns ();
05260
05261
05262
05263 unshare_all_rtl_again (first);
05264
05265
05266
05267 split_all_insns_noflow ();
05268 split_done = 1;
05269
05270 z_replacement_completed = 1;
05271 m68hc11_reassign_regs (first);
05272
05273 if (optimize)
05274 compute_bb_for_insn ();
05275
05276
05277
05278 if (optimize > 0 && split_done)
05279 {
05280 reload_cse_regs (first);
05281 }
05282
05283
05284
05285 if (optimize)
05286 {
05287
05288
05289
05290
05291
05292 for (insn = first; insn; insn = NEXT_INSN (insn))
05293 {
05294 if (INSN_P (insn))
05295 {
05296 rtx *pnote;
05297
05298 pnote = ®_NOTES (insn);
05299 while (*pnote != 0)
05300 {
05301 if (REG_NOTE_KIND (*pnote) == REG_DEAD)
05302 *pnote = XEXP (*pnote, 1);
05303 else
05304 pnote = &XEXP (*pnote, 1);
05305 }
05306 }
05307 }
05308
05309 life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES);
05310 }
05311
05312 z_replacement_completed = 2;
05313
05314
05315
05316
05317 if (optimize > 0)
05318 split_all_insns_noflow ();
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328 {
05329 rtx insn;
05330
05331 for (insn = first; insn; insn = NEXT_INSN (insn))
05332 {
05333 rtx body;
05334
05335 if (INSN_DELETED_P (insn))
05336 continue;
05337 if (!INSN_P (insn))
05338 continue;
05339
05340
05341 body = PATTERN (insn);
05342 if (GET_CODE (body) == SET
05343 && rtx_equal_p (SET_SRC (body), SET_DEST (body)))
05344 {
05345 PUT_CODE (insn, NOTE);
05346 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
05347 NOTE_SOURCE_FILE (insn) = 0;
05348 continue;
05349 }
05350 }
05351 }
05352 }
05353
05354
05355
05356 static void
05357 m68hc11_init_libfuncs (void)
05358 {
05359 memcpy_libfunc = init_one_libfunc ("__memcpy");
05360 memcmp_libfunc = init_one_libfunc ("__memcmp");
05361 memset_libfunc = init_one_libfunc ("__memset");
05362 }
05363
05364
05365
05366
05367
05368
05369 int
05370 m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class class,
05371 int in ATTRIBUTE_UNUSED)
05372 {
05373 if (class <= H_REGS && class > NO_REGS)
05374 {
05375 if (GET_MODE_SIZE (mode) <= 2)
05376 return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
05377 else
05378 return COSTS_N_INSNS (2) + (reload_completed | reload_in_progress);
05379 }
05380 else
05381 {
05382 if (GET_MODE_SIZE (mode) <= 2)
05383 return COSTS_N_INSNS (3);
05384 else
05385 return COSTS_N_INSNS (4);
05386 }
05387 }
05388
05389
05390
05391
05392
05393
05394 int
05395 m68hc11_register_move_cost (enum machine_mode mode, enum reg_class from,
05396 enum reg_class to)
05397 {
05398
05399
05400 if (from < to)
05401 {
05402 enum reg_class tmp = to;
05403 to = from, from = tmp;
05404 }
05405 if (to >= S_REGS)
05406 return m68hc11_memory_move_cost (mode, S_REGS, 0);
05407 else if (from <= S_REGS)
05408 return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
05409 else
05410 return COSTS_N_INSNS (2);
05411 }
05412
05413
05414
05415
05416
05417 static int
05418 m68hc11_address_cost (rtx addr)
05419 {
05420 int cost = 4;
05421
05422 switch (GET_CODE (addr))
05423 {
05424 case REG:
05425
05426 if (REGNO (addr) < FIRST_PSEUDO_REGISTER)
05427 cost = 0;
05428 else
05429 cost = 1;
05430 break;
05431
05432 case SYMBOL_REF:
05433 cost = 8;
05434 break;
05435
05436 case LABEL_REF:
05437 case CONST:
05438 cost = 0;
05439 break;
05440
05441 case PLUS:
05442 {
05443 register rtx plus0 = XEXP (addr, 0);
05444 register rtx plus1 = XEXP (addr, 1);
05445
05446 if (GET_CODE (plus0) != REG)
05447 break;
05448
05449 switch (GET_CODE (plus1))
05450 {
05451 case CONST_INT:
05452 if (INTVAL (plus1) >= 2 * m68hc11_max_offset
05453 || INTVAL (plus1) < m68hc11_min_offset)
05454 cost = 3;
05455 else if (INTVAL (plus1) >= m68hc11_max_offset)
05456 cost = 2;
05457 else
05458 cost = 1;
05459 if (REGNO (plus0) < FIRST_PSEUDO_REGISTER)
05460 cost += 0;
05461 else
05462 cost += 1;
05463 break;
05464
05465 case SYMBOL_REF:
05466 cost = 8;
05467 break;
05468
05469 case CONST:
05470 case LABEL_REF:
05471 cost = 0;
05472 break;
05473
05474 default:
05475 break;
05476 }
05477 break;
05478 }
05479 case PRE_DEC:
05480 case PRE_INC:
05481 if (SP_REG_P (XEXP (addr, 0)))
05482 cost = 1;
05483 break;
05484
05485 default:
05486 break;
05487 }
05488 if (debug_m6811)
05489 {
05490 printf ("Address cost: %d for :", cost);
05491 fflush (stdout);
05492 debug_rtx (addr);
05493 }
05494
05495 return cost;
05496 }
05497
05498 static int
05499 m68hc11_shift_cost (enum machine_mode mode, rtx x, int shift)
05500 {
05501 int total;
05502
05503 total = rtx_cost (x, SET);
05504 if (mode == QImode)
05505 total += m68hc11_cost->shiftQI_const[shift % 8];
05506 else if (mode == HImode)
05507 total += m68hc11_cost->shiftHI_const[shift % 16];
05508 else if (shift == 8 || shift == 16 || shift == 32)
05509 total += m68hc11_cost->shiftHI_const[8];
05510 else if (shift != 0 && shift != 16 && shift != 32)
05511 {
05512 total += m68hc11_cost->shiftHI_const[1] * shift;
05513 }
05514
05515
05516 if (GET_MODE_SIZE (mode) > 2 && (shift % 16) != 0)
05517 total *= GET_MODE_SIZE (mode) / 2;
05518
05519
05520
05521 if (optimize_size && (shift % 8) != 0)
05522 total *= 2;
05523
05524 return total;
05525 }
05526
05527 static int
05528 m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
05529 enum rtx_code outer_code ATTRIBUTE_UNUSED)
05530 {
05531 enum machine_mode mode = GET_MODE (x);
05532 int extra_cost = 0;
05533 int total;
05534
05535 switch (code)
05536 {
05537 case ROTATE:
05538 case ROTATERT:
05539 case ASHIFT:
05540 case LSHIFTRT:
05541 case ASHIFTRT:
05542 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
05543 {
05544 return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1)));
05545 }
05546
05547 total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
05548 total += m68hc11_cost->shift_var;
05549 return total;
05550
05551 case AND:
05552 case XOR:
05553 case IOR:
05554 total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
05555 total += m68hc11_cost->logical;
05556
05557
05558 total *= GET_MODE_SIZE (mode);
05559 return total;
05560
05561 case MINUS:
05562 case PLUS:
05563 total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
05564 total += m68hc11_cost->add;
05565 if (GET_MODE_SIZE (mode) > 2)
05566 {
05567 total *= GET_MODE_SIZE (mode) / 2;
05568 }
05569 return total;
05570
05571 case UDIV:
05572 case DIV:
05573 case MOD:
05574 total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
05575 switch (mode)
05576 {
05577 case QImode:
05578 total += m68hc11_cost->divQI;
05579 break;
05580
05581 case HImode:
05582 total += m68hc11_cost->divHI;
05583 break;
05584
05585 case SImode:
05586 default:
05587 total += m68hc11_cost->divSI;
05588 break;
05589 }
05590 return total;
05591
05592 case MULT:
05593
05594 if (mode == HImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
05595 && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
05596 return m68hc11_cost->multQI
05597 + rtx_cost (XEXP (XEXP (x, 0), 0), code)
05598 + rtx_cost (XEXP (XEXP (x, 1), 0), code);
05599
05600
05601 if (TARGET_M6812 && mode == SImode
05602 && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
05603 && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
05604 return m68hc11_cost->multHI
05605 + rtx_cost (XEXP (XEXP (x, 0), 0), code)
05606 + rtx_cost (XEXP (XEXP (x, 1), 0), code);
05607
05608 total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
05609 switch (mode)
05610 {
05611 case QImode:
05612 total += m68hc11_cost->multQI;
05613 break;
05614
05615 case HImode:
05616 total += m68hc11_cost->multHI;
05617 break;
05618
05619 case SImode:
05620 default:
05621 total += m68hc11_cost->multSI;
05622 break;
05623 }
05624 return total;
05625
05626 case NEG:
05627 case SIGN_EXTEND:
05628 extra_cost = COSTS_N_INSNS (2);
05629
05630
05631 case NOT:
05632 case COMPARE:
05633 case ABS:
05634 case ZERO_EXTEND:
05635 total = extra_cost + rtx_cost (XEXP (x, 0), code);
05636 if (mode == QImode)
05637 {
05638 return total + COSTS_N_INSNS (1);
05639 }
05640 if (mode == HImode)
05641 {
05642 return total + COSTS_N_INSNS (2);
05643 }
05644 if (mode == SImode)
05645 {
05646 return total + COSTS_N_INSNS (4);
05647 }
05648 return total + COSTS_N_INSNS (8);
05649
05650 case IF_THEN_ELSE:
05651 if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
05652 return COSTS_N_INSNS (1);
05653
05654 return COSTS_N_INSNS (1);
05655
05656 default:
05657 return COSTS_N_INSNS (4);
05658 }
05659 }
05660
05661 static bool
05662 m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total)
05663 {
05664 switch (code)
05665 {
05666
05667
05668 case CONST_INT:
05669 case CONST:
05670 case LABEL_REF:
05671 case SYMBOL_REF:
05672 case CONST_DOUBLE:
05673
05674
05675
05676 if (outer_code == SET && x == const0_rtx)
05677
05678
05679 *total = 1 - reload_completed;
05680 else
05681 *total = 0;
05682 return true;
05683
05684 case ROTATE:
05685 case ROTATERT:
05686 case ASHIFT:
05687 case LSHIFTRT:
05688 case ASHIFTRT:
05689 case MINUS:
05690 case PLUS:
05691 case AND:
05692 case XOR:
05693 case IOR:
05694 case UDIV:
05695 case DIV:
05696 case MOD:
05697 case MULT:
05698 case NEG:
05699 case SIGN_EXTEND:
05700 case NOT:
05701 case COMPARE:
05702 case ZERO_EXTEND:
05703 case IF_THEN_ELSE:
05704 *total = m68hc11_rtx_costs_1 (x, code, outer_code);
05705 return true;
05706
05707 default:
05708 return false;
05709 }
05710 }
05711
05712
05713
05714
05715 static void
05716 m68hc11_file_start (void)
05717 {
05718 default_file_start ();
05719
05720 fprintf (asm_out_file, "\t.mode %s\n", TARGET_SHORT ? "mshort" : "mlong");
05721 }
05722
05723
05724
05725
05726 static void
05727 m68hc11_asm_out_constructor (rtx symbol, int priority)
05728 {
05729 default_ctor_section_asm_out_constructor (symbol, priority);
05730 fprintf (asm_out_file, "\t.globl\t__do_global_ctors\n");
05731 }
05732
05733
05734
05735 static void
05736 m68hc11_asm_out_destructor (rtx symbol, int priority)
05737 {
05738 default_dtor_section_asm_out_destructor (symbol, priority);
05739 fprintf (asm_out_file, "\t.globl\t__do_global_dtors\n");
05740 }
05741
05742
05743
05744 static rtx
05745 m68hc11_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
05746 int incoming ATTRIBUTE_UNUSED)
05747 {
05748 return gen_rtx_REG (Pmode, HARD_D_REGNUM);
05749 }
05750
05751
05752
05753
05754
05755 static bool
05756 m68hc11_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
05757 {
05758 if (TYPE_MODE (type) == BLKmode)
05759 {
05760 HOST_WIDE_INT size = int_size_in_bytes (type);
05761 return (size == -1 || size > 4);
05762 }
05763 else
05764 return GET_MODE_SIZE (TYPE_MODE (type)) > 4;
05765 }
05766
05767 #include "gt-m68hc11.h"