浏览代码

* handle LOC_(C)SUBSETREG/REF in second_NegNot_assign

* changed the way OP_NEG and OP_NOT are handled in op_reg_ref, in order to be
  consistent with op_reg_reg
* introduced op_reg,op_ref,op_subsetreg,op_subsetref and op_loc for the unary
  operations only (OP_NEG,OP_NOT)

git-svn-id: trunk@45302 -
(cherry picked from commit 0f6ab0de1707bf3b79303675ece2e4418820ced6)

# Conflicts:
#	compiler/cgobj.pas
nickysn 5 年之前
父节点
当前提交
c9d2028ebd
共有 8 个文件被更改,包括 298 次插入93 次删除
  1. 9 4
      compiler/cg64f32.pas
  2. 95 12
      compiler/cgobj.pas
  3. 30 0
      compiler/hlcg2ll.pas
  4. 66 4
      compiler/hlcgobj.pas
  5. 36 21
      compiler/i386/cgcpu.pas
  6. 44 22
      compiler/i8086/cgcpu.pas
  7. 4 22
      compiler/ncginl.pas
  8. 14 8
      compiler/x86/cgx86.pas

+ 9 - 4
compiler/cg64f32.pas

@@ -738,12 +738,17 @@ unit cg64f32;
       begin
         tempreg.reghi:=cg.getintregister(list,OS_32);
         tempreg.reglo:=cg.getintregister(list,OS_32);
-        a_load64_ref_reg(list,ref,tempreg);
         if op in [OP_NEG,OP_NOT] then
-          a_op64_reg_reg(list,op,size,tempreg,tempreg)
+          begin
+            a_op64_reg_reg(list,op,size,reg,tempreg);
+            a_load64_reg_ref(list,tempreg,ref);
+          end
         else
-          a_op64_reg_reg(list,op,size,reg,tempreg);
-        a_load64_reg_ref(list,tempreg,ref);
+          begin
+            a_load64_ref_reg(list,ref,tempreg);
+            a_op64_reg_reg(list,op,size,reg,tempreg);
+            a_load64_reg_ref(list,tempreg,ref);
+          end;
       end;
 
 

+ 95 - 12
compiler/cgobj.pas

@@ -304,10 +304,6 @@ unit cgobj;
           procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tcgsize; mmreg, intreg: tregister; shuffle : pmmshuffle); virtual;
 
           { basic arithmetic operations }
-          { note: for operators which require only one argument (not, neg), use }
-          { the op_reg_reg, op_reg_ref or op_reg_loc methods and keep in mind   }
-          { that in this case the *second* operand is used as both source and   }
-          { destination (JM)                                                    }
           procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); virtual; abstract;
           procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); virtual;
           procedure a_op_const_loc(list : TAsmList; Op: TOpCG; a: tcgint; const loc: tlocation);
@@ -326,6 +322,11 @@ unit cgobj;
           procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
           procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
 
+          { unary operations (not, neg) }
+          procedure a_op_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg: TRegister); virtual;
+          procedure a_op_ref(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference); virtual;
+          procedure a_op_loc(list : TAsmList; Op: TOpCG; const loc: tlocation);
+
           {  comparison operations }
           procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
             l : tasmlabel); virtual;
@@ -526,6 +527,9 @@ unit cgobj;
         procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);virtual;
         procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);virtual;
         procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);virtual;
+        procedure a_op64_reg(list : TAsmList;op:TOpCG;size : tcgsize;regdst : tregister64);virtual;
+        procedure a_op64_ref(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference);virtual;
+        procedure a_op64_loc(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation);virtual;
 
         procedure a_op64_const_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; a : int64; const sref: tsubsetreference);
         procedure a_op64_reg_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; reg: tregister64; const sref: tsubsetreference);
@@ -580,9 +584,6 @@ unit cgobj;
 implementation
 
     uses
-       globals,systems,
-       verbose,paramgr,symsym,
-       tgobj,cutils,procinfo;
        globals,systems,fmodule,
        verbose,paramgr,symsym,symtable,
        tgobj,cutils,procinfo,
