* fixed a bug which caused non commutative fpu instructions to be wrong when using an intel-style external assembler and compiling a smartlinked unit

git-svn-id: branches/i8086@24151 -
This commit is contained in:
nickysn 2013-04-04 20:17:50 +00:00
parent 74cd67b85c
commit c3aaa37c0c
2 changed files with 34 additions and 24 deletions

View File

@ -306,7 +306,14 @@ interface
procedure changeopsize(siz:topsize);
function GetString:string;
procedure CheckNonCommutativeOpcodes;
{ This is a workaround for the GAS non commutative fpu instruction braindamage.
Early versions of the UnixWare assembler had a bug where some fpu instructions
were reversed and GAS still keeps this "feature" for compatibility.
for details: http://sourceware.org/binutils/docs/as/i386_002dBugs.html#i386_002dBugs
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=372528
http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#Caveats }
function FixNonCommutativeOpcodes: tasmop;
private
FOperandOrder : TOperandOrder;
procedure init(_size : topsize); { this need to be called by all constructor }
@ -961,8 +968,10 @@ implementation
end;
procedure taicpu.CheckNonCommutativeOpcodes;
function taicpu.FixNonCommutativeOpcodes: tasmop;
begin
result:=opcode;
{ we need ATT order }
SetOperandOrder(op_att);
@ -981,21 +990,21 @@ implementation
(ops=0) then
begin
if opcode=A_FSUBR then
opcode:=A_FSUB
result:=A_FSUB
else if opcode=A_FSUB then
opcode:=A_FSUBR
result:=A_FSUBR
else if opcode=A_FDIVR then
opcode:=A_FDIV
result:=A_FDIV
else if opcode=A_FDIV then
opcode:=A_FDIVR
result:=A_FDIVR
else if opcode=A_FSUBRP then
opcode:=A_FSUBP
result:=A_FSUBP
else if opcode=A_FSUBP then
opcode:=A_FSUBRP
result:=A_FSUBRP
else if opcode=A_FDIVRP then
opcode:=A_FDIVP
result:=A_FDIVP
else if opcode=A_FDIVP then
opcode:=A_FDIVRP;
result:=A_FDIVRP;
end;
if (
(ops=1) and
@ -1005,13 +1014,13 @@ implementation
) then
begin
if opcode=A_FSUBRP then
opcode:=A_FSUBP
result:=A_FSUBP
else if opcode=A_FSUBP then
opcode:=A_FSUBRP
result:=A_FSUBRP
else if opcode=A_FDIVRP then
opcode:=A_FDIVP
result:=A_FDIVP
else if opcode=A_FDIVP then
opcode:=A_FDIVRP;
result:=A_FDIVRP;
end;
end;

View File

@ -537,6 +537,7 @@ interface
{$ifdef cpuextended}
e : extended;
{$endif cpuextended}
fixed_opcode: TAsmOp;
begin
if not assigned(p) then
exit;
@ -884,12 +885,12 @@ interface
ait_instruction :
begin
taicpu(hp).CheckNonCommutativeOpcodes;
fixed_opcode:=taicpu(hp).FixNonCommutativeOpcodes;
{ We need intel order, no At&t }
taicpu(hp).SetOperandOrder(op_intel);
s:='';
if ((taicpu(hp).opcode=A_FADDP) or
(taicpu(hp).opcode=A_FMULP))
if ((fixed_opcode=A_FADDP) or
(fixed_opcode=A_FMULP))
and (taicpu(hp).ops=0) then
begin
taicpu(hp).allocate_oper(2);
@ -898,7 +899,7 @@ interface
taicpu(hp).oper[1]^.typ:=top_reg;
taicpu(hp).oper[1]^.reg:=NR_ST;
end;
if taicpu(hp).opcode=A_FWAIT then
if fixed_opcode=A_FWAIT then
AsmWriteln(#9#9'DB'#9'09bh')
else
begin
@ -906,18 +907,18 @@ interface
word prefix to get selectors
to be pushed in 2 bytes PM }
if (taicpu(hp).opsize=S_W) and
((taicpu(hp).opcode=A_PUSH) or
(taicpu(hp).opcode=A_POP)) and
((fixed_opcode=A_PUSH) or
(fixed_opcode=A_POP)) and
(taicpu(hp).oper[0]^.typ=top_reg) and
(is_segment_reg(taicpu(hp).oper[0]^.reg)) then
AsmWriteln(#9#9'DB'#9'066h');
AsmWrite(#9#9+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]);
AsmWrite(#9#9+std_op2str[fixed_opcode]+cond2str[taicpu(hp).condition]);
if taicpu(hp).ops<>0 then
begin
if is_calljmp(taicpu(hp).opcode) then
if is_calljmp(fixed_opcode) then
begin
AsmWrite(#9);
WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp).opcode);
WriteOper_jmp(taicpu(hp).oper[0]^,fixed_opcode);
end
else
begin
@ -927,7 +928,7 @@ interface
AsmWrite(#9)
else
AsmWrite(',');
WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,taicpu(hp).opcode,taicpu(hp).ops,(i=2));
WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,fixed_opcode,taicpu(hp).ops,(i=2));
end;
end;
end;