From 2b32362a2f8f4e7ebc509d7163f12d1ae24346a5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pali=20Roh=C3=A1r?= Date: Sat, 25 Dec 2021 13:45:28 +0100 Subject: [PATCH] libpci: i386-io-windows.h: Fix definitions of I/O port functions for UCRT, CRTDLL and for 64-bit mode Functions _outp(), _outpw(), _outpd(), _inp(), _inpw() and _inpd() are available only in 32-bit version of the old MSVCRT library. They are not available in 64-bit version of old MSVCRT library and neither the oldest CRTDLL library or in new UCRT library. Function prototypes for 32-bit mode should be available in header file. But they are missing in some MinGW toolchains. For 64-bit mode I/O port functions are defined only as inline functions or intrinsics macros in header file but under different names: __outbyte(), __outword(), __outdword(), __inbyte(), __inword(), __indword() This header file is available also in UCRT-compatible compilers. When compiling with the oldest CRTDLL library and not using header file, it is required to provide own implementation of these functions. Do it via inline assembly. With this change it is possible to compile i386-io-windows.h with all combination of toolchains, compilers, crt library and arch mode. The most important is the fix to allow compilation with modern UCRT library. --- lib/i386-io-windows.h | 70 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/lib/i386-io-windows.h b/lib/i386-io-windows.h index e2492df..e065620 100644 --- a/lib/i386-io-windows.h +++ b/lib/i386-io-windows.h @@ -10,7 +10,75 @@ #include #include -#ifndef __GNUC__ +#ifdef _MSC_VER +/* MSVC compiler provides I/O port intrinsics for both 32 and 64-bit modes. */ +#pragma intrinsic(_outp) +#pragma intrinsic(_outpw) +#pragma intrinsic(_outpd) +#pragma intrinsic(_inp) +#pragma intrinsic(_inpw) +#pragma intrinsic(_inpd) +#elif defined(_WIN64) || defined(_UCRT) +/* + * For other compilers I/O port intrinsics are available in header + * file either as inline/external functions or macros. Beware that + * names are different than MSVC intrinsics names and glibc function names. + * Usage of is also the prefered way for 64-bit mode or when using + * new UCRT library. + */ +#include +#define _outp(x,y) __outbyte(x,y) +#define _outpw(x,y) __outword(x,y) +#define _outpd(x,y) __outdword(x,y) +#define _inp(x) __inbyte(x) +#define _inpw(x) __inword(x) +#define _inpd(x) __indword(x) +#elif defined(__CRTDLL__) +/* + * Old CRTDLL library does not provide I/O port functions. Even it is the oldest + * CRT library it exists also in 64-bit variant. Implement I/O port functions + * via inline assembly just for 32-bit mode as 64-bit mode uses above + * header. + */ +static inline int _outp(unsigned short port, int databyte) +{ + asm volatile ("outb %b0, %w1" : : "a" (databyte), "Nd" (port)); + return databyte; +} +static inline unsigned short _outpw(unsigned short port, unsigned short dataword) +{ + asm volatile ("outw %w0, %w1" : : "a" (dataword), "Nd" (port)); + return dataword; +} +static inline unsigned long _outpd(unsigned short port, unsigned long dataword) +{ + asm volatile ("outl %0, %w1" : : "a" (dataword), "Nd" (port)); + return dataword; +} +static inline int _inp(unsigned short port) +{ + unsigned char ret; + asm volatile ("inb %w1, %0" : "=a" (ret) : "Nd" (port)); + return ret; +} +static inline unsigned short _inpw(unsigned short port) +{ + unsigned short ret; + asm volatile ("inw %w1, %0" : "=a" (ret) : "Nd" (port)); + return ret; +} +static inline unsigned long _inpd(unsigned short port) +{ + unsigned long ret; + asm volatile ("inl %w1, %0" : "=a" (ret) : "Nd" (port)); + return ret; +} +#elif !defined(__GNUC__) +/* + * Old 32-bit MSVCRT (non-UCRT) library provides I/O port functions. Function + * prototypes are defined in header file but they are missing in + * some MinGW toolchains. So for GCC compiler define them manually. + */ #include #else int _outp(unsigned short port, int databyte); -- 2.39.2