Просмотр исходного кода

merge with trunk

git-svn-id: branches/tg74/avx2@28413 -
tg74 11 лет назад
Родитель
Сommit
60db1d733e
41 измененных файлов с 3971 добавлено и 775 удалено
  1. 5 1
      .gitattributes
  2. 562 149
      compiler/i8086/cgcpu.pas
  3. 1 0
      compiler/i8086/cpubase.inc
  4. 2 2
      compiler/i8086/cpuinfo.pas
  5. 6 1
      compiler/i8086/cpunode.pas
  6. 22 19
      compiler/i8086/cpupara.pas
  7. 228 22
      compiler/i8086/hlcgcpu.pas
  8. 85 16
      compiler/i8086/i8086att.inc
  9. 82 13
      compiler/i8086/i8086atts.inc
  10. 85 16
      compiler/i8086/i8086int.inc
  11. 1 1
      compiler/i8086/i8086nop.inc
  12. 85 16
      compiler/i8086/i8086op.inc
  13. 148 79
      compiler/i8086/i8086prop.inc
  14. 1003 9
      compiler/i8086/i8086tab.inc
  15. 370 16
      compiler/i8086/n8086add.pas
  16. 35 4
      compiler/i8086/n8086cal.pas
  17. 18 104
      compiler/i8086/n8086cnv.pas
  18. 16 5
      compiler/i8086/n8086con.pas
  19. 138 4
      compiler/i8086/n8086inl.pas
  20. 91 0
      compiler/i8086/n8086ld.pas
  21. 121 100
      compiler/i8086/n8086mat.pas
  22. 46 28
      compiler/i8086/n8086mem.pas
  23. 77 0
      compiler/i8086/n8086tcon.pas
  24. 127 0
      compiler/i8086/n8086util.pas
  25. 8 8
      compiler/i8086/r8086ari.inc
  26. 4 4
      compiler/i8086/r8086att.inc
  27. 22 22
      compiler/i8086/r8086con.inc
  28. 1 1
      compiler/i8086/r8086dwrf.inc
  29. 4 4
      compiler/i8086/r8086int.inc
  30. 8 8
      compiler/i8086/r8086iri.inc
  31. 4 4
      compiler/i8086/r8086nasm.inc
  32. 8 8
      compiler/i8086/r8086nri.inc
  33. 7 7
      compiler/i8086/r8086num.inc
  34. 0 82
      compiler/i8086/r8086op.inc
  35. 3 3
      compiler/i8086/r8086ot.inc
  36. 2 2
      compiler/i8086/r8086rni.inc
  37. 8 8
      compiler/i8086/r8086sri.inc
  38. 4 4
      compiler/i8086/r8086std.inc
  39. 18 5
      compiler/i8086/rgcpu.pas
  40. 458 0
      compiler/i8086/symcpu.pas
  41. 58 0
      compiler/i8086/tgcpu.pas

+ 5 - 1
.gitattributes

@@ -251,8 +251,11 @@ compiler/i8086/n8086cal.pas svneol=native#text/plain
 compiler/i8086/n8086cnv.pas svneol=native#text/plain
 compiler/i8086/n8086con.pas svneol=native#text/plain
 compiler/i8086/n8086inl.pas svneol=native#text/plain
+compiler/i8086/n8086ld.pas svneol=native#text/plain
 compiler/i8086/n8086mat.pas svneol=native#text/plain
 compiler/i8086/n8086mem.pas svneol=native#text/plain
+compiler/i8086/n8086tcon.pas svneol=native#text/plain
+compiler/i8086/n8086util.pas svneol=native#text/plain
 compiler/i8086/r8086ari.inc svneol=native#text/plain
 compiler/i8086/r8086att.inc svneol=native#text/plain
 compiler/i8086/r8086con.inc svneol=native#text/plain
@@ -263,7 +266,6 @@ compiler/i8086/r8086nasm.inc svneol=native#text/plain
 compiler/i8086/r8086nor.inc svneol=native#text/plain
 compiler/i8086/r8086nri.inc svneol=native#text/plain
 compiler/i8086/r8086num.inc svneol=native#text/plain
-compiler/i8086/r8086op.inc svneol=native#text/plain
 compiler/i8086/r8086ot.inc svneol=native#text/plain
 compiler/i8086/r8086rni.inc svneol=native#text/plain
 compiler/i8086/r8086sri.inc svneol=native#text/plain
@@ -272,6 +274,8 @@ compiler/i8086/r8086std.inc svneol=native#text/plain
 compiler/i8086/ra8086att.pas svneol=native#text/plain
 compiler/i8086/ra8086int.pas svneol=native#text/plain
 compiler/i8086/rgcpu.pas svneol=native#text/plain
+compiler/i8086/symcpu.pas svneol=native#text/plain
+compiler/i8086/tgcpu.pas svneol=native#text/plain
 compiler/ia64/aasmcpu.pas svneol=native#text/plain
 compiler/ia64/cpubase.pas svneol=native#text/plain
 compiler/ia64/cpuinfo.pas svneol=native#text/plain

Разница между файлами не показана из-за своего большого размера
+ 562 - 149
compiler/i8086/cgcpu.pas


+ 1 - 0
compiler/i8086/cpubase.inc

@@ -157,6 +157,7 @@
       }
       saved_standard_registers : array[0..0] of tsuperregister = (RS_BP);
 
+      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
       saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined

+ 2 - 2
compiler/i8086/cpuinfo.pas

@@ -123,9 +123,9 @@ Const
                                   cs_opt_tailrecursion,cs_opt_nodecse,cs_useebp,
 				  cs_opt_reorder_fields,cs_opt_fastmath];
 
-   level1optimizerswitches = genericlevel1optimizerswitches + [cs_opt_peephole];
+   level1optimizerswitches = genericlevel1optimizerswitches;
    level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
-     [{cs_opt_regvar,}cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
+     [{cs_opt_regvar,}cs_opt_stackframe,cs_opt_tailrecursion{,cs_opt_nodecse}];
    level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [cs_useebp];
 

+ 6 - 1
compiler/i8086/cpunode.pas

@@ -50,11 +50,16 @@ unit cpunode;
        n8086add,
        n8086cal,
        n8086cnv,
+       n8086ld,
        n8086mem{,
        n386set},
        n8086inl,
        n8086mat,
-       n8086con
+       n8086con,
+       { these are not really nodes }
+       n8086util,n8086tcon,tgcpu,
+       { symtable }
+       symcpu
        ;
 
 end.

+ 22 - 19
compiler/i8086/cpupara.pas

@@ -67,7 +67,7 @@ unit cpupara;
     uses
        cutils,
        systems,verbose,
-       symtable,
+       symtable,symcpu,
        defutil;
 
       const
@@ -418,13 +418,15 @@ unit cpupara;
         paracgsize : tcgsize;
         firstparaloc,
         pushaddr   : boolean;
+        pushleftright: boolean;
       begin
         paraalign:=get_para_align(p.proccalloption);
-        { we push Flags and CS as long
-          to cope with the IRETD
-          and we save 6 register + 4 selectors }
+        { interrupt routines need parameter fixup }
         if po_interrupt in p.procoptions then
-          inc(parasize,8+6*4+4*2);
+          if is_proc_far(p) then
+            dec(parasize,6)
+          else
+            dec(parasize,4);
         { Offset is calculated like:
            sub esp,12
            mov [esp+8],para3
@@ -434,20 +436,21 @@ unit cpupara;
           That means for pushes the para with the
           highest offset (see para3) needs to be pushed first
         }
-        if p.proccalloption in pushleftright_pocalls then
+        pushleftright:=(p.proccalloption in pushleftright_pocalls) or (po_interrupt in p.procoptions);
+        if pushleftright then
           i:=paras.count-1
         else
           i:=0;
-        while ((p.proccalloption in pushleftright_pocalls) and (i>=0)) or
-              (not(p.proccalloption in pushleftright_pocalls) and (i<=paras.count-1)) do
+        while (pushleftright and (i>=0)) or
+              (not(pushleftright) and (i<=paras.count-1)) do
           begin
             hp:=tparavarsym(paras[i]);
             paradef:=hp.vardef;
             pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
             if pushaddr then
               begin
-                paralen:=sizeof(aint);
-                paracgsize:=OS_ADDR;
+                paralen:=voidpointertype.size;
+                paracgsize:=int_cgsize(voidpointertype.size);
                 paradef:=getpointerdef(paradef);
               end
             else
@@ -496,7 +499,7 @@ unit cpupara;
                 if side=calleeside then
                   begin
                     inc(paraloc^.reference.offset,target_info.first_parm_offset);
-                    if po_far in p.procoptions then
+                    if is_proc_far(p) then
                       inc(paraloc^.reference.offset,2);
                   end;
                 parasize:=align(parasize+paralen,varalign);
@@ -546,7 +549,7 @@ unit cpupara;
                         else
                           { return addres }
                           inc(paraloc^.reference.offset,2);
-                        if po_far in p.procoptions then
+                        if is_proc_far(p) then
                           inc(paraloc^.reference.offset,2);
                       end;
                     parasize:=align(parasize+l,varalign);
@@ -554,7 +557,7 @@ unit cpupara;
                     firstparaloc:=false;
                   end;
               end;
-            if p.proccalloption in pushleftright_pocalls then
+            if pushleftright then
               dec(i)
             else
               inc(i);
@@ -606,8 +609,8 @@ unit cpupara;
                     pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
                     if pushaddr then
                       begin
-                        paralen:=sizeof(aint);
-                        paracgsize:=OS_ADDR;
+                        paralen:=voidpointertype.size;
+                        paracgsize:=int_cgsize(voidpointertype.size);
                         paradef:=getpointerdef(paradef);
                       end
                     else
@@ -669,7 +672,7 @@ unit cpupara;
                               if side=calleeside then
                                 begin
                                   inc(paraloc^.reference.offset,target_info.first_parm_offset);
-                                  if po_far in p.procoptions then
+                                  if is_proc_far(p) then
                                     inc(paraloc^.reference.offset,2);
                                 end;
                               parasize:=align(parasize+paralen,varalign);
@@ -692,8 +695,8 @@ unit cpupara;
                                     end
                                   else
                                     begin
-                                      { We can allocate at maximum 32 bits per location }
-                                      if paralen>sizeof(aint) then
+                                      { We can allocate at maximum 16 bits per location }
+                                      if paralen>=sizeof(aint) then
                                         begin
                                           l:=sizeof(aint);
                                           paraloc^.def:=uinttype;
@@ -714,7 +717,7 @@ unit cpupara;
                                   if side=calleeside then
                                     begin
                                       inc(paraloc^.reference.offset,target_info.first_parm_offset);
-                                      if po_far in p.procoptions then
+                                      if is_proc_far(p) then
                                         inc(paraloc^.reference.offset,2);
                                     end;
                                   parasize:=align(parasize+l,varalign);

+ 228 - 22
compiler/i8086/hlcgcpu.pas

@@ -29,7 +29,7 @@ unit hlcgcpu;
 interface
 
   uses
-    globals,
+    globals,globtype,
     aasmdata,
     symtype,symdef,parabase,
     cgbase,cgutils,
@@ -37,10 +37,43 @@ interface
 
 
   type
+
+    { thlcgcpu }
+
     thlcgcpu = class(thlcgx86)
+     private
+      { checks whether the type needs special methodptr-like handling, when stored
+        in a LOC_REGISTER location. This applies to the following types:
+          - i8086 method pointers (incl. 6-byte mixed near + far),
+          - 6-byte records (only in the medium and compact memory model are these
+              loaded in a register)
+          - nested proc ptrs
+        When stored in a LOC_REGISTER tlocation, these types use both register
+        and registerhi with the following sizes:
+
+        register   - cgsize = int_cgsize(voidcodepointertype.size)
+        registerhi - cgsize = int_cgsize(voidpointertype.size) or int_cgsize(parentfpvoidpointertype.size)
+                              (check d.size to determine which one of the two)
+        }
+      function is_methodptr_like_type(d:tdef): boolean;
+
+      { 4-byte records in registers need special handling as well. A record may
+        be located in registerhi:register if it was converted from a procvar or
+        in GetNextReg(register):register if it was converted from a longint.
+        We can tell between the two by checking whether registerhi has been set. }
+      function is_fourbyterecord(d:tdef): boolean;
      protected
       procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint); override;
      public
+      function getaddressregister(list:TAsmList;size:tdef):Tregister;override;
+
+      procedure reference_reset_base(var ref: treference; regsize: tdef; reg: tregister; offset, alignment: longint); override;
+
+      function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; weak: boolean): tcgpara;override;
+
+      procedure a_load_loc_ref(list : TAsmList;fromsize, tosize: tdef; const loc: tlocation; const ref : treference);override;
+      procedure a_loadaddr_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister);override;
+
       procedure g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister); override;
       procedure g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation); override;
 
@@ -52,13 +85,37 @@ interface
 implementation
 
   uses
-    globtype,verbose,
+    verbose,
     paramgr,
     cpubase,cpuinfo,tgobj,cgobj,cgcpu,
-    symconst;
+    defutil,
+    symconst,symcpu,
+    procinfo,fmodule,
+    aasmcpu;
 
   { thlcgcpu }
 
+  function thlcgcpu.is_methodptr_like_type(d: tdef): boolean;
+    var
+      is_sixbyterecord,is_methodptr,is_nestedprocptr: Boolean;
+    begin
+      is_sixbyterecord:=(d.typ=recorddef) and (d.size=6);
+      is_methodptr:=(d.typ=procvardef)
+        and (po_methodpointer in tprocvardef(d).procoptions)
+        and not(po_addressonly in tprocvardef(d).procoptions);
+      is_nestedprocptr:=(d.typ=procvardef)
+        and is_nested_pd(tprocvardef(d))
+        and not(po_addressonly in tprocvardef(d).procoptions);
+      result:=is_sixbyterecord or is_methodptr or is_nestedprocptr;
+    end;
+
+
+  function thlcgcpu.is_fourbyterecord(d: tdef): boolean;
+    begin
+      result:=(d.typ=recorddef) and (d.size=4);
+    end;
+
+
   procedure thlcgcpu.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
     var
       locsize : tcgsize;
