mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-04 13:47:23 +01:00
+ some more arm binary writer stuff, this is mainly a transfer commit
git-svn-id: trunk@1068 -
This commit is contained in:
parent
9452e2a91f
commit
e7e12f0f31
@ -531,13 +531,36 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure BuildInsTabCache;
|
||||
var
|
||||
i : longint;
|
||||
begin
|
||||
new(instabcache);
|
||||
FillChar(instabcache^,sizeof(tinstabcache),$ff);
|
||||
i:=0;
|
||||
while (i<InsTabEntries) do
|
||||
begin
|
||||
if InsTabCache^[InsTab[i].Opcode]=-1 then
|
||||
InsTabCache^[InsTab[i].Opcode]:=i;
|
||||
inc(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure InitAsm;
|
||||
begin
|
||||
if not assigned(instabcache) then
|
||||
BuildInsTabCache;
|
||||
end;
|
||||
|
||||
|
||||
procedure DoneAsm;
|
||||
begin
|
||||
if assigned(instabcache) then
|
||||
begin
|
||||
dispose(instabcache);
|
||||
instabcache:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -823,6 +846,23 @@ implementation
|
||||
|
||||
function taicpu.Pass1(offset:longint):longint;
|
||||
begin
|
||||
Pass1:=0;
|
||||
{ Save the old offset and set the new offset }
|
||||
InsOffset:=Offset;
|
||||
{ Error? }
|
||||
if (Insentry=nil) and (InsSize=-1) then
|
||||
exit;
|
||||
{ set the file postion }
|
||||
aktfilepos:=fileinfo;
|
||||
{ Get InsEntry }
|
||||
if FindInsEntry then
|
||||
begin
|
||||
InsSize:=4;
|
||||
LastInsOffset:=InsOffset;
|
||||
Pass1:=InsSize;
|
||||
exit;
|
||||
end;
|
||||
LastInsOffset:=-1;
|
||||
end;
|
||||
|
||||
|
||||
@ -861,8 +901,130 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function taicpu.Matches(p:PInsEntry):longint;
|
||||
function taicpu.Matches(p:PInsEntry):longint;
|
||||
{ * IF_SM stands for Size Match: any operand whose size is not
|
||||
* explicitly specified by the template is `really' intended to be
|
||||
* the same size as the first size-specified operand.
|
||||
* Non-specification is tolerated in the input instruction, but
|
||||
* _wrong_ specification is not.
|
||||
*
|
||||
* IF_SM2 invokes Size Match on only the first _two_ operands, for
|
||||
* three-operand instructions such as SHLD: it implies that the
|
||||
* first two operands must match in size, but that the third is
|
||||
* required to be _unspecified_.
|
||||
*
|
||||
* IF_SB invokes Size Byte: operands with unspecified size in the
|
||||
* template are really bytes, and so no non-byte specification in
|
||||
* the input instruction will be tolerated. IF_SW similarly invokes
|
||||
* Size Word, and IF_SD invokes Size Doubleword.
|
||||
*
|
||||
* (The default state if neither IF_SM nor IF_SM2 is specified is
|
||||
* that any operand with unspecified size in the template is
|
||||
* required to have unspecified size in the instruction too...)
|
||||
}
|
||||
var
|
||||
i,j,asize,oprs : longint;
|
||||
siz : array[0..3] of longint;
|
||||
begin
|
||||
Matches:=100;
|
||||
|
||||
{ Check the opcode and operands }
|
||||
if (p^.opcode<>opcode) or (p^.ops<>ops) then
|
||||
begin
|
||||
Matches:=0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Check that no spurious colons or TOs are present }
|
||||
for i:=0 to p^.ops-1 do
|
||||
if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
|
||||
begin
|
||||
Matches:=0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Check that the operand flags all match up }
|
||||
for i:=0 to p^.ops-1 do
|
||||
begin
|
||||
if ((p^.optypes[i] and (not oper[i]^.ot)) or
|
||||
((p^.optypes[i] and OT_SIZE_MASK) and
|
||||
((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
|
||||
begin
|
||||
if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
|
||||
(oper[i]^.ot and OT_SIZE_MASK))<>0 then
|
||||
begin
|
||||
Matches:=0;
|
||||
exit;
|
||||
end
|
||||
else
|
||||
Matches:=1;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Check operand sizes }
|
||||
{ as default an untyped size can get all the sizes, this is different
|
||||
from nasm, but else we need to do a lot checking which opcodes want
|
||||
size or not with the automatic size generation }
|
||||
asize:=longint($ffffffff);
|
||||
(*
|
||||
if (p^.flags and IF_SB)<>0 then
|
||||
asize:=OT_BITS8
|
||||
else if (p^.flags and IF_SW)<>0 then
|
||||
asize:=OT_BITS16
|
||||
else if (p^.flags and IF_SD)<>0 then
|
||||
asize:=OT_BITS32;
|
||||
if (p^.flags and IF_ARMASK)<>0 then
|
||||
begin
|
||||
siz[0]:=0;
|
||||
siz[1]:=0;
|
||||
siz[2]:=0;
|
||||
if (p^.flags and IF_AR0)<>0 then
|
||||
siz[0]:=asize
|
||||
else if (p^.flags and IF_AR1)<>0 then
|
||||
siz[1]:=asize
|
||||
else if (p^.flags and IF_AR2)<>0 then
|
||||
siz[2]:=asize;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ we can leave because the size for all operands is forced to be
|
||||
the same
|
||||
but not if IF_SB IF_SW or IF_SD is set PM }
|
||||
if asize=-1 then
|
||||
exit;
|
||||
siz[0]:=asize;
|
||||
siz[1]:=asize;
|
||||
siz[2]:=asize;
|
||||
end;
|
||||
|
||||
if (p^.flags and (IF_SM or IF_SM2))<>0 then
|
||||
begin
|
||||
if (p^.flags and IF_SM2)<>0 then
|
||||
oprs:=2
|
||||
else
|
||||
oprs:=p^.ops;
|
||||
for i:=0 to oprs-1 do
|
||||
if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
|
||||
begin
|
||||
for j:=0 to oprs-1 do
|
||||
siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
|
||||
break;
|
||||
end;
|
||||
end
|
||||
else
|
||||
oprs:=2;
|
||||
|
||||
{ Check operand sizes }
|
||||
for i:=0 to p^.ops-1 do
|
||||
begin
|
||||
if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
|
||||
((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
|
||||
{ Immediates can always include smaller size }
|
||||
((oper[i]^.ot and OT_IMMEDIATE)=0) and
|
||||
(((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
|
||||
Matches:=2;
|
||||
end;
|
||||
*)
|
||||
end;
|
||||
|
||||
|
||||
@ -931,8 +1093,6 @@ implementation
|
||||
inssize:=-1;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
||||
{$ifdef dummy}
|
||||
|
||||
@ -1040,6 +1040,11 @@ Implementation
|
||||
objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
|
||||
{$endif NOAG386BIN}
|
||||
{$endif i386}
|
||||
{$ifdef arm}
|
||||
{ reset instructions which could change in pass 2 }
|
||||
Taicpu(hp).resetpass2;
|
||||
objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
|
||||
{$endif arm}
|
||||
end;
|
||||
ait_cutobject :
|
||||
if SmartAsm then
|
||||
@ -1054,12 +1059,8 @@ Implementation
|
||||
function TInternalAssembler.TreePass1(hp:Tai):Tai;
|
||||
var
|
||||
InlineLevel,
|
||||
l : longint;
|
||||
{$ifdef i386}
|
||||
{$ifndef NOAG386BIN}
|
||||
l,
|
||||
i : longint;
|
||||
{$endif NOAG386BIN}
|
||||
{$endif i386}
|
||||
begin
|
||||
inlinelevel:=0;
|
||||
while assigned(hp) do
|
||||
@ -1210,6 +1211,25 @@ Implementation
|
||||
end;
|
||||
{$endif NOAG386BIN}
|
||||
{$endif i386}
|
||||
{$ifdef arm}
|
||||
objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
|
||||
{ fixup the references }
|
||||
for i:=1 to Taicpu(hp).ops do
|
||||
begin
|
||||
with Taicpu(hp).oper[i-1]^ do
|
||||
begin
|
||||
case typ of
|
||||
top_ref :
|
||||
begin
|
||||
if assigned(ref^.symbol) then
|
||||
objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
|
||||
if assigned(ref^.relsymbol) then
|
||||
objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$endif arm}
|
||||
end;
|
||||
ait_direct :
|
||||
Message(asmw_f_direct_not_supported);
|
||||
@ -1340,12 +1360,8 @@ Implementation
|
||||
but it's better to be on the safe side (PFV) }
|
||||
objectoutput.exportsymbol(Tai_label(hp).l);
|
||||
end;
|
||||
{$ifdef i386}
|
||||
{$ifndef NOAG386BIN}
|
||||
ait_instruction :
|
||||
Taicpu(hp).Pass2(objectdata);
|
||||
{$endif NOAG386BIN}
|
||||
{$endif i386}
|
||||
{$ifdef GDB}
|
||||
ait_stabn :
|
||||
convertstabs(Tai_stabn(hp).str);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user