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 "rtl.h"
00025 #include "regs.h"
00026 #include "hard-reg-set.h"
00027 #include "hashtab.h"
00028 #include "insn-config.h"
00029 #include "output.h"
00030 #include "flags.h"
00031 #include "tree.h"
00032 #include "function.h"
00033 #include "expr.h"
00034 #include "toplev.h"
00035 #include "recog.h"
00036 #include "ggc.h"
00037 #include "dwarf2.h"
00038 #include "debug.h"
00039 #include "tm_p.h"
00040 #include "integrate.h"
00041 #include "target.h"
00042 #include "target-def.h"
00043
00044
00045 #define MMIX_FIRST_GLOBAL_REGNUM 32
00046
00047
00048
00049
00050 #define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0)
00051
00052
00053
00054
00055 #define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
00056 (flag_exceptions && ! leaf_function_p ())
00057
00058 #define IS_MMIX_EH_RETURN_DATA_REG(REGNO) \
00059 (current_function_calls_eh_return \
00060 && (EH_RETURN_DATA_REGNO (0) == REGNO \
00061 || EH_RETURN_DATA_REGNO (1) == REGNO \
00062 || EH_RETURN_DATA_REGNO (2) == REGNO \
00063 || EH_RETURN_DATA_REGNO (3) == REGNO))
00064
00065
00066
00067 rtx mmix_compare_op0;
00068 rtx mmix_compare_op1;
00069
00070
00071
00072
00073 const char *mmix_cc1_ignored_option;
00074
00075
00076
00077
00078
00079 static int mmix_highest_saved_stack_register;
00080
00081
00082 static int mmix_output_destination_register;
00083
00084 static void mmix_output_shiftvalue_op_from_str
00085 PARAMS ((FILE *, const char *, HOST_WIDEST_INT));
00086 static void mmix_output_shifted_value PARAMS ((FILE *, HOST_WIDEST_INT));
00087 static void mmix_output_condition PARAMS ((FILE *, rtx, int));
00088 static HOST_WIDEST_INT mmix_intval PARAMS ((rtx));
00089 static void mmix_output_octa PARAMS ((FILE *, HOST_WIDEST_INT, int));
00090 static bool mmix_assemble_integer PARAMS ((rtx, unsigned int, int));
00091 static void mmix_init_machine_status PARAMS ((struct function *));
00092
00093 extern void mmix_target_asm_function_prologue
00094 PARAMS ((FILE *, HOST_WIDE_INT));
00095 extern void mmix_target_asm_function_epilogue
00096 PARAMS ((FILE *, HOST_WIDE_INT));
00097
00098
00099
00100
00101
00102
00103
00104 #undef TARGET_ASM_BYTE_OP
00105 #define TARGET_ASM_BYTE_OP NULL
00106 #undef TARGET_ASM_ALIGNED_HI_OP
00107 #define TARGET_ASM_ALIGNED_HI_OP NULL
00108 #undef TARGET_ASM_ALIGNED_SI_OP
00109 #define TARGET_ASM_ALIGNED_SI_OP NULL
00110 #undef TARGET_ASM_ALIGNED_DI_OP
00111 #define TARGET_ASM_ALIGNED_DI_OP NULL
00112 #undef TARGET_ASM_INTEGER
00113 #define TARGET_ASM_INTEGER mmix_assemble_integer
00114
00115 #undef TARGET_ASM_FUNCTION_PROLOGUE
00116 #define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue
00117
00118 #undef TARGET_ASM_FUNCTION_EPILOGUE
00119 #define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue
00120
00121 struct gcc_target targetm = TARGET_INITIALIZER;
00122
00123
00124
00125
00126
00127
00128 void
00129 mmix_override_options ()
00130 {
00131
00132
00133
00134
00135
00136 if (flag_pic)
00137 {
00138 warning ("-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
00139 flag_pic = 0;
00140 }
00141
00142
00143
00144 ggc_add_rtx_root (&mmix_compare_op0, 1);
00145 ggc_add_rtx_root (&mmix_compare_op1, 1);
00146 }
00147
00148
00149
00150 void
00151 mmix_init_expanders ()
00152 {
00153 init_machine_status = mmix_init_machine_status;
00154 }
00155
00156
00157
00158 static void
00159 mmix_init_machine_status (f)
00160 struct function *f;
00161 {
00162 f->machine = xcalloc (1, sizeof (struct machine_function));
00163 }
00164
00165
00166
00167
00168
00169
00170 int
00171 mmix_data_alignment (type, basic_align)
00172 tree type ATTRIBUTE_UNUSED;
00173 int basic_align;
00174 {
00175 if (basic_align < 32)
00176 return 32;
00177
00178 return basic_align;
00179 }
00180
00181
00182
00183 int
00184 mmix_constant_alignment (constant, basic_align)
00185 tree constant ATTRIBUTE_UNUSED;
00186 int basic_align;
00187 {
00188 if (basic_align < 32)
00189 return 32;
00190
00191 return basic_align;
00192 }
00193
00194
00195
00196 int
00197 mmix_local_alignment (type, basic_align)
00198 tree type ATTRIBUTE_UNUSED;
00199 int basic_align;
00200 {
00201 if (basic_align < 32)
00202 return 32;
00203
00204 return basic_align;
00205 }
00206
00207
00208
00209 void
00210 mmix_conditional_register_usage ()
00211 {
00212 int i;
00213
00214 if (TARGET_ABI_GNU)
00215 {
00216 static const int gnu_abi_reg_alloc_order[]
00217 = MMIX_GNU_ABI_REG_ALLOC_ORDER;
00218
00219 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00220 reg_alloc_order[i] = gnu_abi_reg_alloc_order[i];
00221
00222
00223
00224
00225
00226
00227
00228
00229 for (i = 15; i <= 30; i++)
00230 call_used_regs[i] = 0;
00231
00232
00233 for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;
00234 i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;
00235 i++)
00236 fixed_regs[i] = 0;
00237 }
00238
00239
00240 if (! TARGET_TOPLEVEL_SYMBOLS)
00241 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00242 if (reg_names[i][0] == ':')
00243 reg_names[i]++;
00244 }
00245
00246
00247
00248
00249 enum reg_class
00250 mmix_preferred_reload_class (x, class)
00251 rtx x ATTRIBUTE_UNUSED;
00252 enum reg_class class;
00253 {
00254
00255 return GET_CODE (x) == MOD && GET_MODE (x) == DImode
00256 ? REMAINDER_REG : class;
00257 }
00258
00259
00260
00261
00262 enum reg_class
00263 mmix_preferred_output_reload_class (x, class)
00264 rtx x ATTRIBUTE_UNUSED;
00265 enum reg_class class;
00266 {
00267
00268 return GET_CODE (x) == MOD && GET_MODE (x) == DImode
00269 ? REMAINDER_REG : class;
00270 }
00271
00272
00273
00274
00275 enum reg_class
00276 mmix_secondary_reload_class (class, mode, x, in_p)
00277 enum reg_class class;
00278 enum machine_mode mode ATTRIBUTE_UNUSED;
00279 rtx x ATTRIBUTE_UNUSED;
00280 int in_p ATTRIBUTE_UNUSED;
00281 {
00282 if (class == REMAINDER_REG
00283 || class == HIMULT_REG
00284 || class == SYSTEM_REGS)
00285 return GENERAL_REGS;
00286
00287 return NO_REGS;
00288 }
00289
00290
00291
00292 int
00293 mmix_const_ok_for_letter_p (value, c)
00294 HOST_WIDE_INT value;
00295 int c;
00296 {
00297 return
00298 (c == 'I' ? value >= 0 && value <= 255
00299 : c == 'J' ? value >= 0 && value <= 65535
00300 : c == 'K' ? value <= 0 && value >= -255
00301 : c == 'L' ? mmix_shiftable_wyde_value (value)
00302 : c == 'M' ? value == 0
00303 : c == 'N' ? mmix_shiftable_wyde_value (~value)
00304 : c == 'O' ? (value == 3 || value == 5 || value == 9
00305 || value == 17)
00306 : 0);
00307 }
00308
00309
00310
00311 int
00312 mmix_const_double_ok_for_letter_p (value, c)
00313 rtx value;
00314 int c;
00315 {
00316 return
00317 (c == 'G' ? value == CONST0_RTX (GET_MODE (value))
00318 : 0);
00319 }
00320
00321
00322
00323
00324
00325 int
00326 mmix_extra_constraint (x, c, strict)
00327 rtx x;
00328 int c;
00329 int strict;
00330 {
00331 HOST_WIDEST_INT value;
00332
00333
00334
00335
00336
00337 if (c == 'U')
00338 return
00339 strict
00340 ? strict_memory_address_p (Pmode, x)
00341 : memory_address_p (Pmode, x);
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 if (c == 'R')
00356 return
00357 GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE
00358 && mmix_constant_address_p (x)
00359 && (! TARGET_BASE_ADDRESSES
00360 || (GET_CODE (x) == LABEL_REF
00361 || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))));
00362
00363 if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode)
00364 return 0;
00365
00366 value = mmix_intval (x);
00367
00368
00369
00370
00371 if (c == 'S')
00372 return mmix_shiftable_wyde_value (value);
00373 else if (c == 'T')
00374 return mmix_shiftable_wyde_value (~value);
00375 return 0;
00376 }
00377
00378
00379
00380 rtx
00381 mmix_dynamic_chain_address (frame)
00382 rtx frame;
00383 {
00384
00385
00386
00387
00388 return plus_constant (frame, -8);
00389 }
00390
00391
00392
00393 int
00394 mmix_starting_frame_offset ()
00395 {
00396
00397
00398
00399
00400
00401
00402 return
00403 (-8
00404 + (MMIX_CFUN_HAS_LANDING_PAD
00405 ? -16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? -8 : 0)));
00406 }
00407
00408
00409
00410 rtx
00411 mmix_return_addr_rtx (count, frame)
00412 int count;
00413 rtx frame ATTRIBUTE_UNUSED;
00414 {
00415 return count == 0
00416 ? (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS
00417
00418
00419
00420
00421 ? validize_mem (gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, -16)))
00422 : get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
00423 : NULL_RTX;
00424 }
00425
00426
00427
00428 void
00429 mmix_setup_frame_addresses ()
00430 {
00431
00432 }
00433
00434
00435
00436
00437 int
00438 mmix_initial_elimination_offset (fromreg, toreg)
00439 int fromreg;
00440 int toreg;
00441 {
00442 int regno;
00443 int fp_sp_offset
00444 = (get_frame_size () + current_function_outgoing_args_size + 7) & ~7;
00445
00446
00447
00448
00449
00450 if (fromreg == MMIX_ARG_POINTER_REGNUM
00451 && toreg == MMIX_FRAME_POINTER_REGNUM)
00452 return 0;
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
00477 regno <= 255;
00478 regno++)
00479 if ((regs_ever_live[regno] && ! call_used_regs[regno])
00480 || IS_MMIX_EH_RETURN_DATA_REG (regno))
00481 fp_sp_offset += 8;
00482
00483 return fp_sp_offset
00484 + (MMIX_CFUN_HAS_LANDING_PAD
00485 ? 16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0))
00486 + (fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8);
00487 }
00488
00489
00490
00491
00492 rtx
00493 mmix_function_arg (argsp, mode, type, named, incoming)
00494 const CUMULATIVE_ARGS * argsp;
00495 enum machine_mode mode;
00496 tree type;
00497 int named ATTRIBUTE_UNUSED;
00498 int incoming;
00499 {
00500
00501
00502
00503
00504
00505 if ((! named && incoming && current_function_varargs) || argsp->now_varargs)
00506 return NULL_RTX;
00507
00508
00509 if (type == void_type_node)
00510 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS)
00511 ? gen_rtx_REG (mode,
00512 (incoming
00513 ? MMIX_FIRST_INCOMING_ARG_REGNUM
00514 : MMIX_FIRST_ARG_REGNUM) + argsp->regs)
00515 : NULL_RTX;
00516
00517 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
00518 && !MUST_PASS_IN_STACK (mode, type)
00519 && (GET_MODE_BITSIZE (mode) <= 64
00520 || argsp->lib
00521 || TARGET_LIBFUNC))
00522 ? gen_rtx_REG (mode,
00523 (incoming
00524 ? MMIX_FIRST_INCOMING_ARG_REGNUM
00525 : MMIX_FIRST_ARG_REGNUM)
00526 + argsp->regs)
00527 : NULL_RTX;
00528 }
00529
00530
00531
00532
00533 int
00534 mmix_function_arg_pass_by_reference (argsp, mode, type, named)
00535 const CUMULATIVE_ARGS * argsp;
00536 enum machine_mode mode;
00537 tree type;
00538 int named ATTRIBUTE_UNUSED;
00539 {
00540
00541
00542 return
00543 MUST_PASS_IN_STACK (mode, type)
00544 || (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
00545 && !TARGET_LIBFUNC
00546 && !argsp->lib);
00547 }
00548
00549
00550
00551
00552 int
00553 mmix_function_arg_regno_p (regno, incoming)
00554 int regno;
00555 int incoming;
00556 {
00557 int first_arg_regnum
00558 = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM;
00559
00560 return regno >= first_arg_regnum
00561 && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS;
00562 }
00563
00564
00565
00566 rtx
00567 mmix_function_outgoing_value (valtype, func)
00568 tree valtype;
00569 tree func ATTRIBUTE_UNUSED;
00570 {
00571 enum machine_mode mode = TYPE_MODE (valtype);
00572 enum machine_mode cmode;
00573 int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM;
00574 rtx vec[MMIX_MAX_REGS_FOR_VALUE];
00575 int i;
00576 int nregs;
00577
00578
00579
00580
00581 if (TARGET_ABI_GNU
00582 || GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
00583 return
00584 gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM);
00585
00586
00587 cmode = TYPE_MODE (TREE_TYPE (valtype));
00588 nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD);
00589
00590
00591
00592
00593
00594
00595 if (nregs > MMIX_MAX_REGS_FOR_VALUE)
00596 internal_error ("too large function value type, needs %d registers,\
00597 have only %d registers for this", nregs, MMIX_MAX_REGS_FOR_VALUE);
00598
00599
00600
00601 for (i = 0; i < nregs - 1; i++)
00602 vec[i]
00603 = gen_rtx_EXPR_LIST (VOIDmode,
00604 gen_rtx_REG (cmode, first_val_regnum + i),
00605 GEN_INT ((i + 1) * BITS_PER_UNIT));
00606
00607 vec[nregs - 1]
00608 = gen_rtx_EXPR_LIST (VOIDmode,
00609 gen_rtx_REG (cmode, first_val_regnum + nregs - 1),
00610 GEN_INT (0));
00611
00612 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs, vec));
00613 }
00614
00615
00616
00617 int
00618 mmix_eh_return_data_regno (n)
00619 int n ATTRIBUTE_UNUSED;
00620 {
00621 if (n >= 0 && n < 4)
00622 return MMIX_EH_RETURN_DATA_REGNO_START + n;
00623
00624 return INVALID_REGNUM;
00625 }
00626
00627
00628
00629 rtx
00630 mmix_eh_return_stackadj_rtx ()
00631 {
00632 return gen_rtx_REG (Pmode, MMIX_EH_RETURN_STACKADJ_REGNUM);
00633 }
00634
00635
00636
00637 rtx
00638 mmix_eh_return_handler_rtx ()
00639 {
00640 return
00641 gen_rtx_REG (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
00642 }
00643
00644
00645
00646 int
00647 mmix_asm_preferred_eh_data_format (code, global)
00648 int code ATTRIBUTE_UNUSED;
00649 int global ATTRIBUTE_UNUSED;
00650 {
00651
00652 return DW_EH_PE_absptr;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661 void
00662 mmix_target_asm_function_prologue (stream, locals_size)
00663 FILE *stream;
00664 HOST_WIDE_INT locals_size;
00665 {
00666 int regno;
00667 int stack_space_to_allocate
00668 = (current_function_outgoing_args_size
00669 + current_function_pretend_args_size
00670 + (int) locals_size + 7) & ~7;
00671 int offset = -8;
00672 int doing_dwarf = dwarf2out_do_frame ();
00673 long cfa_offset = 0;
00674
00675
00676 if (locals_size != (int) locals_size)
00677 error ("stack frame too big");
00678
00679
00680 for (regno = 255;
00681 regno >= MMIX_FIRST_GLOBAL_REGNUM;
00682 regno--)
00683
00684
00685 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
00686 && regs_ever_live[regno] && !call_used_regs[regno]))
00687 || IS_MMIX_EH_RETURN_DATA_REG (regno))
00688 stack_space_to_allocate += 8;
00689
00690
00691 if (frame_pointer_needed)
00692 stack_space_to_allocate += 8;
00693
00694
00695
00696
00697 if (MMIX_CFUN_HAS_LANDING_PAD)
00698 stack_space_to_allocate += 16;
00699 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
00700
00701 stack_space_to_allocate += 8;
00702
00703
00704 if ((stack_space_to_allocate % 8) != 0)
00705 internal_error ("stack frame not a multiple of 8 bytes: %d",
00706 stack_space_to_allocate);
00707
00708 if (current_function_pretend_args_size)
00709 {
00710 int mmix_first_vararg_reg
00711 = (MMIX_FIRST_INCOMING_ARG_REGNUM
00712 + (MMIX_MAX_ARGS_IN_REGS
00713 - current_function_pretend_args_size / 8));
00714
00715 for (regno
00716 = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1;
00717 regno >= mmix_first_vararg_reg;
00718 regno--)
00719 {
00720 if (offset < 0)
00721 {
00722 int stack_chunk
00723 = stack_space_to_allocate > (256 - 8)
00724 ? (256 - 8) : stack_space_to_allocate;
00725
00726 fprintf (stream, "\tSUBU %s,%s,%d\n",
00727 reg_names[MMIX_STACK_POINTER_REGNUM],
00728 reg_names[MMIX_STACK_POINTER_REGNUM],
00729 stack_chunk);
00730
00731 if (doing_dwarf)
00732 {
00733
00734
00735
00736 cfa_offset += stack_chunk;
00737 if (!frame_pointer_needed)
00738 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
00739 cfa_offset);
00740 }
00741 offset += stack_chunk;
00742 stack_space_to_allocate -= stack_chunk;
00743 }
00744
00745 fprintf (stream, "\tSTOU %s,%s,%d\n", reg_names[regno],
00746 reg_names[MMIX_STACK_POINTER_REGNUM],
00747 offset);
00748
00749
00750
00751
00752 offset -= 8;
00753 }
00754 }
00755
00756
00757
00758 if (frame_pointer_needed)
00759 {
00760 if (offset < 0)
00761 {
00762
00763 int stack_chunk
00764 = stack_space_to_allocate > (256 - 8 - 8)
00765 ? (256 - 8 - 8) : stack_space_to_allocate;
00766
00767 fprintf (stream, "\tSUBU %s,%s,%d\n",
00768 reg_names[MMIX_STACK_POINTER_REGNUM],
00769 reg_names[MMIX_STACK_POINTER_REGNUM],
00770 stack_chunk);
00771 if (doing_dwarf)
00772 cfa_offset += stack_chunk;
00773 offset += stack_chunk;
00774 stack_space_to_allocate -= stack_chunk;
00775 }
00776
00777 fprintf (stream, "\tSTOU %s,%s,%d\n\tADDU %s,%s,%d\n",
00778 reg_names[MMIX_FRAME_POINTER_REGNUM],
00779 reg_names[MMIX_STACK_POINTER_REGNUM],
00780 offset,
00781 reg_names[MMIX_FRAME_POINTER_REGNUM],
00782 reg_names[MMIX_STACK_POINTER_REGNUM],
00783 offset + 8);
00784 if (doing_dwarf)
00785 {
00786
00787
00788
00789
00790
00791 dwarf2out_def_cfa ("", MMIX_FRAME_POINTER_REGNUM,
00792 -cfa_offset + offset + 8);
00793
00794 dwarf2out_reg_save ("", MMIX_FRAME_POINTER_REGNUM,
00795 -cfa_offset + offset);
00796 }
00797
00798 offset -= 8;
00799 }
00800
00801 if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
00802 {
00803
00804
00805
00806
00807 if (offset < 0)
00808 {
00809
00810 int stack_chunk
00811 = stack_space_to_allocate > (256 - 8 - 8)
00812 ? (256 - 8 - 8) : stack_space_to_allocate;
00813
00814 fprintf (stream, "\tSUBU %s,%s,%d\n",
00815 reg_names[MMIX_STACK_POINTER_REGNUM],
00816 reg_names[MMIX_STACK_POINTER_REGNUM],
00817 stack_chunk);
00818 if (doing_dwarf)
00819 {
00820 cfa_offset += stack_chunk;
00821 if (!frame_pointer_needed)
00822 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
00823 cfa_offset);
00824 }
00825 offset += stack_chunk;
00826 stack_space_to_allocate -= stack_chunk;
00827 }
00828
00829 fprintf (stream, "\tGET $255,rJ\n\tSTOU $255,%s,%d\n",
00830 reg_names[MMIX_STACK_POINTER_REGNUM],
00831 offset);
00832 if (doing_dwarf)
00833 dwarf2out_return_save ("", -cfa_offset + offset);
00834 offset -= 8;
00835 }
00836 else if (MMIX_CFUN_HAS_LANDING_PAD)
00837 offset -= 8;
00838
00839 if (MMIX_CFUN_HAS_LANDING_PAD)
00840 {
00841
00842
00843
00844 if (offset < 0)
00845 {
00846
00847 int stack_chunk
00848 = stack_space_to_allocate > (256 - 8 - 8)
00849 ? (256 - 8 - 8) : stack_space_to_allocate;
00850
00851 fprintf (stream, "\tSUBU %s,%s,%d\n",
00852 reg_names[MMIX_STACK_POINTER_REGNUM],
00853 reg_names[MMIX_STACK_POINTER_REGNUM],
00854 stack_chunk);
00855 offset += stack_chunk;
00856 stack_space_to_allocate -= stack_chunk;
00857
00858 if (doing_dwarf)
00859 {
00860 cfa_offset += stack_chunk;
00861 if (!frame_pointer_needed)
00862 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
00863 cfa_offset);
00864 }
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 fprintf (stream, "\tGET $255,rO\n\tSTOU $255,%s,%d\n",
00877 reg_names[MMIX_STACK_POINTER_REGNUM], offset);
00878
00879 offset -= 8;
00880 }
00881
00882
00883
00884 offset -= (locals_size + 7) & ~7;
00885
00886
00887
00888
00889
00890
00891
00892 for (regno = 255;
00893 regno >= MMIX_FIRST_GLOBAL_REGNUM;
00894 regno--)
00895 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
00896 && regs_ever_live[regno] && ! call_used_regs[regno])
00897 || IS_MMIX_EH_RETURN_DATA_REG (regno))
00898 {
00899 if (offset < 0)
00900 {
00901 int stack_chunk;
00902
00903
00904
00905 if (offset < -248)
00906 {
00907
00908
00909
00910 stack_chunk =
00911 stack_space_to_allocate > (256 - offset - 8)
00912 ? (256 - offset - 8) : stack_space_to_allocate;
00913
00914 mmix_output_register_setting (stream, 255, stack_chunk, 1);
00915 fprintf (stream, "\tSUBU %s,%s,$255\n",
00916 reg_names[MMIX_STACK_POINTER_REGNUM],
00917 reg_names[MMIX_STACK_POINTER_REGNUM]);
00918
00919 if (doing_dwarf)
00920 {
00921 cfa_offset += stack_chunk;
00922 if (!frame_pointer_needed)
00923 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
00924 cfa_offset);
00925 }
00926 }
00927 else
00928 {
00929 stack_chunk = stack_space_to_allocate > (256 - 8)
00930 ? (256 - 8) : stack_space_to_allocate;
00931
00932 fprintf (stream, "\tSUBU %s,%s,%d\n",
00933 reg_names[MMIX_STACK_POINTER_REGNUM],
00934 reg_names[MMIX_STACK_POINTER_REGNUM], stack_chunk);
00935 if (doing_dwarf)
00936 {
00937 cfa_offset += stack_chunk;
00938 if (!frame_pointer_needed)
00939 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
00940 cfa_offset);
00941 }
00942 }
00943
00944 offset += stack_chunk;
00945 stack_space_to_allocate -= stack_chunk;
00946 }
00947
00948 fprintf (stream, "\tSTOU %s,%s,%d\n", reg_names[regno],
00949 reg_names[MMIX_STACK_POINTER_REGNUM], offset);
00950 if (doing_dwarf)
00951 dwarf2out_reg_save ("", regno, -cfa_offset + offset);
00952 offset -= 8;
00953 }
00954
00955
00956
00957
00958 if (stack_space_to_allocate)
00959 {
00960 if (stack_space_to_allocate < 256)
00961 {
00962 fprintf (stream, "\tSUBU %s,%s,%d\n",
00963 reg_names[MMIX_STACK_POINTER_REGNUM],
00964 reg_names[MMIX_STACK_POINTER_REGNUM],
00965 stack_space_to_allocate);
00966 }
00967 else
00968 {
00969 mmix_output_register_setting (stream, 255,
00970 stack_space_to_allocate, 1);
00971 fprintf (stream, "\tSUBU %s,%s,$255\n",
00972 reg_names[MMIX_STACK_POINTER_REGNUM],
00973 reg_names[MMIX_STACK_POINTER_REGNUM]);
00974 }
00975
00976 if (doing_dwarf)
00977 {
00978 cfa_offset += stack_space_to_allocate;
00979 if (!frame_pointer_needed)
00980 dwarf2out_def_cfa ("", MMIX_STACK_POINTER_REGNUM,
00981 cfa_offset);
00982 }
00983 }
00984
00985
00986
00987
00988
00989 for (regno = MMIX_LAST_REGISTER_FILE_REGNUM;
00990 regno >= 0;
00991 regno--)
00992 if ((regs_ever_live[regno] && !call_used_regs[regno])
00993 || (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
00994 break;
00995
00996 mmix_highest_saved_stack_register = regno;
00997 }
00998
00999
01000
01001 void
01002 mmix_target_asm_function_epilogue (stream, locals_size)
01003 FILE *stream;
01004 HOST_WIDE_INT locals_size;
01005
01006 {
01007 int regno;
01008 int stack_space_to_deallocate
01009 = (current_function_outgoing_args_size
01010 + current_function_pretend_args_size
01011 + (int) locals_size + 7) & ~7;
01012
01013
01014
01015
01016
01017 int offset = current_function_outgoing_args_size;
01018
01019
01020
01021
01022 for (regno = 255;
01023 regno >= MMIX_FIRST_GLOBAL_REGNUM;
01024 regno--)
01025 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
01026 && regs_ever_live[regno] && !call_used_regs[regno])
01027 || IS_MMIX_EH_RETURN_DATA_REG (regno))
01028 stack_space_to_deallocate += 8;
01029
01030
01031
01032 if (MMIX_CFUN_HAS_LANDING_PAD)
01033 stack_space_to_deallocate += 16;
01034 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
01035
01036 stack_space_to_deallocate += 8;
01037
01038
01039 if (frame_pointer_needed)
01040 stack_space_to_deallocate += 8;
01041
01042
01043 if ((stack_space_to_deallocate % 8) != 0)
01044 internal_error ("stack frame not a multiple of octabyte: %d",
01045 stack_space_to_deallocate);
01046
01047
01048
01049
01050
01051 for (regno = MMIX_FIRST_GLOBAL_REGNUM;
01052 regno <= 255;
01053 regno++)
01054 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed)
01055 && regs_ever_live[regno] && !call_used_regs[regno])
01056 || IS_MMIX_EH_RETURN_DATA_REG (regno))
01057 {
01058 if (offset > 255)
01059 {
01060 if (offset > 65535)
01061 {
01062
01063
01064
01065 mmix_output_register_setting (stream, 255, offset, 1);
01066 fprintf (stream, "\tADDU %s,%s,$255\n",
01067 reg_names[MMIX_STACK_POINTER_REGNUM],
01068 reg_names[MMIX_STACK_POINTER_REGNUM]);
01069 }
01070 else
01071 fprintf (stream, "\tINCL %s,%d\n",
01072 reg_names[MMIX_STACK_POINTER_REGNUM], offset);
01073
01074 stack_space_to_deallocate -= offset;
01075 offset = 0;
01076 }
01077
01078 fprintf (stream, "\tLDOU %s,%s,%d\n",
01079 reg_names[regno],
01080 reg_names[MMIX_STACK_POINTER_REGNUM],
01081 offset);
01082 offset += 8;
01083 }
01084
01085
01086
01087 offset += (locals_size + 7) & ~7;
01088
01089
01090
01091
01092
01093 if (MMIX_CFUN_HAS_LANDING_PAD)
01094 offset += 16;
01095 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS)
01096
01097
01098 offset += 8;
01099
01100
01101 if (frame_pointer_needed)
01102 {
01103 if (offset > 255)
01104 {
01105 if (offset > 65535)
01106 {
01107
01108
01109
01110 mmix_output_register_setting (stream, 255, offset, 1);
01111 fprintf (stream, "\tADDU %s,%s,$255\n",
01112 reg_names[MMIX_STACK_POINTER_REGNUM],
01113 reg_names[MMIX_STACK_POINTER_REGNUM]);
01114 }
01115 else
01116 fprintf (stream, "\tINCL %s,%d\n",
01117 reg_names[MMIX_STACK_POINTER_REGNUM], offset);
01118
01119 stack_space_to_deallocate -= offset;
01120 offset = 0;
01121 }
01122
01123 fprintf (stream, "\tLDOU %s,%s,%d\n",
01124 reg_names[MMIX_FRAME_POINTER_REGNUM],
01125 reg_names[MMIX_STACK_POINTER_REGNUM],
01126 offset);
01127 offset += 8;
01128 }
01129
01130
01131
01132 if (stack_space_to_deallocate > 65535)
01133 {
01134
01135
01136 mmix_output_register_setting (stream, 255,
01137 stack_space_to_deallocate, 1);
01138 fprintf (stream, "\tADDU %s,%s,$255\n",
01139 reg_names[MMIX_STACK_POINTER_REGNUM],
01140 reg_names[MMIX_STACK_POINTER_REGNUM]);
01141 }
01142 else if (stack_space_to_deallocate != 0)
01143 fprintf (stream, "\tINCL %s,%d\n",
01144 reg_names[MMIX_STACK_POINTER_REGNUM],
01145 stack_space_to_deallocate);
01146
01147 if (current_function_calls_eh_return)
01148
01149
01150
01151 fprintf (stream, "\tADDU %s,%s,%s\n",
01152 reg_names [MMIX_STACK_POINTER_REGNUM],
01153 reg_names [MMIX_STACK_POINTER_REGNUM],
01154 reg_names [MMIX_EH_RETURN_STACKADJ_REGNUM]);
01155
01156
01157
01158 fprintf (stream, "\tPOP %d,0\n\n",
01159 (! TARGET_ABI_GNU
01160 && current_function_return_rtx != NULL
01161 && ! current_function_returns_struct)
01162 ? (GET_CODE (current_function_return_rtx) == PARALLEL
01163 ? GET_NUM_ELEM (XVEC (current_function_return_rtx, 0)) : 1)
01164 : 0);
01165 }
01166
01167
01168
01169 void
01170 mmix_asm_output_mi_thunk (stream, fndecl, delta, func)
01171 FILE * stream;
01172 tree fndecl ATTRIBUTE_UNUSED;
01173 int delta;
01174 tree func;
01175 {
01176
01177
01178
01179 const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM];
01180
01181 if (delta >= 0 && delta < 65536)
01182 asm_fprintf (stream, "\tINCL %s,%d\n", delta, regname);
01183 else if (delta < 0 && delta >= -255)
01184 asm_fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, -delta);
01185 else
01186 {
01187 mmix_output_register_setting (stream, 255, delta, 1);
01188 asm_fprintf (stream, "\tADDU %s,%s,$255\n", regname, regname);
01189 }
01190
01191 fprintf (stream, "\tJMP ");
01192 assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0));
01193 fprintf (stream, "\n");
01194 }
01195
01196
01197
01198 void
01199 mmix_function_profiler (stream, labelno)
01200 FILE *stream ATTRIBUTE_UNUSED;
01201 int labelno ATTRIBUTE_UNUSED;
01202 {
01203 sorry ("function_profiler support for MMIX");
01204 }
01205
01206
01207
01208 void
01209 mmix_setup_incoming_varargs (args_so_farp, mode, vartype, pretend_sizep,
01210 second_time)
01211 CUMULATIVE_ARGS * args_so_farp;
01212 enum machine_mode mode;
01213 tree vartype;
01214 int * pretend_sizep;
01215 int second_time ATTRIBUTE_UNUSED;
01216 {
01217
01218
01219
01220 if (current_function_stdarg)
01221 {
01222 if (args_so_farp->regs + 1 < MMIX_MAX_ARGS_IN_REGS)
01223 *pretend_sizep
01224 = (MMIX_MAX_ARGS_IN_REGS - (args_so_farp->regs + 1)) * 8;
01225 }
01226 else if (current_function_varargs)
01227 {
01228 if (args_so_farp->regs < MMIX_MAX_ARGS_IN_REGS)
01229 *pretend_sizep
01230 = (MMIX_MAX_ARGS_IN_REGS - args_so_farp->regs) * 8;
01231
01232
01233
01234
01235
01236
01237 args_so_farp->now_varargs = 1;
01238 }
01239 else
01240 internal_error ("neither varargs or stdarg in mmix_setup_incoming_varargs");
01241
01242
01243
01244
01245 if ((7 + (MMIX_FUNCTION_ARG_SIZE (mode, vartype))) / 8 != 1)
01246 internal_error ("MMIX Internal: Last named vararg would not fit in a register");
01247 }
01248
01249
01250
01251
01252
01253
01254
01255
01256 rtx
01257 mmix_expand_builtin_va_arg (valist, type)
01258 tree valist;
01259 tree type;
01260 {
01261 tree ptr_size = size_int (BITS_PER_WORD / BITS_PER_UNIT);
01262 tree addr_tree, type_size = NULL;
01263 tree align, alignm1;
01264 tree rounded_size;
01265 rtx addr;
01266
01267
01268
01269
01270 addr_tree = valist;
01271 align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
01272 alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
01273 if (type == error_mark_node
01274 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
01275 || TREE_OVERFLOW (type_size))
01276
01277
01278 rounded_size = size_zero_node;
01279 else
01280 rounded_size = fold (build (MULT_EXPR, sizetype,
01281 fold (build (TRUNC_DIV_EXPR, sizetype,
01282 fold (build (PLUS_EXPR, sizetype,
01283 type_size, alignm1)),
01284 align)),
01285 align));
01286
01287 if (AGGREGATE_TYPE_P (type)
01288 && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) < 8
01289 && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) != 0)
01290 {
01291
01292
01293
01294
01295
01296
01297
01298 addr_tree
01299 = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
01300 size_int ((BITS_PER_WORD / BITS_PER_UNIT)
01301 - GET_MODE_UNIT_SIZE (TYPE_MODE (type))));
01302 }
01303 else if (!integer_zerop (rounded_size))
01304 {
01305 if (!really_constant_p (type_size))
01306
01307 addr_tree
01308 = build1 (INDIRECT_REF, build_pointer_type (type), addr_tree);
01309 else
01310 {
01311
01312
01313 tree addend
01314 = fold (build (COND_EXPR, sizetype,
01315 fold (build (GT_EXPR, sizetype,
01316 rounded_size,
01317 align)),
01318 size_zero_node,
01319 fold (build (MINUS_EXPR, sizetype,
01320 rounded_size,
01321 type_size))));
01322 tree addr_tree1
01323 = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
01324 addend));
01325
01326
01327
01328 addr_tree
01329 = fold (build (COND_EXPR, TREE_TYPE (addr_tree1),
01330 fold (build (GT_EXPR, sizetype,
01331 rounded_size,
01332 ptr_size)),
01333 build1 (INDIRECT_REF, build_pointer_type (type),
01334 addr_tree1),
01335 addr_tree1));
01336 }
01337 }
01338
01339 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
01340 addr = copy_to_reg (addr);
01341
01342 if (!integer_zerop (rounded_size))
01343 {
01344
01345
01346 tree t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
01347 build (PLUS_EXPR, TREE_TYPE (valist), valist,
01348 ptr_size));
01349 TREE_SIDE_EFFECTS (t) = 1;
01350 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
01351 }
01352
01353 return addr;
01354 }
01355
01356
01357
01358 int mmix_trampoline_size = 32;
01359
01360
01361
01362
01363 void
01364 mmix_trampoline_template (stream)
01365 FILE * stream;
01366 {
01367
01368
01369
01370
01371
01372 fprintf (stream, "\tGETA $255,1F\n\t");
01373 fprintf (stream, "LDOU %s,$255,0\n\t",
01374 reg_names[MMIX_STATIC_CHAIN_REGNUM]);
01375 fprintf (stream, "LDOU $255,$255,8\n\t");
01376 fprintf (stream, "GO $255,$255,0\n");
01377 fprintf (stream, "1H\tOCTA 0\n\t");
01378 fprintf (stream, "OCTA 0\n");
01379 }
01380
01381
01382
01383
01384
01385
01386 void
01387 mmix_initialize_trampoline (trampaddr, fnaddr, static_chain)
01388 rtx trampaddr;
01389 rtx fnaddr;
01390 rtx static_chain;
01391 {
01392 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (trampaddr, 16)),
01393 static_chain);
01394 emit_move_insn (gen_rtx_MEM (DImode,
01395 plus_constant (trampaddr, 24)),
01396 fnaddr);
01397 emit_insn (gen_sync_icache (validize_mem (gen_rtx_MEM (DImode,
01398 trampaddr)),
01399 GEN_INT (mmix_trampoline_size - 1)));
01400 }
01401
01402
01403
01404
01405
01406 int
01407 mmix_constant_address_p (x)
01408 rtx x;
01409 {
01410 RTX_CODE code = GET_CODE (x);
01411 int addend = 0;
01412
01413 int constant_ok = TARGET_BASE_ADDRESSES != 0;
01414
01415 if (code == LABEL_REF || code == SYMBOL_REF)
01416 return 1;
01417
01418 if (code == CONSTANT_P_RTX || code == HIGH)
01419
01420 return constant_ok;
01421
01422 switch (code)
01423 {
01424 case LABEL_REF:
01425 case SYMBOL_REF:
01426 return 1;
01427
01428 case CONSTANT_P_RTX:
01429 case HIGH:
01430
01431
01432 return constant_ok;
01433
01434 case CONST_INT:
01435 addend = INTVAL (x);
01436 break;
01437
01438 case CONST_DOUBLE:
01439 if (GET_MODE (x) != VOIDmode)
01440
01441 return constant_ok;
01442 addend = CONST_DOUBLE_LOW (x);
01443 break;
01444
01445 case CONST:
01446
01447
01448
01449 if (GET_CODE (XEXP (x, 0)) == PLUS)
01450 {
01451 rtx x0 = XEXP (XEXP (x, 0), 0);
01452 rtx x1 = XEXP (XEXP (x, 0), 1);
01453
01454 if ((GET_CODE (x0) == SYMBOL_REF
01455 || GET_CODE (x0) == LABEL_REF)
01456 && (GET_CODE (x1) == CONST_INT
01457 || (GET_CODE (x1) == CONST_DOUBLE
01458 && GET_MODE (x1) == VOIDmode)))
01459 addend = mmix_intval (x1);
01460 else
01461 return constant_ok;
01462 }
01463 else
01464 return constant_ok;
01465 break;
01466
01467 default:
01468 return 0;
01469 }
01470
01471 return constant_ok || (addend & 3) == 0;
01472 }
01473
01474
01475
01476
01477 int
01478 mmix_legitimate_address (mode, x, strict_checking)
01479 enum machine_mode mode ATTRIBUTE_UNUSED;
01480 rtx x;
01481 int strict_checking;
01482 {
01483 #define MMIX_REG_OK(X) \
01484 ((strict_checking \
01485 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \
01486 || (reg_renumber[REGNO (X)] > 0 \
01487 && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER))) \
01488 || (!strict_checking \
01489 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \
01490 || REGNO (X) >= FIRST_PSEUDO_REGISTER \
01491 || REGNO (X) == ARG_POINTER_REGNUM)))
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 if (REG_P (x) && MMIX_REG_OK (x))
01503 return 1;
01504
01505 if (GET_CODE(x) == PLUS)
01506 {
01507 rtx x1 = XEXP (x, 0);
01508 rtx x2 = XEXP (x, 1);
01509
01510
01511 if (! REG_P (x1))
01512 {
01513 rtx tem = x1;
01514 x1 = x2;
01515 x2 = tem;
01516 }
01517
01518
01519 if (!REG_P (x1) || !MMIX_REG_OK (x1))
01520 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
01521
01522
01523 if (REG_P (x2) && MMIX_REG_OK (x2))
01524 return 1;
01525
01526
01527 if (GET_CODE (x2) == CONST_INT
01528 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
01529 return 1;
01530
01531 return 0;
01532 }
01533
01534 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
01535 }
01536
01537
01538
01539 int
01540 mmix_legitimate_constant_p (x)
01541 rtx x;
01542 {
01543 RTX_CODE code = GET_CODE (x);
01544
01545
01546
01547
01548 if (code == CONST_INT || code == CONST_DOUBLE)
01549 return 1;
01550
01551 return CONSTANT_ADDRESS_P (x);
01552 }
01553
01554
01555
01556 enum machine_mode
01557 mmix_select_cc_mode (op, x, y)
01558 RTX_CODE op;
01559 rtx x;
01560 rtx y ATTRIBUTE_UNUSED;
01561 {
01562
01563
01564
01565
01566 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
01567 {
01568 if (op == ORDERED || op == UNORDERED || op == UNGE
01569 || op == UNGT || op == UNLE || op == UNLT)
01570 return CC_FUNmode;
01571
01572 if (op == EQ || op == NE)
01573 return CC_FPEQmode;
01574
01575 return CC_FPmode;
01576 }
01577
01578 if (op == GTU || op == LTU || op == GEU || op == LEU)
01579 return CC_UNSmode;
01580
01581 return CCmode;
01582 }
01583
01584
01585
01586
01587 void
01588 mmix_canonicalize_comparison (codep, op0p, op1p)
01589 RTX_CODE * codep;
01590 rtx * op0p ATTRIBUTE_UNUSED;
01591 rtx * op1p;
01592 {
01593
01594 if ((*codep == LE || *codep == GT)
01595 && GET_CODE (*op1p) == CONST_INT
01596 && *op1p == constm1_rtx)
01597 {
01598 *codep = *codep == LE ? LT : GE;
01599 *op1p = const0_rtx;
01600 }
01601
01602
01603 if ((*codep == LT || *codep == LTU || *codep == GE || *codep == GEU)
01604 && GET_CODE (*op1p) == CONST_INT
01605 && INTVAL (*op1p) == 256)
01606 {
01607
01608 fatal_insn ("oops, not debugged; fixing up value:", *op1p);
01609 *codep = *codep == LT ? LE : *codep == LTU ? LEU : *codep
01610 == GE ? GT : GTU;
01611 *op1p = GEN_INT (255);
01612 }
01613 }
01614
01615
01616
01617 int
01618 mmix_reversible_cc_mode (mode)
01619 enum machine_mode mode;
01620 {
01621
01622
01623 return mode != CC_FPmode;
01624 }
01625
01626
01627
01628 int
01629 mmix_rtx_cost_recalculated (x, code, outer_code, costp)
01630 rtx x ATTRIBUTE_UNUSED;
01631 RTX_CODE code ATTRIBUTE_UNUSED;
01632 RTX_CODE outer_code ATTRIBUTE_UNUSED;
01633 int *costp ATTRIBUTE_UNUSED;
01634 {
01635
01636
01637
01638 return 0;
01639 }
01640
01641
01642
01643 int
01644 mmix_address_cost (addr)
01645 rtx addr ATTRIBUTE_UNUSED;
01646 {
01647
01648
01649
01650 return 1;
01651 }
01652
01653
01654
01655 int
01656 mmix_register_move_cost (mode, from, to)
01657 enum machine_mode mode ATTRIBUTE_UNUSED;
01658 enum reg_class from;
01659 enum reg_class to;
01660 {
01661 return (from == GENERAL_REGS && from == to) ? 2 : 3;
01662 }
01663
01664
01665
01666
01667
01668
01669
01670 const char *
01671 mmix_data_section_asm_op ()
01672 {
01673 return "\t.data ! mmixal:= 8H LOC 9B";
01674 }
01675
01676
01677
01678
01679 void
01680 mmix_select_section (decl, reloc, align)
01681 tree decl;
01682 int reloc;
01683 int align ATTRIBUTE_UNUSED;
01684 {
01685 if (TREE_CODE (decl) == STRING_CST)
01686 {
01687 if (! flag_writable_strings)
01688 const_section ();
01689 else
01690 data_section ();
01691 }
01692 else if (TREE_CODE (decl) == VAR_DECL)
01693 {
01694 if ((flag_pic && reloc)
01695 || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
01696 || !DECL_INITIAL (decl)
01697 || (DECL_INITIAL (decl) != error_mark_node
01698 && !TREE_CONSTANT (DECL_INITIAL (decl))))
01699 data_section ();
01700 else
01701 const_section ();
01702 }
01703 else if (TREE_CODE (decl) == CONSTRUCTOR)
01704 {
01705 if ((flag_pic && reloc)
01706 || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
01707 || ! TREE_CONSTANT (decl))
01708 data_section ();
01709 else
01710 const_section ();
01711 }
01712 else
01713 const_section ();
01714 }
01715
01716
01717
01718 void
01719 mmix_encode_section_info (decl)
01720 tree decl;
01721 {
01722
01723 if ((TREE_CODE (decl) == VAR_DECL
01724 && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl)))
01725 || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)))
01726 ;
01727 else if (DECL_P (decl))
01728 {
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739 const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
01740 int len = strlen (str);
01741 char *newstr;
01742
01743
01744 newstr = (char *) ggc_alloc_string ("", len + 1);
01745
01746 strcpy (newstr + 1, str);
01747 *newstr = '@';
01748 XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
01749 }
01750
01751
01752
01753
01754 if (TREE_CODE (decl) == FUNCTION_DECL
01755 || TREE_CONSTANT (decl)
01756 || (TREE_CODE (decl) == VAR_DECL
01757 && TREE_READONLY (decl)
01758 && !TREE_SIDE_EFFECTS (decl)
01759 && (!DECL_INITIAL (decl)
01760 || TREE_CONSTANT (DECL_INITIAL (decl)))))
01761 {
01762 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
01763 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
01764 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
01765 }
01766 }
01767
01768
01769
01770 const char *
01771 mmix_strip_name_encoding (name)
01772 const char *name;
01773 {
01774 for (; (*name == '@' || *name == '*'); name++)
01775 ;
01776
01777 return name;
01778 }
01779
01780
01781
01782
01783 void
01784 mmix_unique_section (decl, reloc)
01785 tree decl;
01786 int reloc;
01787 {
01788 int len;
01789 int sec;
01790 const char *name;
01791 char *string;
01792 const char *prefix;
01793 static const char *const prefixes[4][2] =
01794 {
01795 { ".text.", ".gnu.linkonce.t." },
01796 { ".rodata.", ".gnu.linkonce.r." },
01797 { ".data.", ".gnu.linkonce.d." },
01798 { ".bss.", ".gnu.linkonce.b." }
01799 };
01800
01801 if (TREE_CODE (decl) == FUNCTION_DECL)
01802 sec = 0;
01803 else if (DECL_INITIAL (decl) == 0
01804 || DECL_INITIAL (decl) == error_mark_node)
01805 sec = 3;
01806 else if (DECL_READONLY_SECTION (decl, reloc))
01807 sec = 1;
01808 else
01809 sec = 2;
01810
01811 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
01812
01813 STRIP_NAME_ENCODING (name, name);
01814 prefix = prefixes[sec][DECL_ONE_ONLY (decl)];
01815 len = strlen (name) + strlen (prefix);
01816 string = alloca (len + 1);
01817
01818 sprintf (string, "%s%s", prefix, name);
01819
01820 DECL_SECTION_NAME (decl) = build_string (len, string);
01821 }
01822
01823
01824
01825 void
01826 mmix_asm_file_start (stream)
01827 FILE * stream;
01828 {
01829
01830
01831 ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename);
01832
01833 fprintf (stream, "! mmixal:= 8H LOC Data_Section\n");
01834
01835
01836 text_section ();
01837 }
01838
01839
01840
01841 void
01842 mmix_asm_file_end (stream)
01843 FILE * stream ATTRIBUTE_UNUSED;
01844 {
01845
01846 data_section ();
01847 }
01848
01849
01850
01851 void
01852 mmix_asm_output_source_filename (stream, name)
01853 FILE * stream;
01854 const char * name;
01855 {
01856 fprintf (stream, "# 1 ");
01857 OUTPUT_QUOTED_STRING (stream, name);
01858 fprintf (stream, "\n");
01859 }
01860
01861
01862
01863 void
01864 mmix_output_quoted_string (stream, string, length)
01865 FILE * stream;
01866 const char * string;
01867 int length;
01868 {
01869 const char * string_end = string + length;
01870 static const char *const unwanted_chars = "\"[]\\";
01871
01872
01873
01874
01875
01876
01877 while (string < string_end)
01878 {
01879 if (*string
01880 && (unsigned char) *string < 128
01881 && !ISCNTRL (*string)
01882 && strchr (unwanted_chars, *string) == NULL)
01883 {
01884 fputc ('"', stream);
01885 while (*string
01886 && (unsigned char) *string < 128
01887 && !ISCNTRL (*string)
01888 && strchr (unwanted_chars, *string) == NULL
01889 && string < string_end)
01890 {
01891 fputc (*string, stream);
01892 string++;
01893 }
01894 fputc ('"', stream);
01895 if (string < string_end)
01896 fprintf (stream, ",");
01897 }
01898 if (string < string_end)
01899 {
01900 fprintf (stream, "#%x", *string & 255);
01901 string++;
01902 if (string < string_end)
01903 fprintf (stream, ",");
01904 }
01905 }
01906 }
01907
01908
01909
01910 void
01911 mmix_asm_output_source_line (stream, lineno)
01912 FILE * stream;
01913 int lineno;
01914 {
01915 fprintf (stream, "# %d ", lineno);
01916 OUTPUT_QUOTED_STRING (stream, main_input_filename);
01917 fprintf (stream, "\n");
01918 }
01919
01920
01921
01922
01923
01924 static bool
01925 mmix_assemble_integer (x, size, aligned_p)
01926 rtx x;
01927 unsigned int size;
01928 int aligned_p;
01929 {
01930 if (aligned_p)
01931 switch (size)
01932 {
01933
01934
01935
01936
01937
01938
01939
01940
01941 case 1:
01942 if (GET_CODE (x) != CONST_INT)
01943 {
01944 aligned_p = 0;
01945 break;
01946 }
01947 fputs ("\tBYTE\t", asm_out_file);
01948 mmix_print_operand (asm_out_file, x, 'B');
01949 fputc ('\n', asm_out_file);
01950 return true;
01951
01952 case 2:
01953 if (GET_CODE (x) != CONST_INT)
01954 {
01955 aligned_p = 0;
01956 break;
01957 }
01958 fputs ("\tWYDE\t", asm_out_file);
01959 mmix_print_operand (asm_out_file, x, 'W');
01960 fputc ('\n', asm_out_file);
01961 return true;
01962
01963 case 4:
01964 if (GET_CODE (x) != CONST_INT)
01965 {
01966 aligned_p = 0;
01967 break;
01968 }
01969 fputs ("\tTETRA\t", asm_out_file);
01970 mmix_print_operand (asm_out_file, x, 'L');
01971 fputc ('\n', asm_out_file);
01972 return true;
01973
01974 case 8:
01975 if (GET_CODE (x) == CONST_DOUBLE)
01976
01977
01978
01979 abort ();
01980 assemble_integer_with_op ("\tOCTA\t", x);
01981 return true;
01982 }
01983 return default_assemble_integer (x, size, aligned_p);
01984 }
01985
01986
01987
01988 void
01989 mmix_asm_output_ascii (stream, string, length)
01990 FILE *stream;
01991 const char *string;
01992 int length;
01993 {
01994 while (length > 0)
01995 {
01996 int chunk_size = length > 60 ? 60 : length;
01997 fprintf (stream, "\tBYTE ");
01998 mmix_output_quoted_string (stream, string, chunk_size);
01999 string += chunk_size;
02000 length -= chunk_size;
02001 fprintf (stream, "\n");
02002 }
02003 }
02004
02005
02006
02007 void
02008 mmix_asm_output_aligned_common (stream, name, size, align)
02009 FILE *stream;
02010 const char *name;
02011 int size;
02012 int align;
02013 {
02014
02015
02016 fprintf (stream, "\t.comm\t");
02017 assemble_name (stream, name);
02018 fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n",
02019 size, align / BITS_PER_UNIT);
02020 }
02021
02022
02023
02024 void
02025 mmix_asm_output_aligned_local (stream, name, size, align)
02026 FILE * stream;
02027 const char * name;
02028 int size;
02029 int align;
02030 {
02031 data_section ();
02032
02033 ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT));
02034 assemble_name (stream, name);
02035 fprintf (stream, "\tLOC @+%d\n", size);
02036 }
02037
02038
02039
02040 void
02041 mmix_asm_output_label (stream, name)
02042 FILE *stream;
02043 const char * name;
02044 {
02045 assemble_name (stream, name);
02046 fprintf (stream, "\tIS @\n");
02047 }
02048
02049
02050
02051 void
02052 mmix_asm_declare_register_global (stream, decl, regno, name)
02053 FILE *stream ATTRIBUTE_UNUSED;
02054 tree decl ATTRIBUTE_UNUSED;
02055 int regno ATTRIBUTE_UNUSED;
02056 const char *name ATTRIBUTE_UNUSED;
02057 {
02058
02059
02060 }
02061
02062
02063
02064 void
02065 mmix_asm_globalize_label (stream, name)
02066 FILE * stream ATTRIBUTE_UNUSED;
02067 const char * name ATTRIBUTE_UNUSED;
02068 {
02069 asm_fprintf (stream, "\t.global ");
02070 assemble_name (stream, name);
02071 putc ('\n', stream);
02072 }
02073
02074
02075
02076 void
02077 mmix_asm_weaken_label (stream, name)
02078 FILE * stream ATTRIBUTE_UNUSED;
02079 const char * name ATTRIBUTE_UNUSED;
02080 {
02081 asm_fprintf (stream, "\t.weak ");
02082 assemble_name (stream, name);
02083 asm_fprintf (stream, " ! mmixal-incompatible\n");
02084 }
02085
02086
02087
02088 void
02089 mmix_make_decl_one_only (decl)
02090 tree decl;
02091 {
02092 DECL_WEAK (decl) = 1;
02093 }
02094
02095
02096
02097
02098 void
02099 mmix_asm_output_labelref (stream, name)
02100 FILE *stream;
02101 const char *name;
02102 {
02103 int is_extern = 1;
02104
02105 for (; (*name == '@' || *name == '*'); name++)
02106 if (*name == '@')
02107 is_extern = 0;
02108
02109 asm_fprintf (stream, "%s%U%s",
02110 is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "",
02111 name);
02112 }
02113
02114
02115
02116 void
02117 mmix_asm_output_internal_label (stream, name, num)
02118 FILE * stream;
02119 const char * name;
02120 int num;
02121 {
02122 fprintf (stream, "%s:%d\tIS @\n", name, num);
02123 }
02124
02125
02126
02127 void
02128 mmix_asm_output_def (stream, name, value)
02129 FILE * stream;
02130 const char * name;
02131 const char * value;
02132 {
02133 assemble_name (stream, name);
02134 fprintf (stream, "\tIS ");
02135 assemble_name (stream, value);
02136 fputc ('\n', stream);
02137 }
02138
02139
02140
02141 void
02142 mmix_asm_output_define_label_difference_symbol (stream, symbol, hi, lo)
02143 FILE *stream;
02144 const char *symbol;
02145 const char *hi;
02146 const char *lo;
02147 {
02148 assemble_name (stream, symbol);
02149 fprintf (stream, "\tIS\t");
02150 assemble_name (stream, hi);
02151 fputc ('-', stream);
02152 assemble_name (stream, lo);
02153 fprintf (stream, "\n");
02154 }
02155
02156
02157
02158 void
02159 mmix_print_operand (stream, x, code)
02160 FILE * stream;
02161 rtx x;
02162 int code;
02163 {
02164
02165
02166 rtx modified_x = x;
02167
02168 switch (code)
02169 {
02170
02171
02172 case '+':
02173
02174 if (TARGET_BRANCH_PREDICT)
02175 {
02176 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
02177 if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2)
02178 putc ('P', stream);
02179 }
02180 return;
02181
02182 case 'B':
02183 if (GET_CODE (x) != CONST_INT)
02184 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
02185 fprintf (stream, "%d", (int) (INTVAL (x) & 0xff));
02186 return;
02187
02188 case 'H':
02189
02190
02191 if (REGNO (x) > MMIX_LAST_GENERAL_REGISTER - 1)
02192 internal_error ("MMIX Internal: Bad register: %d", REGNO (x));
02193
02194
02195 fprintf (stream, "%s", reg_names[REGNO (x)]);
02196 return;
02197
02198 case 'L':
02199
02200
02201 if (GET_CODE (x) == CONST_INT)
02202 {
02203 fprintf (stream, "#%lx",
02204 (unsigned long) (INTVAL (x)
02205 & ((unsigned int) 0x7fffffff * 2 + 1)));
02206 return;
02207 }
02208
02209 if (GET_CODE (x) == SYMBOL_REF)
02210 {
02211 output_addr_const (stream, x);
02212 return;
02213 }
02214
02215 if (REGNO (x) > MMIX_LAST_GENERAL_REGISTER - 1)
02216 internal_error ("MMIX Internal: Bad register: %d", REGNO (x));
02217
02218
02219 fprintf (stream, "%s", reg_names[REGNO (x) + 1]);
02220 return;
02221
02222
02223
02224 case 'A':
02225 mmix_output_shiftvalue_op_from_str (stream, "ANDN",
02226 ~(unsigned HOST_WIDEST_INT)
02227 mmix_intval (x));
02228 return;
02229
02230 case 'i':
02231 mmix_output_shiftvalue_op_from_str (stream, "INC",
02232 (unsigned HOST_WIDEST_INT)
02233 mmix_intval (x));
02234 return;
02235
02236 case 'o':
02237 mmix_output_shiftvalue_op_from_str (stream, "OR",
02238 (unsigned HOST_WIDEST_INT)
02239 mmix_intval (x));
02240 return;
02241
02242 case 's':
02243 mmix_output_shiftvalue_op_from_str (stream, "SET",
02244 (unsigned HOST_WIDEST_INT)
02245 mmix_intval (x));
02246 return;
02247
02248 case 'd':
02249 case 'D':
02250 mmix_output_condition (stream, x, (code == 'D'));
02251 return;
02252
02253 case 'e':
02254
02255 if (TARGET_FCMP_EPSILON)
02256 fprintf (stream, "e");
02257 return;
02258
02259 case 'm':
02260
02261 if (GET_CODE (x) != CONST_INT)
02262 {
02263 fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
02264 x);
02265 }
02266 fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,
02267 (HOST_WIDEST_INT) (mmix_intval (x) - 1));
02268 return;
02269
02270 case 'p':
02271
02272
02273
02274
02275 if (TARGET_ABI_GNU)
02276 fprintf (stream, "%d", mmix_highest_saved_stack_register + 1);
02277 else
02278
02279
02280 fprintf (stream, "15");
02281 return;
02282
02283 case 'r':
02284
02285 if (! REG_P (x))
02286 fatal_insn ("MMIX Internal: Expected a register, not this", x);
02287 mmix_output_destination_register = REGNO (x);
02288 return;
02289
02290 case 'I':
02291
02292 if (GET_CODE (x) != CONST_INT
02293 && (GET_CODE (x) != CONST_DOUBLE
02294 || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode
02295 && GET_MODE (x) != SFmode)))
02296 fatal_insn ("MMIX Internal: Expected a constant, not this", x);
02297 mmix_output_register_setting (stream,
02298 mmix_output_destination_register,
02299 mmix_intval (x), 0);
02300 return;
02301
02302 case 'U':
02303
02304 if (TARGET_ZERO_EXTEND)
02305 putc ('U', stream);
02306 return;
02307
02308 case 'v':
02309 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));
02310 return;
02311
02312 case 'V':
02313 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));
02314 return;
02315
02316 case 'W':
02317 if (GET_CODE (x) != CONST_INT)
02318 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x);
02319 fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff));
02320 return;
02321
02322 case 0:
02323
02324 break;
02325
02326 default:
02327
02328 internal_error ("MMIX Internal: Missing `%c' case in mmix_print_operand", code);
02329 }
02330
02331 switch (GET_CODE (modified_x))
02332 {
02333 case REG:
02334 if (REGNO (modified_x) >= FIRST_PSEUDO_REGISTER)
02335 internal_error ("MMIX Internal: Bad register: %d", REGNO (modified_x));
02336 fprintf (stream, "%s", reg_names[REGNO (modified_x)]);
02337 return;
02338
02339 case MEM:
02340 output_address (XEXP (modified_x, 0));
02341 return;
02342
02343 case CONST_INT:
02344
02345
02346
02347
02348
02349
02350 if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256)
02351 fprintf (stream, "%d", (int) (INTVAL (modified_x)));
02352 else
02353 fprintf (stream, "#%x",
02354 (int) (INTVAL (modified_x)) & (unsigned int) ~0);
02355 return;
02356
02357 case CONST_DOUBLE:
02358
02359 mmix_output_octa (stream, mmix_intval (modified_x), 0);
02360 return;
02361
02362 case CONST:
02363 output_addr_const (stream, modified_x);
02364 return;
02365
02366 default:
02367
02368
02369 if (CONSTANT_P (modified_x)
02370
02371
02372 || GET_CODE (modified_x) == CODE_LABEL)
02373 {
02374 output_addr_const (stream, modified_x);
02375 return;
02376 }
02377
02378
02379 fatal_insn ("MMIX Internal: Cannot decode this operand", x);
02380 }
02381 }
02382
02383
02384
02385 int
02386 mmix_print_operand_punct_valid_p (code)
02387 int code ATTRIBUTE_UNUSED;
02388 {
02389
02390 return code == '+';
02391 }
02392
02393
02394
02395 void
02396 mmix_print_operand_address (stream, x)
02397 FILE *stream;
02398 rtx x;
02399 {
02400 if (REG_P (x))
02401 {
02402
02403
02404 fprintf (stream, "%s,0",reg_names[REGNO (x)]);
02405 return;
02406 }
02407 else if (GET_CODE (x) == PLUS)
02408 {
02409 rtx x1 = XEXP (x, 0);
02410 rtx x2 = XEXP (x, 1);
02411
02412
02413 if (! REG_P (x1))
02414 {
02415 rtx tem = x1;
02416 x1 = x2;
02417 x2 = tem;
02418 }
02419
02420 if (REG_P (x1))
02421 {
02422 fprintf (stream, "%s,", reg_names[REGNO (x1)]);
02423
02424 if (REG_P (x2))
02425 {
02426 fprintf (stream, "%s", reg_names[REGNO (x2)]);
02427 return;
02428 }
02429 else if (GET_CODE (x2) == CONST_INT
02430 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
02431 {
02432 output_addr_const (stream, x2);
02433 return;
02434 }
02435 }
02436 }
02437
02438 if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x))
02439 {
02440 output_addr_const (stream, x);
02441 return;
02442 }
02443
02444 fatal_insn ("MMIX Internal: This is not a recognized address", x);
02445 }
02446
02447
02448
02449 void
02450 mmix_asm_output_reg_push (stream, regno)
02451 FILE * stream;
02452 int regno;
02453 {
02454 fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
02455 reg_names[MMIX_STACK_POINTER_REGNUM],
02456 reg_names[MMIX_STACK_POINTER_REGNUM],
02457 reg_names[regno],
02458 reg_names[MMIX_STACK_POINTER_REGNUM]);
02459 }
02460
02461
02462
02463 void
02464 mmix_asm_output_reg_pop (stream, regno)
02465 FILE * stream;
02466 int regno;
02467 {
02468 fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
02469 reg_names[regno],
02470 reg_names[MMIX_STACK_POINTER_REGNUM],
02471 reg_names[MMIX_STACK_POINTER_REGNUM]);
02472 }
02473
02474
02475
02476 void
02477 mmix_asm_output_addr_diff_elt (stream, body, value, rel)
02478 FILE *stream;
02479 rtx body ATTRIBUTE_UNUSED;
02480 int value;
02481 int rel;
02482 {
02483 fprintf (stream, "\tTETRA L%d-L%d\n", value, rel);
02484 }
02485
02486
02487
02488 void
02489 mmix_asm_output_addr_vec_elt (stream, value)
02490 FILE *stream;
02491 int value;
02492 {
02493 fprintf (stream, "\tOCTA L:%d\n", value);
02494 }
02495
02496
02497
02498 void
02499 mmix_asm_output_skip (stream, nbytes)
02500 FILE *stream;
02501 int nbytes;
02502 {
02503 fprintf (stream, "\tLOC @+%d\n", nbytes);
02504 }
02505
02506
02507
02508 void
02509 mmix_asm_output_align (stream, power)
02510 FILE *stream;
02511 int power;
02512 {
02513
02514
02515
02516
02517
02518
02519 fprintf (stream, "\t.p2align %d\n", power);
02520 fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1);
02521 }
02522
02523
02524
02525 int
02526 mmix_dbx_register_number (regno)
02527 int regno;
02528 {
02529
02530
02531
02532
02533
02534
02535
02536
02537 return regno >= 224 ? (regno - 224) : (regno + 48);
02538 }
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551 void
02552 mmix_output_register_setting (stream, regno, value, do_begin_end)
02553 FILE *stream;
02554 int regno;
02555 HOST_WIDEST_INT value;
02556 int do_begin_end;
02557 {
02558 if (do_begin_end)
02559 fprintf (stream, "\t");
02560
02561 if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value))
02562 {
02563
02564 mmix_output_shiftvalue_op_from_str (stream, "SET",
02565 (unsigned HOST_WIDEST_INT)
02566 value);
02567 fprintf (stream, " %s,", reg_names[regno]);
02568 mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value);
02569 }
02570 else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value))
02571 {
02572
02573
02574
02575 mmix_output_shiftvalue_op_from_str (stream, "SET",
02576 -(unsigned HOST_WIDEST_INT)
02577 value);
02578 fprintf (stream, " %s,", reg_names[regno]);
02579 mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value);
02580 fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
02581 reg_names[regno]);
02582 }
02583 else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value))
02584 {
02585
02586
02587
02588
02589
02590
02591
02592
02593 mmix_output_shiftvalue_op_from_str (stream, "SET",
02594 ~(unsigned HOST_WIDEST_INT)
02595 value);
02596 fprintf (stream, " %s,", reg_names[regno]);
02597 mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value);
02598 fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
02599 reg_names[regno]);
02600 }
02601 else
02602 {
02603
02604 static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
02605 const char *op = "SET";
02606 const char *line_begin = "";
02607 int insns = 0;
02608 int i;
02609 HOST_WIDEST_INT tmpvalue = value;
02610
02611
02612 for (i = 0; i < 4 && tmpvalue != 0; i++)
02613 {
02614 if (tmpvalue & 65535)
02615 insns++;
02616 tmpvalue >>= 16;
02617 }
02618 if (TARGET_BASE_ADDRESSES && insns == 3)
02619 {
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630 fprintf (stream, "LDA %s,", reg_names[regno]);
02631 mmix_output_octa (stream, value, 0);
02632 }
02633 else
02634 {
02635
02636
02637
02638 for (i = 0; i < 4 && value != 0; i++)
02639 {
02640 if (value & 65535)
02641 {
02642 fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
02643 higher_parts[i], reg_names[regno],
02644 (int) (value & 65535));
02645
02646
02647 op = "INC";
02648 line_begin = "\n\t";
02649 }
02650
02651 value >>= 16;
02652 }
02653 }
02654 }
02655
02656 if (do_begin_end)
02657 fprintf (stream, "\n");
02658 }
02659
02660
02661
02662
02663 int
02664 mmix_shiftable_wyde_value (value)
02665 unsigned HOST_WIDEST_INT value;
02666 {
02667
02668
02669 int i;
02670 int has_candidate = 0;
02671
02672 for (i = 0; i < 4; i++)
02673 {
02674 if (value & 65535)
02675 {
02676 if (has_candidate)
02677 return 0;
02678 else
02679 has_candidate = 1;
02680 }
02681
02682 value >>= 16;
02683 }
02684
02685 return 1;
02686 }
02687
02688
02689
02690 int
02691 mmix_symbolic_or_address_operand (op, mode)
02692 rtx op;
02693 enum machine_mode mode;
02694 {
02695 switch (GET_CODE (op))
02696 {
02697 case SYMBOL_REF:
02698 case LABEL_REF:
02699 return 1;
02700 case CONST:
02701 op = XEXP (op, 0);
02702 if ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
02703 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
02704 && (GET_CODE (XEXP (op, 1)) == CONST_INT
02705 || (GET_CODE (XEXP (op, 1)) == CONST_DOUBLE
02706 && GET_MODE (XEXP (op, 1)) == VOIDmode)))
02707 return 1;
02708
02709 default:
02710 return address_operand (op, mode);
02711 }
02712 }
02713
02714
02715
02716
02717
02718 int
02719 mmix_reg_or_constant_operand (op, mode)
02720 rtx op;
02721 enum machine_mode mode;
02722 {
02723 return register_operand (op, mode)
02724 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
02725 || GET_CODE (op) == CONST_INT;
02726 }
02727
02728
02729
02730 int
02731 mmix_reg_cc_operand (op, mode)
02732 rtx op;
02733 enum machine_mode mode;
02734 {
02735 if (mode == VOIDmode)
02736 mode = GET_MODE (op);
02737
02738 return register_operand (op, mode)
02739 && (mode == CCmode || mode == CC_UNSmode || mode == CC_FPmode
02740 || mode == CC_FPEQmode || mode == CC_FUNmode);
02741 }
02742
02743
02744
02745
02746
02747 int
02748 mmix_foldable_comparison_operator (op, mode)
02749 rtx op;
02750 enum machine_mode mode;
02751 {
02752 RTX_CODE code = GET_CODE (op);
02753
02754 if (mode == VOIDmode)
02755 mode = GET_MODE (op);
02756
02757 if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
02758 mode = GET_MODE (XEXP (op, 0));
02759
02760 return ((mode == CCmode || mode == DImode)
02761 && (code == NE || code == EQ || code == GE || code == GT
02762 || code == LE))
02763
02764
02765
02766
02767 || (mode == CC_UNSmode && (code == GTU || code == LEU));
02768 }
02769
02770
02771
02772
02773
02774 int
02775 mmix_comparison_operator (op, mode)
02776 rtx op;
02777 enum machine_mode mode;
02778 {
02779 RTX_CODE code = GET_CODE (op);
02780
02781
02782
02783 if (mode == VOIDmode)
02784 mode = GET_MODE (op);
02785
02786
02787 if (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
02788 mode = GET_MODE (XEXP (op, 0));
02789
02790
02791
02792 return
02793 (mode == VOIDmode && GET_RTX_CLASS (GET_CODE (op)) == '<')
02794 || (mode == CC_FUNmode
02795 && (code == ORDERED || code == UNORDERED))
02796 || (mode == CC_FPmode
02797 && (code == GT || code == LT))
02798 || (mode == CC_FPEQmode
02799 && (code == NE || code == EQ))
02800 || (mode == CC_UNSmode
02801 && (code == GEU || code == GTU || code == LEU || code == LTU))
02802 || (mode == CCmode
02803 && (code == NE || code == EQ || code == GE || code == GT
02804 || code == LE || code == LT))
02805 || (mode == DImode
02806 && (code == NE || code == EQ || code == GE || code == GT
02807 || code == LE || code == LT || code == LEU || code == GTU));
02808 }
02809
02810
02811
02812 int
02813 mmix_reg_or_0_operand (op, mode)
02814 rtx op;
02815 enum machine_mode mode;
02816 {
02817
02818 return
02819 op == CONST0_RTX (mode == VOIDmode ? GET_MODE (op) : mode)
02820 || register_operand (op, mode);
02821 }
02822
02823
02824
02825 int
02826 mmix_reg_or_8bit_operand (op, mode)
02827 rtx op;
02828 enum machine_mode mode;
02829 {
02830 return register_operand (op, mode)
02831 || (GET_CODE (op) == CONST_INT
02832 && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
02833 }
02834
02835
02836
02837
02838
02839
02840 int
02841 mmix_reg_or_8bit_or_256_operand (op, mode)
02842 rtx op;
02843 enum machine_mode mode;
02844 {
02845 return mmix_reg_or_8bit_operand (op, mode)
02846 || (GET_CODE (op) == CONST_INT && INTVAL (op) == 256);
02847 }
02848
02849
02850
02851
02852
02853 int
02854 mmix_valid_comparison (code, mode, op)
02855 RTX_CODE code;
02856 enum machine_mode mode;
02857 rtx op;
02858 {
02859 if (mode == VOIDmode && op != NULL_RTX)
02860 mode = GET_MODE (op);
02861
02862
02863 if (mode == CCmode || mode == CC_UNSmode || mode == DImode)
02864 return 1;
02865
02866 if ((mode == CC_FPmode || mode == DFmode)
02867 && (code == GT || code == LT))
02868 return 1;
02869
02870 if ((mode == CC_FPEQmode || mode == DFmode)
02871 && (code == EQ || code == NE))
02872 return 1;
02873
02874 if ((mode == CC_FUNmode || mode == DFmode)
02875 && (code == ORDERED || code == UNORDERED))
02876 return 1;
02877
02878 return 0;
02879 }
02880
02881
02882
02883
02884
02885 rtx
02886 mmix_gen_compare_reg (code, x, y)
02887 RTX_CODE code;
02888 rtx x, y;
02889 {
02890 enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
02891 rtx cc_reg;
02892
02893
02894 enum machine_mode mode
02895 = GET_MODE (x) == VOIDmode
02896 ? GET_MODE (y)
02897 : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode;
02898
02899 if (! mmix_valid_comparison (code, mode, x))
02900 return NULL_RTX;
02901
02902 cc_reg = gen_reg_rtx (ccmode);
02903
02904
02905 if (! REG_P (x) && ! REG_P (y))
02906 x = force_reg (mode, x);
02907
02908 CANONICALIZE_COMPARISON (code, x, y);
02909
02910
02911 if (! REG_P (y)
02912 && (GET_CODE (y) != CONST_INT
02913 || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I')))
02914 y = force_reg (mode, y);
02915
02916 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
02917 gen_rtx_COMPARE (ccmode, x, y)));
02918
02919 return cc_reg;
02920 }
02921
02922
02923
02924
02925
02926
02927 static void
02928 mmix_output_shiftvalue_op_from_str (stream, mainop, value)
02929 FILE *stream;
02930 const char *mainop;
02931 HOST_WIDEST_INT value;
02932 {
02933 static const char *const op_part[] = {"L", "ML", "MH", "H"};
02934 int i;
02935
02936 if (! mmix_shiftable_wyde_value (value))
02937 {
02938 char s[sizeof ("0xffffffffffffffff")];
02939 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
02940 internal_error ("MMIX Internal: %s is not a shiftable int", s);
02941 }
02942
02943 for (i = 0; i < 4; i++)
02944 {
02945
02946
02947 if (value & 0xffff)
02948 {
02949 fprintf (stream, "%s%s", mainop, op_part[i]);
02950 return;
02951 }
02952 value >>= 16;
02953 }
02954
02955
02956 fprintf (stream, "%sL", mainop);
02957 }
02958
02959
02960
02961 static void
02962 mmix_output_octa (stream, value, do_begin_end)
02963 FILE *stream;
02964 HOST_WIDEST_INT value;
02965 int do_begin_end;
02966 {
02967
02968
02969
02970
02971 char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)];
02972
02973 if (do_begin_end)
02974 fprintf (stream, "\tOCTA ");
02975
02976 strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX);
02977 hex_format[0] = '#';
02978 hex_format[1] = '0';
02979
02980
02981
02982 if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000)
02983 || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384))
02984 fprintf (stream, "%d", (int) value);
02985 else if (value > (HOST_WIDEST_INT) 0
02986 && value < ((HOST_WIDEST_INT) 1 << 31) * 2)
02987 fprintf (stream, "#%x", (unsigned int) value);
02988 else
02989 fprintf (stream, hex_format, value);
02990
02991 if (do_begin_end)
02992 fprintf (stream, "\n");
02993 }
02994
02995
02996
02997
02998 static void
02999 mmix_output_shifted_value (stream, value)
03000 FILE * stream;
03001 HOST_WIDEST_INT value;
03002 {
03003 int i;
03004
03005 if (! mmix_shiftable_wyde_value (value))
03006 {
03007 char s[16+2+1];
03008 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
03009 internal_error ("MMIX Internal: %s is not a shiftable int", s);
03010 }
03011
03012 for (i = 0; i < 4; i++)
03013 {
03014
03015 if (value & 0xffff)
03016 {
03017 fprintf (stream, "#%x", (int) (value & 0xffff));
03018 return;
03019 }
03020
03021 value >>= 16;
03022 }
03023
03024
03025 fprintf (stream, "0");
03026 }
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036 static void
03037 mmix_output_condition (stream, x, reversed)
03038 FILE *stream;
03039 rtx x;
03040 int reversed;
03041 {
03042 struct cc_conv
03043 {
03044 RTX_CODE cc;
03045
03046
03047 const char *const normal;
03048
03049
03050 const char *const reversed;
03051 };
03052
03053 struct cc_type_conv
03054 {
03055 enum machine_mode cc_mode;
03056
03057
03058 const struct cc_conv *const convs;
03059 };
03060
03061 #undef CCEND
03062 #define CCEND {NIL, NULL, NULL}
03063
03064 static const struct cc_conv cc_fun_convs[]
03065 = {{ORDERED, "Z", "P"},
03066 {UNORDERED, "P", "Z"},
03067 CCEND};
03068 static const struct cc_conv cc_fp_convs[]
03069 = {{GT, "P", NULL},
03070 {LT, "N", NULL},
03071 CCEND};
03072 static const struct cc_conv cc_fpeq_convs[]
03073 = {{NE, "Z", "P"},
03074 {EQ, "P", "Z"},
03075 CCEND};
03076 static const struct cc_conv cc_uns_convs[]
03077 = {{GEU, "NN", "N"},
03078 {GTU, "P", "NP"},
03079 {LEU, "NP", "P"},
03080 {LTU, "N", "NN"},
03081 CCEND};
03082 static const struct cc_conv cc_signed_convs[]
03083 = {{NE, "NZ", "Z"},
03084 {EQ, "Z", "NZ"},
03085 {GE, "NN", "N"},
03086 {GT, "P", "NP"},
03087 {LE, "NP", "P"},
03088 {LT, "N", "NN"},
03089 CCEND};
03090 static const struct cc_conv cc_di_convs[]
03091 = {{NE, "NZ", "Z"},
03092 {EQ, "Z", "NZ"},
03093 {GE, "NN", "N"},
03094 {GT, "P", "NP"},
03095 {LE, "NP", "P"},
03096 {LT, "N", "NN"},
03097 {GTU, "NZ", "Z"},
03098 {LEU, "Z", "NZ"},
03099 CCEND};
03100 #undef CCEND
03101
03102 static const struct cc_type_conv cc_convs[]
03103 = {{CC_FUNmode, cc_fun_convs},
03104 {CC_FPmode, cc_fp_convs},
03105 {CC_FPEQmode, cc_fpeq_convs},
03106 {CC_UNSmode, cc_uns_convs},
03107 {CCmode, cc_signed_convs},
03108 {DImode, cc_di_convs}};
03109
03110 unsigned int i;
03111 int j;
03112
03113 enum machine_mode mode = GET_MODE (XEXP (x, 0));
03114 RTX_CODE cc = GET_CODE (x);
03115
03116 for (i = 0; i < sizeof (cc_convs)/sizeof(*cc_convs); i++)
03117 {
03118 if (mode == cc_convs[i].cc_mode)
03119 {
03120 for (j = 0; cc_convs[i].convs[j].cc != NIL; j++)
03121 if (cc == cc_convs[i].convs[j].cc)
03122 {
03123 const char *mmix_cc
03124 = (reversed ? cc_convs[i].convs[j].reversed
03125 : cc_convs[i].convs[j].normal);
03126
03127 if (mmix_cc == NULL)
03128 fatal_insn ("MMIX Internal: Trying to output invalidly\
03129 reversed condition:", x);
03130
03131 fprintf (stream, "%s", mmix_cc);
03132 return;
03133 }
03134
03135 fatal_insn ("MMIX Internal: What's the CC of this?", x);
03136 }
03137 }
03138
03139 fatal_insn ("MMIX Internal: What is the CC of this?", x);
03140 }
03141
03142
03143
03144 static HOST_WIDEST_INT
03145 mmix_intval (x)
03146 rtx x;
03147 {
03148 unsigned HOST_WIDEST_INT retval;
03149
03150 if (GET_CODE (x) == CONST_INT)
03151 return INTVAL (x);
03152
03153
03154
03155
03156 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
03157 {
03158 if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT))
03159 {
03160 retval = (unsigned) CONST_DOUBLE_LOW (x) / 2;
03161 retval *= 2;
03162 retval |= CONST_DOUBLE_LOW (x) & 1;
03163
03164 retval |=
03165 (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x)
03166 << (HOST_BITS_PER_LONG);
03167 }
03168 else
03169 retval = CONST_DOUBLE_HIGH (x);
03170
03171 return retval;
03172 }
03173
03174 if (GET_CODE (x) == CONST_DOUBLE)
03175 {
03176 REAL_VALUE_TYPE value;
03177
03178
03179 REAL_VALUE_FROM_CONST_DOUBLE (value, x);
03180
03181 if (GET_MODE (x) == DFmode)
03182 {
03183 long bits[2];
03184
03185 REAL_VALUE_TO_TARGET_DOUBLE (value, bits);
03186
03187 if (sizeof (long) < sizeof (HOST_WIDEST_INT))
03188 {
03189 retval = (unsigned long) bits[1] / 2;
03190 retval *= 2;
03191 retval |= (unsigned long) bits[1] & 1;
03192 retval
03193 |= (unsigned HOST_WIDEST_INT) bits[0]
03194 << (sizeof (bits[0]) * 8);
03195 }
03196 else
03197 retval = (unsigned long) bits[1];
03198
03199 return retval;
03200 }
03201 else if (GET_MODE (x) == SFmode)
03202 {
03203 long bits;
03204 REAL_VALUE_TO_TARGET_SINGLE (value, bits);
03205
03206 return (unsigned long) bits;
03207 }
03208 }
03209
03210 fatal_insn ("MMIX Internal: This is not a constant:", x);
03211 }
03212
03213
03214
03215
03216
03217
03218