[fpc-pascal] issue when enabling -O2

Matias Vara matiasevara at gmail.com
Wed Jan 10 16:48:57 CET 2018


I think the problem was the way write_portd() is implemented:

procedure write_portd(const Data: Pointer; const Port: Word); {$IFDEF
ASMINLINE} inline; {$ENDIF}
asm // RCX: data, RDX: port
  {$IFDEF LINUX} mov dx, port {$ENDIF}
mov rsi, data // DX=port
        outsd
end;

If I replace with something that does not use the outsd instruction, it
works fine.

Matias

2018-01-10 15:55 GMT+01:00 Matias Vara <matiasevara at gmail.com>:

> Hello everyone,
>
> I am getting an exception when I enable the -O2 optimization. More
> precisaily, the line that stars with write_portd.... is corrupting the data
> section. This is the pascal code:
>
> function PciReadDword(const bus, device, func, regnum: UInt32): UInt32;
> var
>   Send: DWORD;
> begin
>   Send := $80000000 or (bus shl 16) or (device shl 11) or (func shl 8) or
> (regnum shl 2);
>   write_portd(@Send, PCI_CONF_PORT_INDEX);
>   read_portd(@Send, PCI_CONF_PORT_DATA);
>   Result := Send;
> end;
>
> *which generates (without -02):*
>
> .section .text.n_arch_$$_pcireaddword$longword$longword$longword$
> longword$$longword,"x"
> .balign 16,0x90
> .globl ARCH_$$_PCIREADDWORD$LONGWORD$LONGWORD$LONGWORD$LONGWORD$$LONGWORD
> ARCH_$$_PCIREADDWORD$LONGWORD$LONGWORD$LONGWORD$LONGWORD$$LONGWORD:
> .Lc207:
> .seh_proc ARCH_$$_PCIREADDWORD$LONGWORD$LONGWORD$LONGWORD$LONGWORD$$
> LONGWORD
> .Ll464:
> # [992] begin
> pushq %rbp
> .seh_pushreg %rbp
> .Lc209:
> .Lc210:
> movq %rsp,%rbp
> .Lc211:
> leaq -80(%rsp),%rsp
> .seh_stackalloc 80
> .seh_endprologue
> # Var bus located at rbp-8, size=OS_32
> # Var device located at rbp-16, size=OS_32
> # Var func located at rbp-24, size=OS_32
> # Var regnum located at rbp-32, size=OS_32
> # Var $result located at rbp-40, size=OS_32
> # Var Send located at rbp-48, size=OS_32
> movl %ecx,-8(%rbp)
> movl %edx,-16(%rbp)
> movl %r8d,-24(%rbp)
> movl %r9d,-32(%rbp)
> .Ll465:
> # [993] Send := $80000000 or (bus shl 16) or (device shl 11) or (func shl
> 8) or (regnum shl 2);
> movl -8(%rbp),%eax
> shll $16,%eax
> orl $2147483648,%eax
> movl -16(%rbp),%edx
> shll $11,%edx
> orl %eax,%edx
> movl -24(%rbp),%eax
> shll $8,%eax
> orl %edx,%eax
> movl -32(%rbp),%edx
> shll $2,%edx
> orl %eax,%edx
> movl %edx,-48(%rbp)
> .Ll466:
> # [995] write_portd(@Send, PCI_CONF_PORT_INDEX);
> leaq -48(%rbp),%rcx
> movl $3320,%edx
> call ARCH_$$_WRITE_PORTD$POINTER$WORD
> .Ll467:
> # [996] read_portd(@Send, PCI_CONF_PORT_DATA);
> leaq -48(%rbp),%rcx
> movl $3324,%edx
> call ARCH_$$_READ_PORTD$POINTER$WORD
> .Ll468:
> # [997] Result := Send;
> movl -48(%rbp),%eax
> movl %eax,-40(%rbp)
> .Ll469:
> # [998] end;
> movl -40(%rbp),%eax
> nop
> leaq (%rbp),%rsp
> popq %rbp
> ret
> .seh_endproc
> .Lc208:
> .Lt28:
> .Ll470:
>
> *and with -O2:*
>
> .section .text.n_arch_$$_pciwriteword$word$word$word$word$word,"x"
> .balign 16,0x90
> .globl ARCH_$$_PCIWRITEWORD$WORD$WORD$WORD$WORD$WORD
> ARCH_$$_PCIWRITEWORD$WORD$WORD$WORD$WORD$WORD:
> .Lc148:
> # Temps allocated between rbp-16 and rbp-8
> .seh_proc ARCH_$$_PCIWRITEWORD$WORD$WORD$WORD$WORD$WORD
> .Ll471:
> # [1014] begin
> pushq %rbp
> .seh_pushreg %rbp
> .Lc150:
> .Lc151:
> movq %rsp,%rbp
> .Lc152:
> leaq -48(%rsp),%rsp
> .seh_stackalloc 48
> # Var bus located in register ax
> # Var device located in register dx
> # Var func located in register r8w
> # Var regnum located in register r9w
> # Var value located in register cx
> movq %rbx,-16(%rbp)
> .seh_savereg %rbx, 32
> .seh_endprologue
> # Var Send located at rbp-8, size=OS_32
> movw %cx,%ax
> movw 48(%rbp),%bx
> # PeepHole Optimization,var11
> .Ll472:
> # [1015] Send := $80000000 or (bus shl 16) or (device shl 11) or (func shl
> 8) or (regnum and $fc);
> andl $65535,%eax
> shll $16,%eax
> orl $2147483648,%eax
> # PeepHole Optimization,var11
> andl $65535,%edx
> shll $11,%edx
> orl %eax,%edx
> # PeepHole Optimization,var11
> andl $65535,%r8d
> shll $8,%r8d
> orl %edx,%r8d
> # PeepHole Optimization,var1
> # PeepHole Optimization,var11
> andl $252,%r9d
> orl %r8d,%r9d
> movl %r9d,-8(%rbp)
> .Ll473:
> # [1016] write_portd(@Send, PCI_CONF_PORT_INDEX);
> leaq -8(%rbp),%rcx
> movl $3320,%edx
> call ARCH_$$_WRITE_PORTD$POINTER$WORD
> .Ll474:
> # [1017] write_portw(value, PCI_CONF_PORT_DATA);
> movw %bx,%cx
> # Var value located in register cx
> # PeepHole Optimization,var11
> andl $65535,%ecx
> movl $3324,%edx
> call ARCH_$$_WRITE_PORTW$WORD$WORD
> .Ll475:
> # [1018] end;
> movq -16(%rbp),%rbx
> leaq (%rbp),%rsp
> popq %rbp
> ret
> .seh_endproc
>
> The first thing that I realize was the the optimized version is not
> generating the correct source when is exiting since it should return
> "Send", but am I right? The assembler code of write_portd remains the same,
> Am I missing something?
>
> Regards, Matias.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20180110/9a390494/attachment.html>


More information about the fpc-pascal mailing list