فهرست منبع

+ implemented OP_MUL/OP_IMUL in tcgz80.a_op_reg_reg_internal

git-svn-id: branches/z80@45105 -
nickysn 5 سال پیش
والد
کامیت
05ca71133f
1فایلهای تغییر یافته به همراه80 افزوده شده و 4 حذف شده
  1. 80 4
      compiler/z80/cgcpu.pas

+ 80 - 4
compiler/z80/cgcpu.pas

@@ -119,6 +119,7 @@ unit cgcpu;
       protected
         procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
         procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
+        procedure gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
         procedure maybegetcpuregister(list : tasmlist; reg : tregister);
       end;
 
@@ -848,10 +849,13 @@ unit cgcpu;
 
            OP_MUL,OP_IMUL:
              begin
-               { special stuff, needs separate handling inside code
-                 generator                                          }
-               list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_op_reg_reg_internal OP_MUL/OP_IMUL')));
-               {internalerror(2017032604);}
+               tmpreg:=dst;
+               if size in [OS_16,OS_S16] then
+                 begin
+                   tmpreg:=getintregister(list,size);
+                   a_load_reg_reg(list,size,size,dst,tmpreg);
+                 end;
+               gen_multiply(list,op,size,src,tmpreg,dst,false);
              end;
 
            OP_DIV,OP_IDIV:
@@ -1260,6 +1264,78 @@ unit cgcpu;
      end;
 
 
+     procedure tcgz80.gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
+       var
+         pd: tprocdef;
+         paraloc1, paraloc2: tcgpara;
+         ai: taicpu;
+         hl, no_overflow: TAsmLabel;
+         name: String;
+       begin
+         if size in [OS_8,OS_S8] then
+           begin
+             if size=OS_8 then
+               name:='fpc_mul_byte'
+             else
+               name:='fpc_mul_shortint';
+
+             if check_overflow then
+               name:=name+'_checkoverflow';
+
+             pd:=search_system_proc(name);
+             paraloc1.init;
+             paraloc2.init;
+             paramanager.getcgtempparaloc(list,pd,1,paraloc1);
+             paramanager.getcgtempparaloc(list,pd,2,paraloc2);
+             a_load_reg_cgpara(list,OS_8,src1,paraloc2);
+             a_load_reg_cgpara(list,OS_8,src2,paraloc1);
+             paramanager.freecgpara(list,paraloc2);
+             paramanager.freecgpara(list,paraloc1);
+             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+             a_call_name(list,upper(name),false);
+             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+             cg.a_reg_alloc(list,NR_L);
+             cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
+             cg.a_reg_dealloc(list,NR_L);
+             paraloc2.done;
+             paraloc1.done;
+           end
+         else if size in [OS_16,OS_S16] then
+           begin
+             if size=OS_16 then
+               name:='fpc_mul_word'
+             else
+               name:='fpc_mul_integer';
+
+             if check_overflow then
+               name:=name+'_checkoverflow';
+
+             pd:=search_system_proc(name);
+             paraloc1.init;
+             paraloc2.init;
+             paramanager.getcgtempparaloc(list,pd,1,paraloc1);
+             paramanager.getcgtempparaloc(list,pd,2,paraloc2);
+             a_load_reg_cgpara(list,OS_16,src1,paraloc2);
+             a_load_reg_cgpara(list,OS_16,src2,paraloc1);
+             paramanager.freecgpara(list,paraloc2);
+             paramanager.freecgpara(list,paraloc1);
+             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+             a_call_name(list,upper(name),false);
+             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+             cg.a_reg_alloc(list,NR_L);
+             cg.a_reg_alloc(list,NR_H);
+             cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
+             cg.a_reg_dealloc(list,NR_L);
+             cg.a_load_reg_reg(list,OS_8,OS_8,NR_H,GetNextReg(dst));
+             cg.a_reg_dealloc(list,NR_H);
+             paraloc2.done;
+             paraloc1.done;
+           end
+         else
+           internalerror(2011022002);
+       end;
+
+
      procedure tcgz80.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
        var
          mask : qword;