@@ -82,10 +139,10 @@ implementation
                      (cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
                     begin
                       cg.g_stackpointer_alloc(list,stacksize);
-                      reference_reset_base(href,NR_STACK_POINTER_REG,0,sizeof(pint));
+                      reference_reset_base(href,voidstackpointertype,NR_STACK_POINTER_REG,0,voidstackpointertype.size);
                     end
                   else
-                    reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+                    reference_reset_base(href,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
                   cg.a_loadfpu_reg_ref(list,locsize,locsize,l.register,href);
                 end;
               LOC_FPUREGISTER:
@@ -127,10 +184,10 @@ implementation
                      (cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
                     begin
                       cg.g_stackpointer_alloc(list,stacksize);
-                      reference_reset_base(href,NR_STACK_POINTER_REG,0,sizeof(pint));
+                      reference_reset_base(href,voidstackpointertype,NR_STACK_POINTER_REG,0,voidstackpointertype.size);
                     end
                   else
-                    reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+                    reference_reset_base(href,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
                   cg.a_loadmm_reg_ref(list,locsize,locsize,l.register,href,mms_movescalar);
                 end;
               LOC_FPUREGISTER:
@@ -156,7 +213,7 @@ implementation
                     cg.a_load_ref_cgpara(list,locsize,l.reference,cgpara)
                   else
                     begin
-                      reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+                      reference_reset_base(href,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
                       cg.g_concatcopy(list,l.reference,href,stacksize);
                     end;
                 end;
@@ -174,6 +231,146 @@ implementation
     end;
 
 
+  function thlcgcpu.getaddressregister(list: TAsmList; size: tdef): Tregister;
+    begin
+      { implicit pointer types on i8086 follow the default data pointer size for
+        the current memory model }
+      if is_implicit_pointer_object_type(size) or is_implicit_array_pointer(size) then
+        size:=voidpointertype;
+
+      if is_farpointer(size) or is_hugepointer(size) then
+        Result:=cg.getintregister(list,OS_32)
+      else
+        Result:=cg.getintregister(list,OS_16);
+    end;
+
+
+  procedure thlcgcpu.reference_reset_base(var ref: treference; regsize: tdef;
+    reg: tregister; offset, alignment: longint);
+    begin
+      inherited reference_reset_base(ref, regsize, reg, offset, alignment);
+
+      { implicit pointer types on i8086 follow the default data pointer size for
+        the current memory model }
+      if is_implicit_pointer_object_type(regsize) or is_implicit_array_pointer(regsize) then
+        regsize:=voidpointertype;
+
+      if regsize.typ=pointerdef then
+        case tcpupointerdef(regsize).x86pointertyp of
+          x86pt_near:
+            ;
+          x86pt_near_cs:
+            ref.segment:=NR_CS;
+          x86pt_near_ds:
+            ref.segment:=NR_DS;
+          x86pt_near_ss:
+            ref.segment:=NR_SS;
+          x86pt_near_es:
+            ref.segment:=NR_ES;
+          x86pt_near_fs:
+            ref.segment:=NR_FS;
+          x86pt_near_gs:
+            ref.segment:=NR_GS;
+          x86pt_far,
+          x86pt_huge:
+            if reg<>NR_NO then
+              ref.segment:=GetNextReg(reg);
+        end;
+    end;
+
+
+  function thlcgcpu.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara;
+    begin
+      if is_proc_far(pd) then
+        begin
+          { far calls to the same module (in $HUGECODE off mode) can be optimized
+            to push cs + call near, because they are in the same segment }
+          if not (cs_huge_code in current_settings.moduleswitches) and
+             pd.owner.iscurrentunit and not (po_external in pd.procoptions) then
+            begin
+              list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_CS));
+              tcg8086(cg).a_call_name_near(list,s,weak);
+            end
+          else
+            tcg8086(cg).a_call_name_far(list,s,weak);
+        end
+      else
+        tcg8086(cg).a_call_name_near(list,s,weak);
+      result:=get_call_result_cgpara(pd,forceresdef);
+    end;
+
+
+  procedure thlcgcpu.a_load_loc_ref(list: TAsmList; fromsize, tosize: tdef; const loc: tlocation; const ref: treference);
+    var
+      tmpref: treference;
+    begin
+      if is_methodptr_like_type(tosize) and (loc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+        begin
+          tmpref:=ref;
+          a_load_reg_ref(list,voidcodepointertype,voidcodepointertype,loc.register,tmpref);
+          inc(tmpref.offset,voidcodepointertype.size);
+          { the second part could be either self or parentfp }
+          if tosize.size=(voidcodepointertype.size+voidpointertype.size) then
+            a_load_reg_ref(list,voidpointertype,voidpointertype,loc.registerhi,tmpref)
+          else if tosize.size=(voidcodepointertype.size+parentfpvoidpointertype.size) then
+            a_load_reg_ref(list,parentfpvoidpointertype,parentfpvoidpointertype,loc.registerhi,tmpref)
+          else
+            internalerror(2014052201);
+        end
+      else if is_fourbyterecord(tosize) and (loc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+        begin
+          tmpref:=ref;
+          cg.a_load_reg_ref(list,OS_16,OS_16,loc.register,tmpref);
+          inc(tmpref.offset,2);
+          if loc.registerhi<>tregister(0) then
+            cg.a_load_reg_ref(list,OS_16,OS_16,loc.registerhi,tmpref)
+          else
+            cg.a_load_reg_ref(list,OS_16,OS_16,GetNextReg(loc.register),tmpref);
+        end
+      else
+        inherited a_load_loc_ref(list, fromsize, tosize, loc, ref);
+    end;
+
+
+  procedure thlcgcpu.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
+    var
+      tmpref,segref: treference;
+    begin
+      { step 1: call the x86 low level code generator to handle the offset;
+        we set the segment to NR_NO to disable the i8086 segment handling code
+        in the low level cg (which can be removed, once all calls to
+        a_loadaddr_ref_reg go through the high level code generator) }
+      tmpref:=ref;
+      tmpref.segment:=NR_NO;
+      cg.a_loadaddr_ref_reg(list, tmpref, r);
+
+      { step 2: if destination is a far pointer, we have to pass a segment as well }
+      if is_farpointer(tosize) or is_hugepointer(tosize) then
+        begin
+          { if a segment register is specified in ref, we use that }
+          if ref.segment<>NR_NO then
+            begin
+              if is_segment_reg(ref.segment) then
+                list.concat(Taicpu.op_reg_reg(A_MOV,S_W,ref.segment,GetNextReg(r)))
+              else
+                cg.a_load_reg_reg(list,OS_16,OS_16,ref.segment,GetNextReg(r));
+            end
+          { references relative to a symbol use the segment of the symbol,
+            which can be obtained by the SEG directive }
+          else if assigned(ref.symbol) then
+            begin
+              reference_reset_symbol(segref,ref.symbol,0,0);
+              segref.refaddr:=addr_seg;
+              cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,segref,GetNextReg(r));
+            end
+          else if ref.base=NR_BP then
+            list.concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_SS,GetNextReg(r)))
+          else
+            internalerror(2014032801);
+        end;
+    end;
+
+
   procedure thlcgcpu.g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister);
     begin
       if paramanager.use_fixed_stack then
@@ -200,26 +397,35 @@ implementation
     var
       r,tmpref: treference;
     begin
-      { handle i8086 6-byte (mixed near + far) method pointers }
-      if (size.typ in [procvardef,recorddef]) and (size.size=6) and (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+      if is_methodptr_like_type(size) and (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
         begin
           tg.gethltemp(list,size,size.size,tt_normal,r);
           tmpref:=r;
 
-          if current_settings.x86memorymodel in x86_far_code_models then
-            begin
-              cg.a_load_reg_ref(list,OS_32,OS_32,l.register,tmpref);
-              inc(tmpref.offset,4);
-            end
+          a_load_reg_ref(list,voidcodepointertype,voidcodepointertype,l.register,tmpref);
+          inc(tmpref.offset,voidcodepointertype.size);
+          { the second part could be either self or parentfp }
+          if size.size=(voidcodepointertype.size+voidpointertype.size) then
+            a_load_reg_ref(list,voidpointertype,voidpointertype,l.registerhi,tmpref)
+          else if size.size=(voidcodepointertype.size+parentfpvoidpointertype.size) then
+            a_load_reg_ref(list,parentfpvoidpointertype,parentfpvoidpointertype,l.registerhi,tmpref)
           else
-            begin
-              cg.a_load_reg_ref(list,OS_16,OS_16,l.register,tmpref);
-              inc(tmpref.offset,2);
-            end;
-          if current_settings.x86memorymodel in x86_far_data_models then
-            cg.a_load_reg_ref(list,OS_32,OS_32,l.registerhi,tmpref)
+            internalerror(2014052202);
+
+          location_reset_ref(l,LOC_REFERENCE,l.size,0);
+          l.reference:=r;
+        end
+      else if is_fourbyterecord(size) and (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+        begin
+          tg.gethltemp(list,size,size.size,tt_normal,r);
+          tmpref:=r;
+
+          cg.a_load_reg_ref(list,OS_16,OS_16,l.register,tmpref);
+          inc(tmpref.offset,2);
+          if l.registerhi<>tregister(0) then
+            cg.a_load_reg_ref(list,OS_16,OS_16,l.registerhi,tmpref)
           else
-            cg.a_load_reg_ref(list,OS_16,OS_16,l.registerhi,tmpref);
+            cg.a_load_reg_ref(list,OS_16,OS_16,GetNextReg(l.register),tmpref);
 
           location_reset_ref(l,LOC_REFERENCE,l.size,0);
           l.reference:=r;

+ 85 - 16
compiler/i8086/i8086att.inc

@@ -161,10 +161,8 @@
 'iret',
 'iret',
 'iretw',
-'iretq',
 'jcxz',
 'jecxz',
-'jrcxz',
 'jmp',
 'lahf',
 'lar',
@@ -200,7 +198,6 @@
 'movq',
 'movsb',
 'movsl',
-'movsq',
 'movsw',
 'movs',
 'movz',
@@ -272,7 +269,6 @@
 'popf',
 'popfl',
 'popfw',
-'popfq',
 'por',
 'prefetch',
 'prefetchw',
@@ -306,7 +302,6 @@
 'pushf',
 'pushfl',
 'pushfw',
-'pushfq',
 'pxor',
 'rcl',
 'rcr',
@@ -334,7 +329,6 @@
 'sbb',
 'scasb',
 'scasl',
-'scasq',
 'scasw',
 'cs',
 'ds',
@@ -596,10 +590,6 @@
 'xsha256',
 'dmint',
 'rdm',
-'movabs',
-'movslq',
-'cqto',
-'cmpxchg16b',
 'movntss',
 'movntsd',
 'insertq',
@@ -637,11 +627,9 @@
 'pcmpeqq',
 'pextrb',
 'pextrd',
-'pextrq',
 'phminposuw',
 'pinsrb',
 'pinsrd',
-'pinsrq',
 'pmaxsb',
 'pmaxsd',
 'pmaxud',
@@ -682,9 +670,6 @@
 'aesdeclast',
 'aesimc',
 'aeskeygenassist',
-'stosq',
-'lodsq',
-'cmpsq',
 'vaddpd',
 'vaddps',
 'vaddsd',
@@ -946,6 +931,7 @@
 'vzeroupper',
 'andn',
 'bextr',
+'tzcnt',
 'rorx',
 'sarx',
 'shlx',
@@ -969,5 +955,88 @@
 'vpsllvq',
 'vpsravd',
 'vpsrlvd',
-'vpsrlvq'
+'vpsrlvq',
+'vgatherdpd',
+'vgatherdps',
+'vgatherqpd',
+'vgatherqps',
+'vpgatherdd',
+'vpgatherdq',
+'vpgatherqd',
+'vpgatherqq',
+'add4s',
+'brkem',
+'clr1',
+'cmp4s',
+'ext',
+'ins',
+'not1',
+'repc',
+'repnc',
+'rol4',
+'ror4',
+'set1',
+'sub4s',
+'test1',
+'vfmadd132pd',
+'vfmadd213pd',
+'vfmadd231pd',
+'vfmaddpd',
+'vfmadd132ps',
+'vfmadd213ps',
+'vfmadd231ps',
+'vfmadd132sd',
+'vfmadd213sd',
+'vfmadd231sd',
+'vfmadd132ss',
+'vfmadd213ss',
+'vfmadd231ss',
+'vfmaddsub132pd',
+'vfmaddsub213pd',
+'vfmaddsub231pd',
+'vfmaddsub132ps',
+'vfmaddsub213ps',
+'vfmaddsub231ps',
+'vfmsubadd132pd',
+'vfmsubadd213pd',
+'vfmsubadd231pd',
+'vfmsubadd132ps',
+'vfmsubadd213ps',
+'vfmsubadd231ps',
+'vfmsub132pd',
+'vfmsub213pd',
+'vfmsub231pd',
+'vfmsub132ps',
+'vfmsub213ps',
+'vfmsub231ps',
+'vfmsub132sd',
+'vfmsub213sd',
+'vfmsub231sd',
+'vfmsub132ss',
+'vfmsub213ss',
+'vfmsub231ss',
+'vfnmadd132pd',
+'vfnmadd213pd',
+'vfnmadd231pd',
+'vfnmadd132ps',
+'vfnmadd213ps',
+'vfnmadd231ps',
+'vfnmadd132sd',
+'vfnmadd213sd',
+'vfnmadd231sd',
+'vfnmadd132ss',
+'vfnmadd213ss',
+'vfnmadd231ss',
+'vfnmsub132pd',
+'vfnmsub213pd',
+'vfnmsub231pd',
+'vfnmsub132ps',
+'vfnmsub213ps',
+'vfnmsub231ps',
+'vfnmsub132sd',
+'vfnmsub213sd',
+'vfnmsub231sd',
+'vfnmsub132ss',
+'vfnmsub213ss',
+'vfnmsub231ss'
 );

+ 82 - 13
compiler/i8086/i8086atts.inc

@@ -163,8 +163,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
-attsufNONE,
 attsufINT,
 attsufNONE,
 attsufINT,
@@ -201,7 +199,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINTdual,
 attsufINTdual,
 attsufINT,
@@ -273,7 +270,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINT,
 attsufINT,
 attsufNONE,
@@ -307,7 +303,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINT,
 attsufINT,
 attsufNONE,
@@ -342,7 +337,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINT,
 attsufINT,
 attsufINT,
@@ -599,17 +593,77 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufNONE,
 attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -647,6 +701,28 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufMM,
+attsufMM,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufMM,
+attsufMM,
+attsufNONE,
+attsufNONE,
+attsufMM,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -669,13 +745,11 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -716,17 +790,12 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufMM,
-attsufMM,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufMM,
-attsufMM,
 attsufNONE,
 attsufNONE,
-attsufMM,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 85 - 16
compiler/i8086/i8086int.inc

@@ -161,10 +161,8 @@
 'iret',
 'iretd',
 'iretw',
-'iretq',
 'jcxz',
 'jecxz',
-'jrcxz',
 'jmp',
 'lahf',
 'lar',
@@ -200,7 +198,6 @@
 'movq',
 'movsb',
 'movsd',
-'movsq',
 'movsw',
 'movsx',
 'movzx',
@@ -272,7 +269,6 @@
 'popf',
 'popfd',
 'popfw',
-'popfq',
 'por',
 'prefetch',
 'prefetchw',
@@ -306,7 +302,6 @@
 'pushf',
 'pushfd',
 'pushfw',
-'pushfq',
 'pxor',
 'rcl',
 'rcr',
@@ -334,7 +329,6 @@
 'sbb',
 'scasb',
 'scasd',
-'scasq',
 'scasw',
 'segcs',
 'segds',
@@ -596,10 +590,6 @@
 'xsha256',
 'dmint',
 'rdm',
-'movabs',
-'movsxd',
-'cqo',
-'cmpxchg16b',
 'movntss',
 'movntsd',
 'insertq',
@@ -637,11 +627,9 @@
 'pcmpeqq',
 'pextrb',
 'pextrd',
-'pextrq',
 'phminposuw',
 'pinsrb',
 'pinsrd',
-'pinsrq',
 'pmaxsb',
 'pmaxsd',
 'pmaxud',
@@ -682,9 +670,6 @@
 'aesdeclast',
 'aesimc',
 'aeskeygenassist',
-'stosq',
-'lodsq',
-'cmpsq',
 'vaddpd',
 'vaddps',
 'vaddsd',
@@ -946,6 +931,7 @@
 'vzeroupper',
 'andn',
 'bextr',
+'tzcnt',
 'rorx',
 'sarx',
 'shlx',
@@ -969,5 +955,88 @@
 'vpsllvq',
 'vpsravd',
 'vpsrlvd',
-'vpsrlvq'
+'vpsrlvq',
+'vgatherdpd',
+'vgatherdps',
+'vgatherqpd',
+'vgatherqps',
+'vpgatherdd',
+'vpgatherdq',
+'vpgatherqd',
+'vpgatherqq',
+'add4s',
+'brkem',
+'clr1',
+'cmp4s',
+'ext',
+'ins',
+'not1',
+'repc',
+'repnc',
+'rol4',
+'ror4',
+'set1',
+'sub4s',
+'test1',
+'vfmadd132pd',
+'vfmadd213pd',
+'vfmadd231pd',
+'vfmaddpd',
+'vfmadd132ps',
+'vfmadd213ps',
+'vfmadd231ps',
+'vfmadd132sd',
+'vfmadd213sd',
+'vfmadd231sd',
+'vfmadd132ss',
+'vfmadd213ss',
+'vfmadd231ss',
+'vfmaddsub132pd',
+'vfmaddsub213pd',
+'vfmaddsub231pd',
+'vfmaddsub132ps',
+'vfmaddsub213ps',
+'vfmaddsub231ps',
+'vfmsubadd132pd',
+'vfmsubadd213pd',
+'vfmsubadd231pd',
+'vfmsubadd132ps',
+'vfmsubadd213ps',
+'vfmsubadd231ps',
+'vfmsub132pd',
+'vfmsub213pd',
+'vfmsub231pd',
+'vfmsub132ps',
+'vfmsub213ps',
+'vfmsub231ps',
+'vfmsub132sd',
+'vfmsub213sd',
+'vfmsub231sd',
+'vfmsub132ss',
+'vfmsub213ss',
+'vfmsub231ss',
+'vfnmadd132pd',
+'vfnmadd213pd',
+'vfnmadd231pd',
+'vfnmadd132ps',
+'vfnmadd213ps',
+'vfnmadd231ps',
+'vfnmadd132sd',
+'vfnmadd213sd',
+'vfnmadd231sd',
+'vfnmadd132ss',
+'vfnmadd213ss',
+'vfnmadd231ss',
+'vfnmsub132pd',
+'vfnmsub213pd',
+'vfnmsub231pd',
+'vfnmsub132ps',
+'vfnmsub213ps',
+'vfnmsub231ps',
+'vfnmsub132sd',
+'vfnmsub213sd',
+'vfnmsub231sd',
+'vfnmsub132ss',
+'vfnmsub213ss',
+'vfnmsub231ss'
 );

+ 1 - 1
compiler/i8086/i8086nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
-1828;
+1970;

+ 85 - 16
compiler/i8086/i8086op.inc

@@ -161,10 +161,8 @@ A_INVLPG,
 A_IRET,
 A_IRETD,
 A_IRETW,
-A_IRETQ,
 A_JCXZ,
 A_JECXZ,
-A_JRCXZ,
 A_JMP,
 A_LAHF,
 A_LAR,
@@ -200,7 +198,6 @@ A_MOVD,
 A_MOVQ,
 A_MOVSB,
 A_MOVSD,
-A_MOVSQ,
 A_MOVSW,
 A_MOVSX,
 A_MOVZX,
@@ -272,7 +269,6 @@ A_POPAW,
 A_POPF,
 A_POPFD,
 A_POPFW,
-A_POPFQ,
 A_POR,
 A_PREFETCH,
 A_PREFETCHW,
@@ -306,7 +302,6 @@ A_PUSHAW,
 A_PUSHF,
 A_PUSHFD,
 A_PUSHFW,
-A_PUSHFQ,
 A_PXOR,
 A_RCL,
 A_RCR,
@@ -334,7 +329,6 @@ A_SAR,
 A_SBB,
 A_SCASB,
 A_SCASD,
-A_SCASQ,
 A_SCASW,
 A_SEGCS,
 A_SEGDS,
@@ -596,10 +590,6 @@ A_XSHA1,
 A_XSHA256,
 A_DMINT,
 A_RDM,
-A_MOVABS,
-A_MOVSXD,
-A_CQO,
-A_CMPXCHG16B,
 A_MOVNTSS,
 A_MOVNTSD,
 A_INSERTQ,
@@ -637,11 +627,9 @@ A_PBLENDW,
 A_PCMPEQQ,
 A_PEXTRB,
 A_PEXTRD,
-A_PEXTRQ,
 A_PHMINPOSUW,
 A_PINSRB,
 A_PINSRD,
-A_PINSRQ,
 A_PMAXSB,
 A_PMAXSD,
 A_PMAXUD,
@@ -682,9 +670,6 @@ A_AESDEC,
 A_AESDECLAST,
 A_AESIMC,
 A_AESKEYGENASSIST,
-A_STOSQ,
-A_LODSQ,
-A_CMPSQ,
 A_VADDPD,
 A_VADDPS,
 A_VADDSD,
@@ -946,6 +931,7 @@ A_VZEROALL,
 A_VZEROUPPER,
 A_ANDN,
 A_BEXTR,
+A_TZCNT,
 A_RORX,
 A_SARX,
 A_SHLX,
@@ -969,5 +955,88 @@ A_VPSLLVD,
 A_VPSLLVQ,
 A_VPSRAVD,
 A_VPSRLVD,
-A_VPSRLVQ
+A_VPSRLVQ,
+A_VGATHERDPD,
+A_VGATHERDPS,
+A_VGATHERQPD,
+A_VGATHERQPS,
+A_VPGATHERDD,
+A_VPGATHERDQ,
+A_VPGATHERQD,
+A_VPGATHERQQ,
+A_ADD4S,
+A_BRKEM,
+A_CLR1,
+A_CMP4S,
+A_EXT,
+A_INS,
+A_NOT1,
+A_REPC,
+A_REPNC,
+A_ROL4,
+A_ROR4,
+A_SET1,
+A_SUB4S,
+A_TEST1,
+A_VFMADD132PD,
+A_VFMADD213PD,
+A_VFMADD231PD,
+A_VFMADDPD,
+A_VFMADD132PS,
+A_VFMADD213PS,
+A_VFMADD231PS,
+A_VFMADD132SD,
+A_VFMADD213SD,
+A_VFMADD231SD,
+A_VFMADD132SS,
+A_VFMADD213SS,
+A_VFMADD231SS,
+A_VFMADDSUB132PD,
+A_VFMADDSUB213PD,
+A_VFMADDSUB231PD,
+A_VFMADDSUB132PS,
+A_VFMADDSUB213PS,
+A_VFMADDSUB231PS,
+A_VFMSUBADD132PD,
+A_VFMSUBADD213PD,
+A_VFMSUBADD231PD,
+A_VFMSUBADD132PS,
+A_VFMSUBADD213PS,
+A_VFMSUBADD231PS,
+A_VFMSUB132PD,
+A_VFMSUB213PD,
+A_VFMSUB231PD,
+A_VFMSUB132PS,
+A_VFMSUB213PS,
+A_VFMSUB231PS,
+A_VFMSUB132SD,
+A_VFMSUB213SD,
+A_VFMSUB231SD,
+A_VFMSUB132SS,
+A_VFMSUB213SS,
+A_VFMSUB231SS,
+A_VFNMADD132PD,
+A_VFNMADD213PD,
+A_VFNMADD231PD,
+A_VFNMADD132PS,
+A_VFNMADD213PS,
+A_VFNMADD231PS,
+A_VFNMADD132SD,
+A_VFNMADD213SD,
+A_VFNMADD231SD,
+A_VFNMADD132SS,
+A_VFNMADD213SS,
+A_VFNMADD231SS,
+A_VFNMSUB132PD,
+A_VFNMSUB213PD,
+A_VFNMSUB231PD,
+A_VFNMSUB132PS,
+A_VFNMSUB213PS,
+A_VFNMSUB231PS,
+A_VFNMSUB132SD,
+A_VFNMSUB213SD,
+A_VFNMSUB231SD,
+A_VFNMSUB132SS,
+A_VFNMSUB213SS,
+A_VFNMSUB231SS
 );

+ 148 - 79
compiler/i8086/i8086prop.inc

@@ -161,8 +161,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_RECX, Ch_None, Ch_None)),
 (Ch: (Ch_RECX, Ch_None, Ch_None)),
 (Ch: (Ch_RECX, Ch_None, Ch_None)),
 (Ch: (Ch_ROp1, Ch_None, Ch_None)),
