* 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); procedure changeopsize(siz:topsize);
function GetString:string; 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 private
FOperandOrder : TOperandOrder; FOperandOrder : TOperandOrder;
procedure init(_size : topsize); { this need to be called by all constructor } procedure init(_size : topsize); { this need to be called by all constructor }
@ -961,8 +968,10 @@ implementation
end; end;
procedure taicpu.CheckNonCommutativeOpcodes; function taicpu.FixNonCommutativeOpcodes: tasmop;
begin begin
result:=opcode;
{ we need ATT order } { we need ATT order }
SetOperandOrder(op_att); SetOperandOrder(op_att);
@ -981,21 +990,21 @@ implementation
(ops=0) then (ops=0) then
begin begin
if opcode=A_FSUBR then if opcode=A_FSUBR then
opcode:=A_FSUB result:=A_FSUB
else if opcode=A_FSUB then else if opcode=A_FSUB then
opcode:=A_FSUBR result:=A_FSUBR
else if opcode=A_FDIVR then else if opcode=A_FDIVR then
opcode:=A_FDIV result:=A_FDIV
else if opcode=A_FDIV then else if opcode=A_FDIV then
opcode:=A_FDIVR result:=A_FDIVR
else if opcode=A_FSUBRP then else if opcode=A_FSUBRP then
opcode:=A_FSUBP result:=A_FSUBP
else if opcode=A_FSUBP then else if opcode=A_FSUBP then
opcode:=A_FSUBRP result:=A_FSUBRP
else if opcode=A_FDIVRP then else if opcode=A_FDIVRP then
opcode:=A_FDIVP result:=A_FDIVP
else if opcode=A_FDIVP then else if opcode=A_FDIVP then
opcode:=A_FDIVRP; result:=A_FDIVRP;
end; end;
if ( if (
(ops=1) and (ops=1) and
@ -1005,13 +1014,13 @@ implementation
) then ) then
begin begin
if opcode=A_FSUBRP then if opcode=A_FSUBRP then
opcode:=A_FSUBP result:=A_FSUBP
else if opcode=A_FSUBP then else if opcode=A_FSUBP then
opcode:=A_FSUBRP result:=A_FSUBRP
else if opcode=A_FDIVRP then else if opcode=A_FDIVRP then
opcode:=A_FDIVP result:=A_FDIVP
else if opcode=A_FDIVP then else if opcode=A_FDIVP then
opcode:=A_FDIVRP; result:=A_FDIVRP;
end; end;
end; end;

View File

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