|
@@ -29,9 +29,7 @@ interface
|
|
|
|
|
|
uses
|
|
|
cobjects,
|
|
|
-{$ifdef CG11}
|
|
|
- node,
|
|
|
-{$else}
|
|
|
+{$ifndef CG11}
|
|
|
tree,
|
|
|
{$endif}
|
|
|
cpubase,cpuasm,
|
|
@@ -112,20 +110,21 @@ interface
|
|
|
procedure incrstringref(t : pdef;const ref : treference);
|
|
|
procedure decrstringref(t : pdef;const ref : treference);
|
|
|
|
|
|
- function maybe_push(needed : byte;p : {$ifdef CG11}tnode{$else}ptree{$endif};isint64 : boolean) : boolean;
|
|
|
procedure push_int(l : longint);
|
|
|
procedure emit_push_mem(const ref : treference);
|
|
|
procedure emitpushreferenceaddr(const ref : treference);
|
|
|
+{$ifndef CG11}
|
|
|
+ function maybe_push(needed : byte;p : {$ifdef CG11}tnode{$else}ptree{$endif};isint64 : boolean) : boolean;
|
|
|
procedure pushsetelement(p : {$ifdef CG11}tnode{$else}ptree{$endif});
|
|
|
procedure restore(p : {$ifdef CG11}tnode{$else}ptree{$endif};isint64 : boolean);
|
|
|
procedure push_value_para(p:{$ifdef CG11}tnode{$else}ptree{$endif};inlined,is_cdecl:boolean;
|
|
|
para_offset:longint;alignment : longint);
|
|
|
-
|
|
|
{$ifdef TEMPS_NOT_PUSH}
|
|
|
{ does the same as restore, but uses temp. space instead of pushing }
|
|
|
function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
|
|
|
procedure restorefromtemp(p : ptree;isint64 : boolean);
|
|
|
{$endif TEMPS_NOT_PUSH}
|
|
|
+{$endif}
|
|
|
|
|
|
procedure floatload(t : tfloattype;const ref : treference);
|
|
|
procedure floatstore(t : tfloattype;const ref : treference);
|
|
@@ -133,12 +132,14 @@ interface
|
|
|
procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
|
|
|
|
|
|
procedure maybe_loadesi;
|
|
|
- procedure maketojumpbool(p : {$ifdef CG11}tnode{$else}ptree{$endif});
|
|
|
procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;destreg:Tregister;delloc:boolean);
|
|
|
- procedure emitoverflowcheck(p:{$ifdef CG11}tnode{$else}ptree{$endif});
|
|
|
- procedure emitrangecheck(p:{$ifdef CG11}tnode{$else}ptree{$endif};todef:pdef);
|
|
|
procedure concatcopy(source,dest : treference;size : longint;delsource : boolean;loadref:boolean);
|
|
|
- procedure firstcomplex(p : {$ifdef CG11}tnode{$else}ptree{$endif});
|
|
|
+{$ifndef CG11}
|
|
|
+ procedure maketojumpbool(p : ptree);
|
|
|
+ procedure emitoverflowcheck(p:ptree);
|
|
|
+ procedure emitrangecheck(p:ptree;todef:pdef);
|
|
|
+ procedure firstcomplex(p : ptree);
|
|
|
+{$endif}
|
|
|
|
|
|
procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
|
|
|
stackframe:longint;
|
|
@@ -350,22 +351,6 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
internalerror(7453984);
|
|
|
end;
|
|
|
|
|
|
-{$ifdef nojmpfix}
|
|
|
- procedure emitjmp(c : tasmcond;var l : pasmlabel);
|
|
|
- var
|
|
|
- ai : Paicpu;
|
|
|
- begin
|
|
|
- if c=C_None then
|
|
|
- exprasmlist^.concat(new(paicpu,op_sym(A_JMP,S_NO,l)))
|
|
|
- else
|
|
|
- begin
|
|
|
- ai:=new(paicpu,op_sym(A_Jcc,S_NO,l));
|
|
|
- ai^.SetCondition(c);
|
|
|
- ai^.is_jmp:=true;
|
|
|
- exprasmlist^.concat(ai);
|
|
|
- end;
|
|
|
- end;
|
|
|
-{$else nojmpfix}
|
|
|
procedure emitjmp(c : tasmcond;var l : pasmlabel);
|
|
|
var
|
|
|
ai : Paicpu;
|
|
@@ -380,7 +365,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
ai^.is_jmp:=true;
|
|
|
exprasmlist^.concat(ai);
|
|
|
end;
|
|
|
-{$endif nojmpfix}
|
|
|
+
|
|
|
|
|
|
procedure emit_flag2reg(flag:tresflags;hregister:tregister);
|
|
|
var
|
|
@@ -1077,74 +1062,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
Emit Push Functions
|
|
|
*****************************************************************************}
|
|
|
|
|
|
-{$ifdef CG11}
|
|
|
- function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
|
|
|
- var
|
|
|
- pushed : boolean;
|
|
|
- {hregister : tregister; }
|
|
|
-{$ifdef TEMPS_NOT_PUSH}
|
|
|
- href : treference;
|
|
|
-{$endif TEMPS_NOT_PUSH}
|
|
|
- begin
|
|
|
- if needed>usablereg32 then
|
|
|
- begin
|
|
|
- if (p.location.loc=LOC_REGISTER) then
|
|
|
- begin
|
|
|
- if isint64 then
|
|
|
- begin
|
|
|
-{$ifdef TEMPS_NOT_PUSH}
|
|
|
- gettempofsizereference(href,8);
|
|
|
- p.temp_offset:=href.offset;
|
|
|
- href.offset:=href.offset+4;
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p.location.registerhigh,href)));
|
|
|
- href.offset:=href.offset-4;
|
|
|
-{$else TEMPS_NOT_PUSH}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerhigh)));
|
|
|
-{$endif TEMPS_NOT_PUSH}
|
|
|
- ungetregister32(p^.location.registerhigh);
|
|
|
- end
|
|
|
-{$ifdef TEMPS_NOT_PUSH}
|
|
|
- else
|
|
|
- begin
|
|
|
- gettempofsizereference(href,4);
|
|
|
- p.temp_offset:=href.offset;
|
|
|
- end
|
|
|
-{$endif TEMPS_NOT_PUSH}
|
|
|
- ;
|
|
|
- pushed:=true;
|
|
|
-{$ifdef TEMPS_NOT_PUSH}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p.location.register,href)));
|
|
|
-{$else TEMPS_NOT_PUSH}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.register)));
|
|
|
-{$endif TEMPS_NOT_PUSH}
|
|
|
- ungetregister32(p.location.register);
|
|
|
- end
|
|
|
- else if (p.location.loc in [LOC_MEM,LOC_REFERENCE]) and
|
|
|
- ((p.location.reference.base<>R_NO) or
|
|
|
- (p.location.reference.index<>R_NO)
|
|
|
- ) then
|
|
|
- begin
|
|
|
- del_reference(p.location.reference);
|
|
|
- getexplicitregister32(R_EDI);
|
|
|
- emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),R_EDI);
|
|
|
-{$ifdef TEMPS_NOT_PUSH}
|
|
|
- gettempofsizereference(href,4);
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
|
|
|
- p^.temp_offset:=href.offset;
|
|
|
-{$else TEMPS_NOT_PUSH}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
|
|
|
-{$endif TEMPS_NOT_PUSH}
|
|
|
- ungetregister32(R_EDI);
|
|
|
- pushed:=true;
|
|
|
- end
|
|
|
- else pushed:=false;
|
|
|
- end
|
|
|
- else pushed:=false;
|
|
|
- maybe_push:=pushed;
|
|
|
- end;
|
|
|
-
|
|
|
-{$else CG11}
|
|
|
-
|
|
|
+{$ifndef CG11}
|
|
|
function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
|
|
|
var
|
|
|
pushed : boolean;
|
|
@@ -1210,7 +1128,6 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
else pushed:=false;
|
|
|
maybe_push:=pushed;
|
|
|
end;
|
|
|
-{$endif CG11}
|
|
|
|
|
|
{$ifdef TEMPS_NOT_PUSH}
|
|
|
function maybe_savetotemp(needed : byte;p : ptree;isint64 : boolean) : boolean;
|
|
@@ -1263,6 +1180,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
maybe_push:=pushed;
|
|
|
end;
|
|
|
{$endif TEMPS_NOT_PUSH}
|
|
|
+{$endif CG11}
|
|
|
|
|
|
|
|
|
procedure push_int(l : longint);
|
|
@@ -1338,7 +1256,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-
|
|
|
+{$ifndef CG11}
|
|
|
procedure pushsetelement(p : ptree);
|
|
|
{
|
|
|
copies p a set element on the stack
|
|
@@ -1395,8 +1313,9 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
end;
|
|
|
end;
|
|
|
end;
|
|
|
+{$endif CG11}
|
|
|
|
|
|
-
|
|
|
+{$ifndef CG11}
|
|
|
procedure restore(p : ptree;isint64 : boolean);
|
|
|
var
|
|
|
hregister : tregister;
|
|
@@ -1443,6 +1362,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
ungetiftemp(href);
|
|
|
{$endif TEMPS_NOT_PUSH}
|
|
|
end;
|
|
|
+{$endif CG11}
|
|
|
|
|
|
{$ifdef TEMPS_NOT_PUSH}
|
|
|
procedure restorefromtemp(p : ptree;isint64 : boolean);
|
|
@@ -1480,6 +1400,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
end;
|
|
|
{$endif TEMPS_NOT_PUSH}
|
|
|
|
|
|
+{$ifndef CG11}
|
|
|
procedure push_value_para(p:ptree;inlined,is_cdecl:boolean;
|
|
|
para_offset:longint;alignment : longint);
|
|
|
var
|
|
@@ -1990,7 +1911,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
{$endif SUPPORT_MMX}
|
|
|
end;
|
|
|
end;
|
|
|
-
|
|
|
+{$endif CG11}
|
|
|
|
|
|
|
|
|
{*****************************************************************************
|
|
@@ -2075,70 +1996,353 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
Emit Functions
|
|
|
*****************************************************************************}
|
|
|
|
|
|
- procedure maketojumpbool(p : ptree);
|
|
|
- {
|
|
|
- produces jumps to true respectively false labels using boolean expressions
|
|
|
- }
|
|
|
+ procedure concatcopy(source,dest : treference;size : longint;delsource,loadref : boolean);
|
|
|
+
|
|
|
+ const
|
|
|
+ isizes : array[0..3] of topsize=(S_L,S_B,S_W,S_B);
|
|
|
+ ishr : array[0..3] of byte=(2,0,1,0);
|
|
|
+
|
|
|
var
|
|
|
- opsize : topsize;
|
|
|
- storepos : tfileposinfo;
|
|
|
+ ecxpushed : boolean;
|
|
|
+ helpsize : longint;
|
|
|
+ i : byte;
|
|
|
+ reg8,reg32 : tregister;
|
|
|
+ swap : boolean;
|
|
|
+
|
|
|
+ procedure maybepushecx;
|
|
|
+ begin
|
|
|
+ if not(R_ECX in unused) then
|
|
|
+ begin
|
|
|
+ exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
|
|
|
+ ecxpushed:=true;
|
|
|
+ end
|
|
|
+ else getexplicitregister32(R_ECX);
|
|
|
+ end;
|
|
|
+
|
|
|
begin
|
|
|
- if p^.error then
|
|
|
- exit;
|
|
|
- storepos:=aktfilepos;
|
|
|
- aktfilepos:=p^.fileinfo;
|
|
|
- if is_boolean(p^.resulttype) then
|
|
|
+{$IfNDef regallocfix}
|
|
|
+ If delsource then
|
|
|
+ del_reference(source);
|
|
|
+{$EndIf regallocfix}
|
|
|
+ if (not loadref) and
|
|
|
+ ((size<=8) or
|
|
|
+ (not(cs_littlesize in aktglobalswitches ) and (size<=12))) then
|
|
|
begin
|
|
|
- if is_constboolnode(p) then
|
|
|
+ helpsize:=size shr 2;
|
|
|
+ getexplicitregister32(R_EDI);
|
|
|
+ for i:=1 to helpsize do
|
|
|
begin
|
|
|
- if p^.value<>0 then
|
|
|
- emitjmp(C_None,truelabel)
|
|
|
- else
|
|
|
- emitjmp(C_None,falselabel);
|
|
|
- end
|
|
|
- else
|
|
|
+ emit_ref_reg(A_MOV,S_L,newreference(source),R_EDI);
|
|
|
+{$ifdef regallocfix}
|
|
|
+ If (size = 4) and delsource then
|
|
|
+ del_reference(source);
|
|
|
+{$endif regallocfix}
|
|
|
+ exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,newreference(dest))));
|
|
|
+ inc(source.offset,4);
|
|
|
+ inc(dest.offset,4);
|
|
|
+ dec(size,4);
|
|
|
+ end;
|
|
|
+ if size>1 then
|
|
|
begin
|
|
|
- opsize:=def_opsize(p^.resulttype);
|
|
|
- case p^.location.loc of
|
|
|
- LOC_CREGISTER,LOC_REGISTER : begin
|
|
|
- emit_reg_reg(A_OR,opsize,p^.location.register,
|
|
|
- p^.location.register);
|
|
|
- ungetregister(p^.location.register);
|
|
|
- emitjmp(C_NZ,truelabel);
|
|
|
- emitjmp(C_None,falselabel);
|
|
|
- end;
|
|
|
- LOC_MEM,LOC_REFERENCE : begin
|
|
|
- emit_const_ref(
|
|
|
- A_CMP,opsize,0,newreference(p^.location.reference));
|
|
|
- del_reference(p^.location.reference);
|
|
|
- emitjmp(C_NZ,truelabel);
|
|
|
- emitjmp(C_None,falselabel);
|
|
|
- end;
|
|
|
- LOC_FLAGS : begin
|
|
|
- emitjmp(flag_2_cond[p^.location.resflags],truelabel);
|
|
|
- emitjmp(C_None,falselabel);
|
|
|
- end;
|
|
|
- end;
|
|
|
+ emit_ref_reg(A_MOV,S_W,newreference(source),R_DI);
|
|
|
+{$ifdef regallocfix}
|
|
|
+ If (size = 2) and delsource then
|
|
|
+ del_reference(source);
|
|
|
+{$endif regallocfix}
|
|
|
+ exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_W,R_DI,newreference(dest))));
|
|
|
+ inc(source.offset,2);
|
|
|
+ inc(dest.offset,2);
|
|
|
+ dec(size,2);
|
|
|
+ end;
|
|
|
+ ungetregister32(R_EDI);
|
|
|
+ if size>0 then
|
|
|
+ begin
|
|
|
+ { and now look for an 8 bit register }
|
|
|
+ swap:=false;
|
|
|
+ if R_EAX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EAX))
|
|
|
+ else if R_EDX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EDX))
|
|
|
+ else if R_EBX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EBX))
|
|
|
+ else if R_ECX in unused then reg8:=reg32toreg8(getexplicitregister32(R_ECX))
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ swap:=true;
|
|
|
+ { we need only to check 3 registers, because }
|
|
|
+ { one is always not index or base }
|
|
|
+ if (dest.base<>R_EAX) and (dest.index<>R_EAX) then
|
|
|
+ begin
|
|
|
+ reg8:=R_AL;
|
|
|
+ reg32:=R_EAX;
|
|
|
+ end
|
|
|
+ else if (dest.base<>R_EBX) and (dest.index<>R_EBX) then
|
|
|
+ begin
|
|
|
+ reg8:=R_BL;
|
|
|
+ reg32:=R_EBX;
|
|
|
+ end
|
|
|
+ else if (dest.base<>R_ECX) and (dest.index<>R_ECX) then
|
|
|
+ begin
|
|
|
+ reg8:=R_CL;
|
|
|
+ reg32:=R_ECX;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if swap then
|
|
|
+ { was earlier XCHG, of course nonsense }
|
|
|
+ begin
|
|
|
+ getexplicitregister32(R_EDI);
|
|
|
+ emit_reg_reg(A_MOV,S_L,reg32,R_EDI);
|
|
|
+ end;
|
|
|
+ emit_ref_reg(A_MOV,S_B,newreference(source),reg8);
|
|
|
+{$ifdef regallocfix}
|
|
|
+ If delsource then
|
|
|
+ del_reference(source);
|
|
|
+{$endif regallocfix}
|
|
|
+ exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_B,reg8,newreference(dest))));
|
|
|
+ if swap then
|
|
|
+ begin
|
|
|
+ emit_reg_reg(A_MOV,S_L,R_EDI,reg32);
|
|
|
+ ungetregister32(R_EDI);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ ungetregister(reg8);
|
|
|
end;
|
|
|
end
|
|
|
else
|
|
|
- CGMessage(type_e_mismatch);
|
|
|
- aktfilepos:=storepos;
|
|
|
- end;
|
|
|
-
|
|
|
+ begin
|
|
|
+ getexplicitregister32(R_EDI);
|
|
|
+ emit_ref_reg(A_LEA,S_L,newreference(dest),R_EDI);
|
|
|
+{$ifdef regallocfix}
|
|
|
+ {is this ok?? (JM)}
|
|
|
+ del_reference(dest);
|
|
|
+{$endif regallocfix}
|
|
|
+ exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
|
|
|
+ if loadref then
|
|
|
+ emit_ref_reg(A_MOV,S_L,newreference(source),R_ESI)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ emit_ref_reg(A_LEA,S_L,newreference(source),R_ESI);
|
|
|
+{$ifdef regallocfix}
|
|
|
+ if delsource then
|
|
|
+ del_reference(source);
|
|
|
+{$endif regallocfix}
|
|
|
+ end;
|
|
|
|
|
|
- { produces if necessary overflowcode }
|
|
|
- procedure emitoverflowcheck(p:ptree);
|
|
|
- var
|
|
|
- hl : pasmlabel;
|
|
|
- begin
|
|
|
- if not(cs_check_overflow in aktlocalswitches) then
|
|
|
- exit;
|
|
|
- getlabel(hl);
|
|
|
- if not ((p^.resulttype^.deftype=pointerdef) or
|
|
|
- ((p^.resulttype^.deftype=orddef) and
|
|
|
- (porddef(p^.resulttype)^.typ in [u64bit,u16bit,u32bit,u8bit,uchar,
|
|
|
- bool8bit,bool16bit,bool32bit]))) then
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_CLD,S_NO)));
|
|
|
+ ecxpushed:=false;
|
|
|
+ if cs_littlesize in aktglobalswitches then
|
|
|
+ begin
|
|
|
+ maybepushecx;
|
|
|
+ emit_const_reg(A_MOV,S_L,size,R_ECX);
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ helpsize:=size shr 2;
|
|
|
+ size:=size and 3;
|
|
|
+ if helpsize>1 then
|
|
|
+ begin
|
|
|
+ maybepushecx;
|
|
|
+ emit_const_reg(A_MOV,S_L,helpsize,R_ECX);
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
|
|
|
+ end;
|
|
|
+ if helpsize>0 then
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_MOVSD,S_NO)));
|
|
|
+ if size>1 then
|
|
|
+ begin
|
|
|
+ dec(size,2);
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_MOVSW,S_NO)));
|
|
|
+ end;
|
|
|
+ if size=1 then
|
|
|
+ exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
|
|
|
+ end;
|
|
|
+ ungetregister32(R_EDI);
|
|
|
+ exprasmlist^.concat(new(pairegalloc,dealloc(R_ESI)));
|
|
|
+ if ecxpushed then
|
|
|
+ exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
|
|
|
+ else
|
|
|
+ ungetregister32(R_ECX);
|
|
|
+
|
|
|
+ { loading SELF-reference again }
|
|
|
+ maybe_loadesi;
|
|
|
+ end;
|
|
|
+ if delsource then
|
|
|
+ ungetiftemp(source);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;
|
|
|
+ destreg:Tregister;delloc:boolean);
|
|
|
+
|
|
|
+ {A lot smaller and less bug sensitive than the original unfolded loads.}
|
|
|
+
|
|
|
+ var tai:Paicpu;
|
|
|
+ r:Preference;
|
|
|
+
|
|
|
+ begin
|
|
|
+ tai := nil;
|
|
|
+ case location.loc of
|
|
|
+ LOC_REGISTER,LOC_CREGISTER:
|
|
|
+ begin
|
|
|
+ case orddef^.typ of
|
|
|
+ u8bit:
|
|
|
+ tai:=new(paicpu,op_reg_reg(A_MOVZX,S_BL,location.register,destreg));
|
|
|
+ s8bit:
|
|
|
+ tai:=new(paicpu,op_reg_reg(A_MOVSX,S_BL,location.register,destreg));
|
|
|
+ u16bit:
|
|
|
+ tai:=new(paicpu,op_reg_reg(A_MOVZX,S_WL,location.register,destreg));
|
|
|
+ s16bit:
|
|
|
+ tai:=new(paicpu,op_reg_reg(A_MOVSX,S_WL,location.register,destreg));
|
|
|
+ u32bit,s32bit:
|
|
|
+ if location.register <> destreg then
|
|
|
+ tai:=new(paicpu,op_reg_reg(A_MOV,S_L,location.register,destreg));
|
|
|
+ end;
|
|
|
+ if delloc then
|
|
|
+ ungetregister(location.register);
|
|
|
+ end;
|
|
|
+ LOC_MEM,
|
|
|
+ LOC_REFERENCE:
|
|
|
+ begin
|
|
|
+ if location.reference.is_immediate then
|
|
|
+ tai:=new(paicpu,op_const_reg(A_MOV,S_L,location.reference.offset,destreg))
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ r:=newreference(location.reference);
|
|
|
+ case orddef^.typ of
|
|
|
+ u8bit:
|
|
|
+ tai:=new(paicpu,op_ref_reg(A_MOVZX,S_BL,r,destreg));
|
|
|
+ s8bit:
|
|
|
+ tai:=new(paicpu,op_ref_reg(A_MOVSX,S_BL,r,destreg));
|
|
|
+ u16bit:
|
|
|
+ tai:=new(paicpu,op_ref_reg(A_MOVZX,S_WL,r,destreg));
|
|
|
+ s16bit:
|
|
|
+ tai:=new(paicpu,op_ref_reg(A_MOVSX,S_WL,r,destreg));
|
|
|
+ u32bit:
|
|
|
+ tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
|
|
|
+ s32bit:
|
|
|
+ tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if delloc then
|
|
|
+ del_reference(location.reference);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ internalerror(6);
|
|
|
+ end;
|
|
|
+ if assigned(tai) then
|
|
|
+ exprasmlist^.concat(tai);
|
|
|
+ end;
|
|
|
+
|
|
|
+ { if necessary ESI is reloaded after a call}
|
|
|
+ procedure maybe_loadesi;
|
|
|
+
|
|
|
+ var
|
|
|
+ hp : preference;
|
|
|
+ p : pprocinfo;
|
|
|
+ i : longint;
|
|
|
+
|
|
|
+ begin
|
|
|
+ if assigned(procinfo^._class) then
|
|
|
+ begin
|
|
|
+ exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
|
|
|
+ if lexlevel>normal_function_level then
|
|
|
+ begin
|
|
|
+ new(hp);
|
|
|
+ reset_reference(hp^);
|
|
|
+ hp^.offset:=procinfo^.framepointer_offset;
|
|
|
+ hp^.base:=procinfo^.framepointer;
|
|
|
+ emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
+ p:=procinfo^.parent;
|
|
|
+ for i:=3 to lexlevel-1 do
|
|
|
+ begin
|
|
|
+ new(hp);
|
|
|
+ reset_reference(hp^);
|
|
|
+ hp^.offset:=p^.framepointer_offset;
|
|
|
+ hp^.base:=R_ESI;
|
|
|
+ emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
+ p:=p^.parent;
|
|
|
+ end;
|
|
|
+ new(hp);
|
|
|
+ reset_reference(hp^);
|
|
|
+ hp^.offset:=p^.selfpointer_offset;
|
|
|
+ hp^.base:=R_ESI;
|
|
|
+ emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ new(hp);
|
|
|
+ reset_reference(hp^);
|
|
|
+ hp^.offset:=procinfo^.selfpointer_offset;
|
|
|
+ hp^.base:=procinfo^.framepointer;
|
|
|
+ emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+{$ifndef CG11}
|
|
|
+ procedure maketojumpbool(p : ptree);
|
|
|
+ {
|
|
|
+ produces jumps to true respectively false labels using boolean expressions
|
|
|
+ }
|
|
|
+ var
|
|
|
+ opsize : topsize;
|
|
|
+ storepos : tfileposinfo;
|
|
|
+ begin
|
|
|
+ if p^.error then
|
|
|
+ exit;
|
|
|
+ storepos:=aktfilepos;
|
|
|
+ aktfilepos:=p^.fileinfo;
|
|
|
+ if is_boolean(p^.resulttype) then
|
|
|
+ begin
|
|
|
+ if is_constboolnode(p) then
|
|
|
+ begin
|
|
|
+ if p^.value<>0 then
|
|
|
+ emitjmp(C_None,truelabel)
|
|
|
+ else
|
|
|
+ emitjmp(C_None,falselabel);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ opsize:=def_opsize(p^.resulttype);
|
|
|
+ case p^.location.loc of
|
|
|
+ LOC_CREGISTER,LOC_REGISTER : begin
|
|
|
+ emit_reg_reg(A_OR,opsize,p^.location.register,
|
|
|
+ p^.location.register);
|
|
|
+ ungetregister(p^.location.register);
|
|
|
+ emitjmp(C_NZ,truelabel);
|
|
|
+ emitjmp(C_None,falselabel);
|
|
|
+ end;
|
|
|
+ LOC_MEM,LOC_REFERENCE : begin
|
|
|
+ emit_const_ref(
|
|
|
+ A_CMP,opsize,0,newreference(p^.location.reference));
|
|
|
+ del_reference(p^.location.reference);
|
|
|
+ emitjmp(C_NZ,truelabel);
|
|
|
+ emitjmp(C_None,falselabel);
|
|
|
+ end;
|
|
|
+ LOC_FLAGS : begin
|
|
|
+ emitjmp(flag_2_cond[p^.location.resflags],truelabel);
|
|
|
+ emitjmp(C_None,falselabel);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ CGMessage(type_e_mismatch);
|
|
|
+ aktfilepos:=storepos;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ { produces if necessary overflowcode }
|
|
|
+ procedure emitoverflowcheck(p:ptree);
|
|
|
+ var
|
|
|
+ hl : pasmlabel;
|
|
|
+ begin
|
|
|
+ if not(cs_check_overflow in aktlocalswitches) then
|
|
|
+ exit;
|
|
|
+ getlabel(hl);
|
|
|
+ if not ((p^.resulttype^.deftype=pointerdef) or
|
|
|
+ ((p^.resulttype^.deftype=orddef) and
|
|
|
+ (porddef(p^.resulttype)^.typ in [u64bit,u16bit,u32bit,u8bit,uchar,
|
|
|
+ bool8bit,bool16bit,bool32bit]))) then
|
|
|
emitjmp(C_NO,hl)
|
|
|
else
|
|
|
emitjmp(C_NB,hl);
|
|
@@ -2331,288 +2535,6 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
end;
|
|
|
|
|
|
|
|
|
- procedure concatcopy(source,dest : treference;size : longint;delsource,loadref : boolean);
|
|
|
-
|
|
|
- const
|
|
|
- isizes : array[0..3] of topsize=(S_L,S_B,S_W,S_B);
|
|
|
- ishr : array[0..3] of byte=(2,0,1,0);
|
|
|
-
|
|
|
- var
|
|
|
- ecxpushed : boolean;
|
|
|
- helpsize : longint;
|
|
|
- i : byte;
|
|
|
- reg8,reg32 : tregister;
|
|
|
- swap : boolean;
|
|
|
-
|
|
|
- procedure maybepushecx;
|
|
|
- begin
|
|
|
- if not(R_ECX in unused) then
|
|
|
- begin
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
|
|
|
- ecxpushed:=true;
|
|
|
- end
|
|
|
- else getexplicitregister32(R_ECX);
|
|
|
- end;
|
|
|
-
|
|
|
- begin
|
|
|
-{$IfNDef regallocfix}
|
|
|
- If delsource then
|
|
|
- del_reference(source);
|
|
|
-{$EndIf regallocfix}
|
|
|
- if (not loadref) and
|
|
|
- ((size<=8) or
|
|
|
- (not(cs_littlesize in aktglobalswitches ) and (size<=12))) then
|
|
|
- begin
|
|
|
- helpsize:=size shr 2;
|
|
|
- getexplicitregister32(R_EDI);
|
|
|
- for i:=1 to helpsize do
|
|
|
- begin
|
|
|
- emit_ref_reg(A_MOV,S_L,newreference(source),R_EDI);
|
|
|
-{$ifdef regallocfix}
|
|
|
- If (size = 4) and delsource then
|
|
|
- del_reference(source);
|
|
|
-{$endif regallocfix}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,newreference(dest))));
|
|
|
- inc(source.offset,4);
|
|
|
- inc(dest.offset,4);
|
|
|
- dec(size,4);
|
|
|
- end;
|
|
|
- if size>1 then
|
|
|
- begin
|
|
|
- emit_ref_reg(A_MOV,S_W,newreference(source),R_DI);
|
|
|
-{$ifdef regallocfix}
|
|
|
- If (size = 2) and delsource then
|
|
|
- del_reference(source);
|
|
|
-{$endif regallocfix}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_W,R_DI,newreference(dest))));
|
|
|
- inc(source.offset,2);
|
|
|
- inc(dest.offset,2);
|
|
|
- dec(size,2);
|
|
|
- end;
|
|
|
- ungetregister32(R_EDI);
|
|
|
- if size>0 then
|
|
|
- begin
|
|
|
- { and now look for an 8 bit register }
|
|
|
- swap:=false;
|
|
|
- if R_EAX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EAX))
|
|
|
- else if R_EDX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EDX))
|
|
|
- else if R_EBX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EBX))
|
|
|
- else if R_ECX in unused then reg8:=reg32toreg8(getexplicitregister32(R_ECX))
|
|
|
- else
|
|
|
- begin
|
|
|
- swap:=true;
|
|
|
- { we need only to check 3 registers, because }
|
|
|
- { one is always not index or base }
|
|
|
- if (dest.base<>R_EAX) and (dest.index<>R_EAX) then
|
|
|
- begin
|
|
|
- reg8:=R_AL;
|
|
|
- reg32:=R_EAX;
|
|
|
- end
|
|
|
- else if (dest.base<>R_EBX) and (dest.index<>R_EBX) then
|
|
|
- begin
|
|
|
- reg8:=R_BL;
|
|
|
- reg32:=R_EBX;
|
|
|
- end
|
|
|
- else if (dest.base<>R_ECX) and (dest.index<>R_ECX) then
|
|
|
- begin
|
|
|
- reg8:=R_CL;
|
|
|
- reg32:=R_ECX;
|
|
|
- end;
|
|
|
- end;
|
|
|
- if swap then
|
|
|
- { was earlier XCHG, of course nonsense }
|
|
|
- begin
|
|
|
- getexplicitregister32(R_EDI);
|
|
|
- emit_reg_reg(A_MOV,S_L,reg32,R_EDI);
|
|
|
- end;
|
|
|
- emit_ref_reg(A_MOV,S_B,newreference(source),reg8);
|
|
|
-{$ifdef regallocfix}
|
|
|
- If delsource then
|
|
|
- del_reference(source);
|
|
|
-{$endif regallocfix}
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_B,reg8,newreference(dest))));
|
|
|
- if swap then
|
|
|
- begin
|
|
|
- emit_reg_reg(A_MOV,S_L,R_EDI,reg32);
|
|
|
- ungetregister32(R_EDI);
|
|
|
- end
|
|
|
- else
|
|
|
- ungetregister(reg8);
|
|
|
- end;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- getexplicitregister32(R_EDI);
|
|
|
- emit_ref_reg(A_LEA,S_L,newreference(dest),R_EDI);
|
|
|
-{$ifdef regallocfix}
|
|
|
- {is this ok?? (JM)}
|
|
|
- del_reference(dest);
|
|
|
-{$endif regallocfix}
|
|
|
- exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
|
|
|
- if loadref then
|
|
|
- emit_ref_reg(A_MOV,S_L,newreference(source),R_ESI)
|
|
|
- else
|
|
|
- begin
|
|
|
- emit_ref_reg(A_LEA,S_L,newreference(source),R_ESI);
|
|
|
-{$ifdef regallocfix}
|
|
|
- if delsource then
|
|
|
- del_reference(source);
|
|
|
-{$endif regallocfix}
|
|
|
- end;
|
|
|
-
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_CLD,S_NO)));
|
|
|
- ecxpushed:=false;
|
|
|
- if cs_littlesize in aktglobalswitches then
|
|
|
- begin
|
|
|
- maybepushecx;
|
|
|
- emit_const_reg(A_MOV,S_L,size,R_ECX);
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- helpsize:=size shr 2;
|
|
|
- size:=size and 3;
|
|
|
- if helpsize>1 then
|
|
|
- begin
|
|
|
- maybepushecx;
|
|
|
- emit_const_reg(A_MOV,S_L,helpsize,R_ECX);
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
|
|
|
- end;
|
|
|
- if helpsize>0 then
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_MOVSD,S_NO)));
|
|
|
- if size>1 then
|
|
|
- begin
|
|
|
- dec(size,2);
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_MOVSW,S_NO)));
|
|
|
- end;
|
|
|
- if size=1 then
|
|
|
- exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
|
|
|
- end;
|
|
|
- ungetregister32(R_EDI);
|
|
|
- exprasmlist^.concat(new(pairegalloc,dealloc(R_ESI)));
|
|
|
- if ecxpushed then
|
|
|
- exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
|
|
|
- else
|
|
|
- ungetregister32(R_ECX);
|
|
|
-
|
|
|
- { loading SELF-reference again }
|
|
|
- maybe_loadesi;
|
|
|
- end;
|
|
|
- if delsource then
|
|
|
- ungetiftemp(source);
|
|
|
- end;
|
|
|
-
|
|
|
-
|
|
|
- procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;
|
|
|
- destreg:Tregister;delloc:boolean);
|
|
|
-
|
|
|
- {A lot smaller and less bug sensitive than the original unfolded loads.}
|
|
|
-
|
|
|
- var tai:Paicpu;
|
|
|
- r:Preference;
|
|
|
-
|
|
|
- begin
|
|
|
- tai := nil;
|
|
|
- case location.loc of
|
|
|
- LOC_REGISTER,LOC_CREGISTER:
|
|
|
- begin
|
|
|
- case orddef^.typ of
|
|
|
- u8bit:
|
|
|
- tai:=new(paicpu,op_reg_reg(A_MOVZX,S_BL,location.register,destreg));
|
|
|
- s8bit:
|
|
|
- tai:=new(paicpu,op_reg_reg(A_MOVSX,S_BL,location.register,destreg));
|
|
|
- u16bit:
|
|
|
- tai:=new(paicpu,op_reg_reg(A_MOVZX,S_WL,location.register,destreg));
|
|
|
- s16bit:
|
|
|
- tai:=new(paicpu,op_reg_reg(A_MOVSX,S_WL,location.register,destreg));
|
|
|
- u32bit,s32bit:
|
|
|
- if location.register <> destreg then
|
|
|
- tai:=new(paicpu,op_reg_reg(A_MOV,S_L,location.register,destreg));
|
|
|
- end;
|
|
|
- if delloc then
|
|
|
- ungetregister(location.register);
|
|
|
- end;
|
|
|
- LOC_MEM,
|
|
|
- LOC_REFERENCE:
|
|
|
- begin
|
|
|
- if location.reference.is_immediate then
|
|
|
- tai:=new(paicpu,op_const_reg(A_MOV,S_L,location.reference.offset,destreg))
|
|
|
- else
|
|
|
- begin
|
|
|
- r:=newreference(location.reference);
|
|
|
- case orddef^.typ of
|
|
|
- u8bit:
|
|
|
- tai:=new(paicpu,op_ref_reg(A_MOVZX,S_BL,r,destreg));
|
|
|
- s8bit:
|
|
|
- tai:=new(paicpu,op_ref_reg(A_MOVSX,S_BL,r,destreg));
|
|
|
- u16bit:
|
|
|
- tai:=new(paicpu,op_ref_reg(A_MOVZX,S_WL,r,destreg));
|
|
|
- s16bit:
|
|
|
- tai:=new(paicpu,op_ref_reg(A_MOVSX,S_WL,r,destreg));
|
|
|
- u32bit:
|
|
|
- tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
|
|
|
- s32bit:
|
|
|
- tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
|
|
|
- end;
|
|
|
- end;
|
|
|
- if delloc then
|
|
|
- del_reference(location.reference);
|
|
|
- end
|
|
|
- else
|
|
|
- internalerror(6);
|
|
|
- end;
|
|
|
- if assigned(tai) then
|
|
|
- exprasmlist^.concat(tai);
|
|
|
- end;
|
|
|
-
|
|
|
- { if necessary ESI is reloaded after a call}
|
|
|
- procedure maybe_loadesi;
|
|
|
-
|
|
|
- var
|
|
|
- hp : preference;
|
|
|
- p : pprocinfo;
|
|
|
- i : longint;
|
|
|
-
|
|
|
- begin
|
|
|
- if assigned(procinfo^._class) then
|
|
|
- begin
|
|
|
- exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
|
|
|
- if lexlevel>normal_function_level then
|
|
|
- begin
|
|
|
- new(hp);
|
|
|
- reset_reference(hp^);
|
|
|
- hp^.offset:=procinfo^.framepointer_offset;
|
|
|
- hp^.base:=procinfo^.framepointer;
|
|
|
- emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
- p:=procinfo^.parent;
|
|
|
- for i:=3 to lexlevel-1 do
|
|
|
- begin
|
|
|
- new(hp);
|
|
|
- reset_reference(hp^);
|
|
|
- hp^.offset:=p^.framepointer_offset;
|
|
|
- hp^.base:=R_ESI;
|
|
|
- emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
- p:=p^.parent;
|
|
|
- end;
|
|
|
- new(hp);
|
|
|
- reset_reference(hp^);
|
|
|
- hp^.offset:=p^.selfpointer_offset;
|
|
|
- hp^.base:=R_ESI;
|
|
|
- emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- new(hp);
|
|
|
- reset_reference(hp^);
|
|
|
- hp^.offset:=procinfo^.selfpointer_offset;
|
|
|
- hp^.base:=procinfo^.framepointer;
|
|
|
- emit_ref_reg(A_MOV,S_L,hp,R_ESI);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
-
|
|
|
{ DO NOT RELY on the fact that the ptree is not yet swaped
|
|
|
because of inlining code PM }
|
|
|
procedure firstcomplex(p : ptree);
|
|
@@ -2644,6 +2566,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
{else
|
|
|
p^.swaped:=false; do not modify }
|
|
|
end;
|
|
|
+{$endif}
|
|
|
|
|
|
|
|
|
{*****************************************************************************
|
|
@@ -3966,7 +3889,10 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
|
|
|
end.
|
|
|
{
|
|
|
$Log$
|
|
|
- Revision 1.16 2000-09-30 16:08:45 peter
|
|
|
+ Revision 1.17 2000-10-01 19:48:23 peter
|
|
|
+ * lot of compile updates for cg11
|
|
|
+
|
|
|
+ Revision 1.16 2000/09/30 16:08:45 peter
|
|
|
* more cg11 updates
|
|
|
|
|
|
Revision 1.15 2000/09/24 15:06:12 peter
|
|
@@ -4032,4 +3958,4 @@ end.
|
|
|
Revision 1.2 2000/07/13 11:32:37 michael
|
|
|
+ removed logs
|
|
|
|
|
|
-}
|
|
|
+}
|