00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "tree.h"
00025 #include "rtl.h"
00026 #include "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "real.h"
00029 #include "insn-config.h"
00030 #include "conditions.h"
00031 #include "insn-attr.h"
00032 #include "output.h"
00033 #include "function.h"
00034 #include "expr.h"
00035 #include "tm_p.h"
00036 #include "target.h"
00037 #include "target-def.h"
00038
00039
00040
00041 char regno_ok_for_index_p_base[1 + LAST_VIRTUAL_REGISTER + 1];
00042 enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
00043 enum reg_class reg_class_from_letter[256];
00044
00045
00046
00047 int target_cpu;
00048
00049
00050
00051
00052 int current_section_is_text;
00053
00054
00055
00056 static rtx cmp_operand0, cmp_operand1;
00057 static char cmp_modech;
00058
00059
00060
00061 #if 0
00062 static rtx frame_argblock;
00063 static int frame_argblock_size;
00064 static rtx convert_arg_pushes ();
00065 #endif
00066 static void expand_movstr_call PARAMS ((rtx *));
00067 static void convex_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00068 static void convex_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00069 static int convex_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00070
00071
00072 #undef TARGET_ASM_BYTE_OP
00073 #define TARGET_ASM_BYTE_OP "\tds.b\t"
00074 #undef TARGET_ASM_ALIGNED_HI_OP
00075 #define TARGET_ASM_ALIGNED_HI_OP "\tds.h\t"
00076 #undef TARGET_ASM_ALIGNED_SI_OP
00077 #define TARGET_ASM_ALIGNED_SI_OP "\tds.w\t"
00078
00079 #undef TARGET_ASM_FUNCTION_PROLOGUE
00080 #define TARGET_ASM_FUNCTION_PROLOGUE convex_output_function_prologue
00081 #undef TARGET_ASM_FUNCTION_EPILOGUE
00082 #define TARGET_ASM_FUNCTION_EPILOGUE convex_output_function_epilogue
00083 #undef TARGET_SCHED_ADJUST_COST
00084 #define TARGET_SCHED_ADJUST_COST convex_adjust_cost
00085
00086 struct gcc_target targetm = TARGET_INITIALIZER;
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static void
00098 convex_output_function_prologue (file, size)
00099 FILE *file;
00100 HOST_WIDE_INT size;
00101 {
00102 size = ((size) + 7) & -8;
00103 if (size)
00104 {
00105 fprintf (file, "\tsub.w #");
00106 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
00107 fprintf (file, ",sp\n");
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 static void
00120 convex_output_function_epilogue (file, size)
00121 FILE *file;
00122 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
00123 {
00124
00125 fprintf (file, "\tds.h 0\n");
00126 }
00127
00128
00129 static int
00130 convex_adjust_cost (insn, link, dep, cost)
00131 rtx insn;
00132 rtx link;
00133 rtx dep;
00134 int cost;
00135 {
00136
00137 if (REG_NOTE_KIND (link) != 0)
00138 cost = 0;
00139
00140 else if (TARGET_C38
00141 && GET_CODE (PATTERN (insn)) == SET
00142 && GET_CODE (PATTERN (dep)) == SET)
00143 {
00144 enum attr_type insn_type = get_attr_type (insn);
00145 enum attr_type dep_type = get_attr_type (dep);
00146
00147 if (insn_type == TYPE_MLDW || insn_type == TYPE_MLDL
00148 || (insn_type == TYPE_MST
00149 && reg_mentioned_p (SET_DEST (PATTERN (dep)),
00150 SET_SRC (PATTERN (insn)))))
00151 cost += 1;
00152
00153 if (dep_type == TYPE_ALU
00154 && insn_type != TYPE_ALU
00155 && ! (insn_type == TYPE_MST
00156 && SET_DEST (PATTERN (dep)) == SET_SRC (PATTERN (insn))))
00157 cost += 1;
00158 }
00159
00160 return cost;
00161 }
00162
00163
00164
00165
00166
00167 void
00168 init_convex ()
00169 {
00170 int regno;
00171
00172
00173 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00174 if (A_REGNO_P (regno))
00175 {
00176 regno_ok_for_index_p[regno] = 1;
00177 regno_reg_class[regno] = INDEX_REGS;
00178 }
00179 else
00180 {
00181 regno_ok_for_index_p[regno] = 0;
00182 regno_reg_class[regno] = S_REGS;
00183 }
00184
00185
00186 regno_ok_for_index_p[STACK_POINTER_REGNUM] = 0;
00187 regno_reg_class[STACK_POINTER_REGNUM] = SP_REGS;
00188
00189
00190 regno_ok_for_index_p[VIRTUAL_INCOMING_ARGS_REGNUM] = 1;
00191 regno_ok_for_index_p[VIRTUAL_STACK_VARS_REGNUM] = 1;
00192 regno_ok_for_index_p[VIRTUAL_STACK_DYNAMIC_REGNUM] = 0;
00193 regno_ok_for_index_p[VIRTUAL_OUTGOING_ARGS_REGNUM] = 0;
00194
00195
00196 regno_ok_for_index_p[-1] = 0;
00197
00198
00199 reg_class_from_letter['a'] = A_REGS;
00200 reg_class_from_letter['A'] = INDEX_REGS;
00201 reg_class_from_letter['d'] = S_REGS;
00202
00203
00204 psw_disable_float ();
00205 }
00206
00207 void
00208 psw_disable_float ()
00209 {
00210 #if __convex__ && __GNUC__
00211 register int *p;
00212 asm ("mov fp,%0" : "=a" (p));
00213 while (p)
00214 {
00215 p[1] &= ~0x1000c400;
00216 p = (int *) p[2];
00217 }
00218 #endif
00219 }
00220
00221
00222
00223
00224 const char *
00225 output_cmp (operand0, operand1, modech)
00226 rtx operand0, operand1;
00227 int modech;
00228 {
00229 cmp_operand0 = operand0;
00230 cmp_operand1 = operand1;
00231 cmp_modech = modech;
00232 return "";
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 const char *
00245 output_condjump (label, cond, jbr_sense)
00246 rtx label;
00247 const char *cond;
00248 int jbr_sense;
00249 {
00250 rtx operands[3];
00251 char cmp_op[4];
00252 char buf[80];
00253 char jbr_regch;
00254
00255 strcpy (cmp_op, cond);
00256
00257
00258
00259
00260
00261
00262 if (cmp_modech == 'B' || cmp_modech == 'L')
00263 {
00264 cmp_modech = cmp_modech - 'A' + 'a';
00265 strcpy (cmp_op, "neg");
00266 }
00267
00268
00269
00270
00271
00272 else if (cmp_modech == 'W' || cmp_modech == 'H')
00273 {
00274 if (! strcmp (cmp_op, "eq") && cmp_operand1 == constm1_rtx)
00275 jbr_sense ^= 't' ^ 'f';
00276 else if (! strcmp (cmp_op, "lt") && cmp_operand1 == const0_rtx)
00277 ;
00278 else
00279 cmp_modech = cmp_modech - 'A' + 'a';
00280 }
00281
00282
00283
00284
00285
00286 if (! REG_P (cmp_operand1))
00287 {
00288 operands[0] = cmp_operand1;
00289 operands[1] = cmp_operand0;
00290 if (cmp_op[0] == 'l')
00291 {
00292 cmp_op[1] ^= 'e' ^ 't';
00293 jbr_sense ^= 't' ^ 'f';
00294 }
00295 }
00296 else
00297 {
00298 operands[0] = cmp_operand0;
00299 operands[1] = cmp_operand1;
00300 }
00301
00302 operands[2] = label;
00303
00304 if (S_REG_P (operands[1]))
00305 jbr_regch = 's';
00306 else if (A_REG_P (operands[1]))
00307 jbr_regch = 'a';
00308 else
00309 abort ();
00310
00311 if (cmp_modech == 'W' || cmp_modech == 'H')
00312 sprintf (buf, "jbr%c.%c %%l2", jbr_regch, jbr_sense);
00313 else
00314 sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2",
00315 cmp_op, cmp_modech, jbr_regch, jbr_sense);
00316 output_asm_insn (buf, operands);
00317 return "";
00318 }
00319
00320
00321
00322
00323
00324
00325 int
00326 nonmemory_cmpsf_operand (op, mode)
00327 rtx op;
00328 enum machine_mode mode;
00329 {
00330 #if _IEEE_FLOAT_
00331 if (op == CONST0_RTX (SFmode))
00332 return 0;
00333 #endif
00334
00335 return nonmemory_operand (op, mode);
00336 }
00337
00338
00339
00340
00341 rtx
00342 simplify_for_convex (x)
00343 rtx x;
00344 {
00345 switch (GET_CODE (x))
00346 {
00347 case MINUS:
00348 if (GET_CODE (XEXP (x, 1)) == CONST_INT
00349 && INTVAL (XEXP (x, 1)) < 0)
00350 {
00351 PUT_CODE (x, PLUS);
00352 XEXP (x, 1) = GEN_INT (- INTVAL (XEXP (x, 1)));
00353 }
00354 break;
00355
00356 case CONST:
00357 return simplify_for_convex (XEXP (x, 0));
00358 default:
00359 break;
00360 }
00361
00362 return x;
00363 }
00364
00365
00366
00367 int
00368 const_double_high_int (x)
00369 rtx x;
00370 {
00371 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
00372 return CONST_DOUBLE_LOW (x);
00373 else
00374 return CONST_DOUBLE_HIGH (x);
00375 }
00376
00377 int
00378 const_double_low_int (x)
00379 rtx x;
00380 {
00381 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
00382 return CONST_DOUBLE_HIGH (x);
00383 else
00384 return CONST_DOUBLE_LOW (x);
00385 }
00386
00387
00388
00389 void
00390 expand_movstr (operands)
00391 rtx *operands;
00392 {
00393 rtx dest = operands[0];
00394 rtx src = operands[1];
00395 int align = INTVAL (operands[3]);
00396 int nregs, maxsize;
00397 unsigned len;
00398 enum machine_mode mode;
00399 rtx reg, load, store, prev_store, prev_store_2;
00400 int size;
00401
00402
00403
00404
00405
00406 if (TARGET_C1)
00407 {
00408
00409 nregs = 3, maxsize = 8;
00410 }
00411 else if (TARGET_C2)
00412 {
00413
00414 if (align >= 4)
00415 nregs = 2, maxsize = 8;
00416 else
00417 nregs = 2, maxsize = 4;
00418 }
00419 else if (TARGET_C34)
00420 {
00421
00422 nregs = 3, maxsize = align;
00423 }
00424 else if (TARGET_C38)
00425 {
00426
00427 if (align >= 4)
00428 nregs = 2, maxsize = 8;
00429 else
00430 nregs = 3, maxsize = 8;
00431 }
00432 else
00433 abort ();
00434
00435
00436
00437
00438 if (GET_CODE (operands[2]) != CONST_INT
00439 || (len = INTVAL (operands[2])) > (unsigned) 32 * maxsize)
00440 {
00441 expand_movstr_call (operands);
00442 return;
00443 }
00444
00445 reg = 0;
00446 prev_store = prev_store_2 = 0;
00447
00448 while (len > 0)
00449 {
00450 if (len >= 8 && maxsize >= 8)
00451 mode = DImode;
00452 else if (len >= 4 && maxsize >= 4)
00453 mode = SImode;
00454 else if (len >= 2 && maxsize >= 2)
00455 mode = HImode;
00456 else
00457 mode = QImode;
00458
00459
00460 if (! reg || GET_MODE (reg) != mode)
00461 reg = gen_reg_rtx (mode);
00462
00463
00464 if (GET_MODE (src) != mode)
00465 {
00466 src = adjust_address (src, mode, 0);
00467 dest = adjust_address (dest, mode, 0);
00468 }
00469
00470
00471 load = gen_rtx_SET (VOIDmode, reg, src);
00472 store = gen_rtx_SET (VOIDmode, dest, reg);
00473
00474
00475
00476 emit_insn (load);
00477 if (prev_store)
00478 {
00479 reg = SET_SRC (prev_store);
00480 emit_insn (prev_store);
00481 }
00482 else
00483 reg = 0;
00484
00485
00486 if (nregs == 2)
00487 prev_store = store;
00488 else
00489 prev_store = prev_store_2, prev_store_2 = store;
00490
00491
00492 size = GET_MODE_SIZE (mode);
00493 src = adjust_address (src, mode, size);
00494 dest = adjust_address (dest, mode, size);
00495 len -= size;
00496 }
00497
00498
00499 if (prev_store)
00500 emit_insn (prev_store);
00501 if (prev_store_2)
00502 emit_insn (prev_store_2);
00503 }
00504
00505 static void
00506 expand_movstr_call (operands)
00507 rtx *operands;
00508 {
00509 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
00510 VOIDmode, 3,
00511 XEXP (operands[0], 0), Pmode,
00512 XEXP (operands[1], 0), Pmode,
00513 convert_to_mode (TYPE_MODE (sizetype), operands[2],
00514 TREE_UNSIGNED (sizetype)),
00515 TYPE_MODE (sizetype));
00516 }
00517
00518 #if _IEEE_FLOAT_
00519 #define MAX_FLOAT 3.4028234663852886e+38
00520 #define MIN_FLOAT 1.1754943508222875e-38
00521 #else
00522 #define MAX_FLOAT 1.7014117331926443e+38
00523 #define MIN_FLOAT 2.9387358770557188e-39
00524 #endif
00525
00526 int
00527 check_float_value (mode, dp, overflow)
00528 enum machine_mode mode;
00529 REAL_VALUE_TYPE *dp;
00530 int overflow;
00531 {
00532 REAL_VALUE_TYPE d = *dp;
00533
00534 if (overflow)
00535 {
00536 *dp = MAX_FLOAT;
00537 return 1;
00538 }
00539
00540 if (mode == SFmode)
00541 {
00542 if (d > MAX_FLOAT)
00543 {
00544 *dp = MAX_FLOAT;
00545 return 1;
00546 }
00547 else if (d < -MAX_FLOAT)
00548 {
00549 *dp = -MAX_FLOAT;
00550 return 1;
00551 }
00552 else if ((d > 0 && d < MIN_FLOAT) || (d < 0 && d > -MIN_FLOAT))
00553 {
00554 *dp = 0.0;
00555 return 1;
00556 }
00557 }
00558
00559 return 0;
00560 }
00561
00562
00563
00564
00565
00566 void
00567 asm_declare_function_name (file, name, decl)
00568 FILE *file;
00569 const char *name;
00570 tree decl;
00571 {
00572 int nargs = list_length (DECL_ARGUMENTS (decl));
00573
00574 const char *p;
00575 char c;
00576 static char vers[4];
00577 int i;
00578
00579 p = version_string;
00580 for (i = 0; i < 3; ) {
00581 c = *p;
00582 if (ISDIGIT (c))
00583 vers[i++] = c;
00584 if (c == 0 || c == ' ')
00585 vers[i++] = '0';
00586 else
00587 p++;
00588 }
00589 fprintf (file, "\tds.b \"g%s\"\n", vers);
00590
00591 if (nargs < 100)
00592 fprintf (file, "\tds.b \"+%02d\\0\"\n", nargs);
00593 else
00594 fprintf (file, "\tds.b \"+00\\0\"\n");
00595
00596 ASM_OUTPUT_LABEL (file, name);
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 void
00609 print_operand (file, x, code)
00610 FILE *file;
00611 rtx x;
00612 int code;
00613 {
00614 long u[2];
00615 REAL_VALUE_TYPE d;
00616
00617 switch (GET_CODE (x))
00618 {
00619 case REG:
00620 fprintf (file, "%s", reg_names[REGNO (x)]);
00621 break;
00622
00623 case MEM:
00624 output_address (XEXP (x, 0));
00625 break;
00626
00627 case CONST_DOUBLE:
00628 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
00629 switch (GET_MODE (x)) {
00630 case DFmode:
00631 #if 0
00632 REAL_VALUE_TO_TARGET_DOUBLE (d, u);
00633 #else
00634 {
00635 union { double d; int i[2]; } t;
00636 t.d = d;
00637 u[0] = t.i[0];
00638 u[1] = t.i[1];
00639 }
00640 #endif
00641 if (code == 'u')
00642 fprintf (file, "#%#lx", u[0]);
00643 else if (code == 'v')
00644 fprintf (file, "#%#lx", u[1]);
00645 else
00646 outfloat (file, d, "%.17e", "#", "");
00647 break;
00648 case SFmode:
00649 outfloat (file, d, "%.9e", "#", "");
00650 break;
00651 default:
00652 if (code == 'u')
00653 {
00654 fprintf (file, "#");
00655 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_HIGH (x));
00656 }
00657 else
00658 {
00659 fprintf (file, "#");
00660 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
00661 }
00662 }
00663 break;
00664
00665 default:
00666 if (code == 'z')
00667 {
00668 if (GET_CODE (x) != CONST_INT)
00669 abort ();
00670 fprintf (file, "#%d", 1 << INTVAL (x));
00671 }
00672 else
00673 {
00674 putc ('#', file);
00675 output_addr_const (file, x);
00676 }
00677 }
00678 }
00679
00680
00681
00682 void
00683 print_operand_address (file, addr)
00684 FILE *file;
00685 rtx addr;
00686 {
00687 rtx index = 0;
00688 rtx offset = 0;
00689
00690 if (GET_CODE (addr) == MEM)
00691 {
00692 fprintf (file, "@");
00693 addr = XEXP (addr, 0);
00694 }
00695
00696 switch (GET_CODE (addr))
00697 {
00698 case REG:
00699 index = addr;
00700 break;
00701
00702 case PLUS:
00703 index = XEXP (addr, 0);
00704 if (REG_P (index))
00705 offset = XEXP (addr, 1);
00706 else
00707 {
00708 offset = XEXP (addr, 0);
00709 index = XEXP (addr, 1);
00710 if (! REG_P (index))
00711 abort ();
00712 }
00713 break;
00714
00715 default:
00716 offset = addr;
00717 break;
00718 }
00719
00720 if (offset)
00721 output_addr_const (file, offset);
00722
00723 if (index)
00724 fprintf (file, "(%s)", reg_names[REGNO (index)]);
00725 }
00726
00727
00728
00729
00730 void
00731 outfloat (file, value, fmt, pfx, sfx)
00732 FILE *file;
00733 REAL_VALUE_TYPE value;
00734 const char *fmt, *pfx, *sfx;
00735 {
00736 char buf[64];
00737 fputs (pfx, file);
00738 REAL_VALUE_TO_DECIMAL (value, fmt, buf);
00739 fputs (buf, file);
00740 fputs (sfx, file);
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750 void
00751 replace_arg_pushes ()
00752 {
00753
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 const char *
00765 output_call (insn, operands)
00766 rtx insn ATTRIBUTE_UNUSED, *operands;
00767 {
00768 if (operands[4] == stack_pointer_rtx)
00769 output_asm_insn ("mov sp,ap", operands);
00770 else
00771 abort ();
00772
00773 if (TARGET_ARGCOUNT)
00774 output_asm_insn ("pshea %a2", operands);
00775
00776 output_asm_insn ("calls %0", operands);
00777
00778 output_asm_insn ("ld.w 12(fp),ap", operands);
00779
00780 if (operands[4] == stack_pointer_rtx && operands[3] != const0_rtx)
00781 output_asm_insn ("add.w %3,sp", operands);
00782
00783 return "";
00784 }
00785
00786
00787
00788
00789 void
00790 emit_ap_optimizations ()
00791 {
00792
00793 }
00794