|
@@ -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}
|
|
|
+ registersmmx:=left.registersmmx;
|
|
|
+{$endif SUPPORT_MMX}
|
|
|
+ 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}
|
|
|
- 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);
|
|
|
+ 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;
|
|
|
- { reset pushedparasize }
|
|
|
- pushedparasize:=oldpushedparasize;
|
|
|
+
|
|
|
+ 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
|