00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "tree.h"
00028 #include "rtl.h"
00029 #include "function.h"
00030 #include "regs.h"
00031 #include "hard-reg-set.h"
00032 #include "real.h"
00033 #include "insn-config.h"
00034 #include "conditions.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "recog.h"
00038 #include "toplev.h"
00039 #include "expr.h"
00040 #include "reload.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044 #include "debug.h"
00045 #include "flags.h"
00046
00047 enum reg_class regno_reg_class[] =
00048 {
00049 DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS,
00050 DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS,
00051 ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
00052 ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
00053 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00054 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00055 ADDR_REGS
00056 };
00057
00058
00059
00060
00061
00062 #if MOTOROLA
00063 # define ASM_DOT "."
00064 # define ASM_DOTW ".w"
00065 # define ASM_DOTL ".l"
00066 #else
00067 # define ASM_DOT ""
00068 # define ASM_DOTW ""
00069 # define ASM_DOTL ""
00070 #endif
00071
00072
00073
00074 struct m68k_frame
00075 {
00076
00077 HOST_WIDE_INT offset;
00078
00079
00080 HOST_WIDE_INT foffset;
00081
00082
00083 HOST_WIDE_INT size;
00084
00085
00086 int reg_no;
00087 unsigned int reg_mask;
00088 unsigned int reg_rev_mask;
00089
00090
00091 int fpu_no;
00092 unsigned int fpu_mask;
00093 unsigned int fpu_rev_mask;
00094
00095
00096 HOST_WIDE_INT frame_pointer_offset;
00097 HOST_WIDE_INT stack_pointer_offset;
00098
00099
00100 int funcdef_no;
00101 };
00102
00103
00104 static struct m68k_frame current_frame;
00105
00106 static rtx find_addr_reg (rtx);
00107 static const char *singlemove_string (rtx *);
00108 static void m68k_output_function_prologue (FILE *, HOST_WIDE_INT);
00109 static void m68k_output_function_epilogue (FILE *, HOST_WIDE_INT);
00110 #ifdef M68K_TARGET_COFF
00111 static void m68k_coff_asm_named_section (const char *, unsigned int, tree);
00112 #endif
00113 static void m68k_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
00114 HOST_WIDE_INT, tree);
00115 static rtx m68k_struct_value_rtx (tree, int);
00116 static bool m68k_interrupt_function_p (tree func);
00117 static tree m68k_handle_fndecl_attribute (tree *node, tree name,
00118 tree args, int flags,
00119 bool *no_add_attrs);
00120 static void m68k_compute_frame_layout (void);
00121 static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
00122 static int const_int_cost (rtx);
00123 static bool m68k_rtx_costs (rtx, int, int, int *);
00124
00125
00126
00127 const char *m68k_library_id_string;
00128
00129
00130
00131
00132 int m68k_last_compare_had_fp_operands;
00133
00134
00135
00136 #if INT_OP_GROUP == INT_OP_DOT_WORD
00137 #undef TARGET_ASM_ALIGNED_HI_OP
00138 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00139 #endif
00140
00141 #if INT_OP_GROUP == INT_OP_NO_DOT
00142 #undef TARGET_ASM_BYTE_OP
00143 #define TARGET_ASM_BYTE_OP "\tbyte\t"
00144 #undef TARGET_ASM_ALIGNED_HI_OP
00145 #define TARGET_ASM_ALIGNED_HI_OP "\tshort\t"
00146 #undef TARGET_ASM_ALIGNED_SI_OP
00147 #define TARGET_ASM_ALIGNED_SI_OP "\tlong\t"
00148 #endif
00149
00150 #if INT_OP_GROUP == INT_OP_DC
00151 #undef TARGET_ASM_BYTE_OP
00152 #define TARGET_ASM_BYTE_OP "\tdc.b\t"
00153 #undef TARGET_ASM_ALIGNED_HI_OP
00154 #define TARGET_ASM_ALIGNED_HI_OP "\tdc.w\t"
00155 #undef TARGET_ASM_ALIGNED_SI_OP
00156 #define TARGET_ASM_ALIGNED_SI_OP "\tdc.l\t"
00157 #endif
00158
00159 #undef TARGET_ASM_UNALIGNED_HI_OP
00160 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00161 #undef TARGET_ASM_UNALIGNED_SI_OP
00162 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00163
00164 #undef TARGET_ASM_FUNCTION_PROLOGUE
00165 #define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
00166 #undef TARGET_ASM_FUNCTION_EPILOGUE
00167 #define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
00168
00169 #undef TARGET_ASM_OUTPUT_MI_THUNK
00170 #define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
00171 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00172 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
00173
00174 #undef TARGET_ASM_FILE_START_APP_OFF
00175 #define TARGET_ASM_FILE_START_APP_OFF true
00176
00177 #undef TARGET_RTX_COSTS
00178 #define TARGET_RTX_COSTS m68k_rtx_costs
00179
00180 #undef TARGET_ATTRIBUTE_TABLE
00181 #define TARGET_ATTRIBUTE_TABLE m68k_attribute_table
00182
00183 #undef TARGET_PROMOTE_PROTOTYPES
00184 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00185
00186 #undef TARGET_STRUCT_VALUE_RTX
00187 #define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx
00188
00189 static const struct attribute_spec m68k_attribute_table[] =
00190 {
00191
00192 { "interrupt_handler", 0, 0, true, false, false, m68k_handle_fndecl_attribute },
00193 { NULL, 0, 0, false, false, false, NULL }
00194 };
00195
00196 struct gcc_target targetm = TARGET_INITIALIZER;
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void
00208 override_options (void)
00209 {
00210
00211 if (m68k_library_id_string)
00212 {
00213 int id;
00214
00215 if (! TARGET_ID_SHARED_LIBRARY)
00216 error ("-mshared-library-id= specified without -mid-shared-library");
00217 id = atoi (m68k_library_id_string);
00218 if (id < 0 || id > MAX_LIBRARY_ID)
00219 error ("-mshared-library-id=%d is not between 0 and %d", id, MAX_LIBRARY_ID);
00220
00221
00222 asprintf ((char **)&m68k_library_id_string, "%d", (id * -4) - 4);
00223 }
00224 else
00225
00226
00227 m68k_library_id_string = "_current_shared_library_a5_offset_";
00228
00229
00230
00231
00232 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
00233 error ("cannot specify both -msep-data and -mid-shared-library");
00234
00235
00236
00237
00238
00239 if (TARGET_SEP_DATA || TARGET_ID_SHARED_LIBRARY)
00240 flag_pic = 2;
00241
00242
00243
00244 if (!TARGET_68020 && !TARGET_COLDFIRE && (flag_pic == 2))
00245 error("-fPIC is not currently supported on the 68000 or 68010\n");
00246
00247
00248
00249
00250 if (TARGET_PCREL && flag_pic == 0)
00251 flag_pic = 1;
00252
00253
00254
00255
00256
00257
00258 if (flag_pic)
00259 flag_no_function_cse = 1;
00260
00261 SUBTARGET_OVERRIDE_OPTIONS;
00262 }
00263
00264
00265
00266 static bool
00267 m68k_interrupt_function_p(tree func)
00268 {
00269 tree a;
00270
00271 if (TREE_CODE (func) != FUNCTION_DECL)
00272 return false;
00273
00274 a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
00275 return (a != NULL_TREE);
00276 }
00277
00278
00279
00280 static tree
00281 m68k_handle_fndecl_attribute (tree *node, tree name,
00282 tree args ATTRIBUTE_UNUSED,
00283 int flags ATTRIBUTE_UNUSED,
00284 bool *no_add_attrs)
00285 {
00286 if (TREE_CODE (*node) != FUNCTION_DECL)
00287 {
00288 warning ("%qs attribute only applies to functions",
00289 IDENTIFIER_POINTER (name));
00290 *no_add_attrs = true;
00291 }
00292
00293 return NULL_TREE;
00294 }
00295
00296 static void
00297 m68k_compute_frame_layout (void)
00298 {
00299 int regno, saved;
00300 unsigned int mask, rmask;
00301 bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);
00302
00303
00304
00305 if (current_frame.funcdef_no == current_function_funcdef_no
00306 && reload_completed)
00307 return;
00308
00309 current_frame.size = (get_frame_size () + 3) & -4;
00310
00311 mask = rmask = saved = 0;
00312 for (regno = 0; regno < 16; regno++)
00313 if (m68k_save_reg (regno, interrupt_handler))
00314 {
00315 mask |= 1 << regno;
00316 rmask |= 1 << (15 - regno);
00317 saved++;
00318 }
00319 current_frame.offset = saved * 4;
00320 current_frame.reg_no = saved;
00321 current_frame.reg_mask = mask;
00322 current_frame.reg_rev_mask = rmask;
00323
00324 current_frame.foffset = 0;
00325 mask = rmask = saved = 0;
00326 if (TARGET_68881 )
00327 {
00328 for (regno = 16; regno < 24; regno++)
00329 if (m68k_save_reg (regno, interrupt_handler))
00330 {
00331 mask |= 1 << (regno - 16);
00332 rmask |= 1 << (23 - regno);
00333 saved++;
00334 }
00335 current_frame.foffset = saved * 12 ;
00336 current_frame.offset += current_frame.foffset;
00337 }
00338 current_frame.fpu_no = saved;
00339 current_frame.fpu_mask = mask;
00340 current_frame.fpu_rev_mask = rmask;
00341
00342
00343 current_frame.funcdef_no = current_function_funcdef_no;
00344 }
00345
00346 HOST_WIDE_INT
00347 m68k_initial_elimination_offset (int from, int to)
00348 {
00349
00350
00351
00352 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
00353 return 0;
00354
00355 m68k_compute_frame_layout ();
00356
00357 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00358 return current_frame.offset + current_frame.size + (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);
00359 else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00360 return current_frame.offset + current_frame.size;
00361
00362 abort();
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 static bool
00372 m68k_save_reg (unsigned int regno, bool interrupt_handler)
00373 {
00374 if (flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)
00375 {
00376 if (current_function_uses_pic_offset_table)
00377 return true;
00378 if (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)
00379 return true;
00380 }
00381
00382 if (current_function_calls_eh_return)
00383 {
00384 unsigned int i;
00385 for (i = 0; ; i++)
00386 {
00387 unsigned int test = EH_RETURN_DATA_REGNO (i);
00388 if (test == INVALID_REGNUM)
00389 break;
00390 if (test == regno)
00391 return true;
00392 }
00393 }
00394
00395
00396 if (fixed_regs[regno])
00397 return false;
00398
00399
00400 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
00401 return false;
00402
00403
00404
00405 if (interrupt_handler)
00406 {
00407 if (regs_ever_live[regno])
00408 return true;
00409
00410 if (!current_function_is_leaf && call_used_regs[regno])
00411 return true;
00412 }
00413
00414
00415 if (!regs_ever_live[regno])
00416 return false;
00417
00418
00419 return !call_used_regs[regno];
00420 }
00421
00422
00423
00424
00425
00426 static void
00427 m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
00428 {
00429 HOST_WIDE_INT fsize_with_regs;
00430 HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
00431
00432 m68k_compute_frame_layout();
00433
00434
00435
00436 if (current_function_limit_stack
00437 && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
00438 asm_fprintf (stream, "\tcmp" ASM_DOT "l %I%s+%wd,%Rsp\n\ttrapcs\n",
00439 XSTR (stack_limit_rtx, 0), current_frame.size + 4);
00440
00441
00442 fsize_with_regs = current_frame.size;
00443 if (TARGET_COLDFIRE && current_frame.reg_no > 2)
00444 fsize_with_regs += current_frame.reg_no * 4;
00445
00446 if (frame_pointer_needed)
00447 {
00448 if (current_frame.size == 0 && TARGET_68040)
00449
00450 fprintf (stream, MOTOROLA ?
00451 "\tpea (%s)\n\tmove.l %s,%s\n" :
00452 "\tpea %s@\n\tmovel %s,%s\n",
00453 M68K_REGNAME(FRAME_POINTER_REGNUM),
00454 M68K_REGNAME(STACK_POINTER_REGNUM),
00455 M68K_REGNAME(FRAME_POINTER_REGNUM));
00456 else if (fsize_with_regs < 0x8000)
00457 asm_fprintf (stream, "\tlink" ASM_DOTW " %s,%I%wd\n",
00458 M68K_REGNAME(FRAME_POINTER_REGNUM), -fsize_with_regs);
00459 else if (TARGET_68020)
00460 asm_fprintf (stream, "\tlink" ASM_DOTL " %s,%I%wd\n",
00461 M68K_REGNAME(FRAME_POINTER_REGNUM), -fsize_with_regs);
00462 else
00463
00464 asm_fprintf (stream, "\tlink" ASM_DOTW " %s,%I0\n"
00465 "\tadd" ASM_DOT "l %I%wd,%Rsp\n",
00466 M68K_REGNAME(FRAME_POINTER_REGNUM), -fsize_with_regs);
00467
00468 if (dwarf2out_do_frame ())
00469 {
00470 char *l;
00471 l = (char *) dwarf2out_cfi_label ();
00472 cfa_offset += 4;
00473 dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_offset);
00474 dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
00475 cfa_offset += current_frame.size;
00476 }
00477 }
00478 else if (fsize_with_regs)
00479 {
00480 if (fsize_with_regs < 0x8000)
00481 {
00482 if (fsize_with_regs <= 8)
00483 {
00484 if (!TARGET_COLDFIRE)
00485 asm_fprintf (stream, "\tsubq" ASM_DOT "w %I%wd,%Rsp\n",
00486 fsize_with_regs);
00487 else
00488 asm_fprintf (stream, "\tsubq" ASM_DOT "l %I%wd,%Rsp\n",
00489 fsize_with_regs);
00490 }
00491 else if (fsize_with_regs <= 16 && TARGET_CPU32)
00492
00493
00494 asm_fprintf (stream,
00495 "\tsubq" ASM_DOT "w %I8,%Rsp\n"
00496 "\tsubq" ASM_DOT "w %I%wd,%Rsp\n",
00497 fsize_with_regs - 8);
00498 else if (TARGET_68040)
00499
00500 asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n",
00501 -fsize_with_regs);
00502 else
00503 asm_fprintf (stream, MOTOROLA ?
00504 "\tlea (%wd,%Rsp),%Rsp\n" :
00505 "\tlea %Rsp@(%wd),%Rsp\n",
00506 -fsize_with_regs);
00507 }
00508 else
00509 asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", -fsize_with_regs);
00510
00511 if (dwarf2out_do_frame ())
00512 {
00513 cfa_offset += current_frame.size + 4;
00514 dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
00515 }
00516 }
00517
00518 if (current_frame.fpu_mask)
00519 {
00520 asm_fprintf (stream, MOTOROLA ?
00521 "\tfmovm %I0x%x,-(%Rsp)\n" :
00522 "\tfmovem %I0x%x,%Rsp@-\n",
00523 current_frame.fpu_mask);
00524
00525 if (dwarf2out_do_frame ())
00526 {
00527 char *l = (char *) dwarf2out_cfi_label ();
00528 int n_regs, regno;
00529
00530 cfa_offset += current_frame.fpu_no * 12;
00531 if (! frame_pointer_needed)
00532 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
00533 for (regno = 16, n_regs = 0; regno < 24; regno++)
00534 if (current_frame.fpu_mask & (1 << (regno - 16)))
00535 dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 12);
00536 }
00537 }
00538
00539
00540
00541 if (current_function_limit_stack)
00542 {
00543 if (REG_P (stack_limit_rtx))
00544 asm_fprintf (stream, "\tcmp" ASM_DOT "l %s,%Rsp\n\ttrapcs\n",
00545 M68K_REGNAME(REGNO (stack_limit_rtx)));
00546 else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
00547 warning ("stack limit expression is not supported");
00548 }
00549
00550 if (current_frame.reg_no <= 2)
00551 {
00552
00553
00554
00555
00556
00557 int i;
00558
00559 for (i = 0; i < 16; i++)
00560 if (current_frame.reg_rev_mask & (1 << i))
00561 {
00562 asm_fprintf (stream, MOTOROLA ?
00563 "\t%Omove.l %s,-(%Rsp)\n" :
00564 "\tmovel %s,%Rsp@-\n",
00565 M68K_REGNAME(15 - i));
00566 if (dwarf2out_do_frame ())
00567 {
00568 char *l = (char *) dwarf2out_cfi_label ();
00569
00570 cfa_offset += 4;
00571 if (! frame_pointer_needed)
00572 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
00573 dwarf2out_reg_save (l, 15 - i, -cfa_offset);
00574 }
00575 }
00576 }
00577 else if (current_frame.reg_rev_mask)
00578 {
00579 if (TARGET_COLDFIRE)
00580
00581
00582
00583
00584
00585
00586 asm_fprintf (stream, MOTOROLA ?
00587 "\tmovm.l %I0x%x,(%Rsp)\n" :
00588 "\tmoveml %I0x%x,%Rsp@\n",
00589 current_frame.reg_mask);
00590 else
00591 asm_fprintf (stream, MOTOROLA ?
00592 "\tmovm.l %I0x%x,-(%Rsp)\n" :
00593 "\tmoveml %I0x%x,%Rsp@-\n",
00594 current_frame.reg_rev_mask);
00595 if (dwarf2out_do_frame ())
00596 {
00597 char *l = (char *) dwarf2out_cfi_label ();
00598 int n_regs, regno;
00599
00600 cfa_offset += current_frame.reg_no * 4;
00601 if (! frame_pointer_needed)
00602 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
00603 for (regno = 0, n_regs = 0; regno < 16; regno++)
00604 if (current_frame.reg_mask & (1 << regno))
00605 dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 4);
00606 }
00607 }
00608 if (!TARGET_SEP_DATA && flag_pic &&
00609 (current_function_uses_pic_offset_table ||
00610 (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY)))
00611 {
00612 if (TARGET_ID_SHARED_LIBRARY)
00613 {
00614 asm_fprintf (stream, "\tmovel %s@(%s), %s\n",
00615 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM),
00616 m68k_library_id_string,
00617 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));
00618 }
00619 else
00620 {
00621 if (MOTOROLA)
00622 asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
00623 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));
00624 else
00625 {
00626 asm_fprintf (stream, "\tmovel %I%U_GLOBAL_OFFSET_TABLE_, %s\n",
00627 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));
00628 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
00629 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM),
00630 M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM));
00631 }
00632 }
00633 }
00634 }
00635
00636
00637
00638 bool
00639 use_return_insn (void)
00640 {
00641 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
00642 return false;
00643
00644
00645
00646 m68k_compute_frame_layout();
00647 return current_frame.reg_no ? false : true;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 static void
00659 m68k_output_function_epilogue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
00660 {
00661 HOST_WIDE_INT fsize, fsize_with_regs;
00662 bool big = false;
00663 bool restore_from_sp = false;
00664 rtx insn = get_last_insn ();
00665
00666 m68k_compute_frame_layout();
00667
00668
00669 if (GET_CODE (insn) == NOTE)
00670 insn = prev_nonnote_insn (insn);
00671 if (insn && GET_CODE (insn) == BARRIER)
00672 {
00673
00674
00675 fprintf (stream, "\tnop\n");
00676 return;
00677 }
00678
00679 #ifdef FUNCTION_EXTRA_EPILOGUE
00680 FUNCTION_EXTRA_EPILOGUE (stream, size);
00681 #endif
00682
00683 fsize = current_frame.size;
00684
00685
00686
00687
00688 restore_from_sp = ! frame_pointer_needed
00689 || (! current_function_calls_alloca && leaf_function_p ());
00690
00691
00692
00693 fsize_with_regs = fsize;
00694
00695
00696
00697
00698
00699
00700 if (TARGET_COLDFIRE && restore_from_sp && (current_frame.reg_no > 2))
00701 fsize_with_regs += current_frame.reg_no * 4;
00702
00703 if (current_frame.offset + fsize >= 0x8000
00704 && ! restore_from_sp
00705 && (current_frame.reg_mask || current_frame.fpu_mask))
00706 {
00707
00708
00709 if (TARGET_COLDFIRE)
00710 fsize += current_frame.offset;
00711
00712 asm_fprintf (stream, "\t%Omove" ASM_DOT "l %I%wd,%Ra1\n", -fsize);
00713 fsize = 0, big = true;
00714 }
00715 if (current_frame.reg_no <= 2)
00716 {
00717
00718
00719
00720
00721
00722 int i;
00723 HOST_WIDE_INT offset = current_frame.offset + fsize;
00724
00725 for (i = 0; i < 16; i++)
00726 if (current_frame.reg_mask & (1 << i))
00727 {
00728 if (big)
00729 {
00730 if (MOTOROLA)
00731 asm_fprintf (stream, "\t%Omove.l -%wd(%s,%Ra1.l),%s\n",
00732 offset,
00733 M68K_REGNAME(FRAME_POINTER_REGNUM),
00734 M68K_REGNAME(i));
00735 else
00736 asm_fprintf (stream, "\tmovel %s@(-%wd,%Ra1:l),%s\n",
00737 M68K_REGNAME(FRAME_POINTER_REGNUM),
00738 offset,
00739 M68K_REGNAME(i));
00740 }
00741 else if (restore_from_sp)
00742 asm_fprintf (stream, MOTOROLA ?
00743 "\t%Omove.l (%Rsp)+,%s\n" :
00744 "\tmovel %Rsp@+,%s\n",
00745 M68K_REGNAME(i));
00746 else
00747 {
00748 if (MOTOROLA)
00749 asm_fprintf (stream, "\t%Omove.l -%wd(%s),%s\n",
00750 offset,
00751 M68K_REGNAME(FRAME_POINTER_REGNUM),
00752 M68K_REGNAME(i));
00753 else
00754 asm_fprintf (stream, "\tmovel %s@(-%wd),%s\n",
00755 M68K_REGNAME(FRAME_POINTER_REGNUM),
00756 offset,
00757 M68K_REGNAME(i));
00758 }
00759 offset -= 4;
00760 }
00761 }
00762 else if (current_frame.reg_mask)
00763 {
00764
00765 if (TARGET_COLDFIRE)
00766 {
00767 if (big)
00768 {
00769 asm_fprintf (stream, "\tadd" ASM_DOT "l %s,%Ra1\n",
00770 M68K_REGNAME(FRAME_POINTER_REGNUM));
00771 asm_fprintf (stream, MOTOROLA ?
00772 "\tmovm.l (%Ra1),%I0x%x\n" :
00773 "\tmoveml %Ra1@,%I0x%x\n",
00774 current_frame.reg_mask);
00775 }
00776 else if (restore_from_sp)
00777 asm_fprintf (stream, MOTOROLA ?
00778 "\tmovm.l (%Rsp),%I0x%x\n" :
00779 "\tmoveml %Rsp@,%I0x%x\n",
00780 current_frame.reg_mask);
00781 else
00782 {
00783 if (MOTOROLA)
00784 asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
00785 current_frame.offset + fsize,
00786 M68K_REGNAME(FRAME_POINTER_REGNUM),
00787 current_frame.reg_mask);
00788 else
00789 asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
00790 M68K_REGNAME(FRAME_POINTER_REGNUM),
00791 current_frame.offset + fsize,
00792 current_frame.reg_mask);
00793 }
00794 }
00795 else
00796 {
00797 if (big)
00798 {
00799 if (MOTOROLA)
00800 asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n",
00801 current_frame.offset + fsize,
00802 M68K_REGNAME(FRAME_POINTER_REGNUM),
00803 current_frame.reg_mask);
00804 else
00805 asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n",
00806 M68K_REGNAME(FRAME_POINTER_REGNUM),
00807 current_frame.offset + fsize,
00808 current_frame.reg_mask);
00809 }
00810 else if (restore_from_sp)
00811 {
00812 asm_fprintf (stream, MOTOROLA ?
00813 "\tmovm.l (%Rsp)+,%I0x%x\n" :
00814 "\tmoveml %Rsp@+,%I0x%x\n",
00815 current_frame.reg_mask);
00816 }
00817 else
00818 {
00819 if (MOTOROLA)
00820 asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
00821 current_frame.offset + fsize,
00822 M68K_REGNAME(FRAME_POINTER_REGNUM),
00823 current_frame.reg_mask);
00824 else
00825 asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
00826 M68K_REGNAME(FRAME_POINTER_REGNUM),
00827 current_frame.offset + fsize,
00828 current_frame.reg_mask);
00829 }
00830 }
00831 }
00832 if (current_frame.fpu_rev_mask)
00833 {
00834 if (big)
00835 {
00836 if (MOTOROLA)
00837 asm_fprintf (stream, "\tfmovm -%wd(%s,%Ra1.l),%I0x%x\n",
00838 current_frame.foffset + fsize,
00839 M68K_REGNAME(FRAME_POINTER_REGNUM),
00840 current_frame.fpu_rev_mask);
00841 else
00842 asm_fprintf (stream, "\tfmovem %s@(-%wd,%Ra1:l),%I0x%x\n",
00843 M68K_REGNAME(FRAME_POINTER_REGNUM),
00844 current_frame.foffset + fsize,
00845 current_frame.fpu_rev_mask);
00846 }
00847 else if (restore_from_sp)
00848 {
00849 if (MOTOROLA)
00850 asm_fprintf (stream, "\tfmovm (%Rsp)+,%I0x%x\n",
00851 current_frame.fpu_rev_mask);
00852 else
00853 asm_fprintf (stream, "\tfmovem %Rsp@+,%I0x%x\n",
00854 current_frame.fpu_rev_mask);
00855 }
00856 else
00857 {
00858 if (MOTOROLA)
00859 asm_fprintf (stream, "\tfmovm -%wd(%s),%I0x%x\n",
00860 current_frame.foffset + fsize,
00861 M68K_REGNAME(FRAME_POINTER_REGNUM),
00862 current_frame.fpu_rev_mask);
00863 else
00864 asm_fprintf (stream, "\tfmovem %s@(-%wd),%I0x%x\n",
00865 M68K_REGNAME(FRAME_POINTER_REGNUM),
00866 current_frame.foffset + fsize,
00867 current_frame.fpu_rev_mask);
00868 }
00869 }
00870 if (frame_pointer_needed)
00871 fprintf (stream, "\tunlk %s\n", M68K_REGNAME(FRAME_POINTER_REGNUM));
00872 else if (fsize_with_regs)
00873 {
00874 if (fsize_with_regs <= 8)
00875 {
00876 if (!TARGET_COLDFIRE)
00877 asm_fprintf (stream, "\taddq" ASM_DOT "w %I%wd,%Rsp\n",
00878 fsize_with_regs);
00879 else
00880 asm_fprintf (stream, "\taddq" ASM_DOT "l %I%wd,%Rsp\n",
00881 fsize_with_regs);
00882 }
00883 else if (fsize_with_regs <= 16 && TARGET_CPU32)
00884 {
00885
00886
00887 asm_fprintf (stream, "\taddq" ASM_DOT "w %I8,%Rsp\n"
00888 "\taddq" ASM_DOT "w %I%wd,%Rsp\n",
00889 fsize_with_regs - 8);
00890 }
00891 else if (fsize_with_regs < 0x8000)
00892 {
00893 if (TARGET_68040)
00894 asm_fprintf (stream, "\tadd" ASM_DOT "w %I%wd,%Rsp\n",
00895 fsize_with_regs);
00896 else
00897 asm_fprintf (stream, MOTOROLA ?
00898 "\tlea (%wd,%Rsp),%Rsp\n" :
00899 "\tlea %Rsp@(%wd),%Rsp\n",
00900 fsize_with_regs);
00901 }
00902 else
00903 asm_fprintf (stream, "\tadd" ASM_DOT "l %I%wd,%Rsp\n", fsize_with_regs);
00904 }
00905 if (current_function_calls_eh_return)
00906 asm_fprintf (stream, "\tadd" ASM_DOT"l %Ra0,%Rsp\n");
00907 if (m68k_interrupt_function_p (current_function_decl))
00908 fprintf (stream, "\trte\n");
00909 else if (current_function_pops_args)
00910 asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args);
00911 else
00912 fprintf (stream, "\trts\n");
00913 }
00914
00915
00916
00917 int
00918 not_sp_operand (rtx op, enum machine_mode mode)
00919 {
00920 return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 int
00932 valid_dbcc_comparison_p (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
00933 {
00934 switch (GET_CODE (x))
00935 {
00936 case EQ: case NE: case GTU: case LTU:
00937 case GEU: case LEU:
00938 return 1;
00939
00940
00941
00942 case GT: case LT: case GE: case LE:
00943 return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
00944 default:
00945 return 0;
00946 }
00947 }
00948
00949
00950 int
00951 flags_in_68881 (void)
00952 {
00953
00954 return cc_status.flags & CC_IN_68881;
00955 }
00956
00957
00958 void
00959 m68k_output_pic_call(rtx dest)
00960 {
00961 const char *out;
00962
00963 if (!(GET_CODE (dest) == MEM && GET_CODE (XEXP (dest, 0)) == SYMBOL_REF))
00964 out = "jsr %0";
00965
00966
00967
00968
00969
00970
00971
00972 else if (TARGET_PCREL)
00973 out = "bsr.l %o0";
00974 else if ((flag_pic == 1) || TARGET_68020)
00975 #if defined(USE_GAS)
00976 out = "bsr.l %0@PLTPC";
00977 #else
00978 out = "bsr %0@PLTPC";
00979 #endif
00980 else if (optimize_size || TARGET_ID_SHARED_LIBRARY)
00981 out = "move.l %0@GOT(%%a5), %%a1\n\tjsr (%%a1)";
00982 else
00983 out = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)";
00984
00985 output_asm_insn(out, &dest);
00986 }
00987
00988
00989
00990
00991
00992
00993
00994 void
00995 output_dbcc_and_branch (rtx *operands)
00996 {
00997 switch (GET_CODE (operands[3]))
00998 {
00999 case EQ:
01000 output_asm_insn (MOTOROLA ?
01001 "dbeq %0,%l1\n\tjbeq %l2" :
01002 "dbeq %0,%l1\n\tjeq %l2",
01003 operands);
01004 break;
01005
01006 case NE:
01007 output_asm_insn (MOTOROLA ?
01008 "dbne %0,%l1\n\tjbne %l2" :
01009 "dbne %0,%l1\n\tjne %l2",
01010 operands);
01011 break;
01012
01013 case GT:
01014 output_asm_insn (MOTOROLA ?
01015 "dbgt %0,%l1\n\tjbgt %l2" :
01016 "dbgt %0,%l1\n\tjgt %l2",
01017 operands);
01018 break;
01019
01020 case GTU:
01021 output_asm_insn (MOTOROLA ?
01022 "dbhi %0,%l1\n\tjbhi %l2" :
01023 "dbhi %0,%l1\n\tjhi %l2",
01024 operands);
01025 break;
01026
01027 case LT:
01028 output_asm_insn (MOTOROLA ?
01029 "dblt %0,%l1\n\tjblt %l2" :
01030 "dblt %0,%l1\n\tjlt %l2",
01031 operands);
01032 break;
01033
01034 case LTU:
01035 output_asm_insn (MOTOROLA ?
01036 "dbcs %0,%l1\n\tjbcs %l2" :
01037 "dbcs %0,%l1\n\tjcs %l2",
01038 operands);
01039 break;
01040
01041 case GE:
01042 output_asm_insn (MOTOROLA ?
01043 "dbge %0,%l1\n\tjbge %l2" :
01044 "dbge %0,%l1\n\tjge %l2",
01045 operands);
01046 break;
01047
01048 case GEU:
01049 output_asm_insn (MOTOROLA ?
01050 "dbcc %0,%l1\n\tjbcc %l2" :
01051 "dbcc %0,%l1\n\tjcc %l2",
01052 operands);
01053 break;
01054
01055 case LE:
01056 output_asm_insn (MOTOROLA ?
01057 "dble %0,%l1\n\tjble %l2" :
01058 "dble %0,%l1\n\tjle %l2",
01059 operands);
01060 break;
01061
01062 case LEU:
01063 output_asm_insn (MOTOROLA ?
01064 "dbls %0,%l1\n\tjbls %l2" :
01065 "dbls %0,%l1\n\tjls %l2",
01066 operands);
01067 break;
01068
01069 default:
01070 abort ();
01071 }
01072
01073
01074
01075 switch (GET_MODE (operands[0]))
01076 {
01077 case SImode:
01078 output_asm_insn (MOTOROLA ?
01079 "clr%.w %0\n\tsubq%.l #1,%0\n\tjbpl %l1" :
01080 "clr%.w %0\n\tsubq%.l #1,%0\n\tjpl %l1",
01081 operands);
01082 break;
01083
01084 case HImode:
01085 break;
01086
01087 default:
01088 abort ();
01089 }
01090 }
01091
01092 const char *
01093 output_scc_di(rtx op, rtx operand1, rtx operand2, rtx dest)
01094 {
01095 rtx loperands[7];
01096 enum rtx_code op_code = GET_CODE (op);
01097
01098
01099 CC_STATUS_INIT;
01100
01101
01102
01103
01104 if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
01105 {
01106 rtx tmp = operand1;
01107
01108 operand1 = operand2;
01109 operand2 = tmp;
01110 op_code = swap_condition (op_code);
01111 }
01112 loperands[0] = operand1;
01113 if (GET_CODE (operand1) == REG)
01114 loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);
01115 else
01116 loperands[1] = adjust_address (operand1, SImode, 4);
01117 if (operand2 != const0_rtx)
01118 {
01119 loperands[2] = operand2;
01120 if (GET_CODE (operand2) == REG)
01121 loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);
01122 else
01123 loperands[3] = adjust_address (operand2, SImode, 4);
01124 }
01125 loperands[4] = gen_label_rtx ();
01126 if (operand2 != const0_rtx)
01127 {
01128 output_asm_insn (MOTOROLA ?
01129 "cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1" :
01130 "cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1",
01131 loperands);
01132 }
01133 else
01134 {
01135 if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[0]))
01136 output_asm_insn ("tst%.l %0", loperands);
01137 else
01138 {
01139 output_asm_insn ("cmp%.w #0,%0", loperands);
01140 }
01141
01142 output_asm_insn (MOTOROLA ? "jbne %l4" : "jne %l4", loperands);
01143
01144 if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (loperands[1]))
01145 output_asm_insn ("tst%.l %1", loperands);
01146 else
01147 output_asm_insn ("cmp%.w #0,%1", loperands);
01148 }
01149
01150 loperands[5] = dest;
01151
01152 switch (op_code)
01153 {
01154 case EQ:
01155 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01156 CODE_LABEL_NUMBER (loperands[4]));
01157 output_asm_insn ("seq %5", loperands);
01158 break;
01159
01160 case NE:
01161 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01162 CODE_LABEL_NUMBER (loperands[4]));
01163 output_asm_insn ("sne %5", loperands);
01164 break;
01165
01166 case GT:
01167 loperands[6] = gen_label_rtx ();
01168 output_asm_insn (MOTOROLA ?
01169 "shi %5\n\tjbra %l6" :
01170 "shi %5\n\tjra %l6",
01171 loperands);
01172 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01173 CODE_LABEL_NUMBER (loperands[4]));
01174 output_asm_insn ("sgt %5", loperands);
01175 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01176 CODE_LABEL_NUMBER (loperands[6]));
01177 break;
01178
01179 case GTU:
01180 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01181 CODE_LABEL_NUMBER (loperands[4]));
01182 output_asm_insn ("shi %5", loperands);
01183 break;
01184
01185 case LT:
01186 loperands[6] = gen_label_rtx ();
01187 output_asm_insn (MOTOROLA ?
01188 "scs %5\n\tjbra %l6" :
01189 "scs %5\n\tjra %l6",
01190 loperands);
01191 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01192 CODE_LABEL_NUMBER (loperands[4]));
01193 output_asm_insn ("slt %5", loperands);
01194 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01195 CODE_LABEL_NUMBER (loperands[6]));
01196 break;
01197
01198 case LTU:
01199 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01200 CODE_LABEL_NUMBER (loperands[4]));
01201 output_asm_insn ("scs %5", loperands);
01202 break;
01203
01204 case GE:
01205 loperands[6] = gen_label_rtx ();
01206 output_asm_insn (MOTOROLA ?
01207 "scc %5\n\tjbra %l6" :
01208 "scc %5\n\tjra %l6",
01209 loperands);
01210 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01211 CODE_LABEL_NUMBER (loperands[4]));
01212 output_asm_insn ("sge %5", loperands);
01213 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01214 CODE_LABEL_NUMBER (loperands[6]));
01215 break;
01216
01217 case GEU:
01218 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01219 CODE_LABEL_NUMBER (loperands[4]));
01220 output_asm_insn ("scc %5", loperands);
01221 break;
01222
01223 case LE:
01224 loperands[6] = gen_label_rtx ();
01225 output_asm_insn (MOTOROLA ?
01226 "sls %5\n\tjbra %l6" :
01227 "sls %5\n\tjra %l6",
01228 loperands);
01229 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01230 CODE_LABEL_NUMBER (loperands[4]));
01231 output_asm_insn ("sle %5", loperands);
01232 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01233 CODE_LABEL_NUMBER (loperands[6]));
01234 break;
01235
01236 case LEU:
01237 (*targetm.asm_out.internal_label) (asm_out_file, "L",
01238 CODE_LABEL_NUMBER (loperands[4]));
01239 output_asm_insn ("sls %5", loperands);
01240 break;
01241
01242 default:
01243 abort ();
01244 }
01245 return "";
01246 }
01247
01248 const char *
01249 output_btst (rtx *operands, rtx countop, rtx dataop, rtx insn, int signpos)
01250 {
01251 operands[0] = countop;
01252 operands[1] = dataop;
01253
01254 if (GET_CODE (countop) == CONST_INT)
01255 {
01256 register int count = INTVAL (countop);
01257
01258
01259 if (count > signpos)
01260 {
01261 int offset = (count & ~signpos) / 8;
01262 count = count & signpos;
01263 operands[1] = dataop = adjust_address (dataop, QImode, offset);
01264 }
01265 if (count == signpos)
01266 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
01267 else
01268 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
01269
01270
01271
01272 if (count == 31
01273 && next_insn_tests_no_inequality (insn))
01274 return "tst%.l %1";
01275 if (count == 15
01276 && next_insn_tests_no_inequality (insn))
01277 return "tst%.w %1";
01278 if (count == 7
01279 && next_insn_tests_no_inequality (insn))
01280 return "tst%.b %1";
01281
01282 cc_status.flags = CC_NOT_NEGATIVE;
01283 }
01284 return "btst %0,%1";
01285 }
01286
01287
01288
01289
01290 int
01291 symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01292 {
01293 switch (GET_CODE (op))
01294 {
01295 case SYMBOL_REF:
01296 case LABEL_REF:
01297 return true;
01298
01299 case CONST:
01300 op = XEXP (op, 0);
01301 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
01302 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
01303 && GET_CODE (XEXP (op, 1)) == CONST_INT);
01304
01305 #if 0
01306
01307 case CONST_DOUBLE:
01308 return GET_MODE (op) == mode;
01309 #endif
01310
01311 default:
01312 return false;
01313 }
01314 }
01315
01316
01317
01318 int
01319 extend_operator(rtx x, enum machine_mode mode)
01320 {
01321 if (mode != VOIDmode && GET_MODE(x) != mode)
01322 return 0;
01323 switch (GET_CODE(x))
01324 {
01325 case SIGN_EXTEND :
01326 case ZERO_EXTEND :
01327 return 1;
01328 default :
01329 return 0;
01330 }
01331 }
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374 rtx
01375 legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
01376 rtx reg)
01377 {
01378 rtx pic_ref = orig;
01379
01380
01381 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
01382 {
01383 if (reg == 0)
01384 abort ();
01385
01386 pic_ref = gen_rtx_MEM (Pmode,
01387 gen_rtx_PLUS (Pmode,
01388 pic_offset_table_rtx, orig));
01389 current_function_uses_pic_offset_table = 1;
01390 MEM_READONLY_P (pic_ref) = 1;
01391 emit_move_insn (reg, pic_ref);
01392 return reg;
01393 }
01394 else if (GET_CODE (orig) == CONST)
01395 {
01396 rtx base;
01397
01398
01399 if (GET_CODE (XEXP (orig, 0)) == PLUS
01400 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
01401 return orig;
01402
01403 if (reg == 0)
01404 abort ();
01405
01406
01407 if (GET_CODE (XEXP (orig, 0)) == PLUS)
01408 {
01409 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
01410 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
01411 base == reg ? 0 : reg);
01412 }
01413 else abort ();
01414
01415 if (GET_CODE (orig) == CONST_INT)
01416 return plus_constant (base, INTVAL (orig));
01417 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
01418
01419 }
01420 return pic_ref;
01421 }
01422
01423
01424 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ, MVS, MVZ } CONST_METHOD;
01425
01426 static CONST_METHOD const_method (rtx);
01427
01428 #define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
01429
01430 static CONST_METHOD
01431 const_method (rtx constant)
01432 {
01433 int i;
01434 unsigned u;
01435
01436 i = INTVAL (constant);
01437 if (USE_MOVQ (i))
01438 return MOVQ;
01439
01440
01441
01442 if (!TARGET_COLDFIRE)
01443 {
01444
01445
01446 if (USE_MOVQ (i ^ 0xff))
01447 return NOTB;
01448
01449 if (USE_MOVQ (i ^ 0xffff))
01450 return NOTW;
01451
01452 if (i == -65408)
01453 return NEGW;
01454 }
01455
01456
01457 u = i;
01458 if (USE_MOVQ ((u >> 16) | (u << 16)))
01459 return SWAP;
01460
01461 if (TARGET_CFV4)
01462 {
01463
01464 if (i >= 0 && i <= 65535)
01465 return MVZ;
01466 if (i >= -32768 && i <= 32767)
01467 return MVS;
01468 }
01469
01470
01471 return MOVL;
01472 }
01473
01474 static int
01475 const_int_cost (rtx constant)
01476 {
01477 switch (const_method (constant))
01478 {
01479 case MOVQ :
01480
01481 return 0;
01482 case MVZ:
01483 case MVS:
01484 case NOTB :
01485 case NOTW :
01486 case NEGW :
01487 case SWAP :
01488
01489 return 1;
01490 case MOVL :
01491 return 2;
01492 default :
01493 abort ();
01494 }
01495 }
01496
01497 static bool
01498 m68k_rtx_costs (rtx x, int code, int outer_code, int *total)
01499 {
01500 switch (code)
01501 {
01502 case CONST_INT:
01503
01504 if (x == const0_rtx)
01505 *total = 0;
01506 else
01507 *total = const_int_cost (x);
01508 return true;
01509
01510 case CONST:
01511 case LABEL_REF:
01512 case SYMBOL_REF:
01513 *total = 3;
01514 return true;
01515
01516 case CONST_DOUBLE:
01517
01518
01519 if (outer_code == COMPARE
01520 && (x == CONST0_RTX (SFmode) || x == CONST0_RTX (DFmode)))
01521 *total = 4;
01522 else
01523 *total = 5;
01524 return true;
01525
01526
01527
01528
01529
01530
01531
01532 #define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : (TARGET_COLDFIRE && !TARGET_5200) ? 3 : TARGET_COLDFIRE ? 10 : 13)
01533 #define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : \
01534 (TARGET_COLDFIRE && !TARGET_5200) ? 2 : 5)
01535 #define DIVW_COST (TARGET_68020 ? 27 : TARGET_CF_HWDIV ? 11 : 12)
01536
01537 case PLUS:
01538
01539 if (GET_MODE (x) == SImode
01540 && GET_CODE (XEXP (x, 1)) == REG
01541 && GET_CODE (XEXP (x, 0)) == MULT
01542 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
01543 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01544 && (INTVAL (XEXP (XEXP (x, 0), 1)) == 2
01545 || INTVAL (XEXP (XEXP (x, 0), 1)) == 4
01546 || INTVAL (XEXP (XEXP (x, 0), 1)) == 8))
01547 {
01548
01549 *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 2 : 3);
01550 return true;
01551 }
01552 return false;
01553
01554 case ASHIFT:
01555 case ASHIFTRT:
01556 case LSHIFTRT:
01557 if (TARGET_68060)
01558 {
01559 *total = COSTS_N_INSNS(1);
01560 return true;
01561 }
01562 if (! TARGET_68020 && ! TARGET_COLDFIRE)
01563 {
01564 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
01565 {
01566 if (INTVAL (XEXP (x, 1)) < 16)
01567 *total = COSTS_N_INSNS (2) + INTVAL (XEXP (x, 1)) / 2;
01568 else
01569
01570 *total = COSTS_N_INSNS (4) + (INTVAL (XEXP (x, 1)) - 16) / 2;
01571 }
01572 else
01573 *total = COSTS_N_INSNS (10);
01574 return true;
01575 }
01576
01577 if (GET_CODE (XEXP (x, 1)) == CONST_INT
01578 && (INTVAL (XEXP (x, 1)) == 16))
01579 {
01580 *total = COSTS_N_INSNS (2);
01581 return true;
01582 }
01583 if (GET_CODE (XEXP (x, 1)) == CONST_INT
01584 && !(INTVAL (XEXP (x, 1)) > 0
01585 && INTVAL (XEXP (x, 1)) <= 8))
01586 {
01587 *total = COSTS_N_INSNS (TARGET_COLDFIRE ? 1 : 3);
01588 return true;
01589 }
01590 return false;
01591
01592 case MULT:
01593 if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
01594 || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
01595 && GET_MODE (x) == SImode)
01596 *total = COSTS_N_INSNS (MULW_COST);
01597 else if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
01598 *total = COSTS_N_INSNS (MULW_COST);
01599 else
01600 *total = COSTS_N_INSNS (MULL_COST);
01601 return true;
01602
01603 case DIV:
01604 case UDIV:
01605 case MOD:
01606 case UMOD:
01607 if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
01608 *total = COSTS_N_INSNS (DIVW_COST);
01609 else if (TARGET_CF_HWDIV)
01610 *total = COSTS_N_INSNS (18);
01611 else
01612 *total = COSTS_N_INSNS (43);
01613 return true;
01614
01615 default:
01616 return false;
01617 }
01618 }
01619
01620 const char *
01621 output_move_const_into_data_reg (rtx *operands)
01622 {
01623 int i;
01624
01625 i = INTVAL (operands[1]);
01626 switch (const_method (operands[1]))
01627 {
01628 case MVZ:
01629 return "mvsw %1,%0";
01630 case MVS:
01631 return "mvzw %1,%0";
01632 case MOVQ :
01633 return "moveq %1,%0";
01634 case NOTB :
01635 CC_STATUS_INIT;
01636 operands[1] = GEN_INT (i ^ 0xff);
01637 return "moveq %1,%0\n\tnot%.b %0";
01638 case NOTW :
01639 CC_STATUS_INIT;
01640 operands[1] = GEN_INT (i ^ 0xffff);
01641 return "moveq %1,%0\n\tnot%.w %0";
01642 case NEGW :
01643 CC_STATUS_INIT;
01644 return "moveq #-128,%0\n\tneg%.w %0";
01645 case SWAP :
01646 {
01647 unsigned u = i;
01648
01649 operands[1] = GEN_INT ((u << 16) | (u >> 16));
01650 return "moveq %1,%0\n\tswap %0";
01651 }
01652 case MOVL :
01653 return "move%.l %1,%0";
01654 default :
01655 abort ();
01656 }
01657 }
01658
01659
01660
01661 int
01662 valid_mov3q_const (rtx constant)
01663 {
01664 int i;
01665
01666 if (TARGET_CFV4 && GET_CODE (constant) == CONST_INT)
01667 {
01668 i = INTVAL (constant);
01669 if ((i == -1) || (i >= 1 && i <= 7))
01670 return 1;
01671 }
01672 return 0;
01673 }
01674
01675
01676 const char *
01677 output_move_simode_const (rtx *operands)
01678 {
01679 if (operands[1] == const0_rtx
01680 && (DATA_REG_P (operands[0])
01681 || GET_CODE (operands[0]) == MEM)
01682
01683
01684 && ((TARGET_68020 || TARGET_COLDFIRE)
01685 || !(GET_CODE (operands[0]) == MEM
01686 && MEM_VOLATILE_P (operands[0]))))
01687 return "clr%.l %0";
01688 else if ((GET_MODE (operands[0]) == SImode)
01689 && valid_mov3q_const (operands[1]))
01690 return "mov3q%.l %1,%0";
01691 else if (operands[1] == const0_rtx
01692 && ADDRESS_REG_P (operands[0]))
01693 return "sub%.l %0,%0";
01694 else if (DATA_REG_P (operands[0]))
01695 return output_move_const_into_data_reg (operands);
01696 else if (ADDRESS_REG_P (operands[0])
01697 && INTVAL (operands[1]) < 0x8000
01698 && INTVAL (operands[1]) >= -0x8000)
01699 {
01700 if (valid_mov3q_const (operands[1]))
01701 return "mov3q%.l %1,%0";
01702 return "move%.w %1,%0";
01703 }
01704 else if (GET_CODE (operands[0]) == MEM
01705 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
01706 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
01707 && INTVAL (operands[1]) < 0x8000
01708 && INTVAL (operands[1]) >= -0x8000)
01709 {
01710 if (valid_mov3q_const (operands[1]))
01711 return "mov3q%.l %1,%-";
01712 return "pea %a1";
01713 }
01714 return "move%.l %1,%0";
01715 }
01716
01717 const char *
01718 output_move_simode (rtx *operands)
01719 {
01720 if (GET_CODE (operands[1]) == CONST_INT)
01721 return output_move_simode_const (operands);
01722 else if ((GET_CODE (operands[1]) == SYMBOL_REF
01723 || GET_CODE (operands[1]) == CONST)
01724 && push_operand (operands[0], SImode))
01725 return "pea %a1";
01726 else if ((GET_CODE (operands[1]) == SYMBOL_REF
01727 || GET_CODE (operands[1]) == CONST)
01728 && ADDRESS_REG_P (operands[0]))
01729 return "lea %a1,%0";
01730 return "move%.l %1,%0";
01731 }
01732
01733 const char *
01734 output_move_himode (rtx *operands)
01735 {
01736 if (GET_CODE (operands[1]) == CONST_INT)
01737 {
01738 if (operands[1] == const0_rtx
01739 && (DATA_REG_P (operands[0])
01740 || GET_CODE (operands[0]) == MEM)
01741
01742
01743 && ((TARGET_68020 || TARGET_COLDFIRE)
01744 || !(GET_CODE (operands[0]) == MEM
01745 && MEM_VOLATILE_P (operands[0]))))
01746 return "clr%.w %0";
01747 else if (operands[1] == const0_rtx
01748 && ADDRESS_REG_P (operands[0]))
01749 return "sub%.l %0,%0";
01750 else if (DATA_REG_P (operands[0])
01751 && INTVAL (operands[1]) < 128
01752 && INTVAL (operands[1]) >= -128)
01753 {
01754 return "moveq %1,%0";
01755 }
01756 else if (INTVAL (operands[1]) < 0x8000
01757 && INTVAL (operands[1]) >= -0x8000)
01758 return "move%.w %1,%0";
01759 }
01760 else if (CONSTANT_P (operands[1]))
01761 return "move%.l %1,%0";
01762
01763
01764
01765
01766
01767
01768 if (GET_CODE (operands[1]) == MEM
01769 && GET_CODE (XEXP (operands[1], 0)) == PLUS
01770 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
01771 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
01772 {
01773 rtx labelref = XEXP (XEXP (operands[1], 0), 1);
01774 if (MOTOROLA)
01775 asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
01776 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
01777 else
01778 (*targetm.asm_out.internal_label) (asm_out_file, "LI",
01779 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
01780 }
01781 return "move%.w %1,%0";
01782 }
01783
01784 const char *
01785 output_move_qimode (rtx *operands)
01786 {
01787
01788
01789 if (GET_CODE (operands[0]) == MEM
01790 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
01791 && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
01792 && ! ADDRESS_REG_P (operands[1])
01793 && ! TARGET_COLDFIRE)
01794
01795 abort ();
01796
01797
01798
01799 if (!ADDRESS_REG_P (operands[0])
01800 && ((TARGET_68020 || TARGET_COLDFIRE)
01801 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
01802 {
01803 if (operands[1] == const0_rtx)
01804 return "clr%.b %0";
01805 if ((!TARGET_COLDFIRE || DATA_REG_P (operands[0]))
01806 && GET_CODE (operands[1]) == CONST_INT
01807 && (INTVAL (operands[1]) & 255) == 255)
01808 {
01809 CC_STATUS_INIT;
01810 return "st %0";
01811 }
01812 }
01813 if (GET_CODE (operands[1]) == CONST_INT
01814 && DATA_REG_P (operands[0])
01815 && INTVAL (operands[1]) < 128
01816 && INTVAL (operands[1]) >= -128)
01817 {
01818 return "moveq %1,%0";
01819 }
01820 if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
01821 return "sub%.l %0,%0";
01822 if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
01823 return "move%.l %1,%0";
01824
01825
01826 if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
01827 return "move%.w %1,%0";
01828 return "move%.b %1,%0";
01829 }
01830
01831 const char *
01832 output_move_stricthi (rtx *operands)
01833 {
01834 if (operands[1] == const0_rtx
01835
01836
01837 && ((TARGET_68020 || TARGET_COLDFIRE)
01838 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
01839 return "clr%.w %0";
01840 return "move%.w %1,%0";
01841 }
01842
01843 const char *
01844 output_move_strictqi (rtx *operands)
01845 {
01846 if (operands[1] == const0_rtx
01847
01848
01849 && ((TARGET_68020 || TARGET_COLDFIRE)
01850 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
01851 return "clr%.b %0";
01852 return "move%.b %1,%0";
01853 }
01854
01855
01856
01857
01858 static const char *
01859 singlemove_string (rtx *operands)
01860 {
01861 if (GET_CODE (operands[1]) == CONST_INT)
01862 return output_move_simode_const (operands);
01863 return "move%.l %1,%0";
01864 }
01865
01866
01867
01868
01869
01870 const char *
01871 output_move_double (rtx *operands)
01872 {
01873 enum
01874 {
01875 REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
01876 } optype0, optype1;
01877 rtx latehalf[2];
01878 rtx middlehalf[2];
01879 rtx xops[2];
01880 rtx addreg0 = 0, addreg1 = 0;
01881 int dest_overlapped_low = 0;
01882 int size = GET_MODE_SIZE (GET_MODE (operands[0]));
01883
01884 middlehalf[0] = 0;
01885 middlehalf[1] = 0;
01886
01887
01888
01889 if (REG_P (operands[0]))
01890 optype0 = REGOP;
01891 else if (offsettable_memref_p (operands[0]))
01892 optype0 = OFFSOP;
01893 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
01894 optype0 = POPOP;
01895 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
01896 optype0 = PUSHOP;
01897 else if (GET_CODE (operands[0]) == MEM)
01898 optype0 = MEMOP;
01899 else
01900 optype0 = RNDOP;
01901
01902 if (REG_P (operands[1]))
01903 optype1 = REGOP;
01904 else if (CONSTANT_P (operands[1]))
01905 optype1 = CNSTOP;
01906 else if (offsettable_memref_p (operands[1]))
01907 optype1 = OFFSOP;
01908 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
01909 optype1 = POPOP;
01910 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
01911 optype1 = PUSHOP;
01912 else if (GET_CODE (operands[1]) == MEM)
01913 optype1 = MEMOP;
01914 else
01915 optype1 = RNDOP;
01916
01917
01918
01919
01920
01921 if (optype0 == RNDOP || optype1 == RNDOP)
01922 abort ();
01923
01924
01925
01926
01927
01928 if (optype0 == PUSHOP && optype1 == POPOP)
01929 {
01930 operands[0] = XEXP (XEXP (operands[0], 0), 0);
01931 if (size == 12)
01932 output_asm_insn ("sub%.l #12,%0", operands);
01933 else
01934 output_asm_insn ("subq%.l #8,%0", operands);
01935 if (GET_MODE (operands[1]) == XFmode)
01936 operands[0] = gen_rtx_MEM (XFmode, operands[0]);
01937 else if (GET_MODE (operands[0]) == DFmode)
01938 operands[0] = gen_rtx_MEM (DFmode, operands[0]);
01939 else
01940 operands[0] = gen_rtx_MEM (DImode, operands[0]);
01941 optype0 = OFFSOP;
01942 }
01943 if (optype0 == POPOP && optype1 == PUSHOP)
01944 {
01945 operands[1] = XEXP (XEXP (operands[1], 0), 0);
01946 if (size == 12)
01947 output_asm_insn ("sub%.l #12,%1", operands);
01948 else
01949 output_asm_insn ("subq%.l #8,%1", operands);
01950 if (GET_MODE (operands[1]) == XFmode)
01951 operands[1] = gen_rtx_MEM (XFmode, operands[1]);
01952 else if (GET_MODE (operands[1]) == DFmode)
01953 operands[1] = gen_rtx_MEM (DFmode, operands[1]);
01954 else
01955 operands[1] = gen_rtx_MEM (DImode, operands[1]);
01956 optype1 = OFFSOP;
01957 }
01958
01959
01960
01961
01962 if (optype0 == MEMOP)
01963 addreg0 = find_addr_reg (XEXP (operands[0], 0));
01964
01965 if (optype1 == MEMOP)
01966 addreg1 = find_addr_reg (XEXP (operands[1], 0));
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977 if (size == 12)
01978 {
01979 if (optype0 == REGOP)
01980 {
01981 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
01982 middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
01983 }
01984 else if (optype0 == OFFSOP)
01985 {
01986 middlehalf[0] = adjust_address (operands[0], SImode, 4);
01987 latehalf[0] = adjust_address (operands[0], SImode, size - 4);
01988 }
01989 else
01990 {
01991 middlehalf[0] = operands[0];
01992 latehalf[0] = operands[0];
01993 }
01994
01995 if (optype1 == REGOP)
01996 {
01997 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
01998 middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
01999 }
02000 else if (optype1 == OFFSOP)
02001 {
02002 middlehalf[1] = adjust_address (operands[1], SImode, 4);
02003 latehalf[1] = adjust_address (operands[1], SImode, size - 4);
02004 }
02005 else if (optype1 == CNSTOP)
02006 {
02007 if (GET_CODE (operands[1]) == CONST_DOUBLE)
02008 {
02009 REAL_VALUE_TYPE r;
02010 long l[3];
02011
02012 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
02013 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
02014 operands[1] = GEN_INT (l[0]);
02015 middlehalf[1] = GEN_INT (l[1]);
02016 latehalf[1] = GEN_INT (l[2]);
02017 }
02018 else if (CONSTANT_P (operands[1]))
02019 {
02020
02021
02022 abort ();
02023 if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
02024 latehalf[1] = constm1_rtx;
02025 else
02026 latehalf[1] = const0_rtx;
02027 }
02028 }
02029 else
02030 {
02031 middlehalf[1] = operands[1];
02032 latehalf[1] = operands[1];
02033 }
02034 }
02035 else
02036
02037 {
02038 if (optype0 == REGOP)
02039 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02040 else if (optype0 == OFFSOP)
02041 latehalf[0] = adjust_address (operands[0], SImode, size - 4);
02042 else
02043 latehalf[0] = operands[0];
02044
02045 if (optype1 == REGOP)
02046 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
02047 else if (optype1 == OFFSOP)
02048 latehalf[1] = adjust_address (operands[1], SImode, size - 4);
02049 else if (optype1 == CNSTOP)
02050 split_double (operands[1], &operands[1], &latehalf[1]);
02051 else
02052 latehalf[1] = operands[1];
02053 }
02054
02055
02056
02057
02058 if (optype0 == PUSHOP
02059 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
02060 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
02061 operands[1] = middlehalf[1] = latehalf[1];
02062
02063
02064
02065
02066
02067
02068 if (optype0 == REGOP
02069 && (optype1 == OFFSOP || optype1 == MEMOP))
02070 {
02071 rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
02072
02073 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
02074 && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
02075 {
02076
02077
02078
02079 compadr:
02080 xops[0] = latehalf[0];
02081 xops[1] = XEXP (operands[1], 0);
02082 output_asm_insn ("lea %a1,%0", xops);
02083 if (GET_MODE (operands[1]) == XFmode )
02084 {
02085 operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
02086 middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
02087 latehalf[1] = adjust_address (operands[1], DImode, size - 4);
02088 }
02089 else
02090 {
02091 operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
02092 latehalf[1] = adjust_address (operands[1], DImode, size - 4);
02093 }
02094 }
02095 else if (size == 12
02096 && reg_overlap_mentioned_p (middlehalf[0],
02097 XEXP (operands[1], 0)))
02098 {
02099
02100
02101
02102
02103
02104
02105 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
02106 || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
02107 goto compadr;
02108
02109
02110 if (addreg0 || addreg1)
02111 abort ();
02112
02113
02114 output_asm_insn (singlemove_string (operands), operands);
02115 output_asm_insn (singlemove_string (latehalf), latehalf);
02116 output_asm_insn (singlemove_string (middlehalf), middlehalf);
02117 return "";
02118 }
02119 else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
02120
02121
02122 dest_overlapped_low = 1;
02123 }
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133 if (optype0 == PUSHOP || optype1 == PUSHOP
02134 || (optype0 == REGOP && optype1 == REGOP
02135 && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
02136 || REGNO (operands[0]) == REGNO (latehalf[1])))
02137 || dest_overlapped_low)
02138 {
02139
02140 if (addreg0)
02141 {
02142 if (size == 12)
02143 output_asm_insn ("addq%.l #8,%0", &addreg0);
02144 else
02145 output_asm_insn ("addq%.l #4,%0", &addreg0);
02146 }
02147 if (addreg1)
02148 {
02149 if (size == 12)
02150 output_asm_insn ("addq%.l #8,%0", &addreg1);
02151 else
02152 output_asm_insn ("addq%.l #4,%0", &addreg1);
02153 }
02154
02155
02156 output_asm_insn (singlemove_string (latehalf), latehalf);
02157
02158
02159 if (addreg0)
02160 output_asm_insn ("subq%.l #4,%0", &addreg0);
02161 if (addreg1)
02162 output_asm_insn ("subq%.l #4,%0", &addreg1);
02163
02164 if (size == 12)
02165 {
02166 output_asm_insn (singlemove_string (middlehalf), middlehalf);
02167 if (addreg0)
02168 output_asm_insn ("subq%.l #4,%0", &addreg0);
02169 if (addreg1)
02170 output_asm_insn ("subq%.l #4,%0", &addreg1);
02171 }
02172
02173
02174 return singlemove_string (operands);
02175 }
02176
02177
02178
02179 output_asm_insn (singlemove_string (operands), operands);
02180
02181
02182 if (size == 12)
02183 {
02184 if (addreg0)
02185 output_asm_insn ("addq%.l #4,%0", &addreg0);
02186 if (addreg1)
02187 output_asm_insn ("addq%.l #4,%0", &addreg1);
02188
02189 output_asm_insn (singlemove_string (middlehalf), middlehalf);
02190 }
02191
02192
02193 if (addreg0)
02194 output_asm_insn ("addq%.l #4,%0", &addreg0);
02195 if (addreg1)
02196 output_asm_insn ("addq%.l #4,%0", &addreg1);
02197
02198
02199 output_asm_insn (singlemove_string (latehalf), latehalf);
02200
02201
02202 if (addreg0)
02203 {
02204 if (size == 12)
02205 output_asm_insn ("subq%.l #8,%0", &addreg0);
02206 else
02207 output_asm_insn ("subq%.l #4,%0", &addreg0);
02208 }
02209 if (addreg1)
02210 {
02211 if (size == 12)
02212 output_asm_insn ("subq%.l #8,%0", &addreg1);
02213 else
02214 output_asm_insn ("subq%.l #4,%0", &addreg1);
02215 }
02216
02217 return "";
02218 }
02219
02220
02221
02222
02223 static rtx
02224 find_addr_reg (rtx addr)
02225 {
02226 while (GET_CODE (addr) == PLUS)
02227 {
02228 if (GET_CODE (XEXP (addr, 0)) == REG)
02229 addr = XEXP (addr, 0);
02230 else if (GET_CODE (XEXP (addr, 1)) == REG)
02231 addr = XEXP (addr, 1);
02232 else if (CONSTANT_P (XEXP (addr, 0)))
02233 addr = XEXP (addr, 1);
02234 else if (CONSTANT_P (XEXP (addr, 1)))
02235 addr = XEXP (addr, 0);
02236 else
02237 abort ();
02238 }
02239 if (GET_CODE (addr) == REG)
02240 return addr;
02241 abort ();
02242 }
02243
02244
02245
02246 const char *
02247 output_addsi3 (rtx *operands)
02248 {
02249 if (! operands_match_p (operands[0], operands[1]))
02250 {
02251 if (!ADDRESS_REG_P (operands[1]))
02252 {
02253 rtx tmp = operands[1];
02254
02255 operands[1] = operands[2];
02256 operands[2] = tmp;
02257 }
02258
02259
02260
02261 if (GET_CODE (operands[2]) == CONST_INT
02262 && (INTVAL (operands[2]) < -32768 || INTVAL (operands[2]) > 32767))
02263 return "move%.l %2,%0\n\tadd%.l %1,%0";
02264 if (GET_CODE (operands[2]) == REG)
02265 return MOTOROLA ? "lea (%1,%2.l),%0" : "lea %1@(0,%2:l),%0";
02266 return MOTOROLA ? "lea (%c2,%1),%0" : "lea %1@(%c2),%0";
02267 }
02268 if (GET_CODE (operands[2]) == CONST_INT)
02269 {
02270 if (INTVAL (operands[2]) > 0
02271 && INTVAL (operands[2]) <= 8)
02272 return "addq%.l %2,%0";
02273 if (INTVAL (operands[2]) < 0
02274 && INTVAL (operands[2]) >= -8)
02275 {
02276 operands[2] = GEN_INT (- INTVAL (operands[2]));
02277 return "subq%.l %2,%0";
02278 }
02279
02280
02281
02282 if (TARGET_CPU32 && REG_P (operands[0]))
02283 {
02284 if (INTVAL (operands[2]) > 8
02285 && INTVAL (operands[2]) <= 16)
02286 {
02287 operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
02288 return "addq%.l #8,%0\n\taddq%.l %2,%0";
02289 }
02290 if (INTVAL (operands[2]) < -8
02291 && INTVAL (operands[2]) >= -16)
02292 {
02293 operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
02294 return "subq%.l #8,%0\n\tsubq%.l %2,%0";
02295 }
02296 }
02297 if (ADDRESS_REG_P (operands[0])
02298 && INTVAL (operands[2]) >= -0x8000
02299 && INTVAL (operands[2]) < 0x8000)
02300 {
02301 if (TARGET_68040)
02302 return "add%.w %2,%0";
02303 else
02304 return MOTOROLA ? "lea (%c2,%0),%0" : "lea %0@(%c2),%0";
02305 }
02306 }
02307 return "add%.l %2,%0";
02308 }
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319 void
02320 notice_update_cc (rtx exp, rtx insn)
02321 {
02322 if (GET_CODE (exp) == SET)
02323 {
02324 if (GET_CODE (SET_SRC (exp)) == CALL)
02325 {
02326 CC_STATUS_INIT;
02327 }
02328 else if (ADDRESS_REG_P (SET_DEST (exp)))
02329 {
02330 if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
02331 cc_status.value1 = 0;
02332 if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
02333 cc_status.value2 = 0;
02334 }
02335 else if (!FP_REG_P (SET_DEST (exp))
02336 && SET_DEST (exp) != cc0_rtx
02337 && (FP_REG_P (SET_SRC (exp))
02338 || GET_CODE (SET_SRC (exp)) == FIX
02339 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
02340 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
02341 {
02342 CC_STATUS_INIT;
02343 }
02344
02345 else if (!FP_REG_P (SET_DEST (exp))
02346 && !FP_REG_P (SET_SRC (exp))
02347 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
02348 && (GET_CODE (SET_SRC (exp)) == REG
02349 || GET_CODE (SET_SRC (exp)) == MEM
02350 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
02351 {
02352 CC_STATUS_INIT;
02353 }
02354 else if (GET_CODE (SET_SRC (exp)) == CALL)
02355 {
02356 CC_STATUS_INIT;
02357 }
02358 else if (XEXP (exp, 0) != pc_rtx)
02359 {
02360 cc_status.flags = 0;
02361 cc_status.value1 = XEXP (exp, 0);
02362 cc_status.value2 = XEXP (exp, 1);
02363 }
02364 }
02365 else if (GET_CODE (exp) == PARALLEL
02366 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
02367 {
02368 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
02369 CC_STATUS_INIT;
02370 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
02371 {
02372 cc_status.flags = 0;
02373 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
02374 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
02375 }
02376 }
02377 else
02378 CC_STATUS_INIT;
02379 if (cc_status.value2 != 0
02380 && ADDRESS_REG_P (cc_status.value2)
02381 && GET_MODE (cc_status.value2) == QImode)
02382 CC_STATUS_INIT;
02383 if (cc_status.value2 != 0)
02384 switch (GET_CODE (cc_status.value2))
02385 {
02386 case ASHIFT: case ASHIFTRT: case LSHIFTRT:
02387 case ROTATE: case ROTATERT:
02388
02389
02390
02391
02392 CC_STATUS_INIT;
02393 break;
02394
02395 case PLUS: case MINUS: case MULT:
02396 case DIV: case UDIV: case MOD: case UMOD: case NEG:
02397 if (GET_MODE (cc_status.value2) != VOIDmode)
02398 cc_status.flags |= CC_NO_OVERFLOW;
02399 break;
02400 case ZERO_EXTEND:
02401
02402
02403
02404
02405 cc_status.flags |= CC_NOT_NEGATIVE;
02406
02407 default:
02408 break;
02409 }
02410 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
02411 && cc_status.value2
02412 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
02413 cc_status.value2 = 0;
02414 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
02415 || (cc_status.value2 && FP_REG_P (cc_status.value2))))
02416 cc_status.flags = CC_IN_68881;
02417 }
02418
02419 const char *
02420 output_move_const_double (rtx *operands)
02421 {
02422 int code = standard_68881_constant_p (operands[1]);
02423
02424 if (code != 0)
02425 {
02426 static char buf[40];
02427
02428 sprintf (buf, "fmovecr #0x%x,%%0", code & 0xff);
02429 return buf;
02430 }
02431 return "fmove%.d %1,%0";
02432 }
02433
02434 const char *
02435 output_move_const_single (rtx *operands)
02436 {
02437 int code = standard_68881_constant_p (operands[1]);
02438
02439 if (code != 0)
02440 {
02441 static char buf[40];
02442
02443 sprintf (buf, "fmovecr #0x%x,%%0", code & 0xff);
02444 return buf;
02445 }
02446 return "fmove%.s %f1,%0";
02447 }
02448
02449
02450
02451
02452
02453
02454
02455
02456 static int inited_68881_table = 0;
02457
02458 static const char *const strings_68881[7] = {
02459 "0.0",
02460 "1.0",
02461 "10.0",
02462 "100.0",
02463 "10000.0",
02464 "1e8",
02465 "1e16"
02466 };
02467
02468 static const int codes_68881[7] = {
02469 0x0f,
02470 0x32,
02471 0x33,
02472 0x34,
02473 0x35,
02474 0x36,
02475 0x37
02476 };
02477
02478 REAL_VALUE_TYPE values_68881[7];
02479
02480
02481
02482
02483 void
02484 init_68881_table (void)
02485 {
02486 int i;
02487 REAL_VALUE_TYPE r;
02488 enum machine_mode mode;
02489
02490 mode = SFmode;
02491 for (i = 0; i < 7; i++)
02492 {
02493 if (i == 6)
02494 mode = DFmode;
02495 r = REAL_VALUE_ATOF (strings_68881[i], mode);
02496 values_68881[i] = r;
02497 }
02498 inited_68881_table = 1;
02499 }
02500
02501 int
02502 standard_68881_constant_p (rtx x)
02503 {
02504 REAL_VALUE_TYPE r;
02505 int i;
02506
02507
02508
02509 if (TARGET_68040 || TARGET_68060)
02510 return 0;
02511
02512 if (! inited_68881_table)
02513 init_68881_table ();
02514
02515 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02516
02517
02518
02519 for (i = 0; i < 6; i++)
02520 {
02521 if (REAL_VALUES_IDENTICAL (r, values_68881[i]))
02522 return (codes_68881[i]);
02523 }
02524
02525 if (GET_MODE (x) == SFmode)
02526 return 0;
02527
02528 if (REAL_VALUES_EQUAL (r, values_68881[6]))
02529 return (codes_68881[6]);
02530
02531
02532
02533 return 0;
02534 }
02535
02536
02537
02538
02539 int
02540 floating_exact_log2 (rtx x)
02541 {
02542 REAL_VALUE_TYPE r, r1;
02543 int exp;
02544
02545 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02546
02547 if (REAL_VALUES_LESS (r, dconst1))
02548 return 0;
02549
02550 exp = real_exponent (&r);
02551 real_2expN (&r1, exp);
02552 if (REAL_VALUES_EQUAL (r1, r))
02553 return exp;
02554
02555 return 0;
02556 }
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604 void
02605 print_operand (FILE *file, rtx op, int letter)
02606 {
02607 if (letter == '.')
02608 {
02609 if (MOTOROLA)
02610 fprintf (file, ".");
02611 }
02612 else if (letter == '#')
02613 asm_fprintf (file, "%I");
02614 else if (letter == '-')
02615 asm_fprintf (file, MOTOROLA ? "-(%Rsp)" : "%Rsp@-");
02616 else if (letter == '+')
02617 asm_fprintf (file, MOTOROLA ? "(%Rsp)+" : "%Rsp@+");
02618 else if (letter == '@')
02619 asm_fprintf (file, MOTOROLA ? "(%Rsp)" : "%Rsp@");
02620 else if (letter == '!')
02621 asm_fprintf (file, "%Rfpcr");
02622 else if (letter == '$')
02623 {
02624 if (TARGET_68040_ONLY)
02625 fprintf (file, "s");
02626 }
02627 else if (letter == '&')
02628 {
02629 if (TARGET_68040_ONLY)
02630 fprintf (file, "d");
02631 }
02632 else if (letter == '/')
02633 asm_fprintf (file, "%R");
02634 else if (letter == 'o')
02635 {
02636
02637 if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
02638 || !TARGET_PCREL)
02639 abort ();
02640 output_addr_const (file, XEXP (op, 0));
02641 }
02642 else if (GET_CODE (op) == REG)
02643 {
02644 if (letter == 'R')
02645
02646
02647 fputs (M68K_REGNAME(REGNO (op) + 1), file);
02648 else
02649 fputs (M68K_REGNAME(REGNO (op)), file);
02650 }
02651 else if (GET_CODE (op) == MEM)
02652 {
02653 output_address (XEXP (op, 0));
02654 if (letter == 'd' && ! TARGET_68020
02655 && CONSTANT_ADDRESS_P (XEXP (op, 0))
02656 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
02657 && INTVAL (XEXP (op, 0)) < 0x8000
02658 && INTVAL (XEXP (op, 0)) >= -0x8000))
02659 fprintf (file, MOTOROLA ? ".l" : ":l");
02660 }
02661 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
02662 {
02663 REAL_VALUE_TYPE r;
02664 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
02665 ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
02666 }
02667 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
02668 {
02669 REAL_VALUE_TYPE r;
02670 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
02671 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
02672 }
02673 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
02674 {
02675 REAL_VALUE_TYPE r;
02676 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
02677 ASM_OUTPUT_DOUBLE_OPERAND (file, r);
02678 }
02679 else
02680 {
02681
02682
02683 asm_fprintf (file, "%I");
02684 if (TARGET_PCREL
02685 && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
02686 print_operand_address (file, op);
02687 else
02688 output_addr_const (file, op);
02689 }
02690 }
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723 #if MOTOROLA
02724 # define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
02725 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
02726 #else
02727 # define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
02728 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
02729 #endif
02730
02731 void
02732 print_operand_address (FILE *file, rtx addr)
02733 {
02734 register rtx reg1, reg2, breg, ireg;
02735 rtx offset;
02736
02737 switch (GET_CODE (addr))
02738 {
02739 case REG:
02740 fprintf (file, MOTOROLA ? "(%s)" : "%s@", M68K_REGNAME(REGNO (addr)));
02741 break;
02742 case PRE_DEC:
02743 fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
02744 M68K_REGNAME(REGNO (XEXP (addr, 0))));
02745 break;
02746 case POST_INC:
02747 fprintf (file, MOTOROLA ? "(%s)+" : "%s@+",
02748 M68K_REGNAME(REGNO (XEXP (addr, 0))));
02749 break;
02750 case PLUS:
02751 reg1 = reg2 = ireg = breg = offset = 0;
02752 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
02753 {
02754 offset = XEXP (addr, 0);
02755 addr = XEXP (addr, 1);
02756 }
02757 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
02758 {
02759 offset = XEXP (addr, 1);
02760 addr = XEXP (addr, 0);
02761 }
02762 if (GET_CODE (addr) != PLUS)
02763 {
02764 ;
02765 }
02766 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
02767 {
02768 reg1 = XEXP (addr, 0);
02769 addr = XEXP (addr, 1);
02770 }
02771 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
02772 {
02773 reg1 = XEXP (addr, 1);
02774 addr = XEXP (addr, 0);
02775 }
02776 else if (GET_CODE (XEXP (addr, 0)) == MULT)
02777 {
02778 reg1 = XEXP (addr, 0);
02779 addr = XEXP (addr, 1);
02780 }
02781 else if (GET_CODE (XEXP (addr, 1)) == MULT)
02782 {
02783 reg1 = XEXP (addr, 1);
02784 addr = XEXP (addr, 0);
02785 }
02786 else if (GET_CODE (XEXP (addr, 0)) == REG)
02787 {
02788 reg1 = XEXP (addr, 0);
02789 addr = XEXP (addr, 1);
02790 }
02791 else if (GET_CODE (XEXP (addr, 1)) == REG)
02792 {
02793 reg1 = XEXP (addr, 1);
02794 addr = XEXP (addr, 0);
02795 }
02796 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
02797 || GET_CODE (addr) == SIGN_EXTEND)
02798 {
02799 if (reg1 == 0)
02800 {
02801 reg1 = addr;
02802 }
02803 else
02804 {
02805 reg2 = addr;
02806 }
02807 addr = 0;
02808 }
02809 #if 0
02810 else if (GET_CODE (addr) == PLUS)
02811 {
02812 if (GET_CODE (XEXP (addr, 0)) == REG)
02813 {
02814 reg2 = XEXP (addr, 0);
02815 addr = XEXP (addr, 1);
02816 }
02817 else if (GET_CODE (XEXP (addr, 1)) == REG)
02818 {
02819 reg2 = XEXP (addr, 1);
02820 addr = XEXP (addr, 0);
02821 }
02822 }
02823 #endif
02824 if (offset != 0)
02825 {
02826 if (addr != 0)
02827 {
02828 abort ();
02829 }
02830 addr = offset;
02831 }
02832 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
02833 || GET_CODE (reg1) == MULT))
02834 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
02835 {
02836 breg = reg2;
02837 ireg = reg1;
02838 }
02839 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
02840 {
02841 breg = reg1;
02842 ireg = reg2;
02843 }
02844 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
02845 && ! (flag_pic && ireg == pic_offset_table_rtx))
02846 {
02847 int scale = 1;
02848 if (GET_CODE (ireg) == MULT)
02849 {
02850 scale = INTVAL (XEXP (ireg, 1));
02851 ireg = XEXP (ireg, 0);
02852 }
02853 if (GET_CODE (ireg) == SIGN_EXTEND)
02854 {
02855 ASM_OUTPUT_CASE_FETCH (file,
02856 CODE_LABEL_NUMBER (XEXP (addr, 0)),
02857 M68K_REGNAME(REGNO (XEXP (ireg, 0))));
02858 fprintf (file, "w");
02859 }
02860 else
02861 {
02862 ASM_OUTPUT_CASE_FETCH (file,
02863 CODE_LABEL_NUMBER (XEXP (addr, 0)),
02864 M68K_REGNAME(REGNO (ireg)));
02865 fprintf (file, "l");
02866 }
02867 if (scale != 1)
02868 fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
02869 putc (')', file);
02870 break;
02871 }
02872 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
02873 && ! (flag_pic && breg == pic_offset_table_rtx))
02874 {
02875 ASM_OUTPUT_CASE_FETCH (file,
02876 CODE_LABEL_NUMBER (XEXP (addr, 0)),
02877 M68K_REGNAME(REGNO (breg)));
02878 fprintf (file, "l)");
02879 break;
02880 }
02881 if (ireg != 0 || breg != 0)
02882 {
02883 int scale = 1;
02884 if (breg == 0)
02885 {
02886 abort ();
02887 }
02888 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
02889 {
02890 abort ();
02891 }
02892 if (MOTOROLA)
02893 {
02894 if (addr != 0)
02895 {
02896 output_addr_const (file, addr);
02897 if (flag_pic && (breg == pic_offset_table_rtx))
02898 {
02899 fprintf (file, "@GOT");
02900 if (flag_pic == 1)
02901 fprintf (file, ".w");
02902 }
02903 }
02904 fprintf (file, "(%s", M68K_REGNAME(REGNO (breg)));
02905 if (ireg != 0)
02906 putc (',', file);
02907 }
02908 else
02909 {
02910 fprintf (file, "%s@(", M68K_REGNAME(REGNO (breg)));
02911 if (addr != 0)
02912 {
02913 output_addr_const (file, addr);
02914 if (breg == pic_offset_table_rtx)
02915 switch (flag_pic)
02916 {
02917 case 1:
02918 fprintf (file, ":w"); break;
02919 case 2:
02920 fprintf (file, ":l"); break;
02921 default:
02922 break;
02923 }
02924 if (ireg != 0)
02925 putc (',', file);
02926 }
02927 }
02928 if (ireg != 0 && GET_CODE (ireg) == MULT)
02929 {
02930 scale = INTVAL (XEXP (ireg, 1));
02931 ireg = XEXP (ireg, 0);
02932 }
02933 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
02934 fprintf (file, MOTOROLA ? "%s.w" : "%s:w",
02935 M68K_REGNAME(REGNO (XEXP (ireg, 0))));
02936 else if (ireg != 0)
02937 fprintf (file, MOTOROLA ? "%s.l" : "%s:l",
02938 M68K_REGNAME(REGNO (ireg)));
02939 if (scale != 1)
02940 fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
02941 putc (')', file);
02942 break;
02943 }
02944 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
02945 && ! (flag_pic && reg1 == pic_offset_table_rtx))
02946 {
02947 ASM_OUTPUT_CASE_FETCH (file,
02948 CODE_LABEL_NUMBER (XEXP (addr, 0)),
02949 M68K_REGNAME(REGNO (reg1)));
02950 fprintf (file, "l)");
02951 break;
02952 }
02953
02954 default:
02955 if (GET_CODE (addr) == CONST_INT
02956 && INTVAL (addr) < 0x8000
02957 && INTVAL (addr) >= -0x8000)
02958 {
02959 fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr));
02960 }
02961 else if (GET_CODE (addr) == CONST_INT)
02962 {
02963 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
02964 }
02965 else if (TARGET_PCREL)
02966 {
02967 fputc ('(', file);
02968 output_addr_const (file, addr);
02969 if (flag_pic == 1)
02970 asm_fprintf (file, ":w,%Rpc)");
02971 else
02972 asm_fprintf (file, ":l,%Rpc)");
02973 }
02974 else
02975 {
02976
02977
02978
02979 if (GET_CODE (addr) == SYMBOL_REF
02980 && strlen (XSTR (addr, 0)) > 2
02981 && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
02982 {
02983 putc ('(', file);
02984 output_addr_const (file, addr);
02985 putc (')', file);
02986 }
02987 else
02988 output_addr_const (file, addr);
02989 }
02990 break;
02991 }
02992 }
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002 bool
03003 strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn,
03004 rtx target)
03005 {
03006 rtx p;
03007
03008 p = prev_nonnote_insn (first_insn);
03009
03010 while (p)
03011 {
03012
03013 if (GET_CODE (p) != INSN)
03014 return false;
03015
03016 if (reg_set_p (target, p))
03017 {
03018 rtx set = single_set (p);
03019 rtx dest;
03020
03021
03022 if (! set)
03023 return false;
03024
03025 dest = SET_DEST (set);
03026
03027
03028
03029 if (rtx_equal_p (dest, target)
03030 && SET_SRC (set) == const0_rtx)
03031 return true;
03032 else if (GET_CODE (dest) == STRICT_LOW_PART
03033 && GET_CODE (XEXP (dest, 0)) == REG
03034 && REGNO (XEXP (dest, 0)) == REGNO (target)
03035 && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
03036 <= GET_MODE_SIZE (mode)))
03037
03038
03039 ;
03040 else
03041 return false;
03042 }
03043
03044 p = prev_nonnote_insn (p);
03045 }
03046
03047 return false;
03048 }
03049
03050
03051
03052
03053
03054 int
03055 const_uint32_operand (rtx op, enum machine_mode mode)
03056 {
03057
03058
03059 if (GET_MODE_BITSIZE (mode) <= 32)
03060 abort ();
03061
03062 #if HOST_BITS_PER_WIDE_INT > 32
03063
03064 return (GET_CODE (op) == CONST_INT
03065 && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
03066 #else
03067 return (GET_CODE (op) == CONST_INT
03068 || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
03069 #endif
03070 }
03071
03072
03073
03074
03075
03076 int
03077 const_sint32_operand (rtx op, enum machine_mode mode)
03078 {
03079
03080
03081 if (GET_MODE_BITSIZE (mode) <= 32)
03082 abort ();
03083
03084
03085 return (GET_CODE (op) == CONST_INT
03086 && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
03087 }
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150 int
03151 general_src_operand (rtx op, enum machine_mode mode)
03152 {
03153 if (TARGET_PCREL
03154 && GET_CODE (op) == MEM
03155 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
03156 || GET_CODE (XEXP (op, 0)) == LABEL_REF
03157 || GET_CODE (XEXP (op, 0)) == CONST))
03158 return 1;
03159 return general_operand (op, mode);
03160 }
03161
03162
03163
03164
03165
03166 int
03167 nonimmediate_src_operand (rtx op, enum machine_mode mode)
03168 {
03169 if (TARGET_PCREL && GET_CODE (op) == MEM
03170 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
03171 || GET_CODE (XEXP (op, 0)) == LABEL_REF
03172 || GET_CODE (XEXP (op, 0)) == CONST))
03173 return 1;
03174 return nonimmediate_operand (op, mode);
03175 }
03176
03177
03178
03179
03180
03181 int
03182 memory_src_operand (rtx op, enum machine_mode mode)
03183 {
03184 if (TARGET_PCREL && GET_CODE (op) == MEM
03185 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
03186 || GET_CODE (XEXP (op, 0)) == LABEL_REF
03187 || GET_CODE (XEXP (op, 0)) == CONST))
03188 return 1;
03189 return memory_operand (op, mode);
03190 }
03191
03192 int
03193 post_inc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03194 {
03195 return MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC;
03196 }
03197
03198 int
03199 pre_dec_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03200 {
03201 return MEM_P (op) && GET_CODE (XEXP (op, 0)) == PRE_DEC;
03202 }
03203
03204
03205
03206
03207
03208 int
03209 pcrel_address (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03210 {
03211 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
03212 || GET_CODE (op) == CONST);
03213 }
03214
03215 const char *
03216 output_andsi3 (rtx *operands)
03217 {
03218 int logval;
03219 if (GET_CODE (operands[2]) == CONST_INT
03220 && (INTVAL (operands[2]) | 0xffff) == -1
03221 && (DATA_REG_P (operands[0])
03222 || offsettable_memref_p (operands[0]))
03223 && !TARGET_COLDFIRE)
03224 {
03225 if (GET_CODE (operands[0]) != REG)
03226 operands[0] = adjust_address (operands[0], HImode, 2);
03227 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
03228
03229 CC_STATUS_INIT;
03230 if (operands[2] == const0_rtx)
03231 return "clr%.w %0";
03232 return "and%.w %2,%0";
03233 }
03234 if (GET_CODE (operands[2]) == CONST_INT
03235 && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
03236 && (DATA_REG_P (operands[0])
03237 || offsettable_memref_p (operands[0])))
03238 {
03239 if (DATA_REG_P (operands[0]))
03240 {
03241 operands[1] = GEN_INT (logval);
03242 }
03243 else
03244 {
03245 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
03246 operands[1] = GEN_INT (logval % 8);
03247 }
03248
03249 CC_STATUS_INIT;
03250 return "bclr %1,%0";
03251 }
03252 return "and%.l %2,%0";
03253 }
03254
03255 const char *
03256 output_iorsi3 (rtx *operands)
03257 {
03258 register int logval;
03259 if (GET_CODE (operands[2]) == CONST_INT
03260 && INTVAL (operands[2]) >> 16 == 0
03261 && (DATA_REG_P (operands[0])
03262 || offsettable_memref_p (operands[0]))
03263 && !TARGET_COLDFIRE)
03264 {
03265 if (GET_CODE (operands[0]) != REG)
03266 operands[0] = adjust_address (operands[0], HImode, 2);
03267
03268 CC_STATUS_INIT;
03269 if (INTVAL (operands[2]) == 0xffff)
03270 return "mov%.w %2,%0";
03271 return "or%.w %2,%0";
03272 }
03273 if (GET_CODE (operands[2]) == CONST_INT
03274 && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
03275 && (DATA_REG_P (operands[0])
03276 || offsettable_memref_p (operands[0])))
03277 {
03278 if (DATA_REG_P (operands[0]))
03279 operands[1] = GEN_INT (logval);
03280 else
03281 {
03282 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
03283 operands[1] = GEN_INT (logval % 8);
03284 }
03285 CC_STATUS_INIT;
03286 return "bset %1,%0";
03287 }
03288 return "or%.l %2,%0";
03289 }
03290
03291 const char *
03292 output_xorsi3 (rtx *operands)
03293 {
03294 register int logval;
03295 if (GET_CODE (operands[2]) == CONST_INT
03296 && INTVAL (operands[2]) >> 16 == 0
03297 && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
03298 && !TARGET_COLDFIRE)
03299 {
03300 if (! DATA_REG_P (operands[0]))
03301 operands[0] = adjust_address (operands[0], HImode, 2);
03302
03303 CC_STATUS_INIT;
03304 if (INTVAL (operands[2]) == 0xffff)
03305 return "not%.w %0";
03306 return "eor%.w %2,%0";
03307 }
03308 if (GET_CODE (operands[2]) == CONST_INT
03309 && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
03310 && (DATA_REG_P (operands[0])
03311 || offsettable_memref_p (operands[0])))
03312 {
03313 if (DATA_REG_P (operands[0]))
03314 operands[1] = GEN_INT (logval);
03315 else
03316 {
03317 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
03318 operands[1] = GEN_INT (logval % 8);
03319 }
03320 CC_STATUS_INIT;
03321 return "bchg %1,%0";
03322 }
03323 return "eor%.l %2,%0";
03324 }
03325
03326 #ifdef M68K_TARGET_COFF
03327
03328
03329
03330 static void
03331 m68k_coff_asm_named_section (const char *name, unsigned int flags,
03332 tree decl ATTRIBUTE_UNUSED)
03333 {
03334 char flagchar;
03335
03336 if (flags & SECTION_WRITE)
03337 flagchar = 'd';
03338 else
03339 flagchar = 'x';
03340
03341 fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
03342 }
03343
03344 #endif
03345
03346 static void
03347 m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
03348 HOST_WIDE_INT delta,
03349 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
03350 tree function)
03351 {
03352 rtx xops[1];
03353 const char *fmt;
03354
03355 if (delta > 0 && delta <= 8)
03356 asm_fprintf (file, MOTOROLA ?
03357 "\taddq.l %I%d,4(%Rsp)\n" :
03358 "\taddql %I%d,%Rsp@(4)\n",
03359 (int) delta);
03360 else if (delta < 0 && delta >= -8)
03361 asm_fprintf (file, MOTOROLA ?
03362 "\tsubq.l %I%d,4(%Rsp)\n" :
03363 "\tsubql %I%d,%Rsp@(4)\n",
03364 (int) -delta);
03365 else if (TARGET_COLDFIRE)
03366 {
03367
03368
03369
03370 if (delta >= -128 && delta <= 127)
03371 asm_fprintf (file, MOTOROLA ?
03372 "\tmoveq.l %I%wd,%Rd0\n" :
03373 "\tmoveql %I%wd,%Rd0\n", delta);
03374 else
03375 asm_fprintf (file, MOTOROLA ?
03376 "\tmove.l %I%wd,%Rd0\n" :
03377 "\tmovel %I%wd,%Rd0\n", delta);
03378 asm_fprintf (file, MOTOROLA ?
03379 "\tadd.l %Rd0,4(%Rsp)\n" :
03380 "\taddl %Rd0,%Rsp@(4)\n");
03381 }
03382 else
03383 asm_fprintf (file, MOTOROLA ?
03384 "\tadd.l %I%wd,4(%Rsp)\n" :
03385 "\taddl %I%wd,%Rsp@(4)\n",
03386 delta);
03387
03388 xops[0] = DECL_RTL (function);
03389
03390
03391 if (flag_pic)
03392 {
03393 if (TARGET_PCREL)
03394 fmt = "bra.l %o0";
03395 else if ((flag_pic == 1) || TARGET_68020)
03396 {
03397 if (MOTOROLA)
03398 #if defined(USE_GAS)
03399 fmt = "bra.l %0@PLTPC";
03400 #else
03401 fmt = "bra %0@PLTPC";
03402 #endif
03403 else
03404 #ifdef USE_GAS
03405 fmt = "bra.l %0";
03406 #else
03407 fmt = "jra %0,a1";
03408 #endif
03409 }
03410 else if (optimize_size || TARGET_ID_SHARED_LIBRARY)
03411 fmt = "move.l %0@GOT(%%a5), %%a1\n\tjmp (%%a1)";
03412 else
03413 fmt = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)";
03414 }
03415 else
03416 {
03417 #if MOTOROLA && !defined (USE_GAS)
03418 fmt = "jmp %0";
03419 #else
03420 fmt = "jra %0";
03421 #endif
03422 }
03423
03424 output_asm_insn (fmt, xops);
03425 }
03426
03427
03428
03429 static rtx
03430 m68k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
03431 int incoming ATTRIBUTE_UNUSED)
03432 {
03433 return gen_rtx_REG (Pmode, M68K_STRUCT_VALUE_REGNUM);
03434 }
03435
03436
03437 int
03438 m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
03439 unsigned int new_reg)
03440 {
03441
03442
03443
03444
03445
03446 if (m68k_interrupt_function_p (current_function_decl)
03447 && !regs_ever_live[new_reg])
03448 return 0;
03449
03450 return 1;
03451 }
03452
03453
03454
03455
03456 bool
03457 m68k_regno_mode_ok (int regno, enum machine_mode mode)
03458 {
03459 if (regno < 8)
03460 {
03461
03462 if (regno + GET_MODE_SIZE (mode) / 4 <= 8)
03463 return true;
03464 }
03465 else if (regno < 16)
03466 {
03467
03468
03469 if (GET_MODE_SIZE (mode) == 1)
03470 return false;
03471 if (regno + GET_MODE_SIZE (mode) / 4 <= 16)
03472 return true;
03473 }
03474 else if (regno < 24)
03475 {
03476
03477
03478 if ((GET_MODE_CLASS (mode) == MODE_FLOAT
03479 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
03480 && GET_MODE_UNIT_SIZE (mode) <= 12)
03481 return true;
03482 }
03483 return false;
03484 }