00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "rtl.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "recog.h"
00037 #include "tree.h"
00038 #include "expr.h"
00039 #include "obstack.h"
00040 #include "except.h"
00041 #include "function.h"
00042 #include "tm_p.h"
00043 #include "target.h"
00044 #include "target-def.h"
00045
00046
00047
00048
00049
00050
00051
00052 struct rtx_def * fr30_compare_op0;
00053 struct rtx_def * fr30_compare_op1;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 struct fr30_frame_info
00102 {
00103 unsigned int total_size;
00104 unsigned int pretend_size;
00105 unsigned int args_size;
00106 unsigned int reg_size;
00107 unsigned int var_size;
00108 unsigned int frame_size;
00109 unsigned int gmask;
00110 unsigned int save_fp;
00111 unsigned int save_rp;
00112 int initialised;
00113 };
00114
00115
00116 static struct fr30_frame_info current_frame_info;
00117
00118
00119 static struct fr30_frame_info zero_frame_info;
00120
00121 static rtx fr30_pass_by_reference PARAMS ((tree, tree));
00122 static rtx fr30_pass_by_value PARAMS ((tree, tree));
00123
00124 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
00125 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
00126
00127
00128
00129
00130 #define MUST_SAVE_REGISTER(regno) \
00131 ( (regno) != RETURN_POINTER_REGNUM \
00132 && (regno) != FRAME_POINTER_REGNUM \
00133 && regs_ever_live [regno] \
00134 && ! call_used_regs [regno] )
00135
00136 #define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed)
00137 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || current_function_profile)
00138
00139 #if UNITS_PER_WORD == 4
00140 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
00141 #endif
00142
00143
00144 #undef TARGET_ASM_ALIGNED_HI_OP
00145 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00146 #undef TARGET_ASM_ALIGNED_SI_OP
00147 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00148
00149 struct gcc_target targetm = TARGET_INITIALIZER;
00150
00151
00152
00153
00154 unsigned int
00155 fr30_compute_frame_size (from_reg, to_reg)
00156 int from_reg;
00157 int to_reg;
00158 {
00159 int regno;
00160 unsigned int return_value;
00161 unsigned int var_size;
00162 unsigned int args_size;
00163 unsigned int pretend_size;
00164 unsigned int reg_size;
00165 unsigned int gmask;
00166
00167 var_size = WORD_ALIGN (get_frame_size ());
00168 args_size = WORD_ALIGN (current_function_outgoing_args_size);
00169 pretend_size = current_function_pretend_args_size;
00170
00171 reg_size = 0;
00172 gmask = 0;
00173
00174
00175 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
00176 {
00177 if (MUST_SAVE_REGISTER (regno))
00178 {
00179 reg_size += UNITS_PER_WORD;
00180 gmask |= 1 << regno;
00181 }
00182 }
00183
00184 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
00185 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
00186
00187 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
00188 * UNITS_PER_WORD;
00189
00190
00191 current_frame_info.pretend_size = pretend_size;
00192 current_frame_info.var_size = var_size;
00193 current_frame_info.args_size = args_size;
00194 current_frame_info.reg_size = reg_size;
00195 current_frame_info.frame_size = args_size + var_size;
00196 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
00197 current_frame_info.gmask = gmask;
00198 current_frame_info.initialised = reload_completed;
00199
00200
00201 return_value = 0;
00202
00203 if (to_reg == STACK_POINTER_REGNUM)
00204 return_value += args_size + var_size;
00205
00206 if (from_reg == ARG_POINTER_REGNUM)
00207 return_value += reg_size;
00208
00209 return return_value;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219 void
00220 fr30_expand_prologue ()
00221 {
00222 int regno;
00223 rtx insn;
00224
00225 if (! current_frame_info.initialised)
00226 fr30_compute_frame_size (0, 0);
00227
00228
00229 if (current_frame_info.total_size == 0
00230 && current_frame_info.gmask)
00231 abort ();
00232
00233
00234 if (current_frame_info.pretend_size)
00235 {
00236 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
00237
00238
00239 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
00240 {
00241 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
00242 RTX_FRAME_RELATED_P (insn) = 1;
00243 }
00244 }
00245
00246 if (current_frame_info.gmask)
00247 {
00248
00249 for (regno = STACK_POINTER_REGNUM; regno--;)
00250 {
00251 if ((current_frame_info.gmask & (1 << regno)) != 0)
00252 {
00253 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
00254 RTX_FRAME_RELATED_P (insn) = 1;
00255 }
00256 }
00257 }
00258
00259
00260 if (current_frame_info.save_rp)
00261 {
00262 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
00263 RETURN_POINTER_REGNUM)));
00264 RTX_FRAME_RELATED_P (insn) = 1;
00265 }
00266
00267
00268 if (current_frame_info.save_fp)
00269 {
00270 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
00271 {
00272 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
00273 rtx pattern;
00274
00275 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
00276 RTX_FRAME_RELATED_P (insn) = 1;
00277
00278 pattern = PATTERN (insn);
00279
00280
00281 if (GET_CODE (pattern) == PARALLEL)
00282 {
00283 int x;
00284 for (x = XVECLEN (pattern, 0); x--;)
00285 {
00286 rtx part = XVECEXP (pattern, 0, x);
00287
00288
00289
00290
00291
00292
00293
00294
00295 if (! frame_pointer_needed
00296 && GET_CODE (part) == SET
00297 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
00298 RTX_FRAME_RELATED_P (part) = 0;
00299 else
00300 RTX_FRAME_RELATED_P (part) = 1;
00301 }
00302 }
00303 }
00304 else
00305 {
00306 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
00307 RTX_FRAME_RELATED_P (insn) = 1;
00308
00309 if (frame_pointer_needed)
00310 {
00311 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
00312 RTX_FRAME_RELATED_P (insn) = 1;
00313 }
00314 }
00315 }
00316
00317
00318 if (current_frame_info.frame_size == 0)
00319 ;
00320 else if (current_frame_info.save_fp
00321 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
00322 ;
00323 else if (current_frame_info.frame_size <= 512)
00324 {
00325 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
00326 RTX_FRAME_RELATED_P (insn) = 1;
00327 }
00328 else
00329 {
00330 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
00331 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
00332 RTX_FRAME_RELATED_P (insn) = 1;
00333 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
00334 RTX_FRAME_RELATED_P (insn) = 1;
00335 }
00336
00337 if (current_function_profile)
00338 emit_insn (gen_blockage ());
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 void
00348 fr30_expand_epilogue ()
00349 {
00350 int regno;
00351
00352
00353 if (! current_frame_info.initialised)
00354 abort ();
00355
00356
00357
00358
00359
00360
00361 if (current_frame_info.frame_size > 0)
00362 {
00363 if (current_frame_info.save_fp && frame_pointer_needed)
00364 {
00365 emit_insn (gen_leave_func ());
00366 current_frame_info.save_fp = 0;
00367 }
00368 else if (current_frame_info.frame_size <= 508)
00369 emit_insn (gen_add_to_stack
00370 (GEN_INT (current_frame_info.frame_size)));
00371 else
00372 {
00373 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
00374 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
00375 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
00376 }
00377 }
00378
00379 if (current_frame_info.save_fp)
00380 emit_insn (gen_movsi_pop (frame_pointer_rtx));
00381
00382
00383 if (current_frame_info.save_rp)
00384 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
00385
00386 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
00387 if (current_frame_info.gmask & (1 << regno))
00388 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
00389
00390 if (current_frame_info.pretend_size)
00391 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
00392
00393
00394 current_frame_info = zero_frame_info;
00395
00396 emit_jump_insn (gen_return_from_func ());
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406 void
00407 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
00408 CUMULATIVE_ARGS arg_regs_used_so_far;
00409 int int_mode;
00410 tree type ATTRIBUTE_UNUSED;
00411 int * pretend_size;
00412 {
00413 enum machine_mode mode = (enum machine_mode)int_mode;
00414 int size;
00415
00416
00417
00418 if (mode == BLKmode)
00419 abort ();
00420
00421 #if STRICT_ARGUMENT_NAMING
00422
00423
00424
00425 if (! current_function_varargs)
00426 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
00427 #endif
00428
00429 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
00430
00431 if (size <= 0)
00432 return;
00433
00434 * pretend_size = (size * UNITS_PER_WORD);
00435 }
00436
00437
00438
00439
00440
00441
00442 void
00443 fr30_print_operand_address (stream, address)
00444 FILE * stream;
00445 rtx address;
00446 {
00447 switch (GET_CODE (address))
00448 {
00449 case SYMBOL_REF:
00450 output_addr_const (stream, address);
00451 break;
00452
00453 default:
00454 fprintf (stderr, "code = %x\n", GET_CODE (address));
00455 debug_rtx (address);
00456 output_operand_lossage ("fr30_print_operand_address: unhandled address");
00457 break;
00458 }
00459 }
00460
00461
00462
00463 void
00464 fr30_print_operand (file, x, code)
00465 FILE * file;
00466 rtx x;
00467 int code;
00468 {
00469 rtx x0;
00470
00471 switch (code)
00472 {
00473 case '#':
00474
00475 if (dbr_sequence_length () != 0)
00476 fputs (":D", file);
00477 return;
00478
00479 case 'p':
00480
00481
00482 if (GET_CODE (x) != REG)
00483 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
00484 else
00485 fprintf (file, "r%d", REGNO (x) + 1);
00486 return;
00487
00488 case 'b':
00489
00490 switch (GET_CODE (x))
00491 {
00492 case EQ: fprintf (file, "eq"); break;
00493 case NE: fprintf (file, "ne"); break;
00494 case LT: fprintf (file, "lt"); break;
00495 case LE: fprintf (file, "le"); break;
00496 case GT: fprintf (file, "gt"); break;
00497 case GE: fprintf (file, "ge"); break;
00498 case LTU: fprintf (file, "c"); break;
00499 case LEU: fprintf (file, "ls"); break;
00500 case GTU: fprintf (file, "hi"); break;
00501 case GEU: fprintf (file, "nc"); break;
00502 default:
00503 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
00504 break;
00505 }
00506 return;
00507
00508 case 'B':
00509
00510
00511 switch (GET_CODE (x))
00512 {
00513 case EQ: fprintf (file, "ne"); break;
00514 case NE: fprintf (file, "eq"); break;
00515 case LT: fprintf (file, "ge"); break;
00516 case LE: fprintf (file, "gt"); break;
00517 case GT: fprintf (file, "le"); break;
00518 case GE: fprintf (file, "lt"); break;
00519 case LTU: fprintf (file, "nc"); break;
00520 case LEU: fprintf (file, "hi"); break;
00521 case GTU: fprintf (file, "ls"); break;
00522 case GEU: fprintf (file, "c"); break;
00523 default:
00524 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
00525 break;
00526 }
00527 return;
00528
00529 case 'A':
00530
00531 if (GET_CODE (x) != CONST_INT)
00532 output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
00533 else
00534 {
00535 HOST_WIDE_INT val;
00536
00537 val = INTVAL (x);
00538
00539 val &= 0xff;
00540
00541 fprintf (file, "%d", val);
00542 }
00543 return;
00544
00545 case 'x':
00546 if (GET_CODE (x) != CONST_INT
00547 || INTVAL (x) < 16
00548 || INTVAL (x) > 32)
00549 output_operand_lossage ("fr30_print_operand: invalid %%x code");
00550 else
00551 fprintf (file, "%d", INTVAL (x) - 16);
00552 return;
00553
00554 case 'F':
00555 if (GET_CODE (x) != CONST_DOUBLE)
00556 output_operand_lossage ("fr30_print_operand: invalid %%F code");
00557 else
00558 {
00559 REAL_VALUE_TYPE d;
00560
00561 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
00562 fprintf (file, "%.8f", d);
00563 }
00564 return;
00565
00566 case 0:
00567
00568 break;
00569
00570 default:
00571 fprintf (stderr, "unknown code = %x\n", code);
00572 output_operand_lossage ("fr30_print_operand: unknown code");
00573 return;
00574 }
00575
00576 switch (GET_CODE (x))
00577 {
00578 case REG:
00579 fputs (reg_names [REGNO (x)], file);
00580 break;
00581
00582 case MEM:
00583 x0 = XEXP (x,0);
00584
00585 switch (GET_CODE (x0))
00586 {
00587 case REG:
00588 if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
00589 abort ();
00590 fprintf (file, "@%s", reg_names [REGNO (x0)]);
00591 break;
00592
00593 case PLUS:
00594 if (GET_CODE (XEXP (x0, 0)) != REG
00595 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
00596 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
00597 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
00598 {
00599 fprintf (stderr, "bad INDEXed address:");
00600 debug_rtx (x);
00601 output_operand_lossage ("fr30_print_operand: unhandled MEM");
00602 }
00603 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
00604 {
00605 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
00606 if (val < -(1 << 9) || val > ((1 << 9) - 4))
00607 {
00608 fprintf (stderr, "frame INDEX out of range:");
00609 debug_rtx (x);
00610 output_operand_lossage ("fr30_print_operand: unhandled MEM");
00611 }
00612 fprintf (file, "@(r14, #%d)", val);
00613 }
00614 else
00615 {
00616 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
00617 if (val < 0 || val > ((1 << 6) - 4))
00618 {
00619 fprintf (stderr, "stack INDEX out of range:");
00620 debug_rtx (x);
00621 output_operand_lossage ("fr30_print_operand: unhandled MEM");
00622 }
00623 fprintf (file, "@(r15, #%d)", val);
00624 }
00625 break;
00626
00627 case SYMBOL_REF:
00628 output_address (x0);
00629 break;
00630
00631 default:
00632 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
00633 debug_rtx (x);
00634 output_operand_lossage ("fr30_print_operand: unhandled MEM");
00635 break;
00636 }
00637 break;
00638
00639 case CONST_DOUBLE :
00640
00641 if (GET_MODE (x) == SFmode)
00642 {
00643 REAL_VALUE_TYPE d;
00644 long l;
00645
00646 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
00647 REAL_VALUE_TO_TARGET_SINGLE (d, l);
00648 fprintf (file, "0x%08lx", l);
00649 break;
00650 }
00651
00652
00653 default:
00654 output_addr_const (file, x);
00655 break;
00656 }
00657
00658 return;
00659 }
00660
00661
00662
00663
00664
00665
00666 int
00667 fr30_num_arg_regs (int_mode, type)
00668 int int_mode;
00669 tree type;
00670 {
00671 enum machine_mode mode = (enum machine_mode) int_mode;
00672 int size;
00673
00674 if (MUST_PASS_IN_STACK (mode, type))
00675 return 0;
00676
00677 if (type && mode == BLKmode)
00678 size = int_size_in_bytes (type);
00679 else
00680 size = GET_MODE_SIZE (mode);
00681
00682 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 int
00694 fr30_function_arg_partial_nregs (cum, int_mode, type, named)
00695 CUMULATIVE_ARGS cum;
00696 int int_mode;
00697 tree type;
00698 int named;
00699 {
00700
00701
00702
00703 if (named == 0 || cum >= FR30_NUM_ARG_REGS)
00704 return 0;
00705
00706
00707
00708
00709
00710
00711
00712 if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
00713 return 0;
00714
00715
00716 return FR30_NUM_ARG_REGS - cum;
00717 }
00718
00719 static rtx
00720 fr30_pass_by_reference (valist, type)
00721 tree valist;
00722 tree type;
00723 {
00724 tree type_ptr;
00725 tree type_ptr_ptr;
00726 tree t;
00727
00728 type_ptr = build_pointer_type (type);
00729 type_ptr_ptr = build_pointer_type (type_ptr);
00730
00731 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
00732 TREE_SIDE_EFFECTS (t) = 1;
00733 t = build1 (NOP_EXPR, type_ptr_ptr, t);
00734 TREE_SIDE_EFFECTS (t) = 1;
00735 t = build1 (INDIRECT_REF, type_ptr, t);
00736
00737 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
00738 }
00739
00740 static rtx
00741 fr30_pass_by_value (valist, type)
00742 tree valist;
00743 tree type;
00744 {
00745 HOST_WIDE_INT size = int_size_in_bytes (type);
00746 HOST_WIDE_INT rsize;
00747 rtx addr_rtx;
00748 tree t;
00749
00750 if ((size % UNITS_PER_WORD) == 0)
00751 {
00752 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
00753 TREE_SIDE_EFFECTS (t) = 1;
00754
00755 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
00756 }
00757
00758 rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
00759
00760
00761 t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
00762 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
00763 addr_rtx = copy_to_reg (addr_rtx);
00764
00765
00766 t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
00767 t = build (MODIFY_EXPR, va_list_type_node, valist, t);
00768 TREE_SIDE_EFFECTS (t) = 1;
00769 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00770
00771 return addr_rtx;
00772 }
00773
00774
00775
00776 rtx
00777 fr30_va_arg (valist, type)
00778 tree valist;
00779 tree type;
00780 {
00781 HOST_WIDE_INT size;
00782
00783 if (AGGREGATE_TYPE_P (type))
00784 return fr30_pass_by_reference (valist, type);
00785
00786 size = int_size_in_bytes (type);
00787
00788 if ((size % sizeof (int)) == 0
00789 || size < 4)
00790 return fr30_pass_by_value (valist, type);
00791
00792 return fr30_pass_by_reference (valist, type);
00793 }
00794
00795
00796
00797
00798 #ifndef Mmode
00799 #define Mmode enum machine_mode
00800 #endif
00801
00802
00803
00804 int
00805 stack_add_operand (operand, mode)
00806 rtx operand;
00807 Mmode mode ATTRIBUTE_UNUSED;
00808 {
00809 return
00810 (GET_CODE (operand) == CONST_INT
00811 && INTVAL (operand) >= -512
00812 && INTVAL (operand) <= 508
00813 && ((INTVAL (operand) & 3) == 0));
00814 }
00815
00816
00817
00818 int
00819 add_immediate_operand (operand, mode)
00820 rtx operand;
00821 Mmode mode ATTRIBUTE_UNUSED;
00822 {
00823 return
00824 (GET_CODE (operand) == REG
00825 || (GET_CODE (operand) == CONST_INT
00826 && INTVAL (operand) >= -16
00827 && INTVAL (operand) <= 15));
00828 }
00829
00830
00831 int
00832 high_register_operand (operand, mode)
00833 rtx operand;
00834 Mmode mode ATTRIBUTE_UNUSED;
00835 {
00836 return
00837 (GET_CODE (operand) == REG
00838 && REGNO (operand) <= 15
00839 && REGNO (operand) >= 8);
00840 }
00841
00842
00843 int
00844 low_register_operand (operand, mode)
00845 rtx operand;
00846 Mmode mode ATTRIBUTE_UNUSED;
00847 {
00848 return
00849 (GET_CODE (operand) == REG
00850 && REGNO (operand) <= 7);
00851 }
00852
00853
00854 int
00855 call_operand (operand, mode)
00856 rtx operand;
00857 Mmode mode ATTRIBUTE_UNUSED;
00858 {
00859 return (GET_CODE (operand) == MEM
00860 && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
00861 || GET_CODE (XEXP (operand, 0)) == REG));
00862 }
00863
00864
00865 int
00866 di_operand (op, mode)
00867 rtx op;
00868 Mmode mode;
00869 {
00870 if (register_operand (op, mode))
00871 return TRUE;
00872
00873 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
00874 return FALSE;
00875
00876 if (GET_CODE (op) == SUBREG)
00877 op = SUBREG_REG (op);
00878
00879 switch (GET_CODE (op))
00880 {
00881 case CONST_DOUBLE:
00882 case CONST_INT:
00883 return TRUE;
00884
00885 case MEM:
00886 return memory_address_p (DImode, XEXP (op, 0));
00887
00888 default:
00889 return FALSE;
00890 }
00891 }
00892
00893
00894 int
00895 nonimmediate_di_operand (op, mode)
00896 rtx op;
00897 Mmode mode;
00898 {
00899 if (register_operand (op, mode))
00900 return TRUE;
00901
00902 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
00903 return FALSE;
00904
00905 if (GET_CODE (op) == SUBREG)
00906 op = SUBREG_REG (op);
00907
00908 if (GET_CODE (op) == MEM)
00909 return memory_address_p (DImode, XEXP (op, 0));
00910
00911 return FALSE;
00912 }
00913
00914
00915
00916 int
00917 fr30_check_multiple_regs (operands, num_operands, descending)
00918 rtx * operands;
00919 int num_operands;
00920 int descending;
00921 {
00922 if (descending)
00923 {
00924 unsigned int prev_regno = 0;
00925
00926 while (num_operands --)
00927 {
00928 if (GET_CODE (operands [num_operands]) != REG)
00929 return 0;
00930
00931 if (REGNO (operands [num_operands]) < prev_regno)
00932 return 0;
00933
00934 prev_regno = REGNO (operands [num_operands]);
00935 }
00936 }
00937 else
00938 {
00939 unsigned int prev_regno = CONDITION_CODE_REGNUM;
00940
00941 while (num_operands --)
00942 {
00943 if (GET_CODE (operands [num_operands]) != REG)
00944 return 0;
00945
00946 if (REGNO (operands [num_operands]) > prev_regno)
00947 return 0;
00948
00949 prev_regno = REGNO (operands [num_operands]);
00950 }
00951 }
00952
00953 return 1;
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 rtx
00967 fr30_move_double (operands)
00968 rtx * operands;
00969 {
00970 rtx src = operands[1];
00971 rtx dest = operands[0];
00972 enum rtx_code src_code = GET_CODE (src);
00973 enum rtx_code dest_code = GET_CODE (dest);
00974 enum machine_mode mode = GET_MODE (dest);
00975 rtx val;
00976
00977 start_sequence ();
00978
00979 if (dest_code == REG)
00980 {
00981 if (src_code == REG)
00982 {
00983 int reverse = (REGNO (dest) == REGNO (src) + 1);
00984
00985
00986
00987
00988 emit_insn (gen_rtx_SET (VOIDmode,
00989 operand_subword (dest, reverse, TRUE, mode),
00990 operand_subword (src, reverse, TRUE, mode)));
00991
00992 emit_insn (gen_rtx_SET (VOIDmode,
00993 operand_subword (dest, !reverse, TRUE, mode),
00994 operand_subword (src, !reverse, TRUE, mode)));
00995 }
00996 else if (src_code == MEM)
00997 {
00998 rtx addr = XEXP (src, 0);
00999 int dregno = REGNO (dest);
01000 rtx dest0;
01001 rtx dest1;
01002 rtx new_mem;
01003
01004
01005
01006 int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
01007
01008 if (GET_CODE (addr) != REG)
01009 abort ();
01010
01011 dest0 = operand_subword (dest, reverse, TRUE, mode);
01012 dest1 = operand_subword (dest, !reverse, TRUE, mode);
01013
01014 if (reverse)
01015 {
01016 emit_insn (gen_rtx_SET (VOIDmode, dest1,
01017 adjust_address (src, SImode, 0)));
01018 emit_insn (gen_rtx_SET (SImode, dest0,
01019 gen_rtx_REG (SImode, REGNO (addr))));
01020 emit_insn (gen_rtx_SET (SImode, dest0,
01021 plus_constant (dest0, UNITS_PER_WORD)));
01022
01023 new_mem = gen_rtx_MEM (SImode, dest0);
01024 MEM_COPY_ATTRIBUTES (new_mem, src);
01025
01026 emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
01027 }
01028 else
01029 {
01030 emit_insn (gen_rtx_SET (VOIDmode, dest0,
01031 adjust_address (src, SImode, 0)));
01032 emit_insn (gen_rtx_SET (SImode, dest1,
01033 gen_rtx_REG (SImode, REGNO (addr))));
01034 emit_insn (gen_rtx_SET (SImode, dest1,
01035 plus_constant (dest1, UNITS_PER_WORD)));
01036
01037 new_mem = gen_rtx_MEM (SImode, dest1);
01038 MEM_COPY_ATTRIBUTES (new_mem, src);
01039
01040 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
01041 }
01042 }
01043 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
01044 {
01045 rtx words[2];
01046 split_double (src, &words[0], &words[1]);
01047 emit_insn (gen_rtx_SET (VOIDmode,
01048 operand_subword (dest, 0, TRUE, mode),
01049 words[0]));
01050
01051 emit_insn (gen_rtx_SET (VOIDmode,
01052 operand_subword (dest, 1, TRUE, mode),
01053 words[1]));
01054 }
01055 }
01056 else if (src_code == REG && dest_code == MEM)
01057 {
01058 rtx addr = XEXP (dest, 0);
01059 rtx src0;
01060 rtx src1;
01061
01062 if (GET_CODE (addr) != REG)
01063 abort ();
01064
01065 src0 = operand_subword (src, 0, TRUE, mode);
01066 src1 = operand_subword (src, 1, TRUE, mode);
01067
01068 emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
01069 src0));
01070
01071 if (REGNO (addr) == STACK_POINTER_REGNUM
01072 || REGNO (addr) == FRAME_POINTER_REGNUM)
01073 emit_insn (gen_rtx_SET (VOIDmode,
01074 adjust_address (dest, SImode, UNITS_PER_WORD),
01075 src1));
01076 else
01077 {
01078 rtx new_mem;
01079
01080
01081
01082
01083 emit_insn (gen_movsi_push (src0));
01084 emit_insn (gen_movsi_internal (src0, addr));
01085 emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
01086
01087 new_mem = gen_rtx_MEM (SImode, src0);
01088 MEM_COPY_ATTRIBUTES (new_mem, dest);
01089
01090 emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
01091 emit_insn (gen_movsi_pop (src0));
01092 }
01093 }
01094 else
01095
01096 abort ();
01097
01098 val = gen_sequence ();
01099 end_sequence ();
01100
01101 return val;
01102 }