/*******************************************************************************
* Copyright (c) 2015 ARM Ltd. and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* ARM Ltd and ARM Germany GmbH - Initial API and implementation
*******************************************************************************/
package com.arm.cmsis.pack.build.armcc;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IHoldsOptions;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import com.arm.cmsis.pack.build.IBuildSettings;
import com.arm.cmsis.pack.build.settings.ILinkerScriptGenerator;
import com.arm.cmsis.pack.build.settings.RteToolChainAdapter;
import com.arm.cmsis.pack.common.CmsisConstants;
/**
* Toolchain adapter for ARMCC 5.x compiler
*
*/
public class ArmccToolChainAdapter extends RteToolChainAdapter {
static public final int ARMCC5_ASMDEFINES_OPTION = IBuildSettings.RTE_USER_OPTION + 1;
static public final int ARMCC_ENABLE_TOOL_SPECIFIC_OPTION = IBuildSettings.TOOLCHAIN_USER_OPTION + 1;
static public final int ARMCC_USE_MICROLIB = IBuildSettings.TOOLCHAIN_USER_OPTION + 2;
static public final int CPU_FPU_OPTION = IBuildSettings.TOOLCHAIN_USER_OPTION + 5;
static public final int C5_LANGUAGE_MODE = IBuildSettings.TOOLCHAIN_USER_OPTION + 6;
static public final int CPP5_LANGUAGE_MODE = IBuildSettings.TOOLCHAIN_USER_OPTION + 7;
static public final int C6_LANGUAGE_MODE = IBuildSettings.TOOLCHAIN_USER_OPTION + 8;
static public final int CPP6_LANGUAGE_MODE = IBuildSettings.TOOLCHAIN_USER_OPTION + 9;
static public final String CORTEX = "Cortex"; //$NON-NLS-1$
static public final String CORTEX_A = "Cortex-A"; //$NON-NLS-1$
static public final String GENERIC = "Generic"; //$NON-NLS-1$
static public final String GENERIC_ARMV8M_BASE = GENERIC + ".ARMv8-M.Base"; //$NON-NLS-1$
static public final String GENERIC_ARMV8M_MAIN = GENERIC + ".ARMv8-M.Main"; //$NON-NLS-1$
static public final String SPACE = " "; //$NON-NLS-1$
static public final String QUOTE = "\""; //$NON-NLS-1$
static public final String NoFPU = "NoFPU"; //$NON-NLS-1$
static public final String SETA = " SETA "; //$NON-NLS-1$
static public final String AUTO = "auto"; //$NON-NLS-1$
static public final String LITTLE = "little"; //$NON-NLS-1$
static public final String BIG = "big"; //$NON-NLS-1$
static protected final String ENDIAN_PREFICS_5 = "com.arm.tool.c.compiler.option.endian."; //$NON-NLS-1$
static protected final String ENDIAN_PREFICS_6 = "com.arm.tool.c.compiler.v6.base.option.endian."; //$NON-NLS-1$
static protected final String C5_AUTO = "com.arm.tool.c.compile.option.lang.auto"; //$NON-NLS-1$
static protected final String C5_C90 = "com.arm.tool.c.compile.option.lang.c90"; //$NON-NLS-1$
static protected final String C5_C99 = "com.arm.tool.c.compile.option.lang.c99"; //$NON-NLS-1$
static protected final String C5_CPP = "com.arm.tool.c.compile.option.lang.cpp"; //$NON-NLS-1$
static protected final String C5_CPP11 = "com.arm.tool.c.compile.option.lang.cpp11"; //$NON-NLS-1$
static protected final String CPP5_AUTO = "com.arm.tool.cpp.compiler.option.lang.auto"; //$NON-NLS-1$
static protected final String CPP5_C90 = "com.arm.tool.cpp.compiler.option.lang.c90"; //$NON-NLS-1$
static protected final String CPP5_C99 = "com.arm.tool.cpp.compiler.option.lang.c99"; //$NON-NLS-1$
static protected final String CPP5_CPP = "com.arm.tool.cpp.compiler.option.lang.cpp"; //$NON-NLS-1$
static protected final String CPP5_CPP11 = "com.arm.tool.cpp.compiler.option.lang.cpp11"; //$NON-NLS-1$
static protected final String C6_C99 = "com.arm.tool.c.compiler.v6.base.option.lang.c99"; //$NON-NLS-1$
static protected final String CPP6_C99 = "com.arm.tool.cpp.compiler.v6.base.option.lang.c99"; //$NON-NLS-1$
static protected final String CPP6_CPP11 = "com.arm.tool.cpp.compiler.v6.base.option.lang.c11"; //$NON-NLS-1$
protected int compilerVersion = 5; // major compiler version : 5 or 6
public ArmccToolChainAdapter() {
}
@Override
public void setToolChainOptions(IConfiguration configuration, IBuildSettings buildSettings) {
if(configuration == null)
return;
//String baseID =configuration.getBaseId();
IToolChain toolChain = configuration.getToolChain();
if(toolChain == null)
return;
String baseID = toolChain.getBaseId();
if(baseID.startsWith("com.arm.toolchain.v6")) //$NON-NLS-1$
compilerVersion = 6;
super.setToolChainOptions(configuration, buildSettings);
}
@Override
public ILinkerScriptGenerator getLinkerScriptGenerator() {
return new ScatterFileGenerator();
}
@Override
protected void updateRteOption(int oType, IConfiguration configuration, IHoldsOptions tool, IOption option, IBuildSettings buildSettings) throws BuildException {
switch(oType) {
// we add libraries with absolute paths => ignore lib paths
case IBuildSettings.RTE_LIBRARY_PATHS:
return; // NO UPDATE OF THAT
default :
break;
}
super.updateRteOption(oType, configuration, tool, option, buildSettings);
}
@Override
protected Collection<String> getStringListValue(IBuildSettings buildSettings, int oType) {
if (oType == IBuildSettings.RTE_LIBRARY_PATHS) {
return null; // we add libraries with absolute paths => ignore lib paths
} else if (oType == ARMCC5_ASMDEFINES_OPTION) {
List<String> asmDefines = new LinkedList<String>();
Collection<String> defines = buildSettings.getStringListValue(IBuildSettings.RTE_DEFINES);
if(defines != null) {
for(String d : defines) {
String value = getAsmDefString(d);
asmDefines.add(value);
}
}
return asmDefines; // paths are not needed as libs are absolute
}
return super.getStringListValue(buildSettings, oType);
}
@Override
protected List<String> cleanStringList(List<String> value, int oType) {
switch(oType){
case ARMCC5_ASMDEFINES_OPTION:
case IBuildSettings.RTE_DEFINES:
case IBuildSettings.RTE_INCLUDE_PATH:
case IBuildSettings.RTE_LIBRARIES:
case IBuildSettings.RTE_CMISC:
case IBuildSettings.RTE_ASMMISC:
case IBuildSettings.RTE_LMISC:
value.clear();
break;
case IBuildSettings.RTE_LIBRARY_PATHS:
default:
break;
}
return value; // do nothing for all other lists
}
protected String getAsmDefString(String d) {
String val = "1"; //$NON-NLS-1$
String s = CmsisConstants.EMPTY_STRING;
int pos = d.indexOf('=');
if(pos > 0) {
val = d.substring(pos + 1);
s += d.substring(0, pos);
} else {
s += d;
}
s += SETA;
s += val;
return s;
}
@Override
protected String getRteOptionValue(int oType, IBuildSettings buildSettings, IOption option) {
switch(oType){
case ARMCC_ENABLE_TOOL_SPECIFIC_OPTION:
return CmsisConstants.ZERO; // returns "0" false to disable it
case CPU_FPU_OPTION:
return getCpuFpuOptionValue(buildSettings, option);
case C5_LANGUAGE_MODE:
return C5_C99;
case C6_LANGUAGE_MODE:
return C6_C99;
case IBuildSettings.ENDIAN_OPTION:
return getEndianOptionValue( buildSettings);
case IBuildSettings.ARCH_OPTION:
return getTargetArchOptionValue( buildSettings);
default:
break;
}
return super.getRteOptionValue(oType, buildSettings, option);
}
protected String getTargetArchOptionValue(IBuildSettings buildSettings) {
return null; // default does not have it
}
protected String getEndianOptionValue(IBuildSettings buildSettings) {
String endian = getDeviceAttribute(IBuildSettings.ENDIAN_OPTION, buildSettings);
String val = AUTO;;
if (endian != null) {
if(endian.equals(CmsisConstants.LITTLENDIAN)) {
val = LITTLE;
} else if(endian.equals(CmsisConstants.BIGENDIAN)) {
val = BIG;
}
}
String prefix = compilerVersion >= 6 ? ENDIAN_PREFICS_6 : ENDIAN_PREFICS_5;
return prefix + val;
}
@Override
protected int getRteOptionType(String id) {
switch(id){
case "com.arm.tool.c.compiler.option.target.enableToolSpecificSettings"://$NON-NLS-1$
case "com.arm.tool.assembler.option.target.enableToolSpecificSettings": //$NON-NLS-1$
case "com.arm.tool.c.linker.option.target.enableToolSpecificSettings": //$NON-NLS-1$
case "com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings": //$NON-NLS-1$
case "com.arm.tool.assembler.v6.base.options.target.enableToolSpecificSettings": //$NON-NLS-1$
case "com.arm.tool.linker.v6.base.options.target.enableToolSpecificSettings": //$NON-NLS-1$
return ARMCC_ENABLE_TOOL_SPECIFIC_OPTION;
case "com.arm.toolchain.ac5.options.libs.useMicroLib": //$NON-NLS-1$
case "com.arm.toolchain.v6.base.options.libs.useMicroLib": //$NON-NLS-1$
return ARMCC_USE_MICROLIB;
case "com.arm.toolchain.ac5.option.target.cpu_fpu": //$NON-NLS-1$
case "com.arm.toolchain.v6.base.options.target.cpu_fpu": //$NON-NLS-1$
return CPU_FPU_OPTION;
case "com.arm.toolchain.ac5.option.endian": //$NON-NLS-1$
case "com.arm.toolchain.v6.base.options.endian": //$NON-NLS-1$
return IBuildSettings.ENDIAN_OPTION;
case "com.arm.tool.c.compile.option.lang": //$NON-NLS-1$
return C5_LANGUAGE_MODE;
case "com.arm.tool.cpp.compiler.option.lang": //$NON-NLS-1$
return CPP5_LANGUAGE_MODE;
case "com.arm.tool.c.compiler.v6.base.option.lang": //$NON-NLS-1$
return C6_LANGUAGE_MODE;
case "com.arm.tool.cpp.compiler.v6.base.option.lang": //$NON-NLS-1$
return CPP6_LANGUAGE_MODE;
case "com.arm.tool.c.compiler.option.implicit.defmac": //$NON-NLS-1$
case "com.arm.tool.c.compiler.v6.base.option.implicit.defmac": //$NON-NLS-1$
case "com.arm.tool.assembler.v6.base.option.implicit.defmac": //$NON-NLS-1$
return IBuildSettings.RTE_DEFINES;
case "com.arm.tool.assembler.option.implicit.predefine": //$NON-NLS-1$
return ARMCC5_ASMDEFINES_OPTION;
case "com.arm.tool.c.compiler.option.implicit.incpath": //$NON-NLS-1$
case "com.arm.tool.assembler.option.implicit.incpath": //$NON-NLS-1$
case "com.arm.tool.c.compiler.v6.base.option.implicit.incpath": //$NON-NLS-1$
case "com.arm.tool.assembler.v6.base.option.implicit.incpath": //$NON-NLS-1$
return IBuildSettings.RTE_INCLUDE_PATH;
case "com.arm.tool.c.linker.implicit.libs": //$NON-NLS-1$
return IBuildSettings.RTE_LIBRARIES;
case "com.arm.tool.c.compiler.option.flags": //$NON-NLS-1$
case "com.arm.tool.c.compiler.v6.base.option.flags": //$NON-NLS-1$
return IBuildSettings.CMISC_OPTION;
case "com.arm.tool.assembler.option.flags": //$NON-NLS-1$
case "com.arm.tool.assembler.v6.base.option.flags": //$NON-NLS-1$
return IBuildSettings.AMISC_OPTION;
case "com.arm.tool.c.linker.option.flags": //$NON-NLS-1$
return IBuildSettings.LMISC_OPTION;
case "com.arm.tool.librarion.options.misc": //$NON-NLS-1$
return IBuildSettings.ARMISC_OPTION;
case "com.arm.tool.c.linker.option.scatter": //$NON-NLS-1$
return IBuildSettings.RTE_LINKER_SCRIPT;
case "com.arm.tool.c.compiler.option.implicit.flags": //$NON-NLS-1$
case "com.arm.tool.c.compiler.v6.base.option.implicit.flags": //$NON-NLS-1$
return IBuildSettings.RTE_CMISC;
case "com.arm.tool.assembler.option.implicit.flags": //$NON-NLS-1$
case "com.arm.tool.assembler.v6.base.option.implicit.flags": //$NON-NLS-1$
return IBuildSettings.RTE_ASMMISC;
case "com.arm.tool.c.linker.option.implicit.flags": //$NON-NLS-1$
return IBuildSettings.RTE_LMISC;
default:
break;
}
return IBuildSettings.UNKNOWN_OPTION;
}
@Override
protected int getOptionType(int valueType) {
return IBuildSettings.UNKNOWN_OPTION; // do set unknown options
}
/**
* Constructs value for CPU option
* @param buildSettings IBuildSettings to get infromation about device
* @param option option to set new value
* @return cpu option string
*/
protected String getCpuFpuOptionValue(IBuildSettings buildSettings, IOption option) {
String cpu = getDeviceAttribute(IBuildSettings.CPU_OPTION, buildSettings);
if(cpu == null ||cpu.isEmpty())
return null;
String cpuFpu = getCpuPrefix(cpu);
// do we need to change the value for Cortex-A processors or V8?
if(cpuFpu.startsWith(CORTEX_A) || cpuFpu.startsWith(GENERIC)) {
String oldValue = getCurrentStringValue(option);
if(oldValue != null && oldValue.startsWith(cpuFpu))
return null; // do not change option
}
String fpu = getDeviceAttribute(IBuildSettings.FPU_OPTION, buildSettings);
String fpuSuffix = getFpuSuffix(cpu, fpu);
if(fpuSuffix != null && !fpuSuffix.isEmpty()){
cpuFpu += '.' + fpuSuffix;
}
return cpuFpu;
}
/**
* Constructs CPU prefix for CPU-FPU option
* @param cpu device info's Dcore attribute
* @return CPU prefix string
*/
protected String getCpuPrefix(String cpu) {
if(cpu.equals("Cortex-M0+")) { //$NON-NLS-1$
return "Cortex-M0.Plus"; //$NON-NLS-1$
}
if(cpu.equals("ARMV8MBL")){ //$NON-NLS-1$
return GENERIC_ARMV8M_BASE;
}
if(cpu.equals("ARMV8MML")){ //$NON-NLS-1$
return GENERIC_ARMV8M_MAIN;
}
return cpu;
}
/**
* Returns required FPU string depending on device info attributes
* @param cpu device info's Dcore attribute
* @param fpu device info's Dfpu attribute
* @return resulting FPU string
*/
public String getFpuSuffix(String cpu, String fpu) {
if(cpu == null || fpu == null || fpu.equals(CmsisConstants.NO_FPU) || !coreHasFpu(cpu)) {
return NoFPU;
}
boolean dp = fpu.equals(CmsisConstants.DP_FPU);
switch(cpu) {
case "Cortex-M4": //$NON-NLS-1$
return compilerVersion >= 6 ? "FPv4_SP_D16" : "FPv4_SP"; //$NON-NLS-1$ //$NON-NLS-2$
case "Cortex-M7": //$NON-NLS-1$
if(compilerVersion >= 6)
return dp? "FPv5_D16" : "FPv5_SP_D16"; //$NON-NLS-1$ //$NON-NLS-2$
return dp? "FPv5_D16" : "FPv5_SP"; //$NON-NLS-1$ //$NON-NLS-2$
case "Cortex-R4": //$NON-NLS-1$
case "Cortex-R5": //$NON-NLS-1$
return "VFPv3_D16"; //$NON-NLS-1$
case "Cortex-R7": //$NON-NLS-1$
case "Cortex-R8": //$NON-NLS-1$
return "VFPv3_D16_FP16"; //$NON-NLS-1$
case "Cortex-A5": //$NON-NLS-1$
case "Cortex-A7": //$NON-NLS-1$
case "Cortex-A53": //$NON-NLS-1$
case "Cortex-A57": //$NON-NLS-1$
case "Cortex-A72": //$NON-NLS-1$
if(compilerVersion >= 6 )
return dp? "VFPv4" : "VFPv4.Neon"; //$NON-NLS-1$ //$NON-NLS-2$
return dp? "VFPv4_D16" : "VFPv4.Neon"; //$NON-NLS-1$ //$NON-NLS-2$
case "Cortex-A8": //$NON-NLS-1$
if(compilerVersion >= 6)
return "VFPv3.Neon"; //$NON-NLS-1$
return "VFPv3"; //$NON-NLS-1$
case "Cortex-A9": //$NON-NLS-1$
if(compilerVersion >= 6 )
return dp? "VFPv3_D16_FP16" : "VFPv3_FP16.Neon"; //$NON-NLS-1$ //$NON-NLS-2$
return dp? "VFPv3_D16_FP16" : "VFPv3_FP16.Neon"; //$NON-NLS-1$ //$NON-NLS-2$
case "Cortex-A15": //$NON-NLS-1$
return dp? "VFPv4_D16" : "VFPv4.Neon"; //$NON-NLS-1$ //$NON-NLS-2$
case "Cortex-A12": //$NON-NLS-1$
case "Cortex-A17": //$NON-NLS-1$
return "VFPv4.Neon"; //$NON-NLS-1$
case "ARMV8MML": //$NON-NLS-1$
return "FPv5_D16"; //$NON-NLS-1$
}
return NoFPU;
}
}