Package jnr.x86asm

Examples of jnr.x86asm.Assembler


    @Override
    final void compile(Function function, String name, ResultType resultType, ParameterType[] parameterTypes,
                       Class resultClass, Class[] parameterClasses, CallingConvention convention, boolean saveErrno) {

        Assembler a = new Assembler(X86_64);
        int iCount = iCount(parameterTypes);
        int fCount = fCount(parameterTypes);

        boolean canJumpToTarget = !saveErrno & iCount <= 6 & fCount <= 8;
        switch (resultType.nativeType) {
            case SINT:
            case UINT:
                canJumpToTarget &= int.class == resultClass;
                break;

            case SLONGLONG:
            case ULONGLONG:
                canJumpToTarget &= long.class == resultClass;
                break;

            case FLOAT:
                canJumpToTarget &= float.class == resultClass;
                break;

            case DOUBLE:
                canJumpToTarget &= double.class == resultClass;
                break;

            case VOID:
                break;

            default:
                canJumpToTarget = false;
                break;
        }

        // JNI functions all look like:
        // foo(JNIEnv* env, jobject self, arg...)
        // on AMD64, those sit in %rdi, %rsi, %rdx, %rcx, %r8 and %r9
        // So we need to shuffle all the integer args up to over-write the
        // env and self arguments
        //
        for (int i = 0; i < Math.min(iCount, 4); i++) {
            switch (parameterTypes[i].nativeType) {
                case SCHAR:
                    a.movsx(dstRegisters64[i], srcRegisters8[i]);
                    break;

                case UCHAR:
                    a.movzx(dstRegisters64[i], srcRegisters8[i]);
                    break;

                case SSHORT:
                    a.movsx(dstRegisters64[i], srcRegisters16[i]);
                    break;

                case USHORT:
                    a.movzx(dstRegisters64[i], srcRegisters16[i]);
                    break;

                case SINT:
                    a.movsxd(dstRegisters64[i], srcRegisters32[i]);
                    break;

                case UINT:
                    // mov with a 32bit dst reg zero extends to 64bit
                    a.mov(dstRegisters32[i], srcRegisters32[i]);
                    break;

                default:
                    a.mov(dstRegisters64[i], srcRegisters64[i]);
                    break;
            }
        }

        if (iCount > 6) {
            throw new IllegalArgumentException("integer argument count > 6");
        }

        // For args 5 & 6 of the function, they would have been pushed on the stack
        for (int i = 4; i < iCount; i++) {
            int disp = 8 + ((4 - i) * 8);
            switch (parameterTypes[i].nativeType) {
                case SCHAR:
                    a.movsx(dstRegisters64[i], byte_ptr(rsp, disp));
                    break;

                case UCHAR:
                    a.movzx(dstRegisters64[i], byte_ptr(rsp, disp));
                    break;

                case SSHORT:
                    a.movsx(dstRegisters64[i], word_ptr(rsp, disp));
                    break;

                case USHORT:
                    a.movzx(dstRegisters64[i], word_ptr(rsp, disp));
                    break;

                case SINT:
                    a.movsxd(dstRegisters64[i], dword_ptr(rsp, disp));
                    break;

                case UINT:
                    // mov with a 32bit dst reg zero extends to 64bit
                    a.mov(dstRegisters32[i], dword_ptr(rsp, disp));
                    break;

                default:
                    a.mov(dstRegisters64[i], qword_ptr(rsp, disp));
                    break;
            }
        }

        // All the integer registers are loaded; there nothing to do for the floating
        // registers, as the first 8 args are already in xmm0..xmm7, so just sanity check
        if (fCount > 8) {
            throw new IllegalArgumentException("float argument count > 8");
        }

        if (canJumpToTarget) {
            a.jmp(imm(function.getFunctionAddress()));
            stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
            return;
        }

        // Need to align the stack to 16 bytes for function call.
        // It already has 8 bytes pushed (the return address), so making space
        // to save the return value from the function neatly aligns it to 16 bytes
        int space = resultClass == float.class || resultClass == double.class
                    ? 24 : 8;
        a.sub(rsp, imm(space));

        // Clear %rax, since it is used by varargs functions to determine the number of float registers to be saved
        a.mov(rax, imm(0));

        // Call to the actual native function
        a.call(imm(function.getFunctionAddress()));

        if (saveErrno) {
            // Save the return on the stack
            switch (resultType.nativeType) {
                case VOID:
                    // No need to save/reload return value registers
                    break;

                case FLOAT:
                    a.movss(dword_ptr(rsp, 0), xmm0);
                    break;

                case DOUBLE:
                    a.movsd(qword_ptr(rsp, 0), xmm0);
                    break;

                default:
                    a.mov(qword_ptr(rsp, 0), rax);
            }

            // Save the errno in a thread-local variable
            a.call(imm(errnoFunctionAddress));

            // Retrieve return value and put it back in the appropriate return register
            switch (resultType.nativeType) {
                case VOID:
                    // No need to save/reload return value registers
                    break;

                case SCHAR:
                    a.movsx(rax, byte_ptr(rsp, 0));
                    break;

                case UCHAR:
                    a.movzx(rax, byte_ptr(rsp, 0));
                    break;

                case SSHORT:
                    a.movsx(rax, word_ptr(rsp, 0));
                    break;

                case USHORT:
                    a.movzx(rax, word_ptr(rsp, 0));
                    break;

                case SINT:
                    a.movsxd(rax, dword_ptr(rsp, 0));
                    break;

                case UINT:
                    // storing a value in eax zeroes out the upper 32 bits of rax
                    a.mov(eax, dword_ptr(rsp, 0));
                    break;

                case FLOAT:
                    a.movss(xmm0, dword_ptr(rsp, 0));
                    break;

                case DOUBLE:
                    a.movsd(xmm0, qword_ptr(rsp, 0));
                    break;

                default:
                    a.mov(rax, qword_ptr(rsp, 0));
                    break;
            }

        } else {
            // sign/zero extend the result
            switch (resultType.nativeType) {
                case SCHAR:
                    a.movsx(rax, al);
                    break;

                case UCHAR:
                    a.movzx(rax, al);
                    break;

                case SSHORT:
                    a.movsx(rax, ax);
                    break;

                case USHORT:
                    a.movzx(rax, ax);
                    break;

                case SINT:
                    if (long.class == resultClass) a.movsxd(rax, eax);
                    break;

                case UINT:
                    if (long.class == resultClass) a.mov(eax, eax);
                    break;
            }
        }

        // Restore rsp to original position
        a.add(rsp, imm(space));
        a.ret();

        stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
    }
