Selaa lähdekoodia

+ Xtensa: initial support of the windowed abi

git-svn-id: trunk@44370 -
florian 5 vuotta sitten
vanhempi
commit
d7126bd42c
3 muutettua tiedostoa jossa 148 lisäystä ja 79 poistoa
  1. 84 53
      compiler/xtensa/cgcpu.pas
  2. 6 1
      compiler/xtensa/cpupara.pas
  3. 58 25
      compiler/xtensa/cpupi.pas

+ 84 - 53
compiler/xtensa/cgcpu.pas

@@ -566,58 +566,84 @@ implementation
           begin
             regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
             a_reg_alloc(list,NR_STACK_POINTER_REG);
-            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
-              Include(regs,RS_A15);
-            if pi_do_call in current_procinfo.flags then
-              Include(regs,RS_A0);
-            if regs<>[] then
-               begin
-                 for r:=RS_A0 to RS_A15 do
-                   if r in regs then
-                     inc(registerarea,4);
-               end;
-
-            inc(localsize,registerarea);
-            if LocalSize<>0 then
-              begin
-                localsize:=align(localsize,current_settings.alignment.localalignmax);
-                a_reg_alloc(list,NR_STACK_POINTER_REG);
-                list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize));
-              end;
+            case target_info.abi of
+              abi_xtensa_call0:
+                begin
+                  if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+                    Include(regs,RS_A15);
+                  if pi_do_call in current_procinfo.flags then
+                    Include(regs,RS_A0);
+                  if regs<>[] then
+                     begin
+                       for r:=RS_A0 to RS_A15 do
+                         if r in regs then
+                           inc(registerarea,4);
+                     end;
 
-            reference_reset(ref,4,[]);
-            ref.base:=NR_STACK_POINTER_REG;
-            ref.offset:=localsize;
-            if ref.offset>1024 then
-              begin
-                if ref.offset<=1024+32512 then
-                  begin
-                    list.concat(taicpu.op_reg_reg_const(A_ADDMI,NR_A8,NR_STACK_POINTER_REG,ref.offset and $fffffc00));
-                    ref.offset:=ref.offset and $3ff;
-                    ref.base:=NR_A8;
-                  end
-                else
-                  { fix me! }
-                  Internalerror(2020031101);
-              end;
+                  inc(localsize,registerarea);
+                  if LocalSize<>0 then
+                    begin
+                      localsize:=align(localsize,current_settings.alignment.localalignmax);
+                      a_reg_alloc(list,NR_STACK_POINTER_REG);
+                      list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize));
+                    end;
+
+                  reference_reset(ref,4,[]);
+                  ref.base:=NR_STACK_POINTER_REG;
+                  ref.offset:=localsize;
+                  if ref.offset>1024 then
+                    begin
+                      if ref.offset<=1024+32512 then
+                        begin
+                          list.concat(taicpu.op_reg_reg_const(A_ADDMI,NR_A8,NR_STACK_POINTER_REG,ref.offset and $fffffc00));
+                          ref.offset:=ref.offset and $3ff;
+                          ref.base:=NR_A8;
+                        end
+                      else
+                        { fix me! }
+                        Internalerror(2020031101);
+                    end;
+
+                  if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+                    begin
+                      dec(ref.offset,4);
+                      list.concat(taicpu.op_reg_ref(A_S32I,NR_A15,ref));
+                      a_reg_alloc(list,NR_FRAME_POINTER_REG);
+                      list.concat(taicpu.op_reg_reg(A_MOV,NR_A15,NR_STACK_POINTER_REG));
+                    end;
 
-            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
-              begin
-                dec(ref.offset,4);
-                list.concat(taicpu.op_reg_ref(A_S32I,NR_A15,ref));
-                a_reg_alloc(list,NR_FRAME_POINTER_REG);
-                list.concat(taicpu.op_reg_reg(A_MOV,NR_A15,NR_STACK_POINTER_REG));
-              end;
+                  if regs<>[] then
+                    begin
+                      for r:=RS_A14 downto RS_A0 do
+                        if r in regs then
+                          begin
+                            dec(ref.offset,4);
+                            list.concat(taicpu.op_reg_ref(A_S32I,newreg(R_INTREGISTER,r,R_SUBWHOLE),ref));
+                          end;
+                    end;
+                end;
+              abi_xtensa_windowed:
+                begin
+                  if stack_parameters and (pi_estimatestacksize in current_procinfo.flags) then
+                    begin
+                      if localsize>txtensaprocinfo(current_procinfo).stackframesize then
+                        internalerror(2020031402)
+                      else
+                        localsize:=txtensaprocinfo(current_procinfo).stackframesize-registerarea;
+                    end
+                  else
+                    begin
+                      { spill area }
+                      inc(localsize,max(txtensaprocinfo(current_procinfo).maxcall,4)*4);
 
-            if regs<>[] then
-               begin
-                 for r:=RS_A14 downto RS_A0 do
-                   if r in regs then
-                     begin
-                       dec(ref.offset,4);
-                       list.concat(taicpu.op_reg_ref(A_S32I,newreg(R_INTREGISTER,r,R_SUBWHOLE),ref));
-                     end;
-               end;
+                      localsize:=align(localsize,current_settings.alignment.localalignmax);
+                    end;
+
+                  list.concat(taicpu.op_reg_const(A_ENTRY,NR_STACK_POINTER_REG,localsize));
+                end;
+              else
+                Internalerror(2020031401);
+            end;
           end;
       end;
 
