Переглянути джерело

* implemented Trunc() and Round() for i8086

git-svn-id: branches/i8086@23852 -
nickysn 12 роки тому
батько
коміт
f4b5b4ce0f
1 змінених файлів з 86 додано та 1 видалено
  1. 86 1
      compiler/i8086/n8086inl.pas

+ 86 - 1
compiler/i8086/n8086inl.pas

@@ -29,13 +29,98 @@ interface
        nx86inl;
 
     type
+
+       { ti8086inlinenode }
+
        ti8086inlinenode = class(tx86inlinenode)
+         procedure second_round_real; override;
+         procedure second_trunc_real; override;
+       private
+         procedure load_fpu_location;
        end;
 
 implementation
 
   uses
-    ninl;
+    ninl,
+    systems,
+    globtype,globals,
+    cutils,verbose,
+    symconst,
+    defutil,
+    aasmbase,aasmtai,aasmdata,aasmcpu,
+    symtype,symdef,
+    cgbase,pass_2,
+    cpuinfo,cpubase,paramgr,
+    nbas,ncon,ncal,ncnv,nld,ncgutil,
+    tgobj,
+    cga,cgutils,cgx86,cgobj,hlcgobj,
+    node;
+
+     procedure ti8086inlinenode.second_round_real;
+       begin
+         load_fpu_location;
+         location_reset_ref(location,LOC_REFERENCE,OS_S64,0);
+         tg.GetTemp(current_asmdata.CurrAsmList,resultdef.size,resultdef.alignment,tt_normal,location.reference);
+         emit_ref(A_FISTP,S_IQ,location.reference);
+         tcgx86(cg).dec_fpu_stack;
+         emit_none(A_FWAIT,S_NO);
+       end;
+
+     procedure ti8086inlinenode.second_trunc_real;
+       var
+         oldcw,newcw : treference;
+       begin
+         tg.GetTemp(current_asmdata.CurrAsmList,2,2,tt_normal,oldcw);
+         tg.GetTemp(current_asmdata.CurrAsmList,2,2,tt_normal,newcw);
+         emit_ref(A_FNSTCW,S_NO,newcw);
+         emit_ref(A_FNSTCW,S_NO,oldcw);
+         emit_const_ref(A_OR,S_W,$0f00,newcw);
+         load_fpu_location;
+         emit_ref(A_FLDCW,S_NO,newcw);
+         location_reset_ref(location,LOC_REFERENCE,OS_S64,0);
+         tg.GetTemp(current_asmdata.CurrAsmList,resultdef.size,resultdef.alignment,tt_normal,location.reference);
+         emit_ref(A_FISTP,S_IQ,location.reference);
+         tcgx86(cg).dec_fpu_stack;
+         emit_ref(A_FLDCW,S_NO,oldcw);
+         emit_none(A_FWAIT,S_NO);
+         tg.UnGetTemp(current_asmdata.CurrAsmList,oldcw);
+         tg.UnGetTemp(current_asmdata.CurrAsmList,newcw);
+       end;
+
+     procedure ti8086inlinenode.load_fpu_location;
+       var
+         lnode: tnode;
+       begin
+         location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+         location.register:=NR_FPU_RESULT_REG;
+         if left.nodetype <> callparan then
+           internalerror(2013031501);
+         lnode := tcallparanode(left).left;
+         secondpass(lnode);
+         case lnode.location.loc of
+           LOC_FPUREGISTER:
+             ;
+           LOC_CFPUREGISTER:
+             begin
+               cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,lnode.location.size,
+                 lnode.location.size,lnode.location.register,location.register);
+             end;
+           LOC_REFERENCE,LOC_CREFERENCE:
+             begin
+               cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+                  lnode.location.size,lnode.location.size,
+                  lnode.location.reference,location.register);
+             end;
+           LOC_MMREGISTER,LOC_CMMREGISTER:
+             begin
+               location:=lnode.location;
+               location_force_fpureg(current_asmdata.CurrAsmList,location,false);
+             end;
+           else
+             internalerror(309991);
+         end;
+       end;
 
 begin
    cinlinenode:=ti8086inlinenode;