Bad Code for Expression Parameter of outp() with -Oi in C 5.1

ID Number: Q40756

5.10

MS-DOS

buglist5.10 fixlist6.00

Summary:

When compiling the source line below, the Microsoft C Compiler version

5.1 generates incorrect code in some cases for the intrinsic outp()

and outpw() functions when the -Oi option is used and the second

parameter is an expression. Workarounds are listed below.

Microsoft has confirmed this to be a problem in C version 5.1. This

problem was corrected in C version 6.0.

More Information:

The following is the C source line and the generated code:

outp(port + INT_ENABLE_OFF, (i == SIO_CNT) ? 3 : 1);

cmp WORD PTR [bp-6], 8 ;i

je $L20003 ;error !

mov ax, 3

jmp SHORT $L20004

$L20003:

mov ax, 1

$L20004:

push ax

mov ax, WORD PTR [bp-4] ;port

inc ax

push ax

call FAR PTR _outp

This assembly code would be equal to a source line such as the

following:

outp(port + IN_ENABLE_OFF, (i == SIO_CNT) ? 1 : 3);

This is the exact reverse of the original source line. Therefore, the

generated assembler code should read as follows:

cmp WORD PTR [bp-6], 8 ;i

jne $L20003 ;

mov ax, 3

jmp SHORT $L20004

$L20003:

mov ax, 1

$L20004:

push ax

mov ax, WORD PTR [bp-4] ;port

inc ax

push ax

call FAR PTR _outp

There are three workarounds:

1. Use a temporary variable -- for example:

x = (i == SIO_CNT) ? 1 : 3;

outp(port + stuff, x);

2. Do not use -Oi.

3. Use -Oi, but use the "#pragma function(outp outpw)" statement to

have the non-intrinsic version of the function used.