From b0e005d4d04c555d622100047c7ee5d3a7cbf504 Mon Sep 17 00:00:00 2001 From: Nathan Korth Date: Tue, 23 Aug 2022 23:24:11 -0400 Subject: [PATCH] m68k-palm-elf-gcc: new port This is a toolchain for building Palm OS apps. It consists of the Retro68 fork of gcc 9.1.0, with a few patches from dmitrygr. --- palm/m68k-palm-elf-binutils/Portfile | 12 + palm/m68k-palm-elf-gcc/Portfile | 20 + palm/m68k-palm-elf-gcc/files/aarch64.diff | 86 + palm/m68k-palm-elf-gcc/files/palm.diff | 182 ++ palm/m68k-palm-elf-gcc/files/retro68.diff | 2547 +++++++++++++++++++++ 5 files changed, 2847 insertions(+) create mode 100644 palm/m68k-palm-elf-binutils/Portfile create mode 100644 palm/m68k-palm-elf-gcc/Portfile create mode 100644 palm/m68k-palm-elf-gcc/files/aarch64.diff create mode 100644 palm/m68k-palm-elf-gcc/files/palm.diff create mode 100644 palm/m68k-palm-elf-gcc/files/retro68.diff diff --git a/palm/m68k-palm-elf-binutils/Portfile b/palm/m68k-palm-elf-binutils/Portfile new file mode 100644 index 0000000000000..4310d18183339 --- /dev/null +++ b/palm/m68k-palm-elf-binutils/Portfile @@ -0,0 +1,12 @@ +# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 + +PortSystem 1.0 +PortGroup crossbinutils 1.0 + +crossbinutils.setup m68k-palm-elf 2.37 +revision 0 +categories palm cross + +maintainers {@nkorth nkorth.com:nkorth} openmaintainer + +configure.args-append --disable-werror diff --git a/palm/m68k-palm-elf-gcc/Portfile b/palm/m68k-palm-elf-gcc/Portfile new file mode 100644 index 0000000000000..96b634fe43593 --- /dev/null +++ b/palm/m68k-palm-elf-gcc/Portfile @@ -0,0 +1,20 @@ +# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 + +PortSystem 1.0 +PortGroup crossgcc 1.0 + +crossgcc.setup m68k-palm-elf 9.1.0 +crossgcc.languages c +revision 0 +maintainers {@nkorth nkorth.com:nkorth} openmaintainer +categories palm cross + + +patch.pre_args -p1 +patchfiles retro68.diff \ + palm.diff \ + aarch64.diff + +# palm specific config +configure.args-delete --enable-multilib +configure.args-append --disable-multilib --disable-libssp --with-arch=m68k --with-cpu=m68000 diff --git a/palm/m68k-palm-elf-gcc/files/aarch64.diff b/palm/m68k-palm-elf-gcc/files/aarch64.diff new file mode 100644 index 0000000000000..64b7ff85d5ca7 --- /dev/null +++ b/palm/m68k-palm-elf-gcc/files/aarch64.diff @@ -0,0 +1,86 @@ +diff --git a/config.guess b/config.guess +index 8e2a58b86..772577d8d 100755 +--- a/config.guess ++++ b/config.guess +@@ -1309,6 +1309,9 @@ EOF + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; ++ arm64:Darwin:*:*) ++ echo aarch64-apple-darwin"$UNAME_RELEASE" ++ exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + set_cc_for_build +diff --git a/gcc/config.host b/gcc/config.host +index 816a0f06c..adaa50b73 100644 +--- a/gcc/config.host ++++ b/gcc/config.host +@@ -99,7 +99,8 @@ case ${host} in + esac + + case ${host} in +- aarch64*-*-freebsd* | aarch64*-*-linux* | aarch64*-*-fuchsia*) ++ aarch64*-*-freebsd* | aarch64*-*-linux* | aarch64*-*-fuchsia* |\ ++ aarch64*-*-darwin*) + case ${target} in + aarch64*-*-*) + host_extra_gcc_objs="driver-aarch64.o" +@@ -263,6 +264,10 @@ case ${host} in + out_host_hook_obj="${out_host_hook_obj} host-ppc64-darwin.o" + host_xmake_file="${host_xmake_file} rs6000/x-darwin64" + ;; ++ aarch64-*-darwin*) ++ out_host_hook_obj="${out_host_hook_obj} host-aarch64-darwin.o" ++ host_xmake_file="${host_xmake_file} aarch64/x-darwin" ++ ;; + rs6000-ibm-aix* | powerpc-ibm-aix*) + host_xmake_file="${host_xmake_file} rs6000/x-aix" + ;; +diff --git a/gcc/config/aarch64/host-aarch64-darwin.c b/gcc/config/aarch64/host-aarch64-darwin.c +new file mode 100644 +index 000000000..5ed81cf7d +--- /dev/null ++++ b/gcc/config/aarch64/host-aarch64-darwin.c +@@ -0,0 +1,32 @@ ++/* i386-darwin host-specific hook definitions. ++ Copyright (C) 2003-2019 Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify it under ++the terms of the GNU General Public License as published by the Free ++Software Foundation; either version 3, or (at your option) any later ++version. ++ ++GCC is distributed in the hope that it will be useful, but WITHOUT ANY ++WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++for more details. ++ ++You should have received a copy of the GNU General Public License ++along with GCC; see the file COPYING3. If not see ++. */ ++ ++#define IN_TARGET_CODE 1 ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "hosthooks.h" ++#include "hosthooks-def.h" ++#include "config/host-darwin.h" ++ ++/* Darwin doesn't do anything special for aarch64 hosts; this file exists just ++ to include config/host-darwin.h. */ ++ ++const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; +diff --git a/gcc/config/aarch64/x-darwin b/gcc/config/aarch64/x-darwin +new file mode 100644 +index 000000000..6d788d5e8 +--- /dev/null ++++ b/gcc/config/aarch64/x-darwin +@@ -0,0 +1,3 @@ ++host-aarch64-darwin.o : $(srcdir)/config/aarch64/host-aarch64-darwin.c ++ $(COMPILE) $< ++ $(POSTCOMPILE) diff --git a/palm/m68k-palm-elf-gcc/files/palm.diff b/palm/m68k-palm-elf-gcc/files/palm.diff new file mode 100644 index 0000000000000..19049cf37eca4 --- /dev/null +++ b/palm/m68k-palm-elf-gcc/files/palm.diff @@ -0,0 +1,182 @@ +diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c +index 03dca31e7..c46a3a151 100644 +--- a/gcc/c-family/c-lex.c ++++ b/gcc/c-family/c-lex.c +@@ -1353,10 +1353,15 @@ lex_charconst (const cpp_token *token) + } + /* In C, a character constant has type 'int'. + In C++ 'char', but multi-char charconsts have type 'int'. */ +- else if (!c_dialect_cxx () || chars_seen > 1) +- type = integer_type_node; +- else ++ else if (c_dialect_cxx ()) + type = char_type_node; ++ else if (chars_seen > 2) ++ type = long_unsigned_type_node; ++ else if (chars_seen > 1) ++ type = unsigned_type_node; ++ else ++ type = integer_type_node; ++ + + /* Cast to cppchar_signed_t to get correct sign-extension of RESULT + before possibly widening to HOST_WIDE_INT for build_int_cst. */ +diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c +index fbc734a04..5f8c75086 100644 +--- a/gcc/c-family/c-pragma.c ++++ b/gcc/c-family/c-pragma.c +@@ -1557,7 +1557,7 @@ init_pragma (void) + c_register_pragma_with_expansion (0, "message", handle_pragma_message); + + #ifdef REGISTER_TARGET_PRAGMAS +- REGISTER_TARGET_PRAGMAS (); ++// REGISTER_TARGET_PRAGMAS (); + #endif + + global_sso = default_sso; +diff --git a/gcc/calls.c b/gcc/calls.c +index 3d5af427d..b0ce7d4ac 100644 +--- a/gcc/calls.c ++++ b/gcc/calls.c +@@ -4092,7 +4092,7 @@ expand_call (tree exp, rtx target, int ignore) + + if (is_pascal) + { +- auto pascal_return_mode = TYPE_MODE (TREE_TYPE (funtype)); ++ machine_mode pascal_return_mode = TYPE_MODE (TREE_TYPE (funtype)); + poly_uint16 modesize = GET_MODE_SIZE (pascal_return_mode); + #ifdef PUSH_ROUNDING + modesize = PUSH_ROUNDING (modesize); +diff --git a/gcc/config.gcc b/gcc/config.gcc +index 19fc2b6fc..904f58ee5 100644 +--- a/gcc/config.gcc ++++ b/gcc/config.gcc +@@ -456,8 +456,6 @@ m32r*-*-*) + m68k-*-*) + extra_headers=math-68881.h + extra_options="${extra_options} m68k/m68k-tables.opt" +- c_target_objs="m68k-mac-pragmas.o" +- cxx_target_objs="m68k-mac-pragmas.o" + ;; + microblaze*-*-*) + cpu_type=microblaze +diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c +index d66ea01a9..b10a1ebf2 100644 +--- a/gcc/config/m68k/m68k.c ++++ b/gcc/config/m68k/m68k.c +@@ -5537,9 +5537,9 @@ m68k_function_value (const_tree valtype, const_tree func_decl_or_type, bool outg + break; + } + +-#if 1 /* POINTERS_IN_D0 */ ++#if 0 /* POINTERS_IN_D0 */ + return gen_rtx_REG (mode, D0_REG); +-#else ++ + /* If the function returns a pointer, push that into %a0. */ + if (type && POINTER_TYPE_P (TREE_TYPE (type)) && !outgoing) + /* For compatibility with the large body of existing code which +@@ -5558,7 +5558,9 @@ m68k_function_value (const_tree valtype, const_tree func_decl_or_type, bool outg + gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (mode, D0_REG), + const0_rtx))); +- else if (POINTER_TYPE_P (valtype)) ++ else ++#else ++ if (POINTER_TYPE_P (valtype)) + return gen_rtx_REG (mode, A0_REG); + else + return gen_rtx_REG (mode, D0_REG); +diff --git a/libcpp/charset.c b/libcpp/charset.c +index 67eddcc7f..452143631 100644 +--- a/libcpp/charset.c ++++ b/libcpp/charset.c +@@ -1796,7 +1796,7 @@ narrow_str_to_charconst (cpp_reader *pfile, cpp_string str, + unsigned int *pchars_seen, int *unsignedp) + { + size_t width = CPP_OPTION (pfile, char_precision); +- size_t max_chars = CPP_OPTION (pfile, int_precision) / width; ++ size_t max_chars = 4; + size_t mask = width_to_mask (width); + size_t i; + cppchar_t result, c; +@@ -1831,9 +1831,9 @@ narrow_str_to_charconst (cpp_reader *pfile, cpp_string str, + else if (i > 1 && i != 4 && CPP_OPTION (pfile, warn_multichar)) + cpp_warning (pfile, CPP_W_MULTICHAR, "multi-character character constant"); + +- /* Multichar constants are of type int and therefore signed. */ ++ /* Multichar constants are of type UNSIGNED LONG for PALMOS. */ + if (i > 1) +- unsigned_p = 0; ++ unsigned_p = 1; + else + unsigned_p = CPP_OPTION (pfile, unsigned_char); + +@@ -1841,8 +1841,10 @@ narrow_str_to_charconst (cpp_reader *pfile, cpp_string str, + sign- or zero-extend to the full width of cppchar_t. + For single-character constants, the value is WIDTH bits wide. + For multi-character constants, the value is INT_PRECISION bits wide. */ +- if (i > 1) +- width = CPP_OPTION (pfile, int_precision); ++ if (i > 2) //3-4 char sequences are long, 2-char seq is short ++ width = 32; ++ else if (i > 1) ++ width = 16; + if (width < BITS_PER_CPPCHAR_T) + { + mask = ((cppchar_t) 1 << width) - 1; +diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in +index ea390a5bb..2b4eb8601 100644 +--- a/libgcc/Makefile.in ++++ b/libgcc/Makefile.in +@@ -246,7 +246,8 @@ LIBGCC2_DEBUG_CFLAGS = -g + LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ + $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \ + -fbuilding-libgcc -fno-stack-protector \ +- $(INHIBIT_LIBC_CFLAGS) ++ -ffunction-sections \ ++ $(INHIBIT_LIBC_CFLAGS) -mpcrel -fpic + + # Additional options to use when compiling libgcc2.a. + # Some targets override this to -isystem include +@@ -441,10 +442,13 @@ lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2 \ + _negvsi2 _negvdi2 _ctors _ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 \ + _ctzsi2 _ctzdi2 _popcount_tab _popcountsi2 _popcountdi2 \ + _paritysi2 _paritydi2 _powisf2 _powidf2 _powixf2 _powitf2 \ +- _mulhc3 _mulsc3 _muldc3 _mulxc3 _multc3 _divhc3 _divsc3 \ +- _divdc3 _divxc3 _divtc3 _bswapsi2 _bswapdi2 _clrsbsi2 \ ++ _bswapsi2 _bswapdi2 _clrsbsi2 \ + _clrsbdi2 + ++# complex shit we do not support (gcc bugs cause compile failure) ++#lib2funcs += _mulhc3 _mulsc3 _muldc3 _mulxc3 _multc3 _divhc3 _divsc3 \ ++# _divdc3 _divxc3 _divtc3 ++ + # The floating-point conversion routines that involve a single-word integer. + # XX stands for the integer mode. + swfloatfuncs = $(patsubst %,_fixuns%XX,sf df xf) +diff --git a/libgcc/config/m68k/lb1sf68.S b/libgcc/config/m68k/lb1sf68.S +index c38721122..2bd998c2e 100644 +--- a/libgcc/config/m68k/lb1sf68.S ++++ b/libgcc/config/m68k/lb1sf68.S +@@ -97,16 +97,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * a little on this and in the PIC case, we use short offset branches and + * hope that the final object code is within range (which it should be). + */ ++ ++ + #ifndef __PIC__ + + /* Non PIC (absolute/relocatable) versions */ + + .macro PICCALL addr +- jbsr \addr ++ bsr \addr + .endm + + .macro PICJUMP addr +- jmp \addr ++ bra \addr + .endm + + .macro PICLEA sym, reg diff --git a/palm/m68k-palm-elf-gcc/files/retro68.diff b/palm/m68k-palm-elf-gcc/files/retro68.diff new file mode 100644 index 0000000000000..72040a7dd4549 --- /dev/null +++ b/palm/m68k-palm-elf-gcc/files/retro68.diff @@ -0,0 +1,2547 @@ +diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c +index 99ca1ad37..cfb07f12c 100644 +--- a/gcc/c-family/c-common.c ++++ b/gcc/c-family/c-common.c +@@ -753,6 +753,11 @@ fix_string_type (tree value) + charsz = 1; + e_type = char_type_node; + } ++ else if (TREE_TYPE (value) == uchar_array_type_node) ++ { ++ charsz = 1; ++ e_type = unsigned_char_type_node; ++ } + else if (flag_char8_t && TREE_TYPE (value) == char8_array_type_node) + { + charsz = TYPE_PRECISION (char8_type_node) / BITS_PER_UNIT; +@@ -4254,6 +4259,12 @@ c_common_nodes_and_builtins (void) + char_array_type_node + = build_array_type (char_type_node, array_domain_type); + ++ /* Make a type for arrays of unsigned characters. ++ Needed for "\ppascal string" support. */ ++ uchar_array_type_node ++ = build_array_type (unsigned_char_type_node, array_domain_type); ++ ++ + string_type_node = build_pointer_type (char_type_node); + const_string_type_node + = build_pointer_type (build_qualified_type +diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h +index 1cf2cae63..e695b49e4 100644 +--- a/gcc/c-family/c-common.h ++++ b/gcc/c-family/c-common.h +@@ -334,6 +334,7 @@ enum c_tree_index + CTI_UINTPTR_TYPE, + + CTI_CHAR_ARRAY_TYPE, ++ CTI_UCHAR_ARRAY_TYPE, + CTI_CHAR8_ARRAY_TYPE, + CTI_CHAR16_ARRAY_TYPE, + CTI_CHAR32_ARRAY_TYPE, +@@ -483,6 +484,7 @@ extern const unsigned int num_c_common_reswords; + #define truthvalue_false_node c_global_trees[CTI_TRUTHVALUE_FALSE] + + #define char_array_type_node c_global_trees[CTI_CHAR_ARRAY_TYPE] ++#define uchar_array_type_node c_global_trees[CTI_UCHAR_ARRAY_TYPE] + #define char8_array_type_node c_global_trees[CTI_CHAR8_ARRAY_TYPE] + #define char16_array_type_node c_global_trees[CTI_CHAR16_ARRAY_TYPE] + #define char32_array_type_node c_global_trees[CTI_CHAR32_ARRAY_TYPE] +diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c +index 0a368a33a..03dca31e7 100644 +--- a/gcc/c-family/c-lex.c ++++ b/gcc/c-family/c-lex.c +@@ -1166,6 +1166,8 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) + zero '@' before each string. */ + bool objc_at_sign_was_seen = false; + ++ bool pascal_string = false; ++ + retry: + tok = cpp_get_token (parse_in); + switch (tok->type) +@@ -1233,10 +1235,22 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) + warning (OPT_Wtraditional, + "traditional C rejects string constant concatenation"); + ++ if (!strncmp((const char*)strs[0].text, "\"\\p", 3)) ++ { ++ pascal_string = true; ++ /* replace \p by a valid escape sequence */ ++ ((unsigned char*)strs[0].text)[2] = 'n'; ++ } ++ + if ((translate + ? cpp_interpret_string : cpp_interpret_string_notranslate) + (parse_in, strs, concats + 1, &istr, type)) + { ++ if (pascal_string) ++ { ++ /* put the real string length in */ ++ ((unsigned char*)istr.text)[0] = (unsigned char) (istr.len - 2); ++ } + value = build_string (istr.len, (const char *) istr.text); + free (CONST_CAST (unsigned char *, istr.text)); + if (concats) +@@ -1281,7 +1295,10 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) + { + default: + case CPP_STRING: +- TREE_TYPE (value) = char_array_type_node; ++ if (pascal_string) ++ TREE_TYPE (value) = uchar_array_type_node; ++ else ++ TREE_TYPE (value) = char_array_type_node; + break; + case CPP_UTF8STRING: + if (flag_char8_t) +diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c +index c8e7cd01d..004a59423 100644 +--- a/gcc/c/c-decl.c ++++ b/gcc/c/c-decl.c +@@ -4892,7 +4892,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, + break; + + case FUNCTION_DECL: +- error ("function %qD is initialized like a variable", decl); ++ //error ("function %qD is initialized like a variable", decl); ++ // Retro68: a function defined by inline opcodes does not count as initialized. + initialized = false; + break; + +diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c +index 741d172ff..d054299c9 100644 +--- a/gcc/c/c-parser.c ++++ b/gcc/c/c-parser.c +@@ -1499,6 +1499,7 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *); + static bool c_parser_objc_diagnose_bad_element_prefix + (c_parser *, struct c_declspecs *); + ++static tree c_parser_inline_opcodes(c_parser *); + static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass); + + /* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9). +@@ -2114,23 +2115,31 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, + /* The declaration of the variable is in effect while + its initializer is parsed. */ + d = start_decl (declarator, specs, true, +- chainon (postfix_attrs, all_prefix_attrs)); ++ chainon (postfix_attrs, all_prefix_attrs)); + if (!d) + d = error_mark_node; + if (omp_declare_simd_clauses.exists ()) + c_finish_omp_declare_simd (parser, d, NULL_TREE, + omp_declare_simd_clauses); +- init_loc = c_parser_peek_token (parser)->location; +- rich_location richloc (line_table, init_loc); +- start_init (d, asm_name, global_bindings_p (), &richloc); +- /* A parameter is initialized, which is invalid. Don't +- attempt to instrument the initializer. */ +- int flag_sanitize_save = flag_sanitize; +- if (TREE_CODE (d) == PARM_DECL) +- flag_sanitize = 0; +- init = c_parser_initializer (parser); +- flag_sanitize = flag_sanitize_save; +- finish_init (); ++ if(TREE_CODE(d) == FUNCTION_DECL) ++ { ++ tree rawinline_attr = c_parser_inline_opcodes(parser); ++ decl_attributes (&d, rawinline_attr, 0); ++ } ++ else ++ { ++ init_loc = c_parser_peek_token (parser)->location; ++ rich_location richloc (line_table, init_loc); ++ start_init (d, asm_name, global_bindings_p (), &richloc); ++ /* A parameter is initialized, which is invalid. Don't ++ attempt to instrument the initializer. */ ++ int flag_sanitize_save = flag_sanitize; ++ if (TREE_CODE (d) == PARM_DECL) ++ flag_sanitize = 0; ++ init = c_parser_initializer (parser); ++ flag_sanitize = flag_sanitize_save; ++ finish_init (); ++ } + } + if (oacc_routine_data) + c_finish_oacc_routine (oacc_routine_data, d, false); +@@ -19855,6 +19864,33 @@ c_parse_file (void) + the_parser = NULL; + } + ++static tree c_parser_inline_opcodes(c_parser * parser) ++{ ++ tree attr_args; ++ vec *expr_list; ++ bool braced = false; ++ ++ braced = c_parser_next_token_is(parser, CPP_OPEN_BRACE); ++ if(braced) ++ c_parser_consume_token(parser); ++ ++ expr_list = c_parser_expr_list (parser, false, true, ++ NULL, NULL, NULL, NULL); ++ attr_args = build_tree_list_vec (expr_list); ++ release_tree_vector (expr_list); ++ ++ if(braced) ++ { ++ if(c_parser_next_token_is(parser, CPP_CLOSE_BRACE)) ++ c_parser_consume_token(parser); ++ else ++ c_parser_error (parser, "expected %<}%>"); ++ } ++ ++ return build_tree_list ( ++ canonicalize_attr_name(get_identifier("__raw_inline__")), attr_args); ++} ++ + /* Parse the body of a function declaration marked with "__RTL". + + The RTL parser works on the level of characters read from a +diff --git a/gcc/calls.c b/gcc/calls.c +index 6b22e7a23..3d5af427d 100644 +--- a/gcc/calls.c ++++ b/gcc/calls.c +@@ -288,17 +288,29 @@ prepare_call_address (tree fndecl_or_type, rtx funexp, rtx static_chain_value, + } + else + { +- /* funexp could be a SYMBOL_REF represents a function pointer which is +- of ptr_mode. In this case, it should be converted into address mode +- to be a valid address for memory rtx pattern. See PR 64971. */ +- if (GET_MODE (funexp) != Pmode) +- funexp = convert_memory_address (Pmode, funexp); ++ int is_magic = 0; + +- if (!(flags & ECF_SIBCALL)) +- { +- if (!NO_FUNCTION_CSE && optimize && ! flag_no_function_cse) +- funexp = force_reg (Pmode, funexp); +- } ++ if (fndecl_or_type) ++ { ++ tree fntype = TREE_TYPE(fndecl_or_type); ++ if(fntype && lookup_attribute ("raw_inline", TYPE_ATTRIBUTES (fntype))) ++ is_magic = 1; ++ } ++ ++ if (!is_magic) ++ { ++ /* funexp could be a SYMBOL_REF represents a function pointer which is ++ of ptr_mode. In this case, it should be converted into address mode ++ to be a valid address for memory rtx pattern. See PR 64971. */ ++ if (GET_MODE (funexp) != Pmode) ++ funexp = convert_memory_address (Pmode, funexp); ++ ++ if (!(flags & ECF_SIBCALL)) ++ { ++ if (!NO_FUNCTION_CSE && optimize && ! flag_no_function_cse) ++ funexp = force_reg (Pmode, funexp); ++ } ++ } + } + + if (static_chain_value != 0 +@@ -1883,7 +1895,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, + rtx *old_stack_level, + poly_int64_pod *old_pending_adj, + int *must_preallocate, int *ecf_flags, +- bool *may_tailcall, bool call_from_thunk_p) ++ bool *may_tailcall, bool call_from_thunk_p, ++ bool reverse_args) + { + CUMULATIVE_ARGS *args_so_far_pnt = get_cumulative_args (args_so_far); + location_t loc = EXPR_LOCATION (exp); +@@ -1891,7 +1904,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, + /* Count arg position in order args appear. */ + int argpos; + +- int i; ++ int i, inc; + + args_size->constant = 0; + args_size->var = 0; +@@ -1901,7 +1914,17 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, + /* In this loop, we consider args in the order they are written. + We fill up ARGS from the back. */ + +- i = num_actuals - 1; ++ if (!reverse_args) ++ { ++ i = num_actuals - 1, inc = -1; ++ /* In this case, must reverse order of args ++ so that we compute and push the last arg first. */ ++ } ++ else ++ { ++ i = 0, inc = 1; ++ } ++ + { + int j = i; + call_expr_arg_iterator iter; +@@ -1911,7 +1934,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, + if (struct_value_addr_value) + { + args[j].tree_value = struct_value_addr_value; +- j--; ++ j += inc; + } + argpos = 0; + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) +@@ -1925,12 +1948,12 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, + { + tree subtype = TREE_TYPE (argtype); + args[j].tree_value = build1 (REALPART_EXPR, subtype, arg); +- j--; ++ j += inc; + args[j].tree_value = build1 (IMAGPART_EXPR, subtype, arg); + } + else + args[j].tree_value = arg; +- j--; ++ j += inc; + argpos++; + } + +@@ -1958,7 +1981,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, + tree alloc_args[] = { NULL_TREE, NULL_TREE }; + + /* I counts args in order (to be) pushed; ARGPOS counts in order written. */ +- for (argpos = 0; argpos < num_actuals; i--, argpos++) ++ for (argpos = 0; argpos < num_actuals; i += inc, argpos++) + { + tree type = TREE_TYPE (args[i].tree_value); + int unsignedp; +@@ -3355,6 +3378,10 @@ expand_call (tree exp, rtx target, int ignore) + unsigned HOST_WIDE_INT preferred_unit_stack_boundary; + /* The static chain value to use for this call. */ + rtx static_chain_value; ++ ++ /* True if this is a call to a pascal-declared function. */ ++ bool is_pascal = false; ++ + /* See if this is "nothrow" function call. */ + if (TREE_NOTHROW (exp)) + flags |= ECF_NOTHROW; +@@ -3379,6 +3406,10 @@ expand_call (tree exp, rtx target, int ignore) + + struct_value = targetm.calls.struct_value_rtx (fntype, 0); + ++#ifdef IS_PASCAL_FUNC ++ is_pascal = IS_PASCAL_FUNC(fntype, fndecl); ++#endif ++ + /* Warn if this value is an aggregate type, + regardless of which calling convention we are using for it. */ + if (AGGREGATE_TYPE_P (rettype)) +@@ -3595,7 +3626,8 @@ expand_call (tree exp, rtx target, int ignore) + args_so_far, reg_parm_stack_space, + &old_stack_level, &old_pending_adj, + &must_preallocate, &flags, +- &try_tail_call, CALL_FROM_THUNK_P (exp)); ++ &try_tail_call, CALL_FROM_THUNK_P (exp), ++ is_pascal); + + if (args_size.var) + must_preallocate = 1; +@@ -3633,6 +3665,9 @@ expand_call (tree exp, rtx target, int ignore) + if (must_tail_call) + try_tail_call = 1; + ++ if (is_pascal) ++ try_tail_call = 0; ++ + /* Rest of purposes for tail call optimizations to fail. */ + if (try_tail_call) + try_tail_call = can_implement_as_sibling_call_p (exp, +@@ -4055,6 +4090,16 @@ expand_call (tree exp, rtx target, int ignore) + &low_to_save, &high_to_save); + #endif + ++ if (is_pascal) ++ { ++ auto pascal_return_mode = TYPE_MODE (TREE_TYPE (funtype)); ++ poly_uint16 modesize = GET_MODE_SIZE (pascal_return_mode); ++#ifdef PUSH_ROUNDING ++ modesize = PUSH_ROUNDING (modesize); ++#endif ++ push_block (gen_int_mode (modesize, Pmode), 0, 0); ++ } ++ + /* Now store (and compute if necessary) all non-register parms. + These come before register parms, since they can require block-moves, + which could clobber the registers used for register parms. +@@ -4138,7 +4183,8 @@ expand_call (tree exp, rtx target, int ignore) + /* Figure out the register where the value, if any, will come back. */ + valreg = 0; + if (TYPE_MODE (rettype) != VOIDmode +- && ! structure_value_addr) ++ && ! structure_value_addr ++ && ! is_pascal) + { + if (pcc_struct_value) + valreg = hard_function_value (build_pointer_type (rettype), +@@ -4237,6 +4283,27 @@ expand_call (tree exp, rtx target, int ignore) + next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage, + flags, args_so_far); + ++ if (is_pascal) ++ { ++ if (TYPE_MODE (rettype) != VOIDmode ++ && ! structure_value_addr) ++ { ++ valreg = gen_reg_rtx(TYPE_MODE(rettype)); ++ ++ poly_uint16 modesize = GET_MODE_SIZE (GET_MODE (valreg)); ++#ifdef PUSH_ROUNDING ++ modesize = PUSH_ROUNDING (modesize); ++#endif ++ emit_move_insn(valreg, ++ gen_rtx_MEM( GET_MODE (valreg), ++ stack_pointer_rtx ++ )); ++ ++ adjust_stack(gen_int_mode (modesize, Pmode)); ++ } ++ } ++ ++ + if (flag_ipa_ra) + { + rtx_call_insn *last; +diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c +index 3638a1b10..5422f8449 100644 +--- a/gcc/combine-stack-adj.c ++++ b/gcc/combine-stack-adj.c +@@ -727,7 +727,10 @@ public: + { + return rest_of_handle_stack_adjustments (); + } +- ++ virtual opt_pass *clone () ++ { ++ return new pass_stack_adjustments(m_ctxt); ++ } + }; // class pass_stack_adjustments + + bool +diff --git a/gcc/combine.c b/gcc/combine.c +index 4de759a8e..1e38a67b9 100644 +--- a/gcc/combine.c ++++ b/gcc/combine.c +@@ -14345,10 +14345,10 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2, + old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size); + /* emit_call_1 adds for !ACCUMULATE_OUTGOING_ARGS + REG_ARGS_SIZE note to all noreturn calls, allow that here. */ +- gcc_assert (maybe_ne (old_size, args_size) ++ /* gcc_assert (maybe_ne (old_size, args_size) + || (CALL_P (i3) + && !ACCUMULATE_OUTGOING_ARGS +- && find_reg_note (i3, REG_NORETURN, NULL_RTX))); ++ && find_reg_note (i3, REG_NORETURN, NULL_RTX))); ### */ + } + break; + +diff --git a/gcc/config.gcc b/gcc/config.gcc +index 09fb9ecd2..19fc2b6fc 100644 +--- a/gcc/config.gcc ++++ b/gcc/config.gcc +@@ -456,6 +456,8 @@ m32r*-*-*) + m68k-*-*) + extra_headers=math-68881.h + extra_options="${extra_options} m68k/m68k-tables.opt" ++ c_target_objs="m68k-mac-pragmas.o" ++ cxx_target_objs="m68k-mac-pragmas.o" + ;; + microblaze*-*-*) + cpu_type=microblaze +@@ -2093,6 +2095,23 @@ m68k-*-elf* | fido-*-elf*) + ;; + esac + ;; ++m68k-*-macos*) ++ default_m68k_cpu=68020 ++ default_cf_cpu=5206 ++ tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68k-macos.h" ++ tm_defines="${tm_defines} MOTOROLA=1" ++ tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf m68k/t-macos" ++ tmake_file="$tmake_file m68k/t-mlibs" ++ ;; ++ ++fido-*-elf*) ++ default_m68k_cpu=68020 ++ default_cf_cpu=5206 ++ tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h" ++ tm_defines="${tm_defines} MOTOROLA=1" ++ tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf" ++ tmake_file="$tmake_file m68k/t-mlibs" ++ ;; + m68k*-*-netbsdelf*) + default_m68k_cpu=68020 + default_cf_cpu=5475 +@@ -2765,6 +2784,15 @@ powerpcle-*-eabi*) + extra_options="${extra_options} rs6000/sysv4.opt" + use_gcc_stdint=wrap + ;; ++powerpc-apple-macos*) ++ tm_file="${tm_file} rs6000/xcoff.h rs6000/macos.h" ++ tmake_file="rs6000/t-macos" ++ extra_options="${extra_options} rs6000/aix64.opt" ++ use_collect2=yes ++ thread_file='aix' ++ use_gcc_stdint=provide ++ extra_headers= ++ ;; + rs6000-ibm-aix6.* | powerpc-ibm-aix6.*) + tm_file="${tm_file} rs6000/aix.h rs6000/aix61.h rs6000/xcoff.h rs6000/aix-stdint.h" + tmake_file="rs6000/t-aix52 t-slibgcc" +diff --git a/gcc/config/m68k/m68k-mac-pragmas.c b/gcc/config/m68k/m68k-mac-pragmas.c +new file mode 100644 +index 000000000..5a543ba15 +--- /dev/null ++++ b/gcc/config/m68k/m68k-mac-pragmas.c +@@ -0,0 +1,118 @@ ++#include ++#include ++#include ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "hash-set.h" ++#include "vec.h" ++#include "double-int.h" ++#include "input.h" ++#include "alias.h" ++#include "symtab.h" ++#include "inchash.h" ++#include "tree.h" ++ ++#include "c-family/c-pragma.h" ++#include "c-family/c-common.h" ++#include "diagnostic-core.h" ++#include "cpplib.h" ++ ++std::map pragma_parameter_register_names; ++extern std::map< std::string, std::vector > pragma_parameter_directives; ++ ++ ++static int lookup_reg(std::string s) ++{ ++ std::map::const_iterator p = pragma_parameter_register_names.find(s); ++ if(p == pragma_parameter_register_names.end()) ++ return -1; ++ return p->second; ++} ++ ++static void ++m68k_pragma_parameter (cpp_reader * reader ATTRIBUTE_UNUSED) ++{ ++ /* on off */ ++ tree token; ++ enum cpp_ttype type; ++ ++ std::string name; ++ std::vector argregs; ++ ++ type = pragma_lex (&token); ++ argregs.push_back(0); ++ if (type == CPP_NAME) ++ { ++ name = IDENTIFIER_POINTER(token); ++ type = pragma_lex (&token); ++ if (type == CPP_NAME) ++ { ++ argregs.back() = lookup_reg(name); ++ if(argregs.back() < 0) ++ { ++ error ("invalid register name %s", name.c_str()); ++ return; ++ } ++ name = IDENTIFIER_POINTER(token); ++ type = pragma_lex (&token); ++ } ++ if (type == CPP_EOF) ++ { ++ pragma_parameter_directives[name] = argregs; ++ return; ++ } ++ ++ if (type == CPP_OPEN_PAREN) ++ { ++ type = pragma_lex (&token); ++ while(argregs.size() == 1 ? type == CPP_NAME : type == CPP_COMMA) ++ { ++ if(argregs.size() != 1) ++ type = pragma_lex (&token); ++ if(type != CPP_NAME) ++ break; ++ ++ argregs.push_back(lookup_reg(IDENTIFIER_POINTER(token))); ++ if(argregs.back() < 0) ++ { ++ error ("invalid register name %s", IDENTIFIER_POINTER(token)); ++ return; ++ } ++ ++ type = pragma_lex (&token); ++ } ++ ++ if (type == CPP_CLOSE_PAREN) ++ { ++ type = pragma_lex (&token); ++ if (type != CPP_EOF) ++ { ++ error ("junk at end of #pragma parameter"); ++ } ++ else ++ { ++ pragma_parameter_directives[name] = argregs; ++ } ++ return; ++ } ++ } ++ } ++ error ("malformed #pragma parameter "); ++} ++ ++ ++void ++m68k_register_pragmas() ++{ ++ for(int i = 0; i < 8; i++) ++ { ++ std::string n(1, '0' + i); ++ pragma_parameter_register_names["__D" + n] = i; ++ pragma_parameter_register_names["__A" + n] = i + 8; ++ } ++ c_register_pragma (NULL, "parameter", m68k_pragma_parameter); ++ ++} +diff --git a/gcc/config/m68k/m68k-macos.h b/gcc/config/m68k/m68k-macos.h +new file mode 100644 +index 000000000..d43ef14d4 +--- /dev/null ++++ b/gcc/config/m68k/m68k-macos.h +@@ -0,0 +1,18 @@ ++ ++#define LIBGCC_SPEC "--start-group -lretrocrt -lgcc -lInterface --end-group " ++#define LINK_SPEC "-elf2mac -q -undefined=_consolewrite" ++ ++#undef LIB_SPEC ++#define LIB_SPEC "--start-group -lc -lretrocrt -lInterface --end-group" ++ ++#define LINK_GCC_C_SEQUENCE_SPEC "--start-group -lgcc -lc -lretrocrt -lInterface --end-group" ++ ++ ++#undef STARTFILE_SPEC ++#define STARTFILE_SPEC "" ++#undef ENDFILE_SPEC ++#define ENDFILE_SPEC "" ++ ++#undef CPP_SPEC ++#define CPP_SPEC "-Wno-trigraphs" ++ +diff --git a/gcc/config/m68k/m68k-passes.def b/gcc/config/m68k/m68k-passes.def +new file mode 100644 +index 000000000..9a0f91d23 +--- /dev/null ++++ b/gcc/config/m68k/m68k-passes.def +@@ -0,0 +1,22 @@ ++ ++/* ++ Macros that can be used in this file: ++ INSERT_PASS_AFTER (PASS, INSTANCE, TGT_PASS) ++ INSERT_PASS_BEFORE (PASS, INSTANCE, TGT_PASS) ++ REPLACE_PASS (PASS, INSTANCE, TGT_PASS) ++ */ ++ ++ // insert a stack adjustments (csa) pass early in compilation, ++ // before register allocation. ++ // This allows removing some extraneous moves in connection with pascal functions: ++ // pascal short bar(); pascal void foo(short); ++ // foo(bar()); ++ // ++ // subq #2, sp ++ // jsr bar ++ // move (sp), d0 ; <-- otherwise we end up with these two useless instructions ++ // move d0, (sp) ; <-- which are not removed if the register is already allocated ++ // ; <-- when csa figures out that no actual push or pop is needed ++ // jsr foo ++ ++INSERT_PASS_AFTER (pass_combine, 1, pass_stack_adjustments); +diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h +index abd920e70..10e1ac82e 100644 +--- a/gcc/config/m68k/m68k-protos.h ++++ b/gcc/config/m68k/m68k-protos.h +@@ -63,7 +63,7 @@ extern rtx m68k_legitimize_tls_address (rtx); + extern bool m68k_tls_reference_p (rtx, bool); + extern int valid_dbcc_comparison_p_2 (rtx, machine_mode); + extern rtx m68k_libcall_value (machine_mode); +-extern rtx m68k_function_value (const_tree, const_tree); ++extern rtx m68k_function_value (const_tree, const_tree, bool); + extern int emit_move_sequence (rtx *, machine_mode, rtx); + extern bool m68k_movem_pattern_p (rtx, rtx, HOST_WIDE_INT, bool); + extern const char *m68k_output_movem (rtx *, rtx, HOST_WIDE_INT, bool); +@@ -98,4 +98,6 @@ extern void init_68881_table (void); + extern rtx m68k_legitimize_call_address (rtx); + extern rtx m68k_legitimize_sibcall_address (rtx); + extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int); ++ ++extern void m68k_write_macsbug_name(FILE *, const char *, tree decl); + extern poly_int64 m68k_push_rounding (poly_int64); +diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c +index 7a0d6f7c6..d66ea01a9 100644 +--- a/gcc/config/m68k/m68k.c ++++ b/gcc/config/m68k/m68k.c +@@ -17,6 +17,9 @@ You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + ++#include ++#include ++#include + #define IN_TARGET_CODE 1 + + #include "config.h" +@@ -40,6 +43,7 @@ along with GCC; see the file COPYING3. If not see + #include "output.h" + #include "insn-attr.h" + #include "recog.h" ++#include "hashtab.h" + #include "diagnostic-core.h" + #include "flags.h" + #include "expmed.h" +@@ -65,11 +69,16 @@ along with GCC; see the file COPYING3. If not see + #include "optabs.h" + #include "builtins.h" + #include "rtl-iter.h" ++#include "stringpool.h" + #include "toplev.h" + + /* This file should be included last. */ + #include "target-def.h" + ++ ++std::map< std::string, std::vector > pragma_parameter_directives; ++ ++ + enum reg_class regno_reg_class[] = + { + DATA_REGS, DATA_REGS, DATA_REGS, DATA_REGS, +@@ -190,6 +199,9 @@ static bool m68k_output_addr_const_extra (FILE *, rtx); + static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; + static enum flt_eval_method + m68k_excess_precision (enum excess_precision_type); ++ ++static tree m68k_mangle_decl_assembler_name (tree decl, tree id); ++static pad_direction m68k_function_arg_padding (machine_mode mode, const_tree type); + static unsigned int m68k_hard_regno_nregs (unsigned int, machine_mode); + static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode); + static bool m68k_modes_tieable_p (machine_mode, machine_mode); +@@ -277,8 +289,8 @@ static machine_mode m68k_promote_function_mode (const_tree, machine_mode, + #undef TARGET_ATTRIBUTE_TABLE + #define TARGET_ATTRIBUTE_TABLE m68k_attribute_table + +-#undef TARGET_PROMOTE_PROTOTYPES +-#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true ++//#undef TARGET_PROMOTE_PROTOTYPES ++//#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true + + #undef TARGET_STRUCT_VALUE_RTX + #define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx +@@ -353,6 +365,15 @@ static machine_mode m68k_promote_function_mode (const_tree, machine_mode, + #undef TARGET_PROMOTE_FUNCTION_MODE + #define TARGET_PROMOTE_FUNCTION_MODE m68k_promote_function_mode + ++#undef TARGET_FUNCTION_VALUE ++#define TARGET_FUNCTION_VALUE m68k_function_value ++ ++#undef TARGET_MANGLE_DECL_ASSEMBLER_NAME ++#define TARGET_MANGLE_DECL_ASSEMBLER_NAME m68k_mangle_decl_assembler_name ++ ++#undef TARGET_FUNCTION_ARG_PADDING ++#define TARGET_FUNCTION_ARG_PADDING m68k_function_arg_padding ++ + #undef TARGET_HAVE_SPECULATION_SAFE_VALUE + #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed + +@@ -366,6 +387,12 @@ static const struct attribute_spec m68k_attribute_table[] = + m68k_handle_fndecl_attribute, NULL }, + { "interrupt_thread", 0, 0, true, false, false, false, + m68k_handle_fndecl_attribute, NULL }, ++ { "pascal", 0, 0, false, true, true, true, ++ m68k_handle_fndecl_attribute, NULL }, ++ { "regparam", 1, 1, false, true, true, true, ++ m68k_handle_fndecl_attribute, NULL }, ++ { "raw_inline", 1, 32, false, true, true, false, ++ m68k_handle_fndecl_attribute, NULL }, + { NULL, 0, 0, false, false, false, false, NULL, NULL } + }; + +@@ -631,6 +658,8 @@ m68k_option_override (void) + clear how intentional that is. */ + flag_no_function_cse = 1; + } ++ else if(TARGET_PCREL) ++ m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_BSRW_C; + + switch (m68k_symbolic_call_var) + { +@@ -646,6 +675,10 @@ m68k_option_override (void) + m68k_symbolic_call = "bsr%.l %p0"; + break; + ++ case M68K_SYMBOLIC_CALL_BSRW_C: ++ m68k_symbolic_call = "bsr%.w %c0"; ++ break; ++ + case M68K_SYMBOLIC_CALL_NONE: + gcc_assert (m68k_symbolic_call == NULL); + break; +@@ -759,7 +792,7 @@ m68k_get_function_kind (tree func) + tree a; + + gcc_assert (TREE_CODE (func) == FUNCTION_DECL); +- ++ + a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func)); + if (a != NULL_TREE) + return m68k_fk_interrupt_handler; +@@ -783,6 +816,9 @@ m68k_handle_fndecl_attribute (tree *node, tree name, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) + { ++ if (TREE_CODE (*node) != FUNCTION_TYPE && TREE_CODE (*node) != TYPE_DECL) ++ { ++ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute only applies to functions", +@@ -804,6 +840,9 @@ m68k_handle_fndecl_attribute (tree *node, tree name, + } + + return NULL_TREE; ++ } ++ else ++ return NULL_TREE; + } + + static void +@@ -902,7 +941,7 @@ m68k_initial_elimination_offset (int from, int to) + static bool + m68k_save_reg (unsigned int regno, bool interrupt_handler) + { +- if (flag_pic && regno == PIC_REG) ++ if (!TARGET_SEP_DATA && flag_pic && regno == PIC_REG) + { + if (crtl->saves_all_registers) + return true; +@@ -1357,14 +1396,14 @@ m68k_expand_epilogue (bool sibcall_p) + emit_jump_insn (ret_rtx); + } + +-/* Return true if X is a valid comparison operator for the dbcc +- instruction. ++/* Return true if X is a valid comparison operator for the dbcc ++ instruction. + + Note it rejects floating point comparison operators. + (In the future we could use Fdbcc). + + It also rejects some comparisons when CC_NO_OVERFLOW is set. */ +- ++ + int + valid_dbcc_comparison_p_2 (rtx x, machine_mode mode ATTRIBUTE_UNUSED) + { +@@ -1421,12 +1460,15 @@ static bool + m68k_ok_for_sibcall_p (tree decl, tree exp) + { + enum m68k_function_kind kind; +- ++ + /* We cannot use sibcalls for nested functions because we use the + static chain register for indirect calls. */ + if (CALL_EXPR_STATIC_CHAIN (exp)) + return false; + ++ if (decl && lookup_attribute ("raw_inline", TYPE_ATTRIBUTES( TREE_TYPE(decl) ))) ++ return false; ++ + if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl)))) + { + /* Check that the return value locations are the same. For +@@ -1435,9 +1477,9 @@ m68k_ok_for_sibcall_p (tree decl, tree exp) + rtx cfun_value; + rtx call_value; + +- cfun_value = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (cfun->decl)), +- cfun->decl); +- call_value = FUNCTION_VALUE (TREE_TYPE (exp), decl); ++ cfun_value = m68k_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)), ++ cfun->decl, false); ++ call_value = m68k_function_value (TREE_TYPE (exp), decl, false); + + /* Check that the values are equal or that the result the callee + function returns is superset of what the current function returns. */ +@@ -1457,19 +1499,115 @@ m68k_ok_for_sibcall_p (tree decl, tree exp) + the same. */ + if (decl && m68k_get_function_kind (decl) == kind) + return true; +- ++ + return false; + } + +-/* On the m68k all args are always pushed. */ ++/* On the m68k all args are always pushed - NOT. */ ++ ++void m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, ++ const_tree fntype, ++ rtx libname ATTRIBUTE_UNUSED, ++ const_tree fndecl, ++ int n_named_args) ++{ ++ cum->bytes = 0; ++ cum->index = 0; ++ cum->regparam = false; ++ ++ if(!fntype) ++ return; ++ ++ tree regparam = lookup_attribute ("regparam", TYPE_ATTRIBUTES( fntype )); ++ cum->regparam = regparam != NULL; ++ if(regparam) ++ { ++ regparam = TREE_VALUE(TREE_VALUE(regparam)); ++ if(TREE_CODE(regparam) == STRING_CST) ++ { ++ const char *paramstr = TREE_STRING_POINTER(regparam); ++ ++ const char *p = paramstr; ++ ++ bool ok = true; ++ int idx = 0; ++ cum->arg_regs[0] = 0; ++ if(*p == '(') ++ { ++ idx = 1; ++ p++; ++ } ++ while(*p) ++ { ++ while(*p && (*p == '_' || *p == '%' || *p == ',' || *p == '(' || *p == ')' || *p == ' ' || *p == '\t')) ++ p++; ++ ++ if(!*p) ++ break; ++ ++ if(*p != 'a' && *p != 'd' && *p != 'A' && *p != 'D') ++ { ok = false; break; } ++ if(p[1] < '0' || p[1] > '7') ++ { ok = false; break; } ++ cum->arg_regs[idx++] = p[1] - '0' ++ + (*p == 'a' || *p == 'A' ? 8 : 0); ++ ++ p += 2; ++ ++ } ++ // TODO: error checking ++ cum->total_count = idx - 1; ++ if(cum->total_count < 0) ++ cum->total_count = 0; ++ } ++ } ++ ++ if(!regparam && fndecl) ++ { ++ std::map< std::string, std::vector >::iterator p ++ = pragma_parameter_directives.find(IDENTIFIER_POINTER(DECL_NAME(fndecl))); ++ if(p != pragma_parameter_directives.end()) ++ { ++ cum->regparam = true; ++ cum->total_count = p->second.size()-1; ++ for(unsigned i = 0; i < p->second.size(); i++) ++ cum->arg_regs[i] = p->second[i]; ++ } ++ } ++ ++ ++} ++ ++int ++m68k_is_pascal_func(tree fntype, tree fndecl) ++{ ++ if(!fntype) ++ return false; ++ if(lookup_attribute ("pascal", TYPE_ATTRIBUTES (fntype))) ++ { ++ CUMULATIVE_ARGS cum; ++ m68k_init_cumulative_args(&cum, fntype, NULL, fndecl, -1); ++ return !cum.regparam; ++ } ++ else ++ return false; ++} + + static rtx +-m68k_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED, ++m68k_function_arg (cumulative_args_t cum_v, + machine_mode mode ATTRIBUTE_UNUSED, + const_tree type ATTRIBUTE_UNUSED, + bool named ATTRIBUTE_UNUSED) + { +- return NULL_RTX; ++ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); ++ if(!cum->regparam) ++ return NULL_RTX; ++ ++ if(cum->index < cum->total_count) ++ return gen_rtx_REG (mode, cum->arg_regs[cum->index+1]); ++ else ++ return NULL_RTX; ++ //return gen_rtx_REG (mode, 0); // ### + } + + static void +@@ -1478,11 +1616,13 @@ m68k_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, + { + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + +- *cum += (mode != BLKmode +- ? (GET_MODE_SIZE (mode) + 3) & ~3 +- : (int_size_in_bytes (type) + 3) & ~3); ++ cum->bytes += (mode != BLKmode ++ ? (GET_MODE_SIZE (mode) + 1) & ~1 ++ : (int_size_in_bytes (type) + 1) & ~1); ++ cum->index ++; + } + ++ + /* Convert X to a legitimate function call memory reference and return the + result. */ + +@@ -1587,8 +1727,8 @@ m68k_legitimize_address (rtx x, rtx oldx, machine_mode mode) + return x; + } + +- +-/* Output a dbCC; jCC sequence. Note we do not handle the ++ ++/* Output a dbCC; jCC sequence. Note we do not handle the + floating point version of this sequence (Fdbcc). We also + do not handle alternative conditions when CC_NO_OVERFLOW is + set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will +@@ -2427,19 +2567,19 @@ m68k_wrap_symbol_into_got_ref (rtx x, enum m68k_reloc reloc, rtx temp_reg) + /* Legitimize PIC addresses. If the address is already + position-independent, we return ORIG. Newly generated + position-independent addresses go to REG. If we need more +- than one register, we lose. ++ than one register, we lose. + + An address is legitimized by making an indirect reference + through the Global Offset Table with the name of the symbol +- used as an offset. ++ used as an offset. + +- The assembler and linker are responsible for placing the ++ The assembler and linker are responsible for placing the + address of the symbol in the GOT. The function prologue + is responsible for initializing a5 to the starting address + of the GOT. + + The assembler is also responsible for translating a symbol name +- into a constant displacement from the start of the GOT. ++ into a constant displacement from the start of the GOT. + + A quick example may make things a little clearer: + +@@ -2459,9 +2599,9 @@ m68k_wrap_symbol_into_got_ref (rtx x, enum m68k_reloc reloc, rtx temp_reg) + + movel a5@(_foo:w), a0 + movel #12345, a0@ +- + +- That (in a nutshell) is how *all* symbol and label references are ++ ++ That (in a nutshell) is how *all* symbol and label references are + handled. */ + + rtx +@@ -2490,7 +2630,7 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, + + /* legitimize both operands of the PLUS */ + gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS); +- ++ + base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); + orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, + base == reg ? 0 : reg); +@@ -2552,13 +2692,13 @@ m68k_call_tls_get_addr (rtx x, rtx eqv, enum m68k_reloc reloc) + is the simpliest way of generating a call. The difference between + __tls_get_addr() and libcall is that the result is returned in D0 + instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p +- which temporarily switches returning the result to A0. */ ++ which temporarily switches returning the result to A0. */ + + m68k_libcall_value_in_a0_p = true; + a0 = emit_library_call_value (m68k_get_tls_get_addr (), NULL_RTX, LCT_PURE, + Pmode, x, Pmode); + m68k_libcall_value_in_a0_p = false; +- ++ + insns = get_insns (); + end_sequence (); + +@@ -2586,7 +2726,7 @@ m68k_get_m68k_read_tp (void) + /* Emit instruction sequence that calls __m68k_read_tp. + A pseudo register with result of __m68k_read_tp call is returned. */ + +-static rtx ++static rtx + m68k_call_m68k_read_tp (void) + { + rtx a0; +@@ -2600,7 +2740,7 @@ m68k_call_m68k_read_tp (void) + is the simpliest way of generating a call. The difference between + __m68k_read_tp() and libcall is that the result is returned in D0 + instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p +- which temporarily switches returning the result to A0. */ ++ which temporarily switches returning the result to A0. */ + + /* Emit the call sequence. */ + m68k_libcall_value_in_a0_p = true; +@@ -2639,7 +2779,7 @@ m68k_legitimize_tls_address (rtx orig) + rtx eqv; + rtx a0; + rtx x; +- ++ + /* Attach a unique REG_EQUIV, to allow the RTL optimizers to + share the LDM result with other LD model accesses. */ + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), +@@ -3109,7 +3249,7 @@ output_move_qimode (rtx *operands) + { + /* 68k family always modifies the stack pointer by at least 2, even for + byte pushes. The 5200 (ColdFire) does not do this. */ +- ++ + /* This case is generated by pushqi1 pattern now. */ + gcc_assert (!(GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC +@@ -4158,13 +4298,13 @@ notice_update_cc (rtx exp, rtx insn) + if (GET_CODE (exp) == SET) + { + if (GET_CODE (SET_SRC (exp)) == CALL) +- CC_STATUS_INIT; ++ CC_STATUS_INIT; + else if (ADDRESS_REG_P (SET_DEST (exp))) + { + if (cc_status.value1 && modified_in_p (cc_status.value1, insn)) + cc_status.value1 = 0; + if (cc_status.value2 && modified_in_p (cc_status.value2, insn)) +- cc_status.value2 = 0; ++ cc_status.value2 = 0; + } + /* fmoves to memory or data registers do not set the condition + codes. Normal moves _do_ set the condition codes, but not in +@@ -4178,7 +4318,7 @@ notice_update_cc (rtx exp, rtx insn) + && (FP_REG_P (SET_SRC (exp)) + || GET_CODE (SET_SRC (exp)) == FIX + || FLOAT_MODE_P (GET_MODE (SET_DEST (exp))))) +- CC_STATUS_INIT; ++ CC_STATUS_INIT; + /* A pair of move insns doesn't produce a useful overall cc. */ + else if (!FP_REG_P (SET_DEST (exp)) + && !FP_REG_P (SET_SRC (exp)) +@@ -4186,7 +4326,7 @@ notice_update_cc (rtx exp, rtx insn) + && (GET_CODE (SET_SRC (exp)) == REG + || GET_CODE (SET_SRC (exp)) == MEM + || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE)) +- CC_STATUS_INIT; ++ CC_STATUS_INIT; + else if (SET_DEST (exp) != pc_rtx) + { + cc_status.flags = 0; +@@ -4235,7 +4375,7 @@ notice_update_cc (rtx exp, rtx insn) + ends with a move insn moving r2 in r2's mode. + Thus, the cc's are set for r2. + This can set N bit spuriously. */ +- cc_status.flags |= CC_NOT_NEGATIVE; ++ cc_status.flags |= CC_NOT_NEGATIVE; + + default: + break; +@@ -4300,7 +4440,7 @@ output_move_const_single (rtx *operands) + to get the desired constant. */ + + /* This code has been fixed for cross-compilation. */ +- ++ + static int inited_68881_table = 0; + + static const char *const strings_68881[7] = { +@@ -4368,7 +4508,7 @@ standard_68881_constant_p (rtx x) + if (real_identical (r, &values_68881[i])) + return (codes_68881[i]); + } +- ++ + if (GET_MODE (x) == SFmode) + return 0; + +@@ -4657,7 +4797,7 @@ m68k_delegitimize_address (rtx orig_x) + unspec = XEXP (addr.offset, 0); + if (GET_CODE (unspec) == PLUS && CONST_INT_P (XEXP (unspec, 1))) + unspec = XEXP (unspec, 0); +- if (GET_CODE (unspec) != UNSPEC ++ if (GET_CODE (unspec) != UNSPEC + || (XINT (unspec, 1) != UNSPEC_RELOC16 + && XINT (unspec, 1) != UNSPEC_RELOC32)) + return orig_x; +@@ -4678,7 +4818,7 @@ m68k_delegitimize_address (rtx orig_x) + x = replace_equiv_address_nv (orig_x, x); + return x; + } +- ++ + + /* A C compound statement to output to stdio stream STREAM the + assembler syntax for an instruction operand that is a memory +@@ -4692,7 +4832,7 @@ m68k_delegitimize_address (rtx orig_x) + It is possible for PIC to generate a (plus (label_ref...) (reg...)) + and we handle that just like we would a (plus (symbol_ref...) (reg...)). + +- This routine is responsible for distinguishing between -fpic and -fPIC ++ This routine is responsible for distinguishing between -fpic and -fPIC + style relocations in an address. When generating -fpic code the + offset is output in word mode (e.g. movel a5@(_foo:w), a0). When generating + -fPIC code the offset is output in long mode (e.g. movel a5@(_foo:l), a0) */ +@@ -5049,6 +5189,42 @@ output_xorsi3 (rtx *operands) + const char * + output_call (rtx x) + { ++ if(GET_CODE (x) == SYMBOL_REF) ++ { ++ tree decl = SYMBOL_REF_DECL(x); ++ if(decl) ++ { ++ tree attr = lookup_attribute ("raw_inline", TYPE_ATTRIBUTES( TREE_TYPE(decl) )); ++ if(attr) ++ { ++ tree arg = TREE_VALUE(attr); ++ ++ static char buf[512]; ++ char *p = buf, *e = buf + sizeof(buf); ++ bool first = true; ++ p += snprintf(p, e-p, ".short "); ++ ++ while(arg) ++ { ++ tree word_tree = TREE_VALUE(arg); ++ gcc_assert(TREE_CODE(word_tree) == INTEGER_CST); ++ if (TREE_CODE(word_tree) == INTEGER_CST) ++ { ++ int word = TREE_INT_CST_LOW(word_tree); ++ if(!first) ++ p += snprintf(p, e-p, ", "); ++ first = false; ++ p += snprintf(p, e-p, "0x%04x", word); ++ } ++ arg = TREE_CHAIN(arg); ++ } ++ ++ if(p < e) ++ return buf; ++ } ++ } ++ } ++ + if (symbolic_operand (x, VOIDmode)) + return m68k_symbolic_call; + else +@@ -5309,7 +5485,7 @@ m68k_preferred_reload_class (rtx x, enum reg_class rclass) + If there is need for a hard-float ABI it is probably worth doing it + properly and also passing function arguments in FP registers. */ + rtx +-m68k_libcall_value (machine_mode mode) ++m68k_libcall_value (enum machine_mode mode) + { + switch (mode) { + case E_SFmode: +@@ -5329,11 +5505,27 @@ m68k_libcall_value (machine_mode mode) + NOTE: Due to differences in ABIs, don't call this function directly, + use FUNCTION_VALUE instead. */ + rtx +-m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) ++m68k_function_value (const_tree valtype, const_tree func_decl_or_type, bool outgoing) + { + machine_mode mode; + + mode = TYPE_MODE (valtype); ++ ++ const_tree decl = NULL, type = NULL; ++ if(func_decl_or_type) ++ { ++ CUMULATIVE_ARGS cum; ++ decl = func_decl_or_type; ++ type = func_decl_or_type; ++ if(TREE_CODE(type) == FUNCTION_DECL) ++ type = TREE_TYPE(type); ++ else ++ decl = NULL; ++ m68k_init_cumulative_args(&cum, type, NULL, decl, -1); ++ if(cum.regparam) ++ return gen_rtx_REG (mode, cum.arg_regs[0]); ++ } ++ + switch (mode) { + case E_SFmode: + case E_DFmode: +@@ -5345,8 +5537,11 @@ m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) + break; + } + ++#if 1 /* POINTERS_IN_D0 */ ++ return gen_rtx_REG (mode, D0_REG); ++#else + /* If the function returns a pointer, push that into %a0. */ +- if (func && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (func)))) ++ if (type && POINTER_TYPE_P (TREE_TYPE (type)) && !outgoing) + /* For compatibility with the large body of existing code which + does not always properly declare external functions returning + pointer types, the m68k/SVR4 convention is to copy the value +@@ -5367,6 +5562,7 @@ m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) + return gen_rtx_REG (mode, A0_REG); + else + return gen_rtx_REG (mode, D0_REG); ++#endif + } + + /* Worker function for TARGET_RETURN_IN_MEMORY. */ +@@ -6102,7 +6298,7 @@ m68k_sched_variable_issue (FILE *sched_dump ATTRIBUTE_UNUSED, + + case CPU_CFV3: + insn_size = sched_get_attr_size_int (insn); +- ++ + /* ColdFire V3 and V4 cores have instruction buffers that can + accumulate up to 8 instructions regardless of instructions' + sizes. So we should take care not to "prefetch" 24 one-word +@@ -6539,6 +6735,8 @@ m68k_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) + static poly_int64 + m68k_return_pops_args (tree fundecl, tree funtype, poly_int64 size) + { ++ if (lookup_attribute ("pascal", TYPE_ATTRIBUTES (funtype))) ++ return size; + return ((TARGET_RTD + && (!fundecl + || TREE_CODE (fundecl) != IDENTIFIER_NODE) +@@ -6615,6 +6813,66 @@ m68k_excess_precision (enum excess_precision_type type) + return FLT_EVAL_METHOD_UNPREDICTABLE; + } + ++extern int retro68_hack_asm_rts_counter; ++ ++void ++m68k_write_macsbug_name(FILE *file, const char *name, tree decl) ++{ ++ int len = strlen(name); ++ if(len > 255) ++ len = 255; ++ ++ const char *section_name = DECL_SECTION_NAME (decl); ++ if(flag_function_sections && section_name) ++ fprintf(file, "\t.pushsection %s.macsbug,\"ax\",@progbits\n", section_name); ++ fprintf(file, "# macsbug symbol\n"); ++ if(!retro68_hack_asm_rts_counter) ++ fprintf(file, "\trts\n"); ++ if(len < 32) ++ fprintf(file, "\t.byte %d\n", len | 0x80); ++ else ++ fprintf(file, "\t.byte 0x80\n\t.byte %d\n", len); ++ ++ ASM_OUTPUT_ASCII(file, name, len); ++ fprintf(file, "\t.align 2,0\n\t.short 0\n"); ++ if(flag_function_sections && section_name) ++ fprintf(file, "\t.popsection\n", section_name); ++} ++ ++static tree ++m68k_mangle_decl_assembler_name (tree decl, tree id) ++{ ++ tree new_id = NULL_TREE; ++ ++ if (TREE_CODE (decl) == FUNCTION_DECL) ++ { ++ tree attrs = TYPE_ATTRIBUTES ( TREE_TYPE(decl) ); ++ if (attrs != NULL_TREE) ++ { ++ if (lookup_attribute ("pascal", attrs)) ++ { ++ const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl)); ++ char *new_str, *p; ++ int len = strlen(old_str); ++ new_str = XALLOCAVEC (char, 1 + len); ++ for(int i = 0; i < len; i++) ++ new_str[i] = TOUPPER(old_str[i]); ++ new_str[len] = 0; ++ ++ return get_identifier (new_str); ++ } ++ } ++ } ++ ++ return id; ++} ++ ++static pad_direction ++m68k_function_arg_padding (machine_mode mode, const_tree type) ++{ ++ return PAD_UPWARD; ++} ++ + /* Implement PUSH_ROUNDING. On the 680x0, sp@- in a byte insn really pushes + a word. On the ColdFire, sp@- in a byte insn pushes just a byte. */ + +diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h +index fc65e524b..57eddd759 100644 +--- a/gcc/config/m68k/m68k.h ++++ b/gcc/config/m68k/m68k.h +@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see + + #define SUBTARGET_EXTRA_SPECS + ++ + /* Note that some other tm.h files include this one and then override + many of the definitions that relate to assembler syntax. */ + +@@ -193,9 +194,16 @@ along with GCC; see the file COPYING3. If not see + \ + builtin_assert ("cpu=m68k"); \ + builtin_assert ("machine=m68k"); \ ++ \ ++ builtin_define("pascal=__attribute__((__pascal__))"); \ + } \ + while (0) + ++ ++extern void m68k_register_pragmas(void); ++ /* Target Pragmas. */ ++#define REGISTER_TARGET_PRAGMAS() m68k_register_pragmas () ++ + /* Classify the groups of pseudo-ops used to assemble QI, HI and SI + quantities. */ + #define INT_OP_STANDARD 0 /* .byte, .short, .long */ +@@ -287,7 +295,7 @@ along with GCC; see the file COPYING3. If not see + + #define UNITS_PER_WORD 4 + +-#define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32) ++#define PARM_BOUNDARY 16 /* (TARGET_SHORT ? 16 : 32) */ + #define STACK_BOUNDARY 16 + #define FUNCTION_BOUNDARY 16 + #define EMPTY_FIELD_BOUNDARY 16 +@@ -340,7 +348,7 @@ along with GCC; see the file COPYING3. If not see + 0, 0, 0, 0, 0, 0, 0, 0, \ + \ + /* Address registers. */ \ +- 0, 0, 0, 0, 0, 0, 0, 1, \ ++ 0, 0, 0, 0, 0, 1, 0, 1, \ + \ + /* Floating point registers \ + (if available). */ \ +@@ -357,10 +365,10 @@ along with GCC; see the file COPYING3. If not see + Aside from that, you can include as many other registers as you like. */ + #define CALL_USED_REGISTERS \ + {/* Data registers. */ \ +- 1, 1, 0, 0, 0, 0, 0, 0, \ ++ 1, 1, 1, 0, 0, 0, 0, 0, \ + \ + /* Address registers. */ \ +- 1, 1, 0, 0, 0, 0, 0, 1, \ ++ 1, 1, 0, 0, 0, 1, 0, 1, \ + \ + /* Floating point registers \ + (if available). */ \ +@@ -473,8 +481,7 @@ extern enum reg_class regno_reg_class[]; + #define FIRST_PARM_OFFSET(FNDECL) 8 + + /* On the m68k the return value defaults to D0. */ +-#define FUNCTION_VALUE(VALTYPE, FUNC) \ +- gen_rtx_REG (TYPE_MODE (VALTYPE), D0_REG) ++// gen_rtx_REG (TYPE_MODE (VALTYPE), D0_REG) + + /* On the m68k the return value defaults to D0. */ + #define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, D0_REG) +@@ -490,13 +497,21 @@ extern enum reg_class regno_reg_class[]; + /* On the m68k, all arguments are usually pushed on the stack. */ + #define FUNCTION_ARG_REGNO_P(N) 0 + +-/* On the m68k, this is a single integer, which is a number of bytes +- of arguments scanned so far. */ +-#define CUMULATIVE_ARGS int ++ ++typedef struct { ++ int bytes; /* number of bytes of arguments scanned so far. */ ++ int total_count; ++ int index; ++ int regparam; ++ int arg_regs[32]; ++ ++} CUMULATIVE_ARGS; ++ ++extern void m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, const_tree fntype, rtx libname, const_tree fundecl, int n_named_args); + + /* On the m68k, the offset starts at 0. */ + #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ +- ((CUM) = 0) ++ m68k_init_cumulative_args(&(CUM), (FNTYPE), (LIBNAME), (INDIRECT), (N_NAMED_ARGS)); + + #define FUNCTION_PROFILER(FILE, LABELNO) \ + asm_fprintf (FILE, "\tlea %LLP%d,%Ra0\n\tjsr mcount\n", (LABELNO)) +@@ -926,7 +941,8 @@ extern const char *m68k_symbolic_call; + extern const char *m68k_symbolic_jump; + + enum M68K_SYMBOLIC_CALL { M68K_SYMBOLIC_CALL_NONE, M68K_SYMBOLIC_CALL_JSR, +- M68K_SYMBOLIC_CALL_BSR_C, M68K_SYMBOLIC_CALL_BSR_P }; ++ M68K_SYMBOLIC_CALL_BSR_C, M68K_SYMBOLIC_CALL_BSR_P, ++ M68K_SYMBOLIC_CALL_BSRW_C }; + + extern enum M68K_SYMBOLIC_CALL m68k_symbolic_call_var; + +@@ -945,3 +961,15 @@ extern int m68k_sched_address_bypass_p (rtx_insn *, rtx_insn *); + extern int m68k_sched_indexed_address_bypass_p (rtx_insn *, rtx_insn *); + + #define CPU_UNITS_QUERY 1 ++ ++#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ ++ do \ ++ { \ ++ if (!flag_inhibit_size_directive) \ ++ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \ ++ m68k_write_macsbug_name(FILE, FNAME, DECL); \ ++ } \ ++ while (0) ++ ++extern int m68k_is_pascal_func(tree, tree); ++#define IS_PASCAL_FUNC(fntype, fndecl) m68k_is_pascal_func(fntype, fndecl) +diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md +index 31e8767e7..0720c56a4 100644 +--- a/gcc/config/m68k/m68k.md ++++ b/gcc/config/m68k/m68k.md +@@ -1119,12 +1119,26 @@ + move%.b %1,%0" + [(set_attr "type" "clr,clr,move,move")]) + +-(define_expand "pushqi1" +- [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2))) +- (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int 1))) +- (match_operand:QI 0 "general_operand" ""))] ++; (define_expand "pushqi1" ++; [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2))) ++; (set (mem:QI (reg:SI SP_REG) ) ++; (match_operand:QI 0 "general_operand" ""))] ++; "!TARGET_COLDFIRE" ++; "") ++ ++; (define_insn "*pushqi1" ++; [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2))) ++; (set (mem:QI (reg:SI SP_REG) ) ++; (match_operand:QI 0 "general_operand" ""))] ++; "!TARGET_COLDFIRE" ++; { return "move%.b %0,%-"; }) ++ ++(define_insn "*pushqi1" ++ [ ++ (set (mem:QI (pre_modify:SI (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2)))) ++ (match_operand:QI 0 "general_operand" "dmn"))] + "!TARGET_COLDFIRE" +- "") ++ { return "move%.b %0,%-"; }) + + (define_expand "reload_insf" + [(set (match_operand:SF 0 "nonimmediate_operand" "=f") +@@ -6932,6 +6946,41 @@ + operands[1] = m68k_legitimize_call_address (operands[1]); + }) + ++(define_expand "call_pop" ++ [(parallel [(call (match_operand:QI 0 "memory_operand" "") ++ (match_operand:SI 1 "general_operand" "")) ++ (set (reg:SI SP_REG) ++ (plus:SI (reg:SI SP_REG) ++ (match_operand:SI 3 "" "")))])] ++ "" ++{ ++ operands[0] = m68k_legitimize_call_address (operands[0]); ++}) ++(define_expand "call_value_pop" ++ [(parallel [(set (match_operand 0 "" "") ++ (call (match_operand:QI 1 "memory_operand" "") ++ (match_operand:SI 2 "general_operand" ""))) ++ (set (reg:SI SP_REG) ++ (plus:SI (reg:SI SP_REG) ++ (match_operand:SI 4 "" "")))])] ++ "" ++{ ++ operands[1] = m68k_legitimize_call_address (operands[1]); ++}) ++ ++(define_insn "*call_pop" ++ [(call (mem:QI (match_operand:SI 0 "call_operand" "a,W")) ++ (match_operand:SI 1 "general_operand" "g,g")) ++ (set (reg:SI SP_REG) ++ (plus:SI (reg:SI SP_REG) ++ (match_operand:SI 2 "" "")))] ++ ;; Operand 1 not really used on the m68000. ++ "!SIBLING_CALL_P (insn)" ++{ ++ return output_call (operands[0]); ++} ++ [(set_attr "type" "jsr")]) ++ + (define_insn "*non_symbolic_call_value" + [(set (match_operand 0 "" "=rf,rf") + (call (mem:QI (match_operand:SI 1 "non_symbolic_call_operand" "a,W")) +@@ -6950,7 +6999,7 @@ + "!SIBLING_CALL_P (insn) && m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_JSR" + { + operands[0] = operands[1]; +- return m68k_symbolic_call; ++ return output_call (operands[0]); + } + [(set_attr "type" "jsr") + (set_attr "opx" "1")]) +@@ -6962,14 +7011,66 @@ + ;; Operand 2 not really used on the m68000. + "!SIBLING_CALL_P (insn) + && (m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_C +- || m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_P)" ++ || m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_P ++ || m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSRW_C)" ++{ ++ operands[0] = operands[1]; ++ return output_call (operands[0]); ++} ++ [(set_attr "type" "bsr") ++ (set_attr "opx" "1")]) ++ ++ ++(define_insn "*non_symbolic_call_value_pop" ++ [(set (match_operand 0 "" "=rf,rf") ++ (call (mem:QI (match_operand:SI 1 "non_symbolic_call_operand" "a,W")) ++ (match_operand:SI 2 "general_operand" "g,g"))) ++ (set (reg:SI SP_REG) ++ (plus:SI (reg:SI SP_REG) ++ (match_operand:SI 3 "" "")))] ++ ;; Operand 2 not really used on the m68000. ++ "!SIBLING_CALL_P (insn)" ++ "jsr %a1" ++ [(set_attr "type" "jsr") ++ (set_attr "opx" "1")]) ++ ++(define_insn "*symbolic_call_value_pop_jsr" ++ [(set (match_operand 0 "" "=rf,rf") ++ (call (mem:QI (match_operand:SI 1 "symbolic_operand" "a,W")) ++ (match_operand:SI 2 "general_operand" "g,g"))) ++ (set (reg:SI SP_REG) ++ (plus:SI (reg:SI SP_REG) ++ (match_operand:SI 3 "" "")))] ++ ;; Operand 2 not really used on the m68000. ++ "!SIBLING_CALL_P (insn) && m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_JSR" ++{ ++ operands[0] = operands[1]; ++ return output_call (operands[0]); ++} ++ [(set_attr "type" "jsr") ++ (set_attr "opx" "1")]) ++ ++(define_insn "*symbolic_call_value_pop_bsr" ++ [(set (match_operand 0 "" "=rf,rf") ++ (call (mem:QI (match_operand:SI 1 "symbolic_operand" "a,W")) ++ (match_operand:SI 2 "general_operand" "g,g"))) ++ (set (reg:SI SP_REG) ++ (plus:SI (reg:SI SP_REG) ++ (match_operand:SI 3 "" "")))] ++ ;; Operand 2 not really used on the m68000. ++ "!SIBLING_CALL_P (insn) ++ && (m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_C ++ || m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_P ++ || m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSRW_C)" + { + operands[0] = operands[1]; +- return m68k_symbolic_call; ++ return output_call (operands[0]); + } + [(set_attr "type" "bsr") + (set_attr "opx" "1")]) + ++ ++ + ;; Call subroutine returning any type. + + (define_expand "untyped_call" +@@ -7046,6 +7147,7 @@ + [(return)] + "" + { ++ extern int retro68_hack_asm_rts_counter; + switch (m68k_get_function_kind (current_function_decl)) + { + case m68k_fk_interrupt_handler: +@@ -7055,11 +7157,17 @@ + return "sleep"; + + default: ++ retro68_hack_asm_rts_counter = 2; + if (crtl->args.pops_args) + { + operands[0] = GEN_INT (crtl->args.pops_args); +- return "rtd %0"; +- } ++ if (TARGET_68020) ++ return "rtd %0"; ++ else ++ return "move.l (%%a7)+, %%a0\n" ++ "\tlea %a0(%%a7), %%a7\n" ++ "\tjmp (%%a0)"; ++ } + else + return "rts"; + } +diff --git a/gcc/config/m68k/m68kemb.h b/gcc/config/m68k/m68kemb.h +index 893cc756d..64362c179 100644 +--- a/gcc/config/m68k/m68kemb.h ++++ b/gcc/config/m68k/m68kemb.h +@@ -17,8 +17,6 @@ + and unions in registers, which is slightly more efficient. */ + #define DEFAULT_PCC_STRUCT_RETURN 0 + +-#undef FUNCTION_VALUE +-#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE)) + + #undef LIBCALL_VALUE + #define LIBCALL_VALUE(MODE) \ +diff --git a/gcc/config/m68k/t-m68k b/gcc/config/m68k/t-m68k +index cbff34d65..cff52fb59 100644 +--- a/gcc/config/m68k/t-m68k ++++ b/gcc/config/m68k/t-m68k +@@ -2,3 +2,7 @@ + + M68K_MLIB_CPU += && (CPU !~ "^mcf") + M68K_ARCH := m68k ++ ++M68K_MLIB_CPU += && (CPU !~ "^m68060") && (CPU !~ "^cpu32") && (CPU !~ "^fidoa") ++ ++PASSES_EXTRA += $(srcdir)/config/m68k/m68k-passes.def +diff --git a/gcc/config/m68k/t-macos b/gcc/config/m68k/t-macos +new file mode 100644 +index 000000000..1ef1c285f +--- /dev/null ++++ b/gcc/config/m68k/t-macos +@@ -0,0 +1,5 @@ ++m68k-mac-pragmas.o: $(srcdir)/config/m68k/m68k-mac-pragmas.c ++ $(COMPILE) $< ++ $(POSTCOMPILE) ++ ++M68K_MLIB_CPU += && (CPU !~ "^m68060") && (CPU !~ "^cpu32") && (CPU !~ "^fidoa") +diff --git a/gcc/config/rs6000/macos.h b/gcc/config/rs6000/macos.h +new file mode 100644 +index 000000000..1176fe0c6 +--- /dev/null ++++ b/gcc/config/rs6000/macos.h +@@ -0,0 +1,292 @@ ++/* Definitions of target machine for GNU compiler, ++ for IBM RS/6000 POWER running AIX. ++ Copyright (C) 2000-2015 Free Software Foundation, Inc. ++ ++ This file is part of GCC. ++ ++ GCC is free software; you can redistribute it and/or modify it ++ under the terms of the GNU General Public License as published ++ by the Free Software Foundation; either version 3, or (at your ++ option) any later version. ++ ++ GCC is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public ++ License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with GCC; see the file COPYING3. If not see ++ . */ ++ ++/* Yes! We are AIX! */ ++#define DEFAULT_ABI ABI_AIX ++#undef TARGET_AIX ++#define TARGET_AIX 1 ++ ++/* Linux64.h wants to redefine TARGET_AIX based on -m64, but it can't be used ++ in the #if conditional in options-default.h, so provide another macro. */ ++#undef TARGET_AIX_OS ++#define TARGET_AIX_OS 1 ++ ++/* AIX always has a TOC. */ ++#define TARGET_NO_TOC 0 ++#define TARGET_TOC 1 ++#define FIXED_R2 1 ++ ++/* AIX allows r13 to be used in 32-bit mode. */ ++#define FIXED_R13 0 ++ ++/* 32-bit and 64-bit AIX stack boundary is 128. */ ++#undef STACK_BOUNDARY ++#define STACK_BOUNDARY 128 ++ ++#undef TARGET_IEEEQUAD ++#define TARGET_IEEEQUAD 0 ++ ++ ++#if HAVE_AS_REF ++/* Issue assembly directives that create a reference to the given DWARF table ++ identifier label from the current function section. This is defined to ++ ensure we drag frame frame tables associated with needed function bodies in ++ a link with garbage collection activated. */ ++#define ASM_OUTPUT_DWARF_TABLE_REF rs6000_aix_asm_output_dwarf_table_ref ++#endif ++ ++/* This is the only version of nm that collect2 can work with. */ ++//#define REAL_NM_FILE_NAME "/usr/ucb/nm" ++ ++#define USER_LABEL_PREFIX "" ++ ++/* Don't turn -B into -L if the argument specifies a relative file name. */ ++#define RELATIVE_PREFIX_NOT_LINKDIR ++ ++/* Because of the above, we must have gcc search itself to find libgcc.a. */ ++#define LINK_LIBGCC_SPECIAL_1 ++ ++#undef ASM_DEFAULT_SPEC ++#define ASM_DEFAULT_SPEC "" ++ ++ ++/* Static linking with shared libstdc++ requires libsupc++ as well. */ ++#define LIBSTDCXX_STATIC "supc++" ++ ++/* Compute field alignment. ++ This implements the 'power' alignment rule by pegging the alignment of ++ items (beyond the first aggregate field) to 32 bits. The pegging is ++ suppressed for vector and long double items (both 128 in size). ++ There is a dummy use of the FIELD argument to avoid an unused variable ++ warning (see PR59496). */ ++#define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \ ++ ((void) (FIELD), \ ++ (TARGET_ALIGN_NATURAL \ ++ ? (COMPUTED) \ ++ : (COMPUTED) == 128 \ ++ ? 128 \ ++ : MIN ((COMPUTED), 32))) ++ ++/* AIX increases natural record alignment to doubleword if the first ++ field is an FP double while the FP fields remain word aligned. */ ++#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \ ++ ((TREE_CODE (STRUCT) == RECORD_TYPE \ ++ || TREE_CODE (STRUCT) == UNION_TYPE \ ++ || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \ ++ && TARGET_ALIGN_NATURAL == 0 \ ++ ? rs6000_special_round_type_align (STRUCT, COMPUTED, SPECIFIED) \ ++ : MAX ((COMPUTED), (SPECIFIED))) ++ ++/* The AIX ABI isn't explicit on whether aggregates smaller than a ++ word/doubleword should be padded upward or downward. One could ++ reasonably assume that they follow the normal rules for structure ++ layout treating the parameter area as any other block of memory, ++ then map the reg param area to registers, i.e., pad upward, which ++ is the way IBM Compilers for AIX behave. ++ Setting both of the following defines results in this behavior. */ ++#define AGGREGATE_PADDING_FIXED 1 ++#define AGGREGATES_PAD_UPWARD_ALWAYS 1 ++ ++/* Specify padding for the last element of a block move between ++ registers and memory. FIRST is nonzero if this is the only ++ element. */ ++#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \ ++ (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE)) ++ ++ ++/* Indicate that jump tables go in the text section. */ ++ ++#define JUMP_TABLES_IN_TEXT_SECTION 1 ++ ++ ++#define PROFILE_HOOK(LABEL) output_profile_hook (LABEL) ++ ++/* No version of AIX fully supports AltiVec or 64-bit instructions in ++ 32-bit mode. */ ++#define OS_MISSING_POWERPC64 1 ++#define OS_MISSING_ALTIVEC 1 ++ ++/* WINT_TYPE */ ++#define WINT_TYPE "int" ++ ++/* Static stack checking is supported by means of probes. */ ++#define STACK_CHECK_STATIC_BUILTIN 1 ++ ++/* Use standard DWARF numbering for DWARF debugging information. */ ++#define RS6000_USE_DWARF_NUMBERING ++ ++ ++ ++/* MacOS does support Altivec. */ ++#/*undef TARGET_ALTIVEC ++#define TARGET_ALTIVEC 1 ++#undef TARGET_ALTIVEC_ABI ++#define TARGET_ALTIVEC_ABI 1 ++#undef TARGET_ALTIVEC_VRSAVE ++#define TARGET_ALTIVEC_VRSAVE 1*/ ++ ++#undef TARGET_OS_CPP_BUILTINS ++/* __POWERPC__ must be defined for some header files */ ++#define TARGET_OS_CPP_BUILTINS() \ ++ do \ ++ { \ ++ builtin_define ("__ppc__"); \ ++ builtin_define ("__PPC__"); \ ++ builtin_define ("__POWERPC__"); \ ++ builtin_define ("__NATURAL_ALIGNMENT__"); \ ++ builtin_assert ("system=macos"); \ ++ builtin_assert ("cpu=powerpc"); \ ++ builtin_assert ("machine=powerpc"); \ ++ builtin_assert ("cpu=m68k"); \ ++ builtin_assert ("machine=m68k"); \ ++ builtin_define("pascal=__attribute__((__pascal__))"); \ ++ builtin_define("__IEEE_BIG_ENDIAN"); \ ++ } \ ++ while (0) ++ ++/* --no-check-sections : sections overlap on purpose! ++ -undefined=_consolewrite : hack to allow easy configuration of console output ++*/ ++ ++#define LINK_SPEC "%{!r:-btextro} -bhalt:4 -bnodelcsect \ ++--no-check-sections -undefined=_consolewrite \ ++%{shared:-bM:SRE}" ++ ++#define LIB_SPEC "-lc" ++#define LIBGCC_SPEC "-lgcc %{carbon: -lretrocrt-carbon} %{!carbon: -lretrocrt} -lgcc %{carbon: -lCarbonLib} %{!carbon: -lInterfaceLib}" ++ ++#define LINK_GCC_C_SEQUENCE_SPEC "--start-group -lgcc -lc %{carbon: -lretrocrt-carbon} %{!carbon: -lretrocrt} %{carbon: -lCarbonLib} %{!carbon: -lInterfaceLib} --end-group" ++ ++#undef STARTFILE_SPEC ++#define STARTFILE_SPEC "" ++ ++#undef CPP_SPEC ++#define CPP_SPEC "-Wno-trigraphs" ++ ++#undef TARGET_DEFAULT ++#define TARGET_DEFAULT 0 ++// (MASK_POWERPC | MASK_MULTIPLE | MASK_NEW_MNEMONICS) ++ ++#undef PROCESSOR_DEFAULT ++#define PROCESSOR_DEFAULT PROCESSOR_PPC601 ++ ++#undef OS_MISSING_ALTIVEC ++#define OS_MISSING_ALTIVEC 0 ++ ++#undef VECTOR_SAVE_INLINE ++#define VECTOR_SAVE_INLINE(FIRST_REG) 1 ++ ++ ++#define TARGET_USES_AIX64_OPT ++ ++#undef TARGET_POINTERS_TO_NESTED_FUNCTIONS ++#define TARGET_POINTERS_TO_NESTED_FUNCTIONS 0 ++ ++/* Type used for ptrdiff_t, as a string used in a declaration. */ ++#undef PTRDIFF_TYPE ++#define PTRDIFF_TYPE "long int" ++ ++/* The AIX linker will discard static constructors in object files before ++ collect has a chance to see them, so collect2 contains functionality ++ to scan the object files directly, enabled by: ++ #define COLLECT_EXPORT_LIST ++ ++ However, this seems to find all constructors and exception frame tables, ++ and thus leads to huge executables. ++ As we don't need to be compatible with the AIX linker, binutils had been ++ made to not discard these symbols any more *if* the corresponding object ++ file is loaded. ++*/ ++ ++/* Select a format to encode pointers in exception handling data. CODE ++ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is ++ true if the symbol may be affected by dynamic relocations. */ ++#undef ASM_PREFERRED_EH_DATA_FORMAT ++#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \ ++ (DW_EH_PE_absptr) ++#undef EH_TABLES_CAN_BE_READ_ONLY ++#define EH_TABLES_CAN_BE_READ_ONLY 0 ++ ++#if 0 ++/* On AIX, initialisers specified with -binitfini are called in breadth-first ++ order. ++ e.g. if a.out depends on lib1.so, the init function for a.out is called before ++ the init function for lib1.so. ++ ++ To ensure global C++ constructors in linked libraries are run before global ++ C++ constructors from the current module, there is additional symbol scanning ++ logic in collect2. ++ ++ The global initialiser/finaliser functions are named __GLOBAL_AIXI_{libname} ++ and __GLOBAL_AIXD_{libname} and are exported from each shared library. ++ ++ collect2 will detect these symbols when they exist in shared libraries that ++ the current program is being linked against. All such initiliser functions ++ will be called prior to the constructors of the current program, and ++ finaliser functions called after destructors. ++ ++ Reference counting generated by collect2 will ensure that constructors are ++ only invoked once in the case of multiple dependencies on a library. ++ ++ -binitfini is still used in parallel to this solution. ++ This handles the case where a library is loaded through dlopen(), and also ++ handles the option -blazy. ++*/ ++#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \ ++ fprintf ((STREAM), "void %s() {\n\t%s();\n}\n", aix_shared_initname, (FUNC)) ++#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \ ++ fprintf ((STREAM), "void %s() {\n\t%s();\n}\n", aix_shared_fininame, (FUNC)) ++ ++#endif ++ ++ ++ ++#define SIG_ATOMIC_TYPE "int" ++ ++#define INT8_TYPE "signed char" ++#define INT16_TYPE "short int" ++#define INT32_TYPE "long int" ++#define INT64_TYPE "long long int" ++#define UINT8_TYPE "unsigned char" ++#define UINT16_TYPE "short unsigned int" ++#define UINT32_TYPE "long unsigned int" ++#define UINT64_TYPE "long long unsigned int" ++ ++#define INT_LEAST8_TYPE "signed char" ++#define INT_LEAST16_TYPE "short int" ++#define INT_LEAST32_TYPE "long int" ++#define INT_LEAST64_TYPE "long long int" ++#define UINT_LEAST8_TYPE "unsigned char" ++#define UINT_LEAST16_TYPE "short unsigned int" ++#define UINT_LEAST32_TYPE "long unsigned int" ++#define UINT_LEAST64_TYPE "long long unsigned int" ++ ++#define INT_FAST8_TYPE "signed char" ++#define INT_FAST16_TYPE "short int" ++#define INT_FAST32_TYPE "long int" ++#define INT_FAST64_TYPE "long long int" ++#define UINT_FAST8_TYPE "unsigned char" ++#define UINT_FAST16_TYPE "short unsigned int" ++#define UINT_FAST32_TYPE "long unsigned int" ++#define UINT_FAST64_TYPE "long long unsigned int" ++ ++#define INTPTR_TYPE "long int" ++#define UINTPTR_TYPE "long unsigned int" ++ +diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c +index f0de18d4d..6ce4f3cf9 100644 +--- a/gcc/config/rs6000/rs6000.c ++++ b/gcc/config/rs6000/rs6000.c +@@ -1530,6 +1530,9 @@ static const struct attribute_spec rs6000_attribute_table[] = + rs6000_handle_struct_attribute, NULL }, + { "gcc_struct", 0, 0, false, false, false, false, + rs6000_handle_struct_attribute, NULL }, ++ { "pascal", 0, 0, false, true, true, false/*don't be strict about function pointers*/, ++ NULL, NULL }, ++ + #ifdef SUBTARGET_ATTRIBUTE_TABLE + SUBTARGET_ATTRIBUTE_TABLE, + #endif +@@ -34341,8 +34344,8 @@ rs6000_xcoff_declare_object_name (FILE *file, const char *name, tree decl) + struct declare_alias_data data = {file, false}; + RS6000_OUTPUT_BASENAME (file, name); + fputs (":\n", file); +- symtab_node::get_create (decl)->call_for_symbol_and_aliases (rs6000_declare_alias, +- &data, true); ++ if(symtab_node::get (decl)) ++ symtab_node::get (decl)->call_for_symbol_and_aliases (rs6000_declare_alias, &data, true); + } + + /* Overide the default 'SYMBOL-.' syntax with AIX compatible 'SYMBOL-$'. */ +diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt +index f4b5c91e1..cc352d6cd 100644 +--- a/gcc/config/rs6000/rs6000.opt ++++ b/gcc/config/rs6000/rs6000.opt +@@ -565,6 +565,9 @@ Use the given offset for addressing the stack-protector guard. + TargetVariable + long rs6000_stack_protector_guard_offset = 0 + ++carbon ++Target RejectNegative ++ + ;; -mno-speculate-indirect-jumps adds deliberate misprediction to indirect + ;; branches via the CTR. + mspeculate-indirect-jumps +diff --git a/gcc/config/rs6000/t-macos b/gcc/config/rs6000/t-macos +new file mode 100644 +index 000000000..534dd94a4 +--- /dev/null ++++ b/gcc/config/rs6000/t-macos +@@ -0,0 +1,35 @@ ++# Copyright (C) 1998-2015 Free Software Foundation, Inc. ++# ++# This file is part of GCC. ++# ++# GCC is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3, or (at your option) ++# any later version. ++# ++# GCC is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GCC; see the file COPYING3. If not see ++# . ++ ++# Build the libraries for pthread and all of the ++# different processor models ++ ++#MULTILIB_OPTIONS = ++# mcpu=powerpc ++ ++#MULTILIB_DIRNAMES = ++#powerpc ++ ++#MULTILIB_MATCHES = ++# mcpu?powerpc=mcpu?powerpc \ ++# mcpu?powerpc=mcpu?601 \ ++# mcpu?powerpc=mcpu?602 \ ++# mcpu?powerpc=mcpu?603 \ ++# mcpu?powerpc=mcpu?603e \ ++# mcpu?powerpc=mcpu?604 \ ++# mcpu?powerpc=mcpu?604e +diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c +index 01c89cd57..0042a2f7e 100644 +--- a/gcc/cp/decl.c ++++ b/gcc/cp/decl.c +@@ -8975,6 +8975,12 @@ grokfndecl (tree ctype, + (IDENTIFIER_POINTER (declarator)))))) + SET_DECL_LANGUAGE (decl, lang_c); + ++ if (attrlist && lookup_attribute ("pascal", *attrlist)) ++ { ++ // paradoxical, but true: Mac pascal function names aren't mangled. ++ SET_DECL_LANGUAGE (decl, lang_c); ++ } ++ + /* Should probably propagate const out from type to decl I bet (mrs). */ + if (staticp) + { +diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c +index 3d908916a..7396614ef 100644 +--- a/gcc/cp/parser.c ++++ b/gcc/cp/parser.c +@@ -2650,6 +2650,8 @@ static bool cp_parser_init_statement_p + (cp_parser *); + static bool cp_parser_skip_to_closing_square_bracket + (cp_parser *); ++static tree cp_parser_inline_opcodes ++ (cp_parser *); + + /* Concept-related syntactic transformations */ + +@@ -4094,6 +4096,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok, + tree string_tree; + tree suffix_id = NULL_TREE; + bool curr_tok_is_userdef_p = false; ++ bool pascal_string = false; + + tok = cp_lexer_peek_token (parser->lexer); + if (!cp_parser_is_string_literal (tok)) +@@ -4223,9 +4226,21 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok, + type = CPP_STRING; + } + ++ if (!strncmp((const char*)strs[0].text, "\"\\p", 3)) ++ { ++ pascal_string = true; ++ /* replace \p by a valid escape sequence */ ++ ((unsigned char*)strs[0].text)[2] = 'n'; ++ } ++ + if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate) + (parse_in, strs, count, &istr, type)) + { ++ if (pascal_string) ++ { ++ /* put the real string length in */ ++ ((unsigned char*)istr.text)[0] = (unsigned char) (istr.len - 2); ++ } + value = build_string (istr.len, (const char *)istr.text); + free (CONST_CAST (unsigned char *, istr.text)); + if (count > 1) +@@ -4239,7 +4254,10 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok, + { + default: + case CPP_STRING: +- TREE_TYPE (value) = char_array_type_node; ++ if (pascal_string) ++ TREE_TYPE (value) = uchar_array_type_node; ++ else ++ TREE_TYPE (value) = char_array_type_node; + break; + case CPP_UTF8STRING: + if (flag_char8_t) +@@ -20443,20 +20461,42 @@ cp_parser_init_declarator (cp_parser* parser, + { + if (function_declarator_p (declarator)) + { +- if (initialization_kind == CPP_EQ) +- initializer = cp_parser_pure_specifier (parser); +- else +- { +- /* If the declaration was erroneous, we don't really ++ if (initialization_kind == CPP_EQ) ++ { ++ if(member_p) ++ initializer = cp_parser_pure_specifier (parser); ++ else ++ { ++ cp_token *token; ++ cp_lexer_consume_token (parser->lexer); ++ token = cp_lexer_peek_token (parser->lexer); ++ if (token->keyword == RID_DEFAULT ++ || token->keyword == RID_DELETE) ++ { ++ cp_lexer_consume_token (parser->lexer); ++ maybe_warn_cpp0x (CPP0X_DEFAULTED_DELETED); ++ initializer = token->u.value; ++ } ++ else ++ { ++ is_initialized = false; ++ tree rawinline_attr = cp_parser_inline_opcodes (parser); ++ decl_attributes (&decl, rawinline_attr, 0); ++ } ++ } ++ } ++ else ++ { ++ /* If the declaration was erroneous, we don't really + know what the user intended, so just silently + consume the initializer. */ +- if (decl != error_mark_node) ++ if (decl != error_mark_node) + error_at (tmp_init_loc, "initializer provided for function"); +- cp_parser_skip_to_closing_parenthesis (parser, ++ cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); +- } ++ } + } + else + { +@@ -41446,6 +41486,49 @@ finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt) + return member_decl_opt; + } + ++ ++static tree cp_parser_inline_opcodes(cp_parser * parser) ++{ ++ tree attr_args; ++ bool braced = false; ++ ++ braced = cp_lexer_next_token_is(parser->lexer, CPP_OPEN_BRACE); ++ if(braced) ++ cp_lexer_consume_token(parser->lexer); ++ ++ vec *expr_list = make_tree_vector (); ++ ++ if(!braced || !cp_lexer_next_token_is(parser->lexer, CPP_CLOSE_BRACE)) ++ { ++ for(;;) ++ { ++ tree val = cp_parser_constant_expression (parser, ++ /*allow_non_constant_p=*/false, ++ NULL); ++ val = cp_fully_fold(val); ++ vec_safe_push (expr_list, val); ++ ++ if(cp_lexer_next_token_is(parser->lexer, CPP_COMMA)) ++ cp_lexer_consume_token(parser->lexer); ++ else ++ break; ++ } ++ } ++ ++ attr_args = build_tree_list_vec (expr_list); ++ release_tree_vector (expr_list); ++ ++ if(braced) ++ { ++ if(cp_lexer_next_token_is(parser->lexer, CPP_CLOSE_BRACE)) ++ cp_lexer_consume_token(parser->lexer); ++ else ++ cp_parser_error (parser, "expected %<}%>"); ++ } ++ ++ return build_tree_list (canonicalize_attr_name(get_identifier("__raw_inline__")), attr_args); ++} ++ + /* Like finish_fully_implicit_template, but to be used in error + recovery, rearranging scopes so that we restore the state we had + before synthesize_implicit_template_parm inserted the implement +diff --git a/gcc/expr.c b/gcc/expr.c +index fa15b7ece..e2ddab37b 100644 +--- a/gcc/expr.c ++++ b/gcc/expr.c +@@ -4088,12 +4088,14 @@ find_args_size_adjust (rtx_insn *insn) + addr = XEXP (mem, 0); + switch (GET_CODE (addr)) + { ++#ifdef PUSH_ROUNDING + case PRE_INC: + case POST_INC: +- return GET_MODE_SIZE (GET_MODE (mem)); ++ return PUSH_ROUNDING( GET_MODE_SIZE (GET_MODE (mem)) ); + case PRE_DEC: + case POST_DEC: +- return -GET_MODE_SIZE (GET_MODE (mem)); ++ return -PUSH_ROUNDING( GET_MODE_SIZE (GET_MODE (mem)) ); ++#endif + case PRE_MODIFY: + case POST_MODIFY: + addr = XEXP (addr, 1); +@@ -4128,6 +4130,19 @@ fixup_args_size_notes (rtx_insn *prev, rtx_insn *last, + gcc_assert (!note || known_eq (args_size, get_args_size (note))); + + poly_int64 this_delta = find_args_size_adjust (insn); ++ ++ /* **** HALF-UNDERSTOOD HACK: ++ ++ The original code here leaves out REG_ARGS_SIZE annotations for ++ instructions that don't adjust the stack under some circumstances. ++ ++ In some situations, involving both m68k mac pascal functions ++ and exception handling, this leads to a failure in dwarf2cfi.c:combine_traces. ++ ++ Disabling the if (this_delta == 0) fixes this, but causes the subsequent gcc_assert ++ to trip sometimes. Disabling both hasn't caused any observable problems... YET. ++ ++ + if (known_eq (this_delta, 0)) + { + if (!CALL_P (insn) +@@ -4137,6 +4152,8 @@ fixup_args_size_notes (rtx_insn *prev, rtx_insn *last, + } + + gcc_assert (!saw_unknown); ++ ++ */ + if (known_eq (this_delta, HOST_WIDE_INT_MIN)) + saw_unknown = true; + +diff --git a/gcc/final.c b/gcc/final.c +index fefc4874b..c0c26e937 100644 +--- a/gcc/final.c ++++ b/gcc/final.c +@@ -3824,6 +3824,8 @@ do_assembler_dialects (const char *p, int *dialect) + and print a constant expression for minus the value + of the operand, with no other punctuation. */ + ++int retro68_hack_asm_rts_counter = 0; ++ + void + output_asm_insn (const char *templ, rtx *operands) + { +@@ -3841,6 +3843,13 @@ output_asm_insn (const char *templ, rtx *operands) + if (*templ == 0) + return; + ++ /* Hack: in Retro68, we want to know whether the last ++ instruction we output was an rts, so we know ++ whether we have to output an extra one as part ++ of the MacsBug name. */ ++ if(retro68_hack_asm_rts_counter) ++ retro68_hack_asm_rts_counter--; ++ + memset (opoutput, 0, sizeof opoutput); + p = templ; + putc ('\t', asm_out_file); +diff --git a/gcc/function.c b/gcc/function.c +index c6e862b33..ccfc4e352 100644 +--- a/gcc/function.c ++++ b/gcc/function.c +@@ -2393,6 +2393,20 @@ assign_parms_augmented_arg_list (struct assign_parm_data_all *all) + all->function_result_decl = decl; + } + ++#ifdef IS_PASCAL_FUNC ++ if (IS_PASCAL_FUNC(fntype, fndecl)) ++ { ++ // reverse argument order ++ unsigned n = fnargs.length(), n2 = fnargs.length() / 2; ++ for(unsigned i = 0; i < n2; i++) ++ { ++ tree tmp = fnargs[i]; ++ fnargs[i] = fnargs[n - 1 - i]; ++ fnargs[n - 1 - i] = tmp; ++ } ++ } ++#endif ++ + /* If the target wants to split complex arguments into scalars, do so. */ + if (targetm.calls.split_complex_arg) + split_complex_args (&fnargs); +@@ -5344,6 +5358,20 @@ expand_function_end (void) + tree decl_result = DECL_RESULT (current_function_decl); + rtx decl_rtl = DECL_RTL (decl_result); + ++#ifdef IS_PASCAL_FUNC ++ if (IS_PASCAL_FUNC(TREE_TYPE(current_function_decl), current_function_decl)) ++ { ++ enum machine_mode mode = GET_MODE(decl_rtl);; ++ ++ rtx return_slot = gen_int_mode(crtl->args.pops_args + 8, Pmode); ++ return_slot = gen_rtx_PLUS(Pmode, arg_pointer_rtx, return_slot); ++ return_slot = gen_rtx_MEM(mode, return_slot); ++ MEM_VOLATILE_P(return_slot) = true; ++ emit_move_insn (return_slot, decl_rtl); ++ crtl->return_rtx = return_slot; ++ } ++ else ++#endif + if (REG_P (decl_rtl) + ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER + : DECL_REGISTER (decl_result)) +diff --git a/gcc/reload1.c b/gcc/reload1.c +index bb112d817..cf674fab3 100644 +--- a/gcc/reload1.c ++++ b/gcc/reload1.c +@@ -3035,6 +3035,8 @@ elimination_effects (rtx x, machine_mode mem_mode) + else + ep->can_eliminate = 0; + } ++ if (code == POST_DEC || code == POST_INC) ++ ep->can_eliminate = 0; + } + + /* These two aren't unary operators. */ +diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c +index 268a38799..92cdc7475 100644 +--- a/gcc/rtlanal.c ++++ b/gcc/rtlanal.c +@@ -1596,7 +1596,24 @@ set_noop_p (const_rtx set) + return 1; + + if (MEM_P (dst) && MEM_P (src)) +- return rtx_equal_p (dst, src) && !side_effects_p (dst); ++ { ++ if (rtx_equal_p (dst, src) && !side_effects_p (dst)) ++ return 1; ++ ++ src = XEXP(src, 0); ++ dst = XEXP(dst, 0); ++ ++ if( GET_CODE(src) == POST_INC && GET_CODE(dst) == PRE_DEC ) ++ { ++ src = XEXP(src, 0); ++ dst = XEXP(dst, 0); ++ if (rtx_equal_p (dst, src) && !side_effects_p (dst)) ++ return 1; ++ ++ } ++ ++ return 0; ++ } + + if (GET_CODE (dst) == ZERO_EXTRACT) + return rtx_equal_p (XEXP (dst, 0), src) +diff --git a/gcc/system.h b/gcc/system.h +index d04f8fd33..69d195d85 100644 +--- a/gcc/system.h ++++ b/gcc/system.h +@@ -145,7 +145,7 @@ extern int fgetc_unlocked (FILE *); + extern char *fgets_unlocked (char *, int, FILE *); + # endif + # endif +-# ifdef HAVE_FPUTS_UNLOCKED ++# if defined (HAVE_FPUTS_UNLOCKED) && !defined (__CYGWIN__) + # undef fputs + # define fputs(String, Stream) fputs_unlocked (String, Stream) + # if defined (HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED +diff --git a/libcc1/cc1plugin-config.h.in b/libcc1/cc1plugin-config.h.in +index ac06357ba..e1f32b36a 100644 +--- a/libcc1/cc1plugin-config.h.in ++++ b/libcc1/cc1plugin-config.h.in +@@ -34,8 +34,7 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_UNISTD_H + +-/* Define to the sub-directory in which libtool stores uninstalled libraries. +- */ ++/* Define to the sub-directory where libtool stores uninstalled libraries. */ + #undef LT_OBJDIR + + /* Define to the address where bug reports for this package should be sent. */ +diff --git a/libcpp/charset.c b/libcpp/charset.c +index 8a0e5cbb2..67eddcc7f 100644 +--- a/libcpp/charset.c ++++ b/libcpp/charset.c +@@ -1828,7 +1828,7 @@ narrow_str_to_charconst (cpp_reader *pfile, cpp_string str, + cpp_error (pfile, CPP_DL_WARNING, + "character constant too long for its type"); + } +- else if (i > 1 && CPP_OPTION (pfile, warn_multichar)) ++ else if (i > 1 && i != 4 && CPP_OPTION (pfile, warn_multichar)) + cpp_warning (pfile, CPP_W_MULTICHAR, "multi-character character constant"); + + /* Multichar constants are of type int and therefore signed. */ +diff --git a/libgcc/config.host b/libgcc/config.host +index 91abc84da..820da40f5 100644 +--- a/libgcc/config.host ++++ b/libgcc/config.host +@@ -870,6 +870,10 @@ m32rle-*-linux*) + m68k-*-elf* | fido-*-elf) + tmake_file="$tmake_file m68k/t-floatlib" + ;; ++m68k-*-macos) ++ extra_parts="crtbegin.o crtend.o" ++ tmake_file="$tmake_file m68k/t-floatlib" ++ ;; + m68k*-*-netbsdelf*) + ;; + m68k*-*-openbsd*) +@@ -1204,6 +1208,9 @@ rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*) + tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble rs6000/t-aix-cxa" + extra_parts="crtcxa.o crtcxa_s.o crtdbase.o" + ;; ++powerpc-*-macos) ++ tmake_file="t-fdpbit rs6000/t-ibm-ldouble" ++ ;; + rl78-*-elf) + tmake_file="$tm_file t-fdpbit rl78/t-rl78" + ;; +diff --git a/libgcc/config/rs6000/cxa_finalize.c b/libgcc/config/rs6000/cxa_finalize.c +index fe6621b79..b15d47dbe 100644 +--- a/libgcc/config/rs6000/cxa_finalize.c ++++ b/libgcc/config/rs6000/cxa_finalize.c +@@ -29,7 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #include "exit.h" + + +-static boolean_t ++static int + catomic_compare_and_exchange_bool_acq (long *mem, long newval, long oldval) + { + return ! __atomic_compare_exchange (mem, &oldval, &newval, 0,