|
@@ -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;
|