@@ -201,7 +199,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
@@ -224,8 +221,8 @@
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -272,7 +269,6 @@
 (Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_WFLAGS, Ch_None)),
-(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -306,7 +302,6 @@
 (Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_RFLAGS, Ch_None)),
-(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
@@ -335,7 +330,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_None, Ch_None, Ch_None)),
 (Ch: (Ch_None, Ch_None, Ch_None)),
 (Ch: (Ch_None, Ch_None, Ch_None)),
@@ -389,7 +383,7 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_ROp1, Ch_WOp2, Ch_RFLAGS)),
+(Ch: (Ch_ROp1, Ch_RWOp2, Ch_RFLAGS)),
 (Ch: (Ch_RFLAGS, Ch_None, Ch_None)),
 (Ch: (Ch_RFLAGS, Ch_WOp1, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
@@ -489,8 +483,8 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -570,6 +564,7 @@
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -596,13 +591,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
-(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
-(Ch: (Ch_MRAX, Ch_WRDX, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -682,9 +670,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_RRAX, Ch_WMemEDI, Ch_RWRDI)),
-(Ch: (Ch_WRAX, Ch_RWRSI, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
@@ -730,6 +715,10 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -753,6 +742,12 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -761,28 +756,20 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
@@ -796,7 +783,15 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -859,6 +854,14 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -867,6 +870,24 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -876,15 +897,26 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -893,8 +925,17 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -925,49 +966,77 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_Mop1, Ch_RWEAX, Ch_None)),
+(Ch: (Ch_Mop1, Ch_RWEAX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_None)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None))
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1))
 );

+ 1003 - 9
compiler/i8086/i8086tab.inc

@@ -2649,17 +2649,10 @@
   (
     opcode  : A_LEA;
     ops     : 2;
-    optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
-    code    : #208#1#141#72;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+    code    : #193#208#1#141#72;
     flags   : if_8086
   ),
-  (
-    opcode  : A_LEA;
-    ops     : 2;
-    optypes : (ot_reg32 or ot_bits64,ot_immediate,ot_none,ot_none);
-    code    : #208#1#141#72;
-    flags   : if_8086 or if_sd
-  ),
   (
     opcode  : A_LEAVE;
     ops     : 0;
@@ -12460,6 +12453,13 @@
     code    : #242#249#1#247#62#72;
     flags   : if_bmi1
   ),
+  (
+    opcode  : A_TZCNT;
+    ops     : 2;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+    code    : #208#219#2#15#188#72;
+    flags   : if_bmi1 or if_sm
+  ),
   (
     opcode  : A_RORX;
     ops     : 3;
@@ -12795,5 +12795,999 @@
     optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
     code    : #241#242#243#249#1#69#61#80;
     flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_xmem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem32,ot_ymmreg,ot_none);
+    code    : #241#242#244#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_ymem32,ot_xmmreg,ot_none);
+    code    : #241#242#244#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem32,ot_ymmreg,ot_none);
+    code    : #241#242#244#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDQ;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_xmem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_ymem32,ot_xmmreg,ot_none);
+    code    : #241#242#244#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQQ;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_ADD4S;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15#32;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_BRKEM;
+    ops     : 1;
+    optypes : (ot_immediate,ot_none,ot_none,ot_none);
+    code    : #2#15#255#20;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_CLR1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#18#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_CLR1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#19#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_CLR1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+    code    : #2#15#26#128#21;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_CLR1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+    code    : #2#15#27#128#21;
+    flags   : if_nec or if_sw or if_16bitonly
+  ),
+  (
+    opcode  : A_CMP4S;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15#38;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_EXT;
+    ops     : 2;
+    optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+    code    : #2#15#51#65;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_EXT;
+    ops     : 2;
+    optypes : (ot_reg8,ot_immediate,ot_none,ot_none);
+    code    : #2#15#59#128#21;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+    code    : #2#15#49#65;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_reg8,ot_immediate,ot_none,ot_none);
+    code    : #2#15#57#128#21;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_NOT1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#22#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_NOT1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#23#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_NOT1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+    code    : #2#15#30#128#21;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_NOT1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+    code    : #2#15#31#128#21;
+    flags   : if_nec or if_sw or if_16bitonly
+  ),
+  (
+    opcode  : A_REPC;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none);
+    code    : #1#101;
+    flags   : if_nec or if_pre or if_16bitonly
+  ),
+  (
+    opcode  : A_REPNC;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none);
+    code    : #1#100;
+    flags   : if_nec or if_pre or if_16bitonly
+  ),
+  (
+    opcode  : A_ROL4;
+    ops     : 1;
+    optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #2#15#40#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_ROR4;
+    ops     : 1;
+    optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #2#15#42#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_SET1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#20#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_SET1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#21#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_SET1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+    code    : #2#15#28#128#21;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_SET1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+    code    : #2#15#29#128#21;
+    flags   : if_nec or if_sw or if_16bitonly
+  ),
+  (
+    opcode  : A_SUB4S;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15#34;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_TEST1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#16#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_TEST1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_reg_cl,ot_none,ot_none);
+    code    : #2#15#17#128;
+    flags   : if_nec or if_16bitonly
+  ),
+  (
+    opcode  : A_TEST1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+    code    : #2#15#24#128#21;
+    flags   : if_nec or if_sb or if_16bitonly
+  ),
+  (
+    opcode  : A_TEST1;
+    ops     : 2;
+    optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+    code    : #2#15#25#128#21;
+    flags   : if_nec or if_sw or if_16bitonly
+  ),
+  (
+    opcode  : A_VFMADD132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDPD;
+    ops     : 4;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_xmmreg);
+    code    : #241#242#250#1#105#61#80#247;
+    flags   : if_fma4
+  ),
+  (
+    opcode  : A_VFMADDPD;
+    ops     : 4;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmreg,ot_xmmrm);
+    code    : #241#242#250#243#1#105#61#88#246;
+    flags   : if_fma4
+  ),
+  (
+    opcode  : A_VFMADD132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#153#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#169#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#185#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#153#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#169#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#185#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#155#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#171#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#187#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#155#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#171#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#187#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#157#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#173#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#189#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#157#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#173#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#189#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#159#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#175#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#191#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#159#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#175#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#191#61#80;
+    flags   : if_fma
   )
 );

+ 370 - 16
compiler/i8086/n8086add.pas

@@ -33,11 +33,19 @@ interface
        { ti8086addnode }
 
        ti8086addnode = class(tx86addnode)
+         function simplify(forinline: boolean) : tnode;override;
          function use_generic_mul32to64: boolean; override;
+         function first_addpointer: tnode; override;
+         function first_addhugepointer: tnode;
+         function first_cmppointer: tnode; override;
+         function first_cmphugepointer: tnode;
+         function first_cmpfarpointer: tnode;
          procedure second_addordinal; override;
          procedure second_add64bit;override;
+         procedure second_addfarpointer;
          procedure second_cmp64bit;override;
          procedure second_cmp32bit;
+         procedure second_cmpfarpointer;
          procedure second_cmpordinal;override;
          procedure second_mul(unsigned: boolean);
        end;
@@ -46,14 +54,105 @@ interface
 
     uses
       globtype,systems,
-      cutils,verbose,globals,
-      symconst,symdef,paramgr,defutil,
+      cutils,verbose,globals,constexp,pass_1,
+      symconst,symdef,symtype,paramgr,defutil,
       aasmbase,aasmtai,aasmdata,aasmcpu,
       cgbase,procinfo,
-      ncon,nset,cgutils,tgobj,
+      ncal,ncon,nset,cgutils,tgobj,
       cga,ncgutil,cgobj,cg64f32,cgx86,
       hlcgobj;
 
+{*****************************************************************************
+                                simplify
+*****************************************************************************}
+
+    function ti8086addnode.simplify(forinline: boolean): tnode;
+      var
+        t    : tnode;
+        lt,rt: tnodetype;
+        rd,ld: tdef;
+        rv,lv,v: tconstexprint;
+      begin
+        { load easier access variables }
+        rd:=right.resultdef;
+        ld:=left.resultdef;
+        rt:=right.nodetype;
+        lt:=left.nodetype;
+
+        if (
+            (lt = pointerconstn) and is_farpointer(ld) and
+            is_constintnode(right) and
+            (nodetype in [addn,subn])
+           ) or
+           (
+            (rt = pointerconstn) and is_farpointer(rd) and
+            is_constintnode(left) and
+            (nodetype=addn)
+           ) then
+          begin
+            t:=nil;
+
+            { load values }
+            case lt of
+              ordconstn:
+                lv:=tordconstnode(left).value;
+              pointerconstn:
+                lv:=tpointerconstnode(left).value;
+              niln:
+                lv:=0;
+              else
+                internalerror(2002080202);
+            end;
+            case rt of
+              ordconstn:
+                rv:=tordconstnode(right).value;
+              pointerconstn:
+                rv:=tpointerconstnode(right).value;
+              niln:
+                rv:=0;
+              else
+                internalerror(2002080203);
+            end;
+
+            case nodetype of
+              addn:
+                begin
+                  v:=lv+rv;
+                  if lt=pointerconstn then
+                    t := cpointerconstnode.create((qword(lv) and $FFFF0000) or word(qword(v)),resultdef)
+                  else if rt=pointerconstn then
+                    t := cpointerconstnode.create((qword(rv) and $FFFF0000) or word(qword(v)),resultdef)
+                  else
+                    internalerror(2014040604);
+                end;
+              subn:
+                begin
+                  v:=lv-rv;
+                  if (lt=pointerconstn) then
+                    { pointer-pointer results in an integer }
+                    if (rt=pointerconstn) then
+                      begin
+                        if not(nf_has_pointerdiv in flags) then
+                          internalerror(2008030101);
+                        { todo: implement pointer-pointer as well }
+                        internalerror(2014040607);
+                        //t := cpointerconstnode.create(qword(v),resultdef);
+                      end
+                    else
+                      t := cpointerconstnode.create((qword(lv) and $FFFF0000) or word(qword(v)),resultdef)
+                  else
+                    internalerror(2014040606);
+                end;
+              else
+                internalerror(2014040605);
+            end;
+            result:=t;
+            exit;
+          end
+        else
+          Result:=inherited simplify(forinline);
+      end;
+
 {*****************************************************************************
                                 use_generic_mul32to64
 *****************************************************************************}
