Преглед изворни кода

+ Xtensa: basic operations for Xtensa implemented

git-svn-id: trunk@44324 -
florian пре 5 година
родитељ
комит
729425447f

+ 1 - 0
.gitattributes

@@ -1027,6 +1027,7 @@ compiler/xtensa/itcpugas.pas svneol=native#text/pascal
 compiler/xtensa/ncpuadd.pas svneol=native#text/pascal
 compiler/xtensa/ncpuadd.pas svneol=native#text/pascal
 compiler/xtensa/ncpucnv.pas svneol=native#text/pascal
 compiler/xtensa/ncpucnv.pas svneol=native#text/pascal
 compiler/xtensa/ncpumat.pas svneol=native#text/pascal
 compiler/xtensa/ncpumat.pas svneol=native#text/pascal
+compiler/xtensa/ncpuutil.pas svneol=native#text/pascal
 compiler/xtensa/racpugas.pas svneol=native#text/pascal
 compiler/xtensa/racpugas.pas svneol=native#text/pascal
 compiler/xtensa/raxtensa.pas svneol=native#text/pascal
 compiler/xtensa/raxtensa.pas svneol=native#text/pascal
 compiler/xtensa/rgcpu.pas svneol=native#text/pascal
 compiler/xtensa/rgcpu.pas svneol=native#text/pascal

+ 207 - 1
compiler/systems/t_embed.pas

@@ -96,7 +96,7 @@ Var
 begin
 begin
   WriteResponseFile:=False;
   WriteResponseFile:=False;
   linklibc:=(SharedLibFiles.Find('c')<>nil);
   linklibc:=(SharedLibFiles.Find('c')<>nil);
-{$if defined(ARM) or defined(i386) or defined(x86_64) or defined(AVR) or defined(MIPSEL) or defined(RISCV32)}
+{$if defined(ARM) or defined(i386) or defined(x86_64) or defined(AVR) or defined(MIPSEL) or defined(RISCV32) or defined(XTENSA)}
   prtobj:='';
   prtobj:='';
 {$else}
 {$else}
   prtobj:='prt0';
   prtobj:='prt0';
@@ -1351,6 +1351,212 @@ begin
     end;
     end;
   {$endif RISCV32}
   {$endif RISCV32}
 
 
