mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 19:29:24 +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 get_32bit_ops(op: TOpCG; out op1,op2: TAsmOp);
|
||||
|
||||
procedure add_move_instruction(instr:Taicpu);override;
|
||||
end;
|
||||
|
||||
tcg64f8086 = class(tcg64f32)
|
||||
@ -1630,6 +1632,72 @@ unit cgcpu;
|
||||
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);
|
||||
var
|
||||
hsym : tsym;
|
||||
|
Loading…
Reference in New Issue
Block a user