[Lazarus] fpc bug with M1 [[was: Re: UTF8LengthFast returning incorrect results on AARCH64 (MacOS)]]

Noel Duffy noelduffy at xtra.co.nz
Tue Dec 28 23:18:30 CET 2021


On 29/12/21 10:47, Martin Frb via lazarus wrote:
> On 28/12/2021 22:05, Noel Duffy via lazarus wrote:
>> On 29/12/21 01:26, Bart via lazarus wrote:
>>> fpc -al ulen.pas
>>
>> > This will produce the file ulen.s
>> > You can attach or copy that here.
>>
>> File is attached.
> 
> Thanks.
> And I think there is a bug in FPC
> 
> This is the signed version
> 
> # [43] Result += (pn8^ shr 7) and ((not pn8^) shr 6);
>      ldr    x0,[sp]
>      ldrsb    w0,[x0]         # <<<<< sign extend to a 32bit value 
> (32bit register).
>      eor    w0,w0,#255   # <<<<< But only "not" the lowest 8 bit. That 
> is wrong. The calculation uses 32 bit at this point
>      lsr    w0,w0,#6
>      ldr    x2,[sp]
>      ldrsb    w2,[x2]
>      lsr    w2,w2,#7
>      and    w0,w2,w0    # <<<<<< here the full 32 bit are used.
> 
> 
> Had the full 32 bits been "not"ed, the the upper 24 bit where 0 (because 
> they had been sign extended to 1).
> This would mask all the 1, that were sign extended in w2.
> 
> Had the char been < 128 (high bit = 0), then w0 would have the upper 24 
> bit = 1 / but w2 would have them 0.
> 
> And that is why the code worked, even with signed values. (signed values 
> were still a bad idea)
> 

Interesting. As I noted in my message with the ulen.s attached, I tested 
and found the problem is not present in fpc 3.2.2. That's the version of 
fpc packaged by Lazarus, and I used that to compile fpc 3.3.1.

The assembler produced by 3.2.2 looks like this:

# [43] Result += (pn8^ shr 7) and ((not pn8^) shr 6);
	ldr	x0,[sp]
	ldrsb	w0,[x0]
	mvn	w0,w0
	sxtb	w0,w0
	lsr	w1,w0,#6
	ldr	x0,[sp]
	ldrsb	w0,[x0]
	lsr	w0,w0,#7
	and	w0,w0,w1
	sxtw	x0,w0
	ldr	x1,[sp, #16]
	add	x0,x1,x0
	str	x0,[sp, #16]




More information about the lazarus mailing list