@@ -1995,13 +1996,17 @@ implementation
           tmpref:=ref;
         if op in [OP_NEG,OP_NOT] then
           begin
-            if reg<>NR_NO then
-              internalerror(2017040901);
-            a_op_reg_reg(list,op,size,tmpreg,tmpreg);
+            tmpreg:=getintregister(list,size);
+            a_op_reg_reg(list,op,size,reg,tmpreg);
+            a_load_reg_ref(list,size,size,tmpreg,tmpref);
           end
         else
-          a_op_reg_reg(list,op,size,reg,tmpreg);
-        a_load_reg_ref(list,size,size,tmpreg,ref);
+          begin
+            tmpreg:=getintregister(list,size);
+            a_load_ref_reg(list,size,size,tmpref,tmpreg);
+            a_op_reg_reg(list,op,size,reg,tmpreg);
+            a_load_reg_ref(list,size,size,tmpreg,tmpref);
+          end;
       end;
 
 
@@ -2192,6 +2197,49 @@ implementation
       end;
 
 
+    procedure tcg.a_op_reg(list: TAsmList; Op: TOpCG; size: TCGSize; reg: TRegister);
+      begin
+        if not (Op in [OP_NOT,OP_NEG]) then
+          internalerror(2020050701);
+        a_op_reg_reg(list,op,size,reg,reg);
+      end;
+
+
+    procedure tcg.a_op_ref(list: TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference);
+      var
+        tmpreg: TRegister;
+        tmpref: treference;
+      begin
+        if not (Op in [OP_NOT,OP_NEG]) then
+          internalerror(2020050701);
+        if assigned(ref.symbol) then
+          begin
+            tmpreg:=getaddressregister(list);
+            a_loadaddr_ref_reg(list,ref,tmpreg);
+            reference_reset_base(tmpref,tmpreg,0,ref.temppos,ref.alignment,[]);
+          end
+        else
+          tmpref:=ref;
+        tmpreg:=getintregister(list,size);
+        a_load_ref_reg(list,size,size,tmpref,tmpreg);
+        a_op_reg_reg(list,op,size,tmpreg,tmpreg);
+        a_load_reg_ref(list,size,size,tmpreg,tmpref);
+      end;
+
+
+    procedure tcg.a_op_loc(list: TAsmList; Op: TOpCG; const loc: tlocation);
+      begin
+        case loc.loc of
+          LOC_REGISTER, LOC_CREGISTER:
+            a_op_reg(list,op,loc.size,loc.register);
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_op_ref(list,op,loc.size,loc.reference);
+          else
+            internalerror(2020050702);
+        end;
+      end;
+
+
     procedure tcg.a_cmp_const_reg_label(list: TAsmList; size: tcgsize;
       cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
       var
@@ -3044,6 +3092,41 @@ implementation
       end;
 
 
+    procedure tcg64.a_op64_reg(list: TAsmList; op: TOpCG; size: tcgsize; regdst: tregister64);
+      begin
+        if not (op in [OP_NOT,OP_NEG]) then
+          internalerror(2020050706);
+        a_op64_reg_reg(list,op,size,regdst,regdst);
+      end;
+
+
+    procedure tcg64.a_op64_ref(list: TAsmList; op: TOpCG; size: tcgsize; const ref: treference);
+      var
+        tempreg: tregister64;
+      begin
+        if not (op in [OP_NOT,OP_NEG]) then
+          internalerror(2020050706);
+        tempreg.reghi:=cg.getintregister(list,OS_32);
+        tempreg.reglo:=cg.getintregister(list,OS_32);
+        a_load64_ref_reg(list,ref,tempreg);
+        a_op64_reg_reg(list,op,size,tempreg,tempreg);
+        a_load64_reg_ref(list,tempreg,ref);
+      end;
+
+
+    procedure tcg64.a_op64_loc(list: TAsmList; op: TOpCG; size: tcgsize; const l: tlocation);
+      begin
+        case l.loc of
+          LOC_REFERENCE, LOC_CREFERENCE:
+            a_op64_ref(list,op,size,l.reference);
+          LOC_REGISTER,LOC_CREGISTER:
+            a_op64_reg(list,op,size,l.register64);
+          else
+            internalerror(2020050707);
+        end;
+      end;
+
+
     procedure tcg64.a_load64_loc_subsetref(list : TAsmList;const l: tlocation; const sref : tsubsetreference);
       begin
         case l.loc of

+ 30 - 0
compiler/hlcg2ll.pas

@@ -221,6 +221,11 @@ unit hlcg2ll;
           procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); override;
           procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation); override;
 
