+ another helper function: x86_parameterized_string_op_param_count

* when generating x86 code for parameterized string instructions with the
  internal object writer, don't rely on the destination operand being [(r/e)di]
  when determining the segment prefix, because when using intel syntax, source
  and destination can be anything (only the operand size, the address size and
  the source segment is taken into account)

git-svn-id: trunk@37452 -
This commit is contained in:
nickysn 2017-10-12 16:07:15 +00:00
parent 4c75b15afe
commit baf492c7a5
3 changed files with 36 additions and 6 deletions

View File

@ -933,6 +933,9 @@ interface
implementation
uses
{$ifdef x86}
aasmcpu,
{$endif x86}
SysUtils,
verbose,
globals;
@ -2603,6 +2606,10 @@ implementation
procedure tai_cpu_abstract.loadref(opidx:longint;const r:treference);
{$ifdef x86}
var
si_param: ShortInt;
{$endif}
begin
allocate_oper(opidx+1);
with oper[opidx]^ do
@ -2619,9 +2626,10 @@ implementation
too much of a a speed penalty}
if is_x86_parameterized_string_op(opcode) then
begin
if ((ref^.base=NR_NO) or (getsupreg(ref^.base)<>RS_EDI)) and
((ref^.index=NR_NO) or (getsupreg(ref^.index)<>RS_EDI)) and
(ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
si_param:=get_x86_string_op_si_param(opcode);
if (si_param<>-1) and (taicpu(self).OperandOrder=op_att) then
si_param:=x86_parameterized_string_op_param_count(opcode)-si_param-1;
if (si_param=opidx) and (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
segprefix:=ref^.segment;
end
else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
@ -2680,6 +2688,10 @@ implementation
procedure tai_cpu_abstract.loadoper(opidx:longint;o:toper);
{$ifdef x86}
var
si_param: ShortInt;
{$endif x86}
begin
allocate_oper(opidx+1);
clearop(opidx);
@ -2698,11 +2710,14 @@ implementation
new(ref);
ref^:=o.ref^;
{$ifdef x86}
{ We allow this exception for x86, since overloading this would be
too much of a a speed penalty}
if is_x86_parameterized_string_op(opcode) then
begin
if ((ref^.base=NR_NO) or (getsupreg(ref^.base)<>RS_EDI)) and
((ref^.index=NR_NO) or (getsupreg(ref^.index)<>RS_EDI)) and
(ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
si_param:=get_x86_string_op_si_param(opcode);
if (si_param<>-1) and (taicpu(self).OperandOrder=op_att) then
si_param:=x86_parameterized_string_op_param_count(opcode)-si_param-1;
if (si_param=opidx) and (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
segprefix:=ref^.segment;
end
else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then

View File

@ -468,6 +468,7 @@ interface
{$ifdef i8086}
procedure loadsegsymbol(opidx:longint;s:tasmsymbol);
{$endif i8086}
property OperandOrder : TOperandOrder read FOperandOrder;
private
{ next fields are filled in pass1, so pass2 is faster }
insentry : PInsEntry;

View File

@ -323,6 +323,7 @@ uses
{ checks whether the specified op is an x86 parameterized string instruction
(e.g. returns true for movs, cmps, etc, but returns false for movsb, cmpsb, etc.) }
function is_x86_parameterized_string_op(op: TAsmOp): boolean;
function x86_parameterized_string_op_param_count(op: TAsmOp): shortint;
function x86_param2paramless_string_op(op: TAsmOp): TAsmOp;
function get_x86_string_op_size(op: TAsmOp): TOpSize;
{ returns the 0-based operand number (intel syntax) of the ds:[si] param of
@ -716,6 +717,19 @@ implementation
end;
function x86_parameterized_string_op_param_count(op: TAsmOp): shortint;
begin
case op of
A_MOVS,A_CMPS,A_INS,A_OUTS:
result:=2;
A_SCAS,A_LODS,A_STOS:
result:=1;
else
internalerror(2017101203);
end;
end;
function x86_param2paramless_string_op(op: TAsmOp): TAsmOp;
begin
case op of