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