@@ -72,6 +171,8 @@ interface
                 not(is_signed(right.resultdef));
       if nodetype=muln then
         second_mul(unsigned)
+      else if is_farpointer(left.resultdef) xor is_farpointer(right.resultdef) then
+        second_addfarpointer
       else
         inherited second_addordinal;
     end;
@@ -213,6 +314,208 @@ interface
       end;
 
 
+    function ti8086addnode.first_addpointer: tnode;
+      begin
+        if is_hugepointer(left.resultdef) or is_hugepointer(right.resultdef) then
+          result:=first_addhugepointer
+        else
+          result:=inherited;
+      end;
+
+
+    function ti8086addnode.first_addhugepointer: tnode;
+      var
+        procname:string;
+      begin
+        result:=nil;
+
+        if (nodetype=subn) and is_hugepointer(left.resultdef) and is_hugepointer(right.resultdef) then
+          procname:='fpc_hugeptr_sub_hugeptr'
+        else
+          begin
+            case nodetype of
+              addn:
+                procname:='fpc_hugeptr_add_longint';
+              subn:
+                procname:='fpc_hugeptr_sub_longint';
+              else
+                internalerror(2014070301);
+            end;
+
+            if cs_hugeptr_arithmetic_normalization in current_settings.localswitches then
+              procname:=procname+'_normalized';
+          end;
+
+        if is_hugepointer(left.resultdef) then
+          result := ccallnode.createintern(procname,
+            ccallparanode.create(right,
+            ccallparanode.create(left,nil)))
+        else
+          result := ccallnode.createintern(procname,
+            ccallparanode.create(left,
+            ccallparanode.create(right,nil)));
+        left := nil;
+        right := nil;
+        firstpass(result);
+      end;
+
+
+    function ti8086addnode.first_cmppointer: tnode;
+      begin
+        if is_hugepointer(left.resultdef) or is_hugepointer(right.resultdef) then
+          result:=first_cmphugepointer
+        else if is_farpointer(left.resultdef) or is_farpointer(right.resultdef) then
+          result:=first_cmpfarpointer
+        else
+          result:=inherited;
+      end;
+
+
+    function ti8086addnode.first_cmphugepointer: tnode;
+      var
+        procname:string;
+      begin
+        result:=nil;
+
+        if not (cs_hugeptr_comparison_normalization in current_settings.localswitches) then
+          begin
+            expectloc:=LOC_JUMP;
+            exit;
+          end;
+
+        case nodetype of
+          equaln:
+            procname:='fpc_hugeptr_cmp_normalized_e';
+          unequaln:
+            procname:='fpc_hugeptr_cmp_normalized_ne';
+          ltn:
+            procname:='fpc_hugeptr_cmp_normalized_b';
+          lten:
+            procname:='fpc_hugeptr_cmp_normalized_be';
+          gtn:
+            procname:='fpc_hugeptr_cmp_normalized_a';
+          gten:
+            procname:='fpc_hugeptr_cmp_normalized_ae';
+          else
+            internalerror(2014070401);
+        end;
+
+        result := ccallnode.createintern(procname,
+          ccallparanode.create(right,
+          ccallparanode.create(left,nil)));
+        left := nil;
+        right := nil;
+        firstpass(result);
+      end;
+
+
+    function ti8086addnode.first_cmpfarpointer: tnode;
+      begin
+        { = and <> are handled as a 32-bit comparison }
+        if nodetype in [equaln,unequaln] then
+          begin
+            result:=nil;
+            expectloc:=LOC_JUMP;
+          end
+        else
+          begin
+            result:=nil;
+            expectloc:=LOC_FLAGS;
+          end;
+      end;
+
+
+    procedure ti8086addnode.second_addfarpointer;
+      var
+        tmpreg : tregister;
+        pointernode: tnode;
+      begin
+        pass_left_right;
+        force_reg_left_right(false,true);
+        set_result_location_reg;
+
+        if (left.resultdef.typ=pointerdef) and (right.resultdef.typ<>pointerdef) then
+          pointernode:=left
+        else if (left.resultdef.typ<>pointerdef) and (right.resultdef.typ=pointerdef) then
+          pointernode:=right
+        else
+          internalerror(2014040601);
+
+        if not (nodetype in [addn,subn]) then
+          internalerror(2014040602);
+
+        if nodetype=addn then
+          begin
+            if (right.location.loc<>LOC_CONSTANT) then
+              begin
+                cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_16,
+                   left.location.register,right.location.register,location.register);
+                cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,
+                   GetNextReg(pointernode.location.register),GetNextReg(location.register));
+              end
+            else
+              begin
+                if pointernode=left then
+                  begin
+                    { farptr_reg + int_const }
+                    cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_16,
+                       right.location.value,left.location.register,location.register);
+                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,
+                       GetNextReg(left.location.register),GetNextReg(location.register));
+                  end
+                else
+                  begin
+                    { int_reg + farptr_const }
+                    tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+                    hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef,
+                      right.location.value,tmpreg);
+                    cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_16,
+                      left.location.register,tmpreg,location.register);
+                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,
+                       GetNextReg(tmpreg),GetNextReg(location.register));
+                  end;
+              end;
+          end
+        else  { subtract is a special case since its not commutative }
+          begin
+            if (nf_swapped in flags) then
+              swapleftright;
+            { left can only be a pointer in this case, since (int-pointer) is not supported }
+            if pointernode<>left then
+              internalerror(2014040603);
+            if left.location.loc<>LOC_CONSTANT then
+              begin
+                if right.location.loc<>LOC_CONSTANT then
+                  begin
+                    cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_16,
+                        right.location.register,left.location.register,location.register);
+                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,
+                       GetNextReg(pointernode.location.register),GetNextReg(location.register));
+                  end
+                else
+                  begin
+                    { farptr_reg - int_const }
+                    cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_16,
+                       right.location.value,left.location.register,location.register);
+                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,
+                       GetNextReg(left.location.register),GetNextReg(location.register));
+                  end;
+              end
+            else
+              begin
+                { farptr_const - int_reg }
+                tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+                hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef,
+                  left.location.value,tmpreg);
+                cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_16,
+                  right.location.register,tmpreg,location.register);
+                cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,
+                   GetNextReg(tmpreg),GetNextReg(location.register));
+              end;
+          end;
+      end;
+
+
     procedure ti8086addnode.second_cmp64bit;
       var
         hregister,
@@ -508,7 +811,8 @@ interface
         unsigned:=((left.resultdef.typ=orddef) and
                    (torddef(left.resultdef).ordtype=u32bit)) or
                   ((right.resultdef.typ=orddef) and
-                   (torddef(right.resultdef).ordtype=u32bit));
+                   (torddef(right.resultdef).ordtype=u32bit)) or
+                  is_hugepointer(left.resultdef);
 
         { left and right no register?  }
         { then one must be demanded    }
@@ -581,9 +885,60 @@ interface
         location_reset(location,LOC_JUMP,OS_NO)
       end;
 
+
+    procedure ti8086addnode.second_cmpfarpointer;
+      begin
+        { handle = and <> as a 32-bit comparison }
+        if nodetype in [equaln,unequaln] then
+          begin
+            second_cmp32bit;
+            exit;
+          end;
+
+        pass_left_right;
+
+        { <, >, <= and >= compare the 16-bit offset only }
+        if (right.location.loc=LOC_CONSTANT) and
+           (left.location.loc in [LOC_REFERENCE, LOC_CREFERENCE])
+        then
+          begin
+            emit_const_ref(A_CMP, S_W, word(right.location.value), left.location.reference);
+            location_freetemp(current_asmdata.CurrAsmList,left.location);
+          end
+        else
+          begin
+            { left location is not a register? }
+            if left.location.loc<>LOC_REGISTER then
+             begin
+               { if right is register then we can swap the locations }
+               if right.location.loc=LOC_REGISTER then
+                begin
+                  location_swap(left.location,right.location);
+                  toggleflag(nf_swapped);
+                end
+               else
+                begin
+                  { maybe we can reuse a constant register when the
+                    operation is a comparison that doesn't change the
+                    value of the register }
+                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,u16inttype,true);
+                end;
+              end;
+
+            emit_generic_code(A_CMP,OS_16,true,false,false);
+            location_freetemp(current_asmdata.CurrAsmList,right.location);
+            location_freetemp(current_asmdata.CurrAsmList,left.location);
+          end;
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(true);
+      end;
+
+
     procedure ti8086addnode.second_cmpordinal;
       begin
-        if is_32bit(left.resultdef) or is_farpointer(left.resultdef) or is_hugepointer(left.resultdef) then
+        if is_farpointer(left.resultdef) then
+          second_cmpfarpointer
+        else if is_32bit(left.resultdef) or is_hugepointer(left.resultdef) then
           second_cmp32bit
         else
           inherited second_cmpordinal;
@@ -596,15 +951,6 @@ interface
 
     procedure ti8086addnode.second_mul(unsigned: boolean);
 
-      procedure add_mov(instr: Taicpu);
-        begin
-          { Notify the register allocator that we have written a move instruction so
-            it can try to eliminate it. }
-          if (instr.oper[0]^.reg<>current_procinfo.framepointer) and (instr.oper[0]^.reg<>NR_STACK_POINTER_REG) then
-            tcgx86(cg).add_move_instruction(instr);
-          current_asmdata.CurrAsmList.concat(instr);
-        end;
-
     var reg:Tregister;
         ref:Treference;
         use_ref:boolean;
@@ -616,6 +962,13 @@ interface
     begin
       pass_left_right;
 
+      { MUL is faster than IMUL on the 8086 & 8088 (and equal in speed on 286+),
+        but it's only safe to use in place of IMUL when overflow checking is off
+        and we're doing a 16-bit>16-bit multiplication }
+      if not (cs_check_overflow in current_settings.localswitches) and
+        (not is_32bitint(resultdef)) then
+        unsigned:=true;
+
       {The location.register will be filled in later (JM)}
       location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
       { Mul supports registers and references, so if not register/reference,
@@ -661,8 +1014,9 @@ interface
         {Allocate an imaginary 32-bit register, which consists of a pair of
          16-bit registers and store DX:AX into it}
         location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-        add_mov(Taicpu.Op_reg_reg(A_MOV,S_W,NR_AX,location.register));
-        add_mov(Taicpu.Op_reg_reg(A_MOV,S_W,NR_DX,GetNextReg(location.register)));
+        cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_DX,GetNextReg(location.register));
+        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_AX);
+        cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_AX,location.register);
       end
       else
       begin

+ 35 - 4
compiler/i8086/n8086cal.pas

@@ -28,13 +28,15 @@ interface
 { $define AnsiStrRef}
 
     uses
-      nx86cal;
+      nx86cal,cgutils;
 
     type
        ti8086callnode = class(tx86callnode)
        protected
           procedure pop_parasize(pop_size:longint);override;
           procedure extra_interrupt_code;override;
+          procedure extra_call_ref_code(var ref: treference);override;
+          procedure do_call_ref(ref: treference);override;
        end;
 
 
@@ -43,11 +45,11 @@ implementation
     uses
       globtype,systems,
       cutils,verbose,globals,
-      cgbase,cgutils,
+      cgbase,
       cpubase,paramgr,
       aasmtai,aasmdata,aasmcpu,
       ncal,nbas,nmem,nld,ncnv,
-      cga,cgobj,cpuinfo;
+      cga,cgobj,cgx86,cpuinfo;
 
 
 {*****************************************************************************
@@ -58,7 +60,8 @@ implementation
     procedure ti8086callnode.extra_interrupt_code;
       begin
         emit_none(A_PUSHF,S_W);
-        emit_reg(A_PUSH,S_W,NR_CS);
+        if current_settings.x86memorymodel in x86_near_code_models then
+          emit_reg(A_PUSH,S_W,NR_CS);
       end;
 
 
@@ -92,6 +95,34 @@ implementation
       end;
 
 
+    procedure ti8086callnode.extra_call_ref_code(var ref: treference);
+      begin
+        if (ref.base<>NR_NO) and (ref.base<>NR_BP) then
+          begin
+            cg.getcpuregister(current_asmdata.CurrAsmList,NR_BX);
+            cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,ref.base,NR_BX);
+            ref.base:=NR_BX;
+            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_BX);
+          end;
+        if ref.index<>NR_NO then
+          begin
+            cg.getcpuregister(current_asmdata.CurrAsmList,NR_SI);
+            cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_16,OS_16,ref.index,NR_SI);
+            ref.index:=NR_SI;
+            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_SI);
+          end;
+      end;
+
+
+    procedure ti8086callnode.do_call_ref(ref: treference);
+      begin
+        if current_settings.x86memorymodel in x86_far_code_models then
+          current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_CALL,S_FAR,ref))
+        else
+          current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_CALL,S_NO,ref));
+      end;
+
+
 begin
    ccallnode:=ti8086callnode;
 end.

+ 18 - 104
compiler/i8086/n8086cnv.pas

@@ -29,10 +29,13 @@ interface
       node,ncgcnv,nx86cnv,defutil,defcmp;
 
     type
+
+       { t8086typeconvnode }
+
        t8086typeconvnode = class(tx86typeconvnode)
        protected
+         function typecheck_proc_to_procvar: tnode;override;
          procedure second_proc_to_procvar;override;
-         procedure second_nil_to_methodprocvar;override;
        end;
 
 
@@ -41,120 +44,31 @@ implementation
    uses
       verbose,systems,globals,globtype,
       aasmbase,aasmtai,aasmdata,aasmcpu,
-      symconst,symdef,
+      symconst,symdef,symcpu,
       cgbase,cga,procinfo,pass_1,pass_2,
       ncon,ncal,ncnv,
       cpubase,cpuinfo,
       cgutils,cgobj,hlcgobj,cgx86,ncgutil,
       tgobj;
 
-
-    procedure t8086typeconvnode.second_proc_to_procvar;
-      var
-        tmpreg: tregister;
-        tmpref: treference;
+    function t8086typeconvnode.typecheck_proc_to_procvar: tnode;
       begin
-        if not (po_far in tabstractprocdef(resultdef).procoptions) then
-          begin
-            inherited;
-            exit;
-          end;
-
-        if tabstractprocdef(resultdef).is_addressonly then
-          begin
-            location_reset(location,LOC_REGISTER,OS_32);
-            { only a code pointer? (when taking the address of classtype.method
-              we also only get a code pointer even though the resultdef is a
-              procedure of object, and hence is_addressonly would return false)
-             }
-  	    if left.location.size = OS_32 then
-              begin
-                case left.location.loc of
-                  LOC_REFERENCE,LOC_CREFERENCE:
-                    begin
-                      { the procedure symbol is encoded in reference.symbol -> take address }
-                      location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                      cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
-                      tmpref:=left.location.reference;
-                      tmpref.refaddr:=addr_seg;
-                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,tmpref,GetNextReg(location.register));
-                    end;
-                  else
-                    internalerror(2013031501)
-                end;
-              end
-            else
-              begin
-                { conversion from a procedure of object/nested procvar to plain procvar }
-                case left.location.loc of
-                  LOC_REFERENCE,LOC_CREFERENCE:
-                    begin
-                      location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                      { code field is the first one }
-                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,location.register);
-                    end;
-                  LOC_REGISTER,LOC_CREGISTER:
-                    begin
-                      if target_info.endian=endian_little then
-                        location.register:=left.location.register
-                      else
-                        location.register:=left.location.registerhi;
-                    end;
-                  else
-                    internalerror(2013031502)
-                end;
-              end;
-          end
-        else
-          begin
-            { TODO: update for far procs }
-            if not tabstractprocdef(left.resultdef).is_addressonly then
-              location_copy(location,left.location)
-            else
-              begin
-                { assigning a global function to a nested procvar -> create
-                  tmethodpointer record and set the "frame pointer" to nil }
-                if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
-                  internalerror(2013031503);
-                location_reset_ref(location,LOC_REFERENCE,int_cgsize(sizeof(pint)*2),sizeof(pint));
-                tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,location.reference);
-                tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,tmpreg);
-                cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,location.reference);
-                { setting the frame pointer to nil is not strictly necessary
-                  since the global procedure won't use it, but it can help with
-                  debugging }
-                inc(location.reference.offset,sizeof(pint));
-                cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_ADDR,0,location.reference);
-                dec(location.reference.offset,sizeof(pint));
-              end;
-          end;
+        if (current_settings.x86memorymodel in x86_far_code_models) and
+          not is_proc_far(tabstractprocdef(left.resultdef)) then
+          CGMessage1(type_e_procedure_must_be_far,left.resultdef.GetTypeName);
+        Result:=inherited typecheck_proc_to_procvar;
       end;
 
 
