ARM ASM: Bad Instruction end - c

In my current project we are using Segger embOS as an RTOS.
The target system is an ARM Cortex-M MCU
The RTOS has some code written in assembler.
However the ASM code produces an error:
RTOS.s:69: Error: bad instruction `end'
According to the ARM assembler reference guide
http://infocenter.arm.com/help/topic/com.arm.doc.dui0489f/DUI0489F_arm_assembler_reference.pdf
(Chapter 6.8.5) the instruction "END" exists (I'm not sure if assembler is case sensitive)
although this instruction exists, the assembly won't compile.
Each of the includes files terminate with an
.end (note the "." and the lower case letters)
File RTOS.s
#define OS_RTOS_S_INCLUDED
/*******************************************************************
*
* Code section includes selected code
*
********************************************************************
*/
#if (defined __ARM_ARCH_6M__) || (defined __ARM_ARCH_8M_BASE__)
//
// Cortex-M0
//
#include "RTOS_CM0.S"
#elif (defined (__VFP_FP__) && defined (__SOFTFP__))
//
// Cortex-M3 or Cortex-M4 without VFP
//
#include "RTOS_CM3.S"
#elif (defined (__VFP_FP__) && !defined (__SOFTFP__))
//
// Cortex-M4 with VFP
//
#include "RTOS_CM4F.S"
#else
#error "No RTOS.S for selected CPU available, check configuration"
#endif
/********************************************************************/
END//Line 69
/***** End of file ************************************************/
Switch the END to .end seams to resolve the compile error. However the function defined in the assembler script are not found by the linker (this could be different problem though)
So my question is: Why is the instruction END a bad instruction?

The END directive is an armasm directive, not an ARM assembly instruction. That is to say it is an instruction to the assembler during the build of the code, not an instruction to the processor. .end is the GNU as (GNU assembler) equivalent.
Different toolchains use different assembler directives and syntax. You are trying to build the armasm source code using gas (GNU assembler) which is not compatible. You will certainly encounter other issues than this that will prevent you building ARM toolchain specific source code/object with the GNU toolchain - not least, apart from the technical issues, there are legal issues given that embOS licences are toolchain specific.
Each Segger embOS license is provided for a specific toolchain. If you wish to use a different toolchain you will need a new license and different toolchain specific code/library - even if you have a source code licence; it is not just a legal issue but a technical one - Segger do not provide the code for all toolchains with a license for a single toolchain. If you only have an object code licence, it may not link if using a different toolchain (or in some cases even different toolchain version) than the object code was built with.
You need to check, but it is likely that you have a licence for the Keil ARM MDK toolchain (which includes armcc/armasm etc.). It is not a free tool one way or another you need to either purchase an embOS licence for GNU, or licence to the toolchain you have the embOS licence for.
You might do well in any case to update your Segger support and maintenance licence in any case, so you can get technical support from them.

Related

Can't use _m_prefetchw intrinsic with gcc/clang -march=native on older Intel CPU?

I ran into this problem while compiling my project with Clang. I want to use the intrinsic function _m_prefetchw for that I included x86intrin.h, but for some reason my flow is not reaching the _m_prefetchw definition.
I checked the x86intrin.h header file of Clang and I dont have the __PRFCHW__ defined in order to include prfchwintrin.h although I do have PREFETCHW supported by my PC (I ran coreinfo to know this).
does anyone know why __PRFCHW__ isn't defined although I have PREFETCHW supported?
code example:
#include <x86intrin.h>
int main(){
int i = 10;
_m_prefetchw(&i);
return 0;
}
After running I get the error error LNK2019: unresolved external symbol _m_prefetchw referenced in function main
I dug into my clang include header files and found this in x86intrin.h:
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__PRFCHW__)
#include <prfchwintrin.h>
#endif
And _m_prefetchw is defined in the prfchwintrin.h file.
My processor is Intel Xeon E5-2690, Clang version is 9.0.1.
Manually use -mprfchw to tell the compiler to let you use _m_prefetchw even when compiling for a -march= where prefetchw is only a NOP.
-march=native only includes -mprfchw if it will actually have an effect. See What is the effect of second argument in _builtin_prefetch()? for more details on how compilers "think about" availability of prefetch instructions and CPUID.
Your E5-2690 is a Sandybridge, older than Broadwell which introduced (on the Intel side) real support for PREFETCHW.
Any non-ancient Intel CPUs can run prefetchw as a NOP (http://ref.x86asm.net/coder64.html#gen_note_NOP_0F0D), but only Broadwell and later actually advertizes the CPU feature in its CPUID, and only Broadwell and later actually do anything different from a NOP. (AMD CPUs support it as an actual prefetch into Exclusive state ever since 3DNow! introduced it.)
Running as a NOP instead of faulting is apparently necessary for installing 64-bit Windows, so a lot of discussion about "supporting" PREFETCHW revolves around not faulting, rather than its CPUID bit and actually doing anything. For example, comments on Windows 10 64-bit requirements: Does my CPU support PrefetchW? discuss this difference in "support" (as in won't fault) vs. "support" as in actually does something.
This forum thread mentions that P4 Nocona faults on prefetchw, and thus can't install Windows 8.1. But Core2 and later do have "won't fault" support.

How to check that microprocessor is Altera Nios?

I writes some C-program code for Altera/Nios II microprocessor (uP). This code will be different with Altera Arm 9 microprocessor. So I need to write 2 different code pieces for different uP-s. How can I check in execution time which uP is present. Or more simple, current uP is Nios or not.
As the two processors are from different architectures, you will not be able to check which processor is running at run-time. You could do it at compile time, as you will have a specific define flag set by your toolchain (see https://sourceforge.net/p/predef/wiki/Architectures/). For Arm it should be __arm__ or similar, depending on the toolchain you are using for the HPS.
#ifdef __arm__
<specific code for HPS>
#else
<specific code for NIOS>
#endif /* __arm__ */
You can also look at the toolchain's defines using the c pre-processor command (cpp):
<toolchain>-cpp -dM /dev/null
Note: for Arm processor, the MIDR register could be used to know which type you are running and this one could be accessed at runtime. But when building for NIOS II, you would have a compilation error. So you need to use the preprocessor to call specific Arm register name and to remove the code when building for NiosII.
Presumably it will be compiled with a different compiler? These compilers will (very likely) have a #define of some sort which you can use to build different code for each one.
You can make the compiler dump all its default preprocessor defines using:
echo | ./nios2-elf-gcc.exe -dM -E -
This will in particular emit:
#define nios2 1

Migrating from ARM 5 to ARM 6 Compiler: Unknown type name '__STATIC_INLINE' in ARM CMSIS file

Currently migrating a large embedded C project in uVision from ARM 5 to ARM 6 compiler. The most persistent error is
error: unknown type name '__STATIC_INLINE'
which occurs in the core_cm4.h file which is provided by ARM which is read-only, hence I am hesitant to edit it. Nevertheless, I changed (under the CMSIS definitions, under #if defined (__CC_ARM)), the #define __STATIC_INLINE static __inline__ by adding the two underscores after inline, as specified in the ARM 5 to 6 migration guide, but it still is not working.
How to fix this?
I definitely wouldn't touch that file. Instead, ensure you have the most up to date version of core_cm4.h, and use it as reference against your own.
The issue could stem from the ARM compiler being incorrectly installed, as __inline is an ARM specific keyword. Ensure all of your tool chain is correct, and see if that works.

How to check with Intel intrinsics if AVX extensions is supported by the CPU?

I'm writing a program using Intel intrinsics. I want to use _mm_permute_pd intrinsic, which is only available on CPUs with AVX. For CPUs without AVX I can use _mm_shuffle_pd but according to the specs it is much slower than _mm_permute_pd. Do the header files for Intel intrinsics define constants that allow me to distinguish whether AVX is supported so that I can write sth like this:
#ifdef __IS_AVX_SUPPORTED__ // is there sth like this defined?
// use _mm_permute_pd
# else
// use _mm_shuffle_pd
#endif
? I have found this tutorial, which shows how to perform a runtime check but I need to do a static, compile-time check for the current machine.
GCC, ICC, MSVC, and Clang all define a macro __AVX__ which you can check. In fact it's the only SIMD constant defined by all those compilers (MSVC is the one that breaks the mold). This only tells you if your code was compiled with AVX support (e.g. -mavx with GCC or /arch:AVX with MSVC) it does not tell you if your CPU supports AVX. If you want to know if the CPU supports AVX you need to check CPUID. Here, asm-in-c-error, is an example to read CPUID from all those compilers.
To do this properly I suggest you make a CPU dispatcher.
Edit: In case anyone wants to know how to use the values from CPUID to find out if AVX is available see https://github.com/Mysticial/FeatureDetector
I assume you are using Intel C++ Compiler. In this case - yes, there are such macros: Intel C++ Compiler Reference Guide: __AVX__, __AVX2__.
P.S. Be aware that if you compile you application with AVX instruction set enabled it will fail on CPUs not supporting AVX. If you are going to distribute your software as source code package and compile on target machine - this is may be a viable solution. Otherwise you should check for AVX dynamically.
P.P.S. There are several options for ICC. Take a look at the following compiler options and also references from it to other.
It seems to me that the only way is to compile and run a program that identifies whether AVX is available. Then manually or automatically compile separate code with or without AVX functions. For VS 2013, I would used my code in commomAVX folder in the following to identify hasAVX (or not) and use this to execute one of two different BAT files to compile and link the appropriate program.
http://www.roylongbottom.org.uk/gigaflops-benchmarks.zip
My question was to help to identify a solution regarding the use of suitable compile options such as /arch:AVX.

IAR Embedded Workbench - setting endian-ness of variable

I'm using IAR Embedded Workbench for ARM (ARM7TDMI-S) and the majority of my work is done using little-endian format. However, I saw in the manual that I can do something like :
__big_endian int i, j;
to declare those two variables as big endian (while the rest of the app as little endian). This seems like a fantastic feature, but when I try to compile, I always get the errror:
Error[Pa002]: the type attribute "__big_endian" is not allowed on this declaration.
The big endian line above is copied directly from the manual, but it does not work. This is a great feature of the compiler and would make life a big easier. Any ideas how to get it working?
I have my language conformance set to 'Allow IAR extensions' on the C/C++ Compiler options tab on the IDE options.
From IAR's docs:
The __big_endian keyword is available when you compile for ARMv6 or higher.
ARMv6 added the SETEND instruction which manipulates a state bit to configure which endianess the processor will use when performing a load/store operation. Looks like IAR's __big_endian intrinsic just causes the processor to manipulate that bit when accessing the variable tagged with that attribute.
The ARM7TDMI is an ARMv4 (or maybe ARMv5) architecture device (if I recall correctly).
This is an extension feature in the IAR compiler and so has to be enabled either by using the -e option of the command line or by enabling the IAR extensions in the compiler options page of the IDE. This keyword is not compatible with the --strict_ansi compiler option.

Resources