comparison gcc/config/m68k/m68k.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Subroutines for insn-output.c for Motorola 68000 family. 1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987-2017 Free Software Foundation, Inc. 2 Copyright (C) 1987-2018 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify 6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
14 GNU General Public License for more details. 14 GNU General Public License for more details.
15 15
16 You should have received a copy of the GNU General Public License 16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see 17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */ 18 <http://www.gnu.org/licenses/>. */
19
20 #define IN_TARGET_CODE 1
19 21
20 #include "config.h" 22 #include "config.h"
21 #include "system.h" 23 #include "system.h"
22 #include "coretypes.h" 24 #include "coretypes.h"
23 #include "backend.h" 25 #include "backend.h"
61 #include "insn-codes.h" 63 #include "insn-codes.h"
62 #include "opts.h" 64 #include "opts.h"
63 #include "optabs.h" 65 #include "optabs.h"
64 #include "builtins.h" 66 #include "builtins.h"
65 #include "rtl-iter.h" 67 #include "rtl-iter.h"
68 #include "toplev.h"
66 69
67 /* This file should be included last. */ 70 /* This file should be included last. */
68 #include "target-def.h" 71 #include "target-def.h"
69 72
70 enum reg_class regno_reg_class[] = 73 enum reg_class regno_reg_class[] =
174 #if M68K_HONOR_TARGET_STRICT_ALIGNMENT 177 #if M68K_HONOR_TARGET_STRICT_ALIGNMENT
175 static bool m68k_return_in_memory (const_tree, const_tree); 178 static bool m68k_return_in_memory (const_tree, const_tree);
176 #endif 179 #endif
177 static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; 180 static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
178 static void m68k_trampoline_init (rtx, tree, rtx); 181 static void m68k_trampoline_init (rtx, tree, rtx);
179 static int m68k_return_pops_args (tree, tree, int); 182 static poly_int64 m68k_return_pops_args (tree, tree, poly_int64);
180 static rtx m68k_delegitimize_address (rtx); 183 static rtx m68k_delegitimize_address (rtx);
181 static void m68k_function_arg_advance (cumulative_args_t, machine_mode, 184 static void m68k_function_arg_advance (cumulative_args_t, machine_mode,
182 const_tree, bool); 185 const_tree, bool);
183 static rtx m68k_function_arg (cumulative_args_t, machine_mode, 186 static rtx m68k_function_arg (cumulative_args_t, machine_mode,
184 const_tree, bool); 187 const_tree, bool);
188 static enum flt_eval_method 191 static enum flt_eval_method
189 m68k_excess_precision (enum excess_precision_type); 192 m68k_excess_precision (enum excess_precision_type);
190 static unsigned int m68k_hard_regno_nregs (unsigned int, machine_mode); 193 static unsigned int m68k_hard_regno_nregs (unsigned int, machine_mode);
191 static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode); 194 static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode);
192 static bool m68k_modes_tieable_p (machine_mode, machine_mode); 195 static bool m68k_modes_tieable_p (machine_mode, machine_mode);
196 static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
197 int *, const_tree, int);
193 198
194 /* Initialize the GCC target structure. */ 199 /* Initialize the GCC target structure. */
195 200
196 #if INT_OP_GROUP == INT_OP_DOT_WORD 201 #if INT_OP_GROUP == INT_OP_DOT_WORD
197 #undef TARGET_ASM_ALIGNED_HI_OP 202 #undef TARGET_ASM_ALIGNED_HI_OP
343 #define TARGET_HARD_REGNO_MODE_OK m68k_hard_regno_mode_ok 348 #define TARGET_HARD_REGNO_MODE_OK m68k_hard_regno_mode_ok
344 349
345 #undef TARGET_MODES_TIEABLE_P 350 #undef TARGET_MODES_TIEABLE_P
346 #define TARGET_MODES_TIEABLE_P m68k_modes_tieable_p 351 #define TARGET_MODES_TIEABLE_P m68k_modes_tieable_p
347 352
353 #undef TARGET_PROMOTE_FUNCTION_MODE
354 #define TARGET_PROMOTE_FUNCTION_MODE m68k_promote_function_mode
355
356 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
357 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
358
348 static const struct attribute_spec m68k_attribute_table[] = 359 static const struct attribute_spec m68k_attribute_table[] =
349 { 360 {
350 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, 361 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
351 affects_type_identity } */ 362 affects_type_identity, handler, exclude } */
352 { "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute, 363 { "interrupt", 0, 0, true, false, false, false,
353 false }, 364 m68k_handle_fndecl_attribute, NULL },
354 { "interrupt_handler", 0, 0, true, false, false, 365 { "interrupt_handler", 0, 0, true, false, false, false,
355 m68k_handle_fndecl_attribute, false }, 366 m68k_handle_fndecl_attribute, NULL },
356 { "interrupt_thread", 0, 0, true, false, false, 367 { "interrupt_thread", 0, 0, true, false, false, false,
357 m68k_handle_fndecl_attribute, false }, 368 m68k_handle_fndecl_attribute, NULL },
358 { NULL, 0, 0, false, false, false, NULL, false } 369 { NULL, 0, 0, false, false, false, false, NULL, NULL }
359 }; 370 };
360 371
361 struct gcc_target targetm = TARGET_INITIALIZER; 372 struct gcc_target targetm = TARGET_INITIALIZER;
362 373
363 /* Base flags for 68k ISAs. */ 374 /* Base flags for 68k ISAs. */
642 default: 653 default:
643 gcc_unreachable (); 654 gcc_unreachable ();
644 } 655 }
645 656
646 #ifndef ASM_OUTPUT_ALIGN_WITH_NOP 657 #ifndef ASM_OUTPUT_ALIGN_WITH_NOP
647 if (align_labels > 2) 658 parse_alignment_opts ();
648 { 659 int label_alignment = align_labels.levels[0].get_value ();
649 warning (0, "-falign-labels=%d is not supported", align_labels); 660 if (label_alignment > 2)
650 align_labels = 0; 661 {
651 } 662 warning (0, "-falign-labels=%d is not supported", label_alignment);
652 if (align_loops > 2) 663 str_align_labels = "1";
653 { 664 }
654 warning (0, "-falign-loops=%d is not supported", align_loops); 665
655 align_loops = 0; 666 int loop_alignment = align_loops.levels[0].get_value ();
667 if (loop_alignment > 2)
668 {
669 warning (0, "-falign-loops=%d is not supported", loop_alignment);
670 str_align_loops = "1";
656 } 671 }
657 #endif 672 #endif
658 673
659 if ((opt_fstack_limit_symbol_arg != NULL || opt_fstack_limit_register_no >= 0) 674 if ((opt_fstack_limit_symbol_arg != NULL || opt_fstack_limit_register_no >= 0)
660 && !TARGET_68020) 675 && !TARGET_68020)
2312 m68k_unwrap_symbol (rtx orig, bool unwrap_reloc32_p) 2327 m68k_unwrap_symbol (rtx orig, bool unwrap_reloc32_p)
2313 { 2328 {
2314 return m68k_unwrap_symbol_1 (orig, unwrap_reloc32_p, NULL); 2329 return m68k_unwrap_symbol_1 (orig, unwrap_reloc32_p, NULL);
2315 } 2330 }
2316 2331
2317 /* Prescan insn before outputing assembler for it. */ 2332 /* Adjust decorated address operand before outputing assembler for it. */
2318 2333
2319 void 2334 static void
2320 m68k_final_prescan_insn (rtx_insn *insn ATTRIBUTE_UNUSED, 2335 m68k_adjust_decorated_operand (rtx op)
2321 rtx *operands, int n_operands) 2336 {
2322 {
2323 int i;
2324
2325 /* Combine and, possibly, other optimizations may do good job 2337 /* Combine and, possibly, other optimizations may do good job
2326 converting 2338 converting
2327 (const (unspec [(symbol)])) 2339 (const (unspec [(symbol)]))
2328 into 2340 into
2329 (const (plus (unspec [(symbol)]) 2341 (const (plus (unspec [(symbol)])
2338 (const_int N))])). 2350 (const_int N))])).
2339 Note, that the top level of operand remains intact, so we don't have 2351 Note, that the top level of operand remains intact, so we don't have
2340 to patch up anything outside of the operand. */ 2352 to patch up anything outside of the operand. */
2341 2353
2342 subrtx_var_iterator::array_type array; 2354 subrtx_var_iterator::array_type array;
2343 for (i = 0; i < n_operands; ++i) 2355 FOR_EACH_SUBRTX_VAR (iter, array, op, ALL)
2344 { 2356 {
2345 rtx op; 2357 rtx x = *iter;
2346 2358 if (m68k_unwrap_symbol (x, true) != x)
2347 op = operands[i]; 2359 {
2348 2360 rtx plus;
2349 FOR_EACH_SUBRTX_VAR (iter, array, op, ALL) 2361
2350 { 2362 gcc_assert (GET_CODE (x) == CONST);
2351 rtx x = *iter; 2363 plus = XEXP (x, 0);
2352 if (m68k_unwrap_symbol (x, true) != x) 2364
2365 if (GET_CODE (plus) == PLUS || GET_CODE (plus) == MINUS)
2353 { 2366 {
2354 rtx plus; 2367 rtx unspec;
2355 2368 rtx addend;
2356 gcc_assert (GET_CODE (x) == CONST); 2369
2357 plus = XEXP (x, 0); 2370 unspec = XEXP (plus, 0);
2358 2371 gcc_assert (GET_CODE (unspec) == UNSPEC);
2359 if (GET_CODE (plus) == PLUS || GET_CODE (plus) == MINUS) 2372 addend = XEXP (plus, 1);
2360 { 2373 gcc_assert (CONST_INT_P (addend));
2361 rtx unspec; 2374
2362 rtx addend; 2375 /* We now have all the pieces, rearrange them. */
2363 2376
2364 unspec = XEXP (plus, 0); 2377 /* Move symbol to plus. */
2365 gcc_assert (GET_CODE (unspec) == UNSPEC); 2378 XEXP (plus, 0) = XVECEXP (unspec, 0, 0);
2366 addend = XEXP (plus, 1); 2379
2367 gcc_assert (CONST_INT_P (addend)); 2380 /* Move plus inside unspec. */
2368 2381 XVECEXP (unspec, 0, 0) = plus;
2369 /* We now have all the pieces, rearrange them. */ 2382
2370 2383 /* Move unspec to top level of const. */
2371 /* Move symbol to plus. */ 2384 XEXP (x, 0) = unspec;
2372 XEXP (plus, 0) = XVECEXP (unspec, 0, 0);
2373
2374 /* Move plus inside unspec. */
2375 XVECEXP (unspec, 0, 0) = plus;
2376
2377 /* Move unspec to top level of const. */
2378 XEXP (x, 0) = unspec;
2379 }
2380 iter.skip_subrtxes ();
2381 } 2385 }
2386 iter.skip_subrtxes ();
2382 } 2387 }
2383 } 2388 }
2384 } 2389 }
2385 2390
2386 /* Move X to a register and add REG_EQUAL note pointing to ORIG. 2391 /* Move X to a register and add REG_EQUAL note pointing to ORIG.
3479 return; 3484 return;
3480 } 3485 }
3481 3486
3482 /* Normal case: do the two words, low-numbered first. */ 3487 /* Normal case: do the two words, low-numbered first. */
3483 3488
3484 m68k_final_prescan_insn (NULL, operands, 2);
3485 handle_movsi (operands); 3489 handle_movsi (operands);
3486 3490
3487 /* Do the middle one of the three words for long double */ 3491 /* Do the middle one of the three words for long double */
3488 if (size == 12) 3492 if (size == 12)
3489 { 3493 {
3490 if (addreg0) 3494 if (addreg0)
3491 handle_reg_adjust (addreg0, 4); 3495 handle_reg_adjust (addreg0, 4);
3492 if (addreg1) 3496 if (addreg1)
3493 handle_reg_adjust (addreg1, 4); 3497 handle_reg_adjust (addreg1, 4);
3494 3498
3495 m68k_final_prescan_insn (NULL, middlehalf, 2);
3496 handle_movsi (middlehalf); 3499 handle_movsi (middlehalf);
3497 } 3500 }
3498 3501
3499 /* Make any unoffsettable addresses point at high-numbered word. */ 3502 /* Make any unoffsettable addresses point at high-numbered word. */
3500 if (addreg0) 3503 if (addreg0)
3501 handle_reg_adjust (addreg0, 4); 3504 handle_reg_adjust (addreg0, 4);
3502 if (addreg1) 3505 if (addreg1)
3503 handle_reg_adjust (addreg1, 4); 3506 handle_reg_adjust (addreg1, 4);
3504 3507
3505 /* Do that word. */ 3508 /* Do that word. */
3506 m68k_final_prescan_insn (NULL, latehalf, 2);
3507 handle_movsi (latehalf); 3509 handle_movsi (latehalf);
3508 3510
3509 /* Undo the adds we just did. */ 3511 /* Undo the adds we just did. */
3510 if (addreg0) 3512 if (addreg0)
3511 handle_reg_adjust (addreg0, -(size - 4)); 3513 handle_reg_adjust (addreg0, -(size - 4));
3519 static void 3521 static void
3520 output_reg_adjust (rtx reg, int n) 3522 output_reg_adjust (rtx reg, int n)
3521 { 3523 {
3522 const char *s; 3524 const char *s;
3523 3525
3524 gcc_assert (GET_MODE (reg) == SImode 3526 gcc_assert (GET_MODE (reg) == SImode && n >= -12 && n != 0 && n <= 12);
3525 && -12 <= n && n != 0 && n <= 12);
3526 3527
3527 switch (n) 3528 switch (n)
3528 { 3529 {
3529 case 12: 3530 case 12:
3530 s = "add%.l #12,%0"; 3531 s = "add%.l #12,%0";
3562 static void 3563 static void
3563 emit_reg_adjust (rtx reg1, int n) 3564 emit_reg_adjust (rtx reg1, int n)
3564 { 3565 {
3565 rtx reg2; 3566 rtx reg2;
3566 3567
3567 gcc_assert (GET_MODE (reg1) == SImode 3568 gcc_assert (GET_MODE (reg1) == SImode && n >= -12 && n != 0 && n <= 12);
3568 && -12 <= n && n != 0 && n <= 12);
3569 3569
3570 reg1 = copy_rtx (reg1); 3570 reg1 = copy_rtx (reg1);
3571 reg2 = copy_rtx (reg1); 3571 reg2 = copy_rtx (reg1);
3572 3572
3573 if (n < 0) 3573 if (n < 0)
4449 is not locally-bound. */ 4449 is not locally-bound. */
4450 4450
4451 void 4451 void
4452 print_operand (FILE *file, rtx op, int letter) 4452 print_operand (FILE *file, rtx op, int letter)
4453 { 4453 {
4454 if (op != NULL_RTX)
4455 m68k_adjust_decorated_operand (op);
4456
4454 if (letter == '.') 4457 if (letter == '.')
4455 { 4458 {
4456 if (MOTOROLA) 4459 if (MOTOROLA)
4457 fprintf (file, "."); 4460 fprintf (file, ".");
4458 } 4461 }
4696 4699
4697 void 4700 void
4698 print_operand_address (FILE *file, rtx addr) 4701 print_operand_address (FILE *file, rtx addr)
4699 { 4702 {
4700 struct m68k_address address; 4703 struct m68k_address address;
4704
4705 m68k_adjust_decorated_operand (addr);
4701 4706
4702 if (!m68k_decompose_address (QImode, addr, true, &address)) 4707 if (!m68k_decompose_address (QImode, addr, true, &address))
4703 gcc_unreachable (); 4708 gcc_unreachable ();
4704 4709
4705 if (address.code == PRE_DEC) 4710 if (address.code == PRE_DEC)
6529 because the library is compiled with the Unix compiler. 6534 because the library is compiled with the Unix compiler.
6530 Use of RTD is a selectable option, since it is incompatible with 6535 Use of RTD is a selectable option, since it is incompatible with
6531 standard Unix calling sequences. If the option is not selected, 6536 standard Unix calling sequences. If the option is not selected,
6532 the caller must always pop the args. */ 6537 the caller must always pop the args. */
6533 6538
6534 static int 6539 static poly_int64
6535 m68k_return_pops_args (tree fundecl, tree funtype, int size) 6540 m68k_return_pops_args (tree fundecl, tree funtype, poly_int64 size)
6536 { 6541 {
6537 return ((TARGET_RTD 6542 return ((TARGET_RTD
6538 && (!fundecl 6543 && (!fundecl
6539 || TREE_CODE (fundecl) != IDENTIFIER_NODE) 6544 || TREE_CODE (fundecl) != IDENTIFIER_NODE)
6540 && (!stdarg_p (funtype))) 6545 && (!stdarg_p (funtype)))
6541 ? size : 0); 6546 ? (HOST_WIDE_INT) size : 0);
6542 } 6547 }
6543 6548
6544 /* Make sure everything's fine if we *don't* have a given processor. 6549 /* Make sure everything's fine if we *don't* have a given processor.
6545 This assumes that putting a register in fixed_regs will keep the 6550 This assumes that putting a register in fixed_regs will keep the
6546 compiler's mitts completely off it. We don't bother to zero it out 6551 compiler's mitts completely off it. We don't bother to zero it out
6608 gcc_unreachable (); 6613 gcc_unreachable ();
6609 } 6614 }
6610 return FLT_EVAL_METHOD_UNPREDICTABLE; 6615 return FLT_EVAL_METHOD_UNPREDICTABLE;
6611 } 6616 }
6612 6617
6618 /* Implement PUSH_ROUNDING. On the 680x0, sp@- in a byte insn really pushes
6619 a word. On the ColdFire, sp@- in a byte insn pushes just a byte. */
6620
6621 poly_int64
6622 m68k_push_rounding (poly_int64 bytes)
6623 {
6624 if (TARGET_COLDFIRE)
6625 return bytes;
6626 return (bytes + 1) & ~1;
6627 }
6628
6629 /* Implement TARGET_PROMOTE_FUNCTION_MODE. */
6630
6631 static machine_mode
6632 m68k_promote_function_mode (const_tree type, machine_mode mode,
6633 int *punsignedp ATTRIBUTE_UNUSED,
6634 const_tree fntype ATTRIBUTE_UNUSED,
6635 int for_return)
6636 {
6637 /* Promote libcall arguments narrower than int to match the normal C
6638 ABI (for which promotions are handled via
6639 TARGET_PROMOTE_PROTOTYPES). */
6640 if (type == NULL_TREE && !for_return && (mode == QImode || mode == HImode))
6641 return SImode;
6642 return mode;
6643 }
6644
6613 #include "gt-m68k.h" 6645 #include "gt-m68k.h"