+  {$ifdef XTENSA}
+  with linkres do
+    begin
+      Add('/* Script for -z combreloc: combine and sort reloc sections */');
+      Add('/* Copyright (C) 2014-2018 Free Software Foundation, Inc.');
+      Add('   Copying and distribution of this script, with or without modification,');
+      Add('   are permitted in any medium without royalty provided the copyright');
+      Add('   notice and this notice are preserved.  */');
+      Add('ENTRY(_start)');
+      Add('SEARCH_DIR("=/builds/idf/crosstool-NG/builds/xtensa-esp32-elf/xtensa-esp32-elf/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");');
+      Add('SECTIONS');
+      Add('{');
+      Add('  /* Read-only sections, merged into text segment: */');
+      Add('  PROVIDE (__executable_start = 0x400000); . = 0x400000 + SIZEOF_HEADERS;');
+      Add('  .interp         : { *(.interp) }');
+      Add('  .note.gnu.build-id : { *(.note.gnu.build-id) }');
+      Add('  .hash           : { *(.hash) }');
+      Add('  .gnu.hash       : { *(.gnu.hash) }');
+      Add('  .dynsym         : { *(.dynsym) }');
+      Add('  .dynstr         : { *(.dynstr) }');
+      Add('  .gnu.version    : { *(.gnu.version) }');
+      Add('  .gnu.version_d  : { *(.gnu.version_d) }');
+      Add('  .gnu.version_r  : { *(.gnu.version_r) }');
+      Add('  .rela.dyn       :');
+      Add('    {');
+      Add('      *(.rela.init)');
+      Add('      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
+      Add('      *(.rela.fini)');
+      Add('      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
+      Add('      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
+      Add('      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
+      Add('      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
+      Add('      *(.rela.ctors)');
+      Add('      *(.rela.dtors)');
+      Add('      *(.rela.got)');
+      Add('      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
+      Add('    }');
+      Add('  .rela.plt       : { *(.rela.plt) }');
+      Add('  /* .plt* sections are embedded in .text */');
+      Add('  .text           :');
+      Add('  {');
+      Add('    *(.got.plt* .plt*)');
+      Add('    KEEP (*(.init.literal))');
+      Add('    KEEP (*(SORT_NONE(.init)))');
+      Add('    *(.literal .text .stub .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)');
+      Add('    /* .gnu.warning sections are handled specially by elf32.em.  */');
+      Add('    *(.gnu.warning)');
+      Add('    KEEP (*(.fini.literal))');
+      Add('    KEEP (*(SORT_NONE(.fini)))');
+      Add('  } =0');
+      Add('  PROVIDE (__etext = .);');
+      Add('  PROVIDE (_etext = .);');
+      Add('  PROVIDE (etext = .);');
+      Add('  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }');
+      Add('  .rodata1        : { *(.rodata1) }');
+      Add('  .got.loc        : { *(.got.loc) }');
+      Add('  .xt_except_table   : ONLY_IF_RO { KEEP (*(.xt_except_table .xt_except_table.* .gnu.linkonce.e.*)) }');
+      Add('  .eh_frame_hdr : { *(.eh_frame_hdr) }');
+      Add('  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }');
+      Add('  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }');
+      Add('  /* Adjust the address for the data segment.  We want to adjust up to');
+      Add('     the same address within the page on the next page up.  */');
+      Add('  . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));');
+      Add('  /* Exception handling  */');
+      Add('  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }');
+      Add('  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }');
+      Add('  /* Thread Local Storage sections  */');
+      Add('  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }');
+      Add('  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }');
+      Add('  .preinit_array     :');
+      Add('  {');
+      Add('    PROVIDE_HIDDEN (__preinit_array_start = .);');
+      Add('    KEEP (*(.preinit_array))');
+      Add('    PROVIDE_HIDDEN (__preinit_array_end = .);');
+      Add('  }');
+      Add('  .init_array     :');
+      Add('  {');
+      Add('     PROVIDE_HIDDEN (__init_array_start = .);');
+      Add('     KEEP (*(SORT(.init_array.*)))');
+      Add('     KEEP (*(.init_array))');
+      Add('     PROVIDE_HIDDEN (__init_array_end = .);');
+      Add('  }');
+      Add('  .fini_array     :');
+      Add('  {');
+      Add('    PROVIDE_HIDDEN (__fini_array_start = .);');
+      Add('    KEEP (*(SORT(.fini_array.*)))');
+      Add('    KEEP (*(.fini_array))');
+      Add('    PROVIDE_HIDDEN (__fini_array_end = .);');
+      Add('  }');
+      Add('  .ctors          :');
+      Add('  {');
+      Add('    /* gcc uses crtbegin.o to find the start of');
+      Add('       the constructors, so we make sure it is');
+      Add('       first.  Because this is a wildcard, it');
+      Add('       doesn''t matter if the user does not');
+      Add('       actually link against crtbegin.o; the');
+      Add('       linker won''t look for a file to match a');
+      Add('       wildcard.  The wildcard also means that it');
+      Add('       doesn''t matter which directory crtbegin.o');
+      Add('       is in.  */');
+      Add('    KEEP (*crtbegin.o(.ctors))');
+      Add('    KEEP (*crtbegin?.o(.ctors))');
+      Add('    /* We don''t want to include the .ctor section from');
+      Add('       the crtend.o file until after the sorted ctors.');
+      Add('       The .ctor section from the crtend file contains the');
+      Add('       end of ctors marker and it must be last */');
+      Add('    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))');
+      Add('    KEEP (*(SORT(.ctors.*)))');
+      Add('    KEEP (*(.ctors))');
+      Add('  }');
+      Add('  .dtors          :');
+      Add('  {');
+      Add('    KEEP (*crtbegin.o(.dtors))');
+      Add('    KEEP (*crtbegin?.o(.dtors))');
+      Add('    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))');
+      Add('    KEEP (*(SORT(.dtors.*)))');
+      Add('    KEEP (*(.dtors))');
+      Add('  }');
+      Add('  .jcr            : { KEEP (*(.jcr)) }');
+      Add('  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }');
+      Add('  .xt_except_table   : ONLY_IF_RW { KEEP (*(.xt_except_table .xt_except_table.* .gnu.linkonce.e.*)) }');
+      Add('  .dynamic        : { *(.dynamic) }');
+      Add('  .got            : { *(.got) }');
+      Add('  .data           :');
+      Add('  {');
+      Add('    *(.data .data.* .gnu.linkonce.d.*)');
+      Add('    SORT(CONSTRUCTORS)');
+      Add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+      Add('  }');
+      Add('  .data1          : { *(.data1) }');
+      Add('  .xt_except_desc   :');
+      Add('  {');
+      Add('    *(.xt_except_desc .xt_except_desc.* .gnu.linkonce.h.*)');
+      Add('    *(.xt_except_desc_end)');
+      Add('  }');
+      Add('  .lit4           :');
+      Add('  {');
+      Add('    PROVIDE (_lit4_start = .);');
+      Add('    *(.lit4 .lit4.* .gnu.linkonce.lit4.*)');
+      Add('    PROVIDE (_lit4_end = .);');
+      Add('  }');
+      Add('  _edata = .; PROVIDE (edata = .);');
+      Add('  __bss_start = .;');
+      Add('  .bss            :');
+      Add('  {');
+      Add('   *(.dynbss)');
+      Add('   *(.bss .bss.* .gnu.linkonce.b.*)');
+      Add('   *(COMMON)');
+      Add('   /* Align here to ensure that the .bss section occupies space up to');
+      Add('      _end.  Align after .bss to ensure correct alignment even if the');
+      Add('      .bss section disappears because there are no input sections.');
+      Add('      FIXME: Why do we need it? When there is no .bss section, we don''t');
+      Add('      pad the .data section.  */');
+      Add('   . = ALIGN(. != 0 ? 32 / 8 : 1);');
+      Add('  }');
+      Add('  . = ALIGN(32 / 8);');
+      Add('  . = ALIGN(32 / 8);');
+      Add('  _end = .; PROVIDE (end = .);');
+      Add('  /* Stabs debugging sections.  */');
+      Add('  .stab          0 : { *(.stab) }');
+      Add('  .stabstr       0 : { *(.stabstr) }');
+      Add('  .stab.excl     0 : { *(.stab.excl) }');
+      Add('  .stab.exclstr  0 : { *(.stab.exclstr) }');
+      Add('  .stab.index    0 : { *(.stab.index) }');
+      Add('  .stab.indexstr 0 : { *(.stab.indexstr) }');
+      Add('  .comment       0 : { *(.comment) }');
+      Add('  /* DWARF debug sections.');
+      Add('     Symbols in the DWARF debugging sections are relative to the beginning');
+      Add('     of the section so we begin them at 0.  */');
+      Add('  /* DWARF 1 */');
+      Add('  .debug          0 : { *(.debug) }');
+      Add('  .line           0 : { *(.line) }');
+      Add('  /* GNU DWARF 1 extensions */');
+      Add('  .debug_srcinfo  0 : { *(.debug_srcinfo) }');
+      Add('  .debug_sfnames  0 : { *(.debug_sfnames) }');
+      Add('  /* DWARF 1.1 and DWARF 2 */');
+      Add('  .debug_aranges  0 : { *(.debug_aranges) }');
+      Add('  .debug_pubnames 0 : { *(.debug_pubnames) }');
+      Add('  /* DWARF 2 */');
+      Add('  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }');
+      Add('  .debug_abbrev   0 : { *(.debug_abbrev) }');
+      Add('  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }');
+      Add('  .debug_frame    0 : { *(.debug_frame) }');
+      Add('  .debug_str      0 : { *(.debug_str) }');
+      Add('  .debug_loc      0 : { *(.debug_loc) }');
+      Add('  .debug_macinfo  0 : { *(.debug_macinfo) }');
+      Add('  /* SGI/MIPS DWARF 2 extensions */');
+      Add('  .debug_weaknames 0 : { *(.debug_weaknames) }');
+      Add('  .debug_funcnames 0 : { *(.debug_funcnames) }');
+      Add('  .debug_typenames 0 : { *(.debug_typenames) }');
+      Add('  .debug_varnames  0 : { *(.debug_varnames) }');
+      Add('  /* DWARF 3 */');
+      Add('  .debug_pubtypes 0 : { *(.debug_pubtypes) }');
+      Add('  .debug_ranges   0 : { *(.debug_ranges) }');
+      Add('  /* DWARF Extension.  */');
+      Add('  .debug_macro    0 : { *(.debug_macro) }');
+      Add('  .debug_addr     0 : { *(.debug_addr) }');
+      Add('  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }');
+      Add('  .xt.lit       0 : { KEEP (*(.xt.lit .xt.lit.* .gnu.linkonce.p.*)) }');
+      Add('  .xt.insn      0 : { KEEP (*(.xt.insn .gnu.linkonce.x.*)) }');
+      Add('  .xt.prop      0 : { KEEP (*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) }');
+      Add('  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink)  *(.gnu.lto_*) }');
+      Add('}');
+    end;
+{$endif XTENSA}
+
   { Write and Close response }
   { Write and Close response }
   linkres.writetodisk;
   linkres.writetodisk;
   linkres.free;
   linkres.free;

+ 2 - 2
compiler/xtensa/agcpugas.pas

@@ -98,13 +98,13 @@ unit agcpugas;
               end
               end
             else
             else
               begin
               begin
-                s:='['+gas_regname(base);
+                s:=gas_regname(base);
                 if index<>NR_NO then
                 if index<>NR_NO then
                   begin
                   begin
                      s:=s+gas_regname(index);
                      s:=s+gas_regname(index);
                   end
                   end
                 else if offset<>0 then
                 else if offset<>0 then
-                  s:=s+', #'+tostr(offset);
+                  s:=s+','+tostr(offset);
               end;
               end;
           end;
           end;
         getreferencestring:=s;
         getreferencestring:=s;

+ 121 - 13
compiler/xtensa/cgcpu.pas

@@ -63,6 +63,8 @@ interface
         procedure a_jmp_always(list: TAsmList; l: TAsmLabel);override;
         procedure a_jmp_always(list: TAsmList; l: TAsmLabel);override;
 
 
         procedure g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);override;
         procedure g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);override;
+
+        procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 {$ifdef dummy}
 {$ifdef dummy}
        protected
        protected
         { changes register size without adding register allocation info }
         { changes register size without adding register allocation info }
@@ -124,9 +126,13 @@ interface
       end;
       end;
 
 
     procedure create_codegen;
     procedure create_codegen;
-{
+
     const
     const
-      TOpCG2AsmOpReg: array[topcg] of TAsmOp = (
+      TOpCG2AsmOp: array[topcg] of TAsmOp = (
+        A_NONE,A_MOV,A_ADD,A_AND,A_NONE,A_NONE,A_MULL,A_MULL,A_NEG,A_NONE,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR,A_NONE,A_NONE
+      );
+{
+      );TOpCG2AsmOpReg: array[topcg] of TAsmOp = (
         A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NEG,A_MVN,A_ORR,A_ASRV,A_LSLV,A_LSRV,A_SUB,A_EOR,A_NONE,A_RORV
         A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NEG,A_MVN,A_ORR,A_ASRV,A_LSLV,A_LSRV,A_SUB,A_EOR,A_NONE,A_RORV
       );
       );
       TOpCG2AsmOpImm: array[topcg] of TAsmOp = (
       TOpCG2AsmOpImm: array[topcg] of TAsmOp = (
@@ -168,9 +174,46 @@ implementation
 
 
     procedure tcgcpu.a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize;
     procedure tcgcpu.a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize;
       reg1,reg2 : tregister);
       reg1,reg2 : tregister);
+      var
+        conv_done : Boolean;
+        instr : taicpu;
       begin
       begin
-        list.Concat(taicpu.op_none(A_NOP));
-      end;
+         if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
+           internalerror(2020030710);
+
+         conv_done:=false;
+         if tosize<>fromsize then
+           begin
+             conv_done:=true;
+             if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+              fromsize:=tosize;
+             case fromsize of
+                OS_8:
+                  list.concat(taicpu.op_reg_reg_const_const(A_EXTUI,reg2,reg1,0,8));
+                OS_S8:
+                  begin
+                    list.concat(taicpu.op_reg_reg_const(A_SEXT,reg2,reg1,7));
+                    if tosize=OS_16 then
+                      list.concat(taicpu.op_reg_reg_const_const(A_EXTUI,reg2,reg2,0,16));
+                  end;
+                OS_16:
+                  list.concat(taicpu.op_reg_reg_const_const(A_EXTUI,reg2,reg1,0,16));
+                OS_S16:
+                  list.concat(taicpu.op_reg_reg_const(A_SEXT,reg2,reg1,15));
+                else
+                  conv_done:=false;
+              end;
+           end;
+         if not conv_done and (reg1<>reg2) then
+           begin
+             { same size, only a register mov required }
+             instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+             list.Concat(instr);
+             { Notify the register allocator that we have written a move instruction so
+               it can try to eliminate it. }
+             add_move_instruction(instr);
+           end;
+       end;
 
 
 
 
     procedure tcgcpu.a_load_reg_ref(list : TAsmList; fromsize,tosize : tcgsize;
     procedure tcgcpu.a_load_reg_ref(list : TAsmList; fromsize,tosize : tcgsize;
@@ -188,9 +231,25 @@ implementation
 
 
 
 
     procedure tcgcpu.a_load_const_reg(list : TAsmList; size : tcgsize;
     procedure tcgcpu.a_load_const_reg(list : TAsmList; size : tcgsize;
-     a : tcgint; reg : tregister);
+      a : tcgint; reg : tregister);
+      var
+        hr : treference;
+        l : TAsmLabel;
       begin
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        if (a>=-2048) and (a<=2047) then
+          list.Concat(taicpu.op_reg_const(A_MOVI,reg,a))
+        else
+          begin
+            reference_reset(hr,4,[]);
+
+            current_asmdata.getjumplabel(l);
+            cg.a_label(current_procinfo.aktlocaldata,l);
+//            hr.symboldata:=current_procinfo.aktlocaldata.last;
+            current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
+
+            hr.symbol:=l;
+            list.concat(taicpu.op_reg_ref(A_L32R,reg,hr));
+          end;
       end;
       end;
 
 
 
 
@@ -216,28 +275,66 @@ implementation
 
 
 
 
     procedure tcgcpu.a_op_reg_reg_reg(list : TAsmList; op : topcg;
     procedure tcgcpu.a_op_reg_reg_reg(list : TAsmList; op : topcg;
-       size : tcgsize; src1,src2,dst : tregister);
-       begin
-         list.Concat(taicpu.op_none(A_NOP));
+      size : tcgsize; src1,src2,dst : tregister);
+      var
+        tmpreg : TRegister;
+      begin
+        if op=OP_NOT then
+          begin
+            tmpreg:=getintregister(list,size);
+            list.concat(taicpu.op_reg_const(A_MOVI,tmpreg,-1));
+            maybeadjustresult(list,op,size,dst);
+          end
+        else if op=OP_NEG then
+          begin
+            list.concat(taicpu.op_reg_reg(A_NEG,dst,src1));
+            maybeadjustresult(list,op,size,dst);
+          end
+        else if op in [OP_SAR,OP_SHL,OP_SHR] then
+          begin
+            if op=OP_SHL then
+              list.concat(taicpu.op_reg(A_SSL,src1))
+            else
+              list.concat(taicpu.op_reg(A_SSR,src1));
+            list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dst,src2));
+            maybeadjustresult(list,op,size,dst);
+          end
+        else
+          case op of
+            OP_MOVE:
+              a_load_reg_reg(list,size,size,src1,dst);
+            else
+              begin
+                list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src2,src1));
+                maybeadjustresult(list,op,size,dst);
+              end;
+          end;
        end;
        end;
 
 
 
 
     procedure tcgcpu.a_call_name(list : TAsmList; const s : string;
     procedure tcgcpu.a_call_name(list : TAsmList; const s : string;
       weak : boolean);
       weak : boolean);
       begin
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        if not weak then
+          list.concat(taicpu.op_sym(txtensaprocinfo(current_procinfo).callins,current_asmdata.RefAsmSymbol(s,AT_FUNCTION)))
+        else
+          list.concat(taicpu.op_sym(txtensaprocinfo(current_procinfo).callins,current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION)));
       end;
       end;
 
 
 
 
     procedure tcgcpu.a_call_reg(list : TAsmList; Reg : tregister);
     procedure tcgcpu.a_call_reg(list : TAsmList; Reg : tregister);
       begin
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        list.concat(taicpu.op_reg(txtensaprocinfo(current_procinfo).callxins,reg));
       end;
       end;
 
 
 
 
     procedure tcgcpu.a_jmp_name(list : TAsmList; const s : string);
     procedure tcgcpu.a_jmp_name(list : TAsmList; const s : string);
+      var
+        ai : taicpu;
       begin
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        ai:=TAiCpu.op_sym(A_J,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
+        ai.is_jmp:=true;
+        list.Concat(ai);
       end;
       end;
 
 
 
 
@@ -263,8 +360,12 @@ implementation
 
 
 
 
     procedure tcgcpu.a_jmp_always(list : TAsmList; l : TAsmLabel);
     procedure tcgcpu.a_jmp_always(list : TAsmList; l : TAsmLabel);
+      var
+        ai : taicpu;
       begin
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        ai:=taicpu.op_sym(A_J,l);
+        ai.is_jmp:=true;
+        list.concat(ai);
       end;
       end;
 
 
 
 
@@ -275,6 +376,13 @@ implementation
       end;
       end;
 
 
 
 
+    procedure tcgcpu.maybeadjustresult(list : TAsmList; op : TOpCg;
+      size : tcgsize; dst : tregister);
+      begin
+
+      end;
+
+
     procedure tcg64fxtensa.a_op64_reg_reg(list : TAsmList; op : TOpCG;
     procedure tcg64fxtensa.a_op64_reg_reg(list : TAsmList; op : TOpCG;
       size : tcgsize; regsrc,regdst : tregister64);
       size : tcgsize; regsrc,regdst : tregister64);
       begin
       begin

+ 2 - 2
compiler/xtensa/cpubase.pas

@@ -199,8 +199,8 @@ unit cpubase;
       NR_STACK_POINTER_REG = NR_A1;
       NR_STACK_POINTER_REG = NR_A1;
       RS_STACK_POINTER_REG = RS_A1;
       RS_STACK_POINTER_REG = RS_A1;
       { Frame pointer register (initialized in tcpuprocinfo.init_framepointer) }
       { Frame pointer register (initialized in tcpuprocinfo.init_framepointer) }
-      RS_FRAME_POINTER_REG: tsuperregister = RS_NO;
-      NR_FRAME_POINTER_REG: tregister = NR_NO;
+      RS_FRAME_POINTER_REG: tsuperregister = RS_A7;
+      NR_FRAME_POINTER_REG: tregister = NR_A7;
       { Register for addressing absolute data in a position independant way,
       { Register for addressing absolute data in a position independant way,
         such as in PIC code. The exact meaning is ABI specific. For
         such as in PIC code. The exact meaning is ABI specific. For
         further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
         further information look at GCC source : PIC_OFFSET_TABLE_REGNUM

+ 1 - 1
compiler/xtensa/cpunode.pas

@@ -35,7 +35,7 @@ implementation
     symcpu,
     symcpu,
     aasmdef
     aasmdef
 {$ifndef llvm}
 {$ifndef llvm}
-    ,ncpuadd,ncpumat,ncpucnv//,ncpumem,ncpuset,ncpucon
+    ,ncpuadd,ncpumat,ncpucnv,ncpuutil//,ncpumem,ncpuset,ncpucon
 {$else llvm}
 {$else llvm}
     llvmnode
     llvmnode
 {$endif llvm}
 {$endif llvm}

+ 1 - 1
compiler/xtensa/cpupara.pas

@@ -59,7 +59,7 @@ unit cpupara;
 
 
     function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
     function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
       begin
       begin
-        result:=[RS_A0..RS_A15];
+        result:=[RS_A0..RS_A7];
       end;
       end;
 
 
 
 

+ 5 - 5
compiler/xtensa/cpupi.pas

@@ -29,15 +29,13 @@ unit cpupi;
 
 
     uses
     uses
        cutils,globtype,
        cutils,globtype,
+       cpubase,
        cgbase,aasmdata,
        cgbase,aasmdata,
        procinfo,cpuinfo,psub;
        procinfo,cpuinfo,psub;
 
 
     type
     type
       txtensaprocinfo = class(tcgprocinfo)
       txtensaprocinfo = class(tcgprocinfo)
-          { for arm thumb, we need to know the stackframe size before
-            starting procedure compilation, so this contains the stack frame size, the compiler
-            should assume
-            if this size is too little the procedure must be compiled again with a larger value }
+          callins,callxins : TAsmOp;
           stackframesize,
           stackframesize,
           floatregstart : aint;
           floatregstart : aint;
           stackpaddingreg: TSuperRegister;
           stackpaddingreg: TSuperRegister;
@@ -55,7 +53,6 @@ unit cpupi;
 
 
     uses
     uses
        globals,systems,
        globals,systems,
-       cpubase,
        tgobj,
        tgobj,
        symconst,symtype,symsym,symcpu,paramgr,
        symconst,symtype,symsym,symcpu,paramgr,
        cgutils,
        cgutils,
@@ -67,6 +64,9 @@ unit cpupi;
       begin
       begin
         inherited create(aparent);
         inherited create(aparent);
         maxpushedparasize := 0;
         maxpushedparasize := 0;
+        framepointer:=NR_FRAME_POINTER_REG;
+        callins:=A_CALL8;
+        callxins:=A_CALLX8;
       end;
       end;
 
 
 
 

+ 18 - 0
compiler/xtensa/hlcgcpu.pas

@@ -38,6 +38,7 @@ interface
   type
   type
     thlcgxtensa = class(thlcg2ll)
     thlcgxtensa = class(thlcg2ll)
       procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
       procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+      procedure record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList);override;
     end;
     end;
 
 
 implementation
 implementation
@@ -61,6 +62,23 @@ implementation
     begin
     begin
     end;
     end;
 
 
+
+  procedure thlcgxtensa.record_generated_code_for_procdef(pd : tprocdef; code,
+    data : TAsmList);
+    var
+      alt : TAsmListType;
+    begin
+      if not(po_assembler in pd.procoptions) then
+        alt:=al_procedures
+      else
+        alt:=al_pure_assembler;
+      { Xtensa needs the data before the subroutine }
+      if assigned(data) and
+         (not data.empty) then
+        current_asmdata.asmlists[alt].concatlist(data);
+      inherited record_generated_code_for_procdef(pd,code,nil);
+    end;
+
 begin
 begin
   chlcgobj:=thlcgxtensa;
   chlcgobj:=thlcgxtensa;
   create_hlcodegen:=@create_hlcodegen_cpu;
   create_hlcodegen:=@create_hlcodegen_cpu;

+ 6 - 5
compiler/xtensa/ncpuadd.pas

@@ -74,9 +74,9 @@ interface
       var
       var
         tmpreg : tregister;
         tmpreg : tregister;
       begin
       begin
-        //pass_left_right;
-        //location_reset(location,LOC_FLAGS,OS_NO);
-        //force_reg_left_right(false,false);
+        pass_left_right;
+        location_reset(location,LOC_FLAGS,OS_NO);
+        force_reg_left_right(false,false);
         //
         //
         //case nodetype of
         //case nodetype of
         //  equaln:
         //  equaln:
@@ -106,6 +106,7 @@ interface
         //  else
         //  else
         //    internalerror(2004012401);
         //    internalerror(2004012401);
         //end;
         //end;
+        location_copy(location,left.location);
       end;
       end;
 
 
 
 
@@ -212,7 +213,8 @@ interface
         //
         //
         //location_reset(location,LOC_FLAGS,OS_NO);
         //location_reset(location,LOC_FLAGS,OS_NO);
         //location.resflags:=getresflags(unsigned);
         //location.resflags:=getresflags(unsigned);
-        location.loc:=LOC_REGISTER;
+        //location.loc:=LOC_REGISTER;
+        location_copy(location,left.location);
         current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP));
         current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP));
       end;
       end;
 
 
