Browse Source

* x86: some fixes to enable 8 and 16 bit operations

git-svn-id: trunk@48166 -
florian 4 years ago
parent
commit
ecc3ce64ea
3 changed files with 18 additions and 3 deletions
  1. 12 1
      compiler/x86/cgx86.pas
  2. 4 1
      compiler/x86/nx86mat.pas
  3. 2 1
      compiler/x86_64/nx64mat.pas

+ 12 - 1
compiler/x86/cgx86.pas

@@ -1995,7 +1995,7 @@ unit cgx86;
             href.scalefactor:=a;
             list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
           end
-        else if (op in [OP_MUL,OP_IMUL]) and (size in [OS_32,OS_S32,OS_64,OS_S64]) and
+        else if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16,OS_32,OS_S32,OS_64,OS_S64]) and
           (a>1) and (a<=maxLongint) and not ispowerof2(int64(a),power) then
           begin
             { MUL with overflow checking should be handled specifically in the code generator }
@@ -2343,6 +2343,17 @@ unit cgx86;
             begin
               if reg2opsize(src) <> dstsize then
                 internalerror(200109226);
+              { x86 does not have an 8 Bit imul, so do 16 Bit multiplication
+                we do not need to zero/sign extend as we discard the upper bits anyways }
+              if (TOpCG2AsmOp[op]=A_IMUL) and (size in [OS_8,OS_S8]) then
+                begin
+                  { this might only happen if no overflow checking is done }
+                  if cs_check_overflow in current_settings.localswitches then
+                    Internalerror(2021011601);
+                  src:=makeregsize(list,src,OS_16);
+                  dst:=makeregsize(list,dst,OS_16);
+                  dstsize:=S_W;
+                end;
               instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
               list.concat(instr);
             end;

+ 4 - 1
compiler/x86/nx86mat.pas

@@ -387,7 +387,10 @@ interface
         cgsize:=def_cgsize(resultdef);
         opsize:=TCGSize2OpSize[cgsize];
         rega:=newreg(R_INTREGISTER,RS_EAX,cgsize2subreg(R_INTREGISTER,cgsize));
-        regd:=newreg(R_INTREGISTER,RS_EDX,cgsize2subreg(R_INTREGISTER,cgsize));
+        if cgsize in [OS_8,OS_S8] then
+          regd:=NR_AH
+        else
+          regd:=newreg(R_INTREGISTER,RS_EDX,cgsize2subreg(R_INTREGISTER,cgsize));
 
         location_reset(location,LOC_REGISTER,cgsize);
         hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);

+ 2 - 1
compiler/x86_64/nx64mat.pas

@@ -43,6 +43,7 @@ implementation
 
     uses
       globtype,constexp,
+      cutils,
       aasmdata,defutil,
       pass_2,
       ncon,
@@ -70,7 +71,7 @@ implementation
           op:=OP_SHR;
 
         opsize:=def_cgsize(resultdef);
-        mask:=resultdef.size*8-1;
+        mask:=max(resultdef.size,4)*8-1;
 
         { load left operators in a register }
         if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or