-    procedure t8086typeconvnode.second_nil_to_methodprocvar;
+    procedure t8086typeconvnode.second_proc_to_procvar;
       begin
-        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
-        if current_settings.x86memorymodel in x86_far_data_models then
-          begin
-            location.registerhi:=cg.getintregister(current_asmdata.currasmlist,OS_32);
-            cg.a_load_const_reg(current_asmdata.currasmlist,OS_32,0,location.registerhi);
-          end
-        else
-          begin
-            location.registerhi:=cg.getaddressregister(current_asmdata.currasmlist);
-            cg.a_load_const_reg(current_asmdata.currasmlist,OS_ADDR,0,location.registerhi);
-          end;
-        if (resultdef.typ=procvardef) and (po_far in tprocvardef(resultdef).procoptions) then
-          begin
-            location.register:=cg.getintregister(current_asmdata.currasmlist,OS_32);
-            cg.a_load_const_reg(current_asmdata.currasmlist,OS_32,0,location.register);
-          end
-        else
-          begin
-            location.register:=cg.getaddressregister(current_asmdata.currasmlist);
-            cg.a_load_const_reg(current_asmdata.currasmlist,OS_ADDR,0,location.register);
-          end;
+        if is_proc_far(tabstractprocdef(resultdef))<>
+           (current_settings.x86memorymodel in x86_far_code_models) then
+          internalerror(2014041302);
+        if is_proc_far(tabstractprocdef(left.resultdef))<>
+           (current_settings.x86memorymodel in x86_far_code_models) then
+          internalerror(2014041303);
+        inherited;
       end;
 
 

+ 16 - 5
compiler/i8086/n8086con.pas

@@ -26,21 +26,22 @@ unit n8086con;
 interface
 
     uses
-       node,ncon,ncgcon,nx86con;
+       globtype,symtype,ncon,ncgcon,nx86con;
 
     type
 
-      { tcgpointerconstnode }
+      { ti8086pointerconstnode }
 
       ti8086pointerconstnode = class(tcgpointerconstnode)
+        constructor create(v : TConstPtrUInt;def:tdef);override;
         procedure pass_generate_code;override;
       end;
 
 implementation
 
     uses
-      systems,globals,globtype,
-      symconst,symdef,
+      systems,globals,
+      symconst,symdef,symcpu,
       defutil,
       cpubase,
       cga,cgx86,cgobj,cgbase,cgutils;
@@ -49,10 +50,20 @@ implementation
                                T8086POINTERCONSTNODE
     *****************************************************************************}
 
+
+    constructor ti8086pointerconstnode.create(v: TConstPtrUInt; def: tdef);
+      begin
+        { truncate near pointers }
+        if (def.typ<>pointerdef) or not (tcpupointerdef(def).x86pointertyp in [x86pt_far,x86pt_huge]) then
+          v := Word(v);
+        inherited create(v, def);
+      end;
+
+
     procedure ti8086pointerconstnode.pass_generate_code;
       begin
         { far pointer? }
-        if (typedef.typ=pointerdef) and (tpointerdef(typedef).x86pointertyp in [x86pt_far,x86pt_huge]) then
+        if (typedef.typ=pointerdef) and (tcpupointerdef(typedef).x86pointertyp in [x86pt_far,x86pt_huge]) then
           begin
             location_reset(location,LOC_CONSTANT,OS_32);
             location.value:=longint(value);

+ 138 - 4
compiler/i8086/n8086inl.pas

@@ -36,6 +36,8 @@ interface
          function typecheck_seg: tnode; override;
          function first_seg: tnode; override;
          procedure second_seg; override;
+         procedure second_get_frame;override;
+         procedure second_incdec;override;
        end;
 
 implementation
@@ -45,6 +47,7 @@ implementation
     systems,
     globtype,globals,
     cutils,verbose,
+    constexp,
     symconst,
     defutil,
     aasmbase,aasmtai,aasmdata,aasmcpu,
@@ -54,12 +57,19 @@ implementation
     nbas,ncon,ncal,ncnv,nld,ncgutil,
     tgobj,
     cga,cgutils,cgx86,cgobj,hlcgobj,
-    htypechk;
+    htypechk,procinfo;
 
      function ti8086inlinenode.typecheck_seg: tnode;
        begin
          result := nil;
          resultdef:=u16inttype;
+
+         { don't allow constants }
+         if is_constnode(left) then
+          begin
+            CGMessagePos(left.fileinfo,type_e_no_addr_of_constant);
+            exit;
+          end;
        end;
 
      function ti8086inlinenode.first_seg: tnode;
@@ -69,10 +79,134 @@ implementation
        end;
 
      procedure ti8086inlinenode.second_seg;
+       var
+         segref: treference;
+       begin
+         secondpass(left);
+
+         if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+           internalerror(2013040101);
+
+         { if a segment register is specified in ref, we use that }
+         if left.location.reference.segment<>NR_NO then
+           begin
+             location_reset(location,LOC_REGISTER,OS_16);
+             if is_segment_reg(left.location.reference.segment) then
+               begin
+                 location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
+                 current_asmdata.CurrAsmList.Concat(Taicpu.op_reg_reg(A_MOV,S_W,left.location.reference.segment,location.register));
+               end
+             else
+               location.register:=left.location.reference.segment;
+           end
+         { references relative to a symbol use the segment of the symbol,
+           which can be obtained by the SEG directive }
+         else if assigned(left.location.reference.symbol) then
+           begin
+             location_reset(location,LOC_REGISTER,OS_16);
+             location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
+             reference_reset_symbol(segref,left.location.reference.symbol,0,0);
+             segref.refaddr:=addr_seg;
+             cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,segref,location.register);
+           end
+         else if left.location.reference.base=NR_BP then
+           begin
+             location_reset(location,LOC_REGISTER,OS_16);
+             location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
+             current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_SS,location.register));
+           end
+         else
+           begin
+             location_reset(location,LOC_REGISTER,OS_16);
+             location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
+             current_asmdata.CurrAsmList.Concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_DS,location.register));
+           end;
+       end;
+
+     procedure ti8086inlinenode.second_get_frame;
+       begin
+         if current_settings.x86memorymodel in x86_far_data_models then
+           begin
+             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+               internalerror(2014030201);
+             location_reset(location,LOC_REGISTER,OS_32);
+             location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+             emit_reg_reg(A_MOV,S_W,current_procinfo.framepointer,location.register);
+             current_asmdata.CurrAsmList.Concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_SS,GetNextReg(location.register)));
+           end
+         else
+           inherited second_get_frame;
+       end;
+
+     procedure ti8086inlinenode.second_incdec;
+       const
+         addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
+       var
+         addvalue : TConstExprInt;
+         addconstant : boolean;
+         hregister : tregister;
+         tmploc: tlocation;
        begin
-         location_reset(location,LOC_REGISTER,OS_16);
-         location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
-         current_asmdata.CurrAsmList.Concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_DS,location.register));
+         if is_farpointer(tcallparanode(left).left.resultdef) then
+           begin
+             { set defaults }
+             addconstant:=true;
+             hregister:=NR_NO;
+
+             { first secondpass second argument, because if the first arg }
+             { is used in that expression then SSL may move it to another }
+             { register                                                   }
+             if assigned(tcallparanode(left).right) then
+               secondpass(tcallparanode(tcallparanode(left).right).left);
+             { load first parameter, must be a reference }
+             secondpass(tcallparanode(left).left);
+             tmploc:=tcallparanode(left).left.location;
+             tmploc.size:=OS_S16;
+             { get addvalue }
+             case tcallparanode(left).left.resultdef.typ of
+               pointerdef :
+                 begin
+                   if is_void(tpointerdef(tcallparanode(left).left.resultdef).pointeddef) then
+                     addvalue:=1
+                   else
+                     addvalue:=tpointerdef(tcallparanode(left).left.resultdef).pointeddef.size;
+                 end;
+               else
+                 internalerror(10081);
+             end;
+             { second_ argument specified?, must be a s16bit in register }
+             if assigned(tcallparanode(left).right) then
+               begin
+                 { when constant, just multiply the addvalue }
+                 if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
+                    addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
+                 else if is_constpointernode(tcallparanode(tcallparanode(left).right).left) then
+                    addvalue:=addvalue*tpointerconstnode(tcallparanode(tcallparanode(left).right).left).value
+                 else
+                   begin
+                     hlcg.location_force_reg(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.location,tcallparanode(tcallparanode(left).right).left.resultdef,s16inttype,addvalue<=1);
+                     hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
+                     { insert multiply with addvalue if its >1 }
+                     if addvalue>1 then
+                       hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,s16inttype,addvalue.svalue,hregister);
+                     addconstant:=false;
+                   end;
+               end;
+             { write the add instruction }
+             if addconstant then
+               begin
+                 hlcg.a_op_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],s16inttype,
+                   smallint(addvalue.svalue),
+                   tmploc);
+               end
+             else
+               begin
+                 hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],s16inttype,
+                   hregister,tmploc);
+               end;
+           end
+         else
+           inherited second_incdec;
        end;
 
 begin

+ 91 - 0
compiler/i8086/n8086ld.pas

@@ -0,0 +1,91 @@
+{
+    Copyright (c) 2002-2014 by Florian Klaempfl
+
+    Generate i8086 assembler for load nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n8086ld;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      globtype,
+      symsym,symtype,
+      node,ncgld;
+
+    type
+      ti8086loadnode = class(tcgloadnode)
+         procedure generate_nested_access(vs: tsym); override;
+         procedure generate_absaddr_access(vs: tabsolutevarsym); override;
+      end;
+
+
+implementation
+
+    uses
+      globals,aasmdata,
+      symcpu,
+      nld,
+      cgbase,cgobj,
+      cpubase,cpuinfo;
+
+{*****************************************************************************
+                            TI8086LOADNODE
+*****************************************************************************}
+
+    procedure ti8086loadnode.generate_nested_access(vs: tsym);
+      begin
+        inherited;
+
+        { the parentfp pointer is always a near pointer (this is turbo pascal
+          compatible) regardless of memory model, so we need to set the segment
+          manually.
+
+          todo: once the far data memory models are fully implemented, the
+          parentfp type should be changed to a near 'ss' pointer in all memory
+          models and then this code can be removed. But this can only happen
+          after:
+          1) all calls to a_loadaddr_ref_reg go through the high level code
+             generator
+          2) a_loadaddr_ref_reg in the low level code generator stops using
+             the presence of a segment in the source reference to determine the
+             destination reg size
+          3) make_simple_ref is updated to remove unnecessary segment prefixes
+          4) hlcg.reference_reset_base is updated to set the segment on near_ss
+             pointers }
+        if (left.nodetype=loadparentfpn) and
+           (current_settings.x86memorymodel in x86_far_data_models) then
+          location.reference.segment:=NR_SS;
+      end;
+
+    procedure ti8086loadnode.generate_absaddr_access(vs: tabsolutevarsym);
+      begin
+        if tcpuabsolutevarsym(symtableentry).absseg then
+          begin
+            location.reference.segment:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
+            cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_16,aint(tcpuabsolutevarsym(symtableentry).addrsegment),location.reference.segment);
+          end;
+        inherited;
+      end;
+
+
+begin
+   cloadnode:=ti8086loadnode;
+end.

+ 121 - 100
compiler/i8086/n8086mat.pas

@@ -30,6 +30,8 @@ interface
 
     type
       ti8086moddivnode = class(tmoddivnode)
+         function use_moddiv32bit_helper: boolean;
+         function first_moddivint: tnode; override;
          procedure pass_generate_code;override;
       end;
 
@@ -61,7 +63,26 @@ implementation
                              ti8086moddivnode
 *****************************************************************************}
 
-    function log2(i : dword) : dword;
+
+    function ti8086moddivnode.use_moddiv32bit_helper: boolean;
+      begin
+        result:=is_32bit(left.resultdef) or
+                is_64bit(left.resultdef) or
+                is_32bit(right.resultdef) or
+                is_64bit(right.resultdef);
+      end;
+
+
+    function ti8086moddivnode.first_moddivint: tnode;
+      begin
+        if use_moddiv32bit_helper then
+          result:=inherited first_moddivint
+        else
+          result:=nil;
+      end;
+
+
+    function log2(i : word) : word;
       begin
         result:=0;
         i:=i shr 1;
@@ -79,9 +100,9 @@ implementation
         power:longint;
         hl:Tasmlabel;
         op:Tasmop;
-        e : longint;
-        d,l,r,s,m,a,n,t : dword;
-        m_low,m_high,j,k : qword;
+        e : smallint;
+        d,l,r,s,m,a,n,t : word;
+        m_low,m_high,j,k : dword;
       begin
         secondpass(left);
         if codegenerror then
@@ -90,7 +111,7 @@ implementation
         if codegenerror then
           exit;
 
-        if is_64bitint(resultdef) then
+        if is_64bitint(resultdef) or is_32bitint(resultdef) then
           { should be handled in pass_1 (JM) }
           internalerror(200109052);
         { put numerator in register }
@@ -107,39 +128,39 @@ implementation
                   "Cardinal($ffffffff) div 16" overflows! (JM) }
                 if is_signed(left.resultdef) Then
                   begin
-                    if (current_settings.optimizecputype <> cpu_386) and
+                    if (current_settings.optimizecputype > cpu_386) and
                        not(cs_opt_size in current_settings.optimizerswitches) then
                       { use a sequence without jumps, saw this in
                         comp.compilers (JM) }
                       begin
                         { no jumps, but more operations }
                         hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
-                        emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
-                        {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
-                        emit_const_reg(A_SAR,S_L,31,hreg2);
+                        emit_reg_reg(A_MOV,S_W,hreg1,hreg2);
+                        {If the left value is signed, hreg2=$ffff, otherwise 0.}
+                        cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_16,15,hreg2);
                         {If signed, hreg2=right value-1, otherwise 0.}
-                        emit_const_reg(A_AND,S_L,tordconstnode(right).value.svalue-1,hreg2);
+                        emit_const_reg(A_AND,S_W,tordconstnode(right).value.svalue-1,hreg2);
                         { add to the left value }
-                        emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
+                        emit_reg_reg(A_ADD,S_W,hreg2,hreg1);
                         { do the shift }
-                        emit_const_reg(A_SAR,S_L,power,hreg1);
+                        cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_16,power,hreg1);
                       end
                     else
                       begin
                         { a jump, but less operations }
-                        emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
+                        emit_reg_reg(A_TEST,S_W,hreg1,hreg1);
                         current_asmdata.getjumplabel(hl);
                         cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NS,hl);
                         if power=1 then
-                          emit_reg(A_INC,S_L,hreg1)
+                          emit_reg(A_INC,S_W,hreg1)
                         else
-                          emit_const_reg(A_ADD,S_L,tordconstnode(right).value.svalue-1,hreg1);
+                          emit_const_reg(A_ADD,S_W,tordconstnode(right).value.svalue-1,hreg1);
                         cg.a_label(current_asmdata.CurrAsmList,hl);
-                        emit_const_reg(A_SAR,S_L,power,hreg1);
+                        cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_16,power,hreg1);
                       end
                   end
                 else
-                  emit_const_reg(A_SHR,S_L,power,hreg1);
+                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_16,power,hreg1);
                 location.register:=hreg1;
               end
             else
@@ -148,85 +169,85 @@ implementation
                   begin
                     e:=tordconstnode(right).value.svalue;
                     d:=abs(e);
