i386 movsxw instruction in x86_64 - macos

I am trying to compile Apple's Libm (version 2026, tarball here). The only file that is failing to compile properly is Source/Intel/frexp.s because
/<path>/Libm-2026/Source/Intel/frexp.s:239:5:
error: invalid instruction mnemonic 'movsxw'
movsxw 8+(8 + (32 - 8))(%rsp), %eax
^~~~~~
/<path>/Libm-2026/Source/Intel/frexp.s:291:5:
error: invalid instruction mnemonic 'movsxw'
movsxw 8(%rsp), %eax
^~~~~~
Looking around on the Internet I can only find very scanty details of the movsxw instruction but it does appear to exist for i386 architectures. I am running OS X 10.9.3 with a Core i5 processor. The macro __x86_64__ is predefined, however it seems the __i386__ macro is NOT *.
I was under the impression that the x86_64 instruction set was fully compatible with the i386 set. Is this incorrect? I can only assume that the movsxw instruction does not exist in the x86_64 instruction set, thus my question is: what does it do, and what can I replace it with from the x86_64 instruction set?
*Checked with: clang -dM -E -x c /dev/null

The canonical at&t syntax for movsxw is movswl although at least some assembler versions seem to accept the former too.

movsxb : Sign-extend a byte into the second operand
movsxw : Sign-extend a word (16 bits) into the second operand
movsxl : Sign-extend a long (32 bits) into the second operand
movsxw assembles just fine for me in 64-bit mode using gcc/as (4.8.1/2.24). I don't have clang for x86 installed on this machine, but you could try specifying the size of the second operand (i.e. change movsxw to movsxwl, which would be "sign-extend word into long").

Related

Wierd GCC behaviour with ARM assembler. ANDSEQ instruction