@@ -220,7 +222,6 @@ interface
     procedure TCPUAddNode.second_cmp64bit;
     procedure TCPUAddNode.second_cmp64bit;
       begin
       begin
         second_cmp;
         second_cmp;
-        location.loc:=LOC_REGISTER;
       end;
       end;
 
 
 
 

+ 4 - 4
compiler/xtensa/ncpucnv.pas

@@ -79,9 +79,9 @@ implementation
         hlabel    : tasmlabel;
         hlabel    : tasmlabel;
         newsize   : tcgsize;
         newsize   : tcgsize;
       begin
       begin
-//         secondpass(left);
-//         if codegenerror then
-//          exit;
+         secondpass(left);
+         if codegenerror then
+           exit;
 //
 //
 //         { Explicit typecasts from any ordinal type to a boolean type }
 //         { Explicit typecasts from any ordinal type to a boolean type }
 //         { must not change the ordinal value                          }
 //         { must not change the ordinal value                          }
@@ -188,7 +188,7 @@ implementation
 //         else
 //         else
 //{$endif cpu64bitalu}
 //{$endif cpu64bitalu}
 //           location.register:=hreg1;
 //           location.register:=hreg1;
-        location.loc:=LOC_REGISTER;
+        location_copy(location,left.location);
         current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP));
         current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP));
       end;
       end;
 
 

