HRgiger
HRgiger

Reputation: 2790

Source code for adding new GNU assembler x86 instruction and recompile

I am trying to figure out which file I need to modify in binutils project so I can add a new x86 instruction mov2 which will be exact copy of mov. Searching source folder resulted hundred of result yet still I couldnt find any file containing instruction references.

Thank you

Upvotes: 1

Views: 425

Answers (1)

HRgiger
HRgiger

Reputation: 2790

As @Jester mentioned file needs to be modified is opcodes/i386-opc.tbl also I had to bother him on IRC for further details but he was kind enough to guide me. I might note that I was only able to generate on binutils v2.25, I believe later branches start using different solution, might be related with "make run-cgen" target but its study for another day:)

Here are the steps I have followed:

Create temp dirs, one for build and one for binaries:

$mkdir -pv /tmp/{instruction-test,tools}
$cd /tmp/instruction-test/

clone the binutils repo or you can download straight from gnu ftp:

$git clone http://sourceware.org/git/binutils-gdb.git

switch to branch:

$cd binutils/
$git checkout binutils-2_25

pre-build project:

$mkdir -v build
$cd build
$../configure --prefix=/tmp/tools  --with-sysroot=/tmp/tools  --with-lib-path=/tmp/tools/lib  --target=x86_64-custom-linux-gnu  --disable-nls  --disable-werror

$make clean
$time make -s -j XX > make.log || { echo "can not make project, please check logs installation aborted" ; exit 1; }

now add mov2 instructions as exact copy of mov

$cd ../opcodes
$cat i386-opc.tbl | egrep -e '^mov,' | sed 's/mov/mov2/g' >> i386-opc.tbl

now you can pause here and look what we have added:

$git diff i386-opc.tbl

now we need to update i386 opcode table as well:

$cd ../build/opcodes
$make i386-gen
$./i386-gen --srcdir=$(pwd)/../../opcodes

now we can rebuild and install into /tmp/tools:

$cd ..
$time make -s > make.log
$make -s install > install.log

time to test! Here is small example with new instructions:

$cat > /tmp/hello << EOF
        .global _start

        .text
_start:
        # write(1, message, 13)
        mov2     $1, %rax                # system call 1 is write
        mov2     $1, %rdi                # file handle 1 is stdout
        mov2     $message, %rsi          # address of string to output
        mov2     $13, %rdx               # number of bytes
        syscall                         # invoke operating system to do the write

        # exit(0)
        mov2     $60, %rax               # system call 60 is exit
        xor     %rdi, %rdi              # we want return code 0
        syscall                         # invoke operating system to exit
message:
        .ascii  "Hello, world\n"
EOF
$cd /tmp/tools/bin
$./x86_64-custom-linux-gnu-as -o /tmp/hello.o /tmp/hello
$ld /tmp/hello.o -o /tmp/hello.bin
$cd /tmp/
$./hello.bin

now you should be able to see output:

Hello, world

If you hit issues I suspect it would be related with cat/EOF command, you can simply try with your own file. As I mentioned this is not up to date solution and I had trouble running i386-gen on later branches which I believe managed by cgen? or maybe I needed to deal with stdin used here but I didnt have much time

Upvotes: 2

Related Questions