-                    { Determine algorithm (a), multiplier (m), and shift factor (s) for 32-bit
+                    { Determine algorithm (a), multiplier (m), and shift factor (s) for 16-bit
                       signed integer division. Based on: Granlund, T.; Montgomery, P.L.:
                       "Division by Invariant Integers using Multiplication". SIGPLAN Notices,
                       Vol. 29, June 1994, page 61.
                     }
 
                     l:=log2(d);
-                    j:=qword($80000000) mod qword(d);
-                    k:=(qword(1) shl (32+l)) div (qword($80000000-j));
-                    m_low:=((qword(1)) shl (32+l)) div d;
-                    m_high:=(((qword(1)) shl (32+l)) + k) div d;
+                    j:=dword($8000) mod dword(d);
+                    k:=(dword(1) shl (16+l)) div (dword($8000-j));
+                    m_low:=((dword(1)) shl (16+l)) div d;
+                    m_high:=(((dword(1)) shl (16+l)) + k) div d;
                     while ((m_low shr 1) < (m_high shr 1)) and (l > 0) do
                       begin
                         m_low:=m_low shr 1;
                         m_high:=m_high shr 1;
                         dec(l);
                       end;
-                    m:=dword(m_high);
+                    m:=word(m_high);
                     s:=l;
-                    if (m_high shr 31)<>0 then
+                    if (m_high shr 15)<>0 then
                       a:=1
                     else
                       a:=0;
-                    cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
-                    emit_const_reg(A_MOV,S_L,aint(m),NR_EAX);
-                    cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
-                    emit_reg(A_IMUL,S_L,hreg1);
-                    emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
+                    cg.getcpuregister(current_asmdata.CurrAsmList,NR_AX);
+                    emit_const_reg(A_MOV,S_W,aint(m),NR_AX);
+                    cg.getcpuregister(current_asmdata.CurrAsmList,NR_DX);
+                    emit_reg(A_IMUL,S_W,hreg1);
+                    emit_reg_reg(A_MOV,S_W,hreg1,NR_AX);
                     if a<>0 then
                       begin
-                        emit_reg_reg(A_ADD,S_L,NR_EAX,NR_EDX);
+                        emit_reg_reg(A_ADD,S_W,NR_AX,NR_DX);
                         {
-                          printf ("; dividend: memory location or register other than EAX or EDX\n");
+                          printf ("; dividend: memory location or register other than AX or DX\n");
                           printf ("\n");
-                          printf ("MOV EAX, 0%08LXh\n", m);
+                          printf ("MOV AX, 0%08LXh\n", m);
                           printf ("IMUL dividend\n");
-                          printf ("MOV EAX, dividend\n");
-                          printf ("ADD EDX, EAX\n");
-                          if (s) printf ("SAR EDX, %d\n", s);
-                          printf ("SHR EAX, 31\n");
-                          printf ("ADD EDX, EAX\n");
-                          if (e < 0) printf ("NEG EDX\n");
+                          printf ("MOV AX, dividend\n");
+                          printf ("ADD DX, AX\n");
+                          if (s) printf ("SAR DX, %d\n", s);
+                          printf ("SHR AX, 15\n");
+                          printf ("ADD DX, AX\n");
+                          if (e < 0) printf ("NEG DX\n");
                           printf ("\n");
-                          printf ("; quotient now in EDX\n");
+                          printf ("; quotient now in DX\n");
                         }
                       end;
                       {
-                        printf ("; dividend: memory location of register other than EAX or EDX\n");
+                        printf ("; dividend: memory location of register other than AX or DX\n");
                         printf ("\n");
-                        printf ("MOV EAX, 0%08LXh\n", m);
+                        printf ("MOV AX, 0%08LXh\n", m);
                         printf ("IMUL dividend\n");
-                        printf ("MOV EAX, dividend\n");
-                        if (s) printf ("SAR EDX, %d\n", s);
-                        printf ("SHR EAX, 31\n");
-                        printf ("ADD EDX, EAX\n");
-                        if (e < 0) printf ("NEG EDX\n");
+                        printf ("MOV AX, dividend\n");
+                        if (s) printf ("SAR DX, %d\n", s);
+                        printf ("SHR AX, 15\n");
+                        printf ("ADD DX, AX\n");
+                        if (e < 0) printf ("NEG DX\n");
                         printf ("\n");
-                        printf ("; quotient now in EDX\n");
+                        printf ("; quotient now in DX\n");
                       }
                     if s<>0 then
-                      emit_const_reg(A_SAR,S_L,s,NR_EDX);
-                    emit_const_reg(A_SHR,S_L,31,NR_EAX);
-                    emit_reg_reg(A_ADD,S_L,NR_EAX,NR_EDX);
+                      cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_16,s,NR_DX);
+                    cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_16,15,NR_AX);
+                    emit_reg_reg(A_ADD,S_W,NR_AX,NR_DX);
                     if e<0 then
-                      emit_reg(A_NEG,S_L,NR_EDX);
-                    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
-                    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+                      emit_reg(A_NEG,S_W,NR_DX);
+                    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_DX);
+                    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_AX);
                     location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
-                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EDX,location.register)
+                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_DX,location.register)
                   end
                 else
                   begin
                     d:=tordconstnode(right).value.svalue;
-                    if d>=$80000000 then
+                    if d>=$8000 then
                       begin
-                        emit_const_reg(A_CMP,S_L,aint(d),hreg1);
+                        emit_const_reg(A_CMP,S_W,aint(d),hreg1);
                         location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
-                        emit_const_reg(A_MOV,S_L,0,location.register);
-                        emit_const_reg(A_SBB,S_L,-1,location.register);
+                        emit_const_reg(A_MOV,S_W,0,location.register);
+                        emit_const_reg(A_SBB,S_W,-1,location.register);
                       end
                     else
                       begin
@@ -243,19 +264,19 @@ implementation
                         SIGPLAN Notices, Vol. 29, June 1994, page 61.
                         }
                         l:=log2(t)+1;
-                        j:=qword($ffffffff) mod qword(t);
-                        k:=(qword(1) shl (32+l)) div (qword($ffffffff-j));
-                        m_low:=((qword(1)) shl (32+l)) div t;
-                        m_high:=(((qword(1)) shl (32+l)) + k) div t;
+                        j:=dword($ffff) mod dword(t);
+                        k:=(dword(1) shl (16+l)) div (dword($ffff-j));
+                        m_low:=((dword(1)) shl (16+l)) div t;
+                        m_high:=(((dword(1)) shl (16+l)) + k) div t;
                         while ((m_low shr 1) < (m_high shr 1)) and (l>0) do
                           begin
                             m_low:=m_low shr 1;
                             m_high:=m_high shr 1;
                             l:=l-1;
                           end;
-                        if (m_high shr 32)=0 then
+                        if (m_high shr 16)=0 then
                           begin
-                            m:=dword(m_high);
+                            m:=word(m_high);
                             s:=l;
                             a:=0;
                           end
@@ -267,12 +288,12 @@ implementation
                         else
                           begin
                             s:=log2(t);
-                            m_low:=(qword(1) shl (32+s)) div qword(t);
-                            r:=dword(((qword(1)) shl (32+s)) mod qword(t));
+                            m_low:=(dword(1) shl (16+s)) div dword(t);
+                            r:=word(((dword(1)) shl (16+s)) mod dword(t));
                             if (r < ((t>>1)+1)) then
-                              m:=dword(m_low)
+                              m:=word(m_low)
                             else
-                              m:=dword(m_low)+1;
+                              m:=word(m_low)+1;
                             a:=1;
                           end;
                         { Reduce multiplier for either algorithm to smallest possible }
@@ -283,72 +304,72 @@ implementation
                           end;
                         { Adjust multiplier for reduction of even divisors }
                         inc(s,n);
-                        cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
-                        emit_const_reg(A_MOV,S_L,aint(m),NR_EAX);
-                        cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
-                        emit_reg(A_MUL,S_L,hreg1);
+                        cg.getcpuregister(current_asmdata.CurrAsmList,NR_AX);
+                        emit_const_reg(A_MOV,S_W,aint(m),NR_AX);
+                        cg.getcpuregister(current_asmdata.CurrAsmList,NR_DX);
+                        emit_reg(A_MUL,S_W,hreg1);
                         if a<>0 then
                           begin
                             {
-                            printf ("; dividend: register other than EAX or memory location\n");
+                            printf ("; dividend: register other than AX or memory location\n");
                             printf ("\n");
-                            printf ("MOV EAX, 0%08lXh\n", m);
+                            printf ("MOV AX, 0%08lXh\n", m);
                             printf ("MUL dividend\n");
-                            printf ("ADD EAX, 0%08lXh\n", m);
-                            printf ("ADC EDX, 0\n");
-                            if (s) printf ("SHR EDX, %d\n", s);
+                            printf ("ADD AX, 0%08lXh\n", m);
+                            printf ("ADC DX, 0\n");
+                            if (s) printf ("SHR DX, %d\n", s);
                             printf ("\n");
-                            printf ("; quotient now in EDX\n");
+                            printf ("; quotient now in DX\n");
                             }
-                            emit_const_reg(A_ADD,S_L,aint(m),NR_EAX);
-                            emit_const_reg(A_ADC,S_L,0,NR_EDX);
+                            emit_const_reg(A_ADD,S_W,aint(m),NR_AX);
+                            emit_const_reg(A_ADC,S_W,0,NR_DX);
                           end;
                         if s<>0 then
-                          emit_const_reg(A_SHR,S_L,aint(s),NR_EDX);
-                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
-                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+                          cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_16,aint(s),NR_DX);
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_DX);
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_AX);
                         location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
-                        cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EDX,location.register)
+                        cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_DX,location.register)
                       end;
                   end
               end
           end
         else
           begin
-            cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
-            emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
-            cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+            cg.getcpuregister(current_asmdata.CurrAsmList,NR_AX);
+            emit_reg_reg(A_MOV,S_W,hreg1,NR_AX);
+            cg.getcpuregister(current_asmdata.CurrAsmList,NR_DX);
             {Sign extension depends on the left type.}
-            if torddef(left.resultdef).ordtype=u32bit then
-              emit_reg_reg(A_XOR,S_L,NR_EDX,NR_EDX)
+            if torddef(left.resultdef).ordtype=u16bit then
+              emit_reg_reg(A_XOR,S_W,NR_DX,NR_DX)
             else
-              emit_none(A_CDQ,S_NO);
+              emit_none(A_CWD,S_NO);
 
             {Division depends on the right type.}
-            if Torddef(right.resultdef).ordtype=u32bit then
+            if Torddef(right.resultdef).ordtype=u16bit then
               op:=A_DIV
             else
               op:=A_IDIV;
 
             if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
-              emit_ref(op,S_L,right.location.reference)
+              emit_ref(op,S_W,right.location.reference)
             else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-              emit_reg(op,S_L,right.location.register)
+              emit_reg(op,S_W,right.location.register)
             else
               begin
                 hreg1:=cg.getintregister(current_asmdata.CurrAsmList,right.location.size);
-                hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,u32inttype,right.location,hreg1);
-                emit_reg(op,S_L,hreg1);
+                hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,u16inttype,right.location,hreg1);
+                emit_reg(op,S_W,hreg1);
               end;
 
-            {Copy the result into a new register. Release EAX & EDX.}
-            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
-            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+            {Copy the result into a new register. Release AX & DX.}
+            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_DX);
+            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_AX);
             location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
             if nodetype=divn then
-              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EAX,location.register)
+              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_AX,location.register)
             else
-              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EDX,location.register);
+              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_DX,location.register);
           end;
       end;
 

+ 46 - 28
compiler/i8086/n8086mem.pas

@@ -28,23 +28,30 @@ interface
     uses
       globtype,
       cgbase,cpuinfo,cpubase,
-      node,nmem,ncgmem,nx86mem;
+      node,nmem,ncgmem,nx86mem,ni86mem;
 
     type
-       ti8086addrnode = class(tcgaddrnode)
-         procedure pass_generate_code;override;
+       ti8086addrnode = class(ti86addrnode)
+        protected
+         procedure set_absvarsym_resultdef; override;
+         function typecheck_non_proc(realsource: tnode; out res: tnode): boolean; override;
        end;
 
        ti8086derefnode = class(tx86derefnode)
          procedure pass_generate_code;override;
        end;
 
+       { tx86vecnode doesn't work for i8086, so we inherit tcgvecnode }
+       ti8086vecnode = class(tcgvecnode)
+         procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);override;
+       end;
+
 implementation
 
     uses
       systems,globals,
       cutils,verbose,
-      symbase,symconst,symdef,symtable,symtype,symsym,
+      symbase,symconst,symdef,symtable,symtype,symsym,symcpu,
       parabase,paramgr,
       aasmtai,aasmdata,
       nld,ncon,nadd,
@@ -56,34 +63,31 @@ implementation
                              TI8086ADDRNODE
 *****************************************************************************}
 
-    procedure ti8086addrnode.pass_generate_code;
-      var
-        segref: treference;
+    procedure ti8086addrnode.set_absvarsym_resultdef;
       begin
-        if (current_settings.x86memorymodel in x86_far_code_models) and
-           (left.nodetype=loadn) and
-           (tloadnode(left).symtableentry.typ=labelsym) then
-          begin
-            secondpass(left);
-
-            location_reset(location,LOC_REGISTER,OS_32);
-            location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-            if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
-              internalerror(2013091801);
+        if not(nf_typedaddr in flags) then
+          resultdef:=voidfarpointertype
+        else
+          resultdef:=tcpupointerdefclass(cpointerdef).createx86(left.resultdef,x86pt_far);
+      end;
 
-            { load offset }
-            cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
 
-            { load segment }
-            segref:=left.location.reference;
-            segref.refaddr:=addr_seg;
-            cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,segref,GetNextReg(location.register));
+    function ti8086addrnode.typecheck_non_proc(realsource: tnode; out res: tnode): boolean;
+      begin
+        res:=nil;
+        if (realsource.nodetype=loadn) and
+           (tloadnode(realsource).symtableentry.typ=labelsym) then
+          begin
+            if current_settings.x86memorymodel in x86_far_code_models then
+              resultdef:=voidfarpointertype
+            else
+              resultdef:=voidnearpointertype;
+            result:=true
           end
         else
-          inherited;
+          result:=inherited;
       end;
 
-
 {*****************************************************************************
                              TI8086DEREFNODE
 *****************************************************************************}
@@ -96,7 +100,7 @@ implementation
         st : tsymtable;
         tmpref: treference;
       begin
-        if tpointerdef(left.resultdef).x86pointertyp in [x86pt_far,x86pt_huge] then
+        if tcpupointerdef(left.resultdef).x86pointertyp in [x86pt_far,x86pt_huge] then
           begin
             secondpass(left);
             { assume natural alignment, except for packed records }
@@ -111,7 +115,7 @@ implementation
                LOC_CREGISTER,
                LOC_REGISTER:
                  begin
-                   maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
+                   hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,true);
                    location.reference.base := left.location.register;
                    location.reference.segment := GetNextReg(left.location.register);
                  end;
@@ -138,7 +142,7 @@ implementation
                (cs_checkpointer in current_settings.localswitches) and
                not(cs_compilesystem in current_settings.moduleswitches) and
    {$ifdef x86}
-               (tpointerdef(left.resultdef).x86pointertyp = default_x86_data_pointer_type) and
+               (tcpupointerdef(left.resultdef).x86pointertyp = tcpupointerdefclass(cpointerdef).default_x86_data_pointer_type) and
    {$endif x86}
                not(nf_no_checkpointer in flags) and
                { can be NR_NO in case of LOC_CONSTANT }
@@ -162,8 +166,22 @@ implementation
           inherited pass_generate_code;
       end;
 
+{*****************************************************************************
+                             TI8086VECNODE
+*****************************************************************************}
+
+    procedure ti8086vecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+      var
+        saveseg: TRegister;
+      begin
+        saveseg:=location.reference.segment;
+        location.reference.segment:=NR_NO;
+        inherited update_reference_reg_mul(maybe_const_reg,l);
+        location.reference.segment:=saveseg;
+      end;
 
 begin
   caddrnode:=ti8086addrnode;
   cderefnode:=ti8086derefnode;
+  cvecnode:=ti8086vecnode;
 end.

+ 77 - 0
compiler/i8086/n8086tcon.pas

