/* Subroutines for the gcc driver. Copyright (C) 2015-2020 Free Software Foundation, Inc. Contributed by Georg-Johann Lay 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 "diagnostic.h" #include "tm.h" #include "msp430-devices.h" /* This spec function is called if the user has provided an -mmcu option without an -mcpu option. It will place the correct -mcpu option for the given -mmcu onto the command line, to ensure the correct ISA multilib is selected. */ const char * msp430_select_cpu (int argc, const char ** argv) { if (argc == 0) { error ("expected an argument to %"); return NULL; } msp430_extract_mcu_data (argv[0]); if (extracted_mcu_data.name != NULL) { switch (extracted_mcu_data.revision) { case 0: return "-mcpu=msp430"; case 1: return "-mcpu=msp430x"; case 2: return "-mcpu=msp430xv2"; default: gcc_unreachable (); } } /* MCU wasn't found, the compiler proper will warn about this. */ return NULL; } /* Spec function to set a global variable to a specific value in the driver. The first argument is the variable name, and the second is the value to set it to. Currently only "msp430_warn_devices_csv" and "msp430_devices_csv_loc" are supported. The intention is that we can take a "Target" option and set the variable associated with it in the driver as well. Whilst the driver sees "Target" options, it does not set the variables associated with that option. */ const char * msp430_set_driver_var (int argc, const char ** argv) { if (argc != 2) error ("% expects 2 arguments"); else if (strcmp (argv[0], "msp430_warn_devices_csv") == 0) msp430_warn_devices_csv = atoi (argv[1]); else if (strcmp (argv[0], "msp430_devices_csv_loc") == 0) msp430_devices_csv_loc = argv[1]; else error ("unhandled arguments %qs and %qs to %", argv[0], argv[1]); return NULL; } /* Implement spec function `msp430_hwmult_libĀ“. */ const char * msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED, const char ** argv ATTRIBUTE_UNUSED) { int i; switch (argc) { case 1: if (strcasecmp (argv[0], "default")) error ("unexpected argument to msp430_select_hwmult_lib: %s", argv[0]); break; default: /* We can get three or more arguments passed to this function. This happens when the same option is repeated on the command line. For example: msp430-elf-gcc -mhwmult=none -mhwmult=16bit foo.c We have to use the last argument as our selector. */ if (strcasecmp (argv[0], "hwmult") == 0) { static struct hwmult_options { const char * name; const char * lib; } hwmult_options[] = { { "none", "-lmul_none" }, { "auto", "-lmul_AUTO" }, /* Should not see this one... */ { "16bit", "-lmul_16" }, { "32bit", "-lmul_32" }, { "f5series", "-lmul_f5" } }; for (i = ARRAY_SIZE (hwmult_options); i--;) if (strcasecmp (argv[argc - 1], hwmult_options[i].name) == 0) return hwmult_options[i].lib; } else if (strcasecmp (argv[0], "mcu") == 0) { msp430_extract_mcu_data (argv[argc - 1]); if (extracted_mcu_data.name != NULL) { switch (extracted_mcu_data.hwmpy) { case 0: return "-lmul_none"; case 2: case 1: return "-lmul_16"; case 4: return "-lmul_32"; case 8: return "-lmul_f5"; default: /* We have already checked the hwmpy values for validity in msp430_extract_mcu_data. */ gcc_unreachable (); break; } } } else error ("unexpected first argument to msp430_select_hwmult_lib: %s", argv[0]); break; case 0: error ("msp430_select_hwmult_lib needs one or more arguments"); break; } return "-lmul_none"; } /* Spec function. Used to place the path to the MSP430-GCC support files on the command line, prefixed with "-L", so the linker finds the linker scripts in that directory. */ const char * msp430_get_linker_devices_include_path (int argc ATTRIBUTE_UNUSED, const char **argv ATTRIBUTE_UNUSED) { char *devices_csv_path; if (msp430_check_env_var_for_devices (&devices_csv_path)) return NULL; return concat ("-L", msp430_dirname (devices_csv_path), NULL); } /* Spec function. Propagate -m{code,data}-region= to the linker, unless the lower region has been specified without -muse-lower-region-prefix also being used. */ const char * msp430_propagate_region_opt (int argc, const char **argv) { if (strcmp (argv[0], "lower") != 0) return argv[0]; else if ((argc == 2) && (strcmp (argv[1], "-muse-lower-region-prefix") == 0)) return argv[0]; /* argv[0] == "lower". */ return "none"; }