If I try to assemble this program:
.text
main:
andseq r1,r3,r2,lsl #13
With the command gcc -c test.s, I get the following error:
Error: bad instruction `andseq r1,r3,r2,lsl#13'
After some tries I replaced andseq with andeqs, and now it compiles fine.
But if I dump the resulting obj file with objdump -d test.o I get this:
Disassembly of section .text:
00000000 <main>:
0: 00131682 andseq r1, r3, r2, lsl #13
Note how the instruction is decoded as andseq ....
Am I missing something? Is this a bug?
My system is Raspbian GNU/Linux 8, and my gcc is: gcc (Raspbian 4.9.2-10) 4.9.2. I have also tested with gcc-8.1.0 (edit, not really see edit), same results.
EDIT:
In fact, it seems Im using the same binutils with gcc8, so I really only tested this GNU assembler (GNU Binutils for Raspbian) 2.25. I'll try a more recent assembler.
For compatibility with old assembly files, GNU as defaults to divided syntax for ARM assembly. In divided syntax, andeqs is the correct mnemonic for the instruction you desire. You can issue a .syntax unified directive to select unified syntax, in which andseq is the correct mnemonic.
GNU objdump on the other hand only knows unified syntax, which explains the apparent inconsistency.
For new developments, I advise you to consistently use unified syntax if possible.
There is a good UAL vs pre-UAL mnemonic table on ARMv8 Appendix K6 "Legacy Instruction Syntax for AArch32 Instruction Sets"
One of the entries of that table is:
Pre-UAL syntax UAL equivalent
AND<c>S ANDS<c>
where eq is one of the possible condition codes <c>.

Pascal, Ordinal error

I need to run a loop for 10 billion times and failing to run it, please help me get this done. I am getting ordinal error.
program kittu;
var i:qword;
j:qword;
k:qword;
begin
i:= 10000000000;
k:= 0;
for j:=1 to i do
begin
k:=k+1;
end;
writeln(k);
readln();
end.
From the FreePascal docs for this error message.
Error: Ordinal expression expected The expression must be of ordinal
type, i.e., maximum a Longint. This happens, for instance, when you
specify a second argument to Inc or Dec that doesn’t evaluate to an
ordinal value.
Your variable K is defined as qword, which is a 64-bit length. LongInt is 32 bit.
The for statement is platform dependent.
Observation: qword is not supported to be used as a counter variable on 32-bit platform.
But seems no documentary support to tell which set of datatypes are supported to be used as counter variables.
Tried in both 32-bit and 64-bit platforms:
32-bit:
declaration of variable j could be changed to datatype dword to get it successfully compiled.
It is also required to compile with release mode to prevent getting an error due to overflow.
Compiler: Free Pascal IDE for Win32 for i386
Target CPU: i386
Version 1.0.12 2017/02/13
Compiler Version: 3.0.2
Environment: Win10
edit:
Successfully compiled with i386 free pascal with x86_64 cross compiler
on 64-bit Win10 (edit2: in the left hand side's command line)
[Image]
Guess: the counter in for statement might be optimized with using registers. Under i386 configuration, qword is too large for a 32-bit register.
64-bit:
[Image]
But it seems to work fine in 64-bit platform.
Compiler: Free Pascal Compiler version 3.0.2 [2017/03/18] for x86_64
Environment: Mac OSX 10.11.6

"Inconsistent Operand Constraints" with Inline ASM using GCC

Getting this error when trying to compile this source file using GCC:
https://github.com/wolf9466/cpuminer-multi/blob/master/cryptonight_aesni.c
"cryptonight_aesni.c:162:4: error: inconsistent operand constraints"
Specifically:
uint64_t hi, lo;
// hi,lo = 64bit x 64bit multiply of c[0] and b[0]
__asm__("mulq %3\n\t"
: "=d" (hi),
"=a" (lo)
: "%a" (c[0]),
"rm" (b[0])
: "cc" );
Very difficult to find out what this error even means, yet alone how to fix it
The instruction mulq in this code is an x86 64-bit instruction. All the parameters are 64-bit values and can't fit in 32-bit registers (when compiling for a 32-bit x86 platform)
– Michael Petch

How to address errors from gcc cross compiler for ARM7 target [duplicate]

So I have been doing an assembly tutorial, and I got stuck in the very beginning.
Project name: asmtut.s
The Code:
.text
.global _start
start:
MOV R0, #65
MOV R7, #1
SWI 0
Right off the beginning I'm welcomed by 3 error messages after I try this line:as -o asmtut.o asmtut.s
asmtut.s:6: Error: expecting operand after ','; got nothing
asmtut.s:7: Error: expecting operand after ','; got nothing
asmtut.s:9: Error: no such instruction: 'swi 0'
I'm confused, because this is the exact code in the tutorial, and there it works completely fine.
Can anyone help me what could cause this?
You're trying to use an x86 assembler to assemble ARM code. They use different instruction sets and syntax.
The native gcc and as tools on your x86 Linux system will choke, just like if you tried to compile C++ with a Java compiler or vice versa. For example, # is the comment character in GAS x86 syntax, so mov r0, is a syntax error before it even gets to the point of noticing that r0 isn't a valid x86 register name.
You're following a tutorial for Assembly on Raspberry Pi (an ARM architecture) on a x86-based PC. Either run as on the Raspberry Pi, or install a cross-compile toolchain for Rasperry Pi/ARM.
Some Linux distros have packages that provide arm-linux-gnueabi-as and ...-gcc. For example, https://www.acmesystems.it/arm9_toolchain has details for Ubuntu.
To actually run the resulting binaries, you'd either run them on your ARM system, or you'd need an ARM emulator like qemu-arm. How to single step ARM assembly in GDB on QEMU? and How to run a single line of assembly, then see [R1] and condition flags have walkthroughs of doing that.

Configuring GCC for the SPARC architecture

I've been trying to compile a SPARC program. Just a simple one taken straight out of the book: SPARC Architecture, Assembly Language Programming, and C: Second Edition. However, I get an error leading me to believe SPARC wasn't correctly configured on my computer yet. This is on a Windows machine.
.global main
main:
save %sp, 96, %sp
mov 9, %l0
sub %l0, 1, %o0
sub %l0, 7, %o1
call .mul
nop
sub %l0, 11, %o1
call .div
mov %o0, %l1
mov 1, %g1
ta 0
I have GCC 4.9.2 installed through Cygwin 1.7.5.
I get the follow error upon trying to compile through GCC
C:\Users\Matt\Desktop>gcc expr.s -o expr
expr.s: Assembler messages:
expr.s: Warning: end of file not at end of a line; newline inserted
expr.s:3: Error: no such instruction: `save %sp,96,%sp'
expr.s:4: Error: bad register name `%l0'
expr.s:5: Error: bad register name `%l0'
expr.s:6: Error: bad register name `%l0'
expr.s:9: Error: bad register name `%l0'
expr.s:11: Error: bad register name `%o0'
expr.s:13: Error: bad register name `%g1'
expr.s:14: Error: no such instruction: `ta 0'
Which highlights almost everything unique with SPARC compared to a different architecture as being an 'error'.
So, I tried setting the architecture specifically for the program:
gcc -march=sparc expr.s -o expr
This still throws an error, which leads me to believe that my current configuration isn't set up for SPARC.
The procedure I used to setup GCC is: here
The only difference is instead of specifying c,c++ for the languages, I used all.
Thanks
You are right, your gcc is not set up for SPARC. If you are running Windows, the computer you are running on has an ISA other than SPARC (most likely x86). Your ISA is the hardware interface and can not be changed by a software upgrade.
To compile SPARC programs, you will need to rebuild gcc as a SPARC cross-compiler (host and target ISAs are different). When building from source, this is done with the -target= flag. Building a cross-compiler for linux will be similar to cygwin link.
Once you build the cross-compiler, to execute it you will need a way to simulate a SPARC processor. Using a system such as qemu will work.
Here's a small tutorial on compiling simple programs for a Sparc V8 target and running them on Qemu. The tutorial includes steps on obtaining a cross compiler(assuming you're working with Linux)

Resources