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