136ac495dSmrg /* Subroutines for the gcc driver.
2*8feb0f0bSmrg Copyright (C) 2015-2020 Free Software Foundation, Inc.
336ac495dSmrg Contributed by Georg-Johann Lay <avr@gjlay.de>
436ac495dSmrg
536ac495dSmrg This file is part of GCC.
636ac495dSmrg
736ac495dSmrg GCC is free software; you can redistribute it and/or modify
836ac495dSmrg it under the terms of the GNU General Public License as published by
936ac495dSmrg the Free Software Foundation; either version 3, or (at your option)
1036ac495dSmrg any later version.
1136ac495dSmrg
1236ac495dSmrg GCC is distributed in the hope that it will be useful,
1336ac495dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
1436ac495dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1536ac495dSmrg GNU General Public License for more details.
1636ac495dSmrg
1736ac495dSmrg You should have received a copy of the GNU General Public License
1836ac495dSmrg along with GCC; see the file COPYING3. If not see
1936ac495dSmrg <http://www.gnu.org/licenses/>. */
2036ac495dSmrg
21a2dc1f3fSmrg #define IN_TARGET_CODE 1
22a2dc1f3fSmrg
2336ac495dSmrg #include "config.h"
2436ac495dSmrg #include "system.h"
2536ac495dSmrg #include "coretypes.h"
2636ac495dSmrg #include "diagnostic.h"
2736ac495dSmrg #include "tm.h"
28*8feb0f0bSmrg #include "msp430-devices.h"
2936ac495dSmrg
30*8feb0f0bSmrg /* This spec function is called if the user has provided an -mmcu option without
31*8feb0f0bSmrg an -mcpu option. It will place the correct -mcpu option for the given -mmcu
32*8feb0f0bSmrg onto the command line, to ensure the correct ISA multilib is selected. */
33*8feb0f0bSmrg const char *
msp430_select_cpu(int argc,const char ** argv)34*8feb0f0bSmrg msp430_select_cpu (int argc, const char ** argv)
3536ac495dSmrg {
36*8feb0f0bSmrg if (argc == 0)
37*8feb0f0bSmrg {
38*8feb0f0bSmrg error ("expected an argument to %<msp430_select_cpu%>");
39*8feb0f0bSmrg return NULL;
4036ac495dSmrg }
41*8feb0f0bSmrg msp430_extract_mcu_data (argv[0]);
42*8feb0f0bSmrg if (extracted_mcu_data.name != NULL)
4336ac495dSmrg {
44*8feb0f0bSmrg switch (extracted_mcu_data.revision)
45*8feb0f0bSmrg {
46*8feb0f0bSmrg case 0: return "-mcpu=msp430";
47*8feb0f0bSmrg case 1: return "-mcpu=msp430x";
48*8feb0f0bSmrg case 2: return "-mcpu=msp430xv2";
49*8feb0f0bSmrg default:
50*8feb0f0bSmrg gcc_unreachable ();
51*8feb0f0bSmrg }
52*8feb0f0bSmrg }
53*8feb0f0bSmrg /* MCU wasn't found, the compiler proper will warn about this. */
54*8feb0f0bSmrg return NULL;
55*8feb0f0bSmrg }
56*8feb0f0bSmrg
57*8feb0f0bSmrg /* Spec function to set a global variable to a specific value in the driver.
58*8feb0f0bSmrg The first argument is the variable name, and the second is the value to set
59*8feb0f0bSmrg it to.
60*8feb0f0bSmrg Currently only "msp430_warn_devices_csv" and "msp430_devices_csv_loc" are
61*8feb0f0bSmrg supported.
62*8feb0f0bSmrg The intention is that we can take a "Target" option and set the variable
63*8feb0f0bSmrg associated with it in the driver as well. Whilst the driver sees "Target"
64*8feb0f0bSmrg options, it does not set the variables associated with that option. */
65*8feb0f0bSmrg const char *
msp430_set_driver_var(int argc,const char ** argv)66*8feb0f0bSmrg msp430_set_driver_var (int argc, const char ** argv)
67*8feb0f0bSmrg {
68*8feb0f0bSmrg if (argc != 2)
69*8feb0f0bSmrg error ("%<msp430_set_driver_var%> expects 2 arguments");
70*8feb0f0bSmrg else if (strcmp (argv[0], "msp430_warn_devices_csv") == 0)
71*8feb0f0bSmrg msp430_warn_devices_csv = atoi (argv[1]);
72*8feb0f0bSmrg else if (strcmp (argv[0], "msp430_devices_csv_loc") == 0)
73*8feb0f0bSmrg msp430_devices_csv_loc = argv[1];
74*8feb0f0bSmrg else
75*8feb0f0bSmrg error ("unhandled arguments %qs and %qs to %<msp430_set_driver_var%>",
76*8feb0f0bSmrg argv[0], argv[1]);
77*8feb0f0bSmrg return NULL;
78*8feb0f0bSmrg }
7936ac495dSmrg
8036ac495dSmrg /* Implement spec function `msp430_hwmult_lib´. */
8136ac495dSmrg
8236ac495dSmrg const char *
msp430_select_hwmult_lib(int argc ATTRIBUTE_UNUSED,const char ** argv ATTRIBUTE_UNUSED)83*8feb0f0bSmrg msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED,
84*8feb0f0bSmrg const char ** argv ATTRIBUTE_UNUSED)
8536ac495dSmrg {
8636ac495dSmrg int i;
8736ac495dSmrg
8836ac495dSmrg switch (argc)
8936ac495dSmrg {
9036ac495dSmrg case 1:
9136ac495dSmrg if (strcasecmp (argv[0], "default"))
9236ac495dSmrg error ("unexpected argument to msp430_select_hwmult_lib: %s", argv[0]);
9336ac495dSmrg break;
9436ac495dSmrg
9536ac495dSmrg default:
9636ac495dSmrg /* We can get three or more arguments passed to this function.
9736ac495dSmrg This happens when the same option is repeated on the command line.
9836ac495dSmrg For example:
9936ac495dSmrg msp430-elf-gcc -mhwmult=none -mhwmult=16bit foo.c
10036ac495dSmrg We have to use the last argument as our selector. */
10136ac495dSmrg if (strcasecmp (argv[0], "hwmult") == 0)
10236ac495dSmrg {
10336ac495dSmrg static struct hwmult_options
10436ac495dSmrg {
10536ac495dSmrg const char * name;
10636ac495dSmrg const char * lib;
10736ac495dSmrg } hwmult_options[] =
10836ac495dSmrg {
10936ac495dSmrg { "none", "-lmul_none" },
11036ac495dSmrg { "auto", "-lmul_AUTO" }, /* Should not see this one... */
11136ac495dSmrg { "16bit", "-lmul_16" },
11236ac495dSmrg { "32bit", "-lmul_32" },
11336ac495dSmrg { "f5series", "-lmul_f5" }
11436ac495dSmrg };
11536ac495dSmrg
11636ac495dSmrg for (i = ARRAY_SIZE (hwmult_options); i--;)
11736ac495dSmrg if (strcasecmp (argv[argc - 1], hwmult_options[i].name) == 0)
11836ac495dSmrg return hwmult_options[i].lib;
11936ac495dSmrg }
12036ac495dSmrg else if (strcasecmp (argv[0], "mcu") == 0)
12136ac495dSmrg {
122*8feb0f0bSmrg msp430_extract_mcu_data (argv[argc - 1]);
123*8feb0f0bSmrg if (extracted_mcu_data.name != NULL)
12436ac495dSmrg {
125*8feb0f0bSmrg switch (extracted_mcu_data.hwmpy)
12636ac495dSmrg {
12736ac495dSmrg case 0: return "-lmul_none";
12836ac495dSmrg case 2:
12936ac495dSmrg case 1: return "-lmul_16";
13036ac495dSmrg case 4: return "-lmul_32";
13136ac495dSmrg case 8: return "-lmul_f5";
13236ac495dSmrg default:
133*8feb0f0bSmrg /* We have already checked the hwmpy values for
134*8feb0f0bSmrg validity in msp430_extract_mcu_data. */
135*8feb0f0bSmrg gcc_unreachable ();
13636ac495dSmrg break;
13736ac495dSmrg }
13836ac495dSmrg }
13936ac495dSmrg }
14036ac495dSmrg else
141*8feb0f0bSmrg error ("unexpected first argument to msp430_select_hwmult_lib: %s",
142*8feb0f0bSmrg argv[0]);
14336ac495dSmrg break;
14436ac495dSmrg
14536ac495dSmrg case 0:
14636ac495dSmrg error ("msp430_select_hwmult_lib needs one or more arguments");
14736ac495dSmrg break;
14836ac495dSmrg }
14936ac495dSmrg
15036ac495dSmrg return "-lmul_none";
15136ac495dSmrg }
152*8feb0f0bSmrg
153*8feb0f0bSmrg /* Spec function. Used to place the path to the MSP430-GCC support files
154*8feb0f0bSmrg on the command line, prefixed with "-L", so the linker finds the linker
155*8feb0f0bSmrg scripts in that directory. */
156*8feb0f0bSmrg const char *
msp430_get_linker_devices_include_path(int argc ATTRIBUTE_UNUSED,const char ** argv ATTRIBUTE_UNUSED)157*8feb0f0bSmrg msp430_get_linker_devices_include_path (int argc ATTRIBUTE_UNUSED,
158*8feb0f0bSmrg const char **argv ATTRIBUTE_UNUSED)
159*8feb0f0bSmrg {
160*8feb0f0bSmrg char *devices_csv_path;
161*8feb0f0bSmrg if (msp430_check_env_var_for_devices (&devices_csv_path))
162*8feb0f0bSmrg return NULL;
163*8feb0f0bSmrg return concat ("-L", msp430_dirname (devices_csv_path), NULL);
164*8feb0f0bSmrg }
165*8feb0f0bSmrg
166*8feb0f0bSmrg /* Spec function. Propagate -m{code,data}-region= to the linker, unless the
167*8feb0f0bSmrg lower region has been specified without -muse-lower-region-prefix also being
168*8feb0f0bSmrg used. */
169*8feb0f0bSmrg const char *
msp430_propagate_region_opt(int argc,const char ** argv)170*8feb0f0bSmrg msp430_propagate_region_opt (int argc, const char **argv)
171*8feb0f0bSmrg {
172*8feb0f0bSmrg if (strcmp (argv[0], "lower") != 0)
173*8feb0f0bSmrg return argv[0];
174*8feb0f0bSmrg else if ((argc == 2) && (strcmp (argv[1], "-muse-lower-region-prefix") == 0))
175*8feb0f0bSmrg return argv[0]; /* argv[0] == "lower". */
176*8feb0f0bSmrg return "none";
177*8feb0f0bSmrg }
178