Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

error: unknown opcode "movsx"

mtlroom
Beginner
874 Views
Here's code that compiles without any problem with GCC, but icl reports unknown opcode error. (11.1.066 [IA-32] on Win2003-32)


[cpp]#define FDEC_STRIDE 32
__declspec(align(8)) static const unsigned char  pb_12345678[8] = {1,2,3,4,5,6,7,8};
__declspec(align(8)) static const unsigned char  pb_m87654321[8] = {-8,-7,-6,-5,-4,-3,-2,-1};

static void predict_16x16_p_ssse3( unsigned char *src )
{
    int a, b, c, i00;
    int H, V;
    __asm__ (
        "movq           %1, %%mm1 n"
        "movq         8+%1, %%mm0 n"
        "palignr $7, -8+%1, %%mm1 n"
        "pmaddubsw      %2, %%mm0 n"
        "pmaddubsw      %3, %%mm1 n"
        "paddw       %%mm1, %%mm0 n"
        "pshufw $14, %%mm0, %%mm1 n"
        "paddw       %%mm1, %%mm0 n"
        "pshufw  $1, %%mm0, %%mm1 n"
        "paddw       %%mm1, %%mm0 n"
        "movd        %%mm0, %0    n"
        "movsx         %w0, %0    n"
        :"=r"(H)
        :"m"(src[-FDEC_STRIDE]), "m"(*pb_12345678), "m"(*pb_m87654321)
    );
}

int main(int argv, char**argc){
    predict_16x16_p_ssse3((unsigned char*)argc);
}
[/cpp]
0 Kudos
4 Replies
TimP
Honored Contributor III
874 Views
Windows compiler asm syntax defaults are totally incompatible with linux compiler asm defaults. The closest practical option for compatibility would be SSE intrinsics.
0 Kudos
mtlroom
Beginner
874 Views
Quoting - tim18
Windows compiler asm syntax defaults are totally incompatible with linux compiler asm defaults. The closest practical option for compatibility would be SSE intrinsics.

?!? How is this reply related to my question???
It's a plain vanila instruction movsx that I'm asking here about (see the subject).

in short code could have been:

[cpp]static int movexs_16_32(int H)
{  
    __asm__(  
        "movsx         %w0, %0    n"  
        :"=r"(H)  
        :
    );
	return H;
}
[/cpp]

0 Kudos
Brandon_H_Intel
Employee
874 Views
Quoting - mtlroom

?!? How is this reply related to my question???
It's a plain vanila instruction movsx that I'm asking here about (see the subject).

in short code could have been:

[cpp]static int movexs_16_32(int H)
{  
    __asm__(  
        "movsx         %w0, %0    n"  
        :"=r"(H)  
        :
    );
	return H;
}
[/cpp]


The customer is correct - even the Intel C++ Compiler for Windows* should be able to accept GNU-style inline assembly (with some exceptions detailed in the user's guide). I've submitted a problem report to our code generator team to address this, and as progress is made I'll update this thread.

I do have the Microsoft-style inline asm equivalent if you're interested - should be something like:

__asm {
mov ax, WORD PTR src[-FDEC_STRIDE]
movsx eax, ax
mov H, eax
}

if I'm reading your GNU inline asm right. Not sure what the -FDEC_STRIDE is supposed to do as the pointer index, so it may be that the code being generated isn't what you're looking for.
0 Kudos
Brandon_H_Intel
Employee
874 Views

The customer is correct - even the Intel C++ Compiler for Windows* should be able to accept GNU-style inline assembly (with some exceptions detailed in the user's guide). I've submitted a problem report to our code generator team to address this, and as progress is made I'll update this thread.

I do have the Microsoft-style inline asm equivalent if you're interested - should be something like:

__asm {
mov ax, WORD PTR src[-FDEC_STRIDE]
movsx eax, ax
mov H, eax
}

if I'm reading your GNU inline asm right. Not sure what the -FDEC_STRIDE is supposed to do as the pointer index, so it may be that the code being generated isn't what you're looking for.

I'm copying a response from one of our code generator developers on this:

The "movsx" form of the movsx instruction is not parsed by the compiler's internal GNU-asm compatible assembler because the GNU assembler itself treats the "movsx" form inconsistenly. Instead, the compiler's internal GNU-asm compatible assembler uses the specific forms like "movswl" and "movsbw" which explicitly indicate the sizes of the source and destination.

This is well documented in the GNU assembler (as) manual. Here is an excerpt from section 21.3 ("Instruction Naming") in the as manual on RedHat's site (www.redhat.com/docs/manuals/enterprise/RHEL-4.../pdf/rhel-as-en.pdf):

Almost all instructions have the same names in AT&T and Intel format. There are a few exceptions.
The sign extend and zero extend instructions need two sizes to specify them. They need a size to
sign/zero extend from and a size to zero extend to. This is accomplished by using two instruction
mnemonic suffixes in AT&T syntax. Base names for sign extend and zero extend are movs... and
movz... in AT&T syntax (movsx and movzx in Intel syntax). The instruction mnemonic suffixes are
tacked on to this base name, the from suffix before the to suffix. Thus, movsbl %al, %edx is AT&T
syntax for "move sign extend from %al to %edx." Possible suffixes, thus, are bl (from byte to long),
bw (from byte to word), wl (from word to long), bq (from byte to quadruple word), wq (from word to
quadruple word), and lq (from long to quadruple word).

i.e. Not even the as manual suggests using "movsx".

Furthermore, experiments with the GNU assembler on RedHat EL 5.4 show that the GNU assembler translates the illogically in some cases. Consider the following GNU asm syntax:

movsx (%edx), %eax

In this case it is not clear what the size of the source operand is. Assembling this with /usr/bin/as (32-bit) and then dumping the resulting object file with objdump -d shows that the GNU assembler produced:

movsbl (%edx), %eax

i.e. In the absence of any information on the source size, the GNU assembler arbitrarily decided the source size was "byte".

In order to avoid this ambiguity with the "movsx" form in GNU-style assembly, the Intel compiler uses the forms documented above in the manual. Thus the original GNU-assembly example in test3.cpp of:

movsx %w0, %0

is more precisely written as:

movswl %w0, %0

This latter form is properly recognized by the Intel compiler's internal GNU-asm compatible assembler.
0 Kudos
Reply