+ 108 - 0
compiler/xtensa/ncpuutil.pas

@@ -0,0 +1,108 @@
+{
+    Copyright (c) 2015 by Jeppe Johansen
+
+    Xtensa 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 ncpuutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    cclasses,
+    node,nbas,
+    ngenutil,
+    symtype,symconst,symsym,symdef;
+
+
+  type
+    tavrnodeutils = class(tnodeutils)
+    protected
+      class procedure insert_init_final_table(entries:tfplist); override;
+    end;
+
+implementation
+
+    uses
+      verbose,cutils,globtype,globals,constexp,fmodule,
+      aasmdata,aasmtai,aasmcpu,aasmcnst,aasmbase,
+      cpubase,
+      symbase,symcpu,symtable,defutil,
+      ncnv,ncon,ninl,ncal,nld,nmem,
+      systems,
+      CPUInfo,
+      ppu,
+      pass_1;
+
+
+  class procedure tavrnodeutils.insert_init_final_table(entries:tfplist);
+    var
+      op : TAsmOp;
+      initList, finalList, header: TAsmList;
+      entry : pinitfinalentry;
+      i : longint;
+    begin
+      initList:=TAsmList.create;
+      finalList:=TAsmList.create;
+
+     for i:=0 to entries.count-1 do
+        begin
+          entry:=pinitfinalentry(entries[i]);
+          if entry^.finifunc<>'' then
+            finalList.Concat(taicpu.op_sym(A_CALL0,current_asmdata.RefAsmSymbol(entry^.finifunc,AT_FUNCTION)));
+          if entry^.initfunc<>'' then
+            initList.Concat(taicpu.op_sym(A_CALL0,current_asmdata.RefAsmSymbol(entry^.initfunc,AT_FUNCTION)));
+        end;
+
+      initList.Concat(taicpu.op_none(A_RET));
+      finalList.Concat(taicpu.op_none(A_RET));
+
+      begin
+        header:=TAsmList.create;
+        new_section(header, sec_code, 'FPC_INIT_FUNC_TABLE', 1);
+        header.concat(tai_symbol.Createname_global('FPC_INIT_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
+
+        initList.insertList(header);
+        header.free;
+
+        current_asmdata.AsmLists[al_procedures].concatList(initList);
+      end;
+
+      begin
+        header:=TAsmList.create;
+        new_section(header, sec_code, 'FPC_FINALIZE_FUNC_TABLE', 1);
+        header.concat(tai_symbol.Createname_global('FPC_FINALIZE_FUNC_TABLE',AT_FUNCTION,0,voidcodepointertype));
+
+        finalList.insertList(header);
+        header.free;
+
+        current_asmdata.AsmLists[al_procedures].concatList(finalList);
+      end;
+
+      initList.Free;
+      finalList.Free;
+
+      inherited insert_init_final_table(entries);
+    end;
+
+begin
+  cnodeutils:=tavrnodeutils;
+end.
+

+ 16 - 1
compiler/xtensa/xtensaatt.inc

@@ -1,5 +1,7 @@
 (
 (
 'none',
 'none',
+'add',
+'and',
 'bcc',
 'bcc',
 'bt',
 'bt',
 'call0',
 'call0',
@@ -11,17 +13,30 @@
 'callx8',
 'callx8',
 'callx12',
 'callx12',
 'entry',
 'entry',
+'extui',
 'l32i',
 'l32i',
+'l32r',
 'lsi',
 'lsi',
 'j',
 'j',
 'mov',
 'mov',
 'mov.s',
 'mov.s',
 'movi',
 'movi',
+'mull',
+'neg',
 'nop',
 'nop',
+'or',
 'ret',
 'ret',
 'retw',
 'retw',
 's32i',
 's32i',
-'ssi'
+'sext',
+'sll',
+'sra',
+'srl',
+'ssi',
+'ssl',
+'ssr',
+'sub',
+'xor'
 );
 );
 
 
 
 

+ 16 - 1
compiler/xtensa/xtensaop.inc

@@ -1,5 +1,7 @@
 (
 (
 A_NONE,
 A_NONE,
+A_ADD,
+A_AND,
 A_Bcc,
 A_Bcc,
 A_BT,
 A_BT,
 A_CALL0,
 A_CALL0,
@@ -11,17 +13,30 @@ A_CALLX4,
 A_CALLX8,
 A_CALLX8,
 A_CALLX12,
 A_CALLX12,
 A_ENTRY,
 A_ENTRY,
+A_EXTUI,
 A_L32I,
 A_L32I,
+A_L32R,
 A_LSI,
 A_LSI,
 A_J,
 A_J,
 A_MOV,
 A_MOV,
 A_MOV_S,
 A_MOV_S,
 A_MOVI,
 A_MOVI,
+A_MULL,
+A_NEG,
 A_NOP,
 A_NOP,
+A_OR,
 A_RET,
 A_RET,
 A_RETW,
 A_RETW,
 A_S32I,
 A_S32I,
-A_SSI
+A_SEXT,
+A_SLL,
+A_SRA,
+A_SRL,
+A_SSI,
+A_SSL,
+A_SSR,
+A_SUB,
+A_XOR
 );
 );