mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-02 23:50:24 +02:00
+ implemented support for instructions with non-native address size on i8086
(16-bit and 32-bit), i386 (16-bit and 32-bit) and x86_64 (32-bit and 64-bit). Known bug: 32-bit addresses with an offset have their offset truncated to its low 16-bits on i8086 git-svn-id: trunk@37409 -
This commit is contained in:
parent
bfd37969ad
commit
92a52a9f4d
@ -2650,7 +2650,7 @@
|
|||||||
opcode : A_LEA;
|
opcode : A_LEA;
|
||||||
ops : 2;
|
ops : 2;
|
||||||
optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
|
optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
|
||||||
code : #193#208#1#141#72;
|
code : #208#1#141#72;
|
||||||
flags : [if_8086]
|
flags : [if_8086]
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -2664,7 +2664,7 @@
|
|||||||
opcode : A_LEA;
|
opcode : A_LEA;
|
||||||
ops : 2;
|
ops : 2;
|
||||||
optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
|
optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
|
||||||
code : #193#208#1#141#72;
|
code : #208#1#141#72;
|
||||||
flags : [if_8086]
|
flags : [if_8086]
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -483,6 +483,9 @@ interface
|
|||||||
function calcsize(p:PInsEntry):shortint;
|
function calcsize(p:PInsEntry):shortint;
|
||||||
procedure gencode(objdata:TObjData);
|
procedure gencode(objdata:TObjData);
|
||||||
function NeedAddrPrefix(opidx:byte):boolean;
|
function NeedAddrPrefix(opidx:byte):boolean;
|
||||||
|
function NeedAddrPrefix:boolean;
|
||||||
|
procedure write0x66prefix(objdata:TObjData);
|
||||||
|
procedure write0x67prefix(objdata:TObjData);
|
||||||
procedure Swapoperands;
|
procedure Swapoperands;
|
||||||
function FindInsentry(objdata:TObjData):boolean;
|
function FindInsentry(objdata:TObjData):boolean;
|
||||||
end;
|
end;
|
||||||
@ -1704,6 +1707,8 @@ implementation
|
|||||||
InsSize:=calcsize(insentry);
|
InsSize:=calcsize(insentry);
|
||||||
if segprefix<>NR_NO then
|
if segprefix<>NR_NO then
|
||||||
inc(InsSize);
|
inc(InsSize);
|
||||||
|
if NeedAddrPrefix then
|
||||||
|
inc(InsSize);
|
||||||
{ Fix opsize if size if forced }
|
{ Fix opsize if size if forced }
|
||||||
if insentry^.flags*[IF_SB,IF_SW,IF_SD]<>[] then
|
if insentry^.flags*[IF_SB,IF_SW,IF_SD]<>[] then
|
||||||
begin
|
begin
|
||||||
@ -1759,13 +1764,51 @@ implementation
|
|||||||
end
|
end
|
||||||
else if segprefix<>NR_NO then
|
else if segprefix<>NR_NO then
|
||||||
InternalError(201001071);
|
InternalError(201001071);
|
||||||
|
{ Address size prefix? }
|
||||||
|
if NeedAddrPrefix then
|
||||||
|
begin
|
||||||
|
write0x67prefix(objdata);
|
||||||
|
{ fix the offset for GenNode }
|
||||||
|
inc(InsOffset);
|
||||||
|
end;
|
||||||
{ Generate the instruction }
|
{ Generate the instruction }
|
||||||
GenCode(objdata);
|
GenCode(objdata);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function is_16_bit_ref(const input:toper):boolean;
|
||||||
|
var
|
||||||
|
ir,br : Tregister;
|
||||||
|
isub,bsub : tsubregister;
|
||||||
|
has_16_bit_regs: Boolean;
|
||||||
|
begin
|
||||||
|
if (input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)=R_MMREGISTER) then
|
||||||
|
exit(false);
|
||||||
|
ir:=input.ref^.index;
|
||||||
|
br:=input.ref^.base;
|
||||||
|
isub:=getsubreg(ir);
|
||||||
|
bsub:=getsubreg(br);
|
||||||
|
{ it's a direct address }
|
||||||
|
if (br=NR_NO) and (ir=NR_NO) then
|
||||||
|
begin
|
||||||
|
{$ifdef i8086}
|
||||||
|
result:=true;
|
||||||
|
{$else i8086}
|
||||||
|
result:=false;
|
||||||
|
{$endif}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{ it's an indirection }
|
||||||
|
begin
|
||||||
|
result := ((ir<>NR_NO) and (isub=R_SUBW)) or
|
||||||
|
((br<>NR_NO) and (bsub=R_SUBW));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function taicpu.needaddrprefix(opidx:byte):boolean;
|
function taicpu.needaddrprefix(opidx:byte):boolean;
|
||||||
begin
|
begin
|
||||||
|
{$if defined(x86_64)}
|
||||||
result:=(oper[opidx]^.typ=top_ref) and
|
result:=(oper[opidx]^.typ=top_ref) and
|
||||||
(oper[opidx]^.ref^.refaddr=addr_no) and
|
(oper[opidx]^.ref^.refaddr=addr_no) and
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
@ -1781,6 +1824,22 @@ implementation
|
|||||||
(getsubreg(oper[opidx]^.ref^.base)<>R_SUBADDR)
|
(getsubreg(oper[opidx]^.ref^.base)<>R_SUBADDR)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
{$elseif defined(i386)}
|
||||||
|
result:=(oper[opidx]^.typ=top_ref) and is_16_bit_ref(oper[opidx]^);
|
||||||
|
{$elseif defined(i8086)}
|
||||||
|
result:=(oper[opidx]^.typ=top_ref) and not is_16_bit_ref(oper[opidx]^);
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function taicpu.NeedAddrPrefix:boolean;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to ops-1 do
|
||||||
|
if needaddrprefix(i) then
|
||||||
|
exit(true);
|
||||||
|
result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -2055,7 +2114,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{$elseif defined(i386)}
|
{$elseif defined(i386) or defined(i8086)}
|
||||||
|
|
||||||
function process_ea_ref_32(const input:toper;out output:ea;rfield:longint):boolean;
|
function process_ea_ref_32(const input:toper;out output:ea;rfield:longint):boolean;
|
||||||
var
|
var
|
||||||
@ -2210,7 +2269,6 @@ implementation
|
|||||||
output.size:=1+output.bytes;
|
output.size:=1+output.bytes;
|
||||||
result:=true;
|
result:=true;
|
||||||
end;
|
end;
|
||||||
{$elseif defined(i8086)}
|
|
||||||
|
|
||||||
procedure maybe_swap_index_base(var br,ir:Tregister);
|
procedure maybe_swap_index_base(var br,ir:Tregister);
|
||||||
var
|
var
|
||||||
@ -2322,10 +2380,11 @@ implementation
|
|||||||
internalerror(200409263);
|
internalerror(200409263);
|
||||||
{$if defined(x86_64)}
|
{$if defined(x86_64)}
|
||||||
result:=process_ea_ref_64_32(input,output,rfield);
|
result:=process_ea_ref_64_32(input,output,rfield);
|
||||||
{$elseif defined(i386)}
|
{$elseif defined(i386) or defined(i8086)}
|
||||||
result:=process_ea_ref_32(input,output,rfield);
|
if is_16_bit_ref(input) then
|
||||||
{$elseif defined(i8086)}
|
result:=process_ea_ref_16(input,output,rfield)
|
||||||
result:=process_ea_ref_16(input,output,rfield);
|
else
|
||||||
|
result:=process_ea_ref_32(input,output,rfield);
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2593,6 +2652,30 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure taicpu.write0x66prefix(objdata:TObjData);
|
||||||
|
const
|
||||||
|
b66: Byte=$66;
|
||||||
|
begin
|
||||||
|
{$ifdef i8086}
|
||||||
|
if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
|
||||||
|
Message(asmw_e_instruction_not_supported_by_cpu);
|
||||||
|
{$endif i8086}
|
||||||
|
objdata.writebytes(b66,1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure taicpu.write0x67prefix(objdata:TObjData);
|
||||||
|
const
|
||||||
|
b67: Byte=$67;
|
||||||
|
begin
|
||||||
|
{$ifdef i8086}
|
||||||
|
if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
|
||||||
|
Message(asmw_e_instruction_not_supported_by_cpu);
|
||||||
|
{$endif i8086}
|
||||||
|
objdata.writebytes(b67,1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure taicpu.GenCode(objdata:TObjData);
|
procedure taicpu.GenCode(objdata:TObjData);
|
||||||
{
|
{
|
||||||
* the actual codes (C syntax, i.e. octal):
|
* the actual codes (C syntax, i.e. octal):
|
||||||
@ -2756,28 +2839,6 @@ implementation
|
|||||||
end;
|
end;
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
|
|
||||||
procedure write0x66prefix;
|
|
||||||
const
|
|
||||||
b66: Byte=$66;
|
|
||||||
begin
|
|
||||||
{$ifdef i8086}
|
|
||||||
if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
|
|
||||||
Message(asmw_e_instruction_not_supported_by_cpu);
|
|
||||||
{$endif i8086}
|
|
||||||
objdata.writebytes(b66,1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure write0x67prefix;
|
|
||||||
const
|
|
||||||
b67: Byte=$67;
|
|
||||||
begin
|
|
||||||
{$ifdef i8086}
|
|
||||||
if (objdata.CPUType<>cpu_none) and (objdata.CPUType<cpu_386) then
|
|
||||||
Message(asmw_e_instruction_not_supported_by_cpu);
|
|
||||||
{$endif i8086}
|
|
||||||
objdata.writebytes(b67,1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure objdata_writereloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
|
procedure objdata_writereloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
|
||||||
begin
|
begin
|
||||||
{$ifdef i386}
|
{$ifdef i386}
|
||||||
@ -2900,7 +2961,7 @@ implementation
|
|||||||
{ Force word push/pop for registers }
|
{ Force word push/pop for registers }
|
||||||
if (opsize={$ifdef i8086}S_L{$else}S_W{$endif}) and ((codes[0]=#4) or (codes[0]=#6) or
|
if (opsize={$ifdef i8086}S_L{$else}S_W{$endif}) and ((codes[0]=#4) or (codes[0]=#6) or
|
||||||
((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
|
((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
|
||||||
write0x66prefix;
|
write0x66prefix(objdata);
|
||||||
|
|
||||||
// needed VEX Prefix (for AVX etc.)
|
// needed VEX Prefix (for AVX etc.)
|
||||||
|
|
||||||
@ -3272,7 +3333,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
{$if defined(x86_64) or defined(i8086)}
|
{$if defined(x86_64) or defined(i8086)}
|
||||||
if (oper[c and 3]^.ot and OT_SIZE_MASK)=OT_BITS32 then
|
if (oper[c and 3]^.ot and OT_SIZE_MASK)=OT_BITS32 then
|
||||||
write0x67prefix;
|
write0x67prefix(objdata);
|
||||||
{$endif x86_64 or i8086}
|
{$endif x86_64 or i8086}
|
||||||
end;
|
end;
|
||||||
&310 : { fixed 16-bit addr }
|
&310 : { fixed 16-bit addr }
|
||||||
@ -3280,13 +3341,13 @@ implementation
|
|||||||
{ every insentry having code 0310 must be marked with NOX86_64 }
|
{ every insentry having code 0310 must be marked with NOX86_64 }
|
||||||
InternalError(2011051302);
|
InternalError(2011051302);
|
||||||
{$elseif defined(i386)}
|
{$elseif defined(i386)}
|
||||||
write0x67prefix;
|
write0x67prefix(objdata);
|
||||||
{$elseif defined(i8086)}
|
{$elseif defined(i8086)}
|
||||||
{nothing};
|
{nothing};
|
||||||
{$endif}
|
{$endif}
|
||||||
&311 : { fixed 32-bit addr }
|
&311 : { fixed 32-bit addr }
|
||||||
{$if defined(x86_64) or defined(i8086)}
|
{$if defined(x86_64) or defined(i8086)}
|
||||||
write0x67prefix
|
write0x67prefix(objdata)
|
||||||
{$endif x86_64 or i8086}
|
{$endif x86_64 or i8086}
|
||||||
;
|
;
|
||||||
&320,&321,&322 :
|
&320,&321,&322 :
|
||||||
@ -3297,7 +3358,7 @@ implementation
|
|||||||
{$elseif defined(i8086)}
|
{$elseif defined(i8086)}
|
||||||
OT_BITS32 :
|
OT_BITS32 :
|
||||||
{$endif}
|
{$endif}
|
||||||
write0x66prefix;
|
write0x66prefix(objdata);
|
||||||
{$ifndef x86_64}
|
{$ifndef x86_64}
|
||||||
OT_BITS64 :
|
OT_BITS64 :
|
||||||
Message(asmw_e_64bit_not_supported);
|
Message(asmw_e_64bit_not_supported);
|
||||||
@ -3307,7 +3368,7 @@ implementation
|
|||||||
&323 : {no action needed};
|
&323 : {no action needed};
|
||||||
&325:
|
&325:
|
||||||
{$ifdef i8086}
|
{$ifdef i8086}
|
||||||
write0x66prefix;
|
write0x66prefix(objdata);
|
||||||
{$else i8086}
|
{$else i8086}
|
||||||
{no action needed};
|
{no action needed};
|
||||||
{$endif i8086}
|
{$endif i8086}
|
||||||
@ -3317,7 +3378,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
{$ifndef i8086}
|
{$ifndef i8086}
|
||||||
if not(needed_VEX) then
|
if not(needed_VEX) then
|
||||||
write0x66prefix;
|
write0x66prefix(objdata);
|
||||||
{$endif not i8086}
|
{$endif not i8086}
|
||||||
end;
|
end;
|
||||||
&326 :
|
&326 :
|
||||||
|
@ -939,7 +939,7 @@ reg16|32,mem \320\1\xC5\110 8086,NOX86_64
|
|||||||
|
|
||||||
[LEA,leaX]
|
[LEA,leaX]
|
||||||
(Ch_Wop2, Ch_Rop1)
|
(Ch_Wop2, Ch_Rop1)
|
||||||
reg16|32|64,mem \301\320\1\x8D\110 8086
|
reg16|32|64,mem \320\1\x8D\110 8086
|
||||||
|
|
||||||
[LEAVE]
|
[LEAVE]
|
||||||
(Ch_RWESP, Ch_WEBP)
|
(Ch_RWESP, Ch_WEBP)
|
||||||
|
@ -2608,7 +2608,7 @@
|
|||||||
opcode : A_LEA;
|
opcode : A_LEA;
|
||||||
ops : 2;
|
ops : 2;
|
||||||
optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
|
optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
|
||||||
code : #193#208#1#141#72;
|
code : #208#1#141#72;
|
||||||
flags : [if_8086]
|
flags : [if_8086]
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
Loading…
Reference in New Issue
Block a user