Browse Source

+ added 8086 workaround for the 'imul reg,const' 186+ instruction. The compiler can now generate strict 8086/8088 code.

git-svn-id: trunk@24404 -
nickysn 12 years ago
parent
commit
4527fe8fa2
1 changed files with 48 additions and 1 deletions
  1. 48 1
      compiler/i8086/cgcpu.pas

+ 48 - 1
compiler/i8086/cgcpu.pas

@@ -160,6 +160,7 @@ unit cgcpu;
       var
       var
         tmpreg: tregister;
         tmpreg: tregister;
         op1, op2: TAsmOp;
         op1, op2: TAsmOp;
+        ax_subreg: tregister;
       begin
       begin
         optimize_op_const(op, a);
         optimize_op_const(op, a);
         check_register_size(size,reg);
         check_register_size(size,reg);
@@ -212,7 +213,53 @@ unit cgcpu;
             end;
             end;
           end
           end
         else
         else
-          inherited a_op_const_reg(list, Op, size, a, reg);
+          begin
+            { size <= 16-bit }
+
+            { 8086 doesn't support 'imul reg,const', so we handle it here }
+            if (current_settings.cputype<cpu_186) and (op in [OP_MUL,OP_IMUL]) then
+              begin
+                { TODO: also enable the SHL optimization below }
+    {            if not(cs_check_overflow in current_settings.localswitches) and
+                   ispowerof2(int64(a),power) then
+                  begin
+                    list.concat(taicpu.op_const_reg(A_SHL,TCgSize2OpSize[size],power,reg));
+                    exit;
+                  end;}
+                if op = OP_IMUL then
+                  begin
+                    if size in [OS_16,OS_S16] then
+                      ax_subreg := NR_AX
+                    else
+                      if size in [OS_8,OS_S8] then
+                        ax_subreg := NR_AL
+                      else
+                        internalerror(2013050102);
+
+                    getcpuregister(list,NR_AX);
+                    if size in [OS_16,OS_S16] then
+                      getcpuregister(list,NR_DX);
+
+                    a_load_const_reg(list,size,a,ax_subreg);
+                    list.concat(taicpu.op_reg(A_IMUL,TCgSize2OpSize[size],reg));
+                    a_load_reg_reg(list,size,size,ax_subreg,reg);
+
+                    ungetcpuregister(list,NR_AX);
+                    if size in [OS_16,OS_S16] then
+                      ungetcpuregister(list,NR_DX);
+
+                    { TODO: implement overflow checking? }
+
+                    exit;
+                  end
+                else
+                  { OP_MUL should be handled specifically in the code        }
+                  { generator because of the silly register usage restraints }
+                  internalerror(200109225);
+              end
+            else
+              inherited a_op_const_reg(list, Op, size, a, reg);
+          end;
       end;
       end;