00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "rtl.h"
00027 #include "regs.h"
00028 #include "hard-reg-set.h"
00029 #include "real.h"
00030 #include "insn-config.h"
00031 #include "conditions.h"
00032 #include "output.h"
00033 #include "insn-attr.h"
00034 #include "tree.h"
00035 #include "function.h"
00036 #include "expr.h"
00037 #include "libfuncs.h"
00038 #include "c-tree.h"
00039 #include "flags.h"
00040 #include "recog.h"
00041 #include "toplev.h"
00042 #include "tm_p.h"
00043 #include "target.h"
00044 #include "target-def.h"
00045
00046 extern int flag_traditional;
00047 extern FILE *asm_out_file;
00048
00049 const char *m88k_pound_sign = "";
00050 const char *m88k_short_data;
00051 const char *m88k_version;
00052 char m88k_volatile_code;
00053
00054 unsigned m88k_gp_threshold = 0;
00055 int m88k_prologue_done = 0;
00056 int m88k_function_number = 0;
00057 int m88k_fp_offset = 0;
00058 int m88k_stack_size = 0;
00059 int m88k_case_index;
00060
00061 rtx m88k_compare_reg;
00062 rtx m88k_compare_op0;
00063 rtx m88k_compare_op1;
00064
00065 enum processor_type m88k_cpu;
00066
00067 static void m88k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00068 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00069 static void m88k_output_function_end_prologue PARAMS ((FILE *));
00070 static void m88k_output_function_begin_epilogue PARAMS ((FILE *));
00071 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
00072 static void m88k_svr3_asm_out_constructor PARAMS ((rtx, int));
00073 static void m88k_svr3_asm_out_destructor PARAMS ((rtx, int));
00074 #endif
00075
00076 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00077
00078
00079 #undef TARGET_ASM_BYTE_OP
00080 #define TARGET_ASM_BYTE_OP "\tbyte\t"
00081 #undef TARGET_ASM_ALIGNED_HI_OP
00082 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
00083 #undef TARGET_ASM_ALIGNED_SI_OP
00084 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
00085 #undef TARGET_ASM_UNALIGNED_HI_OP
00086 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
00087 #undef TARGET_ASM_UNALIGNED_SI_OP
00088 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
00089
00090 #undef TARGET_ASM_FUNCTION_PROLOGUE
00091 #define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
00092 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
00093 #define TARGET_ASM_FUNCTION_END_PROLOGUE m88k_output_function_end_prologue
00094 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
00095 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE m88k_output_function_begin_epilogue
00096 #undef TARGET_ASM_FUNCTION_EPILOGUE
00097 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
00098
00099 #undef TARGET_SCHED_ADJUST_COST
00100 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
00101
00102 struct gcc_target targetm = TARGET_INITIALIZER;
00103
00104
00105
00106
00107 enum m88k_instruction
00108 classify_integer (mode, value)
00109 enum machine_mode mode;
00110 register int value;
00111 {
00112 if (value == 0)
00113 return m88k_zero;
00114 else if (SMALL_INTVAL (value))
00115 return m88k_or;
00116 else if (SMALL_INTVAL (-value))
00117 return m88k_subu;
00118 else if (mode == HImode)
00119 return m88k_or_lo16;
00120 else if (mode == QImode)
00121 return m88k_or_lo8;
00122 else if ((value & 0xffff) == 0)
00123 return m88k_oru_hi16;
00124 else if (integer_ok_for_set (value))
00125 return m88k_set;
00126 else
00127 return m88k_oru_or;
00128 }
00129
00130
00131
00132 int
00133 condition_value (condition)
00134 rtx condition;
00135 {
00136 switch (GET_CODE (condition))
00137 {
00138 case EQ: return 2;
00139 case NE: return 3;
00140 case GT: return 4;
00141 case LE: return 5;
00142 case LT: return 6;
00143 case GE: return 7;
00144 case GTU: return 8;
00145 case LEU: return 9;
00146 case LTU: return 10;
00147 case GEU: return 11;
00148 default: abort ();
00149 }
00150 }
00151
00152 int
00153 integer_ok_for_set (value)
00154 register unsigned value;
00155 {
00156
00157
00158 register unsigned mask = (value | (value - 1));
00159 return (value && POWER_OF_2_or_0 (mask + 1));
00160 }
00161
00162 const char *
00163 output_load_const_int (mode, operands)
00164 enum machine_mode mode;
00165 rtx *operands;
00166 {
00167 static const char *const patterns[] =
00168 { "or %0,%#r0,0",
00169 "or %0,%#r0,%1",
00170 "subu %0,%#r0,%n1",
00171 "or %0,%#r0,%h1",
00172 "or %0,%#r0,%q1",
00173 "set %0,%#r0,%s1",
00174 "or.u %0,%#r0,%X1",
00175 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
00176 };
00177
00178 if (! REG_P (operands[0])
00179 || GET_CODE (operands[1]) != CONST_INT)
00180 abort ();
00181 return patterns[classify_integer (mode, INTVAL (operands[1]))];
00182 }
00183
00184
00185
00186
00187 const char *
00188 output_load_const_float (operands)
00189 rtx *operands;
00190 {
00191
00192 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
00193 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
00194
00195 return output_load_const_int (SImode, operands);
00196 }
00197
00198 const char *
00199 output_load_const_double (operands)
00200 rtx *operands;
00201 {
00202 rtx latehalf[2];
00203
00204
00205
00206 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
00207 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
00208
00209 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
00210 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
00211
00212 output_asm_insn (output_load_const_int (SImode, operands), operands);
00213
00214 operands[0] = latehalf[0];
00215 operands[1] = latehalf[1];
00216
00217 return output_load_const_int (SImode, operands);
00218 }
00219
00220 const char *
00221 output_load_const_dimode (operands)
00222 rtx *operands;
00223 {
00224 rtx latehalf[2];
00225
00226 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
00227 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
00228
00229 operands[0] = operand_subword (operands[0], 0, 0, DImode);
00230 operands[1] = operand_subword (operands[1], 0, 0, DImode);
00231
00232 output_asm_insn (output_load_const_int (SImode, operands), operands);
00233
00234 operands[0] = latehalf[0];
00235 operands[1] = latehalf[1];
00236
00237 return output_load_const_int (SImode, operands);
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 int
00250 emit_move_sequence (operands, mode, scratch)
00251 rtx *operands;
00252 enum machine_mode mode;
00253 rtx scratch;
00254 {
00255 register rtx operand0 = operands[0];
00256 register rtx operand1 = operands[1];
00257
00258 if (CONSTANT_P (operand1) && flag_pic
00259 && pic_address_needs_scratch (operand1))
00260 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
00261
00262
00263 if (register_operand (operand0, mode))
00264 {
00265 if (register_operand (operand1, mode)
00266 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
00267 || GET_CODE (operand1) == HIGH
00268
00269 || GET_CODE (operand1) == MEM)
00270 {
00271
00272 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
00273 return 1;
00274 }
00275 }
00276 else if (GET_CODE (operand0) == MEM)
00277 {
00278 if (register_operand (operand1, mode)
00279 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
00280 {
00281
00282 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
00283 return 1;
00284 }
00285 if (! reload_in_progress && ! reload_completed)
00286 {
00287 operands[0] = validize_mem (operand0);
00288 operands[1] = operand1 = force_reg (mode, operand1);
00289 }
00290 }
00291
00292
00293 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
00294 {
00295 if (GET_CODE (operand1) != CONST_INT
00296 && GET_CODE (operand1) != CONST_DOUBLE)
00297 {
00298 rtx temp = ((reload_in_progress || reload_completed)
00299 ? operand0 : 0);
00300 operands[1] = legitimize_address (flag_pic
00301 && symbolic_address_p (operand1),
00302 operand1, temp, scratch);
00303 if (mode != SImode)
00304 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
00305 }
00306 }
00307
00308
00309 return 0;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 struct rtx_def *
00321 legitimize_address (pic, orig, reg, scratch)
00322 int pic;
00323 rtx orig;
00324 rtx reg;
00325 rtx scratch;
00326 {
00327 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
00328 rtx new = orig;
00329 rtx temp, insn;
00330
00331 if (pic)
00332 {
00333 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
00334 {
00335 if (reg == 0)
00336 {
00337 if (reload_in_progress || reload_completed)
00338 abort ();
00339 else
00340 reg = gen_reg_rtx (Pmode);
00341 }
00342
00343 if (flag_pic == 2)
00344 {
00345
00346
00347
00348 temp = ((reload_in_progress || reload_completed)
00349 ? reg : gen_reg_rtx (Pmode));
00350
00351 emit_insn (gen_rtx_SET
00352 (VOIDmode, temp,
00353 gen_rtx_HIGH (SImode,
00354 gen_rtx_UNSPEC (SImode,
00355 gen_rtvec (1, addr),
00356 0))));
00357
00358 emit_insn (gen_rtx_SET
00359 (VOIDmode, temp,
00360 gen_rtx_LO_SUM (SImode, temp,
00361 gen_rtx_UNSPEC (SImode,
00362 gen_rtvec (1, addr),
00363 0))));
00364 addr = temp;
00365 }
00366
00367 new = gen_rtx_MEM (Pmode,
00368 gen_rtx_PLUS (SImode,
00369 pic_offset_table_rtx, addr));
00370
00371 current_function_uses_pic_offset_table = 1;
00372 RTX_UNCHANGING_P (new) = 1;
00373 insn = emit_move_insn (reg, new);
00374
00375
00376 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
00377 REG_NOTES (insn));
00378 new = reg;
00379 }
00380 else if (GET_CODE (addr) == CONST)
00381 {
00382 rtx base;
00383
00384 if (GET_CODE (XEXP (addr, 0)) == PLUS
00385 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
00386 return orig;
00387
00388 if (reg == 0)
00389 {
00390 if (reload_in_progress || reload_completed)
00391 abort ();
00392 else
00393 reg = gen_reg_rtx (Pmode);
00394 }
00395
00396 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
00397
00398 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
00399 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
00400 base == reg ? 0 : reg, 0);
00401
00402 if (GET_CODE (addr) == CONST_INT)
00403 {
00404 if (ADD_INT (addr))
00405 return plus_constant (base, INTVAL (addr));
00406 else if (! reload_in_progress && ! reload_completed)
00407 addr = force_reg (Pmode, addr);
00408
00409
00410 else if (scratch)
00411 {
00412 emit_move_insn (scratch, addr);
00413 addr = scratch;
00414 }
00415 else
00416
00417
00418
00419 abort ();
00420 }
00421 new = gen_rtx_PLUS (SImode, base, addr);
00422
00423 }
00424 }
00425 else if (! SHORT_ADDRESS_P (addr, temp))
00426 {
00427 if (reg == 0)
00428 {
00429 if (reload_in_progress || reload_completed)
00430 abort ();
00431 else
00432 reg = gen_reg_rtx (Pmode);
00433 }
00434
00435 emit_insn (gen_rtx_SET (VOIDmode,
00436 reg, gen_rtx_HIGH (SImode, addr)));
00437 new = gen_rtx_LO_SUM (SImode, reg, addr);
00438 }
00439
00440 if (new != orig
00441 && GET_CODE (orig) == MEM)
00442 {
00443 new = gen_rtx_MEM (GET_MODE (orig), new);
00444 MEM_COPY_ATTRIBUTES (new, orig);
00445 }
00446 return new;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 #define MOVSTR_LOOP 64
00460 #define MOVSTR_QI 16
00461 #define MOVSTR_HI 48
00462 #define MOVSTR_SI 96
00463 #define MOVSTR_DI 96
00464 #define MOVSTR_ODD_HI 16
00465 #define MOVSTR_ODD_SI 48
00466
00467
00468 #define MOVSTR_ODD_DI 48
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 #define MOVSTR_QI_LIMIT_88100 13
00485 #define MOVSTR_HI_LIMIT_88100 38
00486 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
00487 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
00488
00489 #define MOVSTR_QI_LIMIT_88000 16
00490 #define MOVSTR_HI_LIMIT_88000 38
00491 #define MOVSTR_SI_LIMIT_88000 72
00492 #define MOVSTR_DI_LIMIT_88000 72
00493
00494 #define MOVSTR_QI_LIMIT_88110 16
00495 #define MOVSTR_HI_LIMIT_88110 38
00496 #define MOVSTR_SI_LIMIT_88110 72
00497 #define MOVSTR_DI_LIMIT_88110 72
00498
00499 static const enum machine_mode mode_from_align[] =
00500 {VOIDmode, QImode, HImode, VOIDmode, SImode,
00501 VOIDmode, VOIDmode, VOIDmode, DImode};
00502 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
00503 0, 0, 0, MOVSTR_DI};
00504 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
00505 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
00506
00507 static const int best_from_align[3][9] = {
00508 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
00509 0, 0, 0, MOVSTR_DI_LIMIT_88100},
00510 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
00511 0, 0, 0, MOVSTR_DI_LIMIT_88110},
00512 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
00513 0, 0, 0, MOVSTR_DI_LIMIT_88000}
00514 };
00515
00516 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
00517 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
00518 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
00519 static void output_short_branch_defs PARAMS ((FILE *));
00520 static int output_option PARAMS ((FILE *, const char *, const char *,
00521 const char *, const char *, int, int));
00522
00523
00524
00525
00526
00527
00528
00529
00530 void
00531 expand_block_move (dest_mem, src_mem, operands)
00532 rtx dest_mem;
00533 rtx src_mem;
00534 rtx *operands;
00535 {
00536 int align = INTVAL (operands[3]);
00537 int constp = (GET_CODE (operands[2]) == CONST_INT);
00538 int bytes = (constp ? INTVAL (operands[2]) : 0);
00539 int target = (int) m88k_cpu;
00540
00541 if (! (PROCESSOR_M88100 == 0
00542 && PROCESSOR_M88110 == 1
00543 && PROCESSOR_M88000 == 2))
00544 abort ();
00545
00546 if (constp && bytes <= 0)
00547 return;
00548
00549
00550 if (align > 4 && !TARGET_88110)
00551 align = 4;
00552 else if (align <= 0 || align == 3)
00553 abort ();
00554
00555 if (constp && bytes <= 3 * align)
00556 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
00557 bytes, align, 0);
00558
00559 else if (constp && bytes <= best_from_align[target][align])
00560 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
00561 bytes, align);
00562
00563 else if (constp && align == 4 && TARGET_88100)
00564 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
00565 bytes, align);
00566
00567 else
00568 {
00569 #ifdef TARGET_MEM_FUNCTIONS
00570 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
00571 VOIDmode, 3,
00572 operands[0], Pmode,
00573 operands[1], Pmode,
00574 convert_to_mode (TYPE_MODE (sizetype), operands[2],
00575 TREE_UNSIGNED (sizetype)),
00576 TYPE_MODE (sizetype));
00577 #else
00578 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
00579 VOIDmode, 3,
00580 operands[1], Pmode,
00581 operands[0], Pmode,
00582 convert_to_mode (TYPE_MODE (integer_type_node),
00583 operands[2],
00584 TREE_UNSIGNED (integer_type_node)),
00585 TYPE_MODE (integer_type_node));
00586 #endif
00587 }
00588 }
00589
00590
00591
00592
00593
00594 static void
00595 block_move_loop (dest, dest_mem, src, src_mem, size, align)
00596 rtx dest, dest_mem;
00597 rtx src, src_mem;
00598 int size;
00599 int align;
00600 {
00601 enum machine_mode mode;
00602 int count;
00603 int units;
00604 int remainder;
00605 rtx offset_rtx;
00606 rtx value_rtx;
00607 char entry[30];
00608 tree entry_name;
00609
00610
00611 if (align != 4)
00612 abort ();
00613
00614
00615 count = size / MOVSTR_LOOP;
00616 units = (size - count * MOVSTR_LOOP) / align;
00617
00618 if (units < 2)
00619 {
00620 count--;
00621 units += MOVSTR_LOOP / align;
00622 }
00623
00624 if (count <= 0)
00625 {
00626 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
00627 return;
00628 }
00629
00630 remainder = size - count * MOVSTR_LOOP - units * align;
00631
00632 mode = mode_from_align[align];
00633 sprintf (entry, "__movstr%s%dn%d",
00634 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
00635 entry_name = get_identifier (entry);
00636
00637 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
00638
00639 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
00640 gen_rtx_PLUS (Pmode,
00641 gen_rtx_REG (Pmode, 3),
00642 offset_rtx));
00643 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
00644
00645 emit_insn (gen_call_movstrsi_loop
00646 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
00647 dest, src, offset_rtx, value_rtx,
00648 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
00649 GEN_INT (count)));
00650
00651 if (remainder)
00652 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
00653 gen_rtx_REG (Pmode, 3), src_mem,
00654 remainder, align, MOVSTR_LOOP + align);
00655 }
00656
00657
00658
00659
00660
00661 static void
00662 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
00663 rtx dest, dest_mem;
00664 rtx src, src_mem;
00665 int size;
00666 int align;
00667 {
00668 enum machine_mode mode = mode_from_align[align];
00669 int units = size / align;
00670 int remainder = size - units * align;
00671 int most;
00672 int value_reg;
00673 rtx offset_rtx;
00674 rtx value_rtx;
00675 char entry[30];
00676 tree entry_name;
00677
00678 if (remainder && size <= all_from_align[align])
00679 {
00680 most = all_from_align[align] - (align - remainder);
00681 remainder = 0;
00682 }
00683 else
00684 {
00685 most = max_from_align[align];
00686 }
00687
00688 sprintf (entry, "__movstr%s%dx%d",
00689 GET_MODE_NAME (mode), most, size - remainder);
00690 entry_name = get_identifier (entry);
00691
00692 offset_rtx = GEN_INT (most - (size - remainder));
00693
00694 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
00695 gen_rtx_PLUS (Pmode,
00696 gen_rtx_REG (Pmode, 3),
00697 offset_rtx));
00698
00699 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
00700
00701 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
00702 ? (align == 8 ? 6 : 5) : 4);
00703
00704 emit_insn (gen_call_block_move
00705 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
00706 dest, src, offset_rtx, value_rtx,
00707 gen_rtx_REG (mode, value_reg)));
00708
00709 if (remainder)
00710 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
00711 gen_rtx_REG (Pmode, 3), src_mem,
00712 remainder, align, most);
00713 }
00714
00715
00716
00717
00718
00719
00720 static void
00721 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
00722 rtx dest, dest_mem;
00723 rtx src, src_mem;
00724 int size;
00725 int align;
00726 int offset;
00727 {
00728 rtx temp[2];
00729 enum machine_mode mode[2];
00730 int amount[2];
00731 int active[2];
00732 int phase = 0;
00733 int next;
00734 int offset_ld = offset;
00735 int offset_st = offset;
00736
00737 active[0] = active[1] = FALSE;
00738
00739
00740
00741 amount[0] = amount[1] = align;
00742 mode[0] = mode_from_align[align];
00743 temp[0] = gen_reg_rtx (mode[0]);
00744 if (size >= 2 * align)
00745 {
00746 mode[1] = mode[0];
00747 temp[1] = gen_reg_rtx (mode[1]);
00748 }
00749
00750 do
00751 {
00752 rtx srcp, dstp;
00753 next = phase;
00754 phase = !phase;
00755
00756 if (size > 0)
00757 {
00758
00759 if (size < amount[next])
00760 {
00761 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
00762 mode[next] = mode_from_align[amount[next]];
00763 temp[next] = gen_reg_rtx (mode[next]);
00764 }
00765 size -= amount[next];
00766 srcp = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
00767 plus_constant (src, offset_ld));
00768
00769 MEM_COPY_ATTRIBUTES (srcp, src_mem);
00770 emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
00771 offset_ld += amount[next];
00772 active[next] = TRUE;
00773 }
00774
00775 if (active[phase])
00776 {
00777 active[phase] = FALSE;
00778 dstp
00779 = gen_rtx_MEM (MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
00780 plus_constant (dest, offset_st));
00781
00782 MEM_COPY_ATTRIBUTES (dstp, dest_mem);
00783 emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
00784 offset_st += amount[phase];
00785 }
00786 }
00787 while (active[next]);
00788 }
00789
00790
00791
00792 const char *
00793 output_and (operands)
00794 rtx operands[];
00795 {
00796 unsigned int value;
00797
00798 if (REG_P (operands[2]))
00799 return "and %0,%1,%2";
00800
00801 value = INTVAL (operands[2]);
00802 if (SMALL_INTVAL (value))
00803 return "mask %0,%1,%2";
00804 else if ((value & 0xffff0000) == 0xffff0000)
00805 return "and %0,%1,%x2";
00806 else if ((value & 0xffff) == 0xffff)
00807 return "and.u %0,%1,%X2";
00808 else if ((value & 0xffff) == 0)
00809 return "mask.u %0,%1,%X2";
00810 else if (integer_ok_for_set (~value))
00811 return "clr %0,%1,%S2";
00812 else
00813 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
00814 }
00815
00816
00817
00818 const char *
00819 output_ior (operands)
00820 rtx operands[];
00821 {
00822 unsigned int value;
00823
00824 if (REG_P (operands[2]))
00825 return "or %0,%1,%2";
00826
00827 value = INTVAL (operands[2]);
00828 if (SMALL_INTVAL (value))
00829 return "or %0,%1,%2";
00830 else if ((value & 0xffff) == 0)
00831 return "or.u %0,%1,%X2";
00832 else if (integer_ok_for_set (value))
00833 return "set %0,%1,%s2";
00834 else
00835 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
00836 }
00837
00838
00839
00840 const char *
00841 output_xor (operands)
00842 rtx operands[];
00843 {
00844 unsigned int value;
00845
00846 if (REG_P (operands[2]))
00847 return "xor %0,%1,%2";
00848
00849 value = INTVAL (operands[2]);
00850 if (SMALL_INTVAL (value))
00851 return "xor %0,%1,%2";
00852 else if ((value & 0xffff) == 0)
00853 return "xor.u %0,%1,%X2";
00854 else
00855 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
00856 }
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 static rtx sb_name = 0;
00869 static rtx sb_high = 0;
00870 static rtx sb_low = 0;
00871
00872 const char *
00873 output_call (operands, addr)
00874 rtx operands[];
00875 rtx addr;
00876 {
00877 operands[0] = addr;
00878 if (final_sequence)
00879 {
00880 rtx jump;
00881 rtx seq_insn;
00882
00883
00884 if (XVECLEN (final_sequence, 0) != 2)
00885 abort ();
00886
00887
00888 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
00889 jump = XVECEXP (final_sequence, 0, 1);
00890 if (GET_CODE (jump) == JUMP_INSN)
00891 {
00892 rtx low, high;
00893 const char *last;
00894 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
00895 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
00896 - INSN_ADDRESSES (INSN_UID (seq_insn))
00897 - 2);
00898 #if (MONITOR_GCC & 0x2)
00899 if ((unsigned) (delta + 0x8000) >= 0x10000)
00900 warning ("internal gcc monitor: short-branch(%x)", delta);
00901 #endif
00902
00903
00904 PUT_CODE (jump, NOTE);
00905 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
00906 NOTE_SOURCE_FILE (jump) = 0;
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 #ifdef AS_BUG_IMMEDIATE_LABEL
00922 if (optimize < 2
00923 || ! ADD_INTVAL (delta * 2)
00924 #else
00925 if (optimize < 2
00926 || ! ADD_INTVAL (delta)
00927 #endif
00928 || (REG_P (addr) && REGNO (addr) == 1))
00929 {
00930 operands[1] = dest;
00931 return (REG_P (addr)
00932 ? "jsr %0\n\tbr %l1"
00933 : (flag_pic
00934 ? "bsr %0#plt\n\tbr %l1"
00935 : "bsr %0\n\tbr %l1"));
00936 }
00937
00938
00939 output_asm_insn ((REG_P (addr)
00940 ? "jsr.n %0"
00941 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
00942 operands);
00943
00944 #ifdef USE_GAS
00945 last = (delta < 0
00946 ? "subu %#r1,%#r1,.-%l0+4"
00947 : "addu %#r1,%#r1,%l0-.-4");
00948 operands[0] = dest;
00949 #else
00950 operands[0] = gen_label_rtx ();
00951 operands[1] = gen_label_rtx ();
00952 if (delta < 0)
00953 {
00954 low = dest;
00955 high = operands[1];
00956 last = "subu %#r1,%#r1,%l0\n%l1:";
00957 }
00958 else
00959 {
00960 low = operands[1];
00961 high = dest;
00962 last = "addu %#r1,%#r1,%l0\n%l1:";
00963 }
00964
00965
00966 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
00967 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
00968 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
00969 #endif
00970
00971 return last;
00972 }
00973 }
00974 return (REG_P (addr)
00975 ? "jsr%. %0"
00976 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
00977 }
00978
00979 static void
00980 output_short_branch_defs (stream)
00981 FILE *stream;
00982 {
00983 char name[256], high[256], low[256];
00984
00985 for (; sb_name && sb_high && sb_low;
00986 sb_name = XEXP (sb_name, 1),
00987 sb_high = XEXP (sb_high, 1),
00988 sb_low = XEXP (sb_low, 1))
00989 {
00990 ASM_GENERATE_INTERNAL_LABEL
00991 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
00992 ASM_GENERATE_INTERNAL_LABEL
00993 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
00994 ASM_GENERATE_INTERNAL_LABEL
00995 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
00996
00997 fprintf (stream, "%s%s,%s-%s\n",
00998 SET_ASM_OP, &name[1], &high[1], &low[1]);
00999 }
01000 if (sb_name || sb_high || sb_low)
01001 abort ();
01002 }
01003
01004
01005
01006
01007 int
01008 mostly_false_jump (jump_insn, condition)
01009 rtx jump_insn, condition;
01010 {
01011 rtx target_label = JUMP_LABEL (jump_insn);
01012 rtx insnt, insnj;
01013
01014
01015 if (optimize == 0)
01016 return 0;
01017
01018
01019 for (insnt = NEXT_INSN (target_label);
01020 insnt;
01021 insnt = NEXT_INSN (insnt))
01022 {
01023 if (GET_CODE (insnt) == JUMP_INSN)
01024 break;
01025 else if (GET_CODE (insnt) == INSN
01026 && GET_CODE (PATTERN (insnt)) == SEQUENCE
01027 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
01028 {
01029 insnt = XVECEXP (PATTERN (insnt), 0, 0);
01030 break;
01031 }
01032 }
01033 if (insnt
01034 && (GET_CODE (PATTERN (insnt)) == RETURN
01035 || (GET_CODE (PATTERN (insnt)) == SET
01036 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
01037 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
01038 insnt = 0;
01039
01040 for (insnj = NEXT_INSN (jump_insn);
01041 insnj;
01042 insnj = NEXT_INSN (insnj))
01043 {
01044 if (GET_CODE (insnj) == JUMP_INSN)
01045 break;
01046 else if (GET_CODE (insnj) == INSN
01047 && GET_CODE (PATTERN (insnj)) == SEQUENCE
01048 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
01049 {
01050 insnj = XVECEXP (PATTERN (insnj), 0, 0);
01051 break;
01052 }
01053 }
01054 if (insnj
01055 && (GET_CODE (PATTERN (insnj)) == RETURN
01056 || (GET_CODE (PATTERN (insnj)) == SET
01057 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
01058 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
01059 insnj = 0;
01060
01061
01062 if ((insnt == 0) != (insnj == 0))
01063 return (insnt == 0);
01064
01065
01066 for (insnt = PREV_INSN (target_label);
01067 insnt && GET_CODE (insnt) == NOTE;
01068 insnt = PREV_INSN (insnt))
01069 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
01070 return 1;
01071 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
01072 return 0;
01073 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
01074 return 0;
01075
01076
01077 if (final_sequence)
01078 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
01079 else
01080 insnj = jump_insn;
01081 if (INSN_ADDRESSES (INSN_UID (insnj))
01082 > INSN_ADDRESSES (INSN_UID (target_label)))
01083 return 0;
01084
01085
01086
01087
01088
01089 switch (GET_CODE (condition))
01090 {
01091 case CONST_INT:
01092
01093 return 0;
01094 case EQ:
01095 return 1;
01096 case NE:
01097 return 0;
01098 case LE:
01099 case LT:
01100 case GEU:
01101 case GTU:
01102 if (XEXP (condition, 1) == const0_rtx)
01103 return 1;
01104 break;
01105 case GE:
01106 case GT:
01107 case LEU:
01108 case LTU:
01109 if (XEXP (condition, 1) == const0_rtx)
01110 return 0;
01111 break;
01112 default:
01113 break;
01114 }
01115
01116 return 0;
01117 }
01118
01119
01120
01121
01122 int
01123 real_power_of_2_operand (op, mode)
01124 rtx op;
01125 enum machine_mode mode ATTRIBUTE_UNUSED;
01126 {
01127 union {
01128 REAL_VALUE_TYPE d;
01129 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
01130 struct {
01131 unsigned sign : 1;
01132 unsigned exponent : 11;
01133 unsigned mantissa1 : 20;
01134 unsigned mantissa2;
01135 } s;
01136 struct {
01137 unsigned sign : 1;
01138 unsigned exponent1 : 4;
01139 unsigned exponent2 : 7;
01140 unsigned mantissa1 : 20;
01141 unsigned mantissa2;
01142 } s2;
01143 } u;
01144
01145 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
01146 return 0;
01147
01148 if (GET_CODE (op) != CONST_DOUBLE)
01149 return 0;
01150
01151 u.i[0] = CONST_DOUBLE_LOW (op);
01152 u.i[1] = CONST_DOUBLE_HIGH (op);
01153
01154 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0
01155 || u.s.exponent == 0
01156 || u.s.exponent == 0x7ff
01157 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
01158 return 0;
01159
01160 return 1;
01161 }
01162
01163
01164
01165
01166
01167 struct rtx_def *
01168 legitimize_operand (op, mode)
01169 rtx op;
01170 enum machine_mode mode;
01171 {
01172 rtx temp;
01173 union {
01174 union real_extract r;
01175 struct {
01176 unsigned sign : 1;
01177 unsigned exponent : 11;
01178 unsigned mantissa1 : 20;
01179 unsigned mantissa2;
01180 } d;
01181 struct {
01182 unsigned sign : 1;
01183 unsigned exponent1 : 4;
01184 unsigned exponent2 : 7;
01185 unsigned mantissa1 : 20;
01186 unsigned mantissa2;
01187 } s;
01188 } u;
01189
01190 if (GET_CODE (op) == REG || mode != DFmode)
01191 return op;
01192
01193 if (GET_CODE (op) == CONST_DOUBLE)
01194 {
01195 memcpy (&u.r, &CONST_DOUBLE_LOW (op), sizeof u);
01196 if (u.d.exponent != 0x7ff
01197 && u.d.mantissa2 == 0
01198 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7)
01199 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
01200 op, mode)) != 0)
01201 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
01202 }
01203 else if (register_operand (op, mode))
01204 return op;
01205
01206 return force_reg (mode, op);
01207 }
01208
01209
01210
01211 int
01212 move_operand (op, mode)
01213 rtx op;
01214 enum machine_mode mode;
01215 {
01216 if (register_operand (op, mode))
01217 return 1;
01218 if (GET_CODE (op) == CONST_INT)
01219 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
01220 if (GET_MODE (op) != mode)
01221 return 0;
01222 if (GET_CODE (op) == SUBREG)
01223 op = SUBREG_REG (op);
01224 if (GET_CODE (op) != MEM)
01225 return 0;
01226
01227 op = XEXP (op, 0);
01228 if (GET_CODE (op) == LO_SUM)
01229 return (REG_P (XEXP (op, 0))
01230 && symbolic_address_p (XEXP (op, 1)));
01231 return memory_address_p (mode, op);
01232 }
01233
01234
01235
01236 int
01237 call_address_operand (op, mode)
01238 rtx op;
01239 enum machine_mode mode ATTRIBUTE_UNUSED;
01240 {
01241 return (REG_P (op) || symbolic_address_p (op));
01242 }
01243
01244
01245
01246
01247 int
01248 symbolic_address_p (op)
01249 register rtx op;
01250 {
01251 switch (GET_CODE (op))
01252 {
01253 case SYMBOL_REF:
01254 case LABEL_REF:
01255 return 1;
01256
01257 case CONST:
01258 op = XEXP (op, 0);
01259 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
01260 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
01261 && GET_CODE (XEXP (op, 1)) == CONST_INT);
01262
01263 default:
01264 return 0;
01265 }
01266 }
01267
01268
01269
01270 int
01271 reg_or_0_operand (op, mode)
01272 rtx op;
01273 enum machine_mode mode;
01274 {
01275 return (op == const0_rtx || register_operand (op, mode));
01276 }
01277
01278
01279
01280 int
01281 arith_operand (op, mode)
01282 rtx op;
01283 enum machine_mode mode;
01284 {
01285 return (register_operand (op, mode)
01286 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
01287 }
01288
01289
01290
01291 int
01292 arith5_operand (op, mode)
01293 rtx op;
01294 enum machine_mode mode;
01295 {
01296 return (register_operand (op, mode)
01297 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
01298 }
01299
01300 int
01301 arith32_operand (op, mode)
01302 rtx op;
01303 enum machine_mode mode;
01304 {
01305 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
01306 }
01307
01308 int
01309 arith64_operand (op, mode)
01310 rtx op;
01311 enum machine_mode mode;
01312 {
01313 return (register_operand (op, mode)
01314 || GET_CODE (op) == CONST_INT
01315 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
01316 }
01317
01318 int
01319 int5_operand (op, mode)
01320 rtx op;
01321 enum machine_mode mode ATTRIBUTE_UNUSED;
01322 {
01323 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
01324 }
01325
01326 int
01327 int32_operand (op, mode)
01328 rtx op;
01329 enum machine_mode mode ATTRIBUTE_UNUSED;
01330 {
01331 return (GET_CODE (op) == CONST_INT);
01332 }
01333
01334
01335
01336
01337 int
01338 add_operand (op, mode)
01339 rtx op;
01340 enum machine_mode mode;
01341 {
01342 return (register_operand (op, mode)
01343 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
01344 }
01345
01346
01347
01348
01349 int
01350 mak_mask_p (value)
01351 int value;
01352 {
01353 return (value && POWER_OF_2_or_0 (value + 1));
01354 }
01355
01356 int
01357 reg_or_bbx_mask_operand (op, mode)
01358 rtx op;
01359 enum machine_mode mode;
01360 {
01361 int value;
01362 if (register_operand (op, mode))
01363 return 1;
01364 if (GET_CODE (op) != CONST_INT)
01365 return 0;
01366
01367 value = INTVAL (op);
01368 if (POWER_OF_2 (value))
01369 return 1;
01370
01371 return 0;
01372 }
01373
01374
01375
01376
01377 int
01378 real_or_0_operand (op, mode)
01379 rtx op;
01380 enum machine_mode mode;
01381 {
01382 if (mode != SFmode && mode != DFmode)
01383 return 0;
01384
01385 return (register_operand (op, mode)
01386 || (GET_CODE (op) == CONST_DOUBLE
01387 && op == CONST0_RTX (mode)));
01388 }
01389
01390
01391
01392
01393 int
01394 partial_ccmode_register_operand (op, mode)
01395 rtx op;
01396 enum machine_mode mode ATTRIBUTE_UNUSED;
01397 {
01398 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
01399 }
01400
01401
01402
01403 int
01404 relop (op, mode)
01405 rtx op;
01406 enum machine_mode mode ATTRIBUTE_UNUSED;
01407 {
01408 switch (GET_CODE (op))
01409 {
01410 case EQ:
01411 case NE:
01412 case LT:
01413 case LE:
01414 case GE:
01415 case GT:
01416 case LTU:
01417 case LEU:
01418 case GEU:
01419 case GTU:
01420 return 1;
01421 default:
01422 return 0;
01423 }
01424 }
01425
01426 int
01427 even_relop (op, mode)
01428 rtx op;
01429 enum machine_mode mode ATTRIBUTE_UNUSED;
01430 {
01431 switch (GET_CODE (op))
01432 {
01433 case EQ:
01434 case LT:
01435 case GT:
01436 case LTU:
01437 case GTU:
01438 return 1;
01439 default:
01440 return 0;
01441 }
01442 }
01443
01444 int
01445 odd_relop (op, mode)
01446 rtx op;
01447 enum machine_mode mode ATTRIBUTE_UNUSED;
01448 {
01449 switch (GET_CODE (op))
01450 {
01451 case NE:
01452 case LE:
01453 case GE:
01454 case LEU:
01455 case GEU:
01456 return 1;
01457 default:
01458 return 0;
01459 }
01460 }
01461
01462
01463
01464
01465 int
01466 relop_no_unsigned (op, mode)
01467 rtx op;
01468 enum machine_mode mode ATTRIBUTE_UNUSED;
01469 {
01470 switch (GET_CODE (op))
01471 {
01472 case EQ:
01473 case NE:
01474 case LT:
01475 case LE:
01476 case GE:
01477 case GT:
01478
01479 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
01480 || GET_MODE (op) == DImode
01481 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
01482 || GET_MODE (XEXP (op, 0)) == DImode
01483 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
01484 || GET_MODE (XEXP (op, 1)) == DImode)
01485 return 0;
01486 return 1;
01487 default:
01488 return 0;
01489 }
01490 }
01491
01492
01493
01494 int
01495 equality_op (op, mode)
01496 rtx op;
01497 enum machine_mode mode ATTRIBUTE_UNUSED;
01498 {
01499 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
01500 }
01501
01502
01503
01504 int
01505 pc_or_label_ref (op, mode)
01506 rtx op;
01507 enum machine_mode mode ATTRIBUTE_UNUSED;
01508 {
01509 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
01510 }
01511
01512
01513
01514
01515 struct m88k_lang_independent_options
01516 {
01517 const char *const string;
01518 int *const variable;
01519 const int on_value;
01520 const char *const description;
01521 };
01522
01523 static void output_options PARAMS ((FILE *,
01524 const struct m88k_lang_independent_options *,
01525 int,
01526 const struct m88k_lang_independent_options *,
01527 int, int, int, const char *, const char *,
01528 const char *));
01529
01530 static int
01531 output_option (file, sep, type, name, indent, pos, max)
01532 FILE *file;
01533 const char *sep;
01534 const char *type;
01535 const char *name;
01536 const char *indent;
01537 int pos;
01538 int max;
01539 {
01540 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
01541 {
01542 fprintf (file, indent);
01543 return fprintf (file, "%s%s", type, name);
01544 }
01545 return pos + fprintf (file, "%s%s%s", sep, type, name);
01546 }
01547
01548 static const struct { const char *const name; const int value; } m_options[] =
01549 TARGET_SWITCHES;
01550
01551 static void
01552 output_options (file, f_options, f_len, W_options, W_len,
01553 pos, max, sep, indent, term)
01554 FILE *file;
01555 const struct m88k_lang_independent_options *f_options;
01556 const struct m88k_lang_independent_options *W_options;
01557 int f_len, W_len;
01558 int pos;
01559 int max;
01560 const char *sep;
01561 const char *indent;
01562 const char *term;
01563 {
01564 register int j;
01565
01566 if (optimize)
01567 pos = output_option (file, sep, "-O", "", indent, pos, max);
01568 if (write_symbols != NO_DEBUG)
01569 pos = output_option (file, sep, "-g", "", indent, pos, max);
01570 if (flag_traditional)
01571 pos = output_option (file, sep, "-traditional", "", indent, pos, max);
01572 if (profile_flag)
01573 pos = output_option (file, sep, "-p", "", indent, pos, max);
01574 for (j = 0; j < f_len; j++)
01575 if (*f_options[j].variable == f_options[j].on_value)
01576 pos = output_option (file, sep, "-f", f_options[j].string,
01577 indent, pos, max);
01578
01579 for (j = 0; j < W_len; j++)
01580 if (*W_options[j].variable == W_options[j].on_value)
01581 pos = output_option (file, sep, "-W", W_options[j].string,
01582 indent, pos, max);
01583
01584 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
01585 if (m_options[j].name[0] != '\0'
01586 && m_options[j].value > 0
01587 && ((m_options[j].value & target_flags)
01588 == m_options[j].value))
01589 pos = output_option (file, sep, "-m", m_options[j].name,
01590 indent, pos, max);
01591
01592 if (m88k_short_data)
01593 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
01594 indent, pos, max);
01595
01596 fprintf (file, term);
01597 }
01598
01599 void
01600 output_file_start (file, f_options, f_len, W_options, W_len)
01601 FILE *file;
01602 const struct m88k_lang_independent_options *f_options;
01603 const struct m88k_lang_independent_options *W_options;
01604 int f_len, W_len;
01605 {
01606 register int pos;
01607
01608 ASM_FIRST_LINE (file);
01609 if (TARGET_88110
01610 && TARGET_SVR4)
01611 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
01612 output_file_directive (file, main_input_filename);
01613
01614
01615 ASM_COFFSEM (file);
01616
01617 if (TARGET_IDENTIFY_REVISION)
01618 {
01619 char indent[256];
01620
01621 time_t now = time ((time_t *)0);
01622 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
01623 fprintf (file, indent+3);
01624 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
01625 #if 1
01626
01627
01628
01629 output_options (file, f_options, f_len, W_options, W_len,
01630 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
01631 #else
01632 fprintf (file, "]\"\n");
01633 print_switch_values (file, 0, 150 - strlen (indent),
01634 indent + 3, " ", "]\"\n");
01635 #endif
01636 }
01637 }
01638
01639
01640
01641 void
01642 output_ascii (file, opcode, max, p, size)
01643 FILE *file;
01644 const char *opcode;
01645 int max;
01646 const char *p;
01647 int size;
01648 {
01649 int i;
01650 int in_escape = 0;
01651
01652 register int num = 0;
01653
01654 fprintf (file, "%s\"", opcode);
01655 for (i = 0; i < size; i++)
01656 {
01657 register int c = (unsigned char) p[i];
01658
01659 if (num > max)
01660 {
01661 fprintf (file, "\"\n%s\"", opcode);
01662 num = 0;
01663 }
01664
01665 if (c == '\"' || c == '\\')
01666 {
01667 escape:
01668 putc ('\\', file);
01669 putc (c, file);
01670 num += 2;
01671 in_escape = 0;
01672 }
01673 else if (in_escape && ISDIGIT (c))
01674 {
01675
01676
01677
01678
01679 fprintf (file, "\\%03o", c);
01680 num += 4;
01681 }
01682 else if ((c >= ' ' && c < 0177) || (c == '\t'))
01683 {
01684 putc (c, file);
01685 num++;
01686 in_escape = 0;
01687 }
01688 else
01689 {
01690 switch (c)
01691 {
01692
01693 case '\f': c = 'f'; goto escape;
01694 case '\b': c = 'b'; goto escape;
01695 case '\r': c = 'r'; goto escape;
01696 case '\n': c = 'n'; goto escape;
01697 }
01698
01699 fprintf (file, "\\%03o", c);
01700 num += 4;
01701 in_escape = 1;
01702 }
01703 }
01704 fprintf (file, "\"\n");
01705 }
01706
01707
01708
01709
01710 void
01711 output_label (label_number)
01712 int label_number;
01713 {
01714 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
01715 }
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790 static void emit_add PARAMS ((rtx, rtx, int));
01791 static void preserve_registers PARAMS ((int, int));
01792 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
01793 static void output_tdesc PARAMS ((FILE *, int));
01794 static int uses_arg_area_p PARAMS ((void));
01795
01796 static int nregs;
01797 static int nxregs;
01798 static char save_regs[FIRST_PSEUDO_REGISTER];
01799 static int frame_laid_out;
01800 static int frame_size;
01801 static int variable_args_p;
01802 static int epilogue_marked;
01803 static int prologue_marked;
01804
01805 #define FIRST_OCS_PRESERVE_REGISTER 14
01806 #define LAST_OCS_PRESERVE_REGISTER 30
01807
01808 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
01809 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
01810
01811 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
01812 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
01813 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
01814
01815
01816
01817
01818
01819 void
01820 m88k_layout_frame ()
01821 {
01822 int regno, sp_size;
01823
01824 frame_laid_out++;
01825
01826 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
01827 sp_size = nregs = nxregs = 0;
01828 frame_size = get_frame_size ();
01829
01830
01831 if (current_function_profile)
01832 save_regs[1] = 1;
01833
01834
01835
01836
01837 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
01838 save_regs[1] = 1;
01839
01840
01841
01842
01843
01844
01845 if (regs_ever_live[1] || frame_pointer_needed)
01846 {
01847 save_regs[1] = 1;
01848 sp_size += REG_PARM_STACK_SPACE (0);
01849 }
01850
01851
01852 if (flag_pic && current_function_uses_pic_offset_table)
01853 {
01854 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
01855 nregs++;
01856 }
01857
01858
01859
01860
01861
01862 if (frame_pointer_needed)
01863 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
01864 else if (regs_ever_live[FRAME_POINTER_REGNUM])
01865 save_regs[FRAME_POINTER_REGNUM] = 1;
01866
01867
01868 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
01869 regno++)
01870 if (regs_ever_live[regno] && ! call_used_regs[regno])
01871 {
01872 save_regs[regno] = 1;
01873 nxregs++;
01874 }
01875
01876
01877 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
01878 if (regs_ever_live[regno] && ! call_used_regs[regno])
01879 {
01880 save_regs[regno] = 1;
01881 nregs++;
01882 }
01883
01884
01885
01886 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
01887 sp_size += 4;
01888
01889 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
01890
01891 if (nxregs > 0 && (nregs & 1) != 0)
01892 sp_size +=4;
01893 sp_size += 4 * nregs;
01894 sp_size += 8 * nxregs;
01895 sp_size += current_function_outgoing_args_size;
01896
01897
01898
01899 if (frame_pointer_needed || sp_size)
01900 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
01901 else
01902 m88k_fp_offset = -STARTING_FRAME_OFFSET;
01903 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
01904
01905
01906
01907
01908
01909 {
01910 int need
01911 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
01912 - (frame_size % STACK_UNIT_BOUNDARY));
01913 if (need < 0)
01914 need += STACK_UNIT_BOUNDARY;
01915 m88k_stack_size
01916 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
01917 + current_function_pretend_args_size);
01918 }
01919 }
01920
01921
01922
01923 int
01924 null_prologue ()
01925 {
01926 if (! reload_completed)
01927 return 0;
01928 if (! frame_laid_out)
01929 m88k_layout_frame ();
01930 return (! frame_pointer_needed
01931 && nregs == 0
01932 && nxregs == 0
01933 && m88k_stack_size == 0);
01934 }
01935
01936
01937
01938
01939
01940
01941 static int
01942 uses_arg_area_p ()
01943 {
01944 register tree parm;
01945
01946 if (current_function_decl == 0
01947 || current_function_varargs
01948 || variable_args_p)
01949 return 1;
01950
01951 for (parm = DECL_ARGUMENTS (current_function_decl);
01952 parm;
01953 parm = TREE_CHAIN (parm))
01954 {
01955 if (DECL_RTL (parm) == 0
01956 || GET_CODE (DECL_RTL (parm)) == MEM)
01957 return 1;
01958
01959 if (DECL_INCOMING_RTL (parm) == 0
01960 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
01961 return 1;
01962 }
01963 return 0;
01964 }
01965
01966 static void
01967 m88k_output_function_prologue (stream, size)
01968 FILE *stream ATTRIBUTE_UNUSED;
01969 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
01970 {
01971 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
01972 fprintf (stderr, "$");
01973
01974 m88k_prologue_done = 1;
01975 }
01976
01977 static void
01978 m88k_output_function_end_prologue (stream)
01979 FILE *stream;
01980 {
01981 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
01982 {
01983 PUT_OCS_FUNCTION_START (stream);
01984 prologue_marked = 1;
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995 if (epilogue_marked)
01996 PUT_OCS_FUNCTION_END (stream);
01997 }
01998 }
01999
02000 void
02001 m88k_expand_prologue ()
02002 {
02003 m88k_layout_frame ();
02004
02005 if (TARGET_OPTIMIZE_ARG_AREA
02006 && m88k_stack_size
02007 && ! uses_arg_area_p ())
02008 {
02009
02010
02011 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
02012 m88k_stack_size = 0;
02013 }
02014
02015 if (m88k_stack_size)
02016 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
02017
02018 if (nregs || nxregs)
02019 preserve_registers (m88k_fp_offset + 4, 1);
02020
02021 if (frame_pointer_needed)
02022 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
02023
02024 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
02025 {
02026 rtx return_reg = gen_rtx_REG (SImode, 1);
02027 rtx label = gen_label_rtx ();
02028 rtx temp_reg = NULL_RTX;
02029
02030 if (! save_regs[1])
02031 {
02032 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
02033 emit_move_insn (temp_reg, return_reg);
02034 }
02035 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
02036 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
02037 emit_insn (gen_addsi3 (pic_offset_table_rtx,
02038 pic_offset_table_rtx, return_reg));
02039 if (! save_regs[1])
02040 emit_move_insn (return_reg, temp_reg);
02041 }
02042 if (current_function_profile)
02043 emit_insn (gen_blockage ());
02044 }
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054 static void
02055 m88k_output_function_begin_epilogue (stream)
02056 FILE *stream;
02057 {
02058 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
02059 {
02060 PUT_OCS_FUNCTION_END (stream);
02061 }
02062 epilogue_marked = 1;
02063 }
02064
02065 static void
02066 m88k_output_function_epilogue (stream, size)
02067 FILE *stream;
02068 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
02069 {
02070 rtx insn = get_last_insn ();
02071
02072 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
02073 PUT_OCS_FUNCTION_END (stream);
02074
02075
02076
02077 if (GET_CODE (insn) == NOTE)
02078 insn = prev_nonnote_insn (insn);
02079 if (insn == 0 || GET_CODE (insn) != BARRIER)
02080 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
02081
02082
02083
02084
02085
02086 if (insn && GET_CODE (insn) == BARRIER)
02087 {
02088 insn = prev_nonnote_insn (insn);
02089 if (insn && GET_CODE (insn) == CALL_INSN)
02090 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
02091 }
02092
02093 output_short_branch_defs (stream);
02094
02095 fprintf (stream, "\n");
02096
02097 if (TARGET_OCS_DEBUG_INFO)
02098 output_tdesc (stream, m88k_fp_offset + 4);
02099
02100 m88k_function_number++;
02101 m88k_prologue_done = 0;
02102 variable_args_p = 0;
02103 frame_laid_out = 0;
02104 epilogue_marked = 0;
02105 prologue_marked = 0;
02106 }
02107
02108 void
02109 m88k_expand_epilogue ()
02110 {
02111 #if (MONITOR_GCC & 0x4)
02112 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
02113 size, m88k_fp_offset, m88k_stack_size);
02114 #endif
02115
02116 if (frame_pointer_needed)
02117 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
02118
02119 if (nregs || nxregs)
02120 preserve_registers (m88k_fp_offset + 4, 0);
02121
02122 if (m88k_stack_size)
02123 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
02124 }
02125
02126
02127
02128
02129 static void
02130 emit_add (dstreg, srcreg, amount)
02131 rtx dstreg;
02132 rtx srcreg;
02133 int amount;
02134 {
02135 rtx incr = GEN_INT (abs (amount));
02136
02137 if (! ADD_INTVAL (amount))
02138 {
02139 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
02140 emit_move_insn (temp, incr);
02141 incr = temp;
02142 }
02143 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
02144 }
02145
02146
02147
02148
02149
02150 static void
02151 preserve_registers (base, store_p)
02152 int base;
02153 int store_p;
02154 {
02155 int regno, offset;
02156 struct mem_op {
02157 int regno;
02158 int nregs;
02159 int offset;
02160 } mem_op[FIRST_PSEUDO_REGISTER];
02161 struct mem_op *mo_ptr = mem_op;
02162
02163
02164
02165
02166
02167 offset = base;
02168 if (save_regs[1])
02169 {
02170
02171
02172 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
02173 offset -= 4;
02174 emit_ldst (store_p, 1, SImode, offset);
02175 offset -= 4;
02176 base = offset;
02177 }
02178
02179
02180 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
02181 if (save_regs[regno])
02182 {
02183 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
02184 {
02185 mo_ptr->nregs = 1;
02186 mo_ptr->regno = regno;
02187 mo_ptr->offset = offset;
02188 mo_ptr++;
02189 offset -= 4;
02190 }
02191 else
02192 {
02193 regno--;
02194 offset -= 2*4;
02195 }
02196 }
02197
02198
02199
02200 offset = base;
02201 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
02202 if (save_regs[regno])
02203 {
02204 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
02205 {
02206 offset -= 4;
02207 }
02208 else
02209 {
02210 mo_ptr->nregs = 2;
02211 mo_ptr->regno = regno-1;
02212 mo_ptr->offset = offset-4;
02213 mo_ptr++;
02214 regno--;
02215 offset -= 2*4;
02216 }
02217 }
02218
02219
02220
02221 offset = (offset - 1) & ~7;
02222 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
02223 regno--)
02224 if (save_regs[regno])
02225 {
02226 mo_ptr->nregs = 2;
02227 mo_ptr->regno = regno;
02228 mo_ptr->offset = offset;
02229 mo_ptr++;
02230 offset -= 2*4;
02231 }
02232
02233 mo_ptr->regno = 0;
02234
02235
02236 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
02237 {
02238 if (mo_ptr->nregs)
02239 emit_ldst (store_p, mo_ptr->regno,
02240 (mo_ptr->nregs > 1 ? DImode : SImode),
02241 mo_ptr->offset);
02242 }
02243 }
02244
02245 static void
02246 emit_ldst (store_p, regno, mode, offset)
02247 int store_p;
02248 int regno;
02249 enum machine_mode mode;
02250 int offset;
02251 {
02252 rtx reg = gen_rtx_REG (mode, regno);
02253 rtx mem;
02254
02255 if (SMALL_INTVAL (offset))
02256 {
02257 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
02258 }
02259 else
02260 {
02261
02262
02263 rtx disp = GEN_INT (offset);
02264 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
02265 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
02266
02267 emit_move_insn (temp, disp);
02268 mem = gen_rtx_MEM (mode, regi);
02269 }
02270
02271 if (store_p)
02272 emit_move_insn (mem, reg);
02273 else
02274 emit_move_insn (reg, mem);
02275 }
02276
02277
02278
02279 int
02280 m88k_debugger_offset (reg, offset)
02281 register rtx reg;
02282 register int offset;
02283 {
02284 if (GET_CODE (reg) == PLUS)
02285 {
02286 offset = INTVAL (XEXP (reg, 1));
02287 reg = XEXP (reg, 0);
02288 }
02289
02290
02291 if (reg == frame_pointer_rtx)
02292 offset += m88k_fp_offset - m88k_stack_size;
02293 else if (reg == stack_pointer_rtx)
02294 offset -= m88k_stack_size;
02295 else if (reg != arg_pointer_rtx)
02296 {
02297 #if (MONITOR_GCC & 0x10)
02298 if (! (GET_CODE (reg) == REG
02299 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
02300 warning ("internal gcc error: Can't express symbolic location");
02301 #endif
02302 return 0;
02303 }
02304
02305 return offset;
02306 }
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327 static void
02328 output_tdesc (file, offset)
02329 FILE *file;
02330 int offset;
02331 {
02332 int regno, i, j;
02333 long mask, return_address_info, register_save_offset;
02334 long xmask, xregister_save_offset;
02335 char buf[256];
02336
02337 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
02338 regno <= LAST_OCS_PRESERVE_REGISTER;
02339 regno++)
02340 {
02341 mask <<= 1;
02342 if (save_regs[regno])
02343 {
02344 mask |= 1;
02345 i++;
02346 }
02347 }
02348
02349 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
02350 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
02351 regno++)
02352 {
02353 xmask <<= 1;
02354 if (save_regs[regno])
02355 {
02356 xmask |= 1;
02357 j++;
02358 }
02359 }
02360
02361 if (save_regs[1])
02362 {
02363 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
02364 offset -= 4;
02365 return_address_info = - m88k_stack_size + offset;
02366 register_save_offset = return_address_info - i*4;
02367 }
02368 else
02369 {
02370 return_address_info = 1;
02371 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
02372 }
02373
02374 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
02375
02376 tdesc_section ();
02377
02378
02379 fprintf (file, "%s%d,%d", integer_asm_op (4, TRUE),
02380 (((xmask != 0) ? 20 : 16) << 2) | 2,
02381 flag_pic ? 2 : 1);
02382
02383 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
02384 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
02385 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
02386 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
02387
02388 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
02389
02390 (int)(((xmask ? 3 : 1) << (17+1+1+5))
02391 | (mask << (1+1+5))
02392 | ((!!save_regs[1]) << 5)
02393 | (frame_pointer_needed
02394 ? FRAME_POINTER_REGNUM
02395 : STACK_POINTER_REGNUM)),
02396 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
02397 return_address_info,
02398 register_save_offset);
02399 if (xmask)
02400 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
02401 fputc ('\n', file);
02402
02403 text_section ();
02404 }
02405
02406
02407
02408
02409
02410
02411 void
02412 output_function_profiler (file, labelno, name, savep)
02413 FILE *file;
02414 int labelno;
02415 const char *name;
02416 int savep;
02417 {
02418 char label[256];
02419 char dbi[256];
02420 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
02421
02422
02423
02424 if (savep)
02425 {
02426 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
02427 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
02428 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
02429 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
02430 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
02431 }
02432
02433 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
02434 if (flag_pic == 2)
02435 {
02436 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
02437 temp, reg_names[0], m88k_pound_sign, &label[1]);
02438 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
02439 temp, temp, m88k_pound_sign, &label[1]);
02440 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
02441 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
02442 }
02443 else if (flag_pic)
02444 {
02445 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
02446 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
02447 }
02448 else
02449 {
02450 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
02451 temp, reg_names[0], m88k_pound_sign, &label[1]);
02452 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
02453 temp, temp, m88k_pound_sign, &label[1]);
02454 }
02455
02456 if (flag_pic)
02457 fprintf (file, "\tbsr.n\t %s#plt\n", name);
02458 else
02459 fprintf (file, "\tbsr.n\t %s\n", name);
02460 fputs (dbi, file);
02461
02462 if (savep)
02463 {
02464 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
02465 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
02466 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
02467 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
02468 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
02469 }
02470 }
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501 struct rtx_def *
02502 m88k_function_arg (args_so_far, mode, type, named)
02503 CUMULATIVE_ARGS args_so_far;
02504 enum machine_mode mode;
02505 tree type;
02506 int named ATTRIBUTE_UNUSED;
02507 {
02508 int bytes, words;
02509
02510 if (type != 0
02511 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
02512 mode = BLKmode;
02513
02514 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
02515 warning ("argument #%d is a structure", args_so_far + 1);
02516
02517 if ((args_so_far & 1) != 0
02518 && (mode == DImode || mode == DFmode
02519 || (type != 0 && TYPE_ALIGN (type) > 32)))
02520 args_so_far++;
02521
02522 #ifdef ESKIT
02523 if (no_reg_params)
02524 return (rtx) 0;
02525 #endif
02526
02527 if (type == 0 && mode == BLKmode)
02528 abort ();
02529
02530 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
02531 words = (bytes + 3) / 4;
02532
02533 if (args_so_far + words > 8)
02534 return (rtx) 0;
02535
02536 else if (mode == BLKmode
02537 && (TYPE_ALIGN (type) != BITS_PER_WORD
02538 || bytes != UNITS_PER_WORD))
02539 return (rtx) 0;
02540
02541 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
02542 2 + args_so_far);
02543 }
02544
02545
02546
02547
02548
02549 struct rtx_def *
02550 m88k_builtin_saveregs ()
02551 {
02552 rtx addr;
02553 tree fntype = TREE_TYPE (current_function_decl);
02554 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
02555 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
02556 != void_type_node)))
02557 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
02558 int fixed;
02559
02560 variable_args_p = 1;
02561
02562 fixed = 0;
02563 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
02564 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
02565 / UNITS_PER_WORD);
02566
02567
02568 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
02569 set_mem_alias_set (addr, get_varargs_alias_set ());
02570 RTX_UNCHANGING_P (addr) = 1;
02571 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
02572
02573
02574 if (fixed < 8)
02575 move_block_from_reg (2 + fixed,
02576 adjust_address (addr, Pmode, fixed * UNITS_PER_WORD),
02577 8 - fixed,
02578 UNITS_PER_WORD * (8 - fixed));
02579
02580
02581
02582
02583 return XEXP (addr, 0);
02584 }
02585
02586
02587
02588 tree
02589 m88k_build_va_list ()
02590 {
02591 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
02592
02593 int_ptr_type_node = build_pointer_type (integer_type_node);
02594
02595 record = make_node (RECORD_TYPE);
02596
02597 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
02598 integer_type_node);
02599 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
02600 int_ptr_type_node);
02601 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
02602 int_ptr_type_node);
02603
02604 DECL_FIELD_CONTEXT (field_arg) = record;
02605 DECL_FIELD_CONTEXT (field_stk) = record;
02606 DECL_FIELD_CONTEXT (field_reg) = record;
02607
02608 TYPE_FIELDS (record) = field_arg;
02609 TREE_CHAIN (field_arg) = field_stk;
02610 TREE_CHAIN (field_stk) = field_reg;
02611
02612 layout_type (record);
02613 return record;
02614 }
02615
02616
02617
02618 void
02619 m88k_va_start (stdarg_p, valist, nextarg)
02620 int stdarg_p ATTRIBUTE_UNUSED;
02621 tree valist;
02622 rtx nextarg ATTRIBUTE_UNUSED;
02623 {
02624 tree field_reg, field_stk, field_arg;
02625 tree reg, stk, arg, t;
02626
02627 field_arg = TYPE_FIELDS (va_list_type_node);
02628 field_stk = TREE_CHAIN (field_arg);
02629 field_reg = TREE_CHAIN (field_stk);
02630
02631 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
02632 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
02633 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
02634
02635
02636 {
02637 tree fntype = TREE_TYPE (current_function_decl);
02638 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
02639 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
02640 != void_type_node)))
02641 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
02642 tree argsize;
02643
02644 if (CONSTANT_P (current_function_arg_offset_rtx))
02645 {
02646 int fixed = (INTVAL (current_function_arg_offset_rtx)
02647 + argadj) / UNITS_PER_WORD;
02648
02649 argsize = build_int_2 (fixed, 0);
02650 }
02651 else
02652 {
02653 argsize = make_tree (integer_type_node,
02654 current_function_arg_offset_rtx);
02655 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
02656 build_int_2 (argadj, 0)));
02657 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
02658 build_int_2 (2, 0)));
02659 }
02660
02661 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
02662 TREE_SIDE_EFFECTS (t) = 1;
02663 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02664 }
02665
02666
02667 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
02668 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
02669 TREE_SIDE_EFFECTS (t) = 1;
02670 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02671
02672
02673 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
02674 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
02675 TREE_SIDE_EFFECTS (t) = 1;
02676 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02677 }
02678
02679
02680
02681 rtx
02682 m88k_va_arg (valist, type)
02683 tree valist, type;
02684 {
02685 tree field_reg, field_stk, field_arg;
02686 tree reg, stk, arg, arg_align, base, t;
02687 int size, wsize, align, reg_p;
02688 rtx addr_rtx;
02689
02690 field_arg = TYPE_FIELDS (va_list_type_node);
02691 field_stk = TREE_CHAIN (field_arg);
02692 field_reg = TREE_CHAIN (field_stk);
02693
02694 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
02695 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
02696 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
02697
02698 size = int_size_in_bytes (type);
02699 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
02700 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
02701 reg_p = (AGGREGATE_TYPE_P (type)
02702 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
02703 : size <= 2*UNITS_PER_WORD);
02704
02705
02706 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
02707 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
02708 arg_align = save_expr (arg_align);
02709
02710
02711 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
02712 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
02713
02714
02715 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
02716 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
02717 addr_rtx = copy_to_reg (addr_rtx);
02718
02719
02720 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
02721 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
02722 TREE_SIDE_EFFECTS (t) = 1;
02723 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02724
02725 return addr_rtx;
02726 }
02727
02728
02729
02730
02731 rtx
02732 emit_test (op, mode)
02733 enum rtx_code op;
02734 enum machine_mode mode;
02735 {
02736 if (m88k_compare_reg == 0)
02737 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
02738 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
02739 }
02740
02741
02742
02743
02744
02745
02746 void
02747 emit_bcnd (op, label)
02748 enum rtx_code op;
02749 rtx label;
02750 {
02751 if (m88k_compare_op1 == const0_rtx)
02752 emit_jump_insn (gen_bcnd
02753 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
02754 label));
02755 else if (m88k_compare_op0 == const0_rtx)
02756 emit_jump_insn (gen_bcnd
02757 (gen_rtx (swap_condition (op),
02758 VOIDmode, m88k_compare_op1, const0_rtx),
02759 label));
02760 else if (op != EQ && op != NE)
02761 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
02762 else
02763 {
02764 rtx zero = gen_reg_rtx (SImode);
02765 rtx reg, constant;
02766 int value;
02767
02768 if (GET_CODE (m88k_compare_op1) == CONST_INT)
02769 {
02770 reg = force_reg (SImode, m88k_compare_op0);
02771 constant = m88k_compare_op1;
02772 }
02773 else
02774 {
02775 reg = force_reg (SImode, m88k_compare_op1);
02776 constant = m88k_compare_op0;
02777 }
02778 value = INTVAL (constant);
02779
02780
02781
02782 if (SMALL_INTVAL (value))
02783 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
02784 else
02785 {
02786 if (SMALL_INTVAL (-value))
02787 emit_insn (gen_addsi3 (zero, reg,
02788 GEN_INT (-value)));
02789 else
02790 emit_insn (gen_xorsi3 (zero, reg, constant));
02791
02792 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
02793 zero, const0_rtx),
02794 label));
02795 }
02796 }
02797 }
02798
02799
02800
02801 void
02802 print_operand (file, x, code)
02803 FILE *file;
02804 rtx x;
02805 int code;
02806 {
02807 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
02808 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
02809 static int sequencep;
02810 static int reversep;
02811
02812 if (sequencep)
02813 {
02814 if (code < 'B' || code > 'E')
02815 output_operand_lossage ("%%R not followed by %%B/C/D/E");
02816 if (reversep)
02817 xc = reverse_condition (xc);
02818 sequencep = 0;
02819 }
02820
02821 switch (code)
02822 {
02823 case '*':
02824 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
02825
02826 case '#':
02827 fputs (m88k_pound_sign, file); return;
02828
02829 case 'V':
02830
02831 case 'v':
02832 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
02833 {
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856 static rtx last_addr = 0;
02857 if (code == 'V'
02858 && m88k_volatile_code != 'V'
02859 && !(m88k_volatile_code == 'v'
02860 && GET_CODE (XEXP (x, 0)) == LO_SUM
02861 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
02862 fprintf (file,
02863 #if 0
02864 #ifdef AS_BUG_FLDCR
02865 "fldcr\t %s,%scr63\n\t",
02866 #else
02867 "fldcr\t %s,%sfcr63\n\t",
02868 #endif
02869 reg_names[0], m88k_pound_sign);
02870 #else
02871 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
02872 #endif
02873 m88k_volatile_code = code;
02874 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
02875 ? XEXP (XEXP (x, 0), 1) : 0);
02876 }
02877 return;
02878
02879 case 'X':
02880 value >>= 16;
02881 case 'x':
02882 if (xc != CONST_INT)
02883 output_operand_lossage ("invalid %%x/X value");
02884 fprintf (file, "0x%x", value & 0xffff); return;
02885
02886 case 'H':
02887 if (xc != CONST_INT)
02888 output_operand_lossage ("invalid %%H value");
02889 value = -value;
02890 case 'h':
02891 if (xc == REG)
02892 goto reg;
02893 if (xc != CONST_INT)
02894 output_operand_lossage ("invalid %%h value");
02895 fprintf (file, "%d", value & 0xffff);
02896 return;
02897
02898 case 'Q':
02899 if (xc != CONST_INT)
02900 output_operand_lossage ("invalid %%Q value");
02901 value = -value;
02902 case 'q':
02903 if (xc == REG)
02904 goto reg;
02905 if (xc != CONST_INT)
02906 output_operand_lossage ("invalid %%q value");
02907 fprintf (file, "%d", value & 0xff);
02908 return;
02909
02910 case 'w':
02911 if (xc != CONST_INT)
02912 output_operand_lossage ("invalid %%o value");
02913 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
02914 return;
02915
02916 case 'p':
02917 if (xc != CONST_INT
02918 || (value = exact_log2 (value)) < 0)
02919 output_operand_lossage ("invalid %%p value");
02920 fprintf (file, "%d", value);
02921 return;
02922
02923 case 'S':
02924 value = ~value;
02925 case 's':
02926
02927 {
02928 register unsigned mask, uval = value;
02929 register int top, bottom;
02930
02931 if (xc != CONST_INT)
02932 output_operand_lossage ("invalid %%s/S value");
02933
02934
02935 mask = (uval | (uval - 1)) + 1;
02936 if (!(uval && POWER_OF_2_or_0 (mask)))
02937 output_operand_lossage ("invalid %%s/S value");
02938 top = mask ? exact_log2 (mask) : 32;
02939 bottom = exact_log2 (uval & ~(uval - 1));
02940 fprintf (file,"%d<%d>", top - bottom, bottom);
02941 return;
02942 }
02943
02944 case 'P':
02945 if (xc == LABEL_REF)
02946 output_addr_const (file, x);
02947 else if (xc != PC)
02948 output_operand_lossage ("invalid %%P operand");
02949 return;
02950
02951 case 'L':
02952 fputc (xc == LABEL_REF ? '1' : '0', file);
02953 case '.':
02954 fputs ((final_sequence
02955 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
02956 ? ".n\t" : "\t", file);
02957 return;
02958
02959 case '!':
02960 sequencep++;
02961 reversep = 1;
02962 return;
02963 case 'R':
02964
02965 sequencep++;
02966 reversep = (xc == LABEL_REF);
02967 return;
02968
02969 case 'B':
02970 fputs (m88k_pound_sign, file);
02971 switch (xc)
02972 {
02973 case EQ: fputs ("eq0", file); return;
02974 case NE: fputs ("ne0", file); return;
02975 case GT: fputs ("gt0", file); return;
02976 case LE: fputs ("le0", file); return;
02977 case LT: fputs ("lt0", file); return;
02978 case GE: fputs ("ge0", file); return;
02979 default: output_operand_lossage ("invalid %%B value");
02980 }
02981
02982 case 'C':
02983 fputs (m88k_pound_sign, file);
02984 switch (xc)
02985 {
02986 case EQ: fputs ("eq", file); return;
02987 case NE: fputs ("ne", file); return;
02988 case GT: fputs ("gt", file); return;
02989 case LE: fputs ("le", file); return;
02990 case LT: fputs ("lt", file); return;
02991 case GE: fputs ("ge", file); return;
02992 case GTU: fputs ("hi", file); return;
02993 case LEU: fputs ("ls", file); return;
02994 case LTU: fputs ("lo", file); return;
02995 case GEU: fputs ("hs", file); return;
02996 default: output_operand_lossage ("invalid %%C value");
02997 }
02998
02999 case 'D':
03000 switch (xc)
03001 {
03002 case EQ: fputs ("0xa", file); return;
03003 case NE: fputs ("0x5", file); return;
03004 case GT: fputs (m88k_pound_sign, file);
03005 fputs ("gt0", file); return;
03006 case LE: fputs ("0xe", file); return;
03007 case LT: fputs ("0x4", file); return;
03008 case GE: fputs ("0xb", file); return;
03009 default: output_operand_lossage ("invalid %%D value");
03010 }
03011
03012 case 'E':
03013 switch (xc)
03014 {
03015 case EQ: fputs ("0x8", file); return;
03016 case NE: fputs ("0x7", file); return;
03017 default: output_operand_lossage ("invalid %%E value");
03018 }
03019
03020 case 'd':
03021 if (xc != REG)
03022 output_operand_lossage ("`%%d' operand isn't a register");
03023 fputs (reg_names[REGNO (x) + 1], file);
03024 return;
03025
03026 case 'r':
03027 if (x == const0_rtx)
03028 {
03029 fputs (reg_names[0], file);
03030 return;
03031 }
03032 else if (xc != REG)
03033 output_operand_lossage ("invalid %%r value");
03034 case 0:
03035 name:
03036 if (xc == REG)
03037 {
03038 reg:
03039 if (REGNO (x) == ARG_POINTER_REGNUM)
03040 output_operand_lossage ("operand is r0");
03041 else
03042 fputs (reg_names[REGNO (x)], file);
03043 }
03044 else if (xc == PLUS)
03045 output_address (x);
03046 else if (xc == MEM)
03047 output_address (XEXP (x, 0));
03048 else if (flag_pic && xc == UNSPEC)
03049 {
03050 output_addr_const (file, XVECEXP (x, 0, 0));
03051 fputs ("#got_rel", file);
03052 }
03053 else if (xc == CONST_DOUBLE)
03054 output_operand_lossage ("operand is const_double");
03055 else
03056 output_addr_const (file, x);
03057 return;
03058
03059 case 'g':
03060 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
03061 {
03062 output_addr_const (file, x);
03063 fputs ("#got_rel", file);
03064 return;
03065 }
03066 goto name;
03067
03068 case 'a':
03069 case 'c':
03070 case 'l':
03071 case 'n':
03072 default:
03073 output_operand_lossage ("invalid code");
03074 }
03075 }
03076
03077 void
03078 print_operand_address (file, addr)
03079 FILE *file;
03080 rtx addr;
03081 {
03082 register rtx reg0, reg1, temp;
03083
03084 switch (GET_CODE (addr))
03085 {
03086 case REG:
03087 if (REGNO (addr) == ARG_POINTER_REGNUM)
03088 abort ();
03089 else
03090 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
03091 break;
03092
03093 case LO_SUM:
03094 fprintf (file, "%s,%slo16(",
03095 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
03096 output_addr_const (file, XEXP (addr, 1));
03097 fputc (')', file);
03098 break;
03099
03100 case PLUS:
03101 reg0 = XEXP (addr, 0);
03102 reg1 = XEXP (addr, 1);
03103 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
03104 {
03105 rtx tmp = reg0;
03106 reg0 = reg1;
03107 reg1 = tmp;
03108 }
03109
03110 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
03111 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
03112 abort ();
03113
03114 else if (REG_P (reg0))
03115 {
03116 if (REG_P (reg1))
03117 fprintf (file, "%s,%s",
03118 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
03119
03120 else if (GET_CODE (reg1) == CONST_INT)
03121 fprintf (file, "%s,%d",
03122 reg_names [REGNO (reg0)], INTVAL (reg1));
03123
03124 else if (GET_CODE (reg1) == MULT)
03125 {
03126 rtx mreg = XEXP (reg1, 0);
03127 if (REGNO (mreg) == ARG_POINTER_REGNUM)
03128 abort ();
03129
03130 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
03131 reg_names[REGNO (mreg)]);
03132 }
03133
03134 else if (GET_CODE (reg1) == ZERO_EXTRACT)
03135 {
03136 fprintf (file, "%s,%slo16(",
03137 reg_names[REGNO (reg0)], m88k_pound_sign);
03138 output_addr_const (file, XEXP (reg1, 0));
03139 fputc (')', file);
03140 }
03141
03142 else if (flag_pic)
03143 {
03144 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
03145 output_addr_const (file, reg1);
03146 fputs ("#got_rel", file);
03147 }
03148 else abort ();
03149 }
03150
03151 else
03152 abort ();
03153 break;
03154
03155 case MULT:
03156 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
03157 abort ();
03158
03159 fprintf (file, "%s[%s]",
03160 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
03161 break;
03162
03163 case CONST_INT:
03164 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
03165 break;
03166
03167 default:
03168 fprintf (file, "%s,", reg_names[0]);
03169 if (SHORT_ADDRESS_P (addr, temp))
03170 {
03171 fprintf (file, "%siw16(", m88k_pound_sign);
03172 output_addr_const (file, addr);
03173 fputc (')', file);
03174 }
03175 else
03176 output_addr_const (file, addr);
03177 }
03178 }
03179
03180
03181
03182
03183 int
03184 pic_address_needs_scratch (x)
03185 rtx x;
03186 {
03187
03188 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
03189 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
03190 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
03191 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
03192 return 1;
03193
03194 return 0;
03195 }
03196
03197
03198
03199
03200 int
03201 symbolic_operand (op, mode)
03202 register rtx op;
03203 enum machine_mode mode;
03204 {
03205 switch (GET_CODE (op))
03206 {
03207 case SYMBOL_REF:
03208 case LABEL_REF:
03209 return 1;
03210
03211 case CONST:
03212 op = XEXP (op, 0);
03213 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
03214 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
03215 && GET_CODE (XEXP (op, 1)) == CONST_INT);
03216
03217
03218 case CONST_DOUBLE:
03219 return GET_MODE (op) == mode;
03220
03221 default:
03222 return 0;
03223 }
03224 }
03225
03226 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
03227 static void
03228 m88k_svr3_asm_out_constructor (symbol, priority)
03229 rtx symbol;
03230 int priority ATTRIBUTE_UNUSED;
03231 {
03232 const char *name = XSTR (symbol, 0);
03233
03234 init_section ();
03235 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
03236 assemble_name (asm_out_file, name);
03237 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
03238 assemble_name (asm_out_file, name);
03239 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
03240 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
03241 }
03242
03243 static void
03244 m88k_svr3_asm_out_destructor (symbol, priority)
03245 rtx symbol;
03246 int priority ATTRIBUTE_UNUSED;
03247 {
03248 int i;
03249
03250 fini_section ();
03251 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
03252 for (i = 1; i < 4; i++)
03253 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
03254 }
03255 #endif
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265 static int
03266 m88k_adjust_cost (insn, link, dep, cost)
03267 rtx insn;
03268 rtx link;
03269 rtx dep;
03270 int cost;
03271 {
03272 if (REG_NOTE_KIND (link) != 0)
03273 return 0;
03274
03275 if (! TARGET_88100
03276 && recog_memoized (insn) >= 0
03277 && get_attr_type (insn) == TYPE_STORE
03278 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
03279 return cost - 4;
03280
03281 return cost;
03282 }