+          { unary operations (not, neg) }
+          procedure a_op_reg(list : TAsmList; Op: TOpCG; size: tdef; reg: TRegister); override;
+          procedure a_op_ref(list : TAsmList; Op: TOpCG; size: tdef; const ref: TReference); override;
+          procedure a_op_loc(list : TAsmList; Op: TOpCG; size: tdef;  const loc: tlocation); override;
+
           {  comparison operations }
           procedure a_cmp_const_reg_label(list : TAsmList;size : tdef;cmp_op : topcmp;a : tcgint;reg : tregister;
             l : tasmlabel);override;
@@ -862,6 +867,31 @@ implementation
       cg.a_op_reg_reg_reg_checkoverflow(list,op,def_cgsize(size),src1,src2,dst,setflags,ovloc);
     end;
 
+  procedure thlcg2ll.a_op_reg(list: TAsmList; Op: TOpCG; size: tdef; reg: TRegister);
+    begin
+      cg.a_op_reg(list,op,def_cgsize(size),reg);
+    end;
+
+  procedure thlcg2ll.a_op_ref(list: TAsmList; Op: TOpCG; size: tdef; const ref: TReference);
+    begin
+      cg.a_op_ref(list,op,def_cgsize(size),ref);
+    end;
+
+  procedure thlcg2ll.a_op_loc(list: TAsmList; Op: TOpCG; size: tdef; const loc: tlocation);
+    begin
+{$ifdef extdebug}
+      if def_cgsize(size)<>loc.size then
+        internalerror(2020050704);
+{$endif}
+      case loc.loc of
+        LOC_SUBSETREG,LOC_CSUBSETREG,
+        LOC_SUBSETREF,LOC_CSUBSETREF:
+          inherited
+        else
+          cg.a_op_loc(list,op,loc);
+      end;
+    end;
+
   procedure thlcg2ll.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
     begin
       cg.a_cmp_const_reg_label(list,def_cgsize(size),cmp_op,a,reg,l);

+ 66 - 4
compiler/hlcgobj.pas

@@ -340,10 +340,6 @@ unit hlcgobj;
           procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tdef; mmreg, intreg: tregister; shuffle : pmmshuffle); virtual; abstract;
 
           { basic arithmetic operations }
-          { note: for operators which require only one argument (not, neg), use }
-          { the op_reg_reg, op_reg_ref or op_reg_loc methods and keep in mind   }
-          { that in this case the *second* operand is used as both source and   }
-          { destination (JM)                                                    }
           procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: tdef; a: tcgint; reg: TRegister); virtual; abstract;
           procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: tdef; a: tcgint; const ref: TReference); virtual;
           procedure a_op_const_subsetreg(list : TAsmList; Op : TOpCG; size, subsetsize : tdef; a : tcgint; const sreg: tsubsetregister); virtual;
@@ -365,6 +361,13 @@ unit hlcgobj;
           procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
           procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
 
+          { unary operations (not, neg) }
+          procedure a_op_reg(list : TAsmList; Op: TOpCG; size: tdef; reg: TRegister); virtual;
+          procedure a_op_ref(list : TAsmList; Op: TOpCG; size: tdef; const ref: TReference); virtual;
+          procedure a_op_subsetreg(list: TAsmList; Op: TOpCG; destsubsetsize: tdef; const sreg: tsubsetregister); virtual;
+          procedure a_op_subsetref(list: TAsmList; Op: TOpCG; destsubsetsize: tdef; const sref: tsubsetreference); virtual;
+          procedure a_op_loc(list : TAsmList; Op: TOpCG; size: tdef;  const loc: tlocation); virtual;
+
           {  comparison operations }
           procedure a_cmp_const_reg_label(list : TAsmList;size : tdef;cmp_op : topcmp;a : tcgint;reg : tregister;
             l : tasmlabel);virtual;