View Full Code Here


        // into the new parameter space.
        // It already has 4 bytes pushed (the return address) so we need to account for that.
        //       
        final int stackadj = align(Math.max(psize, rsize) + 4, 16) - 4;

        Assembler a = new Assembler(X86_32);

        a.sub(esp, imm(stackadj));

        // copy and convert the parameters from the orig stack to the new location
        for (int i = 0, srcoff = 0, dstoff = 0; i < parameterTypes.length; i++)  {
            int srcParameterSize = parameterSize(parameterClasses[i]);
            int dstParameterSize = parameterSize(parameterTypes[i]);
            int disp = stackadj + 4 + 8 + srcoff;

            switch (parameterTypes[i].nativeType) {
                case SCHAR:
                case SSHORT:
                    a.movsx(eax, ptr(esp, disp, parameterTypes[i].nativeType));
                    break;

                case UCHAR:
                case USHORT:
                    a.movzx(eax, ptr(esp, disp, parameterTypes[i].nativeType));
                    break;

                default:
                    a.mov(eax, dword_ptr(esp, disp));
                    break;
            }
            a.mov(dword_ptr(esp, dstoff), eax);

            if (dstParameterSize > 4) {
                if (parameterTypes[i].nativeType == NativeType.SLONGLONG && long.class != parameterClasses[i]) {
                    // sign extend from int.class -> long long
                    a.sar(eax, imm(31));

                } else if (parameterTypes[i].nativeType == NativeType.ULONGLONG && long.class != parameterClasses[i]) {
                    // zero extend from int.class -> unsigned long long
                    a.mov(dword_ptr(esp, dstoff + 4), imm(0));

                } else {
                    a.mov(eax, dword_ptr(esp, disp + 4));
                }
                a.mov(dword_ptr(esp, dstoff + 4), eax);
            }

            dstoff += dstParameterSize;
            srcoff += srcParameterSize;
        }


        // Call to the actual native function
        a.call(imm(function.getFunctionAddress() & 0xffffffffL));
       
        if (saveErrno) {
            int save = 0;
            switch (resultType.nativeType) {
                case FLOAT:
                    a.fstp(dword_ptr(esp, save));
                    break;

                case DOUBLE:
                    a.fstp(qword_ptr(esp, save));
                    break;

                case SLONGLONG:
                case ULONGLONG:
                    a.mov(dword_ptr(esp, save), eax);
                    a.mov(dword_ptr(esp, save + 4), edx);
                    break;

                case VOID:
                    // No need to save for void values
                    break;

                default:
                    a.mov(dword_ptr(esp, save), eax);
            }

            // Save the errno in a thread-local variable
            a.call(imm(errnoFunctionAddress & 0xffffffffL));

            // Retrieve return value and put it back in the appropriate return register
            switch (resultType.nativeType) {
                case FLOAT:
                    a.fld(dword_ptr(esp, save));
                    break;

                case DOUBLE:
                    a.fld(qword_ptr(esp, save));
                    break;

                case SCHAR:
                    a.movsx(eax, byte_ptr(esp, save));
                    break;

                case UCHAR:
                    a.movzx(eax, byte_ptr(esp, save));
                    break;

                case SSHORT:
                    a.movsx(eax, word_ptr(esp, save));
                    break;

                case USHORT:
                    a.movzx(eax, word_ptr(esp, save));
                    break;

                case SLONGLONG:
                case ULONGLONG:
                    a.mov(eax, dword_ptr(esp, save));
                    a.mov(edx, dword_ptr(esp, save + 4));
                    break;

                case VOID:
                    // No need to save for void values
                    break;

                default:
                    a.mov(eax, dword_ptr(esp, save));
            }

        } else {

            switch (resultType.nativeType) {
                case SCHAR:
                    a.movsx(eax, al);
                    break;

                case UCHAR:
                    a.movzx(eax, al);
                    break;

                case SSHORT:
                    a.movsx(eax, ax);
                    break;

                case USHORT:
                    a.movzx(eax, ax);
                    break;
            }
        }

        if (long.class == resultClass) {
            // sign or zero extend the result to 64 bits
            switch (resultType.nativeType) {
                case SCHAR:
                case SSHORT:
                case SINT:
                case SLONG:
                    // sign extend eax to edx:eax
                    a.mov(edx, eax);
                    a.sar(edx, imm(31));
                    break;

                case UCHAR:
                case USHORT:
                case UINT:
                case ULONG:
                case ADDRESS:
                    a.mov(edx, imm(0));
                    break;
            }

        }
        // Restore esp to the original position and return
        a.add(esp, imm(stackadj));
        a.ret();

        stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
    }
