* ARM: Fixed issue where some offsets of ADR assembly instructions

were incorrectly encoded by the internal assembler
This commit is contained in:
J. Gareth "Curious Kit" Moreton 2023-10-17 13:20:59 +01:00 committed by FPK
parent 237e2686f1
commit c4061e49e6

View File

@ -2814,6 +2814,8 @@ implementation
refoper : poper;
msb : longint;
r: byte;
imm : dword;
count : integer;
singlerec : tcompsinglerec;
doublerec : tcompdoublerec;
@ -3870,17 +3872,51 @@ implementation
if assigned(currsym) then
offset:=currsym.offset-insoffset-8;
offset:=offset+oper[1]^.ref^.offset;
if offset>=0 then
if opcode = A_ADR then
begin
{ set U flag }
bytes:=bytes or (1 shl 23);
bytes:=bytes or offset
{ The encoding for an ADR instruction is that of an ADD instruction,
so the offset has to abide by immediate shifter rules, otherwise
it can't be encoded }
if is_shifter_const(offset,r) then
begin
bytes:=bytes or (1 shl 23);
end
else
begin
bytes:=bytes or (1 shl 22);
offset:=-offset;
end;
{ calc rotate and adjust imm }
count:=0;
r:=0;
imm:=dword(offset);
repeat
imm:=RolDWord(imm, 2);
inc(r);
inc(count);
if count > 32 then
begin
message1(asmw_e_invalid_opcode_and_operands, 'invalid shifter imm (offset)');
exit;
end;
until (imm and $ff)=imm;
bytes:=bytes or (r shl 8) or imm;
end
else
begin
bytes:=bytes or (1 shl 22);
offset:=-offset;
bytes:=bytes or offset
if offset>=0 then
begin
{ set U flag }
bytes:=bytes or (1 shl 23);
bytes:=bytes or offset
end
else
begin
bytes:=bytes or (1 shl 22);
offset:=-offset;
bytes:=bytes or offset
end;
end;
end
else