@@ -2994,6 +2997,65 @@ implementation
         internalerror(2010122911);
     end;
 
+  procedure thlcgobj.a_op_reg(list: TAsmList; Op: TOpCG; size: tdef; reg: TRegister);
+    begin
+      if not (Op in [OP_NOT,OP_NEG]) then
+        internalerror(2020050701);
+      a_op_reg_reg(list,op,size,reg,reg);
+    end;
+
+  procedure thlcgobj.a_op_ref(list: TAsmList; Op: TOpCG; size: tdef; const ref: TReference);
+    var
+      tmpreg: TRegister;
+    begin
+      if not (Op in [OP_NOT,OP_NEG]) then
+        internalerror(2020050701);
+      tmpreg:=getintregister(list,size);
+      a_load_ref_reg(list,size,size,ref,tmpreg);
+      a_op_reg_reg(list,op,size,tmpreg,tmpreg);
+      a_load_reg_ref(list,size,size,tmpreg,ref);
+    end;
+
+  procedure thlcgobj.a_op_subsetreg(list: TAsmList; Op: TOpCG; destsubsetsize: tdef; const sreg: tsubsetregister);
+    var
+      tmpreg: tregister;
+      subsetregdef: torddef;
+    begin
+      subsetregdef:=cgsize_orddef(sreg.subsetregsize);
+      tmpreg:=getintregister(list,subsetregdef);
+      a_load_subsetreg_reg(list,destsubsetsize,subsetregdef,sreg,tmpreg);
+      a_op_reg(list,op,subsetregdef,tmpreg);
+      a_load_reg_subsetreg(list,subsetregdef,destsubsetsize,tmpreg,sreg);
+    end;
+
+  procedure thlcgobj.a_op_subsetref(list: TAsmList; Op: TOpCG; destsubsetsize: tdef; const sref: tsubsetreference);
+    var
+      tmpreg: tregister;
+      subsetregdef: torddef;
+    begin
+      subsetregdef:=cgsize_orddef(def_cgsize(destsubsetsize));
+      tmpreg:=getintregister(list,subsetregdef);
+      a_load_subsetref_reg(list,destsubsetsize,subsetregdef,sref,tmpreg);
+      a_op_reg(list,op,subsetregdef,tmpreg);
+      a_load_reg_subsetref(list,subsetregdef,destsubsetsize,tmpreg,sref);
+    end;
+
+  procedure thlcgobj.a_op_loc(list: TAsmList; Op: TOpCG; size: tdef; const loc: tlocation);
+    begin
+      case loc.loc of
+        LOC_REGISTER, LOC_CREGISTER:
+          a_op_reg(list,op,size,loc.register);
+        LOC_REFERENCE, LOC_CREFERENCE:
+          a_op_ref(list,op,size,loc.reference);
+        LOC_SUBSETREG, LOC_CSUBSETREG:
+          a_op_subsetreg(list,op,size,loc.sreg);
+        LOC_SUBSETREF, LOC_CSUBSETREF:
+          a_op_subsetref(list,op,size,loc.sref);
+        else
+          internalerror(2020050703);
+      end;
+    end;
+
   procedure thlcgobj.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
     var
       tmpreg: tregister;

+ 36 - 21
compiler/i386/cgcpu.pas

@@ -56,6 +56,7 @@ unit cgcpu;
         procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
         procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
         procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
+        procedure a_op64_ref(list : TAsmList;op:TOpCG;size : tcgsize;const ref: treference);override;
       private
         procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
       end;
@@ -663,27 +664,8 @@ unit cgcpu;
         l1, l2: TAsmLabel;
       begin
         case op of
