00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "tree.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 "flags.h"
00035 #include "recog.h"
00036 #include "expr.h"
00037 #include "function.h"
00038 #include "obstack.h"
00039 #include "ggc.h"
00040 #include "toplev.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 rtx zero_dreg;
00063 rtx zero_areg;
00064
00065 static void count_tst_insns PARAMS ((int *));
00066
00067
00068 static int out_of_line_epilogue;
00069
00070
00071 #undef TARGET_ASM_ALIGNED_HI_OP
00072 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00073
00074 struct gcc_target targetm = TARGET_INITIALIZER;
00075
00076
00077
00078 void
00079 asm_file_start (file)
00080 FILE *file;
00081 {
00082 fprintf (file, "#\tGCC For the Matsushita MN10200\n");
00083 if (optimize)
00084 fprintf (file, "# -O%d\n", optimize);
00085 else
00086 fprintf (file, "\n\n");
00087 output_file_directive (file, main_input_filename);
00088 ggc_add_rtx_root (&zero_dreg, 1);
00089 ggc_add_rtx_root (&zero_areg, 1);
00090 }
00091
00092
00093
00094
00095 void
00096 print_operand (file, x, code)
00097 FILE *file;
00098 rtx x;
00099 int code;
00100 {
00101 switch (code)
00102 {
00103 case 'b':
00104 case 'B':
00105
00106 switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
00107 {
00108 case NE:
00109 fprintf (file, "ne");
00110 break;
00111 case EQ:
00112 fprintf (file, "eq");
00113 break;
00114 case GE:
00115 fprintf (file, "ge");
00116 break;
00117 case GT:
00118 fprintf (file, "gt");
00119 break;
00120 case LE:
00121 fprintf (file, "le");
00122 break;
00123 case LT:
00124 fprintf (file, "lt");
00125 break;
00126 case GEU:
00127 fprintf (file, "cc");
00128 break;
00129 case GTU:
00130 fprintf (file, "hi");
00131 break;
00132 case LEU:
00133 fprintf (file, "ls");
00134 break;
00135 case LTU:
00136 fprintf (file, "cs");
00137 break;
00138 default:
00139 abort ();
00140 }
00141 break;
00142 case 'C':
00143
00144
00145
00146 if (GET_CODE (x) == REG)
00147 {
00148 fputc ('(', file);
00149 print_operand (file, x, 0);
00150 fputc (')', file);
00151 }
00152 else
00153 print_operand (file, x, 0);
00154 break;
00155
00156
00157
00158
00159 case 'L':
00160 case 'o':
00161 switch (GET_CODE (x))
00162 {
00163 case MEM:
00164 fputc ('(', file);
00165 output_address (XEXP (x, 0));
00166 fputc (')', file);
00167 break;
00168
00169 case REG:
00170 fprintf (file, "%s", reg_names[REGNO (x)]);
00171 break;
00172
00173 case SUBREG:
00174 fprintf (file, "%s", reg_names[subreg_regno (x)]);
00175 break;
00176
00177 case CONST_DOUBLE:
00178 if (code == 'L')
00179 {
00180 long val;
00181 REAL_VALUE_TYPE rv;
00182
00183 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00184 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
00185 print_operand_address (file, GEN_INT (val & 0xffff));
00186 }
00187 else
00188 {
00189 long val;
00190 REAL_VALUE_TYPE rv;
00191
00192 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00193 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
00194
00195 val &= 0xffff;
00196 val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
00197 print_operand_address (file, GEN_INT (val));
00198 }
00199 break;
00200
00201 case CONST_INT:
00202 if (code == 'L')
00203 print_operand_address (file, GEN_INT ((INTVAL (x) & 0xffff)));
00204 else
00205 {
00206 unsigned int val = INTVAL (x) & 0xffff;
00207 val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
00208 print_operand_address (file, GEN_INT (val));
00209 }
00210 break;
00211 default:
00212 abort ();
00213 }
00214 break;
00215
00216
00217 case 'H':
00218 case 'h':
00219 switch (GET_CODE (x))
00220 {
00221 case MEM:
00222 fputc ('(', file);
00223 x = adjust_address (x, HImode, 2);
00224 output_address (XEXP (x, 0));
00225 fputc (')', file);
00226 break;
00227
00228 case REG:
00229 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
00230 break;
00231
00232 case SUBREG:
00233 fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
00234 break;
00235
00236 case CONST_DOUBLE:
00237 if (code == 'H')
00238 {
00239 long val;
00240 REAL_VALUE_TYPE rv;
00241
00242 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00243 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
00244
00245 print_operand_address (file, GEN_INT ((val >> 16) & 0xffff));
00246 }
00247 else
00248 {
00249 long val;
00250 REAL_VALUE_TYPE rv;
00251
00252 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00253 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
00254
00255 val = (val >> 16) & 0xffff;
00256 val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
00257
00258 print_operand_address (file, GEN_INT (val));
00259 }
00260 break;
00261
00262 case CONST_INT:
00263 if (code == 'H')
00264 print_operand_address (file,
00265 GEN_INT ((INTVAL (x) >> 16) & 0xffff));
00266 else
00267 {
00268 unsigned int val = (INTVAL (x) >> 16) & 0xffff;
00269 val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
00270
00271 print_operand_address (file, GEN_INT (val));
00272 }
00273 break;
00274 default:
00275 abort ();
00276 }
00277 break;
00278
00279
00280 case 'N':
00281 if (GET_CODE (x) != CONST_INT)
00282 abort ();
00283 fprintf (file, "%d", ~INTVAL (x));
00284 break;
00285
00286
00287
00288 case 'A':
00289 if (GET_CODE (x) != MEM)
00290 abort ();
00291 if (GET_CODE (XEXP (x, 0)) == REG)
00292 x = gen_rtx_PLUS (PSImode, XEXP (x, 0), GEN_INT (0));
00293 else
00294 x = XEXP (x, 0);
00295 fputc ('(', file);
00296 output_address (x);
00297 fputc (')', file);
00298 break;
00299
00300 case 'Z':
00301 print_operand (file, XEXP (x, 1), 0);
00302 break;
00303
00304
00305
00306 case 's':
00307 case 'S':
00308 if (GET_CODE (x) == CONST_INT)
00309 {
00310 int val = INTVAL (x);
00311
00312 if (code == 's')
00313 x = GEN_INT (((val & 0xffff) ^ (~0x7fff)) + 0x8000);
00314 else
00315 x = GEN_INT (((val & 0xff) ^ (~0x7f)) + 0x80);
00316 }
00317
00318 default:
00319 switch (GET_CODE (x))
00320 {
00321 case MEM:
00322 fputc ('(', file);
00323 output_address (XEXP (x, 0));
00324 fputc (')', file);
00325 break;
00326
00327 case REG:
00328 fprintf (file, "%s", reg_names[REGNO (x)]);
00329 break;
00330
00331 case SUBREG:
00332 fprintf (file, "%s", reg_names[subreg_regno (x)]);
00333 break;
00334
00335 case CONST_INT:
00336 case CONST_DOUBLE:
00337 case SYMBOL_REF:
00338 case CONST:
00339 case LABEL_REF:
00340 case CODE_LABEL:
00341 print_operand_address (file, x);
00342 break;
00343 default:
00344 abort ();
00345 }
00346 break;
00347 }
00348 }
00349
00350
00351
00352 void
00353 print_operand_address (file, addr)
00354 FILE *file;
00355 rtx addr;
00356 {
00357 switch (GET_CODE (addr))
00358 {
00359 case REG:
00360 print_operand (file, addr, 0);
00361 break;
00362 case PLUS:
00363 {
00364 rtx base, index;
00365
00366
00367
00368 if (REG_P (XEXP (addr, 0))
00369 && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
00370 base = XEXP (addr, 0), index = XEXP (addr, 1);
00371 else if (REG_P (XEXP (addr, 1))
00372 && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
00373 base = XEXP (addr, 1), index = XEXP (addr, 0);
00374 else
00375 abort ();
00376 print_operand (file, index, 0);
00377 fputc (',', file);
00378 print_operand (file, base, 0);;
00379 break;
00380 }
00381 case SYMBOL_REF:
00382 output_addr_const (file, addr);
00383 break;
00384 default:
00385 output_addr_const (file, addr);
00386 break;
00387 }
00388 }
00389
00390
00391
00392 static void
00393 count_tst_insns (areg_countp)
00394 int *areg_countp;
00395 {
00396 rtx insn;
00397
00398
00399 *areg_countp = 0;
00400
00401
00402 if (!optimize)
00403 return;
00404
00405
00406 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
00407 {
00408 rtx pat;
00409
00410
00411 if (GET_CODE (insn) != INSN)
00412 continue;
00413
00414
00415 pat = PATTERN (insn);
00416 if (GET_CODE (pat) != SET)
00417 continue;
00418
00419
00420 if (SET_DEST (pat) == cc0_rtx
00421 && GET_CODE (SET_SRC (pat)) == REG
00422 && REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS)
00423 (*areg_countp)++;
00424 }
00425 }
00426
00427
00428
00429
00430 int
00431 total_frame_size ()
00432 {
00433 unsigned int size = get_frame_size ();
00434 unsigned int outgoing_args_size = current_function_outgoing_args_size;
00435 int i;
00436
00437
00438
00439
00440 if (optimize && !current_function_needs_context && !frame_pointer_needed)
00441 {
00442 int inline_count, outline_count;
00443
00444
00445
00446
00447
00448 inline_count = 0;
00449 if (regs_ever_live[5])
00450 inline_count += 2;
00451 if (regs_ever_live[6])
00452 inline_count += 2;
00453 if (regs_ever_live[2])
00454 inline_count += 3;
00455 if (regs_ever_live[3])
00456 inline_count += 3;
00457
00458
00459
00460 if (size || outgoing_args_size
00461 || regs_ever_live[5] || regs_ever_live[6]
00462 || regs_ever_live[2] || regs_ever_live[3])
00463 inline_count += 2;
00464
00465
00466
00467 inline_count = inline_count * 2 + 1;
00468
00469
00470
00471 outline_count = 3;
00472
00473
00474
00475
00476 outline_count += (outgoing_args_size == 0 ? 0 : 2);
00477
00478
00479
00480 if (get_frame_size () != 0)
00481 outline_count += 2;
00482
00483
00484
00485 outline_count = outline_count * 2 + 1;
00486
00487 if (get_frame_size () == 0 && outgoing_args_size == 0)
00488 outline_count -= 1;
00489
00490
00491 if (inline_count > outline_count)
00492 return size + outgoing_args_size + 16;
00493 }
00494
00495
00496 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00497 {
00498 if ((regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i])
00499 || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))
00500 size += 4;
00501 }
00502
00503 return (size + outgoing_args_size);
00504 }
00505
00506
00507 void
00508 expand_prologue ()
00509 {
00510 unsigned int size = total_frame_size ();
00511 unsigned int outgoing_args_size = current_function_outgoing_args_size;
00512 int offset, i;
00513
00514 zero_areg = NULL_RTX;
00515 zero_dreg = NULL_RTX;
00516
00517
00518
00519
00520
00521
00522 if (optimize && !current_function_needs_context && !frame_pointer_needed)
00523 {
00524 int inline_count, outline_count, areg_count;
00525
00526
00527
00528
00529 end_sequence ();
00530
00531
00532
00533
00534 count_tst_insns (&areg_count);
00535
00536
00537 start_sequence ();
00538
00539
00540
00541
00542
00543 inline_count = 0;
00544 if (regs_ever_live[5])
00545 inline_count += 2;
00546 if (regs_ever_live[6])
00547 inline_count += 2;
00548 if (regs_ever_live[2])
00549 inline_count += 3;
00550 if (regs_ever_live[3])
00551 inline_count += 3;
00552
00553
00554
00555 if (size || outgoing_args_size
00556 || regs_ever_live[5] || regs_ever_live[6]
00557 || regs_ever_live[2] || regs_ever_live[3])
00558 inline_count += 2;
00559
00560
00561
00562 inline_count = inline_count * 2 + 1;
00563
00564
00565
00566 outline_count = 3;
00567
00568
00569
00570
00571 outline_count += (outgoing_args_size == 0 ? 0 : 2);
00572
00573
00574
00575 if (get_frame_size () != 0)
00576 outline_count += 2;
00577
00578
00579
00580 outline_count = outline_count * 2 + 1;
00581
00582 if (get_frame_size () == 0 && outgoing_args_size == 0)
00583 outline_count -= 1;
00584
00585
00586 if (inline_count > outline_count)
00587 {
00588 if (get_frame_size () != 0)
00589 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00590 GEN_INT (-size + outgoing_args_size + 16)));
00591 emit_insn (gen_outline_prologue_call ());
00592
00593 if (outgoing_args_size)
00594 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00595 GEN_INT (-outgoing_args_size)));
00596
00597 out_of_line_epilogue = 1;
00598
00599
00600
00601
00602
00603
00604 if (areg_count > 1
00605 && (!regs_ever_live[2] || !regs_ever_live[3]))
00606 {
00607 if (!regs_ever_live[2])
00608 {
00609 regs_ever_live[2] = 1;
00610 zero_dreg = gen_rtx_REG (HImode, 2);
00611 }
00612 if (!regs_ever_live[3])
00613 {
00614 regs_ever_live[3] = 1;
00615 zero_dreg = gen_rtx_REG (HImode, 3);
00616 }
00617 }
00618
00619
00620 if (zero_dreg == NULL_RTX
00621 && areg_count > 2
00622 && (!regs_ever_live[5] || !regs_ever_live[6]))
00623 {
00624 if (!regs_ever_live[5])
00625 {
00626 regs_ever_live[5] = 1;
00627 zero_areg = gen_rtx_REG (HImode, 5);
00628 }
00629 if (!regs_ever_live[6])
00630 {
00631 regs_ever_live[6] = 1;
00632 zero_areg = gen_rtx_REG (HImode, 6);
00633 }
00634 }
00635
00636 if (zero_dreg)
00637 emit_move_insn (zero_dreg, const0_rtx);
00638
00639 if (zero_areg)
00640 emit_move_insn (zero_areg, const0_rtx);
00641
00642 return;
00643 }
00644 }
00645
00646 out_of_line_epilogue = 0;
00647
00648
00649
00650 if (current_function_needs_context)
00651 {
00652 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00653 GEN_INT (-4)));
00654 emit_move_insn (gen_rtx_MEM (PSImode, stack_pointer_rtx),
00655 gen_rtx_REG (PSImode, STATIC_CHAIN_REGNUM));
00656 }
00657
00658 if (frame_pointer_needed)
00659 {
00660
00661 emit_move_insn (gen_rtx_REG (PSImode, 4), frame_pointer_rtx);
00662
00663
00664 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
00665 }
00666
00667
00668 if (size)
00669 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00670 GEN_INT (-size)));
00671
00672
00673
00674 for (i = 0, offset = outgoing_args_size;
00675 i < FIRST_PSEUDO_REGISTER; i++)
00676 {
00677 if ((regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i])
00678 || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))
00679 {
00680 int regno;
00681
00682
00683
00684 regno = (i == FRAME_POINTER_REGNUM && frame_pointer_needed) ? 4 : i;
00685
00686 emit_move_insn (gen_rtx_MEM (PSImode,
00687 plus_constant (stack_pointer_rtx,
00688 offset)),
00689 gen_rtx_REG (PSImode, regno));
00690 offset += 4;
00691 }
00692 }
00693
00694
00695
00696 if (current_function_needs_context)
00697 {
00698 emit_move_insn (gen_rtx_REG (PSImode, STATIC_CHAIN_REGNUM),
00699 gen_rtx (MEM, PSImode,
00700 gen_rtx_PLUS (PSImode, stack_pointer_rtx,
00701 GEN_INT (size))));
00702 }
00703 }
00704
00705
00706 void
00707 expand_epilogue ()
00708 {
00709 unsigned int size;
00710 unsigned int outgoing_args_size = current_function_outgoing_args_size;
00711 int offset, i, temp_regno;
00712 rtx basereg;
00713
00714 size = total_frame_size ();
00715
00716 if (DECL_RESULT (current_function_decl)
00717 && DECL_RTL (DECL_RESULT (current_function_decl))
00718 && REG_P (DECL_RTL (DECL_RESULT (current_function_decl))))
00719 temp_regno = (REGNO (DECL_RTL (DECL_RESULT (current_function_decl))) == 4
00720 ? 0 : 4);
00721 else
00722 temp_regno = 4;
00723
00724
00725 if (out_of_line_epilogue)
00726 {
00727
00728
00729
00730 if (get_frame_size () == 0 && outgoing_args_size == 0)
00731 {
00732 emit_jump_insn (gen_outline_epilogue_jump ());
00733 return;
00734 }
00735
00736 if (outgoing_args_size)
00737 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00738 GEN_INT (outgoing_args_size)));
00739
00740 if (temp_regno == 0)
00741 emit_insn (gen_outline_epilogue_call_d0 ());
00742 else if (temp_regno == 4)
00743 emit_insn (gen_outline_epilogue_call_a0 ());
00744
00745 if (get_frame_size () != 0)
00746 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00747 GEN_INT (size - outgoing_args_size - 16)));
00748 emit_jump_insn (gen_return_internal ());
00749 return;
00750 }
00751
00752
00753
00754
00755 if (frame_pointer_needed)
00756 {
00757 basereg = frame_pointer_rtx;
00758 offset = -(size - outgoing_args_size);
00759 }
00760 else
00761 {
00762 basereg = stack_pointer_rtx;
00763 offset = outgoing_args_size;
00764 }
00765
00766
00767 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00768 {
00769 if ((regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i])
00770 || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))
00771 {
00772 int regno;
00773
00774
00775
00776 regno = ((i == FRAME_POINTER_REGNUM && frame_pointer_needed)
00777 ? temp_regno : i);
00778
00779 emit_move_insn (gen_rtx_REG (PSImode, regno),
00780 gen_rtx_MEM (PSImode,
00781 plus_constant (basereg, offset)));
00782 offset += 4;
00783 }
00784 }
00785
00786 if (frame_pointer_needed)
00787 {
00788
00789 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
00790
00791 emit_move_insn (frame_pointer_rtx, gen_rtx_REG (PSImode, temp_regno));
00792 }
00793 else if (size)
00794 {
00795
00796 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
00797 GEN_INT (size)));
00798 }
00799
00800
00801
00802 if (current_function_needs_context)
00803 emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (4)));
00804
00805
00806
00807
00808 if (size == 0 && !current_function_needs_context)
00809 emit_jump_insn (gen_return ());
00810 else
00811 emit_jump_insn (gen_return_internal ());
00812 }
00813
00814
00815
00816 void
00817 notice_update_cc (body, insn)
00818 rtx body;
00819 rtx insn;
00820 {
00821 switch (get_attr_cc (insn))
00822 {
00823 case CC_NONE:
00824
00825 break;
00826
00827 case CC_NONE_0HIT:
00828
00829 if (cc_status.value1 != 0
00830 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
00831 cc_status.value1 = 0;
00832 break;
00833
00834 case CC_SET_ZN:
00835
00836
00837 CC_STATUS_INIT;
00838 cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
00839 cc_status.value1 = recog_data.operand[0];
00840 break;
00841
00842 case CC_SET_ZNV:
00843
00844
00845 CC_STATUS_INIT;
00846 cc_status.flags |= CC_NO_CARRY;
00847 cc_status.value1 = recog_data.operand[0];
00848 break;
00849
00850 case CC_COMPARE:
00851
00852 CC_STATUS_INIT;
00853 cc_status.value1 = SET_SRC (body);
00854 break;
00855
00856 case CC_CLOBBER:
00857
00858 CC_STATUS_INIT;
00859 break;
00860
00861 default:
00862 CC_STATUS_INIT;
00863 break;
00864 }
00865 }
00866
00867
00868
00869 int
00870 call_address_operand (op, mode)
00871 rtx op;
00872 enum machine_mode mode ATTRIBUTE_UNUSED;
00873 {
00874 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
00875 }
00876
00877
00878
00879 int
00880 constant_memory_operand (op, mode)
00881 rtx op;
00882 enum machine_mode mode ATTRIBUTE_UNUSED;
00883 {
00884 return GET_CODE (op) == MEM && CONSTANT_ADDRESS_P (XEXP (op, 0));
00885 }
00886
00887
00888
00889
00890 int
00891 psimode_truncation_operand (op, mode)
00892 rtx op;
00893 enum machine_mode mode;
00894 {
00895 return (general_operand (op, mode)
00896 && (GET_CODE (op) != MEM
00897 || memory_address_p (PSImode, XEXP (op, 0))));
00898 }
00899
00900
00901
00902
00903
00904 enum reg_class
00905 secondary_reload_class (class, mode, in, input)
00906 enum reg_class class;
00907 enum machine_mode mode;
00908 rtx in;
00909 int input;
00910 {
00911
00912
00913
00914 if (input
00915 && GET_CODE (in) == MEM
00916 && (mode == QImode)
00917 && class == ADDRESS_REGS)
00918 return DATA_REGS;
00919
00920
00921 if (! input
00922 && GET_CODE (in) == MEM
00923 && (mode != PSImode)
00924 && class == ADDRESS_REGS)
00925 return DATA_REGS;
00926
00927
00928 return NO_REGS;
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 int
00965 nshift_operator (x, mode)
00966 rtx x;
00967 enum machine_mode mode ATTRIBUTE_UNUSED;
00968 {
00969 switch (GET_CODE (x))
00970 {
00971 case ASHIFTRT:
00972 case LSHIFTRT:
00973 case ASHIFT:
00974 return 1;
00975
00976 default:
00977 return 0;
00978 }
00979 }
00980
00981
00982
00983
00984
00985 int
00986 expand_a_shift (mode, code, operands)
00987 enum machine_mode mode;
00988 int code;
00989 rtx operands[];
00990 {
00991 emit_move_insn (operands[0], operands[1]);
00992
00993
00994
00995
00996 emit_insn (gen_rtx_PARALLEL
00997 (VOIDmode,
00998 gen_rtvec (2,
00999 gen_rtx_SET (VOIDmode, operands[0],
01000 gen_rtx (code, mode,
01001 operands[0], operands[2])),
01002 gen_rtx_CLOBBER (VOIDmode,
01003 gen_rtx_SCRATCH (HImode)))));
01004
01005 return 1;
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 enum shift_alg
01017 {
01018 SHIFT_INLINE,
01019 SHIFT_SPECIAL,
01020 SHIFT_LOOP,
01021 SHIFT_MAX
01022 };
01023
01024
01025
01026 enum shift_type
01027 {
01028 SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT
01029 };
01030
01031
01032
01033 enum shift_mode
01034 {
01035 HIshift
01036 };
01037
01038
01039
01040
01041
01042 struct shift_insn
01043 {
01044 const char *assembler;
01045 int cc_valid;
01046 };
01047
01048
01049
01050
01051
01052
01053
01054 static const struct shift_insn shift_one[3][3] =
01055 {
01056 {
01057
01058 { "add\t%0,%0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
01059 },
01060
01061 {
01062 { "lsr\t%0", CC_NO_CARRY },
01063 },
01064
01065 {
01066 { "asr\t%0", CC_NO_CARRY },
01067 },
01068 };
01069
01070 static enum shift_alg get_shift_alg PARAMS ((enum shift_type,
01071 enum machine_mode, int,
01072 const char **, int *));
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 static enum shift_alg
01085 get_shift_alg (shift_type, mode, count, assembler_p, cc_valid_p)
01086 enum shift_type shift_type;
01087 enum machine_mode mode;
01088 int count;
01089 const char **assembler_p;
01090 int *cc_valid_p;
01091 {
01092
01093 enum shift_alg alg = SHIFT_LOOP;
01094 enum shift_mode shift_mode;
01095
01096
01097
01098
01099 if (count < 0 || count > GET_MODE_BITSIZE (mode))
01100 abort ();
01101
01102 switch (mode)
01103 {
01104 case HImode:
01105 shift_mode = HIshift;
01106 break;
01107 default:
01108 abort ();
01109 }
01110
01111
01112
01113 *assembler_p = shift_one[shift_type][shift_mode].assembler;
01114 *cc_valid_p = shift_one[shift_type][shift_mode].cc_valid;
01115
01116
01117
01118 switch (shift_mode)
01119 {
01120 case HIshift:
01121 if (count <= 4)
01122 return SHIFT_INLINE;
01123 else if (count < 15 && shift_type != SHIFT_ASHIFTRT)
01124 {
01125 switch (count)
01126 {
01127 case 5:
01128 if (shift_type == SHIFT_ASHIFT)
01129 *assembler_p = "mov 32,%4\n\tmul %4,%0";
01130 else if (shift_type == SHIFT_LSHIFTRT)
01131 *assembler_p
01132 = "sub %4,%4\n\tmov %4,mdr\n\tmov 32,%4\n\tdivu %4,%0";
01133 *cc_valid_p = CC_NO_CARRY;
01134 return SHIFT_SPECIAL;
01135 case 6:
01136 if (shift_type == SHIFT_ASHIFT)
01137 *assembler_p = "mov 64,%4\n\tmul %4,%0";
01138 else if (shift_type == SHIFT_LSHIFTRT)
01139 *assembler_p
01140 = "sub %4,%4\n\tmov %4,mdr\n\tmov 64,%4\n\tdivu %4,%0";
01141 *cc_valid_p = CC_NO_CARRY;
01142 return SHIFT_SPECIAL;
01143 case 7:
01144 if (shift_type == SHIFT_ASHIFT)
01145 *assembler_p = "mov 128,%4\n\tmul %4,%0";
01146 else if (shift_type == SHIFT_LSHIFTRT)
01147 *assembler_p
01148 = "sub %4,%4\n\tmov %4,mdr\n\tmov 128,%4\n\tdivu %4,%0";
01149 *cc_valid_p = CC_NO_CARRY;
01150 return SHIFT_SPECIAL;
01151 case 8:
01152 if (shift_type == SHIFT_ASHIFT)
01153 *assembler_p = "mov 256,%4\n\tmul %4,%0";
01154 else if (shift_type == SHIFT_LSHIFTRT)
01155 *assembler_p
01156 = "sub %4,%4\n\tmov %4,mdr\n\tmov 256,%4\n\tdivu %4,%0";
01157 *cc_valid_p = CC_NO_CARRY;
01158 return SHIFT_SPECIAL;
01159 case 9:
01160 if (shift_type == SHIFT_ASHIFT)
01161 *assembler_p = "mov 512,%4\n\tmul %4,%0";
01162 else if (shift_type == SHIFT_LSHIFTRT)
01163 *assembler_p
01164 = "sub %4,%4\n\tmov %4,mdr\n\tmov 512,%4\n\tdivu %4,%0";
01165 *cc_valid_p = CC_NO_CARRY;
01166 return SHIFT_SPECIAL;
01167 case 10:
01168 if (shift_type == SHIFT_ASHIFT)
01169 *assembler_p = "mov 1024,%4\n\tmul %4,%0";
01170 else if (shift_type == SHIFT_LSHIFTRT)
01171 *assembler_p
01172 = "sub %4,%4\n\tmov %4,mdr\n\tmov 1024,%4\n\tdivu %4,%0";
01173 *cc_valid_p = CC_NO_CARRY;
01174 return SHIFT_SPECIAL;
01175 case 11:
01176 if (shift_type == SHIFT_ASHIFT)
01177 *assembler_p = "mov 2048,%4\n\tmul %4,%0";
01178 else if (shift_type == SHIFT_LSHIFTRT)
01179 *assembler_p
01180 = "sub %4,%4\n\tmov %4,mdr\n\tmov 2048,%4\n\tdivu %4,%0";
01181 *cc_valid_p = CC_NO_CARRY;
01182 return SHIFT_SPECIAL;
01183 case 12:
01184 if (shift_type == SHIFT_ASHIFT)
01185 *assembler_p = "mov 4096,%4\n\tmul %4,%0";
01186 else if (shift_type == SHIFT_LSHIFTRT)
01187 *assembler_p
01188 = "sub %4,%4\n\tmov %4,mdr\n\tmov 4096,%4\n\tdivu %4,%0";
01189 *cc_valid_p = CC_NO_CARRY;
01190 return SHIFT_SPECIAL;
01191 case 13:
01192 if (shift_type == SHIFT_ASHIFT)
01193 *assembler_p = "mov 8192,%4\n\tmul %4,%0";
01194 else if (shift_type == SHIFT_LSHIFTRT)
01195 *assembler_p
01196 = "sub %4,%4\n\tmov %4,mdr\n\tmov 8192,%4\n\tdivu %4,%0";
01197 *cc_valid_p = CC_NO_CARRY;
01198 return SHIFT_SPECIAL;
01199 case 14:
01200 if (shift_type == SHIFT_ASHIFT)
01201 *assembler_p = "mov 16384,%4\n\tmul %4,%0";
01202 else if (shift_type == SHIFT_LSHIFTRT)
01203 *assembler_p
01204 = "sub %4,%4\n\tmov %4,mdr\n\tmov 16384,%4\n\tdivu %4,%0";
01205 *cc_valid_p = CC_NO_CARRY;
01206 return SHIFT_SPECIAL;
01207 }
01208 }
01209 else if (count == 15)
01210 {
01211 if (shift_type == SHIFT_ASHIFTRT)
01212 {
01213 *assembler_p = "add\t%0,%0\n\tsubc\t%0,%0\n";
01214 *cc_valid_p = CC_NO_CARRY;
01215 return SHIFT_SPECIAL;
01216 }
01217 if (shift_type == SHIFT_LSHIFTRT)
01218 {
01219 *assembler_p = "add\t%0,%0\n\tmov 0,%0\n\trol %0\n";
01220 *cc_valid_p = CC_NO_CARRY;
01221 return SHIFT_SPECIAL;
01222 }
01223 if (shift_type == SHIFT_ASHIFT)
01224 {
01225 *assembler_p = "ror\t%0\n\tmov 0,%0\n\tror %0\n";
01226 *cc_valid_p = CC_NO_CARRY;
01227 return SHIFT_SPECIAL;
01228 }
01229 }
01230 break;
01231
01232 default:
01233 abort ();
01234 }
01235
01236 return alg;
01237 }
01238
01239
01240
01241 const char *
01242 emit_a_shift (insn, operands)
01243 rtx insn ATTRIBUTE_UNUSED;
01244 rtx *operands;
01245 {
01246 static int loopend_lab;
01247 const char *assembler;
01248 int cc_valid;
01249 rtx shift = operands[3];
01250 enum machine_mode mode = GET_MODE (shift);
01251 enum rtx_code code = GET_CODE (shift);
01252 enum shift_type shift_type;
01253 enum shift_mode shift_mode;
01254
01255 loopend_lab++;
01256
01257 switch (mode)
01258 {
01259 case HImode:
01260 shift_mode = HIshift;
01261 break;
01262 default:
01263 abort ();
01264 }
01265
01266 switch (code)
01267 {
01268 case ASHIFTRT:
01269 shift_type = SHIFT_ASHIFTRT;
01270 break;
01271 case LSHIFTRT:
01272 shift_type = SHIFT_LSHIFTRT;
01273 break;
01274 case ASHIFT:
01275 shift_type = SHIFT_ASHIFT;
01276 break;
01277 default:
01278 abort ();
01279 }
01280
01281 if (GET_CODE (operands[2]) != CONST_INT)
01282 {
01283
01284 output_asm_insn ("mov %2,%4", operands);
01285 output_asm_insn ("cmp 0,%4", operands);
01286 fprintf (asm_out_file, "\tble .Lle%d\n", loopend_lab);
01287
01288
01289 get_shift_alg (shift_type, mode, 1, &assembler, &cc_valid);
01290 }
01291 else
01292 {
01293 int n = INTVAL (operands[2]);
01294 enum shift_alg alg;
01295
01296
01297 if (n < 0)
01298 n = 0;
01299
01300
01301
01302 else if (n > GET_MODE_BITSIZE (mode))
01303 n = GET_MODE_BITSIZE (mode);
01304
01305 alg = get_shift_alg (shift_type, mode, n, &assembler, &cc_valid);
01306
01307
01308 switch (alg)
01309 {
01310 case SHIFT_INLINE:
01311
01312 while (n > 0)
01313 {
01314 output_asm_insn (assembler, operands);
01315 n -= 1;
01316 }
01317
01318
01319 if (cc_valid)
01320 {
01321 cc_status.value1 = operands[0];
01322 cc_status.flags |= cc_valid;
01323 }
01324 return "";
01325
01326 case SHIFT_SPECIAL:
01327 output_asm_insn (assembler, operands);
01328
01329
01330 if (cc_valid)
01331 {
01332 cc_status.value1 = operands[0];
01333 cc_status.flags |= cc_valid;
01334 }
01335 return "";
01336 }
01337
01338 {
01339 fprintf (asm_out_file, "\tmov %d,%s\n", n,
01340 reg_names[REGNO (operands[4])]);
01341 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
01342 output_asm_insn (assembler, operands);
01343 output_asm_insn ("add -1,%4", operands);
01344 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
01345 return "";
01346 }
01347 }
01348
01349 fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
01350 output_asm_insn (assembler, operands);
01351 output_asm_insn ("add -1,%4", operands);
01352 fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
01353 fprintf (asm_out_file, ".Lle%d:\n", loopend_lab);
01354
01355 return "";
01356 }
01357
01358
01359
01360
01361 rtx
01362 function_arg (cum, mode, type, named)
01363 CUMULATIVE_ARGS *cum;
01364 enum machine_mode mode;
01365 tree type;
01366 int named;
01367 {
01368 rtx result = 0;
01369 int size, align;
01370
01371
01372 int nregs = 2;
01373
01374
01375 if (!named)
01376 return NULL_RTX;
01377
01378
01379
01380
01381 if (mode == BLKmode)
01382 size = int_size_in_bytes (type);
01383 else if (mode == PSImode)
01384 size = 2;
01385 else
01386 size = GET_MODE_SIZE (mode);
01387
01388
01389 align = size;
01390
01391 cum->nbytes = (cum->nbytes + 1) & ~1;
01392
01393
01394
01395 if (cum->nbytes + size > nregs * UNITS_PER_WORD)
01396 return 0;
01397
01398 switch (cum->nbytes / UNITS_PER_WORD)
01399 {
01400 case 0:
01401 result = gen_rtx_REG (mode, 0);
01402 break;
01403 case 1:
01404 result = gen_rtx_REG (mode, 1);
01405 break;
01406 default:
01407 result = 0;
01408 }
01409
01410 return result;
01411 }
01412
01413
01414
01415
01416 int
01417 function_arg_partial_nregs (cum, mode, type, named)
01418 CUMULATIVE_ARGS *cum;
01419 enum machine_mode mode;
01420 tree type;
01421 int named;
01422 {
01423 int size, align;
01424
01425
01426 int nregs = 2;
01427
01428 return 0;
01429
01430 if (!named)
01431 return 0;
01432
01433
01434 if (mode == BLKmode)
01435 size = int_size_in_bytes (type);
01436 else if (mode == PSImode)
01437 size = 2;
01438 else
01439 size = GET_MODE_SIZE (mode);
01440
01441
01442 align = size;
01443
01444 cum->nbytes = (cum->nbytes + 1) & ~1;
01445
01446
01447
01448 if (cum->nbytes > nregs * UNITS_PER_WORD)
01449 return 0;
01450
01451 if (cum->nbytes + size <= nregs * UNITS_PER_WORD)
01452 return 0;
01453
01454
01455
01456 if (type == NULL_TREE
01457 && cum->nbytes + size > nregs * UNITS_PER_WORD)
01458 return 0;
01459
01460 return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
01461 }
01462
01463 rtx
01464 mn10200_va_arg (valist, type)
01465 tree valist, type;
01466 {
01467 HOST_WIDE_INT align, rsize;
01468 tree t, ptr, pptr;
01469
01470
01471 align = PARM_BOUNDARY / BITS_PER_UNIT;
01472 rsize = (((int_size_in_bytes (type) + align - 1) / align) * align);
01473
01474 t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
01475 build_int_2 ((rsize > 8 ? 4 : rsize), 0));
01476 TREE_SIDE_EFFECTS (t) = 1;
01477
01478 ptr = build_pointer_type (type);
01479
01480
01481 if (rsize > 8)
01482 {
01483 pptr = build_pointer_type (ptr);
01484 t = build1 (NOP_EXPR, pptr, t);
01485 TREE_SIDE_EFFECTS (t) = 1;
01486
01487 t = build1 (INDIRECT_REF, ptr, t);
01488 TREE_SIDE_EFFECTS (t) = 1;
01489 }
01490 else
01491 {
01492 t = build1 (NOP_EXPR, ptr, t);
01493 TREE_SIDE_EFFECTS (t) = 1;
01494 }
01495
01496
01497 return force_reg (Pmode, expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL));
01498 }
01499
01500 const char *
01501 output_tst (operand, insn)
01502 rtx operand, insn;
01503 {
01504
01505 rtx temp;
01506 int past_call = 0;
01507
01508
01509 if (REGNO_REG_CLASS (REGNO (operand)) != ADDRESS_REGS)
01510 return "cmp 0,%0";
01511
01512
01513
01514
01515
01516
01517 if (zero_dreg || zero_areg)
01518 {
01519 rtx xoperands[2];
01520 xoperands[0] = operand;
01521 xoperands[1] = zero_dreg ? zero_dreg : zero_areg;
01522
01523 output_asm_insn ("cmp %1,%0", xoperands);
01524 return "";
01525 }
01526
01527
01528
01529 temp = PREV_INSN (insn);
01530 while (temp)
01531 {
01532 rtx set;
01533
01534
01535
01536
01537 if (GET_CODE (temp) == CODE_LABEL
01538 || GET_CODE (temp) == JUMP_INSN
01539 || GET_CODE (temp) == BARRIER)
01540 break;
01541
01542 if (GET_CODE (temp) == CALL_INSN)
01543 past_call = 1;
01544
01545 if (GET_CODE (temp) == NOTE)
01546 {
01547 temp = PREV_INSN (temp);
01548 continue;
01549 }
01550
01551
01552 set = single_set (temp);
01553 if (!set)
01554 {
01555 temp = PREV_INSN (temp);
01556 continue;
01557 }
01558
01559
01560
01561
01562 if (REG_P (SET_DEST (set))
01563 && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
01564 && !reg_set_between_p (SET_DEST (set), temp, insn)
01565 && (!past_call
01566 || !call_used_regs[REGNO (SET_DEST (set))]))
01567 {
01568 rtx xoperands[2];
01569 xoperands[0] = operand;
01570 xoperands[1] = SET_DEST (set);
01571
01572 output_asm_insn ("cmp %1,%0", xoperands);
01573 return "";
01574 }
01575 temp = PREV_INSN (temp);
01576 }
01577 return "cmp 0,%0";
01578 }
01579
01580
01581
01582
01583
01584
01585 int
01586 extendpsi_operand (op, mode)
01587 rtx op;
01588 enum machine_mode mode;
01589 {
01590 return (general_operand (op, mode)
01591 || (GET_CODE (op) == PLUS
01592 && XEXP (op, 0) == stack_pointer_rtx
01593 && general_operand (XEXP (op, 1), VOIDmode)));
01594 }