View Full Code Here

    private static boolean hasAssembler() {
        try {
            switch (Platform.getPlatform().getCPU()) {
                case I386:
                    new Assembler(CPU.X86_32);
                    return true;
                case X86_64:
                    new Assembler(CPU.X86_64);
                    return true;
                default:
                    return false;
            }
        } catch (Throwable t) {
View Full Code Here

    @Override
    final void compile(Function function, String name, ResultType resultType, ParameterType[] parameterTypes,
                       Class resultClass, Class[] parameterClasses, CallingConvention convention, boolean saveErrno) {

        Assembler a = new Assembler(X86_64);
        int iCount = iCount(parameterTypes);
        int fCount = fCount(parameterTypes);

        boolean canJumpToTarget = !saveErrno & iCount <= 6 & fCount <= 8;
        switch (resultType.nativeType) {
            case SINT:
            case UINT:
                canJumpToTarget &= int.class == resultClass;
                break;

            case SLONGLONG:
            case ULONGLONG:
                canJumpToTarget &= long.class == resultClass;
                break;

            case FLOAT:
                canJumpToTarget &= float.class == resultClass;
                break;

            case DOUBLE:
                canJumpToTarget &= double.class == resultClass;
                break;

            case VOID:
                break;

            default:
                canJumpToTarget = false;
                break;
        }

        // JNI functions all look like:
        // foo(JNIEnv* env, jobject self, arg...)
        // on AMD64, those sit in %rdi, %rsi, %rdx, %rcx, %r8 and %r9
        // So we need to shuffle all the integer args up to over-write the
        // env and self arguments
        //
        for (int i = 0; i < Math.min(iCount, 4); i++) {
            switch (parameterTypes[i].nativeType) {
                case SCHAR:
                    a.movsx(dstRegisters64[i], srcRegisters8[i]);
                    break;

                case UCHAR:
                    a.movzx(dstRegisters64[i], srcRegisters8[i]);
                    break;

                case SSHORT:
                    a.movsx(dstRegisters64[i], srcRegisters16[i]);
                    break;

                case USHORT:
                    a.movzx(dstRegisters64[i], srcRegisters16[i]);
                    break;

                case SINT:
                    a.movsxd(dstRegisters64[i], srcRegisters32[i]);
                    break;

                case UINT:
                    // mov with a 32bit dst reg zero extends to 64bit
                    a.mov(dstRegisters32[i], srcRegisters32[i]);
                    break;

                default:
                    a.mov(dstRegisters64[i], srcRegisters64[i]);
                    break;
            }
        }

        if (iCount > 6) {
            throw new IllegalArgumentException("integer argument count > 6");
        }

        // For args 5 & 6 of the function, they would have been pushed on the stack
        for (int i = 4; i < iCount; i++) {
            int disp = 8 + ((4 - i) * 8);
            switch (parameterTypes[i].nativeType) {
                case SCHAR:
                    a.movsx(dstRegisters64[i], byte_ptr(rsp, disp));
                    break;

                case UCHAR:
                    a.movzx(dstRegisters64[i], byte_ptr(rsp, disp));
                    break;

                case SSHORT:
                    a.movsx(dstRegisters64[i], word_ptr(rsp, disp));
                    break;

                case USHORT:
                    a.movzx(dstRegisters64[i], word_ptr(rsp, disp));
                    break;

                case SINT:
                    a.movsxd(dstRegisters64[i], dword_ptr(rsp, disp));
                    break;

                case UINT:
                    // mov with a 32bit dst reg zero extends to 64bit
                    a.mov(dstRegisters32[i], dword_ptr(rsp, disp));
                    break;

                default:
                    a.mov(dstRegisters64[i], qword_ptr(rsp, disp));
                    break;
            }
        }

        // All the integer registers are loaded; there nothing to do for the floating
        // registers, as the first 8 args are already in xmm0..xmm7, so just sanity check
        if (fCount > 8) {
            throw new IllegalArgumentException("float argument count > 8");
        }

        if (canJumpToTarget) {
            a.jmp(imm(function.getFunctionAddress()));
            stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
            return;
        }

        // Need to align the stack to 16 bytes for function call.
        // It already has 8 bytes pushed (the return address), so making space
        // to save the return value from the function neatly aligns it to 16 bytes
        int space = resultClass == float.class || resultClass == double.class
                    ? 24 : 8;
        a.sub(rsp, imm(space));

        // Clear %rax, since it is used by varargs functions to determine the number of float registers to be saved
        a.mov(rax, imm(0));

        // Call to the actual native function
        a.call(imm(function.getFunctionAddress()));

        if (saveErrno) {
            // Save the return on the stack
            switch (resultType.nativeType) {
                case VOID:
                    // No need to save/reload return value registers
                    break;

                case FLOAT:
                    a.movss(dword_ptr(rsp, 0), xmm0);
                    break;

                case DOUBLE:
                    a.movsd(qword_ptr(rsp, 0), xmm0);
                    break;

                default:
                    a.mov(qword_ptr(rsp, 0), rax);
            }

            // Save the errno in a thread-local variable
            a.call(imm(errnoFunctionAddress));

            // Retrieve return value and put it back in the appropriate return register
            switch (resultType.nativeType) {
                case VOID:
                    // No need to save/reload return value registers
                    break;

                case SCHAR:
                    a.movsx(rax, byte_ptr(rsp, 0));
                    break;

                case UCHAR:
                    a.movzx(rax, byte_ptr(rsp, 0));
                    break;

                case SSHORT:
                    a.movsx(rax, word_ptr(rsp, 0));
                    break;

                case USHORT:
                    a.movzx(rax, word_ptr(rsp, 0));
                    break;

                case SINT:
                    a.movsxd(rax, dword_ptr(rsp, 0));
                    break;

                case UINT:
                    // storing a value in eax zeroes out the upper 32 bits of rax
                    a.mov(eax, dword_ptr(rsp, 0));
                    break;

                case FLOAT:
                    a.movss(xmm0, dword_ptr(rsp, 0));
                    break;

                case DOUBLE:
                    a.movsd(xmm0, qword_ptr(rsp, 0));
                    break;

                default:
                    a.mov(rax, qword_ptr(rsp, 0));
                    break;
            }

        } else {
            // sign/zero extend the result
            switch (resultType.nativeType) {
                case SCHAR:
                    a.movsx(rax, al);
                    break;

                case UCHAR:
                    a.movzx(rax, al);
                    break;

                case SSHORT:
                    a.movsx(rax, ax);
                    break;

                case USHORT:
                    a.movzx(rax, ax);
                    break;

                case SINT:
                    if (long.class == resultClass) a.movsxd(rax, eax);
                    break;

                case UINT:
                    if (long.class == resultClass) a.mov(eax, eax);
                    break;
            }
        }

        // Restore rsp to original position
        a.add(rsp, imm(space));
        a.ret();

        stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
    }
View Full Code Here

        long fn = code;
        PrintStream dbg = System.err;
        System.out.flush(); System.err.flush();

        for (Stub stub : stubs) {
            Assembler asm = stub.assembler;
            // align the start of all functions on a 8 byte boundary
            fn = align(fn, 8);
            ByteBuffer buf = ByteBuffer.allocate(asm.codeSize()).order(ByteOrder.LITTLE_ENDIAN);
            stub.assembler.relocCode(buf, fn);
            buf.flip();
            MemoryIO.getInstance().putByteArray(fn, buf.array(), buf.arrayOffset(), buf.limit());

            if (DEBUG && X86Disassembler.isAvailable()) {

                dbg.println(clazz.getName() + "." + stub.name + " " + stub.signature);
                X86Disassembler disassembler = X86Disassembler.create();
                disassembler.setMode(Platform.getNativePlatform().getCPU() == Platform.CPU.I386
                        ? X86Disassembler.Mode.I386 : X86Disassembler.Mode.X86_64);
                disassembler.setSyntax(X86Disassembler.Syntax.INTEL);
                disassembler.setInputBuffer(MemoryUtil.newPointer(fn), asm.offset());
                while (disassembler.disassemble()) {
                    dbg.printf("%8x: %s\n", disassembler.offset(), disassembler.insn());
                }
                if (buf.remaining() > asm.offset()) {
                    // libudis86 for some reason cannot understand the code asmjit emits for the trampolines
                    dbg.printf("%8x: <indirect call trampolines>\n", asm.offset());
                }
                dbg.println();
            }
            methods.add(new NativeMethod(fn, stub.name, stub.signature));

            fn += asm.codeSize();
        }

        pm.protectPages(code, (int) npages, PageManager.PROT_READ | PageManager.PROT_EXEC);

        NativeMethods.register(clazz, methods);
View Full Code Here

    private static final boolean hasAssembler() {
        try {
            switch (Platform.getPlatform().getCPU()) {
                case I386:
                    new Assembler(CPU.X86_32);
                    return true;
                case X86_64:
                    new Assembler(CPU.X86_64);
                    return true;
                default:
                    return false;
            }
        } catch (Throwable t) {
View Full Code Here

        // into the new parameter space.
        // It already has 4 bytes pushed (the return address) so we need to account for that.
        //       
        final int stackadj = align(Math.max(psize, rsize) + 4, 16) - 4;

        Assembler a = new Assembler(X86_32);

        a.sub(esp, imm(stackadj));

        // copy and convert the parameters from the orig stack to the new location
        for (int i = 0, srcoff = 0, dstoff = 0; i < parameterTypes.length; i++)  {
            int srcParameterSize = parameterSize(parameterClasses[i]);
            int dstParameterSize = parameterSize(parameterTypes[i]);
            int disp = stackadj + 4 + 8 + srcoff;

            switch (parameterTypes[i].nativeType) {
                case SCHAR:
                case SSHORT:
                    a.movsx(eax, ptr(esp, disp, parameterTypes[i].nativeType));
                    break;

                case UCHAR:
                case USHORT:
                    a.movzx(eax, ptr(esp, disp, parameterTypes[i].nativeType));
                    break;

                default:
                    a.mov(eax, dword_ptr(esp, disp));
                    break;
            }
            a.mov(dword_ptr(esp, dstoff), eax);

            if (dstParameterSize > 4) {
                if (parameterTypes[i].nativeType == NativeType.SLONGLONG && long.class != parameterClasses[i]) {
                    // sign extend from int.class -> long long
                    a.sar(eax, imm(31));

                } else if (parameterTypes[i].nativeType == NativeType.ULONGLONG && long.class != parameterClasses[i]) {
                    // zero extend from int.class -> unsigned long long
                    a.mov(dword_ptr(esp, dstoff + 4), imm(0));

                } else {
                    a.mov(eax, dword_ptr(esp, disp + 4));
                }
                a.mov(dword_ptr(esp, dstoff + 4), eax);
            }

            dstoff += dstParameterSize;
            srcoff += srcParameterSize;
        }


        // Call to the actual native function
        a.call(imm(function.getFunctionAddress() & 0xffffffffL));
       
        if (saveErrno) {
            int save = 0;
            switch (resultType.nativeType) {
                case FLOAT:
                    a.fstp(dword_ptr(esp, save));
                    break;

                case DOUBLE:
                    a.fstp(qword_ptr(esp, save));
                    break;

                case SLONGLONG:
                case ULONGLONG:
                    a.mov(dword_ptr(esp, save), eax);
                    a.mov(dword_ptr(esp, save + 4), edx);
                    break;

                case VOID:
                    // No need to save for void values
                    break;

                default:
                    a.mov(dword_ptr(esp, save), eax);
            }

            // Save the errno in a thread-local variable
            a.call(imm(errnoFunctionAddress & 0xffffffffL));

            // Retrieve return value and put it back in the appropriate return register
            switch (resultType.nativeType) {
                case FLOAT:
                    a.fld(dword_ptr(esp, save));
                    break;

                case DOUBLE:
                    a.fld(qword_ptr(esp, save));
                    break;

                case SCHAR:
                    a.movsx(eax, byte_ptr(esp, save));
                    break;

                case UCHAR:
                    a.movzx(eax, byte_ptr(esp, save));
                    break;

                case SSHORT:
                    a.movsx(eax, word_ptr(esp, save));
                    break;

                case USHORT:
                    a.movzx(eax, word_ptr(esp, save));
                    break;

                case SLONGLONG:
                case ULONGLONG:
                    a.mov(eax, dword_ptr(esp, save));
                    a.mov(edx, dword_ptr(esp, save + 4));
                    break;

                case VOID:
                    // No need to save for void values
                    break;

                default:
                    a.mov(eax, dword_ptr(esp, save));
            }

        } else {

            switch (resultType.nativeType) {
                case SCHAR:
                    a.movsx(eax, al);
                    break;

                case UCHAR:
                    a.movzx(eax, al);
                    break;

                case SSHORT:
                    a.movsx(eax, ax);
                    break;

                case USHORT:
                    a.movzx(eax, ax);
                    break;
            }
        }

        if (long.class == resultClass) {
            // sign or zero extend the result to 64 bits
            switch (resultType.nativeType) {
                case SCHAR:
                case SSHORT:
                case SINT:
                case SLONG:
                    // sign extend eax to edx:eax
                    a.mov(edx, eax);
                    a.sar(edx, imm(31));
                    break;

                case UCHAR:
                case USHORT:
                case UINT:
                case ULONG:
                case ADDRESS:
                    a.mov(edx, imm(0));
                    break;
            }

        }
        // Restore esp to the original position and return
        a.add(esp, imm(stackadj));
        a.ret();

        stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
    }
View Full Code Here

    private static boolean hasAssembler() {
        try {
            switch (Platform.getPlatform().getCPU()) {
                case I386:
                    new Assembler(CPU.X86_32);
                    return true;
                case X86_64:
                    new Assembler(CPU.X86_64);
                    return true;
                default:
                    return false;
            }
        } catch (Throwable t) {
View Full Code Here

        long fn = code;
        PrintStream dbg = System.err;
        System.out.flush(); System.err.flush();

        for (Stub stub : stubs) {
            Assembler asm = stub.assembler;
            // align the start of all functions on a 8 byte boundary
            fn = align(fn, 8);
            ByteBuffer buf = ByteBuffer.allocate(asm.codeSize()).order(ByteOrder.LITTLE_ENDIAN);
            stub.assembler.relocCode(buf, fn);
            buf.flip();
            MemoryIO.getInstance().putByteArray(fn, buf.array(), buf.arrayOffset(), buf.limit());

            if (DEBUG && X86Disassembler.isAvailable()) {

                dbg.println(clazz.getName() + "." + stub.name + " " + stub.signature);
                X86Disassembler disassembler = X86Disassembler.create();
                disassembler.setMode(Platform.getNativePlatform().getCPU() == Platform.CPU.I386
                        ? X86Disassembler.Mode.I386 : X86Disassembler.Mode.X86_64);
                disassembler.setSyntax(X86Disassembler.Syntax.INTEL);
                disassembler.setInputBuffer(MemoryUtil.newPointer(runtime, fn), asm.offset());
                while (disassembler.disassemble()) {
                    dbg.printf("%8x: %s\n", disassembler.offset(), disassembler.insn());
                }
                if (buf.remaining() > asm.offset()) {
                    // libudis86 for some reason cannot understand the code asmjit emits for the trampolines
                    dbg.printf("%8x: <indirect call trampolines>\n", asm.offset());
                }
                dbg.println();
            }
            methods.add(new NativeMethod(fn, stub.name, stub.signature));

            fn += asm.codeSize();
        }

        pm.protectPages(code, (int) npages, PageManager.PROT_READ | PageManager.PROT_EXEC);

        NativeMethods.register(clazz, methods);
View Full Code Here

        // into the new parameter space.
        // It already has 4 bytes pushed (the return address) so we need to account for that.
        //       
        final int stackadj = align(Math.max(psize, rsize) + 4, 16) - 4;

        Assembler a = new Assembler(X86_32);

        a.sub(esp, imm(stackadj));

        // copy and convert the parameters from the orig stack to the new location
        for (int i = 0, srcoff = 0, dstoff = 0; i < parameterTypes.length; i++)  {
            int srcParameterSize = parameterSize(parameterClasses[i]);
            int dstParameterSize = parameterSize(parameterTypes[i]);
            int disp = stackadj + 4 + 8 + srcoff;

            switch (parameterTypes[i].getNativeType()) {
                case SCHAR:
                case SSHORT:
                    a.movsx(eax, ptr(esp, disp, parameterTypes[i].getNativeType()));
                    break;

                case UCHAR:
                case USHORT:
                    a.movzx(eax, ptr(esp, disp, parameterTypes[i].getNativeType()));
                    break;

                default:
                    a.mov(eax, dword_ptr(esp, disp));
                    break;
            }
            a.mov(dword_ptr(esp, dstoff), eax);

            if (dstParameterSize > 4) {
                if (parameterTypes[i].getNativeType() == NativeType.SLONGLONG && long.class != parameterClasses[i]) {
                    // sign extend from int.class -> long long
                    a.sar(eax, imm(31));

                } else if (parameterTypes[i].getNativeType() == NativeType.ULONGLONG && long.class != parameterClasses[i]) {
                    // zero extend from int.class -> unsigned long long
                    a.mov(dword_ptr(esp, dstoff + 4), imm(0));

                } else {
                    a.mov(eax, dword_ptr(esp, disp + 4));
                }
                a.mov(dword_ptr(esp, dstoff + 4), eax);
            }

            dstoff += dstParameterSize;
            srcoff += srcParameterSize;
        }


        // Call to the actual native function
        a.call(imm(function.getFunctionAddress() & 0xffffffffL));
       
        if (saveErrno) {
            int save = 0;
            switch (resultType.getNativeType()) {
                case FLOAT:
                    a.fstp(dword_ptr(esp, save));
                    break;

                case DOUBLE:
                    a.fstp(qword_ptr(esp, save));
                    break;

                case SLONGLONG:
                case ULONGLONG:
                    a.mov(dword_ptr(esp, save), eax);
                    a.mov(dword_ptr(esp, save + 4), edx);
                    break;

                case VOID:
                    // No need to save for void values
                    break;

                default:
                    a.mov(dword_ptr(esp, save), eax);
            }

            // Save the errno in a thread-local variable
            a.call(imm(errnoFunctionAddress & 0xffffffffL));

            // Retrieve return value and put it back in the appropriate return register
            switch (resultType.getNativeType()) {
                case FLOAT:
                    a.fld(dword_ptr(esp, save));
                    break;

                case DOUBLE:
                    a.fld(qword_ptr(esp, save));
                    break;

                case SCHAR:
                    a.movsx(eax, byte_ptr(esp, save));
                    break;

                case UCHAR:
                    a.movzx(eax, byte_ptr(esp, save));
                    break;

                case SSHORT:
                    a.movsx(eax, word_ptr(esp, save));
                    break;

                case USHORT:
                    a.movzx(eax, word_ptr(esp, save));
                    break;

                case SLONGLONG:
                case ULONGLONG:
                    a.mov(eax, dword_ptr(esp, save));
                    a.mov(edx, dword_ptr(esp, save + 4));
                    break;

                case VOID:
                    // No need to save for void values
                    break;

                default:
                    a.mov(eax, dword_ptr(esp, save));
            }

        } else {

            switch (resultType.getNativeType()) {
                case SCHAR:
                    a.movsx(eax, al);
                    break;

                case UCHAR:
                    a.movzx(eax, al);
                    break;

                case SSHORT:
                    a.movsx(eax, ax);
                    break;

                case USHORT:
                    a.movzx(eax, ax);
                    break;
            }
        }

        if (long.class == resultClass) {
            // sign or zero extend the result to 64 bits
            switch (resultType.getNativeType()) {
                case SCHAR:
                case SSHORT:
                case SINT:
                case SLONG:
                    // sign extend eax to edx:eax
                    a.mov(edx, eax);
                    a.sar(edx, imm(31));
                    break;

                case UCHAR:
                case USHORT:
                case UINT:
                case ULONG:
                case ADDRESS:
                    a.mov(edx, imm(0));
                    break;
            }

        }
        // Restore esp to the original position and return
        a.add(esp, imm(stackadj));
        a.ret();

        stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));
    }
View Full Code Here

TOP

Related Classes of jnr.x86asm.Assembler

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.