-          OP_NOT:
-            begin
-              tempref:=ref;
-              tcgx86(cg).make_simple_ref(list,tempref);
-              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
-              inc(tempref.offset,4);
-              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
-            end;
-          OP_NEG:
-            begin
-              tempref:=ref;
-              tcgx86(cg).make_simple_ref(list,tempref);
-              inc(tempref.offset,4);
-              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
-              cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
-              dec(tempref.offset,4);
-              list.concat(taicpu.op_ref(A_NEG,S_L,tempref));
-              inc(tempref.offset,4);
-              list.concat(taicpu.op_const_ref(A_SBB,S_L,-1,tempref));
-              cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
-            end;
+          OP_NOT,OP_NEG:
+            inherited;
           OP_SHR,OP_SHL,OP_SAR:
             begin
               { load right operators in a register }
@@ -1140,6 +1122,39 @@ unit cgcpu;
         end;
       end;
 
+
+    procedure tcg64f386.a_op64_ref(list: TAsmList; op: TOpCG; size: tcgsize; const ref: treference);
+      var
+        tempref : treference;
+      begin
+        case op of
+          OP_NOT:
+            begin
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
+            end;
+          OP_NEG:
+            begin
+              tempref:=ref;
+              tcgx86(cg).make_simple_ref(list,tempref);
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
+              cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
+              dec(tempref.offset,4);
+              list.concat(taicpu.op_ref(A_NEG,S_L,tempref));
+              inc(tempref.offset,4);
+              list.concat(taicpu.op_const_ref(A_SBB,S_L,-1,tempref));
+              cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
+            end;
+          else
+            internalerror(2020050708);
+        end;
+      end;
+
+
     procedure create_codegen;
       begin
         cg := tcg386.create;

+ 44 - 22
compiler/i8086/cgcpu.pas

@@ -53,6 +53,7 @@ unit cgcpu;
         procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
         procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
         procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
+        procedure a_op_ref(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference); override;
 
         procedure push_const(list:TAsmList;size:tcgsize;a:tcgint);
 
@@ -1138,7 +1139,7 @@ unit cgcpu;
       begin
         tmpref:=ref;
         make_simple_ref(list,tmpref);
-        if not (op in [OP_NEG,OP_NOT,OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR]) then
+        if not (op in [OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR]) then
           check_register_size(size,reg);
 
         if size in [OS_64, OS_S64] then
@@ -1147,27 +1148,8 @@ unit cgcpu;
         if size in [OS_32, OS_S32] then
           begin
             case op of
-              OP_NEG:
-                begin
-                  if reg<>NR_NO then
-                    internalerror(200109237);
-                  inc(tmpref.offset, 2);
-                  list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
-                  dec(tmpref.offset, 2);
-                  cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
-                  list.concat(taicpu.op_ref(A_NEG, S_W, tmpref));
-                  inc(tmpref.offset, 2);
-                  list.concat(taicpu.op_const_ref(A_SBB, S_W,-1, tmpref));
-                  cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
-                end;
-              OP_NOT:
-                begin
-                  if reg<>NR_NO then
-                    internalerror(200109237);
-                  list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
-                  inc(tmpref.offset, 2);
-                  list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
-                end;
+              OP_NEG,OP_NOT:
+                inherited;
               OP_IMUL:
                 begin
                   { this one needs a load/imul/store, which is the default }
@@ -1260,6 +1242,46 @@ unit cgcpu;
       end;
 
 
+    procedure tcg8086.a_op_ref(list: TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference);
+      begin
+        var
+          tmpref: treference;
+        begin
+          tmpref:=ref;
+          make_simple_ref(list,tmpref);
+
+          if size in [OS_64, OS_S64] then
+            internalerror(2013050803);
+
+          if size in [OS_32, OS_S32] then
+            begin
+              case op of
+                OP_NEG:
+                  begin
+                    inc(tmpref.offset, 2);
+                    list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
+                    dec(tmpref.offset, 2);
+                    cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
+                    list.concat(taicpu.op_ref(A_NEG, S_W, tmpref));
+                    inc(tmpref.offset, 2);
+                    list.concat(taicpu.op_const_ref(A_SBB, S_W,-1, tmpref));
+                    cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
+                  end;
+                OP_NOT:
+                  begin
+                    list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
+                    inc(tmpref.offset, 2);
+                    list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
+                  end;
+                else
+                  internalerror(2020050709);
+              end;
+            end
+          else
+            inherited a_op_reg_ref(list,Op,size,reg,tmpref);
+      end;
+
+
     procedure tcg8086.push_const(list: TAsmList; size: tcgsize; a: tcgint);
       var
         tmpreg: TRegister;

