Răsfoiți Sursa

+ Xtensa: basic operations for Xtensa implemented

git-svn-id: trunk@44324 -
florian 5 ani în urmă
părinte
comite
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/ncpucnv.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/raxtensa.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
   WriteResponseFile:=False;
   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:='';
 {$else}
   prtobj:='prt0';
@@ -1351,6 +1351,212 @@ begin
     end;
   {$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 }
   linkres.writetodisk;
   linkres.free;

+ 2 - 2
compiler/xtensa/agcpugas.pas

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

+ 121 - 13
compiler/xtensa/cgcpu.pas

@@ -63,6 +63,8 @@ interface
         procedure a_jmp_always(list: TAsmList; l: TAsmLabel);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}
        protected
         { changes register size without adding register allocation info }
@@ -124,9 +126,13 @@ interface
       end;
 
     procedure create_codegen;
-{
+
     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
       );
       TOpCG2AsmOpImm: array[topcg] of TAsmOp = (
@@ -168,9 +174,46 @@ implementation
 
     procedure tcgcpu.a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize;
       reg1,reg2 : tregister);
+      var
+        conv_done : Boolean;
+        instr : taicpu;
       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;
@@ -188,9 +231,25 @@ implementation
 
 
     procedure tcgcpu.a_load_const_reg(list : TAsmList; size : tcgsize;
-     a : tcgint; reg : tregister);
+      a : tcgint; reg : tregister);
+      var
+        hr : treference;
+        l : TAsmLabel;
       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;
 
 
@@ -216,28 +275,66 @@ implementation
 
 
     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;
 
 
     procedure tcgcpu.a_call_name(list : TAsmList; const s : string;
       weak : boolean);
       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;
 
 
     procedure tcgcpu.a_call_reg(list : TAsmList; Reg : tregister);
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        list.concat(taicpu.op_reg(txtensaprocinfo(current_procinfo).callxins,reg));
       end;
 
 
     procedure tcgcpu.a_jmp_name(list : TAsmList; const s : string);
+      var
+        ai : taicpu;
       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;
 
 
@@ -263,8 +360,12 @@ implementation
 
 
     procedure tcgcpu.a_jmp_always(list : TAsmList; l : TAsmLabel);
+      var
+        ai : taicpu;
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        ai:=taicpu.op_sym(A_J,l);
+        ai.is_jmp:=true;
+        list.concat(ai);
       end;
 
 
@@ -275,6 +376,13 @@ implementation
       end;
 
 
+    procedure tcgcpu.maybeadjustresult(list : TAsmList; op : TOpCg;
+      size : tcgsize; dst : tregister);
+      begin
+
+      end;
+
+
     procedure tcg64fxtensa.a_op64_reg_reg(list : TAsmList; op : TOpCG;
       size : tcgsize; regsrc,regdst : tregister64);
       begin

+ 2 - 2
compiler/xtensa/cpubase.pas

@@ -199,8 +199,8 @@ unit cpubase;
       NR_STACK_POINTER_REG = NR_A1;
       RS_STACK_POINTER_REG = RS_A1;
       { 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,
         such as in PIC code. The exact meaning is ABI specific. For
         further information look at GCC source : PIC_OFFSET_TABLE_REGNUM

+ 1 - 1
compiler/xtensa/cpunode.pas

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

+ 1 - 1
compiler/xtensa/cpupara.pas

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

+ 5 - 5
compiler/xtensa/cpupi.pas

@@ -29,15 +29,13 @@ unit cpupi;
 
     uses
        cutils,globtype,
+       cpubase,
        cgbase,aasmdata,
        procinfo,cpuinfo,psub;
 
     type
       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,
           floatregstart : aint;
           stackpaddingreg: TSuperRegister;
@@ -55,7 +53,6 @@ unit cpupi;
 
     uses
        globals,systems,
-       cpubase,
        tgobj,
        symconst,symtype,symsym,symcpu,paramgr,
        cgutils,
@@ -67,6 +64,9 @@ unit cpupi;
       begin
         inherited create(aparent);
         maxpushedparasize := 0;
+        framepointer:=NR_FRAME_POINTER_REG;
+        callins:=A_CALL8;
+        callxins:=A_CALLX8;
       end;
 
 

+ 18 - 0
compiler/xtensa/hlcgcpu.pas

@@ -38,6 +38,7 @@ interface
   type
     thlcgxtensa = class(thlcg2ll)
       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;
 
 implementation
@@ -61,6 +62,23 @@ implementation
     begin
     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
   chlcgobj:=thlcgxtensa;
   create_hlcodegen:=@create_hlcodegen_cpu;

+ 6 - 5
compiler/xtensa/ncpuadd.pas

@@ -74,9 +74,9 @@ interface
       var
         tmpreg : tregister;
       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
         //  equaln:
@@ -106,6 +106,7 @@ interface
         //  else
         //    internalerror(2004012401);
         //end;
+        location_copy(location,left.location);
       end;
 
 
@@ -212,7 +213,8 @@ interface
         //
         //location_reset(location,LOC_FLAGS,OS_NO);
         //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));
       end;
 
@@ -220,7 +222,6 @@ interface
     procedure TCPUAddNode.second_cmp64bit;
       begin
         second_cmp;
-        location.loc:=LOC_REGISTER;
       end;
 
 

+ 4 - 4
compiler/xtensa/ncpucnv.pas

@@ -79,9 +79,9 @@ implementation
         hlabel    : tasmlabel;
         newsize   : tcgsize;
       begin
-//         secondpass(left);
-//         if codegenerror then
-//          exit;
+         secondpass(left);
+         if codegenerror then
+           exit;
 //
 //         { Explicit typecasts from any ordinal type to a boolean type }
 //         { must not change the ordinal value                          }
@@ -188,7 +188,7 @@ implementation
 //         else
 //{$endif cpu64bitalu}
 //           location.register:=hreg1;
-        location.loc:=LOC_REGISTER;
+        location_copy(location,left.location);
         current_asmdata.CurrAsmList.Concat(taicpu.op_none(A_NOP));
       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',
+'add',
+'and',
 'bcc',
 'bt',
 'call0',
@@ -11,17 +13,30 @@
 'callx8',
 'callx12',
 'entry',
+'extui',
 'l32i',
+'l32r',
 'lsi',
 'j',
 'mov',
 'mov.s',
 'movi',
+'mull',
+'neg',
 'nop',
+'or',
 'ret',
 'retw',
 's32i',
-'ssi'
+'sext',
+'sll',
+'sra',
+'srl',
+'ssi',
+'ssl',
+'ssr',
+'sub',
+'xor'
 );
 
 

+ 16 - 1
compiler/xtensa/xtensaop.inc

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