@@ -0,0 +1,77 @@
+{
+    Copyright (c) 1998-2011 by Florian Klaempfl, Jonas Maebe
+
+    Generates i8086 assembler for typed constant declarations
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n8086tcon;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,symdef,ngtcon;
+
+
+    type
+
+      { ti8086typedconstbuilder }
+
+      ti8086typedconstbuilder = class(tasmlisttypedconstbuilder)
+       protected
+        procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);override;
+      end;
+
+
+implementation
+
+uses
+  ncnv,defcmp,defutil,aasmtai;
+
+    { ti8086typedconstbuilder }
+
+    procedure ti8086typedconstbuilder.tc_emit_pointerdef(def: tpointerdef; var node: tnode);
+      var
+        hp: tnode;
+      begin
+        { remove equal typecasts for pointer/nil addresses }
+        if (node.nodetype=typeconvn) then
+          with Ttypeconvnode(node) do
+            if (left.nodetype in [addrn,niln]) and equal_defs(def,node.resultdef) then
+              begin
+                hp:=left;
+                left:=nil;
+                node.free;
+                node:=hp;
+              end;
+        if node.nodetype=niln then
+          begin
+            if is_farpointer(def) or is_hugepointer(def) then
+              list.concat(Tai_const.Create_32bit(0))
+            else
+              list.concat(Tai_const.Create_16bit(0));
+          end
+        else
+          inherited tc_emit_pointerdef(def, node);
+      end;
+
+begin
+  ctypedconstbuilder:=ti8086typedconstbuilder;
+end.
+

+ 127 - 0
compiler/i8086/n8086util.pas

