浏览代码

* new file

peter 25 年之前
父节点
当前提交
0eee33e3f6
共有 1 个文件被更改,包括 1085 次插入0 次删除
  1. 1085 0
      compiler/n386util.pas

+ 1085 - 0
compiler/n386util.pas

@@ -0,0 +1,1085 @@
+{
+    $Id$
+    Copyright (c) 1998-2000 by Florian Klaempfl
+
+    Helper routines for the i386 code generator
+
+    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 n386util;
+
+{$i defines.inc}
+
+interface
+
+    uses
+      symtable,node;
+
+    function  maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
+{$ifdef TEMPS_NOT_PUSH}
+    function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
+{$endif TEMPS_NOT_PUSH}
+    procedure restore(p : tnode;isint64 : boolean);
+    procedure pushsetelement(p : tnode);
+    procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
+                              para_offset:longint;alignment : longint);
+
+    procedure maketojumpbool(p : tnode);
+    procedure emitoverflowcheck(p:tnode);
+    procedure emitrangecheck(p:tnode;todef:pdef);
+    procedure firstcomplex(p : tnode);
+
+implementation
+
+    uses
+      ncon;
+
+{*****************************************************************************
+                           Emit Push Functions
+*****************************************************************************}
+
+    function maybe_push(needed : byte;p : tnode;isint64 : boolean) : boolean;
+      var
+         pushed : boolean;
+         {hregister : tregister; }
+{$ifdef TEMPS_NOT_PUSH}
+         href : treference;
+{$endif TEMPS_NOT_PUSH}
+      begin
+         if needed>usablereg32 then
+           begin
+              if (p.location.loc=LOC_REGISTER) then
+                begin
+                   if isint64 then
+                     begin
+{$ifdef TEMPS_NOT_PUSH}
+                        gettempofsizereference(href,8);
+                        p.temp_offset:=href.offset;
+                        href.offset:=href.offset+4;
+                        exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p.location.registerhigh,href)));
+                        href.offset:=href.offset-4;
+{$else TEMPS_NOT_PUSH}
+                        exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerhigh)));
+{$endif TEMPS_NOT_PUSH}
+                        ungetregister32(p.location.registerhigh);
+                     end
+{$ifdef TEMPS_NOT_PUSH}
+                   else
+                     begin
+                        gettempofsizereference(href,4);
+                        p.temp_offset:=href.offset;
+                     end
+{$endif TEMPS_NOT_PUSH}
+                     ;
+                   pushed:=true;
+{$ifdef TEMPS_NOT_PUSH}
+                   exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p.location.register,href)));
+{$else TEMPS_NOT_PUSH}
+                   exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.register)));
+{$endif TEMPS_NOT_PUSH}
+                   ungetregister32(p.location.register);
+                end
+              else if (p.location.loc in [LOC_MEM,LOC_REFERENCE]) and
+                      ((p.location.reference.base<>R_NO) or
+                       (p.location.reference.index<>R_NO)
+                      ) then
+                  begin
+                     del_reference(p.location.reference);
+                     getexplicitregister32(R_EDI);
+                     emit_ref_reg(A_LEA,S_L,newreference(p.location.reference),R_EDI);
+{$ifdef TEMPS_NOT_PUSH}
+                     gettempofsizereference(href,4);
+                     exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
+                     p.temp_offset:=href.offset;
+{$else TEMPS_NOT_PUSH}
+                     exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
+{$endif TEMPS_NOT_PUSH}
+                     ungetregister32(R_EDI);
+                     pushed:=true;
+                  end
+              else pushed:=false;
+           end
+         else pushed:=false;
+         maybe_push:=pushed;
+      end;
+
+{$ifdef TEMPS_NOT_PUSH}
+    function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
+
+      var
+         pushed : boolean;
+         href : treference;
+
+      begin
+         if needed>usablereg32 then
+           begin
+              if (p^.location.loc=LOC_REGISTER) then
+                begin
+                   if isint64(p^.resulttype) then
+                     begin
+                        gettempofsizereference(href,8);
+                        p^.temp_offset:=href.offset;
+                        href.offset:=href.offset+4;
+                        exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p^.location.registerhigh,href)));
+                        href.offset:=href.offset-4;
+                        ungetregister32(p^.location.registerhigh);
+                     end
+                   else
+                     begin
+                        gettempofsizereference(href,4);
+                        p^.temp_offset:=href.offset;
+                     end;
+                   pushed:=true;
+                   exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p^.location.register,href)));
+                   ungetregister32(p^.location.register);
+                end
+              else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
+                      ((p^.location.reference.base<>R_NO) or
+                       (p^.location.reference.index<>R_NO)
+                      ) then
+                  begin
+                     del_reference(p^.location.reference);
+                     getexplicitregister32(R_EDI);
+                     emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
+                       R_EDI);
+                     gettempofsizereference(href,4);
+                     exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
+                     ungetregister32(R_EDI);
+                     p^.temp_offset:=href.offset;
+                     pushed:=true;
+                  end
+              else pushed:=false;
+           end
+         else pushed:=false;
+         maybe_push:=pushed;
+      end;
+{$endif TEMPS_NOT_PUSH}
+
+
+    procedure restore(p : tnode;isint64 : boolean);
+      var
+         hregister :  tregister;
+{$ifdef TEMPS_NOT_PUSH}
+         href : treference;
+{$endif TEMPS_NOT_PUSH}
+      begin
+         hregister:=getregister32;
+{$ifdef TEMPS_NOT_PUSH}
+         reset_reference(href);
+         href.base:=procinfo^.frame_pointer;
+         href.offset:=p.temp_offset;
+         emit_ref_reg(A_MOV,S_L,href,hregister);
+{$else  TEMPS_NOT_PUSH}
+         exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,hregister)));
+{$endif TEMPS_NOT_PUSH}
+         if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+           begin
+              p.location.register:=hregister;
+              if isint64 then
+                begin
+                   p.location.registerhigh:=getregister32;
+{$ifdef TEMPS_NOT_PUSH}
+                   href.offset:=p.temp_offset+4;
+                   emit_ref_reg(A_MOV,S_L,p.location.registerhigh);
+                   { set correctly for release ! }
+                   href.offset:=p.temp_offset;
+{$else  TEMPS_NOT_PUSH}
+                   exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,p.location.registerhigh)));
+{$endif TEMPS_NOT_PUSH}
+                end;
+           end
+         else
+           begin
+              reset_reference(p.location.reference);
+              { any reasons why this was moved into the index register ? }
+              { normally usage of base register is much better (FK)      }
+              p.location.reference.base:=hregister;
+              { Why is this done? We can never be sure about p.left
+                because otherwise secondload fails !!!
+              set_location(p.left^.location,p.location);}
+           end;
+{$ifdef TEMPS_NOT_PUSH}
+         ungetiftemp(href);
+{$endif TEMPS_NOT_PUSH}
+      end;
+
+
+    procedure pushsetelement(p : tnode);
+      var
+         hr,hr16,hr32 : tregister;
+      begin
+      { copy the element on the stack, slightly complicated }
+        if p.nodetype=ordconstn then
+         begin
+           if target_os.stackalignment=4 then
+             exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,tordconstnode(p).value)))
+           else
+             exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_W,tordconstnode(p).value)));
+         end
+        else
+         begin
+           case p.location.loc of
+             LOC_REGISTER,
+             LOC_CREGISTER :
+               begin
+                 hr:=p.location.register;
+                 case hr of
+                   R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
+                     begin
+                       hr16:=reg32toreg16(hr);
+                       hr32:=hr;
+                     end;
+                   R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
+                     begin
+                       hr16:=hr;
+                       hr32:=reg16toreg32(hr);
+                     end;
+                   R_AL,R_BL,R_CL,R_DL :
+                     begin
+                       hr16:=reg8toreg16(hr);
+                       hr32:=reg8toreg32(hr);
+                     end;
+                 end;
+                 if target_os.stackalignment=4 then
+                   exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,hr32)))
+                 else
+                   exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,hr16)));
+                 ungetregister32(hr32);
+               end;
+           else
+             begin
+               { you can't push more bytes than the size of the element, }
+               { because this may cross a page boundary and you'll get a }
+               { sigsegv (JM)                                            }
+               emit_push_mem_size(p.location.reference,1);
+               del_reference(p.location.reference);
+             end;
+           end;
+         end;
+      end;
+
+    procedure push_value_para(p:tnode;inlined,is_cdecl:boolean;
+                                para_offset:longint;alignment : longint);
+      var
+        tempreference : treference;
+        r : preference;
+        opsize : topsize;
+        op : tasmop;
+        hreg : tregister;
+        size : longint;
+        hlabel : pasmlabel;
+      begin
+        case p.location.loc of
+           LOC_REGISTER,
+           LOC_CREGISTER:
+             begin
+                case p.location.register of
+                   R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
+                   R_EDI,R_ESP,R_EBP :
+                      begin
+                        if p.resulttype^.size=8 then
+                          begin
+                             inc(pushedparasize,8);
+                             if inlined then
+                               begin
+                                  r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                  exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
+                                    p.location.registerlow,r)));
+                                  r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
+                                  exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
+                                    p.location.registerhigh,r)));
+                               end
+                             else
+                               exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerhigh)));
+                             ungetregister32(p.location.registerhigh);
+                               exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.registerlow)));
+                             ungetregister32(p.location.registerlow);
+                          end
+                        else
+                          begin
+                             inc(pushedparasize,4);
+                             if inlined then
+                               begin
+                                  r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                  exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
+                                    p.location.register,r)));
+                               end
+                             else
+                               exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p.location.register)));
+                             ungetregister32(p.location.register);
+                          end;
+                      end;
+                   R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
+                      begin
+                        if alignment=4 then
+                          begin
+                            opsize:=S_L;
+                            hreg:=reg16toreg32(p.location.register);
+                            inc(pushedparasize,4);
+                          end
+                        else
+                          begin
+                            opsize:=S_W;
+                            hreg:=p.location.register;
+                            inc(pushedparasize,2);
+                          end;
+                        if inlined then
+                          begin
+                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                            exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
+                          end
+                        else
+                          exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
+                        ungetregister32(reg16toreg32(p.location.register));
+                      end;
+                   R_AL,R_BL,R_CL,R_DL:
+                      begin
+                        if alignment=4 then
+                          begin
+                            opsize:=S_L;
+                            hreg:=reg8toreg32(p.location.register);
+                            inc(pushedparasize,4);
+                          end
+                        else
+                          begin
+                            opsize:=S_W;
+                            hreg:=reg8toreg16(p.location.register);
+                            inc(pushedparasize,2);
+                          end;
+                        { we must push always 16 bit }
+                        if inlined then
+                          begin
+                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                            exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
+                          end
+                        else
+                          exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
+                        ungetregister32(reg8toreg32(p.location.register));
+                      end;
+                   else internalerror(1899);
+                end;
+             end;
+           LOC_FPU:
+             begin
+                size:=align(pfloatdef(p.resulttype)^.size,alignment);
+                inc(pushedparasize,size);
+                if not inlined then
+                 emit_const_reg(A_SUB,S_L,size,R_ESP);
+{$ifdef GDB}
+                if (cs_debuginfo in aktmoduleswitches) and
+                   (exprasmlist^.first=exprasmlist^.last) then
+                  exprasmlist^.concat(new(pai_force_line,init));
+{$endif GDB}
+                r:=new_reference(R_ESP,0);
+                floatstoreops(pfloatdef(p.resulttype)^.typ,op,opsize);
+                { this is the easiest case for inlined !! }
+                if inlined then
+                  begin
+                     r^.base:=procinfo^.framepointer;
+                     r^.offset:=para_offset-pushedparasize;
+                  end;
+                exprasmlist^.concat(new(paicpu,op_ref(op,opsize,r)));
+                dec(fpuvaroffset);
+             end;
+           LOC_CFPUREGISTER:
+             begin
+                exprasmlist^.concat(new(paicpu,op_reg(A_FLD,S_NO,
+                  correct_fpuregister(p.location.register,fpuvaroffset))));
+                size:=align(pfloatdef(p.resulttype)^.size,alignment);
+                inc(pushedparasize,size);
+                if not inlined then
+                 emit_const_reg(A_SUB,S_L,size,R_ESP);
+{$ifdef GDB}
+                if (cs_debuginfo in aktmoduleswitches) and
+                   (exprasmlist^.first=exprasmlist^.last) then
+                  exprasmlist^.concat(new(pai_force_line,init));
+{$endif GDB}
+                r:=new_reference(R_ESP,0);
+                floatstoreops(pfloatdef(p.resulttype)^.typ,op,opsize);
+                { this is the easiest case for inlined !! }
+                if inlined then
+                  begin
+                     r^.base:=procinfo^.framepointer;
+                     r^.offset:=para_offset-pushedparasize;
+                  end;
+                exprasmlist^.concat(new(paicpu,op_ref(op,opsize,r)));
+             end;
+           LOC_REFERENCE,LOC_MEM:
+             begin
+                tempreference:=p.location.reference;
+                del_reference(p.location.reference);
+                case p.resulttype^.deftype of
+                  enumdef,
+                  orddef :
+                    begin
+                      case p.resulttype^.size of
+                       8 : begin
+                             inc(pushedparasize,8);
+                             if inlined then
+                               begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                                 getexplicitregister32(R_EDI);
+                                 inc(tempreference.offset,4);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                               end
+                             else
+                               begin
+                                 inc(tempreference.offset,4);
+                                 emit_push_mem(tempreference);
+                                 dec(tempreference.offset,4);
+                                 emit_push_mem(tempreference);
+                               end;
+                           end;
+                       4 : begin
+                             inc(pushedparasize,4);
+                             if inlined then
+                               begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                               end
+                             else
+                               emit_push_mem(tempreference);
+                           end;
+                     1,2 : begin
+                             if alignment=4 then
+                              begin
+                                opsize:=S_L;
+                                hreg:=R_EDI;
+                                inc(pushedparasize,4);
+                              end
+                             else
+                              begin
+                                opsize:=S_W;
+                                hreg:=R_DI;
+                                inc(pushedparasize,2);
+                              end;
+                             if inlined then
+                              begin
+                                getexplicitregister32(R_EDI);
+                                emit_ref_reg(A_MOV,opsize,
+                                  newreference(tempreference),hreg);
+                                r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
+                                ungetregister32(R_EDI);
+                              end
+                             else
+                              emit_push_mem_size(tempreference,p.resulttype^.size);
+                           end;
+                         else
+                           internalerror(234231);
+                      end;
+                    end;
+                  floatdef :
+                    begin
+                      case pfloatdef(p.resulttype)^.typ of
+                        f32bit,
+                        s32real :
+                          begin
+                             inc(pushedparasize,4);
+                             if inlined then
+                               begin
+                                  getexplicitregister32(R_EDI);
+                                  emit_ref_reg(A_MOV,S_L,
+                                    newreference(tempreference),R_EDI);
+                                  r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                  exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                  ungetregister32(R_EDI);
+                               end
+                             else
+                               emit_push_mem(tempreference);
+                          end;
+                        s64real,
+                        s64comp :
+                          begin
+                            inc(pushedparasize,4);
+                            inc(tempreference.offset,4);
+                            if inlined then
+                              begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                              end
+                            else
+                              emit_push_mem(tempreference);
+                            inc(pushedparasize,4);
+                            dec(tempreference.offset,4);
+                            if inlined then
+                              begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                              end
+                            else
+                              emit_push_mem(tempreference);
+                          end;
+                        s80real :
+                          begin
+                            inc(pushedparasize,4);
+                            if alignment=4 then
+                              inc(tempreference.offset,8)
+                            else
+                              inc(tempreference.offset,6);
+                            if inlined then
+                              begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                              end
+                            else
+                              emit_push_mem(tempreference);
+                            dec(tempreference.offset,4);
+                            inc(pushedparasize,4);
+                            if inlined then
+                              begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,S_L,
+                                   newreference(tempreference),R_EDI);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                                 ungetregister32(R_EDI);
+                              end
+                            else
+                              emit_push_mem(tempreference);
+                            if alignment=4 then
+                              begin
+                                opsize:=S_L;
+                                hreg:=R_EDI;
+                                inc(pushedparasize,4);
+                                dec(tempreference.offset,4);
+                              end
+                            else
+                              begin
+                                opsize:=S_W;
+                                hreg:=R_DI;
+                                inc(pushedparasize,2);
+                                dec(tempreference.offset,2);
+                              end;
+                            if inlined then
+                              begin
+                                 getexplicitregister32(R_EDI);
+                                 emit_ref_reg(A_MOV,opsize,
+                                   newreference(tempreference),hreg);
+                                 r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                 exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
+                                 ungetregister32(R_EDI);
+                              end
+                            else
+                              exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,opsize,
+                                newreference(tempreference))));
+                        end;
+                      end;
+                    end;
+                  pointerdef,
+                  procvardef,
+                  classrefdef:
+                    begin
+                       inc(pushedparasize,4);
+                       if inlined then
+                         begin
+                            getexplicitregister32(R_EDI);
+                            emit_ref_reg(A_MOV,S_L,
+                              newreference(tempreference),R_EDI);
+                            r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                            exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
+                            ungetregister32(R_EDI);
+                         end
+                       else
+                         emit_push_mem(tempreference);
+                    end;
+                  arraydef,
+                  recorddef,
+                  stringdef,
+                  setdef,
+                  objectdef :
+                    begin
+                       { even some structured types are 32 bit }
+                       if is_widestring(p.resulttype) or
+                          is_ansistring(p.resulttype) or
+                          is_smallset(p.resulttype) or
+                          ((p.resulttype^.deftype in [recorddef,arraydef]) and
+                           (
+                            (p.resulttype^.deftype<>arraydef) or not
+                            (parraydef(p.resulttype)^.IsConstructor or
+                             parraydef(p.resulttype)^.isArrayOfConst or
+                             is_open_array(p.resulttype))
+                           ) and
+                           (p.resulttype^.size<=4)
+                          ) or
+                          ((p.resulttype^.deftype=objectdef) and
+                           pobjectdef(p.resulttype)^.is_class) then
+                         begin
+                            if (p.resulttype^.size>2) or
+                               ((alignment=4) and (p.resulttype^.size>0)) then
+                              begin
+                                inc(pushedparasize,4);
+                                if inlined then
+                                  begin
+                                    r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                    concatcopy(tempreference,r^,4,false,false);
+                                  end
+                                else
+                                  emit_push_mem(tempreference);
+                              end
+                            else
+                              begin
+                                if p.resulttype^.size>0 then
+                                  begin
+                                    inc(pushedparasize,2);
+                                    if inlined then
+                                      begin
+                                        r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                                        concatcopy(tempreference,r^,2,false,false);
+                                      end
+                                    else
+                                      exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_W,newreference(tempreference))));
+                                  end;
+                              end;
+                         end
+                       { call by value open array ? }
+                       else if is_cdecl then
+                         begin
+                           { push on stack }
+                           size:=align(p.resulttype^.size,alignment);
+                           inc(pushedparasize,size);
+                           emit_const_reg(A_SUB,S_L,size,R_ESP);
+                           r:=new_reference(R_ESP,0);
+                           concatcopy(tempreference,r^,size,false,false);
+                         end
+                       else
+                         internalerror(8954);
+                    end;
+                  else
+                    CGMessage(cg_e_illegal_expression);
+                end;
+             end;
+           LOC_JUMP:
+             begin
+                getlabel(hlabel);
+                if alignment=4 then
+                 begin
+                   opsize:=S_L;
+                   inc(pushedparasize,4);
+                 end
+                else
+                 begin
+                   opsize:=S_W;
+                   inc(pushedparasize,2);
+                 end;
+                emitlab(truelabel);
+                if inlined then
+                  begin
+                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     emit_const_ref(A_MOV,opsize,1,r);
+                  end
+                else
+                  exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,1)));
+                emitjmp(C_None,hlabel);
+                emitlab(falselabel);
+                if inlined then
+                  begin
+                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     emit_const_ref(A_MOV,opsize,0,r);
+                  end
+                else
+                  exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,0)));
+                emitlab(hlabel);
+             end;
+           LOC_FLAGS:
+             begin
+                if not(R_EAX in unused) then
+                  begin
+                    getexplicitregister32(R_EDI);
+                    emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
+                  end;
+                emit_flag2reg(p.location.resflags,R_AL);
+                emit_reg_reg(A_MOVZX,S_BW,R_AL,R_AX);
+                if alignment=4 then
+                 begin
+                   opsize:=S_L;
+                   hreg:=R_EAX;
+                   inc(pushedparasize,4);
+                 end
+                else
+                 begin
+                   opsize:=S_W;
+                   hreg:=R_AX;
+                   inc(pushedparasize,2);
+                 end;
+                if inlined then
+                  begin
+                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
+                  end
+                else
+                  exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
+                if not(R_EAX in unused) then
+                  begin
+                    emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
+                    ungetregister32(R_EDI);
+                  end;
+             end;
+{$ifdef SUPPORT_MMX}
+           LOC_MMXREGISTER,
+           LOC_CMMXREGISTER:
+             begin
+                inc(pushedparasize,8); { was missing !!! (PM) }
+                emit_const_reg(
+                  A_SUB,S_L,8,R_ESP);
+{$ifdef GDB}
+                if (cs_debuginfo in aktmoduleswitches) and
+                   (exprasmlist^.first=exprasmlist^.last) then
+                  exprasmlist^.concat(new(pai_force_line,init));
+{$endif GDB}
+                if inlined then
+                  begin
+                     r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
+                     exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOVQ,S_NO,
+                       p.location.register,r)));
+                  end
+                else
+                   begin
+                      r:=new_reference(R_ESP,0);
+                      exprasmlist^.concat(new(paicpu,op_reg_ref(
+                        A_MOVQ,S_NO,p.location.register,r)));
+                   end;
+             end;
+{$endif SUPPORT_MMX}
+        end;
+      end;
+
+{*****************************************************************************
+                           Emit Functions
+*****************************************************************************}
+
+    procedure maketojumpbool(p : tnode);
+    {
+      produces jumps to true respectively false labels using boolean expressions
+    }
+      var
+        opsize : topsize;
+        storepos : tfileposinfo;
+      begin
+         if p.error then
+           exit;
+         storepos:=aktfilepos;
+         aktfilepos:=p.fileinfo;
+         if is_boolean(p.resulttype) then
+           begin
+              if is_constboolnode(p) then
+                begin
+                   if p.value<>0 then
+                     emitjmp(C_None,truelabel)
+                   else
+                     emitjmp(C_None,falselabel);
+                end
+              else
+                begin
+                   opsize:=def_opsize(p.resulttype);
+                   case p.location.loc of
+                      LOC_CREGISTER,LOC_REGISTER : begin
+                                        emit_reg_reg(A_OR,opsize,p.location.register,
+                                          p.location.register);
+                                        ungetregister(p.location.register);
+                                        emitjmp(C_NZ,truelabel);
+                                        emitjmp(C_None,falselabel);
+                                     end;
+                      LOC_MEM,LOC_REFERENCE : begin
+                                        emit_const_ref(
+                                          A_CMP,opsize,0,newreference(p.location.reference));
+                                        del_reference(p.location.reference);
+                                        emitjmp(C_NZ,truelabel);
+                                        emitjmp(C_None,falselabel);
+                                     end;
+                      LOC_FLAGS : begin
+                                     emitjmp(flag_2_cond[p.location.resflags],truelabel);
+                                     emitjmp(C_None,falselabel);
+                                  end;
+                   end;
+                end;
+           end
+         else
+           CGMessage(type_e_mismatch);
+         aktfilepos:=storepos;
+      end;
+
+
+    { produces if necessary overflowcode }
+    procedure emitoverflowcheck(p:tnode);
+      var
+         hl : pasmlabel;
+      begin
+         if not(cs_check_overflow in aktlocalswitches) then
+          exit;
+         getlabel(hl);
+         if not ((p.resulttype^.deftype=pointerdef) or
+                ((p.resulttype^.deftype=orddef) and
+                 (porddef(p.resulttype)^.typ in [u64bit,u16bit,u32bit,u8bit,uchar,
+                                                  bool8bit,bool16bit,bool32bit]))) then
+           emitjmp(C_NO,hl)
+         else
+           emitjmp(C_NB,hl);
+         emitcall('FPC_OVERFLOW');
+         emitlab(hl);
+      end;
+
+    { produces range check code, while one of the operands is a 64 bit
+      integer }
+    procedure emitrangecheck64(p : tnode;todef : pdef);
+
+      begin
+
+         CGMessage(cg_w_64bit_range_check_not_supported);
+         {internalerror(28699);}
+      end;
+
+     { produces if necessary rangecheckcode }
+     procedure emitrangecheck(p:tnode;todef:pdef);
+     {
+       generate range checking code for the value at location t. The
+       type used is the checked against todefs ranges. fromdef (p.resulttype)
+       is the original type used at that location, when both defs are
+       equal the check is also insert (needed for succ,pref,inc,dec)
+     }
+      var
+        neglabel,
+        poslabel : pasmlabel;
+        href   : treference;
+        rstr   : string;
+        hreg   : tregister;
+        opsize : topsize;
+        op     : tasmop;
+        fromdef : pdef;
+        lto,hto,
+        lfrom,hfrom : longint;
+        doublebound,
+        is_reg,
+        popecx : boolean;
+      begin
+        { range checking on and range checkable value? }
+        if not(cs_check_range in aktlocalswitches) or
+           not(todef^.deftype in [orddef,enumdef,arraydef]) then
+          exit;
+        { only check when assigning to scalar, subranges are different,
+          when todef=fromdef then the check is always generated }
+        fromdef:=p.resulttype;
+        if is_64bitint(fromdef) or is_64bitint(todef) then
+          begin
+             emitrangecheck64(p,todef);
+             exit;
+          end;
+        {we also need lto and hto when checking if we need to use doublebound!
+        (JM)}
+        getrange(todef,lto,hto);
+        if todef<>fromdef then
+         begin
+           getrange(p.resulttype,lfrom,hfrom);
+           { first check for not being u32bit, then if the to is bigger than
+             from }
+           if (lto<hto) and (lfrom<hfrom) and
+              (lto<=lfrom) and (hto>=hfrom) then
+            exit;
+         end;
+        { generate the rangecheck code for the def where we are going to
+          store the result }
+        doublebound:=false;
+        case todef^.deftype of
+          orddef :
+            begin
+              porddef(todef)^.genrangecheck;
+              rstr:=porddef(todef)^.getrangecheckstring;
+              doublebound:=(porddef(todef)^.typ=u32bit) and (lto>hto);
+            end;
+          enumdef :
+            begin
+              penumdef(todef)^.genrangecheck;
+              rstr:=penumdef(todef)^.getrangecheckstring;
+            end;
+          arraydef :
+            begin
+              parraydef(todef)^.genrangecheck;
+              rstr:=parraydef(todef)^.getrangecheckstring;
+              doublebound:=(lto>hto);
+            end;
+        end;
+      { get op and opsize }
+        opsize:=def2def_opsize(fromdef,u32bitdef);
+        if opsize in [S_B,S_W,S_L] then
+         op:=A_MOV
+        else
+         if is_signed(fromdef) then
+          op:=A_MOVSX
+         else
+          op:=A_MOVZX;
+        is_reg:=(p.location.loc in [LOC_REGISTER,LOC_CREGISTER]);
+        if is_reg then
+          hreg:=p.location.register;
+        if not target_os.use_bound_instruction then
+         begin
+           { FPC_BOUNDCHECK needs to be called with
+              %ecx - value
+              %edi - pointer to the ranges }
+           popecx:=false;
+           if not(is_reg) or
+              (p.location.register<>R_ECX) then
+            begin
+              if not(R_ECX in unused) then
+               begin
+                 exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
+                 popecx:=true;
+               end
+                 else exprasmlist^.concat(new(pairegalloc,alloc(R_ECX)));
+              if is_reg then
+               emit_reg_reg(op,opsize,p.location.register,R_ECX)
+              else
+               emit_ref_reg(op,opsize,newreference(p.location.reference),R_ECX);
+            end;
+           if doublebound then
+            begin
+              getlabel(neglabel);
+              getlabel(poslabel);
+              emit_reg_reg(A_OR,S_L,R_ECX,R_ECX);
+              emitjmp(C_L,neglabel);
+            end;
+           { insert bound instruction only }
+           getexplicitregister32(R_EDI);
+           exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),0,R_EDI)));
+           emitcall('FPC_BOUNDCHECK');
+           ungetregister32(R_EDI);
+           { u32bit needs 2 checks }
+           if doublebound then
+            begin
+              emitjmp(C_None,poslabel);
+              emitlab(neglabel);
+              getexplicitregister32(R_EDI);
+              exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),8,R_EDI)));
+              emitcall('FPC_BOUNDCHECK');
+              ungetregister32(R_EDI);
+              emitlab(poslabel);
+            end;
+           if popecx then
+            exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
+           else exprasmlist^.concat(new(pairegalloc,dealloc(R_ECX)));
+         end
+        else
+         begin
+           reset_reference(href);
+           href.symbol:=newasmsymbol(rstr);
+           { load the value in a register }
+           if is_reg then
+            begin
+              { be sure that hreg is a 32 bit reg, if not load it in %edi }
+              if p.location.register in [R_EAX..R_EDI] then
+               hreg:=p.location.register
+              else
+               begin
+                 getexplicitregister32(R_EDI);
+                 emit_reg_reg(op,opsize,p.location.register,R_EDI);
+                 hreg:=R_EDI;
+               end;
+            end
+           else
+            begin
+              getexplicitregister32(R_EDI);
+              emit_ref_reg(op,opsize,newreference(p.location.reference),R_EDI);
+              hreg:=R_EDI;
+            end;
+           if doublebound then
+            begin
+              getlabel(neglabel);
+              getlabel(poslabel);
+              emit_reg_reg(A_TEST,S_L,hreg,hreg);
+              emitjmp(C_L,neglabel);
+            end;
+           { insert bound instruction only }
+           exprasmlist^.concat(new(paicpu,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
+           { u32bit needs 2 checks }
+           if doublebound then
+            begin
+              href.offset:=8;
+              emitjmp(C_None,poslabel);
+              emitlab(neglabel);
+              exprasmlist^.concat(new(paicpu,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
+              emitlab(poslabel);
+            end;
+           if hreg = R_EDI then
+             ungetregister32(R_EDI);
+         end;
+      end;
+
+
+   { DO NOT RELY on the fact that the tnode is not yet swaped
+     because of inlining code PM }
+    procedure firstcomplex(p : tnode);
+      var
+         hp : tnode;
+      begin
+         { always calculate boolean AND and OR from left to right }
+         if (p.treetype in [orn,andn]) and
+            (p.left^.resulttype^.deftype=orddef) and
+            (porddef(p.left^.resulttype)^.typ in [bool8bit,bool16bit,bool32bit]) then
+           begin
+             { p.swaped:=false}
+             if p.swaped then
+               internalerror(234234);
+           end
+         else
+           if (p.left^.registers32<p.right^.registers32) and
+           { the following check is appropriate, because all }
+           { 4 registers are rarely used and it is thereby   }
+           { achieved that the extra code is being dropped   }
+           { by exchanging not commutative operators     }
+              (p.right^.registers32<=4) then
+            begin
+              hp:=p.left;
+              p.left:=p.right;
+              p.right:=hp;
+              p.swaped:=not p.swaped;
+            end;
+         {else
+           p.swaped:=false; do not modify }
+      end;
+{$endif}
+
+end.
+{
+  $Log$
+  Revision 1.1  2000-10-01 19:58:40  peter
+    * new file
+
+}