@@ -625,12 +651,17 @@ implementation
     procedure tcgcpu.g_proc_exit(list : TAsmList; parasize : longint;
      nostackframe : boolean);
       begin
-        if target_info.abi=abi_xtensa_windowed then
-          list.Concat(taicpu.op_none(A_RETW))
-        else
-          list.Concat(taicpu.op_none(A_RET));
+        case target_info.abi of
+          abi_xtensa_windowed:
+            list.Concat(taicpu.op_none(A_RETW));
+          abi_xtensa_call0:
+            list.Concat(taicpu.op_none(A_RET));
+          else
+            Internalerror(2020031403);
+        end;
       end;
 
+
     procedure tcgcpu.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
 
       function is_b4const(v: tcgint): boolean;

+ 6 - 1
compiler/xtensa/cpupara.pas

@@ -59,7 +59,12 @@ unit cpupara;
 
     function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
       begin
-        result:=[RS_A0..RS_A7];
+        { we have actually to check what calling instruction is used, but we do not handle this,
+          instead CALL(X)8 is used always }
+        if target_info.abi=abi_xtensa_windowed then
+          result:=[RS_A8..RS_A15]
+        else
+          result:=[RS_A0..RS_A7];
       end;
 
 

+ 58 - 25
compiler/xtensa/cpupi.pas

@@ -37,10 +37,11 @@ unit cpupi;
       txtensaprocinfo = class(tcgprocinfo)
           callins,callxins : TAsmOp;
           stackframesize,
-          floatregstart : aint;
           stackpaddingreg: TSuperRegister;
 
           needs_frame_pointer: boolean;
+          { highest N used in a call instruction }
+          maxcall : Byte;
           // procedure handle_body_start;override;
           // procedure after_pass1;override;            
           constructor create(aparent: tprocinfo); override;
@@ -65,21 +66,31 @@ unit cpupi;
       begin
         inherited create(aparent);
         maxpushedparasize := 0;
-        framepointer:=NR_FRAME_POINTER_REG;
         if target_info.abi=abi_xtensa_windowed then
           begin
             callins:=A_CALL8;
             callxins:=A_CALLX8;
+            { set properly }
+            maxcall:=8;
+
+            { we do not use a frame pointer for the windowed abi }
+            include(flags,pi_estimatestacksize);
+            framepointer:=NR_STACK_POINTER_REG;
           end
         else
           begin
             callins:=A_CALL0;
             callxins:=A_CALLX0;
-          end
+            maxcall:=0;
+            framepointer:=NR_FRAME_POINTER_REG;
+          end;
       end;
 
 
     procedure txtensaprocinfo.set_first_temp_offset;
+      var
+        localsize : aint;
+        i : longint;
       begin
         if (po_nostackframe in procdef.procoptions) then
           begin
@@ -93,37 +104,59 @@ unit cpupi;
           tg.setfirsttemp(-(1+12)*4)
         else
           tg.setfirsttemp(maxpushedparasize);
+
+        { estimate stack frame size }
+        if pi_estimatestacksize in flags then
+          begin
+            stackframesize:=maxpushedparasize+32;
+            localsize:=0;
+            for i:=0 to procdef.localst.SymList.Count-1 do
+              if tsym(procdef.localst.SymList[i]).typ=localvarsym then
+                inc(localsize,tabstractnormalvarsym(procdef.localst.SymList[i]).getsize);
+            inc(stackframesize,localsize);
+
+            localsize:=0;
+            for i:=0 to procdef.parast.SymList.Count-1 do
+              if tsym(procdef.parast.SymList[i]).typ=paravarsym then
+                begin
+                  if tabstractnormalvarsym(procdef.parast.SymList[i]).varspez in [vs_var,vs_out,vs_constref] then
+                    inc(localsize,4)
+                  else if is_open_string(tabstractnormalvarsym(procdef.parast.SymList[i]).vardef) then
+                    inc(localsize,256)
+                  else
+                    inc(localsize,tabstractnormalvarsym(procdef.parast.SymList[i]).getsize);
+                end;
+
+            inc(stackframesize,localsize);
+
+            if pi_needs_implicit_finally in flags then
+              inc(stackframesize,40);
+
+            if pi_uses_exceptions in flags then
+              inc(stackframesize,40);
+
+            if procdef.proctypeoption in [potype_constructor] then
+              inc(stackframesize,40*2);
+
+            inc(stackframesize,estimatedtempsize);
+
+            stackframesize:=Align(stackframesize,target_info.alignment.localalignmax);
+          end;
       end;
 
 
     function txtensaprocinfo.calc_stackframe_size:longint;
       var
-         firstfloatreg,lastfloatreg,
          r : byte;
-         floatsavesize : aword;
          regs: tcpuregisterset;
       begin
-        maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
-        floatsavesize:=0;
-        //case current_settings.fputype of
-        //  fpu_fd:
-        //    begin
-        //      floatsavesize:=0;
-        //      regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
-        //      for r:=RS_F0 to RS_F31 do
-        //        if r in regs then
-        //          inc(floatsavesize,8);
-        //    end;
-        //  else
-        //    ;
-        //end;
-        floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
-        result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
-
-        if tg.direction=1 then
-          floatregstart:=result-aint(floatsavesize)
+        if pi_estimatestacksize in flags then
+          result:=stackframesize
         else
-          floatregstart:=-result+maxpushedparasize;
+          begin
+            maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
+            result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize;
+          end;
       end;