mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 22:32:29 +02:00
+ added generic inline nodes
This commit is contained in:
parent
f6b1f35207
commit
ebbd8e9e04
@ -29,7 +29,7 @@ unit cpunode;
|
||||
implementation
|
||||
|
||||
uses
|
||||
ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
|
||||
ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncginl,
|
||||
n386add,n386cal,n386con,n386cnv,n386flw,n386mat,n386mem,
|
||||
n386set,n386inl,n386opt,
|
||||
{ this not really a node }
|
||||
@ -38,7 +38,10 @@ unit cpunode;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.14 2002-07-06 20:27:26 carl
|
||||
Revision 1.15 2002-07-25 18:01:58 carl
|
||||
+ added generic inline nodes
|
||||
|
||||
Revision 1.14 2002/07/06 20:27:26 carl
|
||||
+ generic set handling
|
||||
|
||||
Revision 1.13 2002/05/18 13:34:22 peter
|
||||
|
@ -27,11 +27,36 @@ unit n386inl;
|
||||
interface
|
||||
|
||||
uses
|
||||
node,ninl;
|
||||
node,ninl,ncginl;
|
||||
|
||||
type
|
||||
ti386inlinenode = class(tinlinenode)
|
||||
procedure pass_2;override;
|
||||
ti386inlinenode = class(tcginlinenode)
|
||||
{ first pass override
|
||||
so that the code generator will actually generate
|
||||
these nodes.
|
||||
}
|
||||
function first_assigned: tnode;override;
|
||||
function first_pi: tnode ; override;
|
||||
function first_arctan_real: tnode; override;
|
||||
function first_abs_real: tnode; override;
|
||||
function first_sqr_real: tnode; override;
|
||||
function first_sqrt_real: tnode; override;
|
||||
function first_ln_real: tnode; override;
|
||||
function first_cos_real: tnode; override;
|
||||
function first_sin_real: tnode; override;
|
||||
{ second pass override to generate these nodes }
|
||||
procedure second_assigned;override;
|
||||
procedure second_IncludeExclude;override;
|
||||
procedure second_pi; override;
|
||||
procedure second_arctan_real; override;
|
||||
procedure second_abs_real; override;
|
||||
procedure second_sqr_real; override;
|
||||
procedure second_sqrt_real; override;
|
||||
procedure second_ln_real; override;
|
||||
procedure second_cos_real; override;
|
||||
procedure second_sin_real; override;
|
||||
private
|
||||
procedure load_fpu_location;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -51,417 +76,288 @@ implementation
|
||||
TI386INLINENODE
|
||||
*****************************************************************************}
|
||||
|
||||
function ti386inlinenode.first_assigned: tnode;
|
||||
begin
|
||||
location.loc:=LOC_FLAGS;
|
||||
first_assigned := nil;
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.pass_2;
|
||||
const
|
||||
{tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
|
||||
{ float_name: array[tfloattype] of string[8]=
|
||||
('S32REAL','S64REAL','S80REAL','S64BIT','F16BIT','F32BIT'); }
|
||||
addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
|
||||
var
|
||||
asmop : tasmop;
|
||||
{inc/dec}
|
||||
addconstant : boolean;
|
||||
addvalue : longint;
|
||||
href : treference;
|
||||
hp2 : tstringconstnode;
|
||||
l : longint;
|
||||
pushedregs : tmaybesave;
|
||||
hregisterhi,
|
||||
hregister : tregister;
|
||||
lengthlab,
|
||||
otlabel,oflabel{,l1} : tasmlabel;
|
||||
oldpushedparasize : longint;
|
||||
cgop : TOpCG;
|
||||
cgsize : TCGSize;
|
||||
function ti386inlinenode.first_pi : tnode;
|
||||
begin
|
||||
{ save & reset pushedparasize }
|
||||
oldpushedparasize:=pushedparasize;
|
||||
pushedparasize:=0;
|
||||
case inlinenumber of
|
||||
in_assert_x_y:
|
||||
begin
|
||||
{ the node should be removed in the firstpass }
|
||||
if not (cs_do_assertion in aktlocalswitches) then
|
||||
internalerror(7123458);
|
||||
otlabel:=truelabel;
|
||||
oflabel:=falselabel;
|
||||
getlabel(truelabel);
|
||||
getlabel(falselabel);
|
||||
secondpass(tcallparanode(left).left);
|
||||
maketojumpbool(exprasmlist,tcallparanode(left).left,lr_load_regvars);
|
||||
cg.a_label(exprasmlist,falselabel);
|
||||
{ erroraddr }
|
||||
cg.a_param_reg(exprasmlist,OS_ADDR,R_EBP,paramanager.getintparaloc(4));
|
||||
{ lineno }
|
||||
cg.a_param_const(exprasmlist,OS_INT,aktfilepos.line,paramanager.getintparaloc(3));
|
||||
{ filename string }
|
||||
hp2:=cstringconstnode.createstr(current_module.sourcefiles.get_file_name(aktfilepos.fileindex),st_shortstring);
|
||||
firstpass(hp2);
|
||||
secondpass(hp2);
|
||||
if codegenerror then
|
||||
exit;
|
||||
cg.a_paramaddr_ref(exprasmlist,hp2.location.reference,paramanager.getintparaloc(2));
|
||||
hp2.free;
|
||||
{ push msg }
|
||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||
cg.a_paramaddr_ref(exprasmlist,tcallparanode(tcallparanode(left).right).left.location.reference,paramanager.getintparaloc(1));
|
||||
{ call }
|
||||
cg.a_call_name(exprasmlist,'FPC_ASSERT');
|
||||
cg.a_label(exprasmlist,truelabel);
|
||||
truelabel:=otlabel;
|
||||
falselabel:=oflabel;
|
||||
end;
|
||||
in_sizeof_x,
|
||||
in_typeof_x :
|
||||
begin
|
||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
||||
{ for both cases load vmt }
|
||||
if left.nodetype=typen then
|
||||
begin
|
||||
hregister:=rg.getaddressregister(exprasmlist);
|
||||
reference_reset_symbol(href,newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),0);
|
||||
cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
|
||||
end
|
||||
else
|
||||
begin
|
||||
secondpass(left);
|
||||
location_release(exprasmlist,left.location);
|
||||
hregister:=rg.getaddressregister(exprasmlist);
|
||||
{ load VMT pointer }
|
||||
inc(left.location.reference.offset,tobjectdef(left.resulttype.def).vmt_offset);
|
||||
cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister);
|
||||
end;
|
||||
{ in sizeof load size }
|
||||
if inlinenumber=in_sizeof_x then
|
||||
begin
|
||||
reference_reset_base(href,hregister,0);
|
||||
rg.ungetaddressregister(exprasmlist,hregister);
|
||||
hregister:=rg.getregisterint(exprasmlist);
|
||||
cg.a_load_ref_reg(exprasmlist,OS_INT,href,hregister);
|
||||
end;
|
||||
location.register:=hregister;
|
||||
end;
|
||||
in_length_x :
|
||||
begin
|
||||
secondpass(left);
|
||||
{ length in ansi strings is at offset -8 }
|
||||
if is_ansistring(left.resulttype.def) or
|
||||
is_widestring(left.resulttype.def) then
|
||||
begin
|
||||
location_force_reg(exprasmlist,left.location,OS_ADDR,false);
|
||||
hregister:=left.location.register;
|
||||
getlabel(lengthlab);
|
||||
cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,hregister,lengthlab);
|
||||
reference_reset_base(href,hregister,-8);
|
||||
cg.a_load_ref_reg(exprasmlist,OS_INT,href,hregister);
|
||||
cg.a_label(exprasmlist,lengthlab);
|
||||
location_reset(location,LOC_REGISTER,OS_INT);
|
||||
location.register:=hregister;
|
||||
end
|
||||
else
|
||||
begin
|
||||
location_copy(location,left.location);
|
||||
location.size:=OS_8;
|
||||
end;
|
||||
end;
|
||||
in_pred_x,
|
||||
in_succ_x:
|
||||
begin
|
||||
secondpass(left);
|
||||
if inlinenumber=in_pred_x then
|
||||
cgop:=OP_SUB
|
||||
else
|
||||
cgop:=OP_ADD;
|
||||
cgsize:=def_cgsize(resulttype.def);
|
||||
|
||||
{ we need a value in a register }
|
||||
location_copy(location,left.location);
|
||||
location_force_reg(exprasmlist,location,cgsize,false);
|
||||
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
cg64.a_op64_const_reg(exprasmlist,cgop,1,
|
||||
location.register64)
|
||||
else
|
||||
cg.a_op_const_reg(exprasmlist,cgop,1,location.register);
|
||||
|
||||
cg.g_overflowcheck(exprasmlist,self);
|
||||
cg.g_rangecheck(exprasmlist,self,resulttype.def);
|
||||
end;
|
||||
in_dec_x,
|
||||
in_inc_x :
|
||||
begin
|
||||
{ set defaults }
|
||||
addconstant:=true;
|
||||
{ load first parameter, must be a reference }
|
||||
secondpass(tcallparanode(left).left);
|
||||
cgsize:=def_cgsize(tcallparanode(left).left.resulttype.def);
|
||||
{ get addvalue }
|
||||
case tcallparanode(left).left.resulttype.def.deftype of
|
||||
orddef,
|
||||
enumdef :
|
||||
addvalue:=1;
|
||||
pointerdef :
|
||||
begin
|
||||
if is_void(tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def) then
|
||||
addvalue:=1
|
||||
else
|
||||
addvalue:=tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def.size;
|
||||
end;
|
||||
else
|
||||
internalerror(10081);
|
||||
end;
|
||||
{ second argument specified?, must be a s32bit in register }
|
||||
if assigned(tcallparanode(left).right) then
|
||||
begin
|
||||
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
||||
tcallparanode(left).left.location,pushedregs);
|
||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
||||
{ when constant, just multiply the addvalue }
|
||||
if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
|
||||
addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
|
||||
else
|
||||
begin
|
||||
location_force_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,cgsize,false);
|
||||
hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
|
||||
hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.registerhigh;
|
||||
{ insert multiply with addvalue if its >1 }
|
||||
if addvalue>1 then
|
||||
cg.a_op_const_reg(exprasmlist,OP_IMUL,addvalue,hregister);
|
||||
addconstant:=false;
|
||||
end;
|
||||
end;
|
||||
{ write the add instruction }
|
||||
if addconstant then
|
||||
begin
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
cg64.a_op64_const_loc(exprasmlist,addsubop[inlinenumber],
|
||||
addvalue,tcallparanode(left).left.location)
|
||||
else
|
||||
cg.a_op_const_loc(exprasmlist,addsubop[inlinenumber],
|
||||
addvalue,tcallparanode(left).left.location);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
cg64.a_op64_reg_loc(exprasmlist,addsubop[inlinenumber],
|
||||
joinreg64(hregister,hregisterhi),tcallparanode(left).left.location)
|
||||
else
|
||||
cg.a_op_reg_loc(exprasmlist,addsubop[inlinenumber],
|
||||
hregister,tcallparanode(left).left.location);
|
||||
location_release(exprasmlist,tcallparanode(tcallparanode(left).right).left.location);
|
||||
end;
|
||||
cg.g_overflowcheck(exprasmlist,tcallparanode(left).left);
|
||||
cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
|
||||
end;
|
||||
|
||||
in_typeinfo_x:
|
||||
begin
|
||||
location_reset(location,LOC_REGISTER,OS_ADDR);
|
||||
location.register:=rg.getregisterint(exprasmlist);
|
||||
reference_reset_symbol(href,tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(fullrtti),0);
|
||||
emit_ref_reg(A_LEA,S_L,href,location.register);
|
||||
end;
|
||||
|
||||
in_assigned_x :
|
||||
begin
|
||||
secondpass(tcallparanode(left).left);
|
||||
location_release(exprasmlist,tcallparanode(left).left.location);
|
||||
if (tcallparanode(left).left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
||||
begin
|
||||
emit_reg_reg(A_OR,S_L,
|
||||
tcallparanode(left).left.location.register,
|
||||
tcallparanode(left).left.location.register);
|
||||
end
|
||||
else
|
||||
begin
|
||||
emit_const_ref(A_CMP,S_L,0,tcallparanode(left).left.location.reference);
|
||||
end;
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags:=F_NE;
|
||||
end;
|
||||
in_include_x_y,
|
||||
in_exclude_x_y:
|
||||
begin
|
||||
location_copy(location,left.location);
|
||||
secondpass(tcallparanode(left).left);
|
||||
if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
|
||||
begin
|
||||
{ calculate bit position }
|
||||
l:=1 shl (tordconstnode(tcallparanode(tcallparanode(left).right).left).value mod 32);
|
||||
|
||||
{ determine operator }
|
||||
if inlinenumber=in_include_x_y then
|
||||
asmop:=A_OR
|
||||
else
|
||||
begin
|
||||
asmop:=A_AND;
|
||||
l:=not(l);
|
||||
end;
|
||||
if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
|
||||
begin
|
||||
inc(tcallparanode(left).left.location.reference.offset,
|
||||
(tordconstnode(tcallparanode(tcallparanode(left).right).left).value div 32)*4);
|
||||
emit_const_ref(asmop,S_L,l,tcallparanode(left).left.location.reference);
|
||||
location_release(exprasmlist,tcallparanode(left).left.location);
|
||||
end
|
||||
else
|
||||
{ LOC_CREGISTER }
|
||||
begin
|
||||
secondpass(tcallparanode(left).left);
|
||||
emit_const_reg(asmop,S_L,
|
||||
l,tcallparanode(left).left.location.register);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ generate code for the element to set }
|
||||
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
||||
tcallparanode(left).left.location,pushedregs);
|
||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
||||
{ determine asm operator }
|
||||
if inlinenumber=in_include_x_y then
|
||||
asmop:=A_BTS
|
||||
else
|
||||
asmop:=A_BTR;
|
||||
|
||||
if tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
|
||||
{ we don't need a mod 32 because this is done automatically }
|
||||
{ by the bts instruction. For proper checking we would }
|
||||
|
||||
{ note: bts doesn't do any mod'ing, that's why we can also use }
|
||||
{ it for normalsets! (JM) }
|
||||
|
||||
{ need a cmp and jmp, but this should be done by the }
|
||||
{ type cast code which does range checking if necessary (FK) }
|
||||
begin
|
||||
hregister := rg.makeregsize(tcallparanode(tcallparanode(left).right).left.location.register,OS_INT);
|
||||
end
|
||||
else
|
||||
begin
|
||||
rg.getexplicitregisterint(exprasmlist,R_EDI);
|
||||
hregister:=R_EDI;
|
||||
end;
|
||||
cg.a_load_loc_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,hregister);
|
||||
if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
|
||||
emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
|
||||
else
|
||||
emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
|
||||
if hregister = R_EDI then
|
||||
rg.ungetregisterint(exprasmlist,R_EDI);
|
||||
end;
|
||||
end;
|
||||
in_pi:
|
||||
begin
|
||||
location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
|
||||
emit_none(A_FLDPI,S_NO);
|
||||
inc(trgcpu(rg).fpuvaroffset);
|
||||
location.register:=R_ST;
|
||||
end;
|
||||
in_sin_extended,
|
||||
in_arctan_extended,
|
||||
in_abs_extended,
|
||||
in_sqr_extended,
|
||||
in_sqrt_extended,
|
||||
in_ln_extended,
|
||||
in_cos_extended:
|
||||
begin
|
||||
location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
|
||||
location.register:=R_ST;
|
||||
secondpass(left);
|
||||
case left.location.loc of
|
||||
LOC_FPUREGISTER:
|
||||
;
|
||||
LOC_CFPUREGISTER:
|
||||
begin
|
||||
cg.a_loadfpu_reg_reg(exprasmlist,
|
||||
left.location.register,location.register);
|
||||
end;
|
||||
LOC_REFERENCE,LOC_CREFERENCE:
|
||||
begin
|
||||
cg.a_loadfpu_ref_reg(exprasmlist,
|
||||
def_cgsize(left.resulttype.def),
|
||||
left.location.reference,location.register);
|
||||
location_release(exprasmlist,left.location);
|
||||
end
|
||||
else
|
||||
internalerror(309991);
|
||||
end;
|
||||
case inlinenumber of
|
||||
in_sin_extended,
|
||||
in_cos_extended:
|
||||
begin
|
||||
if inlinenumber=in_sin_extended then
|
||||
emit_none(A_FSIN,S_NO)
|
||||
else
|
||||
emit_none(A_FCOS,S_NO);
|
||||
{
|
||||
getlabel(l1);
|
||||
emit_reg(A_FNSTSW,S_NO,R_AX);
|
||||
emit_none(A_SAHF,S_NO);
|
||||
emitjmp(C_NP,l1);
|
||||
emit_reg(A_FSTP,S_NO,R_ST0);
|
||||
emit_none(A_FLDZ,S_NO);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
}
|
||||
end;
|
||||
in_arctan_extended:
|
||||
begin
|
||||
emit_none(A_FLD1,S_NO);
|
||||
emit_none(A_FPATAN,S_NO);
|
||||
end;
|
||||
in_abs_extended:
|
||||
emit_none(A_FABS,S_NO);
|
||||
in_sqr_extended:
|
||||
begin
|
||||
(* emit_reg(A_FLD,S_NO,R_ST0);
|
||||
{ emit_none(A_FMULP,S_NO); nasm does not accept this PM }
|
||||
emit_reg_reg(A_FMULP,S_NO,R_ST0,R_ST1);
|
||||
can be shorten to *)
|
||||
emit_reg_reg(A_FMUL,S_NO,R_ST0,R_ST0);
|
||||
end;
|
||||
in_sqrt_extended:
|
||||
emit_none(A_FSQRT,S_NO);
|
||||
in_ln_extended:
|
||||
begin
|
||||
emit_none(A_FLDLN2,S_NO);
|
||||
emit_none(A_FXCH,S_NO);
|
||||
emit_none(A_FYL2X,S_NO);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registersfpu:=1;
|
||||
first_pi := nil;
|
||||
end;
|
||||
|
||||
|
||||
function ti386inlinenode.first_arctan_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,2);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
in_mmx_pcmpeqb..in_mmx_pcmpgtw:
|
||||
begin
|
||||
location_reset(location,LOC_MMXREGISTER,OS_NO);
|
||||
if left.location.loc=LOC_REGISTER then
|
||||
begin
|
||||
{!!!!!!!}
|
||||
end
|
||||
else if tcallparanode(left).left.location.loc=LOC_REGISTER then
|
||||
begin
|
||||
{!!!!!!!}
|
||||
end
|
||||
else
|
||||
begin
|
||||
{!!!!!!!}
|
||||
end;
|
||||
end;
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
else internalerror(9);
|
||||
end;
|
||||
{ reset pushedparasize }
|
||||
pushedparasize:=oldpushedparasize;
|
||||
first_arctan_real := nil;
|
||||
end;
|
||||
|
||||
function ti386inlinenode.first_abs_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,1);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
first_abs_real := nil;
|
||||
end;
|
||||
|
||||
function ti386inlinenode.first_sqr_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,1);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
first_sqr_real := nil;
|
||||
end;
|
||||
|
||||
function ti386inlinenode.first_sqrt_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,1);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
first_sqrt_real := nil;
|
||||
end;
|
||||
|
||||
function ti386inlinenode.first_ln_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,2);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
first_ln_real := nil;
|
||||
end;
|
||||
|
||||
function ti386inlinenode.first_cos_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,1);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
first_cos_real := nil;
|
||||
end;
|
||||
|
||||
function ti386inlinenode.first_sin_real : tnode;
|
||||
begin
|
||||
location.loc:=LOC_FPUREGISTER;
|
||||
registers32:=left.registers32;
|
||||
registersfpu:=max(left.registersfpu,1);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=left.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
first_sin_real := nil;
|
||||
end;
|
||||
|
||||
|
||||
procedure ti386inlinenode.second_Pi;
|
||||
begin
|
||||
location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
|
||||
emit_none(A_FLDPI,S_NO);
|
||||
inc(trgcpu(rg).fpuvaroffset);
|
||||
location.register:=FPU_RESULT_REG;
|
||||
|
||||
end;
|
||||
|
||||
{ load the FPU into the an fpu register }
|
||||
procedure ti386inlinenode.load_fpu_location;
|
||||
begin
|
||||
location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
|
||||
location.register:=FPU_RESULT_REG;
|
||||
secondpass(left);
|
||||
case left.location.loc of
|
||||
LOC_FPUREGISTER:
|
||||
;
|
||||
LOC_CFPUREGISTER:
|
||||
begin
|
||||
cg.a_loadfpu_reg_reg(exprasmlist,
|
||||
left.location.register,location.register);
|
||||
end;
|
||||
LOC_REFERENCE,LOC_CREFERENCE:
|
||||
begin
|
||||
cg.a_loadfpu_ref_reg(exprasmlist,
|
||||
def_cgsize(left.resulttype.def),
|
||||
left.location.reference,location.register);
|
||||
location_release(exprasmlist,left.location);
|
||||
end
|
||||
else
|
||||
internalerror(309991);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_arctan_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_none(A_FLD1,S_NO);
|
||||
emit_none(A_FPATAN,S_NO);
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_abs_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_none(A_FABS,S_NO);
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_sqr_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_reg_reg(A_FMUL,S_NO,R_ST0,R_ST0);
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_sqrt_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_none(A_FSQRT,S_NO);
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_ln_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_none(A_FLDLN2,S_NO);
|
||||
emit_none(A_FXCH,S_NO);
|
||||
emit_none(A_FYL2X,S_NO);
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_cos_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_none(A_FCOS,S_NO);
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_sin_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
emit_none(A_FSIN,S_NO)
|
||||
end;
|
||||
|
||||
procedure ti386inlinenode.second_assigned;
|
||||
begin
|
||||
secondpass(tcallparanode(left).left);
|
||||
location_release(exprasmlist,tcallparanode(left).left.location);
|
||||
if (tcallparanode(left).left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
||||
begin
|
||||
emit_reg_reg(A_OR,S_L,
|
||||
tcallparanode(left).left.location.register,
|
||||
tcallparanode(left).left.location.register);
|
||||
end
|
||||
else
|
||||
begin
|
||||
emit_const_ref(A_CMP,S_L,0,tcallparanode(left).left.location.reference);
|
||||
end;
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags:=F_NE;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
INCLUDE/EXCLUDE GENERIC HANDLING
|
||||
*****************************************************************************}
|
||||
|
||||
procedure ti386inlinenode.second_IncludeExclude;
|
||||
var
|
||||
scratch_reg : boolean;
|
||||
hregister : tregister;
|
||||
asmop : tasmop;
|
||||
L : longint;
|
||||
pushedregs : TMaybesave;
|
||||
cgop : topcg;
|
||||
begin
|
||||
location_copy(location,left.location);
|
||||
secondpass(tcallparanode(left).left);
|
||||
if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
|
||||
begin
|
||||
{ calculate bit position }
|
||||
l:=1 shl (tordconstnode(tcallparanode(tcallparanode(left).right).left).value mod 32);
|
||||
|
||||
{ determine operator }
|
||||
if inlinenumber=in_include_x_y then
|
||||
cgop:=OP_OR
|
||||
else
|
||||
begin
|
||||
cgop:=OP_AND;
|
||||
l:=not(l);
|
||||
end;
|
||||
if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
|
||||
begin
|
||||
inc(tcallparanode(left).left.location.reference.offset,
|
||||
(tordconstnode(tcallparanode(tcallparanode(left).right).left).value div 32)*4);
|
||||
cg.a_op_const_ref(exprasmlist,cgop,OS_INT,l,tcallparanode(left).left.location.reference);
|
||||
location_release(exprasmlist,tcallparanode(left).left.location);
|
||||
end
|
||||
else
|
||||
{ LOC_CREGISTER }
|
||||
begin
|
||||
cg.a_op_const_reg(exprasmlist,cgop,l,tcallparanode(left).left.location.register);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ generate code for the element to set }
|
||||
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
||||
tcallparanode(left).left.location,pushedregs);
|
||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
||||
{ determine asm operator }
|
||||
if inlinenumber=in_include_x_y then
|
||||
asmop:=A_BTS
|
||||
else
|
||||
asmop:=A_BTR;
|
||||
|
||||
if tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
|
||||
{ we don't need a mod 32 because this is done automatically }
|
||||
{ by the bts instruction. For proper checking we would }
|
||||
|
||||
{ note: bts doesn't do any mod'ing, that's why we can also use }
|
||||
{ it for normalsets! (JM) }
|
||||
|
||||
{ need a cmp and jmp, but this should be done by the }
|
||||
{ type cast code which does range checking if necessary (FK) }
|
||||
begin
|
||||
scratch_reg := FALSE;
|
||||
hregister := rg.makeregsize(tcallparanode(tcallparanode(left).right).left.location.register,OS_INT);
|
||||
end
|
||||
else
|
||||
begin
|
||||
scratch_reg := TRUE;
|
||||
hregister:=cg.get_scratch_reg_int(exprasmlist);
|
||||
end;
|
||||
cg.a_load_loc_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,hregister);
|
||||
if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
|
||||
emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
|
||||
else
|
||||
emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
|
||||
if scratch_reg then
|
||||
cg.free_scratch_reg(exprasmlist,hregister);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cinlinenode:=ti386inlinenode;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.49 2002-07-20 11:58:02 florian
|
||||
Revision 1.50 2002-07-25 18:02:33 carl
|
||||
+ added generic inline nodes
|
||||
|
||||
Revision 1.49 2002/07/20 11:58:02 florian
|
||||
* types.pas renamed to defbase.pas because D6 contains a types
|
||||
unit so this would conflicts if D6 programms are compiled
|
||||
+ Willamette/SSE2 instructions to assembler added
|
||||
@ -550,9 +446,9 @@ end.
|
||||
|
||||
Revision 1.33 2002/03/31 20:26:39 jonas
|
||||
+ a_loadfpu_* and a_loadmm_* methods in tcg
|
||||
* register allocation is now handled by a class and is mostly processor
|
||||
* register allocation is now second_d by a class and is mostly processor
|
||||
independent (+rgobj.pas and i386/rgcpu.pas)
|
||||
* temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
|
||||
* temp allocation is now second_d by a class (+tgobj.pas, -i386\tgcpu.pas)
|
||||
* some small improvements and fixes to the optimizer
|
||||
* some register allocation fixes
|
||||
* some fpuvaroffset fixes in the unary minus node
|
||||
|
Loading…
Reference in New Issue
Block a user