+ 4 - 22
compiler/ncginl.pas

@@ -527,36 +527,18 @@ implementation
       procedure tcginlinenode.second_NegNot_assign;
         const
           negnotop:array[in_neg_assign_x..in_not_assign_x] of TOpCG=(OP_NEG,OP_NOT);
-{$ifndef cpu64bitalu}
-        var
-          NR_NO64: tregister64=(reglo:NR_NO;reghi:NR_NO);
-{$endif not cpu64bitalu}
         begin
           { load parameter, must be a reference }
           secondpass(left);
 
           location_reset(location,LOC_VOID,OS_NO);
 
-          if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-            begin
 {$ifndef cpu64bitalu}
-              if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
-                cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],def_cgsize(left.resultdef),left.location.register64,left.location)
-              else
-{$endif not cpu64bitalu}
-                hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],left.resultdef,left.location.register,left.location);
-            end
-          else if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
-            begin
-{$ifndef cpu64bitalu}
-              if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
-                cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],def_cgsize(left.resultdef),NR_NO64,left.location)
-              else
-{$endif not cpu64bitalu}
-                hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],left.resultdef,NR_NO,left.location);
-            end
+          if (def_cgsize(left.resultdef) in [OS_64,OS_S64]) and (left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
+            cg64.a_op64_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],def_cgsize(left.resultdef),left.location)
           else
-            internalerror(2017040701);
+{$endif not cpu64bitalu}
+            hlcg.a_op_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],left.resultdef,left.location);
         end;
 
 

+ 14 - 8
compiler/x86/cgx86.pas

@@ -67,6 +67,7 @@ unit cgx86;
         procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
         procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
         procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
+        procedure a_op_ref(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference); override;
 
 {$ifndef i8086}
         procedure a_op_const_reg_reg(list : TAsmList; op : Topcg; size : Tcgsize; a : tcgint; src,dst : Tregister); override;
@@ -2433,8 +2434,6 @@ unit cgx86;
         tmpref:=ref;
         make_simple_ref(list,tmpref);
         { we don't check the register size for some operations, for the following reasons:
-          NEG,NOT:
-            reg isn't used in these operations (they are unary and use only ref)
           SHR,SHL,SAR,ROL,ROR:
             We allow the register size to differ from the destination size.
             This allows generating better code when performing, for example, a
@@ -2445,17 +2444,13 @@ unit cgx86;
                 EDX have 8-bit subregisters)
               - avoids partial register writes, which can cause various
                 performance issues on modern out-of-order execution x86 CPUs }
-        if not (op in [OP_NEG,OP_NOT,OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR]) then
+        if not (op in [OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR]) then
           check_register_size(size,reg);
         if (op=OP_MUL) and not (cs_check_overflow in current_settings.localswitches) then
           op:=OP_IMUL;
         case op of
           OP_NEG,OP_NOT:
-            begin
-              if reg<>NR_NO then
-                internalerror(200109237);
-              list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],tmpref));
-            end;
+            inherited;
           OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
             begin
               { Use ecx to load the value, that allows better coalescing }
@@ -2480,6 +2475,17 @@ unit cgx86;
         end;
       end;
 
+    procedure tcgx86.a_op_ref(list: TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference);
+      var
+        tmpref: treference;
+      begin
+        if not (Op in [OP_NOT,OP_NEG]) then
+          internalerror(2020050705);
+        tmpref:=ref;
+        make_simple_ref(list,tmpref);
+        list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],tmpref));
+      end;
+
      procedure tcgx86.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister);
      var
        tmpreg: tregister;