mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-07-08 14:56:09 +02:00
Add missing NOP, and B instruction forms.
Move ThumbFunc flag from section to symbol. Make .w forms optional the other way around. If .w is explicitly put on an instruction the assembler should always chose a wide form. git-svn-id: branches/laksen/armiw@29341 -
This commit is contained in:
parent
de00a1d76d
commit
71cdedea82
@ -93,6 +93,7 @@ uses
|
|||||||
OT_REG64 = $00201008;
|
OT_REG64 = $00201008;
|
||||||
OT_VREG = $00201010; { vector register }
|
OT_VREG = $00201010; { vector register }
|
||||||
OT_REGF = $00201020; { coproc register }
|
OT_REGF = $00201020; { coproc register }
|
||||||
|
OT_REGS = $00201040; { special register with mask }
|
||||||
OT_MEMORY = $00204000; { register number in 'basereg' }
|
OT_MEMORY = $00204000; { register number in 'basereg' }
|
||||||
OT_MEM8 = $00204001;
|
OT_MEM8 = $00204001;
|
||||||
OT_MEM16 = $00204002;
|
OT_MEM16 = $00204002;
|
||||||
@ -1453,10 +1454,6 @@ implementation
|
|||||||
|
|
||||||
|
|
||||||
procedure gather_it_info(list: TAsmList);
|
procedure gather_it_info(list: TAsmList);
|
||||||
const
|
|
||||||
opCount: array[A_IT..A_ITTTT] of longint =
|
|
||||||
(1,2,2,3,3,3,3,
|
|
||||||
4,4,4,4,4,4,4,4);
|
|
||||||
var
|
var
|
||||||
curtai: tai;
|
curtai: tai;
|
||||||
in_it: boolean;
|
in_it: boolean;
|
||||||
@ -1479,7 +1476,7 @@ implementation
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
in_it:=true;
|
in_it:=true;
|
||||||
it_count:=opCount[taicpu(curtai).opcode];
|
it_count:=GetITLevels(taicpu(curtai).opcode);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
@ -1502,8 +1499,51 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ Expands pseudo instructions ( mov r1,r2,lsl #4 -> lsl r1,r2,#4) }
|
||||||
|
procedure expand_instructions(list: TAsmList);
|
||||||
|
var
|
||||||
|
curtai: tai;
|
||||||
|
begin
|
||||||
|
curtai:=tai(list.First);
|
||||||
|
while assigned(curtai) do
|
||||||
|
begin
|
||||||
|
case curtai.typ of
|
||||||
|
ait_instruction:
|
||||||
|
begin
|
||||||
|
case taicpu(curtai).opcode of
|
||||||
|
A_MOV:
|
||||||
|
begin
|
||||||
|
if (taicpu(curtai).ops=3) and
|
||||||
|
(taicpu(curtai).oper[2]^.typ=top_shifterop) then
|
||||||
|
begin
|
||||||
|
case taicpu(curtai).oper[2]^.shifterop^.shiftmode of
|
||||||
|
SM_LSL: taicpu(curtai).opcode:=A_LSL;
|
||||||
|
SM_LSR: taicpu(curtai).opcode:=A_LSR;
|
||||||
|
SM_ASR: taicpu(curtai).opcode:=A_ASR;
|
||||||
|
SM_ROR: taicpu(curtai).opcode:=A_ROR;
|
||||||
|
SM_RRX: taicpu(curtai).opcode:=A_RRX;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if taicpu(curtai).oper[2]^.shifterop^.rs=NR_NO then
|
||||||
|
taicpu(curtai).loadconst(2, taicpu(curtai).oper[2]^.shifterop^.shiftimm)
|
||||||
|
else
|
||||||
|
taicpu(curtai).loadreg(2, taicpu(curtai).oper[2]^.shifterop^.rs);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
curtai:=tai(curtai.Next);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure finalizearmcode(list, listtoinsert: TAsmList);
|
procedure finalizearmcode(list, listtoinsert: TAsmList);
|
||||||
begin
|
begin
|
||||||
|
expand_instructions(list);
|
||||||
|
|
||||||
{ Do Thumb-2 16bit -> 32bit transformations }
|
{ Do Thumb-2 16bit -> 32bit transformations }
|
||||||
if GenerateThumb2Code then
|
if GenerateThumb2Code then
|
||||||
begin
|
begin
|
||||||
@ -1712,6 +1752,9 @@ implementation
|
|||||||
else
|
else
|
||||||
if (ot and OT_FPUREG)=OT_FPUREG then
|
if (ot and OT_FPUREG)=OT_FPUREG then
|
||||||
s:=s+'fpureg'
|
s:=s+'fpureg'
|
||||||
|
else
|
||||||
|
if (ot and OT_REGS)=OT_REGS then
|
||||||
|
s:=s+'sreg'
|
||||||
else
|
else
|
||||||
if (ot and OT_REGF)=OT_REGF then
|
if (ot and OT_REGF)=OT_REGF then
|
||||||
s:=s+'creg'
|
s:=s+'creg'
|
||||||
@ -2109,6 +2152,10 @@ implementation
|
|||||||
begin
|
begin
|
||||||
ot:=OT_CONDITION;
|
ot:=OT_CONDITION;
|
||||||
end;
|
end;
|
||||||
|
top_specialreg:
|
||||||
|
begin
|
||||||
|
ot:=OT_REGS;
|
||||||
|
end;
|
||||||
else
|
else
|
||||||
begin writeln(typ);
|
begin writeln(typ);
|
||||||
internalerror(200402261); end;
|
internalerror(200402261); end;
|
||||||
@ -2166,10 +2213,10 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ Check wideformat flag }
|
{ Check wideformat flag }
|
||||||
if ((p^.flags and IF_WIDE)<>0) <> wideformat then
|
if wideformat and ((p^.flags and IF_WIDE)=0) then
|
||||||
begin
|
begin
|
||||||
{matches:=0;
|
matches:=0;
|
||||||
exit;}
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Check that no spurious colons or TOs are present }
|
{ Check that no spurious colons or TOs are present }
|
||||||
@ -4079,14 +4126,27 @@ implementation
|
|||||||
if oper[0]^.typ=top_const then
|
if oper[0]^.typ=top_const then
|
||||||
begin
|
begin
|
||||||
if insentry^.code[0]=#$63 then
|
if insentry^.code[0]=#$63 then
|
||||||
bytes:=bytes or ((oper[0]^.val shr 1) and $FF)
|
bytes:=bytes or (((oper[0]^.val shr 1)-1) and $FF)
|
||||||
else
|
else
|
||||||
bytes:=bytes or ((oper[0]^.val shr 1) and $3FF);
|
bytes:=bytes or (((oper[0]^.val shr 1)-1) and $3FF);
|
||||||
end
|
end
|
||||||
else if oper[0]^.typ=top_reg then
|
else if oper[0]^.typ=top_reg then
|
||||||
begin
|
begin
|
||||||
bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
|
bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
|
||||||
end;
|
end
|
||||||
|
else if oper[0]^.typ=top_ref then
|
||||||
|
begin
|
||||||
|
offset:=0;
|
||||||
|
currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
|
||||||
|
if assigned(currsym) then
|
||||||
|
offset:=currsym.offset-insoffset-8;
|
||||||
|
offset:=offset+oper[0]^.ref^.offset;
|
||||||
|
|
||||||
|
if insentry^.code[0]=#$63 then
|
||||||
|
bytes:=bytes or (((offset+4) shr 1) and $FF)
|
||||||
|
else
|
||||||
|
bytes:=bytes or (((offset+4) shr 1) and $7FF);
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
#$64: { Thumb: Special encodings }
|
#$64: { Thumb: Special encodings }
|
||||||
begin
|
begin
|
||||||
@ -4171,7 +4231,7 @@ implementation
|
|||||||
else
|
else
|
||||||
bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF);
|
bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF);
|
||||||
end;
|
end;
|
||||||
#$68: { Thumb CB{N}Z }
|
#$68: { Thumb CB[N]Z }
|
||||||
begin
|
begin
|
||||||
bytelen:=2;
|
bytelen:=2;
|
||||||
bytes:=0;
|
bytes:=0;
|
||||||
|
@ -145,11 +145,11 @@ reg32,reg32,reg32,shifterop \x6\x0\x00 ARM32,ARMv4
|
|||||||
reg32,reg32,immshifter \x7\x2\x00 ARM32,ARMv4
|
reg32,reg32,immshifter \x7\x2\x00 ARM32,ARMv4
|
||||||
|
|
||||||
[Bcc]
|
[Bcc]
|
||||||
imm32 \x62\xE0\x0 THUMB,ARMv4T
|
imm24 \x62\xE0\x0 THUMB,ARMv4T
|
||||||
immshifter \x62\xE0\x0 THUMB,ARMv4T
|
immshifter \x62\xE0\x0 THUMB,ARMv4T
|
||||||
mem32 \x62\xE0\x0 THUMB,ARMv4T
|
mem32 \x62\xE0\x0 THUMB,ARMv4T
|
||||||
|
|
||||||
imm32 \x63\xD0\x0 THUMB,ARMv4T
|
imm24 \x63\xD0\x0 THUMB,ARMv4T
|
||||||
immshifter \x63\xD0\x0 THUMB,ARMv4T
|
immshifter \x63\xD0\x0 THUMB,ARMv4T
|
||||||
mem32 \x63\xD0\x0 THUMB,ARMv4T
|
mem32 \x63\xD0\x0 THUMB,ARMv4T
|
||||||
|
|
||||||
@ -361,6 +361,7 @@ reg32,regf \x10\x01\x0F ARM32,ARMv4
|
|||||||
[MSRcc]
|
[MSRcc]
|
||||||
regf,reg32 \x12\x01\x28\xF0 ARM32,ARMv4
|
regf,reg32 \x12\x01\x28\xF0 ARM32,ARMv4
|
||||||
regf,immshifter \x13\x03\x28\xF0 ARM32,ARMv4
|
regf,immshifter \x13\x03\x28\xF0 ARM32,ARMv4
|
||||||
|
regs,immshifter \x13\x03\x28\xF0 ARM32,ARMv4
|
||||||
|
|
||||||
[MULcc]
|
[MULcc]
|
||||||
reglo,reglo,reglo \x64\x43\x40 THUMB,ARMv4T
|
reglo,reglo,reglo \x64\x43\x40 THUMB,ARMv4T
|
||||||
@ -396,6 +397,8 @@ vreg,reg32,reg32 \x40\xC\x40\xB\x10 ARM32,VFPv2
|
|||||||
[NOP]
|
[NOP]
|
||||||
void \x61\xBF\x0 THUMB,ARMv6T2
|
void \x61\xBF\x0 THUMB,ARMv6T2
|
||||||
void \x2F\x03\x20\xF0\x0 ARM32,ARMv6K
|
void \x2F\x03\x20\xF0\x0 ARM32,ARMv6K
|
||||||
|
; Before ARMv6K use mov r0,r0
|
||||||
|
void \x2F\xE1\xA0\x0\x0 ARM32,ARMv4
|
||||||
|
|
||||||
[ORNcc]
|
[ORNcc]
|
||||||
reg32,reg32,immshifter \x80\xF0\x60\x0\x0 THUMB32,ARMv6T2
|
reg32,reg32,immshifter \x80\xF0\x60\x0\x0 THUMB32,ARMv6T2
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
{ don't edit, this file is generated from armins.dat }
|
{ don't edit, this file is generated from armins.dat }
|
||||||
651;
|
653;
|
||||||
|
@ -255,7 +255,7 @@
|
|||||||
(
|
(
|
||||||
opcode : A_B;
|
opcode : A_B;
|
||||||
ops : 1;
|
ops : 1;
|
||||||
optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
|
optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
|
||||||
code : #98#224#0;
|
code : #98#224#0;
|
||||||
flags : if_thumb or if_armv4t
|
flags : if_thumb or if_armv4t
|
||||||
),
|
),
|
||||||
@ -276,7 +276,7 @@
|
|||||||
(
|
(
|
||||||
opcode : A_B;
|
opcode : A_B;
|
||||||
ops : 1;
|
ops : 1;
|
||||||
optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
|
optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
|
||||||
code : #99#208#0;
|
code : #99#208#0;
|
||||||
flags : if_thumb or if_armv4t
|
flags : if_thumb or if_armv4t
|
||||||
),
|
),
|
||||||
@ -1085,6 +1085,13 @@
|
|||||||
code : #19#3#40#240;
|
code : #19#3#40#240;
|
||||||
flags : if_arm32 or if_armv4
|
flags : if_arm32 or if_armv4
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
opcode : A_MSR;
|
||||||
|
ops : 2;
|
||||||
|
optypes : (ot_regs,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
|
||||||
|
code : #19#3#40#240;
|
||||||
|
flags : if_arm32 or if_armv4
|
||||||
|
),
|
||||||
(
|
(
|
||||||
opcode : A_MUL;
|
opcode : A_MUL;
|
||||||
ops : 3;
|
ops : 3;
|
||||||
@ -1225,6 +1232,13 @@
|
|||||||
code : #47#3#32#240#0;
|
code : #47#3#32#240#0;
|
||||||
flags : if_arm32 or if_armv6k
|
flags : if_arm32 or if_armv6k
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
opcode : A_NOP;
|
||||||
|
ops : 0;
|
||||||
|
optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
|
||||||
|
code : #47#225#160#0#0;
|
||||||
|
flags : if_arm32 or if_armv4
|
||||||
|
),
|
||||||
(
|
(
|
||||||
opcode : A_ORN;
|
opcode : A_ORN;
|
||||||
ops : 3;
|
ops : 3;
|
||||||
|
@ -591,7 +591,6 @@ unit cpubase;
|
|||||||
var
|
var
|
||||||
t : aint;
|
t : aint;
|
||||||
i : longint;
|
i : longint;
|
||||||
imm : byte;
|
|
||||||
begin
|
begin
|
||||||
{Loading 0-255 is simple}
|
{Loading 0-255 is simple}
|
||||||
if (d and $FF) = d then
|
if (d and $FF) = d then
|
||||||
@ -611,7 +610,7 @@ unit cpubase;
|
|||||||
result:=false;
|
result:=false;
|
||||||
for i:=1 to 31 do
|
for i:=1 to 31 do
|
||||||
begin
|
begin
|
||||||
t:=RolDWord(imm,i);
|
t:=RolDWord(d,i);
|
||||||
if ((t and $FF)=t) and
|
if ((t and $FF)=t) and
|
||||||
((t and $80)=$80) then
|
((t and $80)=$80) then
|
||||||
begin
|
begin
|
||||||
|
@ -172,6 +172,10 @@ interface
|
|||||||
{ Darwin asm is using indirect symbols resolving }
|
{ Darwin asm is using indirect symbols resolving }
|
||||||
indsymbol : TObjSymbol;
|
indsymbol : TObjSymbol;
|
||||||
|
|
||||||
|
{$ifdef ARM}
|
||||||
|
ThumbFunc : boolean;
|
||||||
|
{$endif ARM}
|
||||||
|
|
||||||
constructor create(AList:TFPHashObjectList;const AName:string);
|
constructor create(AList:TFPHashObjectList;const AName:string);
|
||||||
function address:aword;
|
function address:aword;
|
||||||
procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
|
procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
|
||||||
@ -233,9 +237,6 @@ interface
|
|||||||
ExeSection : TExeSection;
|
ExeSection : TExeSection;
|
||||||
USed : Boolean;
|
USed : Boolean;
|
||||||
VTRefList : TFPObjectList;
|
VTRefList : TFPObjectList;
|
||||||
{$ifdef ARM}
|
|
||||||
ThumbFunc : boolean;
|
|
||||||
{$endif ARM}
|
|
||||||
constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual;
|
constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual;
|
||||||
destructor destroy;override;
|
destructor destroy;override;
|
||||||
function write(const d;l:aword):aword;
|
function write(const d;l:aword):aword;
|
||||||
@ -1140,10 +1141,6 @@ implementation
|
|||||||
begin
|
begin
|
||||||
result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
|
result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
|
||||||
result.ObjData:=self;
|
result.ObjData:=self;
|
||||||
{$ifdef ARM}
|
|
||||||
result.ThumbFunc:=ThumbFunc;
|
|
||||||
ThumbFunc:=false;
|
|
||||||
{$endif ARM}
|
|
||||||
end;
|
end;
|
||||||
FCurrObjSec:=result;
|
FCurrObjSec:=result;
|
||||||
end;
|
end;
|
||||||
@ -1181,6 +1178,11 @@ implementation
|
|||||||
result:=TObjSymbol(FObjSymbolList.Find(aname));
|
result:=TObjSymbol(FObjSymbolList.Find(aname));
|
||||||
if not assigned(result) then
|
if not assigned(result) then
|
||||||
result:=TObjSymbol.Create(FObjSymbolList,aname);
|
result:=TObjSymbol.Create(FObjSymbolList,aname);
|
||||||
|
|
||||||
|
{$ifdef ARM}
|
||||||
|
result.ThumbFunc:=ThumbFunc;
|
||||||
|
ThumbFunc:=false;
|
||||||
|
{$endif ARM}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -970,8 +970,7 @@ implementation
|
|||||||
elfsym.st_value:=objsym.address;
|
elfsym.st_value:=objsym.address;
|
||||||
|
|
||||||
{$ifdef ARM}
|
{$ifdef ARM}
|
||||||
if (objsym.typ=AT_FUNCTION) and
|
if objsym.ThumbFunc then
|
||||||
objsym.objsection.ThumbFunc then
|
|
||||||
inc(elfsym.st_value);
|
inc(elfsym.st_value);
|
||||||
{$endif ARM}
|
{$endif ARM}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
**********************************************************************}
|
**********************************************************************}
|
||||||
|
|
||||||
{$asmmode gas}
|
{$asmmode divided}
|
||||||
|
|
||||||
{$ifndef FPC_SYSTEM_HAS_MOVE}
|
{$ifndef FPC_SYSTEM_HAS_MOVE}
|
||||||
{$define FPC_SYSTEM_FPC_MOVE}
|
{$define FPC_SYSTEM_FPC_MOVE}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
**********************************************************************}
|
**********************************************************************}
|
||||||
|
|
||||||
{$asmmode gas}
|
{$asmmode divided}
|
||||||
|
|
||||||
{$ifndef FPC_SYSTEM_HAS_MOVE}
|
{$ifndef FPC_SYSTEM_HAS_MOVE}
|
||||||
{$define FPC_SYSTEM_FPC_MOVE}
|
{$define FPC_SYSTEM_FPC_MOVE}
|
||||||
|
Loading…
Reference in New Issue
Block a user