@@ -0,0 +1,127 @@
+{
+    Copyright (c) 2014 by Nikolay Nikolov
+
+    i8086 version of some node tree helper routines
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n8086util;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    ngenutil;
+
+
+  type
+    ti8086nodeutils = class(tnodeutils)
+      class procedure InsertMemorySizes; override;
+      class procedure InsertStackSegment;
+      class procedure InsertHeapSegment;
+      class procedure InsertStackPlusHeapSize;
+    end;
+
+
+implementation
+
+  uses
+    sysutils,cutils,
+    globtype,globals,cpuinfo,
+    aasmbase,aasmdata,aasmtai;
+
+
+  class procedure ti8086nodeutils.InsertMemorySizes;
+    begin
+      inherited;
+      if current_settings.x86memorymodel<>mm_tiny then
+        InsertStackSegment;
+      InsertHeapSegment;
+      if current_settings.x86memorymodel in x86_near_data_models then
+        InsertStackPlusHeapSize;
+    end;
+
+
+  class procedure ti8086nodeutils.InsertStackSegment;
+    var
+      stacksizeleft,stackblock: LongInt;
+      i: Integer;
+    begin
+      maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+      new_section(current_asmdata.asmlists[al_globals],sec_stack,'__stack', 16);
+      current_asmdata.asmlists[al_globals].concat(tai_symbol.Createname_global('___stack', AT_DATA, stacksize));
+      { HACK: since tai_datablock's size parameter is aint, which cannot be
+        larger than 32767 on i8086, but we'd like to support stack size of
+        up to 64kb, we may need to use several tai_datablocks to reserve
+        the stack segment }
+      i:=0;
+      stacksizeleft:=stacksize;
+      while stacksizeleft>0 do
+        begin
+          stackblock:=min(stacksizeleft,high(aint));
+          current_asmdata.asmlists[al_globals].concat(tai_datablock.Create('___stackblock'+IntToStr(i),stackblock));
+          dec(stacksizeleft,stackblock);
+          inc(i);
+        end;
+      current_asmdata.asmlists[al_globals].concat(tai_symbol.Createname_global('___stacktop',AT_DATA,0));
+    end;
+
+
+  class procedure ti8086nodeutils.InsertHeapSegment;
+    var
+      heapsizeleft,heapblock: LongInt;
+      i: Integer;
+    begin
+      maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+      new_section(current_asmdata.asmlists[al_globals],sec_heap,'__heap', 16);
+      current_asmdata.asmlists[al_globals].concat(tai_symbol.Createname_global('___heap', AT_DATA, heapsize));
+      { HACK: since tai_datablock's size parameter is aint, which cannot be
+        larger than 32767 on i8086, but we'd like to support heap size of
+        up to 640kb, we may need to use several tai_datablocks to reserve
+        the heap segment }
+      i:=0;
+      heapsizeleft:=heapsize;
+      while heapsizeleft>0 do
+        begin
+          heapblock:=min(heapsizeleft,high(aint));
+          current_asmdata.asmlists[al_globals].concat(tai_datablock.Create('___heapblock'+IntToStr(i),heapblock));
+          dec(heapsizeleft,heapblock);
+          inc(i);
+        end;
+      current_asmdata.asmlists[al_globals].concat(tai_symbol.Createname_global('___heaptop',AT_DATA,0));
+    end;
+
+
+  class procedure ti8086nodeutils.InsertStackPlusHeapSize;
+    var
+      maxheapsize_para: Word;
+      stacksize_para: Word;
+    begin
+      maxheapsize_para:=(maxheapsize+15) div 16;
+      stacksize_para:=(stacksize+15) div 16;
+
+      maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+      new_section(current_asmdata.asmlists[al_globals],sec_data,'__fpc_stackplusmaxheap_in_para',sizeof(pint));
+      current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__fpc_stackplusmaxheap_in_para',AT_DATA,4));
+      current_asmdata.asmlists[al_globals].concat(Tai_const.Create_16bit(min($1000,stacksize_para+maxheapsize_para)));
+    end;
+
+
+begin
+  cnodeutils:=ti8086nodeutils;
+end.

+ 8 - 8
compiler/i8086/r8086ari.inc

@@ -8,22 +8,22 @@
 15,
 6,
 5,
-38,
 39,
 40,
 41,
+42,
 26,
 7,
 10,
 19,
 9,
-32,
 33,
 34,
 35,
 36,
 37,
-27,
+38,
+28,
 11,
 4,
 22,
@@ -31,13 +31,13 @@
 8,
 20,
 12,
+32,
 25,
-28,
 18,
 24,
-47,
-30,
 31,
+29,
+30,
 57,
 58,
 59,
@@ -48,7 +48,7 @@
 64,
 17,
 23,
-29,
+27,
 56,
 48,
 49,
@@ -58,11 +58,11 @@
 53,
 54,
 55,
-42,
 43,
 44,
 45,
 46,
+47,
 65,
 66,
 67,

+ 4 - 4
compiler/i8086/r8086att.inc

@@ -24,13 +24,14 @@
 '%ebp',
 '%sp',
 '%esp',
-'%eip',
-'%cs',
-'%ds',
 '%es',
+'%cs',
 '%ss',
+'%ds',
 '%fs',
 '%gs',
+'%flags',
+'%eip',
 '%dr0',
 '%dr1',
 '%dr2',
@@ -46,7 +47,6 @@
 '%tr5',
 '%tr6',
 '%tr7',
-'%flags',
 '%st(0)',
 '%st(1)',
 '%st(2)',

+ 22 - 22
compiler/i8086/r8086con.inc

@@ -24,29 +24,29 @@ NR_BP = tregister($01030006);
 NR_EBP = tregister($01040006);
 NR_SP = tregister($01030007);
 NR_ESP = tregister($01040007);
-NR_EIP = tregister($05040000);
+NR_ES = tregister($05000000);
 NR_CS = tregister($05000001);
-NR_DS = tregister($05000002);
-NR_ES = tregister($05000003);
-NR_SS = tregister($05000004);
-NR_FS = tregister($05000005);
-NR_GS = tregister($05000006);
-NR_DR0 = tregister($05000007);
-NR_DR1 = tregister($05000008);
-NR_DR2 = tregister($05000009);
-NR_DR3 = tregister($0500000a);
-NR_DR6 = tregister($0500000b);
-NR_DR7 = tregister($0500000c);
-NR_CR0 = tregister($0500000d);
-NR_CR2 = tregister($0500000e);
-NR_CR3 = tregister($0500000f);
-NR_CR4 = tregister($05000010);
-NR_TR3 = tregister($05000011);
-NR_TR4 = tregister($05000012);
-NR_TR5 = tregister($05000013);
-NR_TR6 = tregister($05000014);
-NR_TR7 = tregister($05000015);
-NR_FLAGS = tregister($05000016);
+NR_SS = tregister($05000002);
+NR_DS = tregister($05000003);
+NR_FS = tregister($05000004);
+NR_GS = tregister($05000005);
+NR_FLAGS = tregister($05000006);
+NR_EIP = tregister($05040007);
+NR_DR0 = tregister($05000008);
+NR_DR1 = tregister($05000009);
+NR_DR2 = tregister($0500000a);
+NR_DR3 = tregister($0500000b);
+NR_DR6 = tregister($0500000d);
+NR_DR7 = tregister($0500000e);
+NR_CR0 = tregister($05000010);
+NR_CR2 = tregister($05000012);
+NR_CR3 = tregister($05000013);
+NR_CR4 = tregister($05000014);
+NR_TR3 = tregister($0500001b);
+NR_TR4 = tregister($0500001c);
+NR_TR5 = tregister($0500001d);
+NR_TR6 = tregister($0500001e);
+NR_TR7 = tregister($0500001f);
 NR_ST0 = tregister($02000000);
 NR_ST1 = tregister($02000001);
 NR_ST2 = tregister($02000002);

+ 1 - 1
compiler/i8086/r8086dwrf.inc

@@ -24,7 +24,6 @@
 5,
 4,
 4,
-8,
 -1,
 -1,
 -1,
@@ -32,6 +31,7 @@
 -1,
 -1,
 -1,
+8,
 -1,
 -1,
 -1,

+ 4 - 4
compiler/i8086/r8086int.inc

@@ -24,13 +24,14 @@
 'ebp',
 'sp',
 'esp',
-'eip',
-'cs',
-'ds',
 'es',
+'cs',
 'ss',
+'ds',
 'fs',
 'gs',
+'flags',
+'eip',
 'dr0',
 'dr1',
 'dr2',
@@ -46,7 +47,6 @@
 'tr5',
 'tr6',
 'tr7',
-'flags',
 'st(0)',
 'st(1)',
 'st(2)',

+ 8 - 8
compiler/i8086/r8086iri.inc

@@ -9,22 +9,22 @@
 15,
 6,
 5,
-38,
 39,
 40,
 41,
+42,
 26,
 7,
 10,
 19,
 9,
-32,
 33,
 34,
 35,
 36,
 37,
-27,
+38,
+28,
 11,
 4,
 22,
@@ -32,13 +32,13 @@
 8,
 20,
 12,
+32,
 25,
-28,
 18,
 24,
-47,
-30,
 31,
+29,
+30,
 57,
 58,
 59,
@@ -49,7 +49,7 @@
 64,
 17,
 23,
-29,
+27,
 56,
 48,
 49,
@@ -59,11 +59,11 @@
 53,
 54,
 55,
-42,
 43,
 44,
 45,
 46,
+47,
 65,
 66,
 67,

+ 4 - 4
compiler/i8086/r8086nasm.inc

@@ -24,13 +24,14 @@
 'ebp',
 'sp',
 'esp',
-'eip',
-'cs',
-'ds',
 'es',
+'cs',
 'ss',
+'ds',
 'fs',
 'gs',
+'flags',
+'eip',
 'dr0',
 'dr1',
 'dr2',
@@ -46,7 +47,6 @@
 'tr5',
 'tr6',
 'tr7',
-'flags',
 'st0',
 'st1',
 'st2',

+ 8 - 8
compiler/i8086/r8086nri.inc

@@ -9,22 +9,22 @@
 15,
 6,
 5,
-38,
 39,
 40,
 41,
+42,
 26,
 7,
 10,
 19,
 9,
-32,
 33,
 34,
 35,
 36,
 37,
-27,
+38,
+28,
 11,
 4,
 22,
@@ -32,13 +32,13 @@
 8,
 20,
 12,
+32,
 25,
-28,
 18,
 24,
-47,
-30,
 31,
+29,
+30,
 57,
 58,
 59,
@@ -49,7 +49,7 @@
 64,
 17,
 23,
-29,
+27,
 56,
 48,
 49,
@@ -59,11 +59,11 @@
 53,
 54,
 55,
-42,
 43,
 44,
 45,
 46,
+47,
 65,
 66,
 67,

+ 7 - 7
compiler/i8086/r8086num.inc

@@ -24,29 +24,29 @@ tregister($01030006),
 tregister($01040006),
 tregister($01030007),
 tregister($01040007),
-tregister($05040000),
+tregister($05000000),
 tregister($05000001),
 tregister($05000002),
 tregister($05000003),
 tregister($05000004),
 tregister($05000005),
 tregister($05000006),
-tregister($05000007),
+tregister($05040007),
 tregister($05000008),
 tregister($05000009),
 tregister($0500000a),
 tregister($0500000b),
-tregister($0500000c),
 tregister($0500000d),
 tregister($0500000e),
-tregister($0500000f),
 tregister($05000010),
-tregister($05000011),
 tregister($05000012),
 tregister($05000013),
 tregister($05000014),
-tregister($05000015),
-tregister($05000016),
+tregister($0500001b),
+tregister($0500001c),
+tregister($0500001d),
+tregister($0500001e),
+tregister($0500001f),
 tregister($02000000),
 tregister($02000001),
 tregister($02000002),

+ 0 - 82
compiler/i8086/r8086op.inc

@@ -1,82 +0,0 @@
-{ don't edit, this file is generated from x86reg.dat }
-0,
-0,
-4,
-0,
-0,
-1,
-5,
-1,
-1,
-2,
-6,
-2,
-2,
-3,
-7,
-3,
-3,
-6,
-6,
-7,
-7,
-5,
-5,
-4,
-4,
-0,
-1,
-3,
-0,
-2,
-4,
-5,
-0,
-1,
-2,
-3,
-6,
-7,
-0,
-2,
-3,
-4,
-3,
-4,
-5,
-6,
-7,
-0,
-0,
-1,
-2,
-3,
-4,
-5,
-6,
-7,
-0,
-0,
-1,
-2,
-3,
-4,
-5,
-6,
-7,
-0,
-1,
-2,
-3,
-4,
-5,
-6,
-7,
-0,
-1,
-2,
-3,
-4,
-5,
-6,
-7

+ 3 - 3
compiler/i8086/r8086ot.inc

@@ -24,13 +24,14 @@ OT_REG16,
 OT_REG32,
 OT_REG16,
 OT_REG32,
-OT_NONE,
-OT_REG_CS,
 OT_REG_DESS,
+OT_REG_CS,
 OT_REG_DESS,
 OT_REG_DESS,
 OT_REG_FSGS,
 OT_REG_FSGS,
+OT_NONE,
+OT_NONE,
 OT_REG_DREG,
 OT_REG_DREG,
 OT_REG_DREG,
@@ -46,7 +47,6 @@ OT_REG_TREG,
 OT_REG_TREG,
 OT_REG_TREG,
 OT_REG_TREG,
-OT_NONE,
 OT_FPU0,
 OT_FPUREG,
 OT_FPUREG,

+ 2 - 2
compiler/i8086/r8086rni.inc

@@ -57,13 +57,13 @@
 78,
 79,
 80,
+25,
 26,
 27,
 28,
 29,
 30,
 31,
-32,
 33,
 34,
 35,
@@ -79,4 +79,4 @@
 45,
 46,
 47,
-25
+32

+ 8 - 8
compiler/i8086/r8086sri.inc

@@ -9,22 +9,22 @@
 15,
 6,
 5,
-38,
 39,
 40,
 41,
+42,
 26,
 7,
 10,
 19,
 9,
-32,
 33,
 34,
 35,
 36,
 37,
-27,
+38,
+28,
 11,
 4,
 22,
@@ -32,13 +32,13 @@
 8,
 20,
 12,
+32,
 25,
-28,
 18,
 24,
-47,
-30,
 31,
+29,
+30,
 57,
 58,
 59,
@@ -49,7 +49,7 @@
 64,
 17,
 23,
-29,
+27,
 56,
 48,
 49,
@@ -59,11 +59,11 @@
 53,
 54,
 55,
-42,
 43,
 44,
 45,
 46,
+47,
 65,
 66,
 67,

+ 4 - 4
compiler/i8086/r8086std.inc

@@ -24,13 +24,14 @@
 'ebp',
 'sp',
 'esp',
-'eip',
-'cs',
-'ds',
 'es',
+'cs',
 'ss',
+'ds',
 'fs',
 'gs',
+'flags',
+'eip',
 'dr0',
 'dr1',
 'dr2',
@@ -46,7 +47,6 @@
 'tr5',
 'tr6',
 'tr7',
-'flags',
 'st(0)',
 'st(1)',
 'st(2)',

+ 18 - 5
compiler/i8086/rgcpu.pas

@@ -30,11 +30,15 @@ unit rgcpu;
     uses
       cpubase,
       cpuinfo,
-      aasmbase,aasmtai,aasmdata,
-      cclasses,globtype,cgbase,rgobj,rgx86;
+      aasmbase,aasmtai,aasmdata,aasmcpu,
+      cclasses,globtype,cgbase,cgutils,rgobj,rgx86;
 
     type
+
+       { trgcpu }
+
        trgcpu = class(trgx86)
+          function  do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;override;
           procedure add_constraints(reg:Tregister);override;
        end;
 
@@ -47,9 +51,7 @@ implementation
 
     uses
       systems,
-      verbose,
-      aasmcpu,
-      cgutils;
+      verbose;
 
     const
        { This value is used in tsaved. If the array value is equal
@@ -60,6 +62,17 @@ implementation
                                  trgcpu
 *************************************************************************}
 
+    function trgcpu.do_spill_replace(list: TAsmList; instr: taicpu; orgreg: tsuperregister; const spilltemp: treference): boolean;
+      var
+        spilltemp2: treference;
+      begin
+        spilltemp2:=spilltemp;
+        if spilltemp2.segment=NR_SS then
+          spilltemp2.segment:=NR_NO;
+        Result:=inherited do_spill_replace(list, instr, orgreg, spilltemp2);
+      end;
+
+
     procedure trgcpu.add_constraints(reg:Tregister);
       var
         supreg : tsuperregister;

+ 458 - 0
compiler/i8086/symcpu.pas

@@ -0,0 +1,458 @@
+{
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Symbol table overrides for i8086
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit symcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  globtype,
+  symconst,symtype,symdef,symsym,symx86,symi86;
+
+type
+  { defs }
+  tcpufiledef = class(tfiledef)
+  end;
+  tcpufiledefclass = class of tcpufiledef;
+
+  tcpuvariantdef = class(tvariantdef)
+  end;
+  tcpuvariantdefclass = class of tcpuvariantdef;
+
+  tcpuformaldef = class(tformaldef)
+  end;
+  tcpuformaldefclass = class of tcpuformaldef;
+
+  tcpuforwarddef = class(tforwarddef)
+  end;
+  tcpuforwarddefclass = class of tcpuforwarddef;
+
+  tcpuundefineddef = class(tundefineddef)
+  end;
+  tcpuundefineddefclass = class of tcpuundefineddef;
+
+  tcpuerrordef = class(terrordef)
+  end;
+  tcpuerrordefclass = class of tcpuerrordef;
+
+  tcpupointerdef = class(tx86pointerdef)
+    class function default_x86_data_pointer_type: tx86pointertyp; override;
+    function pointer_arithmetic_int_type:tdef; override;
+    function pointer_subtraction_result_type:tdef; override;
+  end;
+  tcpupointerdefclass = class of tcpupointerdef;
+
+  tcpurecorddef = class(trecorddef)
+  end;
+  tcpurecorddefclass = class of tcpurecorddef;
+
+  tcpuimplementedinterface = class(timplementedinterface)
+  end;
+  tcpuimplementedinterfaceclass = class of tcpuimplementedinterface;
+
+  tcpuobjectdef = class(tobjectdef)
+  end;
+  tcpuobjectdefclass = class of tcpuobjectdef;
+
+  tcpuclassrefdef = class(tclassrefdef)
+  end;
+  tcpuclassrefdefclass = class of tcpuclassrefdef;
+
+  { tcpuarraydef }
+
+  tcpuarraydef = class(tarraydef)
+   private
+    huge: Boolean;
+   protected
+    procedure ppuload_platform(ppufile: tcompilerppufile); override;
+    procedure ppuwrite_platform(ppufile: tcompilerppufile); override;
+   public
+    constructor create_from_pointer(def:tpointerdef);override;
+    function getcopy: tstoreddef; override;
+    function GetTypeName:string;override;
+    property is_huge: Boolean read huge write huge;
+  end;
+  tcpuarraydefclass = class of tcpuarraydef;
+
+  tcpuorddef = class(torddef)
+  end;
+  tcpuorddefclass = class of tcpuorddef;
+
+  tcpufloatdef = class(tfloatdef)
+  end;
+  tcpufloatdefclass = class of tcpufloatdef;
+
+  { tcpuprocvardef }
+
+  tcpuprocvardef = class(ti86procvardef)
+    constructor create(level:byte);override;
+    function is_far:boolean;
+  end;
+  tcpuprocvardefclass = class of tcpuprocvardef;
+
+  { tcpuprocdef }
+
+  tcpuprocdef = class(ti86procdef)
+   private
+    { returns whether the function is far by default, i.e. whether it would be
+      far if _all_ of the following conditions are true:
+      - we're in a far code memory model
+      - it has no 'near' or 'far' specifiers
+      - it is compiled in a $F- state }
+    function default_far:boolean;
+   public
+    constructor create(level:byte);override;
+    function address_type:tdef;override;
+    procedure declared_far;override;
+    procedure declared_near;override;
+    function is_far:boolean;
+  end;
+  tcpuprocdefclass = class of tcpuprocdef;
+
+  tcpustringdef = class(tstringdef)
+  end;
+  tcpustringdefclass = class of tcpustringdef;
+
+  tcpuenumdef = class(tenumdef)
+  end;
+  tcpuenumdefclass = class of tcpuenumdef;
+
+  tcpusetdef = class(tsetdef)
+  end;
+  tcpusetdefclass = class of tcpusetdef;
+
+  { syms }
+  tcpulabelsym = class(tlabelsym)
+  end;
+  tcpulabelsymclass = class of tcpulabelsym;
+
+  tcpuunitsym = class(tunitsym)
+  end;
+  tcpuunitsymclass = class of tcpuunitsym;
+
+  tcpunamespacesym = class(tnamespacesym)
+  end;
+  tcpunamespacesymclass = class of tcpunamespacesym;
+
+  tcpuprocsym = class(tprocsym)
+  end;
+  tcpuprocsymclass = class of tcpuprocsym;
+
+  tcputypesym = class(ttypesym)
+  end;
+  tcpuypesymclass = class of tcputypesym;
+
+  tcpufieldvarsym = class(tfieldvarsym)
+  end;
+  tcpufieldvarsymclass = class of tcpufieldvarsym;
+
+  tcpulocalvarsym = class(tlocalvarsym)
+  end;
+  tcpulocalvarsymclass = class of tcpulocalvarsym;
+
+  tcpuparavarsym = class(tparavarsym)
+  end;
+  tcpuparavarsymclass = class of tcpuparavarsym;
+
+  tcpustaticvarsym = class(tstaticvarsym)
+  end;
+  tcpustaticvarsymclass = class of tcpustaticvarsym;
+
+  tcpuabsolutevarsym = class(ti86absolutevarsym)
+   protected
+    procedure ppuload_platform(ppufile: tcompilerppufile); override;
+    procedure ppuwrite_platform(ppufile: tcompilerppufile); override;
+   public
+    addrsegment : aword;
+  end;
+  tcpuabsolutevarsymclass = class of tcpuabsolutevarsym;
+
+  tcpupropertysym = class(tpropertysym)
+  end;
+  tcpupropertysymclass = class of tcpupropertysym;
+
+  tcpuconstsym = class(tconstsym)
+  end;
+  tcpuconstsymclass = class of tcpuconstsym;
+
+  tcpuenumsym = class(tenumsym)
+  end;
+  tcpuenumsymclass = class of tcpuenumsym;
+
+  tcpusyssym = class(tsyssym)
+  end;
+  tcpusyssymclass = class of tcpusyssym;
+
+
+const
+   pbestrealtype : ^tdef = @s80floattype;
+
+
+  function is_proc_far(p: tabstractprocdef): boolean;
+
+
+implementation
+
+  uses
+    globals, cpuinfo, verbose;
+
+
+  function is_proc_far(p: tabstractprocdef): boolean;
+  begin
+    if p is tcpuprocdef then
+      result:=tcpuprocdef(p).is_far
+    else if p is tcpuprocvardef then
+      result:=tcpuprocvardef(p).is_far
+    else
+      internalerror(2014041301);
+  end;
+
+
+{****************************************************************************
+                               tcpuarraydef
+****************************************************************************}
+
+  constructor tcpuarraydef.create_from_pointer(def: tpointerdef);
+    begin
+      if tcpupointerdef(def).x86pointertyp=x86pt_huge then
+        begin
+          huge:=true;
+          { use -1 so that the elecount will not overflow }
+          self.create(0,high(asizeint)-1,s32inttype);
+          arrayoptions:=[ado_IsConvertedPointer];
+          setelementdef(def.pointeddef);
+        end
+      else
+        begin
+          huge:=false;
+          inherited create_from_pointer(def);
+        end;
+    end;
+
+
+  function tcpuarraydef.getcopy: tstoreddef;
+    begin
+      result:=inherited;
+      tcpuarraydef(result).huge:=huge;
+    end;
+
+
+  function tcpuarraydef.GetTypeName: string;
+    begin
+      Result:=inherited;
+      if is_huge then
+        Result:='Huge '+Result;
+    end;
+
+
+  procedure tcpuarraydef.ppuload_platform(ppufile: tcompilerppufile);
+    begin
+      inherited;
+      huge:=(ppufile.getbyte<>0);
+    end;
+
+
+  procedure tcpuarraydef.ppuwrite_platform(ppufile: tcompilerppufile);
+    begin
+      inherited;
+      ppufile.putbyte(byte(huge));
+    end;
+
+
+{****************************************************************************
+                             tcpuprocdef
+****************************************************************************}
+
+  constructor tcpuprocdef.create(level: byte);
+    begin
+      inherited create(level);
+      if (current_settings.x86memorymodel in x86_far_code_models) and
+         ((cs_huge_code in current_settings.moduleswitches) or
+          (cs_force_far_calls in current_settings.localswitches)) then
+        procoptions:=procoptions+[po_far];
+    end;
+
+
+  function tcpuprocdef.address_type: tdef;
+    begin
+      if is_far then
+        result:=voidfarpointertype
+      else
+        result:=voidnearpointertype;
+    end;
+
+
+  procedure tcpuprocdef.declared_far;
+    begin
+      if current_settings.x86memorymodel in x86_far_code_models then
+        include(procoptions,po_far)
+      else
+        inherited declared_far;
+    end;
+
+
+  procedure tcpuprocdef.declared_near;
+    begin
+      if (current_settings.x86memorymodel in x86_far_code_models) and
+         not (cs_huge_code in current_settings.moduleswitches) then
+        exclude(procoptions,po_far)
+      else
+        inherited declared_near;
+    end;
+
+
+  function tcpuprocdef.default_far: boolean;
+    begin
+      if proctypeoption in [potype_proginit,potype_unitinit,potype_unitfinalize,
+                            potype_constructor,potype_destructor,
+                            potype_class_constructor,potype_class_destructor,
+                            potype_propgetter,potype_propsetter] then
+        exit(true);
+      if (procoptions*[po_classmethod,po_virtualmethod,po_abstractmethod,
+                       po_finalmethod,po_staticmethod,po_overridingmethod,
+                       po_external,po_public,po_interrupt])<>[] then
+        exit(true);
+      if is_methodpointer then
+        exit(true);
+      result:=not (visibility in [vis_private,vis_hidden]);
+    end;
+
+
+  function tcpuprocdef.is_far: boolean;
+    begin
+      result:=(current_settings.x86memorymodel in x86_far_code_models) and
+        ((po_far in procoptions) or default_far);
+    end;
+
+{****************************************************************************
+                             tcpuprocvardef
+****************************************************************************}
+
+  constructor tcpuprocvardef.create(level: byte);
+    begin
+      inherited create(level);
+      { procvars are always far in the far code memory models }
+      if current_settings.x86memorymodel in x86_far_code_models then
+        procoptions:=procoptions+[po_far];
+    end;
+
+
+  function tcpuprocvardef.is_far: boolean;
+    begin
+      { procvars are always far in the far code memory models }
+      result:=current_settings.x86memorymodel in x86_far_code_models;
+    end;
+
+{****************************************************************************
+                             tcpupointerdef
+****************************************************************************}
+
+    class function tcpupointerdef.default_x86_data_pointer_type: tx86pointertyp;
+      begin
+        if current_settings.x86memorymodel in x86_far_data_models then
+          result:=x86pt_far
+        else
+          result:=inherited;
+      end;
+
+
+    function tcpupointerdef.pointer_arithmetic_int_type:tdef;
+      begin
+        if x86pointertyp=x86pt_huge then
+          result:=s32inttype
+        else
+          result:=inherited;
+      end;
+
+
+    function tcpupointerdef.pointer_subtraction_result_type:tdef;
+      begin
+        case x86pointertyp of
+          x86pt_huge:
+            result:=s32inttype;
+          x86pt_far:
+            result:=u16inttype;
+          else
+            result:=inherited;
+        end;
+      end;
+
+
+{****************************************************************************
+                             tcpuabsolutevarsym
+****************************************************************************}
+
+  procedure tcpuabsolutevarsym.ppuload_platform(ppufile: tcompilerppufile);
+    begin
+      inherited;
+      if absseg then
+        addrsegment:=ppufile.getaword;
+    end;
+
+
+  procedure tcpuabsolutevarsym.ppuwrite_platform(ppufile: tcompilerppufile);
+    begin
+      inherited;
+      if absseg then
+        ppufile.putaword(addrsegment);
+    end;
+
+begin
+  { used tdef classes }
+  cfiledef:=tcpufiledef;
+  cvariantdef:=tcpuvariantdef;
+  cformaldef:=tcpuformaldef;
+  cforwarddef:=tcpuforwarddef;
+  cundefineddef:=tcpuundefineddef;
+  cerrordef:=tcpuerrordef;
+  cpointerdef:=tcpupointerdef;
+  crecorddef:=tcpurecorddef;
+  cimplementedinterface:=tcpuimplementedinterface;
+  cobjectdef:=tcpuobjectdef;
+  cclassrefdef:=tcpuclassrefdef;
+  carraydef:=tcpuarraydef;
+  corddef:=tcpuorddef;
+  cfloatdef:=tcpufloatdef;
+  cprocvardef:=tcpuprocvardef;
+  cprocdef:=tcpuprocdef;
+  cstringdef:=tcpustringdef;
+  cenumdef:=tcpuenumdef;
+  csetdef:=tcpusetdef;
+
+  { used tsym classes }
+  clabelsym:=tcpulabelsym;
+  cunitsym:=tcpuunitsym;
+  cnamespacesym:=tcpunamespacesym;
+  cprocsym:=tcpuprocsym;
+  ctypesym:=tcputypesym;
+  cfieldvarsym:=tcpufieldvarsym;
+  clocalvarsym:=tcpulocalvarsym;
+  cparavarsym:=tcpuparavarsym;
+  cstaticvarsym:=tcpustaticvarsym;
+  cabsolutevarsym:=tcpuabsolutevarsym;
+  cpropertysym:=tcpupropertysym;
+  cconstsym:=tcpuconstsym;
+  cenumsym:=tcpuenumsym;
+  csyssym:=tcpusyssym;
+end.
+

+ 58 - 0
compiler/i8086/tgcpu.pas

@@ -0,0 +1,58 @@
+{
+    Copyright (C) 1998-2000 by Florian Klaempfl
+
+    This unit handles the temporary variables stuff for i8086
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+  This unit handles the temporary variables stuff for i8086.
+}
+unit tgcpu;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      tgobj,globtype,aasmdata,cgutils,symtype;
+
+    type
+
+      { ttgi8086 }
+
+      ttgi8086 = class(ttgobj)
+      protected
+        procedure alloctemp(list: TAsmList; size,alignment : longint; temptype : ttemptype; def:tdef; out ref: treference);override;
+      end;
+
+implementation
+
+uses
+  cpubase;
+
+{ ttgi8086 }
+
+procedure ttgi8086.alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef; out ref: treference);
+  begin
+    inherited;
+    ref.segment:=NR_SS;
+  end;
+
+begin
+  tgobjclass:=ttgi8086;
+end.

Некоторые файлы не были показаны из-за большого количества измененных файлов