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