Mercurial > hg > CbC > CbC_gcc
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" |