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 "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "real.h"
00029 #include "insn-config.h"
00030 #include "conditions.h"
00031 #include "output.h"
00032 #include "insn-attr.h"
00033 #include "tree.h"
00034 #include "expr.h"
00035 #include "optabs.h"
00036 #include "libfuncs.h"
00037 #include "c-tree.h"
00038 #include "function.h"
00039 #include "flags.h"
00040 #include "recog.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044
00045 static void clipper_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00046 static void clipper_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00047 static void clix_asm_out_constructor PARAMS ((rtx, int));
00048 static void clix_asm_out_destructor PARAMS ((rtx, int));
00049
00050 extern char regs_ever_live[];
00051
00052 extern int frame_pointer_needed;
00053
00054 static int frame_size;
00055
00056
00057 #undef TARGET_ASM_ALIGNED_HI_OP
00058 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00059
00060 #undef TARGET_ASM_FUNCTION_PROLOGUE
00061 #define TARGET_ASM_FUNCTION_PROLOGUE clipper_output_function_prologue
00062 #undef TARGET_ASM_FUNCTION_EPILOGUE
00063 #define TARGET_ASM_FUNCTION_EPILOGUE clipper_output_function_epilogue
00064
00065 struct gcc_target targetm = TARGET_INITIALIZER;
00066
00067
00068
00069
00070 int
00071 clipper_frame_size (lsize)
00072 int lsize;
00073 {
00074 int i, size;
00075 int save_size;
00076 save_size = 0;
00077
00078 for (i = 16; i < 32; i++)
00079 if (regs_ever_live[i] && !call_used_regs[i])
00080 save_size += 8;
00081
00082 for (i = 0; i < 16; i++)
00083 if (regs_ever_live[i] && !call_used_regs[i])
00084 save_size += 4;
00085
00086 size = lsize + save_size;
00087
00088 size = (size + 7) & ~7;
00089 return size;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 static void
00102 clipper_output_function_prologue (file, lsize)
00103 FILE *file;
00104 HOST_WIDE_INT lsize;
00105 {
00106 int i, offset;
00107 int size;
00108
00109 frame_size = size = clipper_frame_size (lsize);
00110
00111 if (frame_pointer_needed)
00112 {
00113 fputs ("\tpushw fp,sp\n", file);
00114 fputs ("\tmovw sp,fp\n", file);
00115 }
00116 else if (size != 0 || current_function_args_size != 0)
00117 {
00118 size += 4;
00119 frame_size = size;
00120 }
00121
00122 if (size)
00123 {
00124 if (size < 16)
00125 fprintf (file, "\tsubq $%d,sp\n", size);
00126 else
00127 fprintf (file, "\tsubi $%d,sp\n", size);
00128
00129
00130
00131
00132 offset = 0;
00133 for (i = 16; i < 32; i++)
00134 if (regs_ever_live[i] && !call_used_regs[i])
00135 {
00136 if (offset == 0)
00137 fprintf (file, "\tstord f%d,(sp)\n", i-16);
00138 else
00139 fprintf (file, "\tstord f%d,%d(sp)\n", i-16, offset);
00140 offset += 8;
00141 }
00142
00143 for (i = 0; i < 16; i++)
00144 if (regs_ever_live[i] && !call_used_regs[i])
00145 {
00146 if (offset == 0)
00147 fprintf (file, "\tstorw r%d,(sp)\n", i);
00148 else
00149 fprintf (file, "\tstorw r%d,%d(sp)\n", i, offset);
00150 offset += 4;
00151 }
00152 }
00153 }
00154
00155 static void
00156 clipper_output_function_epilogue (file, size)
00157 FILE *file;
00158 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
00159 {
00160 int i, offset;
00161
00162 if (frame_pointer_needed)
00163 {
00164 offset = -frame_size;
00165
00166 for (i = 16; i < 32; i++)
00167 if (regs_ever_live[i] && !call_used_regs[i])
00168 {
00169 fprintf (file, "\tloadd %d(fp),f%d\n", offset, i-16);
00170 offset += 8;
00171 }
00172
00173 for (i = 0; i < 16; i++)
00174 if (regs_ever_live[i] && !call_used_regs[i])
00175 {
00176 fprintf (file, "\tloadw %d(fp),r%d\n", offset, i);
00177 offset += 4;
00178 }
00179
00180 fputs ("\tmovw fp,sp\n\tpopw sp,fp\n\tret sp\n",
00181 file);
00182 }
00183
00184 else
00185 {
00186 offset = 0;
00187
00188 for (i = 16; i < 32; i++)
00189 if (regs_ever_live[i] && !call_used_regs[i])
00190 {
00191 if (offset == 0)
00192 fprintf (file, "\tloadd (sp),f%d\n", i-16);
00193 else
00194 fprintf (file, "\tloadd %d(sp),f%d\n", offset, i-16);
00195 offset += 8;
00196 }
00197
00198 for (i = 0; i < 16; i++)
00199 if (regs_ever_live[i] && !call_used_regs[i])
00200 {
00201 if (offset == 0)
00202 fprintf (file, "\tloadw (sp),r%d\n", i);
00203 else
00204 fprintf (file, "\tloadw %d(sp),r%d\n", offset, i);
00205 offset += 4;
00206 }
00207
00208 if (frame_size > 0)
00209 {
00210 if (frame_size < 16)
00211 fprintf (file, "\taddq $%d,sp\n", frame_size);
00212 else
00213 fprintf (file, "\taddi $%d,sp\n", frame_size);
00214 }
00215
00216 fputs ("\tret sp\n", file);
00217 }
00218 }
00219
00220
00221
00222
00223
00224
00225 void
00226 clipper_movstr (operands)
00227 rtx *operands;
00228 {
00229 rtx dst,src,cnt,tmp,top,bottom=NULL_RTX,xops[3];
00230 int align;
00231 int fixed;
00232
00233 extern FILE *asm_out_file;
00234
00235 dst = operands[0];
00236 src = operands[1];
00237
00238 align = INTVAL (operands[3]);
00239 tmp = operands[4];
00240 cnt = operands[5];
00241
00242 if (GET_CODE (operands[2]) == CONST_INT)
00243 {
00244 if ((fixed = INTVAL (operands[2])) <= 0)
00245 abort ();
00246
00247 if (fixed <16)
00248 output_asm_insn ("loadq %2,%5", operands);
00249 else
00250 output_asm_insn ("loadi %2,%5", operands);
00251 }
00252 else
00253 {
00254 fixed = 0;
00255 bottom = (rtx)gen_label_rtx ();
00256 xops[0] = cnt; xops[1] = bottom;
00257 output_asm_insn ("movw %2,%5", operands);
00258 output_asm_insn ("brle %l1", xops);
00259 }
00260
00261
00262 top = (rtx)gen_label_rtx ();
00263 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (top));
00264
00265
00266 xops[0] = src; xops[1] = tmp; xops[2] = dst;
00267
00268 if (fixed && (align & 0x3) == 0)
00269 {
00270 if (fixed >= 4)
00271 {
00272 rtx xops1[2];
00273 output_asm_insn(
00274 "loadw %a0,%1\n\taddq $4,%0\n\tstorw %1,%a2\n\taddq $4,%2",
00275 xops);
00276
00277 xops1[0] = cnt; xops1[1] = top;
00278 output_asm_insn ("subq $4,%0\n\tbrgt %l1", xops1);
00279 }
00280
00281 if (fixed & 0x2)
00282 {
00283 output_asm_insn ("loadh %a0,%1\n\tstorh %1,%a2", xops);
00284 if (fixed & 0x1)
00285 output_asm_insn ("loadb 2%a0,%1\n\tstorb %1,2%a2", xops);
00286 }
00287 else
00288 if (fixed & 0x1)
00289 output_asm_insn ("loadb %a0,%1\n\tstorb %1,%a2", xops);
00290 }
00291 else
00292 {
00293 output_asm_insn(
00294 "loadb %a0,%1\n\taddq $1,%0\n\tstorb %1,%a2\n\taddq $1,%2",
00295 xops);
00296
00297 xops[0] = cnt; xops[1] = top;
00298 output_asm_insn ("subq $1,%0\n\tbrgt %l1", xops);
00299 }
00300
00301 if (fixed == 0)
00302 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (bottom));
00303 }
00304
00305
00306 void
00307 print_operand_address (file, addr)
00308 FILE *file;
00309 register rtx addr;
00310 {
00311 rtx op0,op1;
00312
00313 switch (GET_CODE (addr))
00314 {
00315 case REG:
00316 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
00317 break;
00318
00319 case PLUS:
00320
00321
00322 op0 = XEXP (addr, 0);
00323 op1 = XEXP (addr, 1);
00324
00325 if (GET_CODE (op0) == REG && GET_CODE (op1) == REG)
00326 {
00327 fprintf (file, "[%s](%s)",
00328 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
00329 break;
00330 }
00331
00332 if (GET_CODE (op0) == REG && CONSTANT_ADDRESS_P (op1))
00333 {
00334 output_addr_const (file, op1);
00335 fprintf (file, "(%s)", reg_names[REGNO (op0)]);
00336 break;
00337 }
00338
00339 if (GET_CODE (op1) == REG && CONSTANT_ADDRESS_P (op0))
00340 {
00341 output_addr_const (file, op0);
00342 fprintf (file, "(%s)", reg_names[REGNO (op1)]);
00343 break;
00344 }
00345 abort ();
00346
00347 default:
00348 output_addr_const (file, addr);
00349 }
00350 }
00351
00352
00353 const char *
00354 rev_cond_name (op)
00355 rtx op;
00356 {
00357 switch (GET_CODE (op))
00358 {
00359 case EQ:
00360 return "ne";
00361 case NE:
00362 return "eq";
00363 case LT:
00364 return "ge";
00365 case LE:
00366 return "gt";
00367 case GT:
00368 return "le";
00369 case GE:
00370 return "lt";
00371 case LTU:
00372 return "geu";
00373 case LEU:
00374 return "gtu";
00375 case GTU:
00376 return "leu";
00377 case GEU:
00378 return "ltu";
00379
00380 default:
00381 abort ();
00382 }
00383 }
00384
00385
00386
00387
00388
00389 struct rtx_def *
00390 clipper_builtin_saveregs ()
00391 {
00392 rtx block, addr, r0_addr, r1_addr, f0_addr, f1_addr, mem;
00393 int set = get_varargs_alias_set ();
00394
00395
00396
00397 block = assign_stack_local (BLKmode, 6 * UNITS_PER_WORD, 2 * BITS_PER_WORD);
00398
00399 RTX_UNCHANGING_P (block) = 1;
00400 RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
00401
00402 addr = XEXP (block, 0);
00403
00404 r0_addr = addr;
00405 r1_addr = plus_constant (addr, 4);
00406 f0_addr = plus_constant (addr, 8);
00407 f1_addr = plus_constant (addr, 16);
00408
00409
00410
00411 mem = gen_rtx_MEM (SImode, r0_addr);
00412 set_mem_alias_set (mem, set);
00413 emit_move_insn (mem, gen_rtx_REG (SImode, 0));
00414
00415 mem = gen_rtx_MEM (SImode, r1_addr);
00416 set_mem_alias_set (mem, set);
00417 emit_move_insn (mem, gen_rtx_REG (SImode, 1));
00418
00419
00420
00421 mem = gen_rtx_MEM (DFmode, f0_addr);
00422 set_mem_alias_set (mem, set);
00423 emit_move_insn (mem, gen_rtx_REG (DFmode, 16));
00424
00425 mem = gen_rtx_MEM (DFmode, f1_addr);
00426 set_mem_alias_set (mem, set);
00427 emit_move_insn (mem, gen_rtx_REG (DFmode, 17));
00428
00429 return addr;
00430 }
00431
00432 tree
00433 clipper_build_va_list ()
00434 {
00435 tree record, ap, reg, num;
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 record = make_node (RECORD_TYPE);
00447
00448 num = build_decl (FIELD_DECL, get_identifier ("__va_num"),
00449 integer_type_node);
00450 DECL_FIELD_CONTEXT (num) = record;
00451
00452 reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
00453 build_array_type (ptr_type_node,
00454 build_index_type (build_int_2 (3, 0))));
00455 DECL_FIELD_CONTEXT (reg) = record;
00456 TREE_CHAIN (reg) = num;
00457
00458 ap = build_decl (FIELD_DECL, get_identifier ("__va_ap"),
00459 integer_type_node);
00460 DECL_FIELD_CONTEXT (ap) = record;
00461 TREE_CHAIN (ap) = reg;
00462
00463 TYPE_FIELDS (record) = ap;
00464 layout_type (record);
00465
00466 return record;
00467 }
00468
00469 void
00470 clipper_va_start (stdarg_p, valist, nextarg)
00471 int stdarg_p;
00472 tree valist;
00473 rtx nextarg ATTRIBUTE_UNUSED;
00474 {
00475 tree ap_field, reg_field, num_field;
00476 tree t, u, save_area;
00477
00478 ap_field = TYPE_FIELDS (TREE_TYPE (valist));
00479 reg_field = TREE_CHAIN (ap_field);
00480 num_field = TREE_CHAIN (reg_field);
00481
00482 ap_field = build (COMPONENT_REF, TREE_TYPE (ap_field), valist, ap_field);
00483 reg_field = build (COMPONENT_REF, TREE_TYPE (reg_field), valist, reg_field);
00484 num_field = build (COMPONENT_REF, TREE_TYPE (num_field), valist, num_field);
00485
00486
00487
00488 save_area = make_tree (integer_type_node, expand_builtin_saveregs ());
00489
00490
00491
00492 t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
00493 if (stdarg_p && current_function_args_info.size != 0)
00494 t = build (PLUS_EXPR, ptr_type_node, t,
00495 build_int_2 (current_function_args_info.size, 0));
00496 t = build (MODIFY_EXPR, TREE_TYPE (ap_field), ap_field, t);
00497 TREE_SIDE_EFFECTS (t) = 1;
00498 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00499
00500
00501
00502 t = build1 (NOP_EXPR, ptr_type_node, save_area);
00503 u = build (ARRAY_REF, ptr_type_node, reg_field, build_int_2 (0, 0));
00504 t = build (MODIFY_EXPR, ptr_type_node, u, t);
00505 TREE_SIDE_EFFECTS (t) = 1;
00506 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00507
00508 t = fold (build (PLUS_EXPR, integer_type_node, save_area,
00509 build_int_2 (8, 0)));
00510 t = build1 (NOP_EXPR, ptr_type_node, save_area);
00511 u = build (ARRAY_REF, ptr_type_node, reg_field, build_int_2 (1, 0));
00512 t = build (MODIFY_EXPR, ptr_type_node, u, t);
00513 TREE_SIDE_EFFECTS (t) = 1;
00514 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00515
00516 t = fold (build (PLUS_EXPR, integer_type_node, save_area,
00517 build_int_2 (4, 0)));
00518 t = build1 (NOP_EXPR, ptr_type_node, save_area);
00519 u = build (ARRAY_REF, ptr_type_node, reg_field, build_int_2 (2, 0));
00520 t = build (MODIFY_EXPR, ptr_type_node, u, t);
00521 TREE_SIDE_EFFECTS (t) = 1;
00522 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00523
00524 t = fold (build (PLUS_EXPR, integer_type_node, save_area,
00525 build_int_2 (16, 0)));
00526 t = build1 (NOP_EXPR, ptr_type_node, save_area);
00527 u = build (ARRAY_REF, ptr_type_node, reg_field, build_int_2 (3, 0));
00528 t = build (MODIFY_EXPR, ptr_type_node, u, t);
00529 TREE_SIDE_EFFECTS (t) = 1;
00530 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00531
00532
00533
00534 t = build_int_2 (current_function_args_info.num, 0);
00535 t = build (MODIFY_EXPR, TREE_TYPE (num_field), num_field, t);
00536 TREE_SIDE_EFFECTS (t) = 1;
00537 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00538 }
00539
00540 rtx
00541 clipper_va_arg (valist, type)
00542 tree valist, type;
00543 {
00544 tree ap_field, reg_field, num_field;
00545 tree addr, t;
00546 HOST_WIDE_INT align;
00547 rtx addr_rtx, over_label = NULL_RTX, tr;
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 ap_field = TYPE_FIELDS (TREE_TYPE (valist));
00573 reg_field = TREE_CHAIN (ap_field);
00574 num_field = TREE_CHAIN (reg_field);
00575
00576 ap_field = build (COMPONENT_REF, TREE_TYPE (ap_field), valist, ap_field);
00577 reg_field = build (COMPONENT_REF, TREE_TYPE (reg_field), valist, reg_field);
00578 num_field = build (COMPONENT_REF, TREE_TYPE (num_field), valist, num_field);
00579
00580 addr_rtx = gen_reg_rtx (Pmode);
00581
00582 if (! AGGREGATE_TYPE_P (type))
00583 {
00584 tree inreg;
00585 rtx false_label;
00586
00587 over_label = gen_label_rtx ();
00588 false_label = gen_label_rtx ();
00589
00590 emit_cmp_and_jump_insns (expand_expr (num_field, NULL_RTX, 0,
00591 OPTAB_LIB_WIDEN),
00592 GEN_INT (2), GE, const0_rtx,
00593 TYPE_MODE (TREE_TYPE (num_field)),
00594 TREE_UNSIGNED (num_field), false_label);
00595
00596 inreg = fold (build (MULT_EXPR, integer_type_node, num_field,
00597 build_int_2 (2, 0)));
00598 if (FLOAT_TYPE_P (type))
00599 inreg = fold (build (PLUS_EXPR, integer_type_node, inreg,
00600 build_int_2 (1, 0)));
00601 inreg = fold (build (ARRAY_REF, ptr_type_node, reg_field, inreg));
00602
00603 tr = expand_expr (inreg, addr_rtx, VOIDmode, EXPAND_NORMAL);
00604 if (tr != addr_rtx)
00605 emit_move_insn (addr_rtx, tr);
00606
00607 emit_jump_insn (gen_jump (over_label));
00608 emit_barrier ();
00609 emit_label (false_label);
00610 }
00611
00612
00613
00614 align = TYPE_ALIGN (type);
00615 if (align < TYPE_ALIGN (integer_type_node))
00616 align = TYPE_ALIGN (integer_type_node);
00617 align /= BITS_PER_UNIT;
00618
00619 addr = fold (build (PLUS_EXPR, ptr_type_node, ap_field,
00620 build_int_2 (align-1, 0)));
00621 addr = fold (build (BIT_AND_EXPR, ptr_type_node, addr,
00622 build_int_2 (-align, -1)));
00623 addr = save_expr (addr);
00624
00625 tr = expand_expr (addr, addr_rtx, Pmode, EXPAND_NORMAL);
00626 if (tr != addr_rtx)
00627 emit_move_insn (addr_rtx, tr);
00628
00629 t = build (MODIFY_EXPR, TREE_TYPE (ap_field), ap_field,
00630 build (PLUS_EXPR, TREE_TYPE (ap_field),
00631 addr, build_int_2 (int_size_in_bytes (type), 0)));
00632 TREE_SIDE_EFFECTS (t) = 1;
00633 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00634
00635 if (over_label)
00636 emit_label (over_label);
00637
00638 t = build (MODIFY_EXPR, TREE_TYPE (num_field), num_field,
00639 build (PLUS_EXPR, TREE_TYPE (num_field),
00640 num_field, build_int_2 (1, 0)));
00641 TREE_SIDE_EFFECTS (t) = 1;
00642 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
00643
00644 return addr_rtx;
00645 }
00646
00647
00648
00649
00650 int
00651 int_reg_operand (op, mode)
00652 rtx op;
00653 enum machine_mode mode;
00654 {
00655 return (register_operand (op, mode) &&
00656 (GET_CODE (op) != SUBREG ||
00657 GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_INT));
00658 }
00659
00660
00661
00662
00663 int
00664 fp_reg_operand (op, mode)
00665 rtx op;
00666 enum machine_mode mode;
00667 {
00668 return (register_operand (op, mode) &&
00669 (GET_CODE (op) != SUBREG ||
00670 GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_FLOAT));
00671 }
00672
00673 static void
00674 clix_asm_out_constructor (symbol, priority)
00675 rtx symbol;
00676 int priority ATTRIBUTE_UNUSED;
00677 {
00678 init_section ();
00679 fputs ("\tloada ", asm_out_file);
00680 assemble_name (asm_out_file, XSTR (symbol, 0));
00681 fputs (",r0\n\tsubq $8,sp\n\tstorw r0,(sp)\n", asm_out_file);
00682 }
00683
00684 static void
00685 clix_asm_out_destructor (symbol, priority)
00686 rtx symbol;
00687 int priority ATTRIBUTE_UNUSED;
00688 {
00689 fini_section ();
00690 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
00691 assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
00692 }