mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 19:29:39 +02:00
* on i8086 with regvars on, do not notify the register allocator of moves to BX.
This fixes compilation of unit math (and the whole RTL) with regvars enabled. git-svn-id: trunk@26282 -
This commit is contained in:
parent
e6a9bfdc1d
commit
fdd36b4603
@ -89,6 +89,8 @@ unit cgcpu;
|
|||||||
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
|
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
|
||||||
|
|
||||||
procedure get_32bit_ops(op: TOpCG; out op1,op2: TAsmOp);
|
procedure get_32bit_ops(op: TOpCG; out op1,op2: TAsmOp);
|
||||||
|
|
||||||
|
procedure add_move_instruction(instr:Taicpu);override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tcg64f8086 = class(tcg64f32)
|
tcg64f8086 = class(tcg64f32)
|
||||||
@ -1630,6 +1632,72 @@ unit cgcpu;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tcg8086.add_move_instruction(instr: Taicpu);
|
||||||
|
begin
|
||||||
|
{ HACK: when regvars are on, don't notify the register allocator of any
|
||||||
|
direct moves to BX, so it doesn't try to coalesce them. Currently,
|
||||||
|
direct moves to BX are only used when returning an int64 value in
|
||||||
|
AX:BX:CX:DX. This hack fixes a common issue with functions, returning
|
||||||
|
int64, for example:
|
||||||
|
|
||||||
|
function RandomFrom(const AValues: array of Int64): Int64;
|
||||||
|
begin
|
||||||
|
result:=AValues[random(High(AValues)+1)];
|
||||||
|
end;
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
; Var AValues located in register ireg20w
|
||||||
|
; Var $highAVALUES located in register ireg21w
|
||||||
|
; Var $result located in register ireg33w:ireg32w:ireg31w:ireg30w
|
||||||
|
mov ireg20w,word [bp+6]
|
||||||
|
mov ireg21w,word [bp+4]
|
||||||
|
; [3] result:=AValues[random(High(AValues)+1)];
|
||||||
|
mov ireg22w,ireg21w
|
||||||
|
inc ireg22w
|
||||||
|
mov ax,ireg22w
|
||||||
|
cwd
|
||||||
|
mov ireg23w,ax
|
||||||
|
mov ireg24w,dx
|
||||||
|
push ireg24w
|
||||||
|
push ireg23w
|
||||||
|
call SYSTEM_$$_RANDOM$LONGINT$$LONGINT
|
||||||
|
mov ireg25w,ax
|
||||||
|
mov ireg26w,dx
|
||||||
|
mov ireg27w,ireg25w
|
||||||
|
mov ireg28w,ireg27w
|
||||||
|
mov ireg29w,ireg28w
|
||||||
|
mov cl,3
|
||||||
|
shl ireg29w,cl
|
||||||
|
; Var $result located in register ireg32w:ireg30w
|
||||||
|
mov ireg30w,word [ireg20w+ireg29w]
|
||||||
|
mov ireg31w,word [ireg20w+ireg29w+2]
|
||||||
|
mov ireg32w,word [ireg20w+ireg29w+4] ; problematic section start
|
||||||
|
mov ireg33w,word [ireg20w+ireg29w+6]
|
||||||
|
; [4] end;
|
||||||
|
mov bx,ireg32w ; problematic section end
|
||||||
|
mov ax,ireg33w
|
||||||
|
mov dx,ireg30w
|
||||||
|
mov cx,ireg31w
|
||||||
|
mov sp,bp
|
||||||
|
pop bp
|
||||||
|
ret 4
|
||||||
|
|
||||||
|
the problem arises, because the register allocator tries to coalesce
|
||||||
|
mov bx,ireg32w
|
||||||
|
however, in the references [ireg20w+ireg29w+const], due to the
|
||||||
|
constraints of i8086, ireg20w can only be BX (or BP, which isn't available
|
||||||
|
to the register allocator, because it's used as a base pointer) }
|
||||||
|
|
||||||
|
if (cs_opt_regvar in current_settings.optimizerswitches) and
|
||||||
|
(instr.opcode=A_MOV) and (instr.ops=2) and
|
||||||
|
(instr.oper[1]^.typ=top_reg) and (getsupreg(instr.oper[1]^.reg)=RS_BX) then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
inherited add_move_instruction(instr);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tcg8086.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
|
procedure tcg8086.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
|
||||||
var
|
var
|
||||||
hsym : tsym;
|
hsym : tsym;
|
||||||
|
Loading…
Reference in New Issue
Block a user