Переглянути джерело

Added compiler support for avr32
Added RTL code for avr32-embedded
Added simple startup code for at32uc3b1256
Introduced avr32 as a target for fpcmake

git-svn-id: branches/laksen/avr32new@17826 -

Jeppe Johansen 14 роки тому
батько
коміт
27cae64f6e
77 змінених файлів з 11187 додано та 93 видалено
  1. 49 0
      .gitattributes
  2. 3 0
      Makefile.fpc
  3. 12 2
      compiler/Makefile.fpc
  4. 25 5
      compiler/aasmtai.pas
  5. 10 10
      compiler/aoptobj.pas
  6. 1628 0
      compiler/avr32/aasmcpu.pas
  7. 245 0
      compiler/avr32/agavr32gas.pas
  8. 194 0
      compiler/avr32/aoptcpu.pas
  9. 120 0
      compiler/avr32/aoptcpub.pas
  10. 38 0
      compiler/avr32/aoptcpuc.pas
  11. 40 0
      compiler/avr32/aoptcpud.pas
  12. 181 0
      compiler/avr32/avr32att.inc
  13. 181 0
      compiler/avr32/avr32atts.inc
  14. 290 0
      compiler/avr32/avr32ins.dat
  15. 2 0
      compiler/avr32/avr32nop.inc
  16. 181 0
      compiler/avr32/avr32op.inc
  17. 24 0
      compiler/avr32/avr32reg.dat
  18. 388 0
      compiler/avr32/avr32tab.inc
  19. 1838 0
      compiler/avr32/cgcpu.pas
  20. 532 0
      compiler/avr32/cpubase.pas
  21. 131 0
      compiler/avr32/cpuinfo.pas
  22. 53 0
      compiler/avr32/cpunode.pas
  23. 526 0
      compiler/avr32/cpupara.pas
  24. 53 0
      compiler/avr32/cpupi.pas
  25. 70 0
      compiler/avr32/cputarg.pas
  26. 93 0
      compiler/avr32/itcpugas.pas
  27. 376 0
      compiler/avr32/navr32add.pas
  28. 74 0
      compiler/avr32/navr32cal.pas
  29. 233 0
      compiler/avr32/navr32cnv.pas
  30. 134 0
      compiler/avr32/navr32con.pas
  31. 273 0
      compiler/avr32/navr32mat.pas
  32. 115 0
      compiler/avr32/navr32mem.pas
  33. 54 0
      compiler/avr32/raavr32.pas
  34. 974 0
      compiler/avr32/raavr32gas.pas
  35. 18 0
      compiler/avr32/ravr32con.inc
  36. 18 0
      compiler/avr32/ravr32dwa.inc
  37. 2 0
      compiler/avr32/ravr32nor.inc
  38. 18 0
      compiler/avr32/ravr32num.inc
  39. 18 0
      compiler/avr32/ravr32rni.inc
  40. 18 0
      compiler/avr32/ravr32sri.inc
  41. 18 0
      compiler/avr32/ravr32sta.inc
  42. 18 0
      compiler/avr32/ravr32std.inc
  43. 18 0
      compiler/avr32/ravr32sup.inc
  44. 159 0
      compiler/avr32/rgcpu.pas
  45. 4 4
      compiler/cgobj.pas
  46. 5 0
      compiler/cgutils.pas
  47. 9 0
      compiler/fpcdefs.inc
  48. 11 6
      compiler/globals.pas
  49. 11 6
      compiler/ncgutil.pas
  50. 17 10
      compiler/options.pas
  51. 2 2
      compiler/pmodules.pas
  52. 6 0
      compiler/pp.pas
  53. 6 2
      compiler/psub.pas
  54. 4 0
      compiler/psystem.pas
  55. 37 2
      compiler/raatt.pas
  56. 17 1
      compiler/rautils.pas
  57. 3 0
      compiler/symdef.pas
  58. 5 2
      compiler/systems.inc
  59. 7 3
      compiler/systems.pas
  60. 67 0
      compiler/systems/i_embed.pas
  61. 140 1
      compiler/systems/t_embed.pas
  62. 1 1
      compiler/utils/Makefile.fpc
  63. 409 0
      compiler/utils/mkavr32ins.pp
  64. 278 0
      compiler/utils/mkavr32reg.pp
  65. 189 0
      rtl/avr32/avr32.inc
  66. 20 0
      rtl/avr32/int64p.inc
  67. 6 0
      rtl/avr32/makefile.cpu
  68. 52 0
      rtl/avr32/math.inc
  69. 15 0
      rtl/avr32/set.inc
  70. 26 0
      rtl/avr32/setjump.inc
  71. 25 0
      rtl/avr32/setjumph.inc
  72. 4 0
      rtl/embedded/Makefile.fpc
  73. 299 0
      rtl/embedded/avr32/at32uc3b1256.pas
  74. 3 0
      rtl/embedded/rtl.cfg
  75. 7 0
      rtl/inc/system.inc
  76. 21 0
      rtl/inc/systemh.inc
  77. 36 36
      utils/fpcm/fpcmmain.pp

+ 49 - 0
.gitattributes

@@ -105,6 +105,45 @@ compiler/avr/ravrsta.inc svneol=native#text/plain
 compiler/avr/ravrstd.inc svneol=native#text/plain
 compiler/avr/ravrsup.inc svneol=native#text/plain
 compiler/avr/rgcpu.pas svneol=native#text/plain
+compiler/avr32/aasmcpu.pas svneol=native#text/plain
+compiler/avr32/agavr32gas.pas svneol=native#text/plain
+compiler/avr32/aoptcpu.pas svneol=native#text/plain
+compiler/avr32/aoptcpub.pas svneol=native#text/plain
+compiler/avr32/aoptcpuc.pas svneol=native#text/plain
+compiler/avr32/aoptcpud.pas svneol=native#text/plain
+compiler/avr32/avr32att.inc svneol=native#text/plain
+compiler/avr32/avr32atts.inc svneol=native#text/plain
+compiler/avr32/avr32ins.dat svneol=native#text/plain
+compiler/avr32/avr32nop.inc svneol=native#text/plain
+compiler/avr32/avr32op.inc svneol=native#text/plain
+compiler/avr32/avr32reg.dat svneol=native#text/plain
+compiler/avr32/avr32tab.inc svneol=native#text/plain
+compiler/avr32/cgcpu.pas svneol=native#text/plain
+compiler/avr32/cpubase.pas svneol=native#text/plain
+compiler/avr32/cpuinfo.pas svneol=native#text/plain
+compiler/avr32/cpunode.pas svneol=native#text/plain
+compiler/avr32/cpupara.pas svneol=native#text/plain
+compiler/avr32/cpupi.pas svneol=native#text/plain
+compiler/avr32/cputarg.pas svneol=native#text/plain
+compiler/avr32/itcpugas.pas svneol=native#text/plain
+compiler/avr32/navr32add.pas svneol=native#text/plain
+compiler/avr32/navr32cal.pas svneol=native#text/plain
+compiler/avr32/navr32cnv.pas svneol=native#text/plain
+compiler/avr32/navr32con.pas svneol=native#text/plain
+compiler/avr32/navr32mat.pas svneol=native#text/plain
+compiler/avr32/navr32mem.pas svneol=native#text/plain
+compiler/avr32/raavr32.pas svneol=native#text/plain
+compiler/avr32/raavr32gas.pas svneol=native#text/plain
+compiler/avr32/ravr32con.inc svneol=native#text/plain
+compiler/avr32/ravr32dwa.inc svneol=native#text/plain
+compiler/avr32/ravr32nor.inc svneol=native#text/plain
+compiler/avr32/ravr32num.inc svneol=native#text/plain
+compiler/avr32/ravr32rni.inc svneol=native#text/plain
+compiler/avr32/ravr32sri.inc svneol=native#text/plain
+compiler/avr32/ravr32sta.inc svneol=native#text/plain
+compiler/avr32/ravr32std.inc svneol=native#text/plain
+compiler/avr32/ravr32sup.inc svneol=native#text/plain
+compiler/avr32/rgcpu.pas svneol=native#text/plain
 compiler/browcol.pas svneol=native#text/plain
 compiler/bsdcompile -text
 compiler/catch.pas svneol=native#text/plain
@@ -587,6 +626,8 @@ compiler/utils/gppc386.pp svneol=native#text/plain
 compiler/utils/mk68kreg.pp svneol=native#text/plain
 compiler/utils/mkarmins.pp svneol=native#text/plain
 compiler/utils/mkarmreg.pp svneol=native#text/plain
+compiler/utils/mkavr32ins.pp svneol=native#text/plain
+compiler/utils/mkavr32reg.pp svneol=native#text/plain
 compiler/utils/mkavrreg.pp svneol=native#text/plain
 compiler/utils/mkmpsreg.pp svneol=native#text/plain
 compiler/utils/mkppcreg.pp svneol=native#text/plain
@@ -6896,6 +6937,13 @@ rtl/avr/math.inc svneol=native#text/plain
 rtl/avr/set.inc svneol=native#text/plain
 rtl/avr/setjump.inc svneol=native#text/plain
 rtl/avr/setjumph.inc svneol=native#text/plain
+rtl/avr32/avr32.inc svneol=native#text/plain
+rtl/avr32/int64p.inc svneol=native#text/plain
+rtl/avr32/makefile.cpu svneol=native#text/plain
+rtl/avr32/math.inc svneol=native#text/plain
+rtl/avr32/set.inc svneol=native#text/plain
+rtl/avr32/setjump.inc svneol=native#text/plain
+rtl/avr32/setjumph.inc svneol=native#text/plain
 rtl/beos/Makefile svneol=native#text/plain
 rtl/beos/Makefile.fpc svneol=native#text/plain
 rtl/beos/baseunix.pp svneol=native#text/plain
@@ -6994,6 +7042,7 @@ rtl/embedded/arm/stellaris.pp svneol=native#text/plain
 rtl/embedded/arm/stm32f103.pp svneol=native#text/plain
 rtl/embedded/avr/atmega128.pp svneol=native#text/plain
 rtl/embedded/avr/start.inc svneol=native#text/plain
+rtl/embedded/avr32/at32uc3b1256.pas svneol=native#text/plain
 rtl/embedded/check.inc svneol=native#text/plain
 rtl/embedded/empty.cfg svneol=native#text/plain
 rtl/embedded/rtl.cfg svneol=native#text/plain

+ 3 - 0
Makefile.fpc

@@ -60,6 +60,9 @@ endif
 ifeq ($(CPU_TARGET),armeb)
 PPSUF=arm
 endif
+ifeq ($(CPU_TARGET),avr32)
+PPSUF=avr32
+endif
 
 # cross compilers uses full cpu_target, not just ppc-suffix.
 ifdef CROSSCOMPILE

+ 12 - 2
compiler/Makefile.fpc

@@ -32,7 +32,7 @@ fpcdir=..
 unexport FPC_VERSION FPC_COMPILERINFO
 
 # Which platforms are ready for inclusion in the cycle
-CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr avr32
 
 # All supported targets used for clean
 ALLTARGETS=$(CYCLETARGETS)
@@ -71,6 +71,9 @@ endif
 ifdef MIPSEL
 PPC_TARGET=mipsel
 endif
+ifdef AVR32
+PPC_TARGET=avr32
+endif
 
 # Default is to generate a compiler for the same
 # platform as CPU_TARGET (a native compiler)
@@ -154,6 +157,9 @@ endif
 ifeq ($(CPC_TARGET),mipsel)
 CPUSUF=mipsel
 endif
+ifeq ($(CPC_TARGET),avr32)
+CPUSUF=avr32
+endif
 
 # Do not define the default -d$(CPU_TARGET) because that
 # will conflict with our -d$(CPC_TARGET)
@@ -404,7 +410,11 @@ insdatarm : arm/armins.dat
 	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmins.pp
         cd arm && ../utils/mkarmins$(SRCEXEEXT)
 
-insdat: insdatx86 insdatarm
+insdatavr32 : avr32/avr32ins.dat
+	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkavr32ins.pp
+        cd avr32 && ../utils/mkavr32ins$(SRCEXEEXT)
+
+insdat: insdatx86 insdatarm insdatavr32
 
 regdatarm : arm/armreg.dat
 	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmreg.pp

+ 25 - 5
compiler/aasmtai.pas

@@ -181,6 +181,13 @@ interface
        ,top_conditioncode
        ,top_modeflags
 {$endif arm}
+{$ifdef avr32}
+       { AVR32 only }
+       ,top_regset
+       ,top_shifterop
+       ,top_coh
+       ,top_selector
+{$endif avr32}
 {$ifdef m68k}
        { m68k only }
        ,top_regset
@@ -218,6 +225,12 @@ interface
           top_conditioncode : (cc : TAsmCond);
           top_modeflags : (modeflags : tcpumodeflags);
       {$endif arm}
+      {$ifdef avr32}
+          top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister);
+          top_shifterop : (shifterop : pshifterop);
+          top_coh : ();
+          top_selector : (topreg : tregister; selector : tregisterselector);
+      {$endif avr32}
       {$ifdef m68k}
           top_regset : (regset:^tcpuregisterset);
       {$endif m68k}
@@ -2032,14 +2045,14 @@ implementation
          end;
         if assigned(add_reg_instruction_hook) then
           add_reg_instruction_hook(self,r);
-{$ifdef ARM}
-        { R15 is the PC on the ARM thus moves to R15 are jumps.
+{$if defined(ARM) or defined(AVR32)}
+        { R15 is the PC on the ARM and AVR32, thus moves to R15 are jumps.
           Due to speed considerations we don't use a virtual overridden method here.
           Because the pc/r15 isn't handled by the reg. allocator this should never cause
           problems with iregs getting r15.
         }
         is_jmp:=(opcode=A_MOV) and (opidx=0) and (r=NR_R15);
-{$endif ARM}
+{$endif}
       end;
 
 
@@ -2076,6 +2089,13 @@ implementation
                     add_reg_instruction_hook(self,shifterop^.rs);
                 end;
 {$endif ARM}
+{$ifdef AVR32}
+              top_shifterop:
+                begin
+                  new(shifterop);
+                  shifterop^:=o.shifterop^;
+                end;
+{$endif AVR32}
              end;
           end;
       end;
@@ -2089,12 +2109,12 @@ implementation
                 dispose(ref);
               top_local:
                 dispose(localoper);
-{$ifdef ARM}
+{$if defined(ARM) or defined(AVR32)}
               top_shifterop:
                 dispose(shifterop);
               top_regset:
                 dispose(regset);
-{$endif ARM}
+{$endif}
             end;
             typ:=top_none;
           end;

+ 10 - 10
compiler/aoptobj.pas

@@ -930,9 +930,9 @@ Unit AoptObj;
               if { the next instruction after the label where the jump hp arrives}
                  { is unconditional or of the same type as hp, so continue       }
                  (((taicpu(p1).opcode = aopt_uncondjmp) and
-{$ifdef arm}
+{$if defined(ARM) or defined(AVR32)}
                    (taicpu(p1).condition = C_None) and
-{$endif arm}
+{$endif}
                    (taicpu(p1).oper[0]^.typ = top_ref) and
                    (assigned(taicpu(p1).oper[0]^.ref^.symbol)) and
                    (taicpu(p1).oper[0]^.ref^.symbol is TAsmLabel)) or
@@ -947,9 +947,9 @@ Unit AoptObj;
                   (p2.typ = ait_instruction) and
                   (taicpu(p2).is_jmp) and
                   (((taicpu(p2).opcode = aopt_uncondjmp) and
-{$ifdef arm}
+{$if defined(ARM) or defined(AVR32)}
                     (taicpu(p1).condition = C_None) and
-{$endif arm}
+{$endif}
                     (taicpu(p2).oper[0]^.typ = top_ref) and
                     (assigned(taicpu(p2).oper[0]^.ref^.symbol)) and
                     (taicpu(p2).oper[0]^.ref^.symbol is TAsmLabel)) or
@@ -1027,9 +1027,9 @@ Unit AoptObj;
                         because it can never be executed
                       }
                       if (taicpu(p).opcode = aopt_uncondjmp) and
-{$ifdef arm}
+{$if defined(ARM) or defined(AVR32)}
                          (taicpu(p).condition = C_None) and
-{$endif arm}
+{$endif}
                          (taicpu(p).oper[0]^.typ = top_ref) and
                          (assigned(taicpu(p).oper[0]^.ref^.symbol)) and
                          (taicpu(p).oper[0]^.ref^.symbol is TAsmLabel) then
@@ -1069,9 +1069,9 @@ Unit AoptObj;
                                 SkipLabels(hp1,hp1);
                               if (tai(hp1).typ=ait_instruction) and
                                   (taicpu(hp1).opcode=aopt_uncondjmp) and
-{$ifdef arm}
+{$if defined(ARM) or defined(AVR32)}
                                   (taicpu(hp1).condition=C_None) and
-{$endif arm}
+{$endif}
                                   (taicpu(hp1).oper[0]^.typ = top_ref) and
                                   (assigned(taicpu(hp1).oper[0]^.ref^.symbol)) and
                                   (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
@@ -1079,9 +1079,9 @@ Unit AoptObj;
                                   FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
                                 begin
                                   if (taicpu(p).opcode=aopt_condjmp)
-{$ifdef arm}
+{$if defined(ARM) or defined(AVR32)}
                                     and (taicpu(p).condition<>C_None)
-{$endif arm}
+{$endif}
                                   then
                                     begin
                                       taicpu(p).condition:=inverse_cond(taicpu(p).condition);

+ 1628 - 0
compiler/avr32/aasmcpu.pas

@@ -0,0 +1,1628 @@
+{
+    Copyright (c) 2003 by Florian Klaempfl
+
+    Contains the assembler object for the AVR32
+
+    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 aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  cclasses,globtype,globals,verbose,
+  aasmbase,aasmtai,aasmdata,aasmsym,
+  ogbase,
+  symtype,
+  cpubase,cpuinfo,cgbase,cgutils;
+
+    const
+      { "mov reg,reg" source operand number }
+      O_MOV_SOURCE = 1;
+      { "mov reg,reg" source operand number }
+      O_MOV_DEST = 0;
+
+      { Operand types }
+      OT_NONE      = $00000000;
+
+      OT_BITS5     = $00000001;  { size, and other attributes, of the operand  }
+      OT_BITS8     = $00000002;
+      OT_BITS16    = $00000002;
+      OT_BITS21    = $00000002;
+      OT_BITS32    = $00000004;
+      OT_BITS64    = $00000008;  { FPU only  }
+      OT_BITS80    = $00000010;
+      OT_FAR       = $00000020;  { this means 16:16 or 16:32, like in CALL/JMP }
+      OT_NEAR      = $00000040;
+      OT_SHORT     = $00000080;
+      OT_BITSTINY  = $00000100;  { fpu constant }
+      OT_BITSSHIFTER =
+                     $00000200;
+      OT_COH =
+                     $00000200;
+
+      OT_SIZE_MASK = $000003FF;  { all the size attributes  }
+      OT_NON_SIZE  = longint(not OT_SIZE_MASK);
+
+      OT_SIGNED    = $00000100;  { the operand need to be signed -128-127 }
+
+      OT_TO        = $00000200;  { operand is followed by a colon  }
+                                 { reverse effect in FADD, FSUB &c  }
+      OT_COLON     = $00000400;
+
+      OT_SHIFTEROP = $00000800;
+      OT_REGISTER  = $00001000;
+      OT_IMM       = $00002000;
+      OT_REGLIST   = $00008000;
+      OT_IMM5      = $00002001;
+      OT_IMM8      = $00002001;
+      OT_IMM16     = $00002001;
+      OT_IMM24     = $00002002;
+      OT_IMM32     = $00002004;
+      OT_IMM64     = $00002008;
+      OT_IMM80     = $00002010;
+      OT_IMMTINY   = $00002100;
+      OT_IMMSHIFTER= $00002200;
+      OT_IMMEDIATE24 = OT_IMM24;
+      OT_SHIFTIMM  = OT_SHIFTEROP or OT_IMMSHIFTER;
+      OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
+      OT_IMMEDIATESHIFTER = OT_IMMSHIFTER;
+
+      OT_IMMEDIATEFPU = OT_IMMTINY;
+
+      OT_REGMEM    = $00200000;  { for r/m, ie EA, operands  }
+      OT_REGNORM   = $00201000;  { 'normal' reg, qualifies as EA  }
+      OT_REG8      = $00201001;
+      OT_REG16     = $00201002;
+      OT_REG32     = $00201004;
+      OT_REG64     = $00201008;
+      OT_VREG      = $00201010;  { vector register }
+      OT_REGF      = $00201020;  { coproc register }
+      OT_MEMORY    = $00204000;  { register number in 'basereg'  }
+      OT_MEM8      = $00204001;
+      OT_MEM16     = $00204002;
+      OT_MEM32     = $00204004;
+      OT_MEM64     = $00204008;
+      OT_MEM80     = $00204010;
+      { word/byte load/store }
+      OT_AM2       = $00010000;
+      { misc ld/st operations }
+      OT_AM3       = $00020000;
+      { multiple ld/st operations }
+      OT_AM4       = $00040000;
+      { co proc. ld/st operations }
+      OT_AM5       = $00080000;
+      OT_AMMASK    = $000f0000;
+      { IT instruction }
+      OT_CONDITION = $00100000;
+
+      OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
+      OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
+      OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
+      OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
+
+      OT_FPUREG    = $01000000;  { floating point stack registers  }
+      OT_REG_SMASK = $00070000;  { special register operands: these may be treated differently  }
+                                 { a mask for the following  }
+
+      OT_MEM_OFFS  = $00604000;  { special type of EA  }
+                                 { simple [address] offset  }
+      OT_ONENESS   = $00800000;  { special type of immediate operand  }
+                                 { so UNITY == IMMEDIATE | ONENESS  }
+      OT_UNITY     = $00802000;  { for shift/rotate instructions  }
+
+      instabentries = {$i avr32nop.inc}
+
+      maxinfolen = 5;
+
+      IF_NONE   = $00000000;
+
+      IF_ARMMASK    = $000F0000;
+      IF_1          = $00070000;
+      IF_FPMASK     = $00F00000;
+      IF_FPA        = $00100000;
+
+      { if the instruction can change in a second pass }
+      IF_PASS2  = longint($80000000);
+
+    type
+      TInsTabCache=array[TasmOp] of longint;
+      PInsTabCache=^TInsTabCache;
+
+      tinsentry = record
+        opcode  : tasmop;
+        ops     : byte;
+        optypes : array[0..3] of longint;
+        code    : array[0..maxinfolen] of char;
+        flags   : longint;
+      end;
+
+      pinsentry=^tinsentry;
+
+    const
+      InsTab : array[0..instabentries-1] of TInsEntry={$i avr32tab.inc}
+
+    var
+      InsTabCache : PInsTabCache;
+
+    type
+
+      { taicpu }
+
+      taicpu = class(tai_cpu_abstract_sym)
+         oppostfix : TOpPostfix;
+         wideformat : boolean;
+         roundingmode : troundingmode;
+         procedure loadregisterselector(opidx:longint;_op1:tregister;aselector:tregisterselector);
+         procedure loadCOH(opidx:longint);
+         procedure loadshifterop(opidx:longint;const so:tshifterop);
+         procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset);
+         constructor op_none(op : tasmop);
+
+         constructor op_reg(op : tasmop;_op1 : tregister);
+         constructor op_ref(op : tasmop;const _op1 : treference);
+         constructor op_const(op : tasmop;_op1 : longint);
+
+         constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+         constructor op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+         constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+         constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+         constructor op_reg_const_coh(op:tasmop; _op1: tregister; _op2: aint);
+
+         constructor op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
+
+         constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+         constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+         constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
+         constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+         constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
+         constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+         constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3,_op4: aint);
+         { SFM/LFM }
+         constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+
+         { *M*LL }
+         constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+
+         { this is for Jmp instructions }
+         constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+         constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+         constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+         constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
+         constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+         function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+         function spilling_get_operation_type(opnr: longint): topertype;override;
+
+         { assembler }
+      public
+         { the next will reset all instructions that can change in pass 2 }
+         procedure ResetPass1;override;
+         procedure ResetPass2;override;
+         function  CheckIfValid:boolean;
+         function GetString:string;
+         function  Pass1(objdata:TObjData):longint;override;
+         procedure Pass2(objdata:TObjData);override;
+      protected
+         procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
+         procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
+         procedure ppubuildderefimploper(var o:toper);override;
+         procedure ppuderefoper(var o:toper);override;
+      private
+         { next fields are filled in pass1, so pass2 is faster }
+         inssize   : shortint;
+         insoffset : longint;
+         LastInsOffset : longint; { need to be public to be reset }
+         insentry  : PInsEntry;
+         function  InsEnd:longint;
+         procedure create_ot(objdata:TObjData);
+         function  Matches(p:PInsEntry):longint;
+         function  calcsize(p:PInsEntry):shortint;
+         procedure gencode(objdata:TObjData);
+         function  NeedAddrPrefix(opidx:byte):boolean;
+         procedure Swapoperands;
+         function  FindInsentry(objdata:TObjData):boolean;
+      end;
+
+      tai_align = class(tai_align_abstract)
+        { nothing to add }
+      end;
+
+    function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+    function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+    function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
+    function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
+    function setcondition(i : taicpu;c : tasmcond) : taicpu;
+
+    { inserts pc relative symbols at places where they are reachable
+      and transforms special instructions to valid instruction encodings }
+    procedure finalizeavr32code(list,listtoinsert : TAsmList);
+
+    procedure InitAsm;
+    procedure DoneAsm;
+
+
+implementation
+
+  uses
+    cutils,rgobj,itcpugas;
+
+    procedure taicpu.loadregisterselector(opidx: longint; _op1: tregister; aselector: tregisterselector);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+          begin
+            if typ<>top_selector then
+              clearop(opidx);
+            topreg:=_op1;
+            selector:=aselector;
+            typ:=top_selector;
+          end;
+      end;
+
+    procedure taicpu.loadCOH(opidx: longint);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+          begin
+            if typ<>top_coh then
+              clearop(opidx);
+            typ:=top_coh;
+          end;
+      end;
+
+    procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+          begin
+            if typ<>top_shifterop then
+              begin
+                clearop(opidx);
+                new(shifterop);
+              end;
+            shifterop^:=so;
+            typ:=top_shifterop;
+          end;
+      end;
+
+
+    procedure taicpu.loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset);
+      var
+        i : byte;
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+         begin
+           if typ<>top_regset then
+             begin
+               clearop(opidx);
+               new(regset);
+             end;
+           regset^:=s;
+           regtyp:=regsetregtype;
+           subreg:=regsetsubregtype;
+           typ:=top_regset;
+           case regsetregtype of
+             R_INTREGISTER:
+               for i:=RS_R0 to RS_R15 do
+                 begin
+                   if assigned(add_reg_instruction_hook) and (i in regset^) then
+                     add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,regsetsubregtype));
+                 end;
+           end;
+         end;
+      end;
+
+{*****************************************************************************
+                                 taicpu Constructors
+*****************************************************************************}
+
+    constructor taicpu.op_none(op : tasmop);
+      begin
+         inherited create(op);
+      end;
+
+
+    { for pld }
+    constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadref(0,_op1);
+      end;
+
+
+    constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadreg(0,_op1);
+      end;
+
+
+    constructor taicpu.op_const(op : tasmop;_op1 : longint);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadconst(0,aint(_op1));
+      end;
+
+
+    constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+      end;
+
+    constructor taicpu.op_ref_reg(op: tasmop; const _op1: treference; _op2: tregister);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadref(0,_op1);
+         loadreg(1,_op2);
+      end;
+
+
+    constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadconst(1,aint(_op2));
+      end;
+
+    constructor taicpu.op_reg_const_coh(op: tasmop; _op1: tregister; _op2: aint);
+      begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadconst(1,aint(_op2));
+         loadCOH(2);
+      end;
+
+
+    constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadref(0,_op1);
+         loadregset(1,regtype,subreg,_op2);
+      end;
+
+
+    constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadref(1,_op2);
+      end;
+
+
+    constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+      begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+      end;
+
+
+    constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+      begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+         loadreg(3,_op4);
+      end;
+
+
+     constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadconst(2,aint(_op3));
+      end;
+
+
+    constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+      begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadconst(1,_op2);
+         loadref(2,_op3);
+      end;
+
+
+     constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadsymbol(0,_op3,_op3ofs);
+      end;
+
+
+     constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadref(2,_op3);
+      end;
+
+
+     constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
+      begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadshifterop(2,_op3);
+      end;
+
+
+     constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+      begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+         loadshifterop(3,_op4);
+      end;
+
+    constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+      begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadconst(2,_op3);
+         loadconst(3,_op4);
+      end;
+
+
+    constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+      begin
+         inherited create(op);
+         condition:=cond;
+         ops:=1;
+         loadsymbol(0,_op1,0);
+      end;
+
+
+    constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadsymbol(0,_op1,0);
+      end;
+
+
+    constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadsymbol(0,_op1,_op1ofs);
+      end;
+
+
+     constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadsymbol(1,_op2,_op2ofs);
+      end;
+
+
+    constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadsymbol(0,_op1,_op1ofs);
+         loadref(1,_op2);
+      end;
+
+
+    function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+      begin
+        { allow the register allocator to remove unnecessary moves }
+        result:=(((opcode=A_MOV) and (regtype = R_INTREGISTER))
+                ) and
+                (condition=C_None) and
+                (ops=2) and
+                (oper[0]^.typ=top_reg) and
+                (oper[1]^.typ=top_reg) and
+                (oper[0]^.reg=oper[1]^.reg);
+      end;
+
+
+    function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+      var
+        op: tasmop;
+      begin
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=setoppostfix(taicpu.op_reg_ref(A_LD,r,ref),PF_W);
+          else
+            internalerror(200401041);
+        end;
+      end;
+
+
+    function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+      var
+        op: tasmop;
+      begin
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=setoppostfix(taicpu.op_ref_reg(A_ST,ref,r),PF_W);
+          else
+            internalerror(200401041);
+        end;
+      end;
+
+
+    function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+      begin
+        result := operand_read;
+        case opcode of
+          A_ABS,
+          A_ACR,
+          A_NEG,
+          A_SCR,
+          A_SATRNDS,A_SATRNDU,
+          A_SATS,A_SATU,
+          A_MACHH,A_MACWH,A_MACSATHH,
+          A_ANDH,A_ANDL,
+          A_COM,
+          A_EORH,A_EORL,
+          A_ORH,A_ORL,
+          A_TST,
+          A_CASTS,A_CASTU,
+          A_CBR,A_SWAP,
+          A_ROL,A_ROR:
+            if opnr = 0 then
+              result:=operand_readwrite;
+          A_CPC,A_CP,
+          A_TBNZ,
+          A_BLD,A_BST,
+          A_BR,
+          A_RJMP,A_ACALL,A_ICALL,A_MCALL,A_RCALL,A_SCALL,
+          A_RET,A_RETD,A_RETE,A_RETS,
+          A_MEMC,A_MEMS,A_MEMT:;
+
+          A_ADC,A_ADD,A_ADDABS,
+          A_MAX,A_MIN,
+          A_RSUB,A_SBC,A_SUB,
+          A_DIVS,A_DIVU,
+          A_ADDHH,
+          A_MAC,A_MACS,A_MACU,
+          A_MUL,A_MULS,A_MULU,
+          A_MULHH,A_MULWH,A_MULNHH,A_MULNWH,
+          A_SATADD,A_SATSUB,
+          A_SUBHH,
+          A_MULSATHH,A_MULSATRNDHH,A_MULSATRNDWH,A_MULSATWH,
+          A_AND,A_ANDN,
+          A_EOR,A_OR,
+          A_BFEXTS,A_BFEXTU,
+          A_BFINS,
+          A_BREV,
+          A_CLZ,
+          A_SBR,
+          A_ASR,
+          A_LSL,
+          A_LSR,
+          A_MOV,
+          A_MOVH,
+          A_LD,A_LDINS,A_LDSWP,A_LDDPC,A_LDDSP,
+          A_ST,A_STCOND,A_STDSP,A_STHH,A_STSWP,
+          A_XCHG,
+          A_LDM,A_LDMTS,A_POPM,
+          A_PUSHM,A_STM,A_STMTS,
+          A_BREAKPOINT,
+          A_CACHE,
+          A_CSRF,
+          A_CSRFCZ,
+          A_FRS,
+          A_MFDR,
+          A_MFSR,
+          A_MTDR,
+          A_MTSR,
+          A_MUSFR,
+          A_MUSTR,
+          A_NOP,
+          A_PREF,
+          A_SLEEP,
+          A_SR,
+          A_SSRF,
+          A_SYNC,
+          A_TLBR,
+          A_TLBS,
+          A_TLBW,
+          A_COP,
+          A_LDC,
+          A_LDC0,
+          A_LDCM,
+          A_MVCR,
+          A_MVRC,
+          A_STC,
+          A_STC0,
+          A_STCM,
+          A_PABS,
+          A_PACKSH,
+          A_PACKW,
+          A_PADD,
+          A_PADDH,
+          A_PADDS,
+          A_PADDSUB,
+          A_PADDSUBH,
+          A_PADDSUBS,
+          A_PADDX,
+          A_PADDXH,
+          A_PADDXS,
+          A_PASR,
+          A_PAVG,
+          A_PLSL,
+          A_PLSR,
+          A_PMAX,
+          A_PMIN,
+          A_PSAD,
+          A_PSUB,
+          A_PSUBADD,
+          A_PSUBADDH,
+          A_PSUBADDS,
+          A_PSUBH,
+          A_PSUBS,
+          A_PSUBX,
+          A_PSUBXH,
+          A_PSUBXS,
+          A_PUNPCK:
+            if opnr = 0 then
+              result := operand_write
+            else
+              result := operand_read;
+          else
+            internalerror(200403151);
+        end;
+      end;
+
+
+    procedure BuildInsTabCache;
+      var
+        i : longint;
+      begin
+        new(instabcache);
+        FillChar(instabcache^,sizeof(tinstabcache),$ff);
+        i:=0;
+        while (i<InsTabEntries) do
+          begin
+            if InsTabCache^[InsTab[i].Opcode]=-1 then
+              InsTabCache^[InsTab[i].Opcode]:=i;
+            inc(i);
+          end;
+      end;
+
+
+    procedure InitAsm;
+      begin
+        if not assigned(instabcache) then
+          BuildInsTabCache;
+      end;
+
+
+    procedure DoneAsm;
+      begin
+        if assigned(instabcache) then
+          begin
+            dispose(instabcache);
+            instabcache:=nil;
+          end;
+      end;
+
+
+    function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
+      begin
+        i.oppostfix:=pf;
+        result:=i;
+      end;
+
+
+    function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
+      begin
+        i.roundingmode:=rm;
+        result:=i;
+      end;
+
+
+    function setcondition(i : taicpu;c : tasmcond) : taicpu;
+      begin
+        i.condition:=c;
+        result:=i;
+      end;
+
+
+    Function SimpleGetNextInstruction(Current: tai; Var Next: tai): Boolean;
+      Begin
+        Current:=tai(Current.Next);
+        While Assigned(Current) And (Current.typ In SkipInstr) Do
+          Current:=tai(Current.Next);
+        Next:=Current;
+        If Assigned(Next) And Not(Next.typ In SkipInstr) Then
+           Result:=True
+          Else
+            Begin
+              Next:=Nil;
+              Result:=False;
+            End;
+      End;
+
+
+    procedure insertpcrelativedata(list,listtoinsert : TAsmList);
+      var
+        curinspos,
+        penalty,
+        lastinspos,
+        { increased for every data element > 4 bytes inserted }
+        extradataoffset,
+        limit: longint;
+        curop : longint;
+        curtai : tai;
+        curdatatai,hp,hp2 : tai;
+        curdata : TAsmList;
+        l : tasmlabel;
+        doinsert,
+        removeref : boolean;
+      begin
+        curdata:=TAsmList.create;
+        lastinspos:=-1;
+        curinspos:=0;
+        extradataoffset:=0;
+        limit:=1016;
+        curtai:=tai(list.first);
+        doinsert:=false;
+        while assigned(curtai) do
+          begin
+            { instruction? }
+            case curtai.typ of
+              ait_instruction:
+                begin
+                  { walk through all operand of the instruction }
+                  for curop:=0 to taicpu(curtai).ops-1 do
+                    begin
+                      { reference? }
+                      if (taicpu(curtai).oper[curop]^.typ=top_ref) then
+                        begin
+                          { pc relative symbol? }
+                          curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
+                          if assigned(curdatatai) and
+                            { move only if we're at the first reference of a label }
+                            (taicpu(curtai).oper[curop]^.ref^.offset=0) then
+                            begin
+                              { check if symbol already used. }
+                              { if yes, reuse the symbol }
+                              hp:=tai(curdatatai.next);
+                              removeref:=false;
+                              if assigned(hp) then
+                                begin
+                                  case hp.typ of
+                                    ait_const:
+                                      begin
+                                        if (tai_const(hp).consttype=aitconst_64bit) then
+                                          inc(extradataoffset);
+                                      end;
+                                    ait_comp_64bit,
+                                    ait_real_64bit:
+                                      begin
+                                        inc(extradataoffset);
+                                      end;
+                                    ait_real_80bit:
+                                      begin
+                                        inc(extradataoffset,2);
+                                      end;
+                                  end;
+                                  if (hp.typ=ait_const) then
+                                    begin
+                                      hp2:=tai(curdata.first);
+                                      while assigned(hp2) do
+                                        begin
+    {                                      if armconstequal(hp2,hp) then }
+                                          if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
+                                            and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label)
+                                          then
+                                            begin
+                                              with taicpu(curtai).oper[curop]^.ref^ do
+                                                begin
+                                                  symboldata:=hp2.previous;
+                                                  symbol:=tai_label(hp2.previous).labsym;
+                                                end;
+                                              removeref:=true;
+                                              break;
+                                            end;
+                                          hp2:=tai(hp2.next);
+                                        end;
+                                    end;
+                                end;
+                              { move or remove symbol reference }
+                              repeat
+                                hp:=tai(curdatatai.next);
+                                listtoinsert.remove(curdatatai);
+                                if removeref then
+                                  curdatatai.free
+                                else
+                                  curdata.concat(curdatatai);
+                                curdatatai:=hp;
+                              until (curdatatai=nil) or (curdatatai.typ=ait_label);
+                              if lastinspos=-1 then
+                                lastinspos:=curinspos;
+                            end;
+                        end;
+                    end;
+                  inc(curinspos);
+                end;
+              ait_const:
+                begin
+                  inc(curinspos);
+                  if (tai_const(curtai).consttype=aitconst_64bit) then
+                    inc(curinspos);
+                end;
+              ait_real_32bit:
+                begin
+                  inc(curinspos);
+                end;
+              ait_comp_64bit,
+              ait_real_64bit:
+                begin
+                  inc(curinspos,2);
+                end;
+              ait_real_80bit:
+                begin
+                  inc(curinspos,3);
+                end;
+            end;
+            { special case for case jump tables }
+            if SimpleGetNextInstruction(curtai,hp) and
+              (tai(hp).typ=ait_instruction) and
+              (taicpu(hp).opcode=A_LD) and
+              (taicpu(hp).oper[0]^.typ=top_reg) and
+              (taicpu(hp).oper[0]^.reg=NR_PC) then
+              begin
+                penalty:=1;
+                hp:=tai(hp.next);
+                while assigned(hp) and (hp.typ=ait_const) do
+                  begin
+                    inc(penalty);
+                    hp:=tai(hp.next);
+                  end;
+              end
+            else
+              penalty:=0;
+
+            { don't miss an insert }
+            doinsert:=doinsert or
+              (not(curdata.empty) and
+               (curinspos-lastinspos+penalty+extradataoffset>limit));
+
+            { split only at real instructions else the test below fails }
+            if doinsert and (curtai.typ=ait_instruction) and
+              (
+                { don't split loads of pc to lr and the following move }
+                not(
+                    (taicpu(curtai).opcode=A_MOV) and
+                    (taicpu(curtai).oper[0]^.typ=top_reg) and
+                    (taicpu(curtai).oper[0]^.reg=NR_R14) and
+                    (taicpu(curtai).oper[1]^.typ=top_reg) and
+                    (taicpu(curtai).oper[1]^.reg=NR_PC)
+                   )
+              ) then
+              begin
+                lastinspos:=-1;
+                extradataoffset:=0;
+                limit:=1016;
+                doinsert:=false;
+                hp:=tai(curtai.next);
+                current_asmdata.getjumplabel(l);
+                curdata.insert(taicpu.op_sym(A_BR,l));
+                curdata.concat(tai_label.create(l));
+                list.insertlistafter(curtai,curdata);
+                curtai:=hp;
+              end
+            else
+              curtai:=tai(curtai.next);
+          end;
+        list.concatlist(curdata);
+        curdata.free;
+      end;
+
+    procedure finalizeavr32code(list, listtoinsert: TAsmList);
+      begin
+        insertpcrelativedata(list, listtoinsert);
+      end;
+
+(*
+      Floating point instruction format information, taken from the linux kernel
+      ARM Floating Point Instruction Classes
+      | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+      |c o n d|1 1 0 P|U|u|W|L|   Rn  |v|  Fd |0|0|0|1|  o f f s e t  | CPDT
+      |c o n d|1 1 0 P|U|w|W|L|   Rn  |x|  Fd |0|0|1|0|  o f f s e t  | CPDT (copro 2)
+      | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+      |c o n d|1 1 1 0|a|b|c|d|e|  Fn |j|  Fd |0|0|0|1|f|g|h|0|i|  Fm | CPDO
+      |c o n d|1 1 1 0|a|b|c|L|e|  Fn |   Rd  |0|0|0|1|f|g|h|1|i|  Fm | CPRT
+      |c o n d|1 1 1 0|a|b|c|1|e|  Fn |1|1|1|1|0|0|0|1|f|g|h|1|i|  Fm | comparisons
+      | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+
+      CPDT            data transfer instructions
+                      LDF, STF, LFM (copro 2), SFM (copro 2)
+
+      CPDO            dyadic arithmetic instructions
+                      ADF, MUF, SUF, RSF, DVF, RDF,
+                      POW, RPW, RMF, FML, FDV, FRD, POL
+
+      CPDO            monadic arithmetic instructions
+                      MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
+                      SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
+
+      CPRT            joint arithmetic/data transfer instructions
+                      FIX (arithmetic followed by load/store)
+                      FLT (load/store followed by arithmetic)
+                      CMF, CNF CMFE, CNFE (comparisons)
+                      WFS, RFS (write/read floating point status register)
+                      WFC, RFC (write/read floating point control register)
+
+      cond            condition codes
+      P               pre/post index bit: 0 = postindex, 1 = preindex
+      U               up/down bit: 0 = stack grows down, 1 = stack grows up
+      W               write back bit: 1 = update base register (Rn)
+      L               load/store bit: 0 = store, 1 = load
+      Rn              base register
+      Rd              destination/source register
+      Fd              floating point destination register
+      Fn              floating point source register
+      Fm              floating point source register or floating point constant
+
+      uv              transfer length (TABLE 1)
+      wx              register count (TABLE 2)
+      abcd            arithmetic opcode (TABLES 3 & 4)
+      ef              destination size (rounding precision) (TABLE 5)
+      gh              rounding mode (TABLE 6)
+      j               dyadic/monadic bit: 0 = dyadic, 1 = monadic
+      i               constant bit: 1 = constant (TABLE 6)
+      */
+
+      /*
+      TABLE 1
+      +-------------------------+---+---+---------+---------+
+      |  Precision              | u | v | FPSR.EP | length  |
+      +-------------------------+---+---+---------+---------+
+      | Single                  | 0 | 0 |    x    | 1 words |
+      | Double                  | 1 | 1 |    x    | 2 words |
+      | Extended                | 1 | 1 |    x    | 3 words |
+      | Packed decimal          | 1 | 1 |    0    | 3 words |
+      | Expanded packed decimal | 1 | 1 |    1    | 4 words |
+      +-------------------------+---+---+---------+---------+
+      Note: x = don't care
+      */
+
+      /*
+      TABLE 2
+      +---+---+---------------------------------+
+      | w | x | Number of registers to transfer |
+      +---+---+---------------------------------+
+      | 0 | 1 |  1                              |
+      | 1 | 0 |  2                              |
+      | 1 | 1 |  3                              |
+      | 0 | 0 |  4                              |
+      +---+---+---------------------------------+
+      */
+
+      /*
+      TABLE 3: Dyadic Floating Point Opcodes
+      +---+---+---+---+----------+-----------------------+-----------------------+
+      | a | b | c | d | Mnemonic | Description           | Operation             |
+      +---+---+---+---+----------+-----------------------+-----------------------+
+      | 0 | 0 | 0 | 0 | ADF      | Add                   | Fd := Fn + Fm         |
+      | 0 | 0 | 0 | 1 | MUF      | Multiply              | Fd := Fn * Fm         |
+      | 0 | 0 | 1 | 0 | SUF      | Subtract              | Fd := Fn - Fm         |
+      | 0 | 0 | 1 | 1 | RSF      | Reverse subtract      | Fd := Fm - Fn         |
+      | 0 | 1 | 0 | 0 | DVF      | Divide                | Fd := Fn / Fm         |
+      | 0 | 1 | 0 | 1 | RDF      | Reverse divide        | Fd := Fm / Fn         |
+      | 0 | 1 | 1 | 0 | POW      | Power                 | Fd := Fn ^ Fm         |
+      | 0 | 1 | 1 | 1 | RPW      | Reverse power         | Fd := Fm ^ Fn         |
+      | 1 | 0 | 0 | 0 | RMF      | Remainder             | Fd := IEEE rem(Fn/Fm) |
+      | 1 | 0 | 0 | 1 | FML      | Fast Multiply         | Fd := Fn * Fm         |
+      | 1 | 0 | 1 | 0 | FDV      | Fast Divide           | Fd := Fn / Fm         |
+      | 1 | 0 | 1 | 1 | FRD      | Fast reverse divide   | Fd := Fm / Fn         |
+      | 1 | 1 | 0 | 0 | POL      | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm)  |
+      | 1 | 1 | 0 | 1 |          | undefined instruction | trap                  |
+      | 1 | 1 | 1 | 0 |          | undefined instruction | trap                  |
+      | 1 | 1 | 1 | 1 |          | undefined instruction | trap                  |
+      +---+---+---+---+----------+-----------------------+-----------------------+
+      Note: POW, RPW, POL are deprecated, and are available for backwards
+            compatibility only.
+      */
+
+      /*
+      TABLE 4: Monadic Floating Point Opcodes
+      +---+---+---+---+----------+-----------------------+-----------------------+
+      | a | b | c | d | Mnemonic | Description           | Operation             |
+      +---+---+---+---+----------+-----------------------+-----------------------+
+      | 0 | 0 | 0 | 0 | MVF      | Move                  | Fd := Fm              |
+      | 0 | 0 | 0 | 1 | MNF      | Move negated          | Fd := - Fm            |
+      | 0 | 0 | 1 | 0 | ABS      | Absolute value        | Fd := abs(Fm)         |
+      | 0 | 0 | 1 | 1 | RND      | Round to integer      | Fd := int(Fm)         |
+      | 0 | 1 | 0 | 0 | SQT      | Square root           | Fd := sqrt(Fm)        |
+      | 0 | 1 | 0 | 1 | LOG      | Log base 10           | Fd := log10(Fm)       |
+      | 0 | 1 | 1 | 0 | LGN      | Log base e            | Fd := ln(Fm)          |
+      | 0 | 1 | 1 | 1 | EXP      | Exponent              | Fd := e ^ Fm          |
+      | 1 | 0 | 0 | 0 | SIN      | Sine                  | Fd := sin(Fm)         |
+      | 1 | 0 | 0 | 1 | COS      | Cosine                | Fd := cos(Fm)         |
+      | 1 | 0 | 1 | 0 | TAN      | Tangent               | Fd := tan(Fm)         |
+      | 1 | 0 | 1 | 1 | ASN      | Arc Sine              | Fd := arcsin(Fm)      |
+      | 1 | 1 | 0 | 0 | ACS      | Arc Cosine            | Fd := arccos(Fm)      |
+      | 1 | 1 | 0 | 1 | ATN      | Arc Tangent           | Fd := arctan(Fm)      |
+      | 1 | 1 | 1 | 0 | URD      | Unnormalized round    | Fd := int(Fm)         |
+      | 1 | 1 | 1 | 1 | NRM      | Normalize             | Fd := norm(Fm)        |
+      +---+---+---+---+----------+-----------------------+-----------------------+
+      Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
+            available for backwards compatibility only.
+      */
+
+      /*
+      TABLE 5
+      +-------------------------+---+---+
+      |  Rounding Precision     | e | f |
+      +-------------------------+---+---+
+      | IEEE Single precision   | 0 | 0 |
+      | IEEE Double precision   | 0 | 1 |
+      | IEEE Extended precision | 1 | 0 |
+      | undefined (trap)        | 1 | 1 |
+      +-------------------------+---+---+
+      */
+
+      /*
+      TABLE 5
+      +---------------------------------+---+---+
+      |  Rounding Mode                  | g | h |
+      +---------------------------------+---+---+
+      | Round to nearest (default)      | 0 | 0 |
+      | Round toward plus infinity      | 0 | 1 |
+      | Round toward negative infinity  | 1 | 0 |
+      | Round toward zero               | 1 | 1 |
+      +---------------------------------+---+---+
+*)
+    function taicpu.GetString:string;
+      var
+        i : longint;
+        s : string;
+        addsize : boolean;
+      begin
+        s:='['+gas_op2str[opcode];
+        for i:=0 to ops-1 do
+         begin
+           with oper[i]^ do
+             begin
+               if i=0 then
+                s:=s+' '
+               else
+                s:=s+',';
+               { type }
+               addsize:=false;
+               if (ot and OT_VREG)=OT_VREG then
+                s:=s+'vreg'
+               else
+                 if (ot and OT_FPUREG)=OT_FPUREG then
+                  s:=s+'fpureg'
+               else
+                if (ot and OT_REGISTER)=OT_REGISTER then
+                 begin
+                   s:=s+'reg';
+                   addsize:=true;
+                 end
+               else
+                if (ot and OT_REGLIST)=OT_REGLIST then
+                 begin
+                   s:=s+'reglist';
+                   addsize:=false;
+                 end
+               else
+                if (ot and OT_IMM)=OT_IMM then
+                 begin
+                   s:=s+'imm';
+                   addsize:=true;
+                 end
+               else
+                if (ot and OT_MEMORY)=OT_MEMORY then
+                 begin
+                   s:=s+'mem';
+                   addsize:=true;
+                   if (ot and OT_AM2)<>0 then
+                     s:=s+' am2 ';
+                 end
+               else
+                 s:=s+'???';
+               { size }
+               if addsize then
+                begin
+                  if (ot and OT_BITS8)<>0 then
+                    s:=s+'8'
+                  else
+                   if (ot and OT_BITS16)<>0 then
+                    s:=s+'24'
+                  else
+                   if (ot and OT_BITS32)<>0 then
+                    s:=s+'32'
+                  else
+                   if (ot and OT_BITSSHIFTER)<>0 then
+                    s:=s+'shifter'
+                  else
+                    s:=s+'??';
+                  { signed }
+                  if (ot and OT_SIGNED)<>0 then
+                   s:=s+'s';
+                end;
+             end;
+         end;
+        GetString:=s+']';
+      end;
+
+
+    procedure taicpu.ResetPass1;
+      begin
+        { we need to reset everything here, because the choosen insentry
+          can be invalid for a new situation where the previously optimized
+          insentry is not correct }
+        InsEntry:=nil;
+        InsSize:=0;
+        LastInsOffset:=-1;
+      end;
+
+
+    procedure taicpu.ResetPass2;
+      begin
+        { we are here in a second pass, check if the instruction can be optimized }
+        if assigned(InsEntry) and
+           ((InsEntry^.flags and IF_PASS2)<>0) then
+         begin
+           InsEntry:=nil;
+           InsSize:=0;
+         end;
+        LastInsOffset:=-1;
+      end;
+
+
+    function taicpu.CheckIfValid:boolean;
+      begin
+        Result:=False; { unimplemented }
+      end;
+
+
+    function taicpu.Pass1(objdata:TObjData):longint;
+      {var
+        ldr2op : array[PF_B..PF_T] of tasmop = (
+          A_LDRB,A_LDRSB,A_LDRBT,A_LDRH,A_LDRSH,A_LDRT);
+        str2op : array[PF_B..PF_T] of tasmop = (
+          A_STRB,A_None,A_STRBT,A_STRH,A_None,A_STRT);}
+      begin
+        Pass1:=0;
+        { Save the old offset and set the new offset }
+        InsOffset:=ObjData.CurrObjSec.Size;
+        { Error? }
+        if (Insentry=nil) and (InsSize=-1) then
+          exit;
+        { set the file postion }
+        current_filepos:=fileinfo;
+
+        { tranlate LDR+postfix to complete opcode }
+        {if (opcode=A_LDR) and (oppostfix<>PF_None) then
+          begin
+            if (oppostfix in [low(ldr2op)..high(ldr2op)]) then
+              opcode:=ldr2op[oppostfix]
+            else
+              internalerror(2005091001);
+            if opcode=A_None then
+              internalerror(2005091004);
+            { postfix has been added to opcode }
+            oppostfix:=PF_None;
+          end
+        else if (opcode=A_STR) and (oppostfix<>PF_None) then
+          begin
+            if (oppostfix in [low(str2op)..high(str2op)]) then
+              opcode:=str2op[oppostfix]
+            else
+              internalerror(2005091002);
+            if opcode=A_None then
+              internalerror(2005091003);
+            { postfix has been added to opcode }
+            oppostfix:=PF_None;
+          end;  }
+
+        { Get InsEntry }
+        if FindInsEntry(objdata) then
+         begin
+           InsSize:=4;
+           LastInsOffset:=InsOffset;
+           Pass1:=InsSize;
+           exit;
+         end;
+        LastInsOffset:=-1;
+      end;
+
+
+    procedure taicpu.Pass2(objdata:TObjData);
+      begin
+        { error in pass1 ? }
+        if insentry=nil then
+         exit;
+        current_filepos:=fileinfo;
+        { Generate the instruction }
+        GenCode(objdata);
+      end;
+
+
+    procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
+      begin
+      end;
+
+
+    procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
+      begin
+      end;
+
+
+    procedure taicpu.ppubuildderefimploper(var o:toper);
+      begin
+      end;
+
+
+    procedure taicpu.ppuderefoper(var o:toper);
+      begin
+      end;
+
+
+    function  taicpu.InsEnd:longint;
+      begin
+        Result:=0; { unimplemented }
+      end;
+
+
+    procedure taicpu.create_ot(objdata:TObjData);
+      var
+        i,l,relsize : longint;
+        dummy : byte;
+        currsym : TObjSymbol;
+      begin
+        if ops=0 then
+         exit;
+        { update oper[].ot field }
+        for i:=0 to ops-1 do
+         with oper[i]^ do
+          begin
+            case typ of
+              top_regset:
+                begin
+                  ot:=OT_REGLIST;
+                end;
+              top_reg :
+                begin
+                  case getregtype(reg) of
+                    R_INTREGISTER:
+                      ot:=OT_REG32 or OT_SHIFTEROP;
+                    R_FPUREGISTER:
+                      ot:=OT_FPUREG;
+                    else
+                      internalerror(2005090901);
+                  end;
+                end;
+              top_ref :
+                begin
+                  if ref^.refaddr=addr_no then
+                    begin
+                      { create ot field }
+                      { we should get the size here dependend on the
+                        instruction }
+                      if (ot and OT_SIZE_MASK)=0 then
+                        ot:=OT_MEMORY or OT_BITS32
+                      else
+                        ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+                      if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
+                        ot:=ot or OT_MEM_OFFS;
+                      { if we need to fix a reference, we do it here }
+
+                      { pc relative addressing }
+                      if (ref^.base=NR_NO) and
+                        (ref^.index=NR_NO)
+                        { at least we should check if the destination symbol
+                          is in a text section }
+                        { and
+                        (ref^.symbol^.owner="text") } then
+                        ref^.base:=NR_PC;
+
+                      { determine possible address modes }
+                      if (ref^.base<>NR_NO) and
+                        (
+                          (
+                            (ref^.index=NR_NO) and
+                            (ref^.offset>=-4097) and
+                            (ref^.offset<=4097)
+                          ) or
+                          (
+                            (ref^.offset=0)
+                          ) or
+                          (
+                            (ref^.index<>NR_NO) and
+                            (ref^.offset=0)
+                          )
+                        ) then
+                        ot:=ot or OT_AM2;
+
+                    end
+                  else
+                    begin
+                      l:=ref^.offset;
+                      currsym:=ObjData.symbolref(ref^.symbol);
+                      if assigned(currsym) then
+                        inc(l,currsym.address);
+                      relsize:=(InsOffset+2)-l;
+                      if (relsize<-33554428) or (relsize>33554428) then
+                       ot:=OT_IMM32
+                      else
+                       ot:=OT_IMM24;
+                    end;
+                end;
+              top_local :
+                begin
+                  { we should get the size here dependend on the
+                    instruction }
+                  if (ot and OT_SIZE_MASK)=0 then
+                    ot:=OT_MEMORY or OT_BITS32
+                  else
+                    ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+                end;
+              top_const :
+                begin
+                  ot:=OT_IMM;
+                end;
+              top_none :
+                begin
+                  { generated when there was an error in the
+                    assembler reader. It never happends when generating
+                    assembler }
+                end;
+              top_shifterop:
+                begin
+                  ot:=OT_SHIFTEROP;
+                end;
+              top_coh:
+                begin
+                  ot:=OT_COH;
+                end;
+              else
+                internalerror(200402261);
+            end;
+          end;
+      end;
+
+
+    function taicpu.Matches(p:PInsEntry):longint;
+      { * IF_SM stands for Size Match: any operand whose size is not
+       * explicitly specified by the template is `really' intended to be
+       * the same size as the first size-specified operand.
+       * Non-specification is tolerated in the input instruction, but
+       * _wrong_ specification is not.
+       *
+       * IF_SM2 invokes Size Match on only the first _two_ operands, for
+       * three-operand instructions such as SHLD: it implies that the
+       * first two operands must match in size, but that the third is
+       * required to be _unspecified_.
+       *
+       * IF_SB invokes Size Byte: operands with unspecified size in the
+       * template are really bytes, and so no non-byte specification in
+       * the input instruction will be tolerated. IF_SW similarly invokes
+       * Size Word, and IF_SD invokes Size Doubleword.
+       *
+       * (The default state if neither IF_SM nor IF_SM2 is specified is
+       * that any operand with unspecified size in the template is
+       * required to have unspecified size in the instruction too...)
+      }
+      var
+        i{,j,asize,oprs} : longint;
+        {siz : array[0..3] of longint;}
+      begin
+        Matches:=100;
+        writeln(getstring,'---');
+
+        { Check the opcode and operands }
+        if (p^.opcode<>opcode) or (p^.ops<>ops) then
+         begin
+           Matches:=0;
+           exit;
+         end;
+
+        { Check that no spurious colons or TOs are present }
+        for i:=0 to p^.ops-1 do
+         if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
+          begin
+            Matches:=0;
+            exit;
+          end;
+
+        { Check that the operand flags all match up }
+        for i:=0 to p^.ops-1 do
+         begin
+           if ((p^.optypes[i] and (not oper[i]^.ot)) or
+               ((p^.optypes[i] and OT_SIZE_MASK) and
+                ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
+            begin
+              if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
+                  (oper[i]^.ot and OT_SIZE_MASK))<>0 then
+               begin
+                 Matches:=0;
+                 exit;
+               end
+              else
+               Matches:=1;
+            end;
+         end;
+      end;
+
+
+    function  taicpu.calcsize(p:PInsEntry):shortint;
+      begin
+        result:=4;
+      end;
+
+
+    function  taicpu.NeedAddrPrefix(opidx:byte):boolean;
+      begin
+        Result:=False; { unimplemented }
+      end;
+
+
+    procedure taicpu.Swapoperands;
+      begin
+      end;
+
+
+    function taicpu.FindInsentry(objdata:TObjData):boolean;
+      var
+        i : longint;
+      begin
+        result:=false;
+      { Things which may only be done once, not when a second pass is done to
+        optimize }
+        if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
+         begin
+           { create the .ot fields }
+           create_ot(objdata);
+           { set the file postion }
+           current_filepos:=fileinfo;
+         end
+        else
+         begin
+           { we've already an insentry so it's valid }
+           result:=true;
+           exit;
+         end;
+        { Lookup opcode in the table }
+        InsSize:=-1;
+        i:=instabcache^[opcode];
+        if i=-1 then
+         begin
+           Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
+           exit;
+         end;
+        insentry:=@instab[i];
+        while (insentry^.opcode=opcode) do
+         begin
+           if matches(insentry)=100 then
+             begin
+               result:=true;
+               exit;
+             end;
+           inc(i);
+           insentry:=@instab[i];
+         end;
+        Message1(asmw_e_invalid_opcode_and_operands,GetString);
+        { No instruction found, set insentry to nil and inssize to -1 }
+        insentry:=nil;
+        inssize:=-1;
+      end;
+
+
+    procedure taicpu.gencode(objdata:TObjData);
+      var
+        bytes : dword;
+        i_field : byte;
+
+      procedure setshifterop(op : byte);
+        begin
+          case oper[op]^.typ of
+            top_const:
+              begin
+                i_field:=1;
+                bytes:=bytes or dword(oper[op]^.val and $fff);
+              end;
+            top_reg:
+              begin
+                i_field:=0;
+                bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
+
+                { does a real shifter op follow? }
+                if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
+                  begin
+                  end;
+              end;
+          else
+            internalerror(2005091103);
+          end;
+        end;
+
+      begin
+        bytes:=$0;
+        { evaluate and set condition code }
+
+        { condition code allowed? }
+
+        { setup rest of the instruction }
+        case insentry^.code[0] of
+          #$08:
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 26);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 21);
+
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+              { create shifter op }
+              setshifterop(1);
+
+              { set i field }
+              bytes:=bytes or (i_field shl 25);
+            end;
+          #$ff:
+            internalerror(2005091101);
+          else
+            internalerror(2005091102);
+        end;
+        { we're finished, write code }
+        objdata.writebytes(bytes,sizeof(bytes));
+      end;
+
+
+begin
+  cai_align:=tai_align;
+end.
+

+ 245 - 0
compiler/avr32/agavr32gas.pas

@@ -0,0 +1,245 @@
+{
+    Copyright (c) 2003 by Florian Klaempfl
+
+    This unit implements an asm for the avr32
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit implements the GNU Assembler writer for the avr32
+}
+
+unit agavr32gas;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       globtype,
+       aasmtai,aasmdata,
+       aggas,
+       cpubase;
+
+    type
+      Tavr32GNUAssembler=class(TGNUassembler)
+        constructor create(smart: boolean); override;
+        function MakeCmdLine: TCmdStr; override;
+      end;
+
+      Tavr32InstrWriter=class(TCPUInstrWriter)
+        procedure WriteInstruction(hp : tai);override;
+      end;
+
+
+    const
+      gas_shiftmode2str : array[tshiftmode] of string[3] = (
+        '','<<','>>');
+
+  implementation
+
+    uses
+       cutils,globals,verbose,
+       systems,
+       assemble,
+       cpuinfo,aasmcpu,
+       itcpugas,
+       cgbase,cgutils;
+
+{****************************************************************************}
+{                         GNU avr32 Assembler writer                           }
+{****************************************************************************}
+
+    const
+      selector2str: array[tregisterselector] of string[2] = ('',':b',':l',':u',':t');
+
+    constructor Tavr32GNUAssembler.create(smart: boolean);
+      begin
+        inherited create(smart);
+        InstrWriter := Tavr32InstrWriter.create(self);
+      end;
+
+
+    function Tavr32GNUAssembler.MakeCmdLine: TCmdStr;
+      begin
+        result:=inherited MakeCmdLine;
+      end;
+
+
+{****************************************************************************}
+{                  Helper routines for Instruction Writer                    }
+{****************************************************************************}
+
+    function getreferencestring(var ref : treference) : string;
+      var
+        s : string;
+        function GetShift(a : aint) : aint;
+          begin
+            case a of
+              1: result:=0;
+              2: result:=1;
+              4: result:=2;
+              8: result:=3;
+            else
+              internalerror(2011012102);
+            end;
+          end;
+
+      begin
+         with ref do
+          begin
+{$ifdef extdebug}
+            // if base=NR_NO then
+            //   internalerror(200308292);
+
+            // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then
+            //   internalerror(200308293);
+{$endif extdebug}
+
+            if assigned(symbol) then
+              begin
+                if (base<>NR_NO) and not(is_pc(base)) then
+                  internalerror(200309011);
+                s:='pc['+symbol.name;
+                s:=symbol.name;
+                if offset<0 then
+                  s:=s+tostr(offset)
+                else if offset>0 then
+                  s:=s+'+'+tostr(offset);
+                //s:=s+']';
+              end
+            else
+              begin
+                s:=gas_regname(base);
+                if addressmode=AM_POSTINDEXED then
+                  s:=s+'++'
+                else if addressmode=AM_PREINDEXED then
+                  s:='--'+s;
+
+                if index<>NR_NO then
+                  begin
+                    if scalefactor > 1 then
+                      s:=s+'['+gas_regname(index)+selector2str[indexselector]+'<<'+tostr(getshift(scalefactor))+']'
+                    else
+                      s:=s+'['+gas_regname(index)+selector2str[indexselector]+']';
+                  end
+                else if offset<>0 then
+                  s:=s+'['+tostr(offset)+']';
+              end;
+
+          end;
+        getreferencestring:=s;
+      end;
+
+
+    const
+      shiftmode2str: array[tshiftmode] of string[3] = ('','<<','>>');
+
+    function getopstr(const o:toper) : string;
+      var
+        hs : string;
+        first : boolean;
+        r : tsuperregister;
+      begin
+        case o.typ of
+          top_reg:
+            getopstr:=gas_regname(o.reg);
+          top_shifterop:
+            getopstr:=shiftmode2str[o.shifterop^.shiftmode]+tostr(o.shifterop^.shiftimm);
+          top_const:
+            getopstr:=tostr(longint(o.val));
+          top_regset:
+            begin
+              getopstr:='';
+              first:=true;
+              for r:=RS_R0 to RS_R15 do
+                if r in o.regset^ then
+                  begin
+                    if not(first) then
+                      getopstr:=getopstr+',';
+                    getopstr:=getopstr+gas_regname(newreg(o.regtyp,r,o.subreg));
+                    first:=false;
+                  end;
+            end;
+          top_ref:
+            if o.ref^.refaddr=addr_full then
+              begin
+                hs:=o.ref^.symbol.name;
+                if o.ref^.offset>0 then
+                 hs:=hs+'+'+tostr(o.ref^.offset)
+                else
+                 if o.ref^.offset<0 then
+                  hs:=hs+tostr(o.ref^.offset);
+                getopstr:=hs;
+              end
+            else
+              getopstr:=getreferencestring(o.ref^);
+          top_coh:
+            getopstr:='COH';
+          top_selector:
+            getopstr:=gas_regname(o.reg)+selector2str[o.selector];
+          else
+            internalerror(2002070604);
+        end;
+      end;
+
+
+    Procedure Tavr32InstrWriter.WriteInstruction(hp : tai);
+    var op: TAsmOp;
+        postfix,s: string;
+        i: byte;
+        sep: string[3];
+    begin
+      op:=taicpu(hp).opcode;
+      s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition];
+      if taicpu(hp).oppostfix<>PF_None then
+        s:=s+'.'+oppostfix2str[taicpu(hp).oppostfix];
+
+      if taicpu(hp).ops<>0 then
+        begin
+          sep:=#9;
+          for i:=0 to taicpu(hp).ops-1 do
+            begin
+              if taicpu(hp).oper[i]^.typ = top_shifterop then
+                s:=s+getopstr(taicpu(hp).oper[i]^)
+              else
+                s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+
+              sep:=',';
+            end;
+        end;
+      owner.AsmWriteLn(s);
+    end;
+
+
+    const
+       as_avr32_gas_info : tasminfo =
+          (
+            id     : as_gas;
+
+            idtxt  : 'AS';
+            asmbin : 'as';
+            asmcmd : '-o $OBJ $ASM';
+            supported_targets : [system_avr32_embedded];
+            flags : [af_allowdirect,af_needar,af_smartlink_sections];
+            labelprefix : '.L';
+            comment : '# ';
+          );
+
+
+begin
+  RegisterAssembler(as_avr32_gas_info,Tavr32GNUAssembler);
+end.

+ 194 - 0
compiler/avr32/aoptcpu.pas

@@ -0,0 +1,194 @@
+{
+    Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+    Development Team
+
+    This unit implements the ARM optimizer object
+
+    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 aoptcpu;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses cpubase, aasmtai, aopt, aoptcpub;
+
+Type
+
+  { TCpuAsmOptimizer }
+
+  TCpuAsmOptimizer = class(TAsmOptimizer)
+    { uses the same constructor as TAopObj }
+    function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+  End;
+
+Implementation
+
+  uses
+    verbose,
+    aasmbase,aasmcpu,
+    cgbase;
+
+{ TCpuAsmOptimizer }
+
+  function Test_Set(const RegSet,t: tcpuregisterset): boolean;
+    begin
+      result := ((RegSet*t) = []) or ((RegSet*t) = t);
+    end;
+
+  function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+    var
+      v: LongInt;
+    begin
+      result := false;
+      case p.typ of
+        ait_instruction:
+          begin
+            { Collapse ADD r0,r0,r1 -> ADD r0,r1 }
+            if (taicpu(p).opcode in [A_ADD,A_SUB,A_AND,A_EOR,A_OR]) and
+               (taicpu(p).ops = 3) and
+               (taicpu(p).oper[0]^.typ = top_reg) and
+               (taicpu(p).oper[1]^.typ = top_reg) and
+               (taicpu(p).oper[2]^.typ = top_reg) and
+               (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+              begin
+                taicpu(p).ops:=2;
+                taicpu(p).loadreg(1,taicpu(p).oper[2]^.reg);
+                result:=true;
+                exit;
+              end;
+
+            { Collapse ADD r0,r1,r0 -> ADD r0,r1
+              SUB needs RSUB }
+            if (taicpu(p).opcode in [A_ADD,A_AND,A_EOR,A_OR]) and
+               (taicpu(p).ops = 3) and
+               (taicpu(p).oper[0]^.typ = top_reg) and
+               (taicpu(p).oper[1]^.typ = top_reg) and
+               (taicpu(p).oper[2]^.typ = top_reg) and
+               (taicpu(p).oper[0]^.reg = taicpu(p).oper[2]^.reg) then
+              begin
+                taicpu(p).ops:=2;
+                result:=true;
+                exit;
+              end;
+
+            case taicpu(p).opcode of
+              { Collapse instructions into a compact format }
+              A_SUB:
+                begin
+                  { SUB r0,r0,imm8 -> SUB r0,imm8 }
+                  if (taicpu(p).ops=3) and
+                     (taicpu(p).oper[0]^.typ = top_reg) and
+                     (taicpu(p).oper[1]^.typ = top_reg) and
+                     (taicpu(p).oper[2]^.typ = top_const) and
+                     (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+                     in_signed_bits(taicpu(p).oper[2]^.val, 8) then
+                    begin
+                      taicpu(p).ops:=2;
+                      taicpu(p).loadconst(1,taicpu(p).oper[2]^.val);
+                      result:=true;
+                    end
+                  { SUB r0,r1,r0 -> RSUB r0,r1 }
+                  else if (taicpu(p).ops=3) and
+                          (taicpu(p).oper[0]^.typ = top_reg) and
+                          (taicpu(p).oper[1]^.typ = top_reg) and
+                          (taicpu(p).oper[2]^.typ = top_reg) and
+                          (taicpu(p).oper[0]^.reg = taicpu(p).oper[2]^.reg) then
+                    begin
+                      taicpu(p).opcode:=A_RSUB;
+                      taicpu(p).ops:=2;
+                      result:=true;
+                    end;
+                end;
+              A_LSL,
+              A_LSR,
+              A_ASR:
+                begin
+                  { LSL r0,r0,imm8 -> LSL r0,imm8 }
+                  if (taicpu(p).ops=3) and
+                     (taicpu(p).oper[0]^.typ = top_reg) and
+                     (taicpu(p).oper[1]^.typ = top_reg) and
+                     (taicpu(p).oper[2]^.typ = top_const) and
+                     (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+                    begin
+                      taicpu(p).ops:=2;
+                      taicpu(p).loadconst(1,taicpu(p).oper[2]^.val);
+                      result:=true;
+                    end
+                end;
+              A_STM:
+                begin
+                  { Try to compress STM --sp, LIST down to PUSHM LIST }
+                  if (taicpu(p).oper[0]^.ref^.base = NR_STACK_POINTER_REG) and
+                     (taicpu(p).oper[0]^.ref^.addressmode = AM_PREINDEXED) and
+                     (taicpu(p).oper[1]^.regset^ <> []) then
+                    begin
+                      if test_set(taicpu(p).oper[1]^.regset^, [0..3]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [4..7]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [8..9]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [10]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [11]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [12]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [14]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [15]) and
+                         ((taicpu(p).oper[1]^.regset^ * [13]) = []) then
+                        begin
+                          taicpu(p).loadregset(0,taicpu(p).oper[1]^.regtyp,taicpu(p).oper[1]^.subreg,taicpu(p).oper[1]^.regset^);
+                          taicpu(p).ops:=1;
+                          taicpu(p).opcode:=A_PUSHM;
+                          result:=true;
+                          exit;
+                        end;
+                    end;
+                end;
+              A_LDM:
+                begin
+                  { Try to compress LDM sp++, LIST down to POPM LIST }
+                  if (taicpu(p).oper[0]^.ref^.base = NR_STACK_POINTER_REG) and
+                     ((taicpu(p).oper[0]^.ref^.addressmode = AM_POSTINDEXED) or
+                      (RS_STACK_POINTER_REG in taicpu(p).oper[1]^.regset^)) and
+                     (taicpu(p).oper[1]^.regset^ <> []) then
+                    begin
+                      if test_set(taicpu(p).oper[1]^.regset^, [0..3]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [4..7]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [8..9]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [10]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [11]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [12]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [14]) and
+                         test_set(taicpu(p).oper[1]^.regset^, [15]) and
+                         ((taicpu(p).oper[1]^.regset^ * [13]) = []) then
+                        begin
+                          taicpu(p).loadregset(0,taicpu(p).oper[1]^.regtyp,taicpu(p).oper[1]^.subreg,taicpu(p).oper[1]^.regset^);
+                          taicpu(p).ops:=1;
+                          taicpu(p).opcode:=A_POPM;
+                          result:=true;
+                          exit;
+                        end;
+                    end;
+                end;
+            end;
+          end;
+      end;
+    end;
+
+begin
+  casmoptimizer:=TCpuAsmOptimizer;
+End.

+ 120 - 0
compiler/avr32/aoptcpub.pas

@@ -0,0 +1,120 @@
+ {
+    Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+    Development Team
+
+    This unit contains several types and constants necessary for the
+    optimizer to work on the ARM architecture
+
+    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 aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand                                               }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{$define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override                                                            }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+  cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+  TInstr = Taicpu;
+  PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers                                      }
+  TCondRegs = Object
+    Constructor Init;
+    Destructor Done;
+  End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+  TAoptBaseCpu = class(TAoptBase)
+  End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes                                                                    }
+
+  MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+  MaxOps = 4;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction                                                            }
+
+  LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction                                                                }
+
+  LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction                                                            }
+
+  StoreSrc = 1;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction                                                                 }
+
+  StoreDst = 0;
+
+  aopt_uncondjmp = A_RJMP;
+  aopt_condjmp = A_BR;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.

+ 38 - 0
compiler/avr32/aoptcpuc.pas

@@ -0,0 +1,38 @@
+ {
+    Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+    Development Team
+
+    This unit contains the processor specific implementation of the
+    assembler optimizer common subexpression elimination object.
+
+    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 aoptcpuc;
+
+Interface
+
+Uses
+  AOptCs;
+
+Type
+  TRegInfoCpu = Object(TRegInfo)
+  End;
+
+
+Implementation
+
+End.

+ 40 - 0
compiler/avr32/aoptcpud.pas

@@ -0,0 +1,40 @@
+{
+    Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+    Development Team
+
+    This unit contains the processor specific implementation of the
+    assembler optimizer data flow analyzer.
+
+    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 aoptcpud;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+  AOptDA;
+
+Type
+  TAOptDFACpu = class(TAOptDFA)
+  End;
+
+Implementation
+
+
+End.

+ 181 - 0
compiler/avr32/avr32att.inc

@@ -0,0 +1,181 @@
+{ don't edit, this file is generated from avr32ins.dat }
+(
+'none',
+'abs',
+'acr',
+'adc',
+'add',
+'addabs',
+'cp',
+'cpc',
+'max',
+'min',
+'neg',
+'rsub',
+'sbc',
+'scr',
+'sub',
+'tbnz',
+'divs',
+'divu',
+'mac',
+'macs',
+'macu',
+'mul',
+'muls',
+'mulu',
+'addhh',
+'machh',
+'macwh',
+'mulhh',
+'mulwh',
+'mulnhh',
+'mulnwh',
+'satadd',
+'satsub',
+'satrnds',
+'satrndu',
+'sats',
+'satu',
+'subhh',
+'mulsathh',
+'mulsatrndhh',
+'mulsatrndwh',
+'mulsatwh',
+'macsathh',
+'and',
+'andn',
+'andh',
+'andl',
+'com',
+'eor',
+'eorh',
+'eorl',
+'or',
+'orh',
+'orl',
+'tst',
+'bfexts',
+'bfextu',
+'bfins',
+'bld',
+'brev',
+'bst',
+'casts',
+'castu',
+'cbr',
+'clz',
+'sbr',
+'swap',
+'asr',
+'lsl',
+'lsr',
+'rol',
+'ror',
+'br',
+'rjmp',
+'acall',
+'icall',
+'mcall',
+'rcall',
+'scall',
+'ret',
+'retd',
+'rete',
+'rets',
+'mov',
+'movh',
+'ld',
+'ldins',
+'ldswp',
+'lddpc',
+'lddsp',
+'st',
+'stcond',
+'stdsp',
+'sthh',
+'stswp',
+'xchg',
+'ldm',
+'ldmts',
+'popm',
+'pushm',
+'stm',
+'stmts',
+'breakpoint',
+'cache',
+'csrf',
+'csrfcz',
+'frs',
+'mfdr',
+'mfsr',
+'mtdr',
+'mtsr',
+'musfr',
+'mustr',
+'nop',
+'pref',
+'sleep',
+'sr',
+'ssrf',
+'sync',
+'tlbr',
+'tlbs',
+'tlbw',
+'cop',
+'ldc',
+'ldc0',
+'ldcm',
+'mvcr',
+'mvrc',
+'stc',
+'stc0',
+'stcm',
+'pabs',
+'packsh',
+'packw',
+'padd',
+'paddh',
+'padds',
+'paddsub',
+'paddsubh',
+'paddsubs',
+'paddx',
+'paddxh',
+'paddxs',
+'pasr',
+'pavg',
+'plsl',
+'plsr',
+'pmax',
+'pmin',
+'psad',
+'psub',
+'psubadd',
+'psubaddh',
+'psubadds',
+'psubh',
+'psubs',
+'psubx',
+'psubxh',
+'psubxs',
+'punpck',
+'memc',
+'mems',
+'memt',
+'fmac',
+'fnmac',
+'fmsc',
+'fnmsc',
+'fmul',
+'fnmul',
+'fadd',
+'fsub',
+'fcastrs',
+'fcastsw',
+'fcastuw',
+'fcp',
+'fchk',
+'frcpa',
+'frsqrta'
+);

+ 181 - 0
compiler/avr32/avr32atts.inc

@@ -0,0 +1,181 @@
+{ don't edit, this file is generated from avr32ins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);

+ 290 - 0
compiler/avr32/avr32ins.dat

@@ -0,0 +1,290 @@
+;
+; Table of assembler instructions for Free Pascal
+; adapted from Netwide Assembler by Florian Klaempfl
+;
+;
+; The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+; Julian Hall. All rights reserved. The software is
+; redistributable under the licence given in the file "Licence"
+; distributed in the NASM archive.
+;
+; Format of file: first field is operands, second field is \encodingformat\needed bytes.starting from lsb
+; Encodingformat follows the indexes from the AVR32 architecture manual version 32000B–AVR32–11/07 
+; Third field is architecture version
+
+[NONE]
+void                    void                            none
+
+[ABS]
+reg32                   \2\x4                           1
+[ACR]
+reg32                   \2\x0                           1
+[ADC]
+reg32,reg32,reg32       \20\x4                          1
+[ADD]
+reg32,reg32             \1\0                            1
+reg32,reg32,shifterop   \19\0                           1 
+;[ADDcc]
+;reg32,reg32,reg32       \                               2
+[ADDABS]
+reg32,reg32,reg32       \20\xE4                         1
+[CP]
+[CPC]
+reg32,reg32             \27\3                           1
+reg32                   \2\2                            1
+[MAX]
+reg32,reg32,reg32       \20\xC4                         1
+[MIN]
+reg32,reg32,reg32       \20\xD4                         1
+[NEG]
+reg32                   \2\3                            1
+[RSUB]
+reg32,reg32             \1\2                            1
+reg32,reg32,imm8        \23\1                           1
+;[RSUBcc]
+;reg32,imm8              \10\xD                          1
+[SBC]
+reg32,reg32,reg32       \20\x14                         1
+[SCR]
+reg32,imm5              \11\xD                          1
+[SUB]
+reg32,reg32             \1\1                            1
+reg32,reg32,shifterop   \19\1                           1
+reg32,imm8              \4\0                            1
+reg32,imm21             \30\1                           1
+reg32,reg32,imm16       \32\xC                          1
+;[SUBcc]
+;reg32,imm8
+;reg32,reg32,reg32
+[TBNZ]
+reg32                   \2\xE                           1
+
+; MULTIPLY
+[DIVS]
+reg32,reg32,reg32       \20\xC0                         1
+[DIVU]
+reg32,reg32,reg32       \20\xD0                         1
+[MAC]
+reg32,reg32,reg32       \20\x34                         1
+[MACS]
+reg32,reg32,reg32       \20\x54                         1
+[MACU]
+reg32,reg32,reg32       \20\x74                         1
+[MUL]
+reg32,reg32             \1\xB3                          1
+reg32,reg32,reg32       \20\x24                         1
+reg32,reg32,imm8        \23\0                           1
+[MULS]
+reg32,reg32,reg32       \20\x44                         1
+[MULU]
+reg32,reg32,reg32       \20\x64                         1
+
+; DSP
+[ADDHH]
+[MACHH]
+[MACWH]
+[MULHH]
+[MULWH]
+[MULNHH]
+[MULNWH]
+[SATADD]
+[SATSUB]
+[SATRNDS]
+[SATRNDU]
+[SATS]
+[SATU]
+[SUBHH]
+[MULSATHH]
+[MULSATRNDHH]
+[MULSATRNDWH]
+[MULSATWH]
+[MACSATHH]
+
+; LOGIC
+[AND]
+reg32,reg32             \1\x6                           1
+reg32,reg32,shifterop   \49\0                           1
+;[ANDcc]
+;reg32,reg32,reg32       \1\x6                           1
+[ANDN]
+reg32,reg32             \1\x8                           1
+[ANDH]
+reg32,imm16             \47\2                           1
+reg32,imm16,coh         \47\3                           1
+[ANDL]
+reg32,imm16             \47\0                           1
+reg32,imm16,coh         \47\1                           1
+[COM]
+reg32                   \2\xB                           1
+[EOR]
+reg32,reg32             \1\5                            1
+reg32,reg32,shifterop   \49\x20                         1
+;[EORcc]
+;reg32,reg32,reg         \
+[EORH]
+reg32,imm16             \28\0\xE1                       1
+[EORL]
+reg32,imm16             \28\0\xC1                       1
+[OR]
+reg32,reg32             \1\4                            1
+reg32,reg32,shifterop   \49\x80                         1
+;[ORcc]
+;reg32,reg32,reg32
+[ORH]
+reg32,imm16             \28\0\xA1                       1
+[ORL]
+reg32,imm16             \28\0\x81                       1
+[TST]
+reg32,reg32             \1\x7                           1
+
+; BIT
+[BFEXTS]
+reg32,reg32,imm5,imm5   \25\x2C                         1
+[BFEXTU]
+reg32,reg32,imm5,imm5   \25\x30                         1
+[BFINS]
+reg32,reg32,imm5,imm5   \25\x34                         1
+[BLD]
+reg32,imm5              \42\6                           1
+[BREV]
+reg32                   \2\x49                          1
+[BST]
+reg32,imm5              \42\7                           1
+[CASTS]
+
+[CASTU]
+[CBR]
+[CLZ]
+[SBR]
+[SWAP]
+
+; SHIFT
+[ASR]
+[LSL]
+[LSR]
+[ROL]
+[ROR]
+
+; CONTROL
+[BRcc]
+[RJMP]
+[ACALL]
+[ICALL]
+[MCALL]
+[RCALL]
+[SCALL]
+[RETcc]
+[RETD]
+[RETE]
+[RETS]
+
+; DATA
+[MOVcc]
+[MOVH]
+
+[LDcc]
+[LDINS]
+[LDSWP]
+[LDDPC]
+[LDDSP]
+[STcc]
+[STCOND]
+[STDSP]
+[STHH]
+[STSWP]
+[XCHG]
+
+; MULTIPLE DATA
+[LDM]
+[LDMTS]
+[POPM]
+[PUSHM]
+[STM]
+[STMTS]
+
+[BREAKPOINT]
+[CACHE]
+[CSRF]
+[CSRFCZ]
+[FRS]
+[MFDR]
+[MFSR]
+[MTDR]
+[MTSR]
+[MUSFR]
+[MUSTR]
+[NOP]
+[PREF]
+[SLEEP]
+[SRcc]
+[SSRF]
+[SYNC]
+[TLBR]
+[TLBS]
+[TLBW]
+
+; COPROCESSOR
+[COP]
+[LDC]
+[LDC0]
+[LDCM]
+[MVCR]
+[MVRC]
+[STC]
+[STC0]
+[STCM]
+
+; SIMD
+[PABS]
+[PACKSH]
+[PACKW]
+[PADD]
+[PADDH]
+[PADDS]
+[PADDSUB]
+[PADDSUBH]
+[PADDSUBS]
+[PADDX]
+[PADDXH]
+[PADDXS]
+[PASR]
+[PAVG]
+[PLSL]
+[PLSR]
+[PMAX]
+[PMIN]
+[PSAD]
+[PSUB]
+[PSUBADD]
+[PSUBADDH]
+[PSUBADDS]
+[PSUBH]
+[PSUBS]
+[PSUBX]
+[PSUBXH]
+[PSUBXS]
+[PUNPCK]
+
+[MEMC]
+[MEMS]
+[MEMT]
+
+; FPU
+[FMAC]
+[FNMAC]
+[FMSC]
+[FNMSC]
+[FMUL]
+[FNMUL]
+[FADD]
+[FSUB]
+
+[FCASTRS]
+[FCASTSW]
+[FCASTUW]
+
+[FCP]
+[FCHK]
+
+[FRCPA]
+[FRSQRTA]

+ 2 - 0
compiler/avr32/avr32nop.inc

@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from avr32ins.dat }
+55;

+ 181 - 0
compiler/avr32/avr32op.inc

@@ -0,0 +1,181 @@
+{ don't edit, this file is generated from avr32ins.dat }
+(
+A_NONE,
+A_ABS,
+A_ACR,
+A_ADC,
+A_ADD,
+A_ADDABS,
+A_CP,
+A_CPC,
+A_MAX,
+A_MIN,
+A_NEG,
+A_RSUB,
+A_SBC,
+A_SCR,
+A_SUB,
+A_TBNZ,
+A_DIVS,
+A_DIVU,
+A_MAC,
+A_MACS,
+A_MACU,
+A_MUL,
+A_MULS,
+A_MULU,
+A_ADDHH,
+A_MACHH,
+A_MACWH,
+A_MULHH,
+A_MULWH,
+A_MULNHH,
+A_MULNWH,
+A_SATADD,
+A_SATSUB,
+A_SATRNDS,
+A_SATRNDU,
+A_SATS,
+A_SATU,
+A_SUBHH,
+A_MULSATHH,
+A_MULSATRNDHH,
+A_MULSATRNDWH,
+A_MULSATWH,
+A_MACSATHH,
+A_AND,
+A_ANDN,
+A_ANDH,
+A_ANDL,
+A_COM,
+A_EOR,
+A_EORH,
+A_EORL,
+A_OR,
+A_ORH,
+A_ORL,
+A_TST,
+A_BFEXTS,
+A_BFEXTU,
+A_BFINS,
+A_BLD,
+A_BREV,
+A_BST,
+A_CASTS,
+A_CASTU,
+A_CBR,
+A_CLZ,
+A_SBR,
+A_SWAP,
+A_ASR,
+A_LSL,
+A_LSR,
+A_ROL,
+A_ROR,
+A_BR,
+A_RJMP,
+A_ACALL,
+A_ICALL,
+A_MCALL,
+A_RCALL,
+A_SCALL,
+A_RET,
+A_RETD,
+A_RETE,
+A_RETS,
+A_MOV,
+A_MOVH,
+A_LD,
+A_LDINS,
+A_LDSWP,
+A_LDDPC,
+A_LDDSP,
+A_ST,
+A_STCOND,
+A_STDSP,
+A_STHH,
+A_STSWP,
+A_XCHG,
+A_LDM,
+A_LDMTS,
+A_POPM,
+A_PUSHM,
+A_STM,
+A_STMTS,
+A_BREAKPOINT,
+A_CACHE,
+A_CSRF,
+A_CSRFCZ,
+A_FRS,
+A_MFDR,
+A_MFSR,
+A_MTDR,
+A_MTSR,
+A_MUSFR,
+A_MUSTR,
+A_NOP,
+A_PREF,
+A_SLEEP,
+A_SR,
+A_SSRF,
+A_SYNC,
+A_TLBR,
+A_TLBS,
+A_TLBW,
+A_COP,
+A_LDC,
+A_LDC0,
+A_LDCM,
+A_MVCR,
+A_MVRC,
+A_STC,
+A_STC0,
+A_STCM,
+A_PABS,
+A_PACKSH,
+A_PACKW,
+A_PADD,
+A_PADDH,
+A_PADDS,
+A_PADDSUB,
+A_PADDSUBH,
+A_PADDSUBS,
+A_PADDX,
+A_PADDXH,
+A_PADDXS,
+A_PASR,
+A_PAVG,
+A_PLSL,
+A_PLSR,
+A_PMAX,
+A_PMIN,
+A_PSAD,
+A_PSUB,
+A_PSUBADD,
+A_PSUBADDH,
+A_PSUBADDS,
+A_PSUBH,
+A_PSUBS,
+A_PSUBX,
+A_PSUBXH,
+A_PSUBXS,
+A_PUNPCK,
+A_MEMC,
+A_MEMS,
+A_MEMT,
+A_FMAC,
+A_FNMAC,
+A_FMSC,
+A_FNMSC,
+A_FMUL,
+A_FNMUL,
+A_FADD,
+A_FSUB,
+A_FCASTRS,
+A_FCASTSW,
+A_FCASTUW,
+A_FCP,
+A_FCHK,
+A_FRCPA,
+A_FRSQRTA
+);

+ 24 - 0
compiler/avr32/avr32reg.dat

@@ -0,0 +1,24 @@
+;
+; AVR32 registers
+;
+; layout
+; <name>,<type>,<subtype>,<value>,<stdname>,<stab idx>,<dwarf idx>
+;
+NO,$00,$00,$00,INVALID,-1,-1
+; Integer registers
+R0,$01,$04,$00,r0,0,0
+R1,$01,$04,$01,r1,1,1
+R2,$01,$04,$02,r2,2,2
+R3,$01,$04,$03,r3,3,3
+R4,$01,$04,$04,r4,4,4
+R5,$01,$04,$05,r5,5,5
+R6,$01,$04,$06,r6,6,6
+R7,$01,$04,$07,r7,7,7
+R8,$01,$04,$08,r8,8,8
+R9,$01,$04,$09,r9,9,9
+R10,$01,$04,$0a,r10,10,10
+R11,$01,$04,$0b,r11,11,11
+R12,$01,$04,$0c,r12,12,12
+R13,$01,$04,$0d,r13,13,13
+R14,$01,$04,$0e,r14,14,14
+R15,$01,$04,$0f,r15,15,15

+ 388 - 0
compiler/avr32/avr32tab.inc

@@ -0,0 +1,388 @@
+{ don't edit, this file is generated from avr32ins.dat }
+(
+  (
+    opcode  : A_NONE;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none);
+    code    : #0;
+    flags   : if_none
+  ),
+  (
+    opcode  : A_ABS;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#4;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ACR;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#4;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #17#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ADDABS;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#228;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_CPC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #23#3;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_CPC;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#2;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#196;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MIN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#212;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_NEG;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#3;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_RSUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#2;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_RSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_imm or ot_bits8,ot_none);
+    code    : #19#1;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#20;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SCR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits5,ot_none,ot_none);
+    code    : #9#13;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#1;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #17#1;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits8,ot_none,ot_none);
+    code    : #4#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits21,ot_none,ot_none);
+    code    : #24#1;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_imm or ot_bits16,ot_none);
+    code    : #26#12;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_TBNZ;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#14;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_DIVS;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#192;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_DIVU;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#208;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MAC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#52;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MACS;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#84;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MACU;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#116;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#179;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#36;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_imm or ot_bits8,ot_none);
+    code    : #19#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MULS;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#68;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_MULU;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+    code    : #16#100;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#6;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #41#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ANDN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#8;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ANDH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_none,ot_none);
+    code    : #39#2;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ANDH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_coh,ot_none);
+    code    : #39#3;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ANDL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_none,ot_none);
+    code    : #39#0;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ANDL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_coh,ot_none);
+    code    : #39#1;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_COM;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#11;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#5;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #41#32;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_EORH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_none,ot_none);
+    code    : #24#0#225;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_EORL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_none,ot_none);
+    code    : #24#0#193;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_OR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#4;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_OR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+    code    : #41#128;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ORH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_none,ot_none);
+    code    : #24#0#161;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_ORL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits16,ot_none,ot_none);
+    code    : #24#0#129;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #1#7;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_BFEXTS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_imm or ot_bits5,ot_imm or ot_bits5);
+    code    : #21#44;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_BFEXTU;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_imm or ot_bits5,ot_imm or ot_bits5);
+    code    : #21#48;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_BFINS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_imm or ot_bits5,ot_imm or ot_bits5);
+    code    : #21#52;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_BLD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits5,ot_none,ot_none);
+    code    : #34#6;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_BREV;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none);
+    code    : #2#73;
+    flags   : if_1
+  ),
+  (
+    opcode  : A_BST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_imm or ot_bits5,ot_none,ot_none);
+    code    : #34#7;
+    flags   : if_1
+  )
+);

+ 1838 - 0
compiler/avr32/cgcpu.pas

@@ -0,0 +1,1838 @@
+{
+
+    Copyright (c) 2003 by Florian Klaempfl
+    Member of the Free Pascal development team
+
+    This unit implements the code generator for the avr32
+
+    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 cgcpu;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       globtype,symtype,symdef,
+       cgbase,cgutils,cgobj,
+       aasmbase,aasmcpu,aasmtai,aasmdata,
+       parabase,
+       cpubase,cpuinfo,node,cg64f32,rgcpu;
+
+
+    type
+
+      { tcgavr32 }
+
+      tcgavr32 = class(tcg)
+        procedure init_register_allocators;override;
+        procedure done_register_allocators;override;
+
+        {function getfpuregister(list: TAsmList; size: Tcgsize): Tregister; override;
+        function getmmregister(list: TAsmList; size: Tcgsize): Tregister; override;}
+
+        procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
+        procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
+        procedure a_load_reg_cgpara(list: TAsmList; size: tcgsize; r: tregister; const cgpara: TCGPara); override;
+        procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
+
+        procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+        procedure a_call_reg(list : TAsmList;reg: tregister);override;
+        procedure a_call_ref(list : TAsmList;ref: treference);override;
+
+        procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+        procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+        procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg;size: tcgsize; a: tcgint; src, dst: tregister); override;
+        procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg;size: tcgsize; src1, src2, dst: tregister); override;
+        procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+        procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+
+        { move instructions }
+        procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
+        procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+        procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
+        procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+        function a_internal_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference):treference;
+        function a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
+
+        {  comparison operations }
+        procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);override;
+        procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+        procedure a_jmp_name(list : TAsmList;const s : string); override;
+        procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+        procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+
+        procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+        procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+        procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+
+        procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+        procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+        procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);override;
+        procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+        procedure g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : tcgint;aligned : boolean);
+
+        procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
+        procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
+
+        procedure g_save_registers(list : TAsmList);override;
+        procedure g_restore_registers(list : TAsmList);override;
+
+        procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+        procedure fixref(list : TAsmList;var ref : treference);
+        function handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference; virtual;
+
+        procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+        procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint); override;
+        procedure g_stackpointer_alloc(list : TAsmList;size : longint);override;
+      private
+        { clear out potential overflow bits from 8 or 16 bit operations  }
+        { the upper 24/16 bits of a register after an operation          }
+        procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+      end;
+
+      tcg64favr32 = class(tcg64f32)
+        procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+        procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+        procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+        procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+        procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+        procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+      end;
+
+    const
+      OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
+                           C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
+
+      winstackpagesize = 4096;
+
+    procedure create_codegen;
+
+  implementation
+
+
+    uses
+       globals,verbose,systems,cutils,
+       aopt,aoptcpu,
+       fmodule,
+       symconst,symsym,
+       tgobj,
+       procinfo,cpupi,
+       paramgr;
+
+
+    function size2postfix(size: TCgSize): TOpPostfix;
+      begin
+        case size of
+          OS_S8:
+            result:=PF_SB;
+          OS_8:
+            result:=PF_UB;
+          OS_S16:
+            result:=PF_SH;
+          OS_16:
+            result:=PF_UH;
+          OS_S32,
+          OS_32:
+            result:=PF_W;
+        else
+          result:=PF_NONE;
+        end;
+      end;
+
+
+    function unsignedsize2postfix(size: TCgSize): TOpPostfix;
+      begin
+        case size of
+          OS_S8,
+          OS_8:
+            result:=PF_B;
+          OS_S16,
+          OS_16:
+            result:=PF_H;
+          OS_S32,
+          OS_32:
+            result:=PF_W;
+        else
+          result:=PF_NONE;
+        end;
+      end;
+
+
+    function use_push(const cgpara:tcgpara):boolean;
+      begin
+        result:=(not paramanager.use_fixed_stack) and
+                assigned(cgpara.location) and
+                (cgpara.location^.loc=LOC_REFERENCE) and
+                (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
+      end;
+
+
+    procedure tcgavr32.init_register_allocators;
+      begin
+        inherited init_register_allocators;
+        { Reverse order to make it allocate the higher registers first.
+          This makes it more likely to contract a pushm statement into a compact pushm }
+        rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+            [RS_R12,RS_R11,RS_R10,RS_R9,RS_R8,RS_R6,RS_R5,RS_R4,
+             RS_R3,RS_R2,RS_R1,RS_R0],first_int_imreg,[]); 
+      end;
+
+
+    procedure tcgavr32.done_register_allocators;
+      begin
+        rg[R_INTREGISTER].free;
+        inherited done_register_allocators;
+      end;
+
+    {function tcgavr32.getfpuregister(list: TAsmList; size: Tcgsize): Tregister;
+      begin
+        case size of
+          OS_F32:
+            size:=OS_S32;
+          OS_F64:
+            size:=OS_S64;
+          OS_F80,
+          OS_F128:
+            size:=OS_128;
+        end;
+
+        Result:=getintregister(list, size);
+      end;
+
+    function tcgavr32.getmmregister(list: TAsmList; size: Tcgsize): Tregister;
+      begin
+        case size of
+          OS_F32:
+            size:=OS_S32;
+          OS_F64:
+            size:=OS_S64;
+          OS_F80,
+          OS_F128:
+            size:=OS_128;
+        end;
+
+        Result:=getintregister(list, size);
+      end;}
+
+
+     procedure tcgavr32.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
+       var
+          imm_shift : byte;
+          l : tasmlabel;
+          hr : treference;
+       begin
+          if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+            internalerror(2002090902);
+          if in_signed_bits(a,21) then
+            list.concat(taicpu.op_reg_const(A_MOV,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(setoppostfix(taicpu.op_reg_ref(A_LD,reg,hr),size2postfix(size)));
+            end;
+       end;
+
+
+     procedure tcgavr32.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
+       var
+         oppostfix:toppostfix;
+         usedtmpref: treference;
+         tmpreg,tmpreg2 : tregister;
+         so : tshifterop;
+         dir : integer;
+       begin
+         if (TCGSize2Size[FromSize] >= TCGSize2Size[ToSize]) then
+           FromSize := ToSize;
+         oppostfix:=size2postfix(fromsize);
+         if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[fromsize]) then
+           begin
+             if target_info.endian=endian_big then
+               dir:=-1
+             else
+               dir:=1;
+             case FromSize of
+               OS_16,OS_S16:
+                 begin
+                   { only complicated references need an extra loadaddr }
+                   if assigned(ref.symbol) or
+                     (ref.index<>NR_NO) or
+                     (ref.offset<-4095) or
+                     (ref.offset>4094) or
+                     { sometimes the compiler reused registers }
+                     (reg=ref.index) or
+                     (reg=ref.base) then
+                     begin
+                       tmpreg2:=getintregister(list,OS_INT);
+                       a_loadaddr_ref_reg(list,ref,tmpreg2);
+                       reference_reset_base(usedtmpref,tmpreg2,0,ref.alignment);
+                     end
+                   else
+                     usedtmpref:=ref;
+
+                   if target_info.endian=endian_big then
+                     inc(usedtmpref.offset,1);
+                   shifterop_reset(so);so.shiftmode:=SM_LSL;so.shiftimm:=8;
+                   tmpreg:=getintregister(list,OS_INT);
+                   a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
+                   inc(usedtmpref.offset,dir);
+                   if FromSize=OS_16 then
+                     a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg)
+                   else
+                     a_internal_load_ref_reg(list,OS_S8,OS_S8,usedtmpref,tmpreg);
+                   list.concat(taicpu.op_reg_reg_reg_shifterop(A_OR,reg,reg,tmpreg,so));
+                 end;
+               OS_32,OS_S32:
+                 begin
+                   tmpreg:=getintregister(list,OS_INT);
+
+                   { only complicated references need an extra loadaddr }
+                   if assigned(ref.symbol) or
+                     (ref.index<>NR_NO) or
+                     (ref.offset<-4095) or
+                     (ref.offset>4092) or
+                     { sometimes the compiler reused registers }
+                     (reg=ref.index) or
+                     (reg=ref.base) then
+                     begin
+                       tmpreg2:=getintregister(list,OS_INT);
+                       a_loadaddr_ref_reg(list,ref,tmpreg2);
+                       reference_reset_base(usedtmpref,tmpreg2,0,ref.alignment);
+                     end
+                   else
+                     usedtmpref:=ref;
+
+                   shifterop_reset(so);so.shiftmode:=SM_LSL;
+                   if ref.alignment=2 then
+                     begin
+                       if target_info.endian=endian_big then
+                         inc(usedtmpref.offset,2);
+                       a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,reg);
+                       inc(usedtmpref.offset,dir*2);
+                       a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,tmpreg);
+                       so.shiftimm:=16;
+                       list.concat(taicpu.op_reg_reg_reg_shifterop(A_OR,reg,reg,tmpreg,so));
+                     end
+                   else
+                     begin
+                       if target_info.endian=endian_big then
+                         inc(usedtmpref.offset,3);
+                       a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
+                       inc(usedtmpref.offset,dir);
+                       a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+                       so.shiftimm:=8;
+                       list.concat(taicpu.op_reg_reg_reg_shifterop(A_OR,reg,reg,tmpreg,so));
+                       inc(usedtmpref.offset,dir);
+                       a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+                       so.shiftimm:=16;
+                       list.concat(taicpu.op_reg_reg_reg_shifterop(A_OR,reg,reg,tmpreg,so));
+                       inc(usedtmpref.offset,dir);
+                       a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+                       so.shiftimm:=24;
+                       list.concat(taicpu.op_reg_reg_reg_shifterop(A_OR,reg,reg,tmpreg,so));
+                     end;
+                 end
+               else
+                 handle_load_store(list,A_LD,oppostfix,reg,ref);
+             end;
+           end
+         else
+           handle_load_store(list,A_LD,oppostfix,reg,ref);
+
+         if (fromsize=OS_S8) and (tosize = OS_16) then
+           a_load_reg_reg(list,OS_16,OS_32,reg,reg);
+       end;
+
+
+    procedure tcgavr32.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
+      var
+        ref: treference;
+        treg: TRegister;
+      begin
+        paraloc.check_simple_location;
+        paramanager.allocparaloc(list,paraloc.location);
+        case paraloc.location^.loc of
+          LOC_REGISTER,LOC_CREGISTER:
+            a_load_const_reg(list,size,a,paraloc.location^.register);
+          LOC_REFERENCE:
+            begin
+              treg:=getintregister(list,size);
+              a_load_const_reg(list,size,a,treg);
+              a_load_reg_cgpara(list,size,treg,paraloc);
+            end;
+          else
+            internalerror(2002081101);
+        end;
+      end;
+
+
+    procedure tcgavr32.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
+      var
+        tmpref, ref: treference;
+        location: pcgparalocation;
+        sizeleft: tcgint;
+      begin
+        location := paraloc.location;
+        tmpref := r;
+        sizeleft := paraloc.intsize;
+        while assigned(location) do
+          begin
+            paramanager.allocparaloc(list,location);
+            case location^.loc of
+              LOC_REGISTER,LOC_CREGISTER:
+                a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+              LOC_REFERENCE:
+                begin
+                  reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment);
+                  { doubles in softemu mode have a strange order of registers and references }
+                  if location^.size=OS_32 then
+                    g_concatcopy(list,tmpref,ref,4)
+                  else
+                    begin
+                      g_concatcopy(list,tmpref,ref,sizeleft);
+                      if assigned(location^.next) then
+                        internalerror(2005010710);
+                    end;
+                end;
+              LOC_FPUREGISTER,LOC_CFPUREGISTER:
+                case location^.size of
+                   OS_F32, OS_F64:
+                     a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+                   else
+                     internalerror(2002072801);
+                end;
+              LOC_VOID:
+                begin
+                  // nothing to do
+                end;
+              else
+                internalerror(2002081103);
+            end;
+            inc(tmpref.offset,tcgsize2size[location^.size]);
+            dec(sizeleft,tcgsize2size[location^.size]);
+            location := location^.next;
+          end;
+      end;
+
+
+    procedure tcgavr32.a_load_reg_cgpara(list: TAsmList; size: tcgsize; r: tregister; const cgpara: TCGPara);
+      var
+        pushsize : tcgsize;
+        href: treference;
+      begin
+        if use_push(cgpara) then
+          begin
+            cgpara.check_simple_location;
+            if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+              pushsize:=cgpara.location^.size
+            else
+              pushsize:=int_cgsize(cgpara.alignment);
+
+            reference_reset_base(href,cgpara.Location^.reference.index,0,cgpara.Alignment);
+            href.addressmode:=AM_PREINDEXED;
+            list.concat(setoppostfix(taicpu.op_ref_reg(A_ST,href,makeregsize(list,r,pushsize)),size2postfix(pushsize)));
+          end
+        else
+          inherited a_load_reg_cgpara(list, size, r, cgpara);
+      end;
+
+
+    procedure tcgavr32.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
+      var
+        ref: treference;
+        tmpreg: tregister;
+      begin
+        paraloc.check_simple_location;
+        paramanager.allocparaloc(list,paraloc.location);
+        case paraloc.location^.loc of
+          LOC_REGISTER,LOC_CREGISTER:
+            a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+          LOC_REFERENCE:
+            begin
+              reference_reset(ref,paraloc.alignment);
+              ref.base := paraloc.location^.reference.index;
+              ref.offset := paraloc.location^.reference.offset;
+              tmpreg := getintregister(list,OS_ADDR);
+              a_loadaddr_ref_reg(list,r,tmpreg);
+              a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+            end;
+          else
+            internalerror(2002080701);
+        end;
+      end;
+
+
+    procedure tcgavr32.a_call_name(list : TAsmList;const s : string; weak: boolean);
+      begin
+        if not weak then
+          list.concat(taicpu.op_sym(A_RCALL,current_asmdata.RefAsmSymbol(s)))
+        else
+          list.concat(taicpu.op_sym(A_RCALL,current_asmdata.WeakRefAsmSymbol(s)));
+{
+        the compiler does not properly set this flag anymore in pass 1, and
+        for now we only need it after pass 2 (I hope) (JM)
+          if not(pi_do_call in current_procinfo.flags) then
+            internalerror(2003060703);
+}
+        include(current_procinfo.flags,pi_do_call);
+      end;
+
+
+    procedure tcgavr32.a_call_reg(list : TAsmList;reg: tregister);
+      begin
+        { check not really correct: should only be used for non-Thumb cpus }
+        list.concat(taicpu.op_reg(A_ICALL, reg));
+{
+        the compiler does not properly set this flag anymore in pass 1, and
+        for now we only need it after pass 2 (I hope) (JM)
+          if not(pi_do_call in current_procinfo.flags) then
+            internalerror(2003060703);
+}
+        include(current_procinfo.flags,pi_do_call);
+      end;
+
+
+    procedure tcgavr32.a_call_ref(list : TAsmList;ref: treference);
+      begin
+        a_reg_alloc(list,NR_R12);
+        a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_R12);
+        a_call_reg(list,NR_R12);
+        a_reg_dealloc(list,NR_R12);
+        include(current_procinfo.flags,pi_do_call);
+      end;
+
+
+     procedure tcgavr32.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
+       begin
+          a_op_const_reg_reg(list,op,size,a,reg,reg);
+       end;
+
+
+     procedure tcgavr32.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+       begin
+         case op of
+           OP_NEG:
+             list.concat(taicpu.op_reg_reg_const(A_RSUB,dst,dst,0));
+           OP_NOT:
+             begin
+               a_load_reg_reg(list,size,size,src,dst);
+               list.concat(taicpu.op_reg(A_COM,dst));
+               case size of
+                 OS_8 :
+                   list.concat(taicpu.op_reg_const_coh(A_ANDL,dst,$FF));
+                 OS_16 :
+                   list.concat(taicpu.op_reg_const_coh(A_ANDL,dst,$FFFF));
+               end;
+             end
+           else
+             a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
+         end;
+       end;
+
+
+    const
+      op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
+        (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_OR,
+         A_NONE,A_NONE,A_NONE,A_SUB,A_EOR,A_NONE,A_NONE);
+
+
+    procedure tcgavr32.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
+      var
+        ovloc : tlocation;
+      begin
+        a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,ovloc);
+      end;
+
+
+    procedure tcgavr32.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+      size: tcgsize; src1, src2, dst: tregister);
+      var
+        ovloc : tlocation;
+      begin
+        a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
+      end;
+
+
+    procedure tcgavr32.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+      var
+        shift : byte;
+        tmpreg : tregister;
+        so : tshifterop;
+        l1 : longint;
+      begin
+        ovloc.loc:=LOC_VOID;
+
+        if op = OP_ADD then
+          begin
+            op := OP_SUB;
+            a := -a;
+          end;
+
+        if in_signed_bits(a,16) and (op = OP_SUB) then
+          begin
+            list.concat(taicpu.op_reg_reg_const(A_SUB,dst,src,a));
+          end
+        else if in_signed_bits(a,21) and (op = OP_SUB) then
+          begin
+            a_load_reg_reg(list,size,size,src,dst);
+            list.concat(taicpu.op_reg_const(A_SUB,dst,a));
+          end
+        else if in_signed_bits(a,8) and (op = OP_SUB) then
+          begin
+            a_load_reg_reg(list,size,size,src,dst);
+            list.concat(taicpu.op_reg_const(A_SUB,dst,a));
+          end
+        { there could be added some more sophisticated optimizations }
+        else if (op in [OP_MUL,OP_IMUL]) and (a=1) then
+          a_load_reg_reg(list,size,size,src,dst)
+        else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
+          a_load_const_reg(list,size,0,dst)
+        else if (op in [OP_IMUL]) and (a=-1) then
+          a_op_reg_reg(list,OP_NEG,size,src,dst)
+        { we do this here instead in the peephole optimizer because
+          it saves us a register }
+        else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) then
+          a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
+        else if op in [OP_SHL,OP_SHR,OP_SAR,OP_ROL,OP_ROR] then
+          begin
+            case op of
+              OP_ROR,OP_ROL:
+                internalerror(2011012001);
+              OP_SHL:
+                begin
+                  if a>32 then
+                    internalerror(200308294);
+                  a_load_reg_reg(list,size,size,src,dst);
+                  if a>0 then
+                    list.concat(taicpu.op_reg_const(A_LSL,dst,a));
+                end;
+              OP_SHR:
+                begin
+                  if a>32 then
+                    internalerror(200308294);
+                  a_load_reg_reg(list,size,size,src,dst);
+                  if a>0 then
+                    list.concat(taicpu.op_reg_const(A_LSR,dst,a));
+                end;
+              OP_SAR:
+                begin
+                  if a>32 then
+                    internalerror(200308294);
+                  a_load_reg_reg(list,size,size,src,dst);
+                  if a>0 then
+                    list.concat(taicpu.op_reg_const(A_ASR,dst,a));
+                end;
+              else
+                list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a));
+            end;
+          end
+        else
+          begin
+            tmpreg:=getintregister(list,size);
+            a_load_const_reg(list,size,a,tmpreg);
+            a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
+          end;
+        maybeadjustresult(list,op,size,dst);
+      end;
+
+
+    procedure tcgavr32.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+      var
+        so : tshifterop;
+        tmpreg,overflowreg : tregister;
+        asmop : tasmop;
+      begin
+        ovloc.loc:=LOC_VOID;
+        case op of
+          OP_NEG,OP_NOT,
+          OP_DIV,OP_IDIV,
+          OP_ROL,OP_ROR:
+            internalerror(200308281);
+          OP_SHL:
+            list.concat(taicpu.op_reg_reg_reg(A_LSL,dst,src2,src1));
+          OP_SHR:
+            list.concat(taicpu.op_reg_reg_reg(A_LSR,dst,src2,src1));
+          OP_SAR:
+            list.concat(taicpu.op_reg_reg_reg(A_ASR,dst,src2,src1));
+          OP_IMUL,
+          OP_MUL:
+            begin
+              if op=OP_IMUL then
+                asmop:=A_MULS
+              else
+                asmop:=A_MULU;
+
+              list.concat(setoppostfix(taicpu.op_reg_reg_reg(asmop,dst,src2,src1), PF_D));
+              {overflowreg:=getintregister(list,OS_64);
+              if op=OP_IMUL then
+                asmop:=A_MULS
+              else
+                asmop:=A_MULU;
+
+              list.concat(setoppostfix(taicpu.op_reg_reg_reg(asmop,overflowreg,src2,src1), PF_D));
+              a_load_reg_reg(list,size,size,overflowreg,dst);
+
+              if op=OP_IMUL then
+                begin
+                  a_op_const_reg(list,OP_SAR,OS_SINT,31,overflowreg);
+                  list.concat(taicpu.op_reg_reg(A_CP,tregister(longint(overflowreg)+1),overflowreg));
+                end
+              else
+                list.concat(taicpu.op_reg_const(A_CP,overflowreg,0));
+
+               ovloc.loc:=LOC_FLAGS;
+               ovloc.resflags:=F_NE;}
+            end;
+          else
+            list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
+        end;
+        maybeadjustresult(list,op,size,dst);
+      end;
+
+
+    function tcgavr32.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
+      var
+        tmpreg : tregister;
+        tmpref : treference;
+        l : tasmlabel;
+      begin
+        tmpreg:=NR_NO;
+
+        { Be sure to have a base register }
+        if (ref.base=NR_NO) and
+           not assigned(ref.symbol) then
+          begin
+            ref.base:=ref.index;
+            ref.index:=NR_NO;
+          end;
+
+        { absolute symbols can't be handled directly, we've to store the symbol reference
+          in the text segment and access it pc relative
+
+          For now, we assume that references where base or index equals to PC are already
+          relative, all other references are assumed to be absolute and thus they need
+          to be handled extra.
+
+          A proper solution would be to change refoptions to a set and store the information
+          if the symbol is absolute or relative there.
+        }
+
+        if (assigned(ref.symbol) and
+            not(is_pc(ref.base)) and
+            not(is_pc(ref.index))
+           ) or
+           { [#xxx] isn't a valid address operand }
+           ((ref.base=NR_NO) and (ref.index=NR_NO)) or
+           (ref.offset<-65535) or
+           (ref.offset>65535) then
+          begin
+            reference_reset(tmpref,4);
+
+            { load symbol }
+            tmpreg:=getintregister(list,OS_INT);
+            if assigned(ref.symbol) then
+              begin
+                current_asmdata.getjumplabel(l);
+                cg.a_label(current_procinfo.aktlocaldata,l);
+                tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+                current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
+
+                { load consts entry }
+                tmpref.symbol:=l;
+                tmpref.base:=NR_R15;
+                list.concat(setoppostfix(taicpu.op_reg_ref(A_LD,tmpreg,tmpref), PF_W));
+
+                { in case of LDF/STF, we got rid of the NR_R15 }
+                if is_pc(ref.base) then
+                  ref.base:=NR_NO;
+                if is_pc(ref.index) then
+                  ref.index:=NR_NO;
+              end
+            else
+              a_load_const_reg(list,OS_ADDR,ref.offset,tmpreg);
+
+            if (ref.base<>NR_NO) then
+              begin
+                if ref.index<>NR_NO then
+                  begin
+                    list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+                    ref.base:=tmpreg;
+                  end
+                else
+                  begin
+                    ref.index:=tmpreg;
+                  end;
+              end
+            else
+              ref.base:=tmpreg;
+            ref.offset:=0;
+            ref.symbol:=nil;
+          end;
+
+        if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
+          begin
+            if tmpreg<>NR_NO then
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
+            else
+              begin
+                tmpreg:=getintregister(list,OS_ADDR);
+                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
+                ref.base:=tmpreg;
+              end;
+            ref.offset:=0;
+          end;
+
+        if op in [A_LD,A_LDINS,A_LDSWP,A_LDDPC,A_LDDSP] then
+          list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix))
+        else
+          list.concat(setoppostfix(taicpu.op_ref_reg(op,ref,reg),oppostfix));
+        Result := ref;
+      end;
+
+
+    procedure tcgavr32.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
+      var
+        oppostfix:toppostfix;
+        usedtmpref: treference;
+        tmpreg : tregister;
+        dir : integer;
+      begin
+        if (TCGSize2Size[FromSize] >= TCGSize2Size[ToSize]) then
+          FromSize := ToSize;
+        oppostfix:=unsignedsize2postfix(tosize);
+        if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[tosize]) then
+          begin
+            if target_info.endian=endian_big then
+              dir:=-1
+            else
+              dir:=1;
+            case FromSize of
+              OS_16,OS_S16:
+                begin
+                  tmpreg:=getintregister(list,OS_INT);
+
+                  usedtmpref:=ref;
+                  if target_info.endian=endian_big then
+                    inc(usedtmpref.offset,1);
+
+                  usedtmpref:=a_internal_load_reg_ref(list,OS_8,OS_8,reg,usedtmpref);
+                  inc(usedtmpref.offset,dir);
+                  list.concat(taicpu.op_reg_reg_const(A_LSR,tmpreg,reg,8));
+                  a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+                end;
+              OS_32,OS_S32:
+                begin
+                  tmpreg:=getintregister(list,OS_INT);
+                  usedtmpref:=ref;
+                  if ref.alignment=2 then
+                    begin
+                      if target_info.endian=endian_big then
+                        inc(usedtmpref.offset,2);
+                      usedtmpref:=a_internal_load_reg_ref(list,OS_16,OS_16,reg,usedtmpref);
+                      list.concat(taicpu.op_reg_reg_const(A_LSR,tmpreg,reg,16));
+                      inc(usedtmpref.offset,dir*2);
+                      a_internal_load_reg_ref(list,OS_16,OS_16,tmpreg,usedtmpref);
+                    end
+                  else
+                    begin
+                      if target_info.endian=endian_big then
+                        inc(usedtmpref.offset,3);
+                      usedtmpref:=a_internal_load_reg_ref(list,OS_8,OS_8,reg,usedtmpref);
+                      list.concat(taicpu.op_reg_reg_const(A_LSR,tmpreg,reg,8));
+                      inc(usedtmpref.offset,dir);
+                      a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+                      list.concat(taicpu.op_reg_reg_const(A_LSR,tmpreg,tmpreg,8));
+                      inc(usedtmpref.offset,dir);
+                      a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+                      list.concat(taicpu.op_reg_reg_const(A_LSR,tmpreg,tmpreg,8));
+                      inc(usedtmpref.offset,dir);
+                      a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+                    end;
+                end
+              else
+                handle_load_store(list,A_ST,oppostfix,reg,ref);
+            end;
+          end
+        else
+          handle_load_store(list,A_ST,oppostfix,reg,ref);
+      end;
+
+
+    function tcgavr32.a_internal_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference):treference;
+      var
+        oppostfix:toppostfix;
+      begin
+        oppostfix:=unsignedsize2postfix(tosize);
+        result:=handle_load_store(list,A_ST,oppostfix,reg,ref);
+      end;
+
+
+    function tcgavr32.a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
+      var
+        oppostfix:toppostfix;
+      begin
+        oppostfix:=size2postfix(fromsize);
+        result:=handle_load_store(list,A_LD,oppostfix,reg,ref);
+      end;
+
+    procedure tcgavr32.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+
+      procedure do_shift(op: TAsmOp; shiftimm : byte; reg : tregister);
+        begin
+          list.concat(taicpu.op_reg_reg_const(op,reg2,reg,shiftimm));
+        end;
+
+      var
+        instr: taicpu;
+        conv_done: boolean;
+      begin
+        if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
+          internalerror(2002090901);
+
+        conv_done:=false;
+        if tosize<>fromsize then
+          begin
+            conv_done:=true;
+            if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+              fromsize:=tosize;
+            case fromsize of
+              OS_8:
+                begin
+                  a_load_reg_reg(list,OS_INT,OS_INT,reg1,reg2);
+                  list.concat(setoppostfix(taicpu.op_reg(A_CASTU, reg2), PF_B));
+                end;
+              OS_S8:
+                begin
+                  if tosize=OS_16 then
+                    begin
+                      do_shift(A_LSL,24,reg1);
+                      do_shift(A_ASR,8,reg2);
+                      do_shift(A_LSR,16,reg2);
+                    end
+                  else
+                    list.concat(taicpu.op_reg_reg_const_const(A_BFEXTS,reg2,reg1,0,8));
+                end;
+              OS_16:
+                list.concat(taicpu.op_reg_reg_const_const(A_BFEXTU,reg2,reg1,0,16));
+              OS_S16:
+                list.concat(taicpu.op_reg_reg_const_const(A_BFEXTS,reg2,reg1,0,16));
+              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;
+
+
+    {  comparison operations }
+    procedure tcgavr32.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+      l : tasmlabel);
+      var
+        tmpreg : tregister;
+        b : byte;
+      begin
+        if in_signed_bits(a,21) and
+           (size in [OS_32, OS_S32]) then
+          list.concat(taicpu.op_reg_const(A_CP,reg,a))
+        else
+          begin
+            tmpreg:=getintregister(list,size);
+            a_load_const_reg(list,size,a,tmpreg);
+            list.concat(setoppostfix(taicpu.op_reg_reg(A_CP,reg,tmpreg), unsignedsize2postfix(size)));
+          end;
+        a_jmp_cond(list,cmp_op,l);
+      end;
+
+
+    procedure tcgavr32.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+      begin
+        list.concat(setoppostfix(taicpu.op_reg_reg(A_CP,reg2,reg1), unsignedsize2postfix(size)));
+        a_jmp_cond(list,cmp_op,l);
+      end;
+
+
+    procedure tcgavr32.a_jmp_name(list : TAsmList;const s : string);
+      var
+        ai : taicpu;
+      begin
+        ai:=taicpu.op_sym(A_BR,current_asmdata.RefAsmSymbol(s));
+        ai.is_jmp:=true;
+        list.concat(ai);
+      end;
+
+
+    procedure tcgavr32.a_jmp_always(list : TAsmList;l: tasmlabel);
+      var
+        ai : taicpu;
+      begin
+        ai:=taicpu.op_sym(A_RJMP,l);
+        ai.is_jmp:=true;
+        list.concat(ai);
+      end;
+
+
+    procedure tcgavr32.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+      var
+        ai : taicpu;
+      begin
+        ai:=setcondition(taicpu.op_sym(A_BR,l),flags_to_cond(f));
+        ai.is_jmp:=true;
+        list.concat(ai);
+      end;
+
+
+    procedure tcgavr32.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
+      begin
+        list.Concat(setcondition(taicpu.op_reg(A_SR,reg), flags_to_cond(f)));
+      end;
+
+
+    procedure tcgavr32.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+      var
+         ref : treference;
+         r : byte;
+         regs : tcpuregisterset;
+         stackcount : pint;
+      begin
+        if not(nostackframe) then
+          begin
+            a_reg_alloc(list,NR_STACK_POINTER_REG);
+
+            { save int registers }
+            reference_reset(ref,4);
+            ref.base:=NR_STACK_POINTER_REG;
+            ref.addressmode:=AM_PREINDEXED;
+            regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+            Exclude(regs,RS_STACK_POINTER_REG);
+
+            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+              regs:=regs+[RS_FRAME_POINTER_REG,RS_R14]
+            else
+              if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
+                include(regs,RS_R14);
+
+            if regs<>[] then
+              list.concat(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,regs));
+
+            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+              begin
+                stackcount:=0;
+                for r:=RS_R0 to RS_R15 do
+                  if (r in regs) then
+                    inc(stackcount,4);
+
+                dec(stackcount,4); // Point at LR
+                if stackcount > 0 then
+                  list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,-stackcount));
+              end;
+          end
+        else
+          begin
+            reference_reset(ref,4);
+            ref.base:=NR_STACK_POINTER_REG;
+            ref.addressmode:=AM_PREINDEXED;
+            regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+            if pi_do_call in current_procinfo.flags then
+              Include(regs,RS_R14); // Link register
+
+            if regs <> [] then
+              list.concat(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,regs));
+          end;
+      end;
+
+
+    procedure tcgavr32.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+      var
+         ref : treference;
+         LocalSize : longint;
+         r,
+         shift : byte;
+         regs : tcpuregisterset;
+         stackmisalignment: pint;
+      begin
+        if not(nostackframe) then
+          begin
+            stackmisalignment:=0;
+
+            regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)        ;
+            if (pi_do_call in current_procinfo.flags) or (regs<>[]) then
+              begin
+                exclude(regs,RS_R14);
+                include(regs,RS_R15);
+              end;
+            { restore saved stack pointer to SP (R13) and saved lr to PC (R15).
+              The saved PC came after that but is discarded, since we restore
+              the stack pointer }
+            if (current_procinfo.framepointer<>NR_STACK_POINTER_REG) then
+              regs:=regs+[RS_FRAME_POINTER_REG,RS_R15];
+
+            Exclude(regs,RS_STACK_POINTER_REG);
+
+            if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+              begin
+                if regs=[] then
+                  list.concat(taicpu.op_reg(A_RET,NR_FUNCTION_RETURN_REG))
+                else
+                  begin
+                    reference_reset(ref,4);
+                    ref.base:=NR_STACK_POINTER_REG;
+                    ref.addressmode:=AM_POSTINDEXED;
+                    list.concat(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs));
+                  end;
+              end
+            else
+              begin
+                { restore int registers and return }
+                reference_reset(ref,4);
+                ref.base:=NR_STACK_POINTER_REG;
+                ref.addressmode:=AM_POSTINDEXED;
+                list.concat(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs));
+              end;
+          end
+        else
+          begin
+            reference_reset(ref,4);
+            ref.base:=NR_STACK_POINTER_REG;
+            ref.addressmode:=AM_POSTINDEXED;
+            regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+            if (pi_do_call in current_procinfo.flags) or
+               (regs <> []) then
+              Include(regs,RS_R15); // PC register
+
+            if regs <> [] then
+              list.concat(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs))
+            else
+              list.concat(taicpu.op_reg(A_RET,NR_FUNCTION_RETURN_REG));
+          end;
+      end;
+
+
+    procedure tcgavr32.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+      var
+        b : byte;
+        tmpref : treference;
+        instr : taicpu;
+      begin
+        if ref.addressmode<>AM_OFFSET then
+          internalerror(200309071);
+        tmpref:=ref;
+        { Be sure to have a base register }
+        if (tmpref.base=NR_NO) then
+          begin
+            tmpref.base:=tmpref.index;
+            tmpref.index:=NR_NO;
+          end;
+
+        if assigned(tmpref.symbol) or
+           not in_signed_bits(tmpref.offset,16) then
+          fixref(list,tmpref);
+
+        { expect a base here if there is an index }
+        if (tmpref.base=NR_NO) and (tmpref.index<>NR_NO) then
+          internalerror(200312022);
+
+        if tmpref.index<>NR_NO then
+          begin
+            a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
+            if tmpref.offset<>0 then
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
+          end
+        else
+          begin
+            if tmpref.base=NR_NO then
+              a_load_const_reg(list,OS_ADDR,tmpref.offset,r)
+            else
+              if tmpref.offset<>0 then
+                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
+              else
+                begin
+                  instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
+                  list.concat(instr);
+                  add_move_instruction(instr);
+                end;
+          end;
+      end;
+
+
+    procedure tcgavr32.fixref(list : TAsmList;var ref : treference);
+      var
+        tmpreg : tregister;
+        tmpref : treference;
+        l : tasmlabel;
+      begin
+        { absolute symbols can't be handled directly, we've to store the symbol reference
+          in the text segment and access it pc relative
+
+          For now, we assume that references where base or index equals to PC are already
+          relative, all other references are assumed to be absolute and thus they need
+          to be handled extra.
+
+          A proper solution would be to change refoptions to a set and store the information
+          if the symbol is absolute or relative there.
+        }
+        { create consts entry }
+        reference_reset(tmpref,4);
+        current_asmdata.getjumplabel(l);
+        cg.a_label(current_procinfo.aktlocaldata,l);
+        tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+        if assigned(ref.symbol) then
+          current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
+        else
+          current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
+
+        { load consts entry }
+        tmpreg:=getintregister(list,OS_INT);
+        tmpref.symbol:=l;
+        tmpref.base:=NR_PC;
+        list.concat(setoppostfix(taicpu.op_reg_ref(A_LD,tmpreg,tmpref),size2postfix(OS_INT)));
+
+        if (ref.base<>NR_NO) then
+          begin
+            if ref.index<>NR_NO then
+              begin
+                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+                ref.base:=tmpreg;
+              end
+            else
+              if ref.base<>NR_PC then
+                  ref.index:=tmpreg
+                else
+                  ref.base:=tmpreg;
+          end
+        else
+          ref.base:=tmpreg;
+        ref.offset:=0;
+        ref.symbol:=nil;
+      end;
+
+
+    procedure tcgavr32.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+      var
+        paraloc1,paraloc2,paraloc3 : TCGPara;
+      begin
+        paraloc1.init;
+        paraloc2.init;
+        paraloc3.init;
+        paramanager.getintparaloc(pocall_default,1,paraloc1);
+        paramanager.getintparaloc(pocall_default,2,paraloc2);
+        paramanager.getintparaloc(pocall_default,3,paraloc3);
+        a_load_const_cgpara(list,OS_INT,len,paraloc3);
+        a_loadaddr_ref_cgpara(list,dest,paraloc2);
+        a_loadaddr_ref_cgpara(list,source,paraloc1);
+        paramanager.freecgpara(list,paraloc3);
+        paramanager.freecgpara(list,paraloc2);
+        paramanager.freecgpara(list,paraloc1);
+        alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+        a_call_name(list,'FPC_MOVE',false);
+        dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+        dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        paraloc3.done;
+        paraloc2.done;
+        paraloc1.done;
+      end;
+
+
+    procedure tcgavr32.g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : tcgint;aligned : boolean);
+      const
+        maxtmpreg=10;{roozbeh: can be reduced to 8 or lower if might conflick with reserved ones,also +2 is used becouse of regs required for referencing}
+
+      var
+        srcref,dstref,usedtmpref,usedtmpref2:treference;
+        srcreg,destreg,countreg,r,tmpreg:tregister;
+        helpsize:tcgint;
+        copysize:byte;
+        cgsize:Tcgsize;
+        tmpregisters:array[1..maxtmpreg] of tregister;
+        tmpregi,tmpregi2:byte;
+
+      { will never be called with count<=4 }
+      procedure genloop(count : aword;size : byte);
+        const
+          size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
+        var
+          l : tasmlabel;
+        begin
+          current_asmdata.getjumplabel(l);
+          if count<size then size:=1;
+          a_load_const_reg(list,OS_INT,count div size,countreg);
+          cg.a_label(list,l);
+          srcref.addressmode:=AM_POSTINDEXED;
+          dstref.addressmode:=AM_POSTINDEXED;
+          srcref.offset:=size;
+          dstref.offset:=size;
+          r:=getintregister(list,size2opsize[size]);
+          a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
+          list.concat(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1));
+          a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
+          a_jmp_flags(list,F_NE,l);
+          srcref.offset:=1;
+          dstref.offset:=1;
+          case count mod size of
+            1:
+              begin
+                a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+              end;
+            2:
+              if aligned then
+                begin
+                  a_load_ref_reg(list,OS_16,OS_16,srcref,r);
+                  a_load_reg_ref(list,OS_16,OS_16,r,dstref);
+                end
+              else
+                begin
+                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                end;
+            3:
+              if aligned then
+                begin
+                  srcref.offset:=2;
+                  dstref.offset:=2;
+                  a_load_ref_reg(list,OS_16,OS_16,srcref,r);
+                  a_load_reg_ref(list,OS_16,OS_16,r,dstref);
+                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                end
+              else
+                begin
+                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                end;
+          end;
+          { keep the registers alive }
+          list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+          list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
+          list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
+        end;
+
+      begin
+        if len=0 then
+          exit;
+        helpsize:=12+maxtmpreg*4;//52 with maxtmpreg=10
+        dstref:=dest;
+        srcref:=source;
+        if cs_opt_size in current_settings.optimizerswitches then
+          helpsize:=8;
+        if (len<=helpsize) and aligned then
+          begin
+            tmpregi:=0;
+            srcreg:=getintregister(list,OS_ADDR);
+
+            { explicit pc relative addressing, could be
+              e.g. a floating point constant }
+            if source.base=NR_PC then
+              begin
+                { ... then we don't need a loadaddr }
+                srcref:=source;
+              end
+            else
+              begin
+                a_loadaddr_ref_reg(list,source,srcreg);
+                reference_reset_base(srcref,srcreg,0,source.alignment);
+              end;
+
+            while (len div 4 <> 0) and (tmpregi<maxtmpreg) do
+              begin
+                inc(tmpregi);
+                tmpregisters[tmpregi]:=getintregister(list,OS_32);
+                a_load_ref_reg(list,OS_32,OS_32,srcref,tmpregisters[tmpregi]);
+                inc(srcref.offset,4);
+                dec(len,4);
+              end;
+
+            destreg:=getintregister(list,OS_ADDR);
+            a_loadaddr_ref_reg(list,dest,destreg);
+            reference_reset_base(dstref,destreg,0,dest.alignment);
+            tmpregi2:=1;
+            while (tmpregi2<=tmpregi) do
+              begin
+                a_load_reg_ref(list,OS_32,OS_32,tmpregisters[tmpregi2],dstref);
+                inc(dstref.offset,4);
+                inc(tmpregi2);
+              end;
+
+            copysize:=4;
+            cgsize:=OS_32;
+            while len<>0 do
+              begin
+                if len<2 then
+                  begin
+                    copysize:=1;
+                    cgsize:=OS_8;
+                  end
+                else if len<4 then
+                  begin
+                    copysize:=2;
+                    cgsize:=OS_16;
+                  end;
+                dec(len,copysize);
+                r:=getintregister(list,cgsize);
+                a_load_ref_reg(list,cgsize,cgsize,srcref,r);
+                a_load_reg_ref(list,cgsize,cgsize,r,dstref);
+                inc(srcref.offset,copysize);
+                inc(dstref.offset,copysize);
+              end;{end of while}
+          end
+        else
+          begin
+            cgsize:=OS_32;
+            if (len<=4) then{len<=4 and not aligned}
+              begin
+                r:=getintregister(list,cgsize);
+                usedtmpref:=a_internal_load_ref_reg(list,OS_8,OS_8,srcref,r);
+                if Len=1 then
+                  a_load_reg_ref(list,OS_8,OS_8,r,dstref)
+                else
+                  begin
+                    tmpreg:=getintregister(list,cgsize);
+                    usedtmpref2:=a_internal_load_reg_ref(list,OS_8,OS_8,r,dstref);
+                    inc(usedtmpref.offset,1);
+                    a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+                    inc(usedtmpref2.offset,1);
+                    a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
+                    if len>2 then
+                      begin
+                        inc(usedtmpref.offset,1);
+                        a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+                        inc(usedtmpref2.offset,1);
+                        a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
+                        if len>3 then
+                          begin
+                            inc(usedtmpref.offset,1);
+                            a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+                            inc(usedtmpref2.offset,1);
+                            a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
+                          end;
+                        end;
+                      end;
+            end{end of if len<=4}
+            else
+              begin{unaligned & 4<len<helpsize **or** aligned/unaligned & len>helpsize}
+                destreg:=getintregister(list,OS_ADDR);
+                a_loadaddr_ref_reg(list,dest,destreg);
+                reference_reset_base(dstref,destreg,0,dest.alignment);
+
+                srcreg:=getintregister(list,OS_ADDR);
+                a_loadaddr_ref_reg(list,source,srcreg);
+                reference_reset_base(srcref,srcreg,0,source.alignment);
+
+                countreg:=getintregister(list,OS_32);
+
+//            if cs_opt_size in current_settings.optimizerswitches  then
+                { roozbeh : it seems loading 1 byte is faster becouse of caching/fetching(?) }
+                {if aligned then
+                genloop(len,4)
+                else}
+                genloop(len,1);
+            end;
+          end;
+    end;
+
+    procedure tcgavr32.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);
+      begin
+        g_concatcopy_internal(list,source,dest,len,false);
+      end;
+
+
+    procedure tcgavr32.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
+      begin
+        if (source.alignment in [1..3]) or
+          (dest.alignment in [1..3]) then
+          g_concatcopy_internal(list,source,dest,len,false)
+        else
+          g_concatcopy_internal(list,source,dest,len,true);
+      end;
+
+
+    procedure tcgavr32.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
+      var
+        ovloc : tlocation;
+      begin
+        ovloc.loc:=LOC_VOID;
+        g_overflowCheck_loc(list,l,def,ovloc);
+      end;
+
+
+    procedure tcgavr32.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
+      var
+        hl : tasmlabel;
+        ai:TAiCpu;
+        hflags : tresflags;
+      begin
+        if not(cs_check_overflow in current_settings.localswitches) then
+          exit;
+        current_asmdata.getjumplabel(hl);
+        case ovloc.loc of
+          LOC_VOID:
+            begin
+              ai:=taicpu.op_sym(A_BR,hl);
+              ai.is_jmp:=true;
+
+              if not((def.typ=pointerdef) or
+                    ((def.typ=orddef) and
+                     (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,pasbool]))) then
+                 ai.SetCondition(C_VC)
+              else
+                if TAiCpu(List.Last).opcode in [A_RSUB,A_SBC,A_SCR,A_SUB] then
+                  ai.SetCondition(C_CS)
+                else
+                  ai.SetCondition(C_CC);
+
+              list.concat(ai);
+            end;
+          LOC_FLAGS:
+            begin
+              hflags:=ovloc.resflags;
+              inverse_flags(hflags);
+              cg.a_jmp_flags(list,hflags,hl);
+            end;
+          else
+            internalerror(200409281);
+        end;
+
+        a_call_name(list,'FPC_OVERFLOW',false);
+        a_label(list,hl);
+      end;
+
+
+    procedure tcgavr32.g_save_registers(list : TAsmList);
+      begin
+        { this work is done in g_proc_entry }
+      end;
+
+
+    procedure tcgavr32.g_restore_registers(list : TAsmList);
+      begin
+        { this work is done in g_proc_exit }
+      end;
+
+
+    procedure tcgavr32.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+      var
+        ai : taicpu;
+      begin
+        ai:=Taicpu.Op_sym(A_BR,l);
+        ai.SetCondition(OpCmp2AsmCond[cond]);
+        ai.is_jmp:=true;
+        list.concat(ai);
+      end;
+
+
+    procedure tcgavr32.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
+      var
+        hsym : tsym;
+        href : treference;
+        paraloc : Pcgparalocation;
+        shift : byte;
+      begin
+        { calculate the parameter info for the procdef }
+        procdef.init_paraloc_info(callerside);
+        hsym:=tsym(procdef.parast.Find('self'));
+        if not(assigned(hsym) and
+          (hsym.typ=paravarsym)) then
+          internalerror(200305251);
+        paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+        while paraloc<>nil do
+          with paraloc^ do
+            begin
+              case loc of
+                LOC_REGISTER:
+                  begin
+                    if in_signed_bits(ioffset, 21) then
+                      a_op_const_reg(list,OP_SUB,size,ioffset,register)
+                    else
+                      begin
+                        a_load_const_reg(list,OS_ADDR,ioffset,NR_R12);
+                        a_op_reg_reg(list,OP_SUB,size,NR_R12,register);
+                      end;
+                  end;
+                LOC_REFERENCE:
+                  begin
+                    { offset in the wrapper needs to be adjusted for the stored
+                      return address }
+                    reference_reset_base(href,reference.index,reference.offset+sizeof(aint),sizeof(pint));
+                    if in_signed_bits(ioffset,21) then
+                      a_op_const_ref(list,OP_SUB,size,ioffset,href)
+                    else
+                      begin
+                        a_load_const_reg(list,OS_ADDR,ioffset,NR_R12);
+                        a_op_reg_ref(list,OP_SUB,size,NR_R12,href);
+                      end;
+                  end
+                else
+                  internalerror(200309189);
+              end;
+              paraloc:=next;
+            end;
+      end;
+
+    procedure tcgavr32.g_stackpointer_alloc(list: TAsmList; size: longint);
+      begin
+        internalerror(200807237);
+      end;
+
+
+    procedure tcgavr32.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+      procedure loadvmttor12;
+        var
+          href : treference;
+        begin
+          reference_reset_base(href,NR_R0,0,sizeof(pint));
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+        end;
+
+
+      procedure op_onr12methodaddr;
+        var
+          href : treference;
+        begin
+          if (procdef.extnumber=$ffff) then
+            Internalerror(200006139);
+          { call/jmp  vmtoffs(%eax) ; method offs }
+          reference_reset_base(href,NR_R12,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+          list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
+        end;
+
+      var
+        make_global : boolean;
+      begin
+        if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+          Internalerror(200006137);
+        if not assigned(procdef.struct) or
+           (procdef.procoptions*[po_classmethod, po_staticmethod,
+             po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+          Internalerror(200006138);
+        if procdef.owner.symtabletype<>ObjectSymtable then
+          Internalerror(200109191);
+
+        make_global:=false;
+        if (not current_module.is_unit) or
+           create_smartlink or
+           (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+          make_global:=true;
+
+        if make_global then
+          list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+        else
+          list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+        { the wrapper might need aktlocaldata for the additional data to
+          load the constant }
+        current_procinfo:=cprocinfo.create(nil);
+
+        { set param1 interface to self  }
+        g_adjust_self_value(list,procdef,ioffset);
+
+        { case 4 }
+        if po_virtualmethod in procdef.procoptions then
+          begin
+            loadvmttor12;
+            op_onr12methodaddr;
+          end
+        { case 0 }
+        else
+          list.concat(taicpu.op_sym(A_BR,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+        list.concatlist(current_procinfo.aktlocaldata);
+
+        current_procinfo.Free;
+        current_procinfo:=nil;
+
+        list.concat(Tai_symbol_end.Createname(labelname));
+      end;
+
+
+    procedure tcgavr32.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+      const
+        overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+      begin
+        if (op in overflowops) and
+           (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+          a_load_reg_reg(list,OS_32,size,dst,dst);
+      end;
+
+
+    procedure tcg64favr32.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+      begin
+        case op of
+          OP_NEG:
+            begin
+              list.concat(taicpu.op_reg_reg_const(A_RSUB,regdst.reglo,regsrc.reglo,0));
+              list.concat(taicpu.op_reg(A_ACR, regdst.reghi));
+              list.concat(taicpu.op_reg_reg_const(A_RSUB,regdst.reghi,regsrc.reghi,0));
+            end;
+          OP_NOT:
+            begin
+              cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
+              cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
+            end;
+          else
+            a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
+        end;
+      end;
+
+
+    procedure tcg64favr32.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+      begin
+        a_op64_const_reg_reg(list,op,size,value,reg,reg);
+      end;
+
+
+    procedure tcg64favr32.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
+      var
+        ovloc : tlocation;
+      begin
+        a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc);
+      end;
+
+
+    procedure tcg64favr32.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+      var
+        ovloc : tlocation;
+      begin
+        a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc);
+      end;
+
+
+    procedure tcg64favr32.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+      var
+        tmpreg : tregister;
+        b : byte;
+      begin
+        ovloc.loc:=LOC_VOID;
+        case op of
+          OP_NEG,
+          OP_NOT :
+            internalerror(200306017);
+        end;
+          begin
+            case op of
+              OP_AND,OP_OR,OP_XOR:
+                begin
+                  cg.a_op_const_reg_reg(list,op,OS_32,aint(lo(value)),regsrc.reglo,regdst.reglo);
+                  cg.a_op_const_reg_reg(list,op,OS_32,aint(hi(value)),regsrc.reghi,regdst.reghi);
+                end;
+              OP_ADD:
+                begin
+                    begin
+                      tmpreg:=cg.getintregister(list,OS_32);
+                      cg.a_load_const_reg(list,OS_32,aint(lo(value)),tmpreg);
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg));
+                    end;
+
+                    begin
+                      tmpreg:=cg.getintregister(list,OS_32);
+                      cg.a_load_const_reg(list,OS_32,aint(hi(value)),tmpreg);
+                      list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
+                    end;
+                end;
+              OP_SUB:
+                begin
+                    begin
+                      tmpreg:=cg.getintregister(list,OS_32);
+                      cg.a_load_const_reg(list,OS_32,aint(lo(value)),tmpreg);
+                      list.concat(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg));
+                    end;
+
+                    begin
+                      tmpreg:=cg.getintregister(list,OS_32);
+                      cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+                      list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
+                    end;
+                end;
+            else
+              internalerror(2003083101);
+          end;
+        end;
+      end;
+
+
+    procedure tcg64favr32.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+      begin
+        ovloc.loc:=LOC_VOID;
+        case op of
+          OP_NEG,
+          OP_NOT :
+            internalerror(200306017);
+        end;
+          begin
+            case op of
+              OP_AND,OP_OR,OP_XOR:
+                begin
+                  cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+                  cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
+                end;
+              OP_ADD:
+                begin
+                  list.concat(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo));
+                  list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+                end;
+              OP_SUB:
+                begin
+                  list.concat(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo));
+                  list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
+                end;
+              else
+                internalerror(2003083101);
+            end;
+          end;
+      end;
+
+
+    procedure create_codegen;
+      begin
+        cg:=tcgavr32.create;
+        cg64:=tcg64favr32.create;
+
+        casmoptimizer:=TCpuAsmOptimizer;
+      end;
+
+end.

+ 532 - 0
compiler/avr32/cpubase.pas

@@ -0,0 +1,532 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+    Contains the base types for the AVR32
+
+    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.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+   enumerations of registers, opcodes, sizes, and other
+   such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      cutils,cclasses,
+      globtype,globals,
+      cpuinfo,
+      aasmbase,
+      cgbase
+      ;
+
+
+{*****************************************************************************
+                                Assembler Opcodes
+*****************************************************************************}
+
+    type
+      TAsmOp= {$i avr32op.inc}
+
+      { This should define the array of instructions as string }
+      op2strtable=array[tasmop] of string[11];
+
+    const
+      { First value of opcode enumeration }
+      firstop = low(tasmop);
+      { Last value of opcode enumeration  }
+      lastop  = high(tasmop);
+
+{*****************************************************************************
+                                  Registers
+*****************************************************************************}
+
+    type
+      { Number of registers used for indexing in tables }
+      tregisterindex=0..{$i ravr32nor.inc}-1;
+
+    const
+      { Available Superregisters }
+      {$i ravr32sup.inc}
+
+      RS_PC = RS_R15;
+
+      { No Subregisters }
+      R_SUBWHOLE = R_SUBNONE;
+
+      { Available Registers }
+      {$i ravr32con.inc}
+
+      { aliases }
+      NR_PC = NR_R15;
+
+      { Integer Super registers first and last }
+      first_int_supreg = RS_R0;
+      first_int_imreg = $10;
+
+      { Float Super register first and last }
+      first_fpu_supreg    = RS_NO;
+      first_fpu_imreg     = $0;
+
+      { MM Super register first and last }
+      first_mm_supreg    = RS_NO;
+      first_mm_imreg     = $0;
+
+{ TODO: Calculate bsstart}
+      regnumber_count_bsstart = 64;
+
+      regnumber_table : array[tregisterindex] of tregister = (
+        {$i ravr32num.inc}
+      );
+
+      regstabs_table : array[tregisterindex] of shortint = (
+        {$i ravr32sta.inc}
+      );
+
+      regdwarf_table : array[tregisterindex] of shortint = (
+        {$i ravr32dwa.inc}
+      );
+      { registers which may be destroyed by calls }
+      VOLATILE_INTREGISTERS = [RS_R8,RS_R9,RS_R10,RS_R11,RS_R12];
+      VOLATILE_FPUREGISTERS = [];
+      VOLATILE_MMREGISTERS =  [];
+
+    type
+      totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+                          Instruction post fixes
+*****************************************************************************}
+    type
+      { AVR32 instructions load/store and arithmetic instructions
+        can have several instruction post fixes which are collected
+        in this enumeration
+      }
+      TOpPostfix = (PF_None,
+        { update condition flags
+          or floating point single }
+        PF_T,PF_U,PF_L,PF_B,
+        PF_S,PF_D,PF_W,PF_H,
+        PF_UB,PF_UH,
+        PF_SB,PF_SH
+      );
+
+      TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
+
+    const
+      oppostfix2str : array[TOpPostfix] of string[3] = ('',
+        't','u','l','b',
+        's','d','w','h',
+        'ub','uh',
+        'sb','sh');
+
+      roundingmode2str : array[TRoundingMode] of string[1] = ('',
+        'p','m','z');
+
+{*****************************************************************************
+                                Conditions
+*****************************************************************************}
+
+    type
+      TAsmCond=(C_None,
+        C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+        C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
+      );
+
+    const
+      cond2str : array[TAsmCond] of string[2]=('',
+        'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
+        'ge','lt','gt','le','al','nv'
+      );
+
+      uppercond2str : array[TAsmCond] of string[2]=('',
+        'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
+        'GE','LT','GT','LE','AL','NV'
+      );
+
+{*****************************************************************************
+                                   Flags
+*****************************************************************************}
+
+    type
+      TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
+        F_GE,F_LT,F_GT,F_LE);
+
+{*****************************************************************************
+                                Operands
+*****************************************************************************}
+
+      taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
+      tshiftmode = (SM_None,SM_LSL,SM_LSR);
+
+      tupdatereg = (UR_None,UR_Update);
+
+      pshifterop = ^tshifterop;
+
+      tshifterop = record
+        shiftmode : tshiftmode;
+        shiftimm : byte;
+      end;
+
+      tregisterselector = (RS_None,RS_B,RS_L,RS_U,RS_T);
+
+{*****************************************************************************
+                                 Constants
+*****************************************************************************}
+
+    const
+      max_operands = 4;
+
+      {# Constant defining possibly all registers which might require saving }
+      ALL_OTHERREGISTERS = [];
+
+      general_superregisters = [RS_R0..RS_PC];
+
+      {# Table of registers which can be allocated by the code generator
+         internally, when generating the code.
+      }
+      { legend:                                                                }
+      { xxxregs = set of all possibly used registers of that type in the code  }
+      {           generator                                                    }
+      { usableregsxxx = set of all 32bit components of registers that can be   }
+      {           possible allocated to a regvar or using getregisterxxx (this }
+      {           excludes registers which can be only used for parameter      }
+      {           passing on ABI's that define this)                           }
+      { c_countusableregsxxx = amount of registers in the usableregsxxx set    }
+
+      maxintregs = 15;
+      { to determine how many registers to use for regvars }
+      maxintscratchregs = 3;
+      usableregsint = [RS_R0..RS_R10,RS_R12];
+      c_countusableregsint = 12;
+
+      maxfpuregs = 0;
+      fpuregs = [];
+      usableregsfpu = [];
+      c_countusableregsfpu = 0;
+
+      mmregs = [];
+      usableregsmm = [];
+      c_countusableregsmm  = 0;
+
+      maxaddrregs = 0;
+      addrregs    = [];
+      usableregsaddr = [];
+      c_countusableregsaddr = 0;
+
+{*****************************************************************************
+                                Operand Sizes
+*****************************************************************************}
+
+    type
+      topsize = (S_NO,
+        S_B,S_W,S_L,S_BW,S_BL,S_WL,
+        S_IS,S_IL,S_IQ,
+        S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+      );
+
+{*****************************************************************************
+                                 Constants
+*****************************************************************************}
+
+    const
+      firstsaveintreg = RS_R0;
+      lastsaveintreg  = RS_R7;
+      firstsavefpureg = RS_NO;
+      lastsavefpureg  = RS_NO;
+      firstsavemmreg  = RS_NO;
+      lastsavemmreg   = RS_NO;
+
+      maxvarregs = 7;
+      varregs : Array [1..maxvarregs] of tsuperregister =
+                (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+{*****************************************************************************
+                          Default generic sizes
+*****************************************************************************}
+
+      { Defines the default address size for a processor, }
+      OS_ADDR = OS_32;
+      { the natural int size for a processor,             }
+      OS_INT = OS_32;
+      OS_SINT = OS_S32;
+      { the maximum float size for a processor,           }
+      OS_FLOAT = OS_F64;
+      { the size of a vector register for a processor     }
+      OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+                          Generic Register names
+*****************************************************************************}
+
+      { Stack pointer register }
+      NR_STACK_POINTER_REG = NR_R13;
+      RS_STACK_POINTER_REG = RS_R13;
+      { Frame pointer register }
+      RS_FRAME_POINTER_REG = RS_R7;
+      NR_FRAME_POINTER_REG = NR_R7;
+      { 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
+      }
+      NR_PIC_OFFSET_REG = NR_R9;
+      { Results are returned in this register (32-bit values) }
+      NR_FUNCTION_RETURN_REG = NR_R12;
+      RS_FUNCTION_RETURN_REG = RS_R12;
+      { The value returned from a function is available in this register }
+      NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+      RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+
+      NR_FPU_RESULT_REG = NR_NO;
+
+      NR_MM_RESULT_REG  = NR_NO;
+
+      NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
+
+      { Offset where the parent framepointer is pushed }
+      PARENT_FRAMEPOINTER_OFFSET = 0;
+
+      { Low part of 64bit return value }
+      NR_FUNCTION_RESULT64_LOW_REG = NR_R10;
+      RS_FUNCTION_RESULT64_LOW_REG = RS_R10;
+      { High part of 64bit return value }
+      NR_FUNCTION_RESULT64_HIGH_REG = NR_R11;
+      RS_FUNCTION_RESULT64_HIGH_REG = RS_R11;
+
+{*****************************************************************************
+                       GCC /ABI linking information
+*****************************************************************************}
+
+    const
+      { Registers which must be saved when calling a routine declared as
+        cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+        saved should be the ones as defined in the target ABI and / or GCC.
+
+        This value can be deduced from the CALLED_USED_REGISTERS array in the
+        GCC source.
+      }
+      saved_standard_registers : array[0..7] of tsuperregister =
+        (RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7);
+
+      { this is only for the generic code which is not used for this architecture }
+      saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+      { Required parameter alignment when calling a routine declared as
+        stdcall and cdecl. The alignment value should be the one defined
+        by GCC or the target ABI.
+
+        The value of this constant is equal to the constant
+        PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+      }
+      std_param_align = 4;
+
+
+{*****************************************************************************
+                                  Helpers
+*****************************************************************************}
+
+    { Returns the tcgsize corresponding with the size of reg.}
+    function reg_cgsize(const reg: tregister) : tcgsize;
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+    function is_calljmp(o:tasmop):boolean;
+    procedure inverse_flags(var f: TResFlags);
+    function flags_to_cond(const f: TResFlags) : TAsmCond;
+    function findreg_by_number(r:Tregister):tregisterindex;
+    function std_regnum_search(const s:string):Tregister;
+    function std_regname(r:Tregister):string;
+
+    function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+    function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+
+    procedure shifterop_reset(var so : tshifterop);
+    function is_pc(const r : tregister) : boolean;
+
+    function in_signed_bits(a : aint; bits : byte): boolean;
+    function dwarf_reg(r:tregister):shortint;
+
+  implementation
+
+    uses
+      systems,rgBase,verbose;
+
+
+    const
+      std_regname_table : array[tregisterindex] of string[7] = (
+        {$i ravr32std.inc}
+      );
+
+      regnumber_index : array[tregisterindex] of tregisterindex = (
+        {$i ravr32rni.inc}
+      );
+
+      std_regname_index : array[tregisterindex] of tregisterindex = (
+        {$i ravr32sri.inc}
+      );
+
+
+    function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+      begin
+        case regtype of
+          R_MMREGISTER:
+            begin
+              case s of
+                OS_F32:
+                  cgsize2subreg:=R_SUBFS;
+                OS_F64:
+                  cgsize2subreg:=R_SUBFD;
+                else
+                  internalerror(2009112701);
+              end;
+            end;
+          else
+            cgsize2subreg:=R_SUBWHOLE;
+        end;
+      end;
+
+
+    function reg_cgsize(const reg: tregister): tcgsize;
+      begin
+        case getregtype(reg) of
+          R_INTREGISTER :
+            reg_cgsize:=OS_32;
+          R_FPUREGISTER :
+            reg_cgsize:=OS_F80;
+          R_MMREGISTER :
+            begin
+              case getsubreg(reg) of
+                R_SUBFD,
+                R_SUBWHOLE:
+                  result:=OS_F64;
+                R_SUBFS:
+                  result:=OS_F32;
+                else
+                  internalerror(2009112903);
+              end;
+            end;
+          else
+            internalerror(200303181);
+          end;
+        end;
+
+
+    function is_calljmp(o:tasmop):boolean;
+      begin
+        { This isn't 100% perfect because the avr32 allows jumps also by writing to PC=R15.
+          To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
+        is_calljmp:= o in [A_BR,A_RJMP,A_ACALL,A_ICALL,A_MCALL,A_RCALL,A_SCALL];
+      end;
+
+
+    procedure inverse_flags(var f: TResFlags);
+      const
+        inv_flags: array[TResFlags] of TResFlags =
+          (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
+          F_LT,F_GE,F_LE,F_GT);
+      begin
+        f:=inv_flags[f];
+      end;
+
+
+    function flags_to_cond(const f: TResFlags) : TAsmCond;
+      const
+        flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
+          (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+           C_GE,C_LT,C_GT,C_LE);
+      begin
+        if f>high(flag_2_cond) then
+          internalerror(200112301);
+        result:=flag_2_cond[f];
+      end;
+
+
+    function findreg_by_number(r:Tregister):tregisterindex;
+      begin
+        result:=rgBase.findreg_by_number_table(r,regnumber_index);
+      end;
+
+
+    function std_regnum_search(const s:string):Tregister;
+      begin
+        result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+      end;
+
+
+    function std_regname(r:Tregister):string;
+      var
+        p : tregisterindex;
+      begin
+        p:=findreg_by_number_table(r,regnumber_index);
+        if p<>0 then
+          result:=std_regname_table[p]
+        else
+          result:=generic_regname(r);
+      end;
+
+
+    procedure shifterop_reset(var so : tshifterop);
+      begin
+        FillChar(so,sizeof(so),0);
+      end;
+
+
+    function is_pc(const r : tregister) : boolean;
+      begin
+        is_pc:=(r=NR_R15);
+      end;
+
+
+    function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+      const
+        inverse: array[TAsmCond] of TAsmCond=(C_None,
+          C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+          C_LT,C_GE,C_LE,C_GT,C_None,C_None
+        );
+      begin
+        result := inverse[c];
+      end;
+
+
+    function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+      begin
+        result := c1 = c2;
+      end;
+
+
+    function rotl(d : dword;b : byte) : dword;
+      begin
+         result:=(d shr (32-b)) or (d shl b);
+      end;
+
+    function in_signed_bits(a: aint; bits: byte): boolean;
+      var
+        val : aint;
+      begin
+        val := (1 shl (bits-1))-1;
+        result := (a < val) and (a >= -val);
+      end;
+
+    function dwarf_reg(r:tregister):shortint;
+      begin
+        result:=regdwarf_table[findreg_by_number(r)];
+        if result=-1 then
+          internalerror(200603251);
+      end;
+
+end.

+ 131 - 0
compiler/avr32/cpuinfo.pas

@@ -0,0 +1,131 @@
+{
+    Copyright (c) 1998-2002 by the Free Pascal development team
+
+    Basic Processor information for the ARM
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+  uses
+    globtype;
+
+Type
+   bestreal = double;
+   ts32real = single;
+   ts64real = double;
+   ts80real = type extended;
+   ts128real = type extended;
+   ts64comp = comp;
+
+   pbestreal=^bestreal;
+
+   { possible supported processors for this target }
+   tcputype =
+      (cpu_none,
+       cpu_avr32a,
+       cpu_avr32b
+      );
+
+Type
+   tfputype =
+     (fpu_none,
+      fpu_libgcc,
+      fpu_soft,
+      fpu_avr32
+     );
+
+   tcontrollertype =
+     (ct_none,
+
+      ct_at32uc3l016,
+      ct_at32uc3l032,
+      ct_at32uc3l064,
+      ct_at32uc3b1256
+     );
+
+Const
+   {# Size of native extended floating point type }
+   extended_size = 12;
+   {# Size of a multimedia register               }
+   mmreg_size = 16;
+   { target cpu string (used by compiler options) }
+   target_cpu_string = 'avr32';
+
+   { calling conventions supported by the code generator }
+   supported_calling_conventions : tproccalloptions = [
+     pocall_internproc,
+     pocall_safecall,
+     pocall_stdcall,
+     { same as stdcall only different name mangling }
+     pocall_cdecl,
+     { same as stdcall only different name mangling }
+     pocall_cppdecl,
+     { same as stdcall but floating point numbers are handled like equal sized integers }
+     pocall_softfloat,
+     { same as stdcall (requires that all const records are passed by
+       reference, but that's already done for stdcall) }
+     pocall_mwpascal
+   ];
+
+   cputypestr : array[tcputype] of string[8] = ('',
+     'AVR32A',
+     'AVR32B'
+   );
+
+   fputypestr : array[tfputype] of string[6] = ('',
+     'LIBGCC',
+     'SOFT',
+     'AVR32'
+   );
+
+   controllertypestr : array[tcontrollertype] of string[20] =
+     ('',
+      'AT32UC3L016',
+      'AT32UC3L032',
+      'AT32UC3L064',
+      'AT32UC3B1256'
+     );
+
+   controllerunitstr : array[tcontrollertype] of string[20] =
+     ('',
+      'AT32UC3L016',
+      'AT32UC3L032',
+      'AT32UC3L064',
+      'AT32UC3B1256'
+     );
+
+   interruptvectors : array[tcontrollertype] of longint =
+     (0,
+      18,
+      18,
+      18,
+      18
+     );
+
+   { Supported optimizations, only used for information }
+   supported_optimizerswitches = genericlevel1optimizerswitches+
+                                 genericlevel2optimizerswitches+
+                                 genericlevel3optimizerswitches-
+                                 { no need to write info about those }
+                                 [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+                                 [cs_opt_regvar,cs_opt_loopunroll,cs_opt_tailrecursion,
+								  cs_opt_stackframe,cs_opt_nodecse];
+
+   level1optimizerswitches = genericlevel1optimizerswitches;
+   level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+     [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
+   level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+Implementation
+
+end.

+ 53 - 0
compiler/avr32/cpunode.pas

@@ -0,0 +1,53 @@
+{
+    Copyright (c) 2000-2003 by Florian Klaempfl
+
+    This unit includes the ARM code generator into the compiler
+
+    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 cpunode;
+
+{$i fpcdefs.inc}
+
+  interface
+
+  implementation
+
+    uses
+       { generic nodes }
+       ncgbas,ncgld,ncgflw,ncgset,ncginl,ncgopt,ncgobjc//,
+       { to be able to only parts of the generic code,
+         the processor specific nodes must be included
+         after the generic one (FK)
+       }
+       ,navr32add
+       ,navr32mem
+       ,navr32mat
+       ,navr32cal
+       ,navr32cnv
+       ,navr32con
+       {narmadd,
+       narmcal,
+       narmmat,
+       narminl,
+       narmcnv,
+       narmcon,
+       narmset }
+       ;
+
+
+end.

+ 526 - 0
compiler/avr32/cpupara.pas

@@ -0,0 +1,526 @@
+{
+    Copyright (c) 2003 by Florian Klaempfl
+
+    avr32 specific calling conventions
+     - (R12,R10,R9,R8,FP[4],FP[8]...)
+
+    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.
+ ****************************************************************************
+}
+{ avr32 specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       globtype,globals,
+       aasmtai,aasmdata,
+       cpuinfo,cpubase,cgbase,cgutils,
+       symconst,symbase,symtype,symdef,parabase,paramgr;
+
+    type
+       tavr32paramanager = class(tparamanager)
+          function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+          function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+          function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+          procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+          function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+          function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+         private
+          procedure init_values(var curintreg: tsuperregister; var cur_stack_offset: aword);
+          function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
+          procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+       end;
+
+  implementation
+
+    uses
+       verbose,systems,cutils,
+       rgobj,
+       defutil,symsym;
+
+
+    function tavr32paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+      begin
+        result:=VOLATILE_INTREGISTERS;
+      end;
+
+
+    procedure tavr32paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+      var
+        paraloc : pcgparalocation;
+      begin
+        if nr<1 then
+          internalerror(2002070801);
+        cgpara.reset;
+        cgpara.size:=OS_ADDR;
+        cgpara.intsize:=sizeof(pint);
+        cgpara.alignment:=std_param_align;
+        paraloc:=cgpara.add_location;
+        with paraloc^ do
+          begin
+            size:=OS_INT;
+            { the four first parameters are passed into registers }
+            if nr<=4 then
+              begin
+                loc:=LOC_REGISTER;
+                register:=newreg(R_INTREGISTER,RS_R0+nr-1,R_SUBWHOLE);
+              end
+            else
+              begin
+                { the other parameters are passed on the stack }
+                loc:=LOC_REFERENCE;
+                reference.index:=NR_STACK_POINTER_REG;
+                reference.offset:=(nr-5)*4;
+              end;
+          end;
+      end;
+
+
+    function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc;
+      begin
+         { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+           if push_addr_param for the def is true
+         }
+         case p.typ of
+            orddef:
+              getparaloc:=LOC_REGISTER;
+            floatdef:
+              getparaloc:=LOC_REGISTER;
+            enumdef:
+              getparaloc:=LOC_REGISTER;
+            pointerdef:
+              getparaloc:=LOC_REGISTER;
+            formaldef:
+              getparaloc:=LOC_REGISTER;
+            classrefdef:
+              getparaloc:=LOC_REGISTER;
+            recorddef:
+              getparaloc:=LOC_REGISTER;
+            objectdef:
+              getparaloc:=LOC_REGISTER;
+            stringdef:
+              if is_shortstring(p) or is_longstring(p) then
+                getparaloc:=LOC_REFERENCE
+              else
+                getparaloc:=LOC_REGISTER;
+            procvardef:
+              getparaloc:=LOC_REGISTER;
+            filedef:
+              getparaloc:=LOC_REGISTER;
+            arraydef:
+              getparaloc:=LOC_REFERENCE;
+            setdef:
+              if is_smallset(p) then
+                getparaloc:=LOC_REGISTER
+              else
+                getparaloc:=LOC_REFERENCE;
+            variantdef:
+              getparaloc:=LOC_REGISTER;
+            { avoid problems with errornous definitions }
+            errordef:
+              getparaloc:=LOC_REGISTER;
+            else
+              internalerror(2002071001);
+         end;
+      end;
+
+
+    function tavr32paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+      begin
+        result:=false;
+        if varspez in [vs_var,vs_out,vs_constref] then
+          begin
+            result:=true;
+            exit;
+          end;
+        case def.typ of
+          objectdef:
+            result:=is_object(def) and ((varspez=vs_const) or (def.size=0));
+          recorddef:
+            { note: should this ever be changed, make sure that const records
+                are always passed by reference for calloption=pocall_mwpascal }
+            result:=(varspez=vs_const) or (def.size=0);
+          variantdef,
+          formaldef:
+            result:=true;
+          arraydef:
+            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+                             is_open_array(def) or
+                             is_array_of_const(def) or
+                             is_array_constructor(def);
+          setdef :
+            result:=not is_smallset(def);
+          stringdef :
+            result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+        end;
+      end;
+
+
+    function tavr32paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+      begin
+        case def.typ of
+          recorddef:
+            result:=def.size>4;
+          procvardef:
+            if not tprocvardef(def).is_addressonly then
+              result:=true
+            else
+              result:=false
+          else
+            result:=inherited ret_in_param(def,calloption);
+        end;
+      end;
+
+
+    procedure tavr32paramanager.init_values(var curintreg: tsuperregister; var cur_stack_offset: aword);
+      begin
+        curintreg:=RS_R12;
+        cur_stack_offset:=0;
+      end;
+
+
+    function tavr32paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+        var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
+
+      var
+        nextintreg : tsuperregister;
+        paradef : tdef;
+        paraloc : pcgparalocation;
+        stack_offset : aword;
+        hp : tparavarsym;
+        loc : tcgloc;
+        paracgsize   : tcgsize;
+        paralen : longint;
+        i : integer;
+        firstparaloc: boolean;
+
+      procedure assignintreg;
+        begin
+          { In case of po_delphi_nested_cc, the parent frame pointer
+            is always passed on the stack. }
+           if (nextintreg>=RS_R8) and
+              (not(vo_is_parentfp in hp.varoptions) or
+               not(po_delphi_nested_cc in p.procoptions)) then
+             begin
+               paraloc^.loc:=LOC_REGISTER;
+               paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+               inc(nextintreg);
+             end
+           else
+             begin
+               paraloc^.loc:=LOC_REFERENCE;
+               paraloc^.reference.index:=NR_STACK_POINTER_REG;
+               paraloc^.reference.offset:=stack_offset;
+               inc(stack_offset,4);
+            end;
+        end;
+
+
+      begin
+        result:=0;
+        nextintreg:=curintreg;
+        stack_offset:=cur_stack_offset;
+
+        for i:=0 to paras.count-1 do
+          begin
+            hp:=tparavarsym(paras[i]);
+            paradef:=hp.vardef;
+
+            hp.paraloc[side].reset;
+
+            { currently only support C-style array of const,
+              there should be no location assigned to the vararg array itself }
+            if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+               is_array_of_const(paradef) then
+              begin
+                paraloc:=hp.paraloc[side].add_location;
+                { hack: the paraloc must be valid, but is not actually used }
+                paraloc^.loc:=LOC_REGISTER;
+                paraloc^.register:=NR_R0;
+                paraloc^.size:=OS_ADDR;
+                break;
+              end;
+
+            if (hp.varspez in [vs_var,vs_out]) or
+               push_addr_param(hp.varspez,paradef,p.proccalloption) or
+               is_open_array(paradef) or
+               is_array_of_const(paradef) then
+              begin
+                paradef:=voidpointertype;
+                loc:=LOC_REGISTER;
+                paracgsize := OS_ADDR;
+                paralen := tcgsize2size[OS_ADDR];
+              end
+            else
+              begin
+                if not is_special_array(paradef) then
+                  paralen := paradef.size
+                else
+                  paralen := tcgsize2size[def_cgsize(paradef)];
+                loc := getparaloc(p.proccalloption,paradef);
+                if (paradef.typ in [objectdef,arraydef,recorddef]) and
+                  not is_special_array(paradef) and
+                  (hp.varspez in [vs_value,vs_const]) then
+                  paracgsize := int_cgsize(paralen)
+                else
+                  begin
+                    paracgsize:=def_cgsize(paradef);
+                    { for things like formaldef }
+                    if (paracgsize=OS_NO) then
+                      begin
+                        paracgsize:=OS_ADDR;
+                        paralen := tcgsize2size[OS_ADDR];
+                      end;
+                  end
+              end;
+
+             hp.paraloc[side].size:=paracgsize;
+             hp.paraloc[side].Alignment:=std_param_align;
+             hp.paraloc[side].intsize:=paralen;
+             firstparaloc:=true;
+
+{$ifdef EXTDEBUG}
+             if paralen=0 then
+               internalerror(200410311);
+{$endif EXTDEBUG}
+             while paralen>0 do
+               begin
+                 paraloc:=hp.paraloc[side].add_location;
+
+                 if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
+                   case paracgsize of
+                     OS_F32:
+                       paraloc^.size:=OS_32;
+                     OS_F64:
+                       paraloc^.size:=OS_32;
+                     else
+                       internalerror(2005082901);
+                   end
+                 else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+                   paraloc^.size := OS_32
+                 else
+                   paraloc^.size:=paracgsize;
+                 case loc of
+                    LOC_REGISTER:
+                      begin
+                        if nextintreg>=RS_R8 then
+                          begin
+                            paraloc^.loc:=LOC_REGISTER;
+                            paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+                            dec(nextintreg);
+                            if nextintreg=RS_R11 then
+                              dec(nextintreg);
+                          end
+                        else
+                          begin
+                            { LOC_REFERENCE always contains everything that's left }
+                            paraloc^.loc:=LOC_REFERENCE;
+                            paraloc^.size:=int_cgsize(paralen);
+                            if (side=callerside) then
+                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
+                            paraloc^.reference.offset:=stack_offset;
+                            inc(stack_offset,align(paralen,4));
+                            paralen:=0;
+                         end;
+                      end;
+                    LOC_FPUREGISTER:
+                      begin
+                        paraloc^.loc:=LOC_REFERENCE;
+                        paraloc^.reference.index:=NR_STACK_POINTER_REG;
+                        paraloc^.reference.offset:=stack_offset;
+                        case paraloc^.size of
+                          OS_F32:
+                            inc(stack_offset,4);
+                          OS_F64:
+                            inc(stack_offset,8);
+                          OS_F80:
+                            inc(stack_offset,10);
+                          OS_F128:
+                            inc(stack_offset,16);
+                          else
+                            internalerror(200403201);
+                          end;
+                      end;
+                    LOC_REFERENCE:
+                      begin
+                        if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+                          begin
+                            paraloc^.size:=OS_ADDR;
+                            assignintreg
+                          end
+                        else
+                          begin
+                             paraloc^.size:=paracgsize;
+                             paraloc^.loc:=LOC_REFERENCE;
+                             paraloc^.reference.index:=NR_STACK_POINTER_REG;
+                             paraloc^.reference.offset:=stack_offset;
+                             inc(stack_offset,align(paralen,4));
+                             paralen:=0
+                          end;
+                      end;
+                    else
+                      internalerror(2002071002);
+                 end;
+                 if side=calleeside then
+                   begin
+                     if paraloc^.loc=LOC_REFERENCE then
+                       begin
+                         paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                         inc(paraloc^.reference.offset,4);
+                       end;
+                   end;
+                 dec(paralen,tcgsize2size[paraloc^.size]);
+                 firstparaloc:=false
+               end;
+          end;
+        curintreg:=nextintreg;
+        cur_stack_offset:=stack_offset;
+        result:=cur_stack_offset;
+      end;
+
+
+    procedure tavr32paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+      begin
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
+
+
+    function  tavr32paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+      var
+        paraloc : pcgparalocation;
+        retcgsize  : tcgsize;
+      begin
+        result.init;
+        result.alignment:=get_para_align(p.proccalloption);
+        { void has no location }
+        if is_void(def) then
+          begin
+            paraloc:=result.add_location;
+            result.size:=OS_NO;
+            result.intsize:=0;
+            paraloc^.size:=OS_NO;
+            paraloc^.loc:=LOC_VOID;
+            exit;
+          end;
+        { Constructors return self instead of a boolean }
+        if (p.proctypeoption=potype_constructor) then
+          begin
+            retcgsize:=OS_ADDR;
+            result.intsize:=sizeof(pint);
+          end
+        else
+          begin
+            retcgsize:=def_cgsize(def);
+            result.intsize:=def.size;
+          end;
+        result.size:=retcgsize;
+        { Return is passed as var parameter }
+        if ret_in_param(def,p.proccalloption) then
+          begin
+            paraloc:=result.add_location;
+            paraloc^.loc:=LOC_REFERENCE;
+            paraloc^.size:=retcgsize;
+            exit;
+          end;
+
+        paraloc:=result.add_location;
+        { Return in FPU register? }
+        if def.typ=floatdef then
+          begin
+            case retcgsize of
+              OS_64,
+              OS_F64:
+                begin
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+                  paraloc^.size:=OS_32;
+                  paraloc:=result.add_location;
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+                  paraloc^.size:=OS_32;
+                end;
+              OS_32,
+              OS_F32:
+                begin
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_FUNCTION_RETURN_REG;
+                  paraloc^.size:=OS_32;
+                end;
+              else
+                internalerror(2005082603);
+            end;
+          end
+          { Return in register }
+        else
+          begin
+            if retcgsize in [OS_64,OS_S64] then
+              begin
+                paraloc^.loc:=LOC_REGISTER;
+                paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+                paraloc^.size:=OS_32;
+                paraloc:=result.add_location;
+                paraloc^.loc:=LOC_REGISTER;
+                paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+                paraloc^.size:=OS_32;
+              end
+            else
+              begin
+                paraloc^.loc:=LOC_REGISTER;
+                paraloc^.register:=NR_FUNCTION_RETURN_REG;
+                if (result.intsize<>3) then
+                  paraloc^.size:=retcgsize
+                else
+                  paraloc^.size:=OS_32;
+              end;
+          end;
+      end;
+
+
+    function tavr32paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+      var
+        cur_stack_offset: aword;
+        curintreg: tsuperregister;
+      begin
+        init_values(curintreg,cur_stack_offset);
+
+        result:=create_paraloc_info_intern(p,side,p.paras,curintreg,cur_stack_offset);
+
+        create_funcretloc_info(p,side);
+     end;
+
+
+    function tavr32paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+      var
+        cur_stack_offset: aword;
+        curintreg: tsuperregister;
+      begin
+        init_values(curintreg,cur_stack_offset);
+
+        result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,cur_stack_offset);
+        if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+          { just continue loading the parameters in the registers }
+          result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,cur_stack_offset)
+        else
+          internalerror(200410231);
+      end;
+
+begin
+   paramanager:=tavr32paramanager.create;
+end.

+ 53 - 0
compiler/avr32/cpupi.pas

@@ -0,0 +1,53 @@
+{
+    Copyright (c) 2002 by Florian Klaempfl
+
+    This unit contains the CPU specific part of tprocinfo
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       globtype,cutils,
+       procinfo,cpuinfo,psub;
+
+    type
+       tarmprocinfo = class(tcgprocinfo)
+       end;
+
+
+  implementation
+
+    uses
+       globals,systems,
+       cpubase,
+       aasmtai,aasmdata,
+       tgobj,
+       symconst,symsym,paramgr,
+       cgbase,
+       cgobj;
+
+
+begin
+   cprocinfo:=tarmprocinfo;
+end.

+ 70 - 0
compiler/avr32/cputarg.pas

@@ -0,0 +1,70 @@
+{
+    Copyright (c) 2001-2002 by Peter Vreman
+
+    Includes the arm dependent target units
+
+    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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+    uses
+      systems { prevent a syntax error when nothing is included }
+
+{**************************************
+             Targets
+**************************************}
+
+    {$ifndef NOTARGETEMBEDDED}
+      ,t_embed
+    {$endif}
+
+{**************************************
+             Assemblers
+**************************************}
+
+    {$ifndef NOAGARMGAS}
+      ,agavr32gas
+    {$endif}
+
+{**************************************
+        Assembler Readers
+**************************************}
+
+  {$ifndef NoRaarmgas}
+       ,raavr32gas
+  {$endif NoRaarmgas}
+
+{**************************************
+             Debuginfo
+**************************************}
+
+  {$ifndef NoDbgStabs}
+      ,dbgstabs
+  {$endif NoDbgStabs}
+  {$ifndef NoDbgDwarf}
+      ,dbgdwarf
+  {$endif NoDbgDwarf}
+      ;
+
+end.

+ 93 - 0
compiler/avr32/itcpugas.pas

@@ -0,0 +1,93 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    This unit contains the AVR32 GAS instruction tables
+
+    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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    cpubase,cgbase;
+
+
+  const
+    { Standard opcode string table (for each tasmop enumeration). The
+      opcode strings should conform to the names as defined by the
+      processor manufacturer.
+    }
+    gas_op2str : op2strtable = {$i avr32att.inc}
+
+    function gas_regnum_search(const s:string):Tregister;
+    function gas_regname(r:Tregister):string;
+
+
+implementation
+
+    uses
+      cutils,verbose;
+
+    const
+      gas_regname_table : array[tregisterindex] of string[7] = (
+        {$i ravr32std.inc}
+      );
+
+      gas_regname_index : array[tregisterindex] of tregisterindex = (
+        {$i ravr32sri.inc}
+      );
+
+    function findreg_by_gasname(const s:string):tregisterindex;
+      var
+        i,p : tregisterindex;
+      begin
+        {Binary search.}
+        p:=0;
+        i:=regnumber_count_bsstart;
+        repeat
+          if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+            p:=p+i;
+          i:=i shr 1;
+        until i=0;
+        if gas_regname_table[gas_regname_index[p]]=s then
+          findreg_by_gasname:=gas_regname_index[p]
+        else
+          findreg_by_gasname:=0;
+      end;
+
+
+    function gas_regnum_search(const s:string):Tregister;
+      begin
+        result:=regnumber_table[findreg_by_gasname(s)];
+      end;
+
+
+    function gas_regname(r:Tregister):string;
+      var
+        p : tregisterindex;
+      begin
+        p:=findreg_by_number(r);
+        if p<>0 then
+          result:=gas_regname_table[p]
+        else
+          result:=generic_regname(r);
+      end;
+
+end.

+ 376 - 0
compiler/avr32/navr32add.pas

@@ -0,0 +1,376 @@
+{
+    Copyright (c) 2000-2002 by Florian Klaempfl
+
+    Code generation for add nodes on the avr32
+
+    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 navr32add;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       node,ncgadd,cpubase;
+
+    type
+       tavr32addnode = class(tcgaddnode)
+       private
+          function  GetResFlags(unsigned:Boolean):TResFlags;
+       public
+          function pass_1 : tnode;override;
+       protected
+          procedure second_addfloat;override;
+          procedure second_cmpfloat;override;
+          procedure second_cmpordinal;override;
+          procedure second_cmpsmallset;override;
+          procedure second_cmp64bit;override;
+       end;
+
+  implementation
+
+    uses
+      globtype,systems,
+      cutils,verbose,globals,
+      symconst,symdef,paramgr,
+      aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+      cgbase,cgutils,cgcpu,
+      cpuinfo,pass_1,pass_2,regvars,procinfo,
+      cpupara,
+      ncon,nset,nadd,
+      ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+{*****************************************************************************
+                               TSparcAddNode
+*****************************************************************************}
+
+    function floatsize2postfix(size:TCgSize):TOpPostfix;
+      begin
+        case size of
+          OS_F32:
+            result:=PF_S;
+          OS_F64:
+            result:=PF_D;
+          else
+            internalerror(2011012302);
+        end;
+      end;
+
+    function tavr32addnode.GetResFlags(unsigned:Boolean):TResFlags;
+      begin
+        case NodeType of
+          equaln:
+            GetResFlags:=F_EQ;
+          unequaln:
+            GetResFlags:=F_NE;
+          else
+            if not(unsigned) then
+              begin
+                if nf_swapped in flags then
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_GT;
+                    lten:
+                      GetResFlags:=F_GE;
+                    gtn:
+                      GetResFlags:=F_LT;
+                    gten:
+                      GetResFlags:=F_LE;
+                  end
+                else
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_LT;
+                    lten:
+                      GetResFlags:=F_LE;
+                    gtn:
+                      GetResFlags:=F_GT;
+                    gten:
+                      GetResFlags:=F_GE;
+                  end;
+              end
+            else
+              begin
+                if nf_swapped in Flags then
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_HI;
+                    lten:
+                      GetResFlags:=F_CS;
+                    gtn:
+                      GetResFlags:=F_CC;
+                    gten:
+                      GetResFlags:=F_LS;
+                  end
+                else
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_CC;
+                    lten:
+                      GetResFlags:=F_LS;
+                    gtn:
+                      GetResFlags:=F_HI;
+                    gten:
+                      GetResFlags:=F_CS;
+                  end;
+              end;
+        end;
+      end;
+
+
+    procedure tavr32addnode.second_addfloat;
+      var
+        op : TAsmOp;
+        singleprec: boolean;
+      begin
+        pass_left_right;
+        if (nf_swapped in flags) then
+          swapleftright;
+
+        case current_settings.fputype of
+          fpu_avr32:
+            begin
+              singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+              if not singleprec then
+                internalerror(2011012304);
+
+              { force mmreg as location, left right doesn't matter
+                as both will be in a fpureg }
+              location_force_reg(current_asmdata.CurrAsmList,left.location,OS_F32,true);
+              location_force_reg(current_asmdata.CurrAsmList,right.location,OS_F32,true);
+
+              location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+              if left.location.loc<>LOC_CMMREGISTER then
+                location.register:=left.location.register
+              else if right.location.loc<>LOC_CMMREGISTER then
+                location.register:=right.location.register
+              else
+                location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+
+              case nodetype of
+                addn :
+                  current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_FADD,location.register,left.location.register,right.location.register),PF_S));
+                muln :
+                  current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_FMUL,location.register,left.location.register,right.location.register),PF_S));
+                subn :
+                  current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_FSUB,location.register,left.location.register,right.location.register),PF_S));
+                slashn :
+                  begin
+                    current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_FRCPA,location.register,right.location.register),PF_S));
+                    current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_FMUL,location.register,left.location.register,location.register),PF_S));
+                  end
+                else
+                  internalerror(2009111401);
+              end;
+            end;
+          fpu_soft:
+            { this case should be handled already by pass1 }
+            internalerror(200308252);
+          else
+            internalerror(200308251);
+        end;
+      end;
+
+
+    procedure tavr32addnode.second_cmpfloat;
+      var
+        op: TAsmOp;
+        singleprec: Boolean;
+      begin
+        pass_left_right;
+        if (nf_swapped in flags) then
+          swapleftright;
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(true);
+
+        case current_settings.fputype of
+          fpu_avr32:
+            begin
+              singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+              if not singleprec then
+                internalerror(2011012304);
+
+              location_force_reg(current_asmdata.CurrAsmList,left.location,OS_F32,true);
+              location_force_reg(current_asmdata.CurrAsmList,right.location,OS_F32,true);
+
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_FCP,left.location.register,right.location.register),PF_S));
+            end;
+          fpu_soft:
+            { this case should be handled already by pass1 }
+            internalerror(2009112404);
+        end;
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(false);
+      end;
+
+
+    procedure tavr32addnode.second_cmpsmallset;
+      var
+        tmpreg : tregister;
+      begin
+        pass_left_right;
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+
+        force_reg_left_right(false,false);
+
+        case nodetype of
+          equaln:
+            begin
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register,right.location.register),PF_W));
+              location.resflags:=F_EQ;
+            end;
+          unequaln:
+            begin
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register,right.location.register),PF_W));
+              location.resflags:=F_NE;
+            end;
+          lten,
+          gten:
+            begin
+              if (not(nf_swapped in flags) and
+                  (nodetype = lten)) or
+                 ((nf_swapped in flags) and
+                  (nodetype = gten)) then
+                swapleftright;
+              tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_TST,tmpreg,left.location.register,right.location.register));
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,tmpreg,right.location.register),PF_W));
+              location.resflags:=F_EQ;
+            end;
+          else
+            internalerror(2004012401);
+        end;
+      end;
+
+
+    procedure tavr32addnode.second_cmp64bit;
+      var
+        unsigned : boolean;
+        oldnodetype : tnodetype;
+      begin
+        pass_left_right;
+        force_reg_left_right(false,false);
+
+        unsigned:=not(is_signed(left.resultdef)) or
+                  not(is_signed(right.resultdef));
+
+        { operation requiring proper N, Z and C flags ? }
+        if unsigned or (nodetype in [equaln,unequaln]) then
+          begin
+            location_reset(location,LOC_FLAGS,OS_NO);
+            location.resflags:=getresflags(unsigned);
+            current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register64.reghi,right.location.register64.reghi),PF_W));
+            current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,left.location.register64.reglo,right.location.register64.reglo));
+          end
+        else
+        { operation requiring proper N, Z and V flags ? }
+          begin
+            location_reset(location,LOC_JUMP,OS_NO);
+            current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register64.reghi,right.location.register64.reghi),PF_W));
+            { the jump the sequence is a little bit hairy }
+            case nodetype of
+               ltn,gtn:
+                 begin
+                    cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrTrueLabel);
+                    { cheat a little bit for the negative test }
+                    toggleflag(nf_swapped);
+                    cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrFalseLabel);
+                    toggleflag(nf_swapped);
+                 end;
+               lten,gten:
+                 begin
+                    oldnodetype:=nodetype;
+                    if nodetype=lten then
+                      nodetype:=ltn
+                    else
+                      nodetype:=gtn;
+                    cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+                    { cheat for the negative test }
+                    if nodetype=ltn then
+                      nodetype:=gtn
+                    else
+                      nodetype:=ltn;
+                    cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
+                    nodetype:=oldnodetype;
+                 end;
+            end;
+            current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register64.reglo,right.location.register64.reglo),PF_W));
+            { the comparisaion of the low dword have to be
+               always unsigned!                            }
+            cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
+            cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+          end;
+      end;
+
+
+    function tavr32addnode.pass_1 : tnode;
+      var
+        unsigned : boolean;
+      begin
+        result:=inherited pass_1;
+
+        if not(assigned(result)) then
+          begin
+            unsigned:=not(is_signed(left.resultdef)) or
+              not(is_signed(right.resultdef));
+
+            if is_64bit(left.resultdef) and
+              ((nodetype in [equaln,unequaln]) or
+               (unsigned and (nodetype in [ltn,lten,gtn,gten]))
+              ) then
+              expectloc:=LOC_FLAGS;
+          end;
+      end;
+
+
+    procedure tavr32addnode.second_cmpordinal;
+      var
+        unsigned : boolean;
+        tmpreg : tregister;
+        b : byte;
+      begin
+        pass_left_right;
+        force_reg_left_right(true,true);
+
+        unsigned:=not(is_signed(left.resultdef)) or
+                  not(is_signed(right.resultdef));
+
+        if right.location.loc = LOC_CONSTANT then
+          begin
+             if in_signed_bits(right.location.value,21) then
+               current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_const(A_CP,left.location.register,right.location.value),PF_W))
+             else
+               begin
+                 tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+                 cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT, right.location.value,tmpreg);
+                 current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register,tmpreg),PF_W));
+               end;
+          end
+        else
+          current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CP,left.location.register,right.location.register),PF_W));
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(unsigned);
+      end;
+
+begin
+  caddnode:=tavr32addnode;
+end.

+ 74 - 0
compiler/avr32/navr32cal.pas

@@ -0,0 +1,74 @@
+{
+    Copyright (c) 2002 by Florian Klaempfl
+
+    Implements the avr32 specific part of call nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navr32cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      symdef,node,ncal,ncgcal;
+
+    type
+       tavr32callnode = class(tcgcallnode)
+         procedure set_result_location(realresdef: tstoreddef);override;
+       end;
+
+implementation
+
+  uses
+    verbose,globtype,globals,aasmdata,
+    symconst,
+    cgbase,
+    cpubase,cpuinfo,
+    ncgutil,
+    paramgr;
+
+  procedure tavr32callnode.set_result_location(realresdef: tstoreddef);
+    begin
+      if (realresdef.typ=floatdef){ and
+         ((cs_fp_emulation in current_settings.moduleswitches) or
+          (current_settings.fputype in [fpu_avr32]))} then
+        begin
+          { keep the fpu values in integer registers for now, the code
+            generator will move them to memory or an mmregister when necessary
+            (avoids double moves in case a function result is assigned to
+             another function result, or passed as a parameter) }
+          case retloc.size of
+            OS_32,
+            OS_F32:
+              location_allocate_register(current_asmdata.CurrAsmList,location,s32inttype,false);
+            OS_64,
+            OS_F64:
+              location_allocate_register(current_asmdata.CurrAsmList,location,s64inttype,false);
+            else
+              internalerror(2010053008);
+          end
+        end
+      else
+        inherited;
+    end;
+
+
+begin
+   ccallnode:=tavr32callnode;
+end.

+ 233 - 0
compiler/avr32/navr32cnv.pas

@@ -0,0 +1,233 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate avr32 assembler for type converting nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navr32cnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ncnv,ncgcnv,defcmp;
+
+    type
+       tavr32typeconvnode = class(tcgtypeconvnode)
+         protected
+           function first_int_to_real: tnode;override;
+           procedure second_int_to_real;override;
+           procedure second_int_to_bool;override;
+       end;
+
+implementation
+
+   uses
+      verbose,globtype,globals,systems,
+      symconst,symdef,aasmbase,aasmtai,aasmdata,
+      defutil,
+      cgbase,cgutils,
+      pass_1,pass_2,procinfo,
+      ncon,ncal,
+      ncgutil,
+      cpubase,cpuinfo,aasmcpu,
+      rgobj,tgobj,cgobj,cgcpu;
+
+
+{*****************************************************************************
+                             FirstTypeConv
+*****************************************************************************}
+
+    function tavr32typeconvnode.first_int_to_real: tnode;
+      var
+        fname: string[19];
+      begin
+        if cs_fp_emulation in current_settings.moduleswitches then
+          result:=inherited first_int_to_real
+        else
+          begin
+            { converting a 64bit integer to a float requires a helper }
+            if is_64bitint(left.resultdef) or
+              is_currency(left.resultdef) then
+              begin
+                { hack to avoid double division by 10000, as it's
+                  already done by typecheckpass.resultdef_int_to_real }
+                if is_currency(left.resultdef) then
+                  left.resultdef := s64inttype;
+                if is_signed(left.resultdef) then
+                  fname := 'fpc_int64_to_double'
+                else
+                  fname := 'fpc_qword_to_double';
+                result := ccallnode.createintern(fname,ccallparanode.create(
+                  left,nil));
+                left:=nil;
+                if (tfloatdef(resultdef).floattype=s32real) then
+                  inserttypeconv(result,s32floattype);
+                firstpass(result);
+                exit;
+              end
+            else
+              { other integers are supposed to be 32 bit }
+              begin
+                if is_signed(left.resultdef) then
+                  inserttypeconv(left,s32inttype)
+                else
+                  inserttypeconv(left,u32inttype);
+                firstpass(left);
+              end;
+            result := nil;
+            case current_settings.fputype of
+              fpu_avr32:
+                expectloc:=LOC_REGISTER;
+              else
+                internalerror(2009112702);
+            end;
+          end;
+      end;
+
+
+    procedure tavr32typeconvnode.second_int_to_real;
+      var
+        instr : taicpu;
+        href : treference;
+        l1,l2 : tasmlabel;
+        hregister : tregister;
+        signed : boolean;
+      begin
+        case current_settings.fputype of
+          fpu_avr32:
+            begin
+              location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+              signed:=left.location.size=OS_S32;
+              location_force_reg(current_asmdata.CurrAsmList,left.location,OS_INT,false);
+              if not(left.location.size in [OS_F32,OS_32,OS_S32]) then
+                internalerror(2009112703);
+              if left.location.size<>location.size then
+                location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size)
+              else
+                location.register:=left.location.register;
+              if signed then
+                current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_FCASTSW,location.register,left.location.register),PF_S))
+              else
+                current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_FCASTUW,location.register,left.location.register),PF_S));
+            end;
+        end;
+      end;
+
+
+    procedure tavr32typeconvnode.second_int_to_bool;
+      var
+        hregister : tregister;
+        href      : treference;
+        resflags  : tresflags;
+        hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+        newsize   : tcgsize;
+      begin
+         oldTrueLabel:=current_procinfo.CurrTrueLabel;
+         oldFalseLabel:=current_procinfo.CurrFalseLabel;
+         current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+         current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+         secondpass(left);
+         if codegenerror then
+          exit;
+
+         { Explicit typecasts from any ordinal type to a boolean type }
+         { must not change the ordinal value                          }
+         if (nf_explicit in flags) and
+            not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+           begin
+              location_copy(location,left.location);
+              newsize:=def_cgsize(resultdef);
+              { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+              if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+                 ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+                location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+              else
+                location.size:=newsize;
+              current_procinfo.CurrTrueLabel:=oldTrueLabel;
+              current_procinfo.CurrFalseLabel:=oldFalseLabel;
+              exit;
+           end;
+
+         { Load left node into flag F_NE/F_E }
+         resflags:=F_NE;
+         case left.location.loc of
+            LOC_CREFERENCE,
+            LOC_REFERENCE :
+              begin
+                if left.location.size in [OS_64,OS_S64] then
+                 begin
+                   hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                   cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister);
+                   href:=left.location.reference;
+                   inc(href.offset,4);
+                   cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister);
+                 end
+                else
+                 begin
+                   location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+                   cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+                 end;
+              end;
+            LOC_FLAGS :
+              begin
+                resflags:=left.location.resflags;
+              end;
+            LOC_REGISTER,LOC_CREGISTER :
+              begin
+                if left.location.size in [OS_64,OS_S64] then
+                 begin
+                   hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+                   cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister);
+                   cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
+                 end
+                else
+                 begin
+                   cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+                 end;
+              end;
+            LOC_JUMP :
+              begin
+                hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                current_asmdata.getjumplabel(hlabel);
+                cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+                cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hregister);
+                cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+                cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+                cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister);
+                cg.a_label(current_asmdata.CurrAsmList,hlabel);
+                cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,hregister,hregister);
+              end;
+            else
+              internalerror(200311301);
+         end;
+         { load flags to register }
+         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+         location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+         cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register);
+         if (is_cbool(resultdef)) then
+           cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,location.register,location.register);
+         current_procinfo.CurrTrueLabel:=oldTrueLabel;
+         current_procinfo.CurrFalseLabel:=oldFalseLabel;
+      end;
+
+
+begin
+  ctypeconvnode:=tavr32typeconvnode;
+end.

+ 134 - 0
compiler/avr32/navr32con.pas

@@ -0,0 +1,134 @@
+{
+    Copyright (c) 2005 by Florian Klaempfl
+
+    Code generation for const nodes on the avr32
+
+    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 navr32con;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ncgcon,cpubase;
+
+    type
+      tavr32realconstnode = class(tcgrealconstnode)
+        procedure pass_generate_code;override;
+      end;
+
+  implementation
+
+    uses
+      verbose,
+      globtype,globals,
+      cpuinfo,
+      aasmbase,aasmtai,aasmdata,
+      symconst,symdef,
+      defutil,
+      cgbase,cgutils,
+      procinfo,
+      ncon;
+
+{*****************************************************************************
+                           Tavr32REALCONSTNODE
+*****************************************************************************}
+
+    procedure tavr32realconstnode.pass_generate_code;
+      { I suppose the parser/pass_1 must make sure the generated real  }
+      { constants are actually supported by the target processor? (JM) }
+      const
+        floattype2ait:array[tfloattype] of taitype=
+          (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
+      var
+         lastlabel : tasmlabel;
+         realait : taitype;
+      begin
+        location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),4);
+        lastlabel:=nil;
+        realait:=floattype2ait[tfloatdef(resultdef).floattype];
+        { const already used ? }
+        if not assigned(lab_real) then
+          begin
+            current_asmdata.getjumplabel(lastlabel);
+            lab_real:=lastlabel;
+            current_procinfo.aktlocaldata.concat(Tai_label.Create(lastlabel));
+            location.reference.symboldata:=current_procinfo.aktlocaldata.last;
+            case realait of
+              ait_real_32bit :
+                begin
+                  current_procinfo.aktlocaldata.concat(Tai_real_32bit.Create(ts32real(value_real)));
+                  { range checking? }
+                  if ((cs_check_range in current_settings.localswitches) or
+                    (cs_check_overflow in current_settings.localswitches)) and
+                    (tai_real_32bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    Message(parser_e_range_check_error);
+                end;
+
+              ait_real_64bit :
+                begin
+                  current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create(ts64real(value_real)));
+
+                  { range checking? }
+                  if ((cs_check_range in current_settings.localswitches) or
+                    (cs_check_overflow in current_settings.localswitches)) and
+                    (tai_real_64bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    Message(parser_e_range_check_error);
+               end;
+
+              ait_real_80bit :
+                begin
+                  current_procinfo.aktlocaldata.concat(Tai_real_80bit.Create(value_real,tfloatdef(resultdef).size));
+
+                  { range checking? }
+                  if ((cs_check_range in current_settings.localswitches) or
+                    (cs_check_overflow in current_settings.localswitches)) and
+                    (tai_real_80bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    Message(parser_e_range_check_error);
+                end;
+{$ifdef cpufloat128}
+              ait_real_128bit :
+                begin
+                  current_procinfo.aktlocaldata.concat(Tai_real_128bit.Create(value_real));
+
+                  { range checking? }
+                  if ((cs_check_range in current_settings.localswitches) or
+                    (cs_check_overflow in current_settings.localswitches)) and
+                    (tai_real_128bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    Message(parser_e_range_check_error);
+                end;
+{$endif cpufloat128}
+
+              { the round is necessary for native compilers where comp isn't a float }
+              ait_comp_64bit :
+                if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
+                  message(parser_e_range_check_error)
+                else
+                  current_procinfo.aktlocaldata.concat(Tai_comp_64bit.Create(round(value_real)));
+            else
+              internalerror(2005092401);
+            end;
+          end;
+        location.reference.symbol:=lab_real;
+        location.reference.base:=NR_R15;
+      end;
+
+begin
+  crealconstnode:=tavr32realconstnode;
+end.

+ 273 - 0
compiler/avr32/navr32mat.pas

@@ -0,0 +1,273 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate avr32 assembler for math nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navr32mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,nmat,ncgmat;
+
+    type
+      tavr32moddivnode = class(tmoddivnode)
+        function first_moddivint: tnode;override;
+        procedure pass_generate_code;override;
+      end;
+
+      tavr32notnode = class(tcgnotnode)
+        procedure second_boolean;override;
+      end;
+
+      tavr32unaryminusnode = class(tcgunaryminusnode)
+        procedure second_float;override;
+      end;
+
+
+implementation
+
+    uses
+      globtype,systems,
+      cutils,verbose,globals,constexp,
+      aasmbase,aasmcpu,aasmtai,aasmdata,
+      defutil,
+      cgbase,cgobj,cgutils,
+      pass_2,procinfo,
+      ncon,
+      cpubase,cpuinfo,
+      ncgutil,cgcpu;
+
+{*****************************************************************************
+                             Tavr32MODDIVNODE
+*****************************************************************************}
+
+    function tavr32moddivnode.first_moddivint: tnode;
+      var
+        power  : longint;
+      begin
+        if (right.nodetype=ordconstn) and
+          (nodetype=divn) and
+          (ispowerof2(tordconstnode(right).value,power) or
+           (tordconstnode(right).value=1) or
+           (tordconstnode(right).value=int64(-1))
+          ) and
+          not(is_64bitint(resultdef)) then
+          result:=nil
+        else
+          result:=inherited first_moddivint;
+      end;
+
+
+    procedure tavr32moddivnode.pass_generate_code;
+      var
+        power  : longint;
+        numerator,
+        resultreg  : tregister;
+        size       : Tcgsize;
+        so : tshifterop;
+
+       procedure genOrdConstNodeDiv;
+         begin
+           if tordconstnode(right).value=0 then
+             internalerror(2005061701)
+           else if tordconstnode(right).value=1 then
+             cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, numerator, resultreg)
+           else if (tordconstnode(right).value = int64(-1)) then
+             begin
+               // note: only in the signed case possible..., may overflow
+               current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_MOV,resultreg,numerator));
+               current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_NEG,resultreg));
+             end
+           else if ispowerof2(tordconstnode(right).value,power) then
+             begin
+               if (is_signed(right.resultdef)) then
+                 begin
+                   cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,31,numerator,resultreg);
+                   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LSR,resultreg,32-power));
+                   current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_ADD,resultreg,numerator));
+                   current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_ASR,resultreg,power));
+                  end
+               else
+                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,numerator,resultreg)
+             end;
+         end;
+
+{
+       procedure genOrdConstNodeMod;
+         var
+             modreg, maskreg, tempreg : tregister;
+         begin
+             if (tordconstnode(right).value = 0) then begin
+                 internalerror(2005061702);
+             end
+             else if (abs(tordconstnode(right).value.svalue) = 1) then
+             begin
+                // x mod +/-1 is always zero
+                cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, resultreg);
+             end
+             else if (ispowerof2(tordconstnode(right).value, power)) then
+             begin
+                 if (is_signed(right.resultdef)) then begin
+
+                     tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+                     maskreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+                     modreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+                     cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, abs(tordconstnode(right).value.svalue)-1, modreg);
+                     cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, maskreg);
+                     cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+                     cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, modreg, maskreg, maskreg);
+                     cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+                 end else begin
+                     cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).value.svalue-1, numerator, resultreg);
+                 end;
+             end else begin
+                 genOrdConstNodeDiv();
+                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, tordconstnode(right).value.svalue, resultreg, resultreg);
+                 cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+             end;
+         end;
+}
+
+      begin
+        secondpass(left);
+        secondpass(right);
+        location_copy(location,left.location);
+
+        { put numerator in register }
+        size:=def_cgsize(left.resultdef);
+        location_force_reg(current_asmdata.CurrAsmList,left.location,
+          size,true);
+        location_copy(location,left.location);
+        numerator:=location.register;
+        resultreg:=location.register;
+        if location.loc=LOC_CREGISTER then
+          begin
+            location.loc := LOC_REGISTER;
+            location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+            resultreg:=location.register;
+          end
+        else if (nodetype=modn) or (right.nodetype=ordconstn) then
+          begin
+            // for a modulus op, and for const nodes we need the result register
+            // to be an extra register
+            resultreg:=cg.getintregister(current_asmdata.CurrAsmList,size);
+          end;
+
+        if right.nodetype=ordconstn then
+          begin
+            if nodetype=divn then
+              genOrdConstNodeDiv
+            else
+//              genOrdConstNodeMod;
+          end;
+
+        location.register:=resultreg;
+
+        { unsigned division/module can only overflow in case of division by zero }
+        { (but checking this overflow flag is more convoluted than performing a  }
+        {  simple comparison with 0)                                             }
+        if is_signed(right.resultdef) then
+          cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+      end;
+
+{*****************************************************************************
+                               Tavr32NOTNODE
+*****************************************************************************}
+
+    procedure tavr32notnode.second_boolean;
+      var
+        hl : tasmlabel;
+      begin
+        { if the location is LOC_JUMP, we do the secondpass after the
+          labels are allocated
+        }
+        if left.expectloc=LOC_JUMP then
+          begin
+            hl:=current_procinfo.CurrTrueLabel;
+            current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+            current_procinfo.CurrFalseLabel:=hl;
+            secondpass(left);
+            maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+            hl:=current_procinfo.CurrTrueLabel;
+            current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+            current_procinfo.CurrFalseLabel:=hl;
+            location.loc:=LOC_JUMP;
+          end
+        else
+          begin
+            secondpass(left);
+            case left.location.loc of
+              LOC_FLAGS :
+                begin
+                  location_copy(location,left.location);
+                  inverse_flags(location.resflags);
+                end;
+              LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE,
+              LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF :
+                begin
+                  location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+                  current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_const(A_CP,left.location.register,0), PF_W));
+                  location_reset(location,LOC_FLAGS,OS_NO);
+                  location.resflags:=F_EQ;
+               end;
+              else
+                internalerror(2003042401);
+            end;
+          end;
+      end;
+
+{*****************************************************************************
+                               Tavr32UNARYMINUSNODE
+*****************************************************************************}
+
+    procedure tavr32unaryminusnode.second_float;
+      var
+        op: tasmop;
+      begin
+        secondpass(left);
+        case current_settings.fputype of
+          fpu_avr32:
+            begin
+              location_force_reg(current_asmdata.CurrAsmList,left.location,OS_F32,true);
+              location:=left.location;
+              if (left.location.loc=LOC_CREGISTER) then
+                location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_MOV,location.register,left.location.register));
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_NEG,location.register));
+            end;
+          else
+            internalerror(2009112602);
+        end;
+      end;
+
+
+begin
+  cmoddivnode:=tavr32moddivnode;
+  cnotnode:=tavr32notnode;
+  cunaryminusnode:=tavr32unaryminusnode;
+end.

+ 115 - 0
compiler/avr32/navr32mem.pas

@@ -0,0 +1,115 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate avr32 assembler for in memory related nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navr32mem;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      globtype,
+      cgbase,cpuinfo,cpubase,
+      node,nmem,ncgmem;
+
+    type
+
+       tavr32vecnode = class(tcgvecnode)
+          procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);override;
+       end;
+
+implementation
+
+    uses
+      systems,
+      cutils,verbose,
+      symdef,paramgr,
+      aasmtai,aasmdata,
+      nld,ncon,nadd,
+      cgutils,cgobj;
+
+
+{*****************************************************************************
+                             TI386VECNODE
+*****************************************************************************}
+
+     { this routine must, like any other routine, not change the contents }
+     { of base/index registers of references, as these may be regvars.    }
+     { The register allocator can coalesce one LOC_REGISTER being moved   }
+     { into another (as their live ranges won't overlap), but not a       }
+     { LOC_CREGISTER moved into a LOC_(C)REGISTER most of the time (as    }
+     { the live range of the LOC_CREGISTER will most likely overlap the   }
+     { the live range of the target LOC_(C)REGISTER)                      }
+     { The passed register may be a LOC_CREGISTER as well.                }
+     procedure tavr32vecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+       var
+         l2 : integer;
+         hreg : tregister;
+       begin
+         { Optimized for avr32 to use the index register and scalefactor }
+         if location.reference.index=NR_NO then
+          begin
+            { no preparations needed }
+          end
+         else if location.reference.base=NR_NO then
+          begin
+            if (location.reference.scalefactor > 1) then
+              hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+            case location.reference.scalefactor of
+             0,1 : hreg:=location.reference.index;
+             2 : cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,1,location.reference.index,hreg);
+             4 : cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,location.reference.index,hreg);
+             8 : cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,3,location.reference.index,hreg);
+             else
+               internalerror(2008091401);
+            end;
+            location.reference.base:=hreg;
+          end
+         else
+          begin
+            hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+            cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
+            reference_reset_base(location.reference,hreg,0,location.reference.alignment);
+          end;
+         { insert the new index register and scalefactor or
+           do the multiplication manual }
+         case l of
+          1,2,4,8 :
+            begin
+              location.reference.scalefactor:=l;
+              hreg:=maybe_const_reg;
+            end;
+         else
+           begin
+              hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+              if ispowerof2(l,l2) then
+                cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,l2,maybe_const_reg,hreg)
+              else
+                cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,maybe_const_reg,hreg);
+           end;
+         end;
+         location.reference.index:=hreg;
+       end;
+
+
+begin
+   cvecnode:=tavr32vecnode;
+end.

+ 54 - 0
compiler/avr32/raavr32.pas

@@ -0,0 +1,54 @@
+{
+    Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+    Handles the common avr32 assembler reader 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 raavr32;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      cpubase,
+      aasmtai,aasmdata,
+      rautils;
+
+    type
+      Tavr32Operand=class(TOperand)
+      end;
+
+      Tavr32Instruction=class(TInstruction)
+        oppostfix : toppostfix;
+        function ConcatInstruction(p:TAsmList) : tai;override;
+      end;
+
+  implementation
+
+    uses
+      aasmcpu;
+
+    function Tavr32Instruction.ConcatInstruction(p:TAsmList) : tai;
+      begin
+        result:=inherited ConcatInstruction(p);
+        (result as taicpu).oppostfix:=oppostfix;
+      end;
+
+
+end.

+ 974 - 0
compiler/avr32/raavr32gas.pas

@@ -0,0 +1,974 @@
+{
+    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+    Does the parsing for the avr32 GNU AS styled inline assembler.
+
+    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 raavr32gas;
+
+{$i fpcdefs.inc}
+
+  Interface
+
+    uses
+      raatt,raavr32,
+      cpubase;
+
+    type
+
+      { tavr32attreader }
+
+      tavr32attreader = class(tattreader)
+        actoppostfix : TOpPostfix;
+        function is_asmopcode(const s: string):boolean;override;
+        function is_register(const s:string):boolean;override;
+        procedure handleopcode;override;
+        procedure BuildReference(oper : tavr32operand);
+        procedure BuildRegset(oper : tavr32operand);
+        procedure BuildOperand(oper : tavr32operand);
+        function TryBuildShifterOp(oper : tavr32operand) : boolean;
+        procedure BuildOpCode(instr : tavr32instruction);
+        procedure ReadSym(oper : tavr32operand);
+        procedure ConvertCalljmp(instr : tavr32instruction);
+        function read_selector : tregisterselector;
+      end;
+
+
+  Implementation
+
+    uses
+      { helpers }
+      cutils,
+      { global }
+      globtype,globals,verbose,
+      systems,
+      { aasm }
+      cpuinfo,aasmbase,aasmtai,aasmdata,aasmcpu,
+      { symtable }
+      symconst,symbase,symtype,symsym,symtable,
+      { parser }
+      scanner,
+      procinfo,
+      itcpugas,
+      rabase,rautils,
+      cgbase,cgobj
+      ;
+
+
+    function tavr32attreader.is_register(const s:string):boolean;
+      type
+        treg2str = record
+          name : string[2];
+          reg : tregister;
+        end;
+
+      const
+        extraregs : array[0..3] of treg2str = (
+          (name: 'FP'; reg : NR_R11),
+          (name: 'SP'; reg : NR_R13),
+          (name: 'LR'; reg : NR_R14),
+          (name: 'PC'; reg : NR_R15));
+
+      var
+        i : longint;
+
+      begin
+        result:=inherited is_register(s);
+        { reg found?
+          possible aliases are always 2 char
+        }
+        if result or (length(s)<>2) then
+          exit;
+        for i:=low(extraregs) to high(extraregs) do
+          begin
+            if s=extraregs[i].name then
+              begin
+                actasmregister:=extraregs[i].reg;
+                result:=true;
+                actasmtoken:=AS_REGISTER;
+                exit;
+              end;
+          end;
+      end;
+
+
+    procedure tavr32attreader.ReadSym(oper : tavr32operand);
+      var
+         tempstr, mangledname : string;
+         typesize,l,k : longint;
+      begin
+        tempstr:=actasmpattern;
+        Consume(AS_ID);
+        { typecasting? }
+        if (actasmtoken=AS_LPAREN) and
+           SearchType(tempstr,typesize) then
+          begin
+            oper.hastype:=true;
+            Consume(AS_LPAREN);
+            BuildOperand(oper);
+            Consume(AS_RPAREN);
+            if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+              oper.SetSize(typesize,true);
+          end
+        else
+          if not oper.SetupVar(tempstr,false) then
+            Message1(sym_e_unknown_id,tempstr);
+        { record.field ? }
+        if actasmtoken=AS_DOT then
+          begin
+            BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+            if (mangledname<>'') then
+              Message(asmr_e_invalid_reference_syntax);
+            inc(oper.opr.ref.offset,l);
+          end;
+      end;
+
+
+    Procedure tavr32attreader.BuildReference(oper : tavr32operand);
+
+      procedure do_error;
+        begin
+          Message(asmr_e_invalid_reference_syntax);
+          RecoverConsume(false);
+        end;
+
+
+      procedure test_end(require_rbracket : boolean);
+        begin
+          if require_rbracket then begin
+            if not(actasmtoken=AS_RBRACKET) then 
+              begin 
+                do_error; 
+                exit; 
+              end
+            else 
+              Consume(AS_RBRACKET);
+          end;
+          if not(actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_end]) then
+            do_error
+          else 
+            begin
+{$IFDEF debugasmreader}
+              writeln('TEST_end_FINAL_OK. Created the following ref:');
+              writeln('oper.opr.ref.shiftimm=',oper.opr.ref.shiftimm);
+              writeln('oper.opr.ref.shiftmode=',ord(oper.opr.ref.shiftmode));
+              writeln('oper.opr.ref.index=',ord(oper.opr.ref.index));
+              writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
+              writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
+              writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
+              writeln;
+{$endIF debugasmreader}
+            end;
+        end;
+
+
+      procedure read_index_shift(require_rbracket : boolean);
+        begin
+          case actasmtoken of
+            AS_SHL :
+              begin
+                Consume(AS_SHL);
+                oper.opr.ref.scalefactor := 1 shl BuildConstExpression(false,true);
+                if (oper.opr.ref.scalefactor<1) or (oper.opr.ref.scalefactor>8) then
+                  do_error;
+                test_end(require_rbracket);
+              end;
+            AS_RBRACKET : 
+              if require_rbracket then 
+                test_end(require_rbracket)
+              else 
+                begin 
+                  do_error; 
+                  exit; 
+                end;
+            AS_SEPARATOR,AS_END : 
+              if not require_rbracket then 
+                test_end(false)
+               else 
+                 do_error; 
+            else 
+              begin
+                do_error; 
+                exit;
+              end;
+          end;
+        end;
+
+
+      procedure read_index(require_rbracket : boolean);
+        var 
+          recname : string;
+          o_int,s_int : aint;
+        begin
+          case actasmtoken of
+            AS_REGISTER : 
+              begin
+                oper.opr.ref.index:=actasmregister;
+                oper.opr.ref.indexselector:=RS_None;
+                Consume(AS_REGISTER);
+                if actasmtoken=AS_COLON then
+                  oper.opr.ref.indexselector:=read_selector;
+                read_index_shift(require_rbracket);
+                exit;
+              end;
+            AS_PLUS,AS_MINUS,AS_INTNUM: // constant
+              begin
+                o_int := BuildConstExpression(false,true);
+                if not in_signed_bits(o_int,16) then
+                  begin
+                    Message(asmr_e_constant_out_of_bounds);
+                    RecoverConsume(false);
+                    exit;
+                  end 
+                else 
+                  begin
+                    inc(oper.opr.ref.offset,o_int);
+                    test_end(require_rbracket);
+                    exit;
+                  end;
+              end;
+            AS_ID :
+              begin
+                recname := actasmpattern;
+                Consume(AS_ID);
+                BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
+                if not in_signed_bits(o_int,16) then
+                  begin
+                    Message(asmr_e_constant_out_of_bounds);
+                    RecoverConsume(false);
+                    exit;
+                  end 
+                else 
+                  begin
+                    inc(oper.opr.ref.offset,o_int);
+                    test_end(require_rbracket);
+                    exit;
+                  end;
+              end;
+            AS_AT: 
+              begin
+                do_error;
+                exit;
+              end;
+            AS_DOT : // local label
+              begin
+                oper.opr.ref.offset := BuildConstExpression(true,false);
+                test_end(require_rbracket);
+                exit;
+              end;
+            AS_RBRACKET :
+              begin
+                if require_rbracket then 
+                  begin
+                    test_end(require_rbracket);
+                    exit;
+                  end 
+                else 
+                  begin
+                    do_error; // unexpected rbracket
+                    exit;
+                  end;
+              end;
+            AS_SEPARATOR,AS_end : 
+              begin
+                if not require_rbracket then 
+                  begin
+                    test_end(false);
+                    exit;
+                  end 
+                else 
+                  begin
+                    do_error; 
+                    exit;
+                  end;
+              end;
+            else 
+              begin
+                // unexpected token
+                do_error; 
+                exit;
+              end;
+          end; // case
+        end;
+ 
+      var 
+        lab : TASMLABEL;
+      begin
+        oper.InitRef;
+        case actasmtoken of
+          AS_MINUSMINUS:
+            begin
+              oper.opr.ref.addressmode:=AM_PREINDEXED;
+              consume(AS_MINUSMINUS);
+
+              oper.opr.ref.base:=actasmregister;
+              Consume(AS_REGISTER);
+            end;
+          AS_REGISTER:
+            begin
+              oper.opr.ref.base:=actasmregister;
+              Consume(AS_REGISTER);
+
+              if actasmtoken=AS_PLUSPLUS then
+                begin
+                  oper.opr.ref.addressmode:=AM_POSTINDEXED;
+                  consume(AS_PLUSPLUS);
+                end
+              else if actasmtoken=AS_LBRACKET then
+                begin
+                  consume(AS_LBRACKET);
+                  read_index(true);
+                end;
+            end;
+        end;
+      end;
+
+    procedure tavr32attreader.BuildRegset(oper: tavr32operand);
+      var
+        tempreg : tregister;
+        ireg : tsuperregister;
+        regtype: tregistertype;
+        subreg: tsubregister;
+        {ofs : longint;}
+        registerset : tcpuregisterset;
+      begin
+        registerset:=[];
+        regtype:=R_INVALIDREGISTER;
+        subreg:=R_SUBNONE;
+        while true do
+          begin
+            if actasmtoken=AS_REGISTER then
+              begin
+                include(registerset,getsupreg(actasmregister));
+                if regtype<>R_INVALIDREGISTER then
+                  begin
+                    if (getregtype(actasmregister)<>regtype) or
+                       (getsubreg(actasmregister)<>subreg) then
+                      Message(asmr_e_mixing_regtypes);
+                  end
+                else
+                  begin
+                    regtype:=getregtype(actasmregister);
+                    subreg:=getsubreg(actasmregister);
+                  end;
+                tempreg:=actasmregister;
+                consume(AS_REGISTER);
+                if actasmtoken=AS_MINUS then
+                  begin
+                    consume(AS_MINUS);
+                    for ireg:=getsupreg(tempreg) to getsupreg(actasmregister) do
+                      include(registerset,ireg);
+                    consume(AS_REGISTER);
+                  end;
+              end
+            else
+              consume(AS_REGISTER);
+            if actasmtoken=AS_COMMA then
+              consume(AS_COMMA)
+            else
+              break;
+          end;
+        oper.opr.typ:=OPR_REGSET;
+        oper.opr.regtype:=regtype;
+        oper.opr.subreg:=subreg;
+        oper.opr.regset:=registerset;
+        if (registerset=[]) then
+          Message(asmr_e_empty_regset);
+      end;
+
+
+    function tavr32attreader.TryBuildShifterOp(oper : tavr32operand) : boolean;
+
+      procedure handlepara(sm : tshiftmode);
+        begin
+          consume(actasmtoken);
+          fillchar(oper.opr,sizeof(oper.opr),0);
+          oper.opr.typ:=OPR_SHIFTEROP;
+          oper.opr.shifterop.shiftmode:=sm;
+          case actasmtoken of
+            AS_INTNUM,
+            AS_PLUS,
+            AS_MINUS:
+              oper.opr.shifterop.shiftimm:=BuildConstExpression(false,false);
+            else
+              Message(asmr_e_illegal_shifterop_syntax);
+          end;
+        end;
+
+      begin
+        result:=true;
+        if (actasmtoken in [AS_SHL,AS_SHR]) then
+          begin
+            if (actasmtoken=AS_SHL) then
+              handlepara(SM_LSL)
+            else if (actasmtoken=AS_SHR) then
+              handlepara(SM_LSR)
+            else
+              result:=false;
+          end
+        else
+          result:=false;
+      end;
+
+
+    Procedure tavr32attreader.BuildOperand(oper : tavr32operand);
+      var
+        expr : string;
+        typesize,l : longint;
+
+
+        procedure AddLabelOperand(hl:tasmlabel);
+          begin
+            if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+               is_calljmp(actopcode) then
+             begin
+               oper.opr.typ:=OPR_SYMBOL;
+               oper.opr.symbol:=hl;
+             end
+            else
+             begin
+               oper.InitRef;
+               oper.opr.ref.symbol:=hl;
+             end;
+          end;
+
+
+        procedure MaybeRecordOffset;
+          var
+            mangledname: string;
+            hasdot  : boolean;
+            l,
+            toffset,
+            tsize   : longint;
+          begin
+            if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+             exit;
+            l:=0;
+            hasdot:=(actasmtoken=AS_DOT);
+            if hasdot then
+              begin
+                if expr<>'' then
+                  begin
+                    BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+                    if (oper.opr.typ<>OPR_CONSTANT) and
+                       (mangledname<>'') then
+                      Message(asmr_e_wrong_sym_type);
+                    inc(l,toffset);
+                    oper.SetSize(tsize,true);
+                  end;
+              end;
+            if actasmtoken in [AS_PLUS,AS_MINUS] then
+              inc(l,BuildConstExpression(true,false));
+            case oper.opr.typ of
+              OPR_LOCAL :
+                begin
+                  { don't allow direct access to fields of parameters, because that
+                    will generate buggy code. Allow it only for explicit typecasting }
+                  if hasdot and
+                     (not oper.hastype) and
+                     (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+                     (current_procinfo.procdef.proccalloption<>pocall_register) then
+                    Message(asmr_e_cannot_access_field_directly_for_parameters);
+                  inc(oper.opr.localsymofs,l)
+                end;
+              OPR_CONSTANT :
+                inc(oper.opr.val,l);
+              OPR_REFERENCE :
+                if (mangledname<>'') then
+                  begin
+                    if (oper.opr.val<>0) then
+                      Message(asmr_e_wrong_sym_type);
+                    oper.opr.typ:=OPR_SYMBOL;
+                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+                  end
+                else
+                  inc(oper.opr.val,l);
+              OPR_SYMBOL:
+                Message(asmr_e_invalid_symbol_ref);
+              else
+                internalerror(200309221);
+            end;
+          end;
+
+
+        function MaybeBuildReference:boolean;
+          { Try to create a reference, if not a reference is found then false
+            is returned }
+          begin
+            MaybeBuildReference:=true;
+            case actasmtoken of
+              AS_INTNUM,
+              AS_MINUS,
+              AS_PLUS:
+                Begin
+                  oper.opr.ref.offset:=BuildConstExpression(True,False);
+                  if actasmtoken<>AS_LPAREN then
+                    Message(asmr_e_invalid_reference_syntax)
+                  else
+                    BuildReference(oper);
+                end;
+              AS_LPAREN:
+                BuildReference(oper);
+              AS_ID: { only a variable is allowed ... }
+                Begin
+                  ReadSym(oper);
+                  case actasmtoken of
+                    AS_end,
+                    AS_SEPARATOR,
+                    AS_COMMA: ;
+                    AS_LPAREN:
+                      BuildReference(oper);
+                  else
+                    Begin
+                      Message(asmr_e_invalid_reference_syntax);
+                      Consume(actasmtoken);
+                    end;
+                  end; {end case }
+                end;
+              else
+               MaybeBuildReference:=false;
+            end; { end case }
+          end;
+
+      var
+        tempreg : tregister;
+        hl : tasmlabel;
+      Begin
+        expr:='';
+        case actasmtoken of
+          AS_INTNUM,
+          AS_MINUS,
+          AS_PLUS:
+            BuildConstantOperand(oper);
+
+          AS_ID: { A constant expression, or a Variable ref.  }
+            Begin
+              { Local Label ? }
+              if is_locallabel(actasmpattern) then
+               begin
+                 CreateLocalLabel(actasmpattern,hl,false);
+                 Consume(AS_ID);
+                 AddLabelOperand(hl);
+               end
+              else
+               { Check for label }
+               if SearchLabel(actasmpattern,hl,false) then
+                begin
+                  Consume(AS_ID);
+                  AddLabelOperand(hl);
+                end
+              else
+               { probably a variable or normal expression }
+               { or a procedure (such as in CALL ID)      }
+               Begin
+                 { is it a constant ? }
+                 if SearchIConstant(actasmpattern,l) then
+                  Begin
+                    if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+                     Message(asmr_e_invalid_operand_type);
+                    BuildConstantOperand(oper);
+                  end
+                 else
+                  begin
+                    expr:=actasmpattern;
+                    Consume(AS_ID);
+                    { typecasting? }
+                    if (actasmtoken=AS_LPAREN) and
+                       SearchType(expr,typesize) then
+                     begin
+                       oper.hastype:=true;
+                       Consume(AS_LPAREN);
+                       BuildOperand(oper);
+                       Consume(AS_RPAREN);
+                       if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+                         oper.SetSize(typesize,true);
+                     end
+                    else
+                     begin
+                       if not(oper.SetupVar(expr,false)) then
+                        Begin
+                          { look for special symbols ... }
+                          if expr= '__HIGH' then
+                            begin
+                              consume(AS_LPAREN);
+                              if not oper.setupvar('high'+actasmpattern,false) then
+                                Message1(sym_e_unknown_id,'high'+actasmpattern);
+                              consume(AS_ID);
+                              consume(AS_RPAREN);
+                            end
+                          else
+                           if expr = '__RESULT' then
+                            oper.SetUpResult
+                          else
+                           if expr = '__SELF' then
+                            oper.SetupSelf
+                          else
+                           if expr = '__OLDEBP' then
+                            oper.SetupOldEBP
+                          else
+                            Message1(sym_e_unknown_id,expr);
+                        end;
+                     end;
+                  end;
+                  if actasmtoken=AS_DOT then
+                    MaybeRecordOffset;
+                  { add a constant expression? }
+                  if (actasmtoken=AS_PLUS) then
+                   begin
+                     l:=BuildConstExpression(true,false);
+                     case oper.opr.typ of
+                       OPR_CONSTANT :
+                         inc(oper.opr.val,l);
+                       OPR_LOCAL :
+                         inc(oper.opr.localsymofs,l);
+                       OPR_REFERENCE :
+                         inc(oper.opr.ref.offset,l);
+                       else
+                         internalerror(200309202);
+                     end;
+                   end
+               end;
+              { Do we have a indexing reference, then parse it also }
+              if actasmtoken=AS_LPAREN then
+                BuildReference(oper);
+            end;
+
+          { Register, a variable reference or a constant reference  }
+          AS_REGISTER:
+            Begin
+              { save the type of register used. }
+              tempreg:=actasmregister;
+              Consume(AS_REGISTER);
+              if (actasmtoken = AS_COLON) then
+                begin
+                  oper.opr.typ:=OPR_REGISTERSELECTOR;
+                  oper.opr.topreg:=tempreg;
+                  oper.opr.selector:=read_selector;
+                end
+              else if (actasmtoken in [AS_SHL,AS_SHR,AS_END,AS_SEPARATOR,AS_COMMA]) then
+                Begin
+                  if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+                    Message(asmr_e_invalid_operand_type);
+
+                  oper.opr.typ:=OPR_REGISTER;
+                  oper.opr.reg:=tempreg;
+                end
+              else
+                Message(asmr_e_syn_operand);
+            end;
+
+          AS_end,
+          AS_SEPARATOR,
+          AS_COMMA: ;
+        else
+          Begin
+            Message(asmr_e_syn_operand);
+            Consume(actasmtoken);
+          end;
+        end; { end case }
+      end;
+
+
+{*****************************************************************************
+                                tavr32attreader
+*****************************************************************************}
+
+    procedure tavr32attreader.BuildOpCode(instr : tavr32instruction);
+      var
+        operandnum : longint;
+      Begin
+        { opcode }
+        if (actasmtoken<>AS_OPCODE) then
+         Begin
+           Message(asmr_e_invalid_or_missing_opcode);
+           RecoverConsume(true);
+           exit;
+         end;
+        { Fill the instr object with the current state }
+        with instr do
+          begin
+            Opcode:=ActOpcode;
+            condition:=ActCondition;
+            oppostfix:=actoppostfix;
+          end;
+
+        { We are reading operands, so opcode will be an AS_ID }
+        operandnum:=1;
+        Consume(AS_OPCODE);
+        { Zero operand opcode ?  }
+        if actasmtoken in [AS_SEPARATOR,AS_end] then
+         begin
+           operandnum:=0;
+           exit;
+         end;
+        { Read the operands }
+        repeat
+          case actasmtoken of
+            AS_SHL,AS_SHR:
+              begin
+                if not(TryBuildShifterOp(instr.Operands[operandnum+1] as tavr32operand)) then
+                  Message(asmr_e_illegal_shifterop_syntax);
+                Inc(operandnum);
+              end;
+            AS_COMMA: { Operand delimiter }
+              Begin
+                if (instr.opcode in [A_ANDL,A_ANDH]) and
+                   (operandnum=2) then
+                  begin
+                    consume(AS_COMMA);
+                    if (actasmtoken=AS_ID) and
+                       (actasmpattern='COH') then
+                      begin
+                        consume(AS_ID);
+                        (instr.operands[operandnum+1] as Tavr32Operand).opr.typ:=OPR_COH;
+                        Inc(operandnum);
+                      end
+                    else
+                      message(asmr_e_invalid_operand_type);
+                  end
+                else
+                  if (instr.opcode in [A_LD,A_LDDPC,A_LDDSP,A_LDINS,A_LDSWP]) and
+                     (operandnum=1) then
+                  begin
+                    Consume(AS_COMMA);
+                    BuildReference(instr.operands[operandnum+1] as Tavr32Operand);
+                    Inc(operandnum);
+                  end
+                else
+                  if (instr.opcode in [A_LDM,A_LDMTS,A_STM,A_STMTS]) and
+                     (operandnum=1) then
+                  begin
+                    Consume(AS_COMMA);
+                    BuildRegset(instr.operands[operandnum+1] as Tavr32Operand);
+                    Inc(operandnum);
+                  end
+                else
+                  if ((instr.opcode=A_MOV) and (operandnum=2)) or
+                     ((operandnum=3) and not(instr.opcode in [A_ADD,A_AND])) then
+                  begin
+                    Consume(AS_COMMA);
+                    if not(TryBuildShifterOp(instr.Operands[operandnum+1] as tavr32operand)) then
+                      Message(asmr_e_illegal_shifterop_syntax);
+                    Inc(operandnum);
+                  end
+                else
+                  begin
+                    if operandnum>Max_Operands then
+                      Message(asmr_e_too_many_operands)
+                    else
+                      Inc(operandnum);
+                    Consume(AS_COMMA);
+                  end;
+              end;
+            AS_SEPARATOR,
+            AS_end : { End of asm operands for this opcode  }
+              begin
+                break;
+              end;
+          else
+            if (instr.opcode in [A_ST,A_STDSP,A_STHH,A_STSWP,A_LDM,A_LDMTS,A_STM,A_STMTS]) and
+               (operandnum=1) then
+              BuildReference(instr.operands[operandnum] as Tavr32Operand)
+            else if (instr.opcode in [A_PUSHM,A_POPM]) and
+                    (operandnum=1) then
+              BuildRegset(instr.operands[operandnum] as Tavr32Operand)
+            else
+              BuildOperand(instr.Operands[operandnum] as tavr32operand);
+          end; { end case }
+        until false;
+        instr.Ops:=operandnum;
+      end;
+
+
+    function tavr32attreader.is_asmopcode(const s: string):boolean;
+
+      const
+        { sorted by length so longer postfixes will match first }
+        postfix2strsorted : array[1..11] of string[3] = (
+          'UB','UH',
+          'SB','SH',
+          'W','H','D',
+          'T','U','L','B');
+
+        postfixsorted : array[1..11] of TOpPostfix = (
+          PF_UB,PF_UH,
+          PF_SB,PF_SH,
+          PF_W,PF_H,PF_D,
+          PF_T,PF_U,PF_L,PF_B);
+
+      var
+        j  : longint;
+        hs : string;
+        maxlen : longint;
+        icond : tasmcond;
+      Begin
+        { making s a value parameter would break other assembler readers }
+        hs:=s;
+        is_asmopcode:=false;
+
+        { clear op code }
+        actopcode:=A_None;
+
+        actcondition:=C_None;
+
+        { first, handle B else BLS is read wrong }
+        if ((hs[1]='B') and (hs[2]='R') and (length(hs)=4)) then
+          begin
+            for icond:=low(tasmcond) to high(tasmcond) do
+              begin
+                if copy(hs,2,3)=uppercond2str[icond] then
+                  begin
+                    actopcode:=A_BR;
+                    actasmtoken:=AS_OPCODE;
+                    actcondition:=icond;
+                    is_asmopcode:=true;
+                    exit;
+                  end;
+              end;
+          end;
+        maxlen:=max(length(hs),5);
+        actopcode:=A_NONE;
+        for j:=maxlen downto 1 do
+          begin
+            actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
+            if actopcode<>A_NONE then
+              begin
+                actasmtoken:=AS_OPCODE;
+                { strip op code }
+                delete(hs,1,j);
+                break;
+              end;
+          end;
+        if actopcode=A_NONE then
+          exit;
+			 
+        { search for condition, conditions are always 2 chars }
+        if length(hs)>1 then
+          begin
+            for icond:=low(tasmcond) to high(tasmcond) do
+              begin
+                if copy(hs,1,2)=uppercond2str[icond] then
+                  begin
+                    actcondition:=icond;
+                    { strip condition }
+                    delete(hs,1,2);
+                    break;
+                  end;
+              end;
+          end;
+        { check for postfix }
+        if (length(hs)>1) and
+           (hs[1] = '.') then
+          begin
+            for j:=low(postfixsorted) to high(postfixsorted) do
+              begin
+                if copy(hs,2,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                  begin
+                    actoppostfix:=postfixsorted[j];
+                    { strip postfix }
+                    delete(hs,1,1+length(postfix2strsorted[j]));
+                    break;
+                  end;
+              end;
+          end;
+        { if we stripped all postfixes, it's a valid opcode }
+        is_asmopcode:=length(hs)=0;
+      end;
+
+
+    procedure tavr32attreader.ConvertCalljmp(instr : tavr32instruction);
+      var
+        newopr : toprrec;
+      begin
+        if instr.Operands[1].opr.typ=OPR_REFERENCE then
+          begin
+            newopr.typ:=OPR_SYMBOL;
+            newopr.symbol:=instr.Operands[1].opr.ref.symbol;
+            newopr.symofs:=instr.Operands[1].opr.ref.offset;
+            if (instr.Operands[1].opr.ref.base<>NR_NO) or
+              (instr.Operands[1].opr.ref.index<>NR_NO) then
+              Message(asmr_e_syn_operand);
+            instr.Operands[1].opr:=newopr;
+          end;
+      end;
+
+    function tavr32attreader.read_selector: tregisterselector;
+      begin
+        consume(AS_COLON);
+        if not ((actasmtoken=AS_ID) and
+                (length(actasmpattern)=1)) then
+          message(asmr_e_invalid_operand_type);
+
+        case actasmpattern[1] of
+          'B':
+            read_selector:=RS_B;
+          'L':
+            read_selector:=RS_L;
+          'U':
+            read_selector:=RS_U;
+          'T':
+            read_selector:=RS_T;
+          else
+            message(asmr_e_invalid_operand_type);
+        end;
+        consume(AS_ID);
+      end;
+
+
+    procedure tavr32attreader.handleopcode;
+      var
+        instr : tavr32instruction;
+      begin
+        instr:=Tavr32Instruction.Create(Tavr32Operand);
+        BuildOpcode(instr);
+        if is_calljmp(instr.opcode) then
+          ConvertCalljmp(instr);
+        {
+        instr.AddReferenceSizes;
+        instr.SetInstructionOpsize;
+        instr.CheckOperandSizes;
+        }
+        instr.ConcatInstruction(curlist);
+        instr.Free;
+        actoppostfix:=PF_None;
+      end;
+
+
+{*****************************************************************************
+                                     Initialize
+*****************************************************************************}
+
+const
+  asmmode_avr32_att_info : tasmmodeinfo =
+          (
+            id    : asmmode_avr32_gas;
+            idtxt : 'GAS';
+            casmreader : tavr32attreader;
+          );
+
+  asmmode_avr32_standard_info : tasmmodeinfo =
+          (
+            id    : asmmode_standard;
+            idtxt : 'STANDARD';
+            casmreader : tavr32attreader;
+          );
+
+initialization
+  RegisterAsmMode(asmmode_avr32_att_info);
+  RegisterAsmMode(asmmode_avr32_standard_info);
+end.

+ 18 - 0
compiler/avr32/ravr32con.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);

+ 18 - 0
compiler/avr32/ravr32dwa.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15

+ 2 - 0
compiler/avr32/ravr32nor.inc

@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from avr32reg.dat }
+17

+ 18 - 0
compiler/avr32/ravr32num.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f)

+ 18 - 0
compiler/avr32/ravr32rni.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16

+ 18 - 0
compiler/avr32/ravr32sri.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+0,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10

+ 18 - 0
compiler/avr32/ravr32sta.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15

+ 18 - 0
compiler/avr32/ravr32std.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15'

+ 18 - 0
compiler/avr32/ravr32sup.inc

@@ -0,0 +1,18 @@
+{ don't edit, this file is generated from avr32reg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;

+ 159 - 0
compiler/avr32/rgcpu.pas

@@ -0,0 +1,159 @@
+{
+    Copyright (c) 1998-2003 by Florian Klaempfl
+
+    This unit implements the arm specific class for the register
+    allocator
+
+    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 rgcpu;
+
+{$i fpcdefs.inc}
+
+  interface
+
+     uses
+       aasmbase,aasmtai,aasmdata,aasmcpu,
+       cgbase,cgutils,
+       cpubase,
+       rgobj;
+
+     type
+       trgcpu = class(trgobj)
+         procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+         procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+       end;
+
+       trgintcpu = class(trgcpu)
+       end;
+
+  implementation
+
+    uses
+      verbose, cutils,globtype,
+      cgobj,
+      procinfo;
+
+
+    procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+      var
+        tmpref : treference;
+        helplist : TAsmList;
+        l : tasmlabel;
+        hreg : tregister;
+      begin
+        { don't load spilled register between
+          mov lr,pc
+          mov pc,r4
+          but befure the mov lr,pc
+        }
+        if assigned(pos.previous) and
+          (pos.typ=ait_instruction) and
+          (taicpu(pos).opcode=A_MOV) and
+          (taicpu(pos).oper[0]^.typ=top_reg) and
+          (taicpu(pos).oper[0]^.reg=NR_R14) and
+          (taicpu(pos).oper[1]^.typ=top_reg) and
+          (taicpu(pos).oper[1]^.reg=NR_PC) then
+          pos:=tai(pos.previous);
+
+        if in_signed_bits(spilltemp.offset,16) then
+          begin
+            {helplist:=TAsmList.create;
+            reference_reset(tmpref,sizeof(aint));
+            { create consts entry }
+            current_asmdata.getjumplabel(l);
+            cg.a_label(current_procinfo.aktlocaldata,l);
+            tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+            current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+            { load consts entry }
+            if getregtype(tempreg)=R_INTREGISTER then
+              hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+            else
+              hreg:=cg.getintregister(helplist,OS_ADDR);
+
+            tmpref.symbol:=l;
+            tmpref.base:=NR_R15;
+            helplist.concat(setoppostfix(taicpu.op_reg_ref(A_LD,hreg,tmpref),PF_W));
+
+            reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(aint));
+            tmpref.index:=hreg;
+
+            if spilltemp.index<>NR_NO then
+              internalerror(200401263);
+
+            helplist.concat(spilling_create_load(tmpref,tempreg));
+            if getregtype(tempreg)=R_INTREGISTER then
+              ungetregisterinline(helplist,hreg);
+
+            list.insertlistafter(pos,helplist);
+            helplist.free;      }
+          end
+        else
+          inherited do_spill_read(list,pos,spilltemp,tempreg);
+      end;
+
+
+    procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+      var
+        tmpref : treference;
+        helplist : TAsmList;
+        l : tasmlabel;
+        hreg : tregister;
+      begin
+        if in_signed_bits(spilltemp.offset,16) then
+          begin
+            {helplist:=TAsmList.create;
+            reference_reset(tmpref,sizeof(aint));
+            { create consts entry }
+            current_asmdata.getjumplabel(l);
+            cg.a_label(current_procinfo.aktlocaldata,l);
+            tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+            current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+            { load consts entry }
+            if getregtype(tempreg)=R_INTREGISTER then
+              hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+            else
+              hreg:=cg.getintregister(helplist,OS_ADDR);
+            tmpref.symbol:=l;
+            tmpref.base:=NR_R15;
+            helplist.concat(setoppostfix(taicpu.op_reg_ref(A_LD,hreg,tmpref),PF_W));
+
+            if spilltemp.index<>NR_NO then
+              internalerror(200401263);
+
+            reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(pint));
+            tmpref.index:=hreg;
+
+            helplist.concat(spilling_create_store(tempreg,tmpref));
+
+            if getregtype(tempreg)=R_INTREGISTER then
+              ungetregisterinline(helplist,hreg);
+
+            list.insertlistafter(pos,helplist);
+            helplist.free;}
+          end
+        else
+          inherited do_spill_written(list,pos,spilltemp,tempreg);
+      end;
+
+
+end.

+ 4 - 4
compiler/cgobj.pas

@@ -757,12 +757,12 @@ implementation
     procedure tcg.allocallcpuregisters(list:TAsmList);
       begin
         alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
-{$if not(defined(i386)) and not(defined(avr))}
+{$if not(defined(i386)) and not(defined(avr)) and not(defined(avr32))}
         alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
 {$ifdef cpumm}
         alloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
 {$endif cpumm}
-{$endif not(defined(i386)) and not(defined(avr))}
+{$endif not(defined(i386)) and not(defined(avr)) and not(defined(avr32))}
       end;
 
 
@@ -778,12 +778,12 @@ implementation
     procedure tcg.deallocallcpuregisters(list:TAsmList);
       begin
         dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
-{$if not(defined(i386)) and not(defined(avr))}
+{$if not(defined(i386)) and not(defined(avr)) and not(defined(avr32))}
         dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
 {$ifdef cpumm}
         dealloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
 {$endif cpumm}
-{$endif not(defined(i386)) and not(defined(avr))}
+{$endif not(defined(i386)) and not(defined(avr)) and not(defined(avr32))}
       end;
 
 

+ 5 - 0
compiler/cgutils.pas

@@ -56,6 +56,11 @@ unit cgutils;
 {$ifdef avr}
          addressmode : taddressmode;
 {$endif avr}
+{$ifdef avr32}
+         symboldata  : tlinkedlistitem;
+         addressmode : taddressmode;
+         indexselector : tregisterselector;
+{$endif avr32}
 {$ifdef m68k}
          { indexed increment and decrement mode }
          { (An)+ and -(An)                      }

+ 9 - 0
compiler/fpcdefs.inc

@@ -132,6 +132,15 @@
   {$define cpuneedsmulhelper}
 {$endif avr}
 
+{$ifdef avr32}
+  {$define cpu32bit}
+  {$define cpu32bitaddr}
+  {$define cpu32bitalu}
+  {$define cpuflags}
+  {$define cpufpemu}
+  { $define cputargethasfixedstack}
+{$endif avr32}
+
 {$ifdef mipsel}
   {$define mips}
 {$endif mipsel}

+ 11 - 6
compiler/globals.pas

@@ -140,9 +140,9 @@ interface
          disabledircache : boolean;
 
         { CPU targets with microcontroller support can add a controller specific unit }
-{$if defined(ARM) or defined(AVR)}
+{$if defined(ARM) or defined(AVR) or defined(AVR32)}
         controllertype   : tcontrollertype;
-{$endif defined(ARM) or defined(AVR)}
+{$endif defined(ARM) or defined(AVR) or defined(AVR32)}
        end;
 
     const
@@ -413,6 +413,11 @@ interface
         optimizecputype : cpuinfo.cpu_avr5;
         fputype : fpu_none;
   {$endif avr}
+  {$ifdef avr32}
+        cputype : cpuinfo.cpu_avr32a;
+        optimizecputype : cpuinfo.cpu_avr32a;
+        fputype : fpu_none;
+  {$endif avr32}
   {$ifdef mips}
         cputype : cpu_mips32;
         optimizecputype : cpu_mips32;
@@ -459,9 +464,9 @@ interface
     function Setabitype(const s:string;var a:tabi):boolean;
     function Setcputype(const s:string;var a:tcputype):boolean;
     function SetFpuType(const s:string;var a:tfputype):boolean;
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(avr32)}
     function SetControllerType(const s:string;var a:tcontrollertype):boolean;
-{$endif defined(arm) or defined(avr)}
+{$endif defined(arm) or defined(avr) or defined(avr32)}
     function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
     function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
     function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
@@ -1094,7 +1099,7 @@ implementation
       end;
 
 
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(avr32)}
     function SetControllerType(const s:string;var a:tcontrollertype):boolean;
       var
         t  : tcontrollertype;
@@ -1110,7 +1115,7 @@ implementation
               break;
             end;
       end;
-{$endif defined(arm) or defined(avr)}
+{$endif defined(arm) or defined(avr) or defined(avr32)}
 
 
     function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;

+ 11 - 6
compiler/ncgutil.pas

@@ -1868,7 +1868,7 @@ implementation
         paraloc  : pcgparalocation;
         href     : treference;
         sizeleft : aint;
-{$if defined(sparc) or defined(arm)}
+{$if defined(sparc) or defined(arm) or defined(avr32)}
         tempref  : treference;
 {$endif sparc}
 {$ifndef cpu64bitalu}
@@ -1975,8 +1975,8 @@ implementation
           LOC_FPUREGISTER,
           LOC_CFPUREGISTER :
             begin
-{$if defined(sparc) or defined(arm)}
-              { Arm and Sparc passes floats in int registers, when loading to fpu register
+{$if defined(sparc) or defined(arm) or defined(avr32)}
+              { Arm, Avr32 and Sparc passes floats in int registers, when loading to fpu register
                 we need a temp }
               sizeleft := TCGSize2Size[destloc.size];
               tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref);
@@ -3116,10 +3116,10 @@ implementation
     procedure InsertInterruptTable;
 
       procedure WriteVector(const name: string);
-{$IFDEF arm}
+{$IF defined(arm) or defined(avr32)}
         var
           ai: taicpu;
-{$ENDIF arm}
+{$ENDIF}
         begin
 {$IFDEF arm}
           if current_settings.cputype in [cpu_armv7m, cpu_cortexm3] then
@@ -3131,11 +3131,16 @@ implementation
               current_asmdata.asmlists[al_globals].concat(ai);
             end;
 {$ENDIF arm}
+{$IFDEF avr32}
+          ai:=taicpu.op_sym(A_RJMP,current_asmdata.RefAsmSymbol(name));
+          ai.is_jmp:=true;
+          current_asmdata.asmlists[al_globals].concat(ai);
+{$ENDIF avr32}
         end;
 
       function GetInterruptTableLength: longint;
         begin
-{$if defined(ARM)}
+{$if defined(ARM) or defined(AVR32)}
           result:=interruptvectors[current_settings.controllertype];
 {$else}
           result:=0;

+ 17 - 10
compiler/options.pas

@@ -181,9 +181,9 @@ var
   opt : toptimizerswitch;
   wpopt: twpoptimizerswitch;
   abi : tabi;
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(avr32)}
   controllertype : tcontrollertype;
-{$endif defined(arm) or defined(avr)}
+{$endif defined(arm) or defined(avr) or defined(avr32)}
 begin
   p:=MessagePchar(option_info);
   while assigned(p) do
@@ -278,7 +278,7 @@ begin
       end
      else if pos('$CONTROLLERTYPES',s)>0 then
       begin
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(avr32)}
         for controllertype:=low(tcontrollertype) to high(tcontrollertype) do
           begin
 {           currently all whole program optimizations are platform-independent
@@ -294,8 +294,8 @@ begin
                   end;
               end;
           end
-{$else defined(arm) or defined(avr)}
-{$endif defined(arm) or defined(avr)}
+{$else defined(arm) or defined(avr) or defined(avr32)}
+{$endif defined(arm) or defined(avr) or defined(avr32)}
       end
      else
       Comment(V_Normal,s);
@@ -1600,7 +1600,7 @@ begin
                       end;
                     'p':
                       begin
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(avr32)}
                         if (target_info.system in systems_embedded) then
                           begin
                             s:=upper(copy(more,j+1,length(more)-j));
@@ -1609,7 +1609,7 @@ begin
                             break;
                           end
                         else
-{$endif defined(arm) or defined(avr)}
+{$endif defined(arm) or defined(avr) or defined(avr32)}
                           IllegalPara(opt);
                       end;
                     'R':
@@ -2600,6 +2600,12 @@ begin
   def_system_macro('FPC_CURRENCY_IS_INT64');
   def_system_macro('FPC_COMP_IS_INT64');
 {$endif avr}
+{$ifdef avr32}
+  def_system_macro('CPUAVR32');
+  def_system_macro('CPU32');
+  def_system_macro('FPC_CURRENCY_IS_INT64');
+  def_system_macro('FPC_COMP_IS_INT64');
+{$endif avr32}
 
   { read configuration file }
   if (not disable_configfile) and
@@ -2802,14 +2808,15 @@ begin
     arm/darwin if fpu type not explicitly set }
   if not(option.FPUSetExplicitly) and
      ((target_info.system in [system_arm_wince,system_arm_gba,system_m68k_amiga,
-         system_m68k_linux,system_arm_nds,system_arm_embedded,system_arm_darwin])
+         system_m68k_linux,system_arm_nds,system_arm_embedded,system_arm_darwin,
+         system_avr32_embedded])
 {$ifdef arm}
       or (target_info.abi=abi_eabi)
 {$endif arm}
      )
-{$ifdef arm}
+{$if defined(arm) or defined(avr32)}
      or (init_settings.fputype=fpu_soft)
-{$endif arm}
+{$endif defined(arm) or defined(avr32)}
   then
     begin
 {$ifdef cpufpemu}

+ 2 - 2
compiler/pmodules.pas

@@ -709,10 +709,10 @@ implementation
           end;
 
         { CPU targets with microcontroller support can add a controller specific unit }
-{$if defined(ARM) or defined(AVR)}
+{$if defined(ARM) or defined(AVR) or defined(AVR32)}
         if (target_info.system in systems_embedded) and (current_settings.controllertype<>ct_none) then
           AddUnit(controllerunitstr[current_settings.controllertype]);
-{$endif ARM}
+{$endif}
       end;
 
 

+ 6 - 0
compiler/pp.pas

@@ -135,6 +135,12 @@ program pp;
   {$endif CPUDEFINED}
   {$define CPUDEFINED}
 {$endif AVR}
+{$ifdef AVR32}
+  {$ifdef CPUDEFINED}
+    {$fatal ONLY one of the switches for the CPU type must be defined}
+  {$endif CPUDEFINED}
+  {$define CPUDEFINED}
+{$endif AVR32}
 {$ifndef CPUDEFINED}
   {$fatal A CPU type switch must be defined}
 {$endif CPUDEFINED}

+ 6 - 2
compiler/psub.pas

@@ -104,7 +104,7 @@ implementation
        opttail,
        optcse,optloop,
        optutils
-{$if defined(arm) or defined(powerpc) or defined(powerpc64)}
+{$if defined(arm) or defined(avr32) or defined(powerpc) or defined(powerpc64)}
        ,aasmcpu
 {$endif arm}
        {$ifndef NOOPT}
@@ -950,7 +950,7 @@ implementation
             { set the start offset to the start of the temp area in the stack }
             tg:=ttgobj.create;
 
-{$if defined(x86) or defined(arm)}
+{$if defined(x86) or defined(arm) or defined(avr32)}
             { try to strip the stack frame }
             { set the framepointer to esp if:
               - no assembler directive, those are handled in assembler_block
@@ -1227,6 +1227,10 @@ implementation
             { because of the limited constant size of the arm, all data access is done pc relative }
             finalizearmcode(aktproccode,aktlocaldata);
 {$endif ARM}
+{$ifdef AVR32}
+            { because of the limited constant size of the arm, all data access is done pc relative }
+            finalizeavr32code(aktproccode,aktlocaldata);
+{$endif AVR32}
 
             { Add end symbol and debug info }
             { this must be done after the pcrelativedata is appended else the distance calculation of

+ 4 - 0
compiler/psystem.pas

@@ -211,6 +211,10 @@ implementation
         sc80floattype:=tfloatdef.create(sc80real);
         s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
 {$endif avr}
+{$ifdef avr32}
+        create_fpu_types;
+        s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif avr32}
 {$ifdef cpu64bitaddr}
         uinttype:=u64inttype;
         sinttype:=s64inttype;

+ 37 - 2
compiler/raatt.pas

@@ -55,7 +55,7 @@ unit raatt;
         AS_DATA,AS_TEXT,AS_INIT,AS_FINI,AS_END,
         {------------------ Assembler Operators  --------------------}
         AS_TYPE,AS_SIZEOF,AS_VMTOFFSET,AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR,AS_AT,
-        AS_LO,AS_HI);
+        AS_LO,AS_HI,AS_MINUSMINUS,AS_PLUSPLUS);
 
         tasmkeyword = string[10];
 
@@ -75,7 +75,7 @@ unit raatt;
         '.align','.balign','.p2align','.ascii',
         '.asciz','.lcomm','.comm','.single','.double','.tfloat','.tcfloat',
         '.data','.text','.init','.fini','END',
-        'TYPE','SIZEOF','VMTOFFSET','%','<<','>>','!','&','|','^','~','@','lo','hi');
+        'TYPE','SIZEOF','VMTOFFSET','%','<<','>>','!','&','|','^','~','@','lo','hi','--','++');
 
     type
        tattreader = class(tasmreader)
@@ -277,6 +277,31 @@ unit raatt;
                end
            end;
 {$endif ARM}
+{$if defined(AVR32)}
+           { AVR32 instructions can have a .** postfix to indicate operand size
+           }
+           case c of
+             '.':
+               begin
+                 actasmpattern:=actasmpattern+c;
+                 c:=current_scanner.asmgetchar;
+
+                 if upcase(c) in ['U','S','B','W','H','D'] then
+                   begin
+                     if upcase(c) in ['U','S'] then
+                       begin
+                         actasmpattern:=actasmpattern+c;
+                         c:=current_scanner.asmgetchar;
+                       end;
+                     actasmpattern:=actasmpattern+c;
+                     c:=current_scanner.asmgetchar;
+
+                   end
+                 else
+                   internalerror(2011012103);
+               end
+           end;
+{$endif AVR32}
            { Opcode ? }
            If is_asmopcode(upper(actasmpattern)) then
             Begin
@@ -685,6 +710,11 @@ unit raatt;
                begin
                  actasmtoken:=AS_PLUS;
                  c:=current_scanner.asmgetchar;
+                 if c='+' then
+                   begin
+                     actasmtoken:=AS_PLUSPLUS;
+                     c:=current_scanner.asmgetchar;
+                   end;
                  exit;
                end;
 
@@ -692,6 +722,11 @@ unit raatt;
                begin
                  actasmtoken:=AS_MINUS;
                  c:=current_scanner.asmgetchar;
+                 if c='-' then
+                   begin
+                     actasmtoken:=AS_MINUSMINUS;
+                     c:=current_scanner.asmgetchar;
+                   end;
                  exit;
                end;
 

+ 17 - 1
compiler/rautils.pas

@@ -65,7 +65,7 @@ Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
 
 type
   TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
-            OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS);
+            OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_COH,OPR_REGISTERSELECTOR);
 
   TOprRec = record
     case typ:TOprType of
@@ -90,6 +90,12 @@ type
       OPR_COND      : (cc : tasmcond);
       OPR_MODEFLAGS : (flags : tcpumodeflags);
 {$endif arm}
+{$ifdef avr32}
+      OPR_REGSET    : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister);
+      OPR_SHIFTEROP : (shifterop : tshifterop);
+      OPR_COH       : ();
+      OPR_REGISTERSELECTOR : (topreg : tregister; selector : tregisterselector);
+{$endif avr32}
   end;
 
   TOperand = class
@@ -1071,6 +1077,16 @@ end;
               OPR_MODEFLAGS:
                 ai.loadmodeflags(i-1,flags);
 {$endif ARM}
+{$ifdef AVR32}
+              OPR_REGSET:
+                ai.loadregset(i-1,regtype,subreg,regset);
+              OPR_SHIFTEROP:
+                ai.loadshifterop(i-1,shifterop);
+              OPR_COH:
+                ai.loadCOH(i-1);
+              OPR_REGISTERSELECTOR:
+                ai.loadregisterselector(i-1,topreg,selector);
+{$endif AVR32}
               { ignore wrong operand }
               OPR_NONE:
                 ;

+ 3 - 0
compiler/symdef.pas

@@ -784,6 +784,9 @@ interface
 {$ifdef AVR}
        pbestrealtype : ^tdef = @s64floattype;
 {$endif AVR}
+{$ifdef AVR32}
+       pbestrealtype : ^tdef = @s64floattype;
+{$endif AVR32}
 
     function make_mangledname(const typeprefix:string;st:TSymtable;const suffix:string):string;
 

+ 5 - 2
compiler/systems.inc

@@ -47,7 +47,8 @@
              cpu_arm,                      { 10 }
              cpu_powerpc64,                { 11 }
              cpu_avr,                      { 12 }
-             cpu_mipsel                    { 13 }
+             cpu_mipsel,                   { 13 }
+             cpu_avr32                     { 14 }
        );
 
        tasmmode= (asmmode_none
@@ -64,6 +65,7 @@
             ,asmmode_x86_64_intel
             ,asmmode_x86_64_att
             ,asmmode_avr_gas
+            ,asmmode_avr32_gas
        );
 
      (* IMPORTANT NOTE:
@@ -146,7 +148,8 @@
              system_mipsel_linux,       { 67 }
              system_i386_nativent,      { 68 }
              system_i386_iphonesim,     { 69 }
-             system_powerpc_wii         { 70 }
+             system_powerpc_wii,        { 70 }
+             system_avr32_embedded      { 71 }
        );
 
      type

+ 7 - 3
compiler/systems.pas

@@ -237,7 +237,7 @@ interface
                            system_sparc_embedded,system_vm_embedded,
                            system_iA64_embedded,system_x86_64_embedded,
                            system_mips_embedded,system_arm_embedded,
-                           system_powerpc64_embedded];
+                           system_powerpc64_embedded,system_avr32_embedded];
 
        { all symbian systems }
        systems_symbian = [system_i386_symbian,system_arm_symbian];
@@ -271,7 +271,7 @@ interface
 
        systems_internal_sysinit = [system_i386_linux,system_i386_win32];
 
-       systems_interrupt_table = [{system_arm_embedded}];
+       systems_interrupt_table = [{system_arm_embedded,system_avr32_embedded}];
 
        { all systems for which istack must be at a 16 byte boundary
          when calling a function }
@@ -286,7 +286,7 @@ interface
 
        cpu2str : array[TSystemCpu] of string[10] =
             ('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
-             'mips','arm', 'powerpc64', 'avr', 'mipsel');
+             'mips','arm', 'powerpc64', 'avr', 'mipsel', 'avr32');
 
        abi2str : array[tabi] of string[10] =
          ('DEFAULT','SYSV','AIX','EABI','ARMEB');
@@ -826,6 +826,10 @@ begin
   default_target(system_avr_embedded);
 {$endif avr}
 
+{$ifdef avr32}
+  default_target(system_avr32_embedded);
+{$endif avr32}
+
 {$ifdef mips}
 {$ifdef mipsel}
   default_target(system_mipsel_linux);

+ 67 - 0
compiler/systems/i_embed.pas

@@ -214,6 +214,68 @@ unit i_embed;
             abi : abi_default
           );
 
+       system_avr32_embedded_info : tsysteminfo =
+          (
+            system       : system_avr32_embedded;
+            name         : 'Embedded';
+            shortname    : 'embedded';
+            flags        : [tf_needs_symbol_size,tf_files_case_sensitive
+	                          ,tf_smartlink_sections];
+            cpu          : cpu_avr32;
+            unit_env     : '';
+            extradefines : '';
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.s';
+            objext       : '.o';
+            resext       : '.res';
+            resobjext    : '.or';
+            sharedlibext : '.so';
+            staticlibext : '.a';
+            staticlibprefix : 'libp';
+            sharedlibprefix : 'lib';
+            sharedClibext : '.so';
+            staticClibext : '.a';
+            staticClibprefix : 'lib';
+            sharedClibprefix : 'lib';
+            importlibprefix : 'libimp';
+            importlibext : '.a';
+            Cprefix      : '';
+            newline      : #10;
+            dirsep       : '/';
+            assem        : as_gas;
+            assemextern  : as_gas;
+            link         : nil;
+            linkextern   : nil;
+            ar           : ar_gnu_ar;
+            res          : res_none;
+            dbg          : dbg_stabs;
+            script       : script_unix;
+            endian       : endian_big;
+            alignment    :
+              (
+                procalign       : 2;
+                loopalign       : 2;
+                jumpalign       : 0;
+                constalignmin   : 0;
+                constalignmax   : 4;
+                varalignmin     : 0;
+                varalignmax     : 4;
+                localalignmin   : 2;
+                localalignmax   : 8;
+                recordalignmin  : 0;
+                recordalignmax  : 4;
+                maxCrecordalign : 4
+              );
+            first_parm_offset : 0;
+            stacksize    : 1024;
+            abi : abi_default
+          );
+
   implementation
 
 initialization
@@ -232,4 +294,9 @@ initialization
     set_source_info(system_i386_embedded_info);
   {$endif embedded}
 {$endif CPUI386}
+{$ifdef CPUAVR32}
+  {$ifdef embedded}
+    set_source_info(system_avr32_embedded_info);
+  {$endif embedded}
+{$endif CPUAVR32}
 end.

+ 140 - 1
compiler/systems/t_embed.pas

@@ -79,10 +79,13 @@ Var
   linklibc : boolean;
   found1,
   found2   : boolean;
+{$ifdef AVR32}
+  flashsize,ramsize: longword;
+{$endif AVR32}
 begin
   WriteResponseFile:=False;
   linklibc:=(SharedLibFiles.Find('c')<>nil);
-{$if defined(ARM) or defined(i386) or defined(AVR)}
+{$if defined(ARM) or defined(i386) or defined(AVR) or defined(AVR32)}
   prtobj:='';
 {$else}
   prtobj:='prt0';
@@ -565,6 +568,137 @@ begin
     end;
 {$endif AVR}
 
+{$ifdef AVR32}
+  case current_settings.controllertype of
+    ct_none:
+      ;
+    ct_at32uc3l016:
+      begin
+        flashsize:=16;
+        ramsize:=8;
+      end;
+    ct_at32uc3l032:
+      begin
+        flashsize:=32;
+        ramsize:=16;
+      end;
+    ct_at32uc3l064:
+      begin
+        flashsize:=64;
+        ramsize:=16;
+      end;
+    ct_at32uc3b1256:
+      begin
+        flashsize:=256;
+        ramsize:=32;
+      end;
+    else
+      internalerror(200902011);
+  end;
+
+
+  if current_settings.controllertype<>ct_none then
+    begin
+      with linkres do
+        begin
+          Add('ENTRY(_START)');
+          Add('MEMORY');
+          Add('{');
+          Add(Format('    flash : ORIGIN = 0x80000000, LENGTH = %DK',[flashsize]));
+          Add(Format('    ram : ORIGIN = 0, LENGTH = %DK',[ramsize]));
+          Add('}');
+          Add(format('_stack_top = 0x%X;',[ramsize*1024-4]));
+        end;
+    end;
+
+  with linkres do
+    begin
+      Add('SECTIONS');
+      Add('{');
+      Add('  .rel.init      : { *(.rel.init)		}');
+      Add('  .rela.init     : { *(.rela.init)	}');
+      Add('  .rel.text      :');
+      Add('    {');
+      Add('      *(.rel.text)');
+      Add('      *(.rel.text.*)');
+      Add('      *(.rel.gnu.linkonce.t*)');
+      Add('    }');
+      Add('  .rela.text     :');
+      Add('    {');
+      Add('      *(.rela.text)');
+      Add('      *(.rela.text.*)');
+      Add('      *(.rela.gnu.linkonce.t*)');
+      Add('    }');
+      Add('  .rel.fini      : { *(.rel.fini)		}');
+      Add('  .rela.fini     : { *(.rela.fini)	}');
+      Add('  .rel.rodata    :');
+      Add('    {');
+      Add('      *(.rel.rodata)');
+      Add('      *(.rel.rodata.*)');
+      Add('      *(.rel.gnu.linkonce.r*)');
+      Add('    }');
+      Add('  .rela.rodata   :');
+      Add('    {');
+      Add('      *(.rela.rodata)');
+      Add('      *(.rela.rodata.*)');
+      Add('      *(.rela.gnu.linkonce.r*)');
+      Add('    }');
+      Add('  .rel.data      :');
+      Add('    {');
+      Add('      *(.rel.data)');
+      Add('      *(.rel.data.*)');
+      Add('      *(.rel.gnu.linkonce.d*)');
+      Add('    }');
+      Add('  .rela.data     :');
+      Add('    {');
+      Add('      *(.rela.data)');
+      Add('      *(.rela.data.*)');
+      Add('      *(.rela.gnu.linkonce.d*)');
+      Add('    }');
+      Add('  .rel.ctors     : { *(.rel.ctors)	}');
+      Add('  .rela.ctors    : { *(.rela.ctors)	}');
+      Add('  .rel.dtors     : { *(.rel.dtors)	}');
+      Add('  .rela.dtors    : { *(.rela.dtors)	}');
+      Add('  .rel.got       : { *(.rel.got)		}');
+      Add('  .rela.got      : { *(.rela.got)		} >flash');
+      Add('  .rel.bss       : { *(.rel.bss)		}');
+      Add('  .rela.bss      : { *(.rela.bss)		}');
+      Add('  .rel.plt       : { *(.rel.plt)		}');
+      Add('  .rela.plt      : { *(.rela.plt)		}');
+      Add('     .text :');
+      Add('    {');
+      Add('    KEEP(*(.init))');
+      Add('    KEEP(*(.init.*))');
+      Add('    *(.text)');
+      Add('    *(.text.*)');
+      Add('    *(.strings)');
+      Add('    *(.rodata)');
+      Add('    *(.rodata.*)');
+      Add('    *(.comment)');
+      Add('    _etext = .;');
+      Add('    } >flash =0xd703d703');
+      Add('    .data :');
+      Add('    {');
+      Add('    _data = .;');
+      Add('    *(.data)');
+      Add('    *(.data.*)');
+      Add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+      Add('    _edata = .;');
+      Add('    } >ram AT >flash');
+      Add('    .bss :');
+      Add('    {');
+      Add('    _bss_start = .;');
+      Add('    *(.bss)');
+      Add('    *(.bss.*)');
+      Add('    *(COMMON)');
+      Add('    } >ram');
+      Add('. = ALIGN(4);');
+      Add('_bss_end = . ;');
+      Add('}');
+      Add('_end = .;');
+    end;
+{$endif AVR32}
+
   { Write and Close response }
   linkres.writetodisk;
   linkres.free;
@@ -655,4 +789,9 @@ initialization
   RegisterExternalLinker(system_i386_embedded_info,TlinkerEmbedded);
   RegisterTarget(system_i386_embedded_info);
 {$endif i386}
+
+{$ifdef avr32}
+  RegisterExternalLinker(system_avr32_embedded_info,TlinkerEmbedded);
+  RegisterTarget(system_avr32_embedded_info);
+{$endif avr32}
 end.

+ 1 - 1
compiler/utils/Makefile.fpc

@@ -3,7 +3,7 @@
 #
 
 [target]
-programs=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+programs=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins mkavr32ins
 rst=fpcsubst
 
 [clean]

+ 409 - 0
compiler/utils/mkavr32ins.pp

@@ -0,0 +1,409 @@
+{
+    Copyright (c) 1998-2005 by Peter Vreman and Florian Klaempfl
+
+    Convert i386ins.dat from Nasm to a .inc file for usage with
+    the Free pascal compiler
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+program mkavr32ins;
+
+const
+  Version = '0.9';
+
+var
+   s : string;
+   i : longint;
+
+    function lower(const s : string) : string;
+    {
+      return lowercased string of s
+    }
+      var
+         i : longint;
+      begin
+         for i:=1 to length(s) do
+          if s[i] in ['A'..'Z'] then
+           lower[i]:=char(byte(s[i])+32)
+          else
+           lower[i]:=s[i];
+         lower[0]:=s[0];
+      end;
+
+      function Replace(var s:string;const s1,s2:string):boolean;
+      var
+        i  : longint;
+      begin
+        i:=pos(s1,s);
+        if i>0 then
+         begin
+           Delete(s,i,length(s1));
+           Insert(s2,s,i);
+           Replace:=true;
+         end
+        else
+         Replace:=false;
+      end;
+
+
+function formatop(s:string):string;
+   const
+     replaces=20;
+     replacetab : array[1..replaces,1..2] of string[32]=(
+       (':',' or ot_colon'),
+       ('mem8','mem or ot_bits8'),
+       ('mem16','mem or ot_bits16'),
+       ('mem32','mem or ot_bits32'),
+       ('mem64','mem or ot_bits64'),
+       ('mem80','mem or ot_bits80'),
+       ('mem','memory'),
+       ('memory_offs','mem_offs'),
+       ('imm5','imm or ot_bits5'),
+       ('imm8','imm or ot_bits8'),
+       ('imm16','imm or ot_bits16'),
+       ('imm21','imm or ot_bits21'),
+       ('imm32','imm or ot_bits32'),
+       ('imm64','imm or ot_bits64'),
+       ('imm80','imm or ot_bits80'),
+       ('rm8','regmem or ot_bits8'),
+       ('rm16','regmem or ot_bits16'),
+       ('rm32','regmem or ot_bits32'),
+       ('rm64','regmem or ot_bits64'),
+       ('rm80','regmem or ot_bits80')
+     );
+  var
+    i : longint;
+  begin
+    for i:=1to replaces do
+     replace(s,replacetab[i,1],replacetab[i,2]);
+    formatop:=s;
+  end;
+
+
+function readnumber : longint;
+
+  var
+     base : longint;
+     result : longint;
+
+  begin
+     result:=0;
+     if s[i]='\' then
+       begin
+          base:=8;
+          inc(i);
+          if s[i]='x' then
+            begin
+               base:=16;
+               inc(i);
+            end;
+       end
+     else
+       base:=10;
+     s[i]:=upcase(s[i]);
+     while s[i] in ['0'..'9','A'..'F'] do
+       begin
+          case s[i] of
+             '0'..'9':
+               result:=result*base+ord(s[i])-ord('0');
+
+             'A'..'F':
+               result:=result*base+ord(s[i])-ord('A')+10;
+          end;
+          inc(i);
+       end;
+     readnumber:=result;
+  end;
+
+function tostr(l : longint) : string;
+
+  var
+     hs : string;
+
+  begin
+     str(l,hs);
+     tostr:=hs;
+  end;
+
+function readstr : string;
+
+  var
+     result : string;
+
+  begin
+     result:='';
+     while (s[i] in ['0'..'9','A'..'Z','a'..'z','_']) and (i<=length(s)) do
+       begin
+          result:=result+s[i];
+          inc(i);
+       end;
+     readstr:=result;
+  end;
+
+procedure skipspace;
+
+  begin
+     while (s[i] in [' ',#9]) do
+       inc(i);
+  end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+  writeln('creating ',fn);
+  assign(f,fn);
+  rewrite(f);
+  writeln(f,'{ don''t edit, this file is generated from avr32ins.dat }');
+  writeln(f,'(');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+  writeln(f);
+  writeln(f,');');
+  close(f);
+end;
+
+
+var
+   attsuffix,
+   hs : string;
+   j : longint;
+   firstopcode,
+   first : boolean;
+   maxinfolen,
+   code : byte;
+   insns : longint;
+   attsuffile,{propfile,}opfile,
+   nopfile,attfile,
+   infile,insfile : text;
+   { instruction fields }
+   skip : boolean;
+   {last,}
+   ops    : longint;
+   attopcode,
+   opcode,
+   codes,
+   flags   : string;
+   optypes : array[1..4] of string;
+begin
+   writeln('Navr32 Instruction Table Converter Version ',Version);
+   insns:=0;
+   maxinfolen:=0;
+   { open dat file }
+   assign(infile,'../avr32/avr32ins.dat');
+   { create inc files }
+   openinc(insfile,'avr32tab.inc');
+   openinc(opfile,'avr32op.inc');
+   assign(nopfile,'avr32nop.inc');
+   openinc(attfile,'avr32att.inc');
+   openinc(attsuffile,'avr32atts.inc');
+   {
+   openinc(intfile,'i386int.inc');
+   openinc(propfile,'i386prop.inc');
+   }
+   rewrite(nopfile);
+   writeln(nopfile,'{ don''t edit, this file is generated from avr32ins.dat }');
+   reset(infile);
+   first:=true;
+   opcode:='';
+   firstopcode:=true;
+   while not(eof(infile)) do
+     begin
+        { handle comment }
+        readln(infile,s);
+        while (s[1]=' ') do
+         delete(s,1,1);
+        if (s='') or (s[1]=';') then
+          continue;
+        if (s[1]='[') then
+         begin
+           i:=pos(',',s);
+           j:=pos(']',s);
+           if i=0 then
+            begin
+              opcode:='A_'+Copy(s,2,j-2);
+              attopcode:=Copy(s,2,j-2);
+              { Conditional }
+              if (attopcode[length(attopcode)]='c') and
+                 (attopcode[length(attopcode)-1]='c') then
+                begin
+                  dec(byte(attopcode[0]),2);
+                  dec(byte(opcode[0]),2);
+                end;
+              attsuffix:='attsufNONE';
+            end
+           else
+            begin
+              opcode:='A_'+Copy(s,2,i-2);
+              { intel conditional }
+              if (opcode[length(attopcode)]='c') and
+                 (opcode[length(attopcode)-1]='c') then
+                dec(byte(opcode[0]),2);
+              attopcode:=Copy(s,i+1,j-i-1);
+              { att Suffix }
+              case attopcode[length(attopcode)] of
+                'X' :
+                  begin
+                    dec(attopcode[0]);
+                    attsuffix:='attsufINT';
+                  end;
+                'F' :
+                  begin
+                    dec(attopcode[0]);
+                    attsuffix:='attsufFPU';
+                  end;
+                'R' :
+                  begin
+                    dec(attopcode[0]);
+                    attsuffix:='attsufFPUint';
+                  end;
+                else
+                  attsuffix:='attsufNONE';
+              end;
+              { att Conditional }
+              if (attopcode[length(attopcode)]='C') and
+                 (attopcode[length(attopcode)-1]='C') then
+                dec(byte(attopcode[0]),2);
+            end;
+           attopcode:=Lower(attopcode);
+           if firstopcode then
+            firstopcode:=false
+           else
+            begin
+              writeln(opfile,',');
+              writeln(attfile,',');
+              writeln(attsuffile,',');
+{              writeln(propfile,','); }
+            end;
+           write(opfile,opcode);
+           write(attfile,'''',attopcode,'''');
+           write(attsuffile,attsuffix);
+           { read the next line which contains the Change options }
+           {
+           repeat
+             readln(infile,s);
+           until eof(infile) or ((s<>'') and (s[1]<>';'));
+           write(propfile,'(Ch: ',s,')');
+           }
+           continue;
+         end;
+        { we must have an opcode }
+        if opcode='' then
+         runerror(234);
+        { clear }
+        ops:=0;
+        optypes[1]:='';
+        optypes[2]:='';
+        optypes[3]:='';
+        optypes[4]:='';
+        codes:='';
+        flags:='';
+        skip:=false;
+        { ops and optypes }
+        i:=1;
+        repeat
+          hs:=readstr;
+          if (hs='void') or (hs='ignore') then
+            break;
+          inc(ops);
+          optypes[ops]:=optypes[ops]+'ot_'+formatop(hs);
+{          if s[i]=':' then
+            begin
+               inc(i);
+               optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+            end;}
+          while s[i]='|' do
+            begin
+               inc(i);
+               optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+            end;
+          if s[i] in [',',':'] then
+            inc(i)
+          else
+            break;
+        until false;
+        for j:=1 to 4-ops do
+          optypes[4-j+1]:='ot_none';
+        { codes }
+        skipspace;
+        j:=0;
+(*        last:=0;*)
+        if s[i] in ['\','0'..'9'] then
+          begin
+             while not(s[i] in [' ',#9]) do
+               begin
+                 code:=readnumber;
+(*
+                 { for some codes we want also to change the optypes, but not
+                   if the last byte was a 1 then this byte belongs to a direct
+                   copy }
+                 if last<>1 then
+                  begin
+                    case code of
+                      12,13,14 :
+                        optypes[code-11]:=optypes[code-11]+' or ot_signed';
+                    end;
+                  end;
+*)
+                 codes:=codes+'#'+tostr(code);
+(*                 last:=code;*)
+                 inc(j);
+               end;
+          end
+        else
+          begin
+            readstr;
+            codes:='#0';
+          end;
+        if j>maxinfolen then
+         maxinfolen:=j;
+        { flags }
+        skipspace;
+        while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
+          begin
+             hs:=readstr;
+             if hs<>'ND' then
+              begin
+                if flags<>'' then
+                 flags:=flags+' or ';
+                flags:=flags+'if_'+lower(hs);
+              end;
+             if (s[i]=',') and (i<=length(s)) then
+              inc(i)
+             else
+              break;
+          end;
+        { write instruction }
+        if not skip then
+          begin
+            if not(first) then
+              writeln(insfile,',')
+            else
+              first:=false;
+            writeln(insfile,'  (');
+            writeln(insfile,'    opcode  : ',opcode,';');
+            writeln(insfile,'    ops     : ',ops,';');
+            writeln(insfile,'    optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
+            writeln(insfile,'    code    : ',codes,';');
+            writeln(insfile,'    flags   : ',flags);
+            write(insfile,'  )');
+            inc(insns);
+          end;
+     end;
+   close(infile);
+   closeinc(insfile);
+   closeinc(attfile);
+   closeinc(attsuffile);
+   closeinc(opfile);
+   writeln(nopfile,insns,';');
+   close(nopfile);
+{   closeinc(propfile); }
+   writeln(insns,' nodes procesed (maxinfolen=',maxinfolen,')');
+end.

+ 278 - 0
compiler/utils/mkavr32reg.pp

@@ -0,0 +1,278 @@
+{
+    Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+    Convert spreg.dat to several .inc files for usage with
+    the Free pascal compiler
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+program mkavr32reg;
+
+const Version = '1.00';
+      max_regcount = 200;
+
+var s : string;
+    i : longint;
+    line : longint;
+    regcount:byte;
+    regcount_bsstart:byte;
+    names,
+    regtypes,
+    subtypes,
+    supregs,
+    numbers,
+    stdnames,
+    stabs,dwarf : array[0..max_regcount-1] of string[63];
+    regnumber_index,
+    std_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+  str(l,tostr);
+end;
+
+function readstr : string;
+
+  var
+     result : string;
+
+  begin
+     result:='';
+     while (s[i]<>',') and (i<=length(s)) do
+       begin
+          result:=result+s[i];
+          inc(i);
+       end;
+     readstr:=result;
+  end;
+
+
+procedure readcomma;
+  begin
+     if s[i]<>',' then
+       begin
+         writeln('Missing "," at line ',line);
+         writeln('Line: "',s,'"');
+         halt(1);
+       end;
+     inc(i);
+  end;
+
+
+procedure skipspace;
+
+  begin
+     while (s[i] in [' ',#9]) do
+       inc(i);
+  end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+  writeln('creating ',fn);
+  assign(f,fn);
+  rewrite(f);
+  writeln(f,'{ don''t edit, this file is generated from avr32reg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+  writeln(f);
+  close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+  {Build the registernumber2regindex index.
+   Step 1: Fill.}
+  for i:=0 to regcount-1 do
+    regnumber_index[i]:=i;
+  {Step 2: Sort. We use a Shell-Metzner sort.}
+  p:=regcount_bsstart;
+  repeat
+    for h:=0 to regcount-p-1 do
+      begin
+        i:=h;
+        repeat
+          j:=i+p;
+          if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+            break;
+          t:=regnumber_index[i];
+          regnumber_index[i]:=regnumber_index[j];
+          regnumber_index[j]:=t;
+          if i<p then
+            break;
+          dec(i,p);
+        until false;
+      end;
+    p:=p shr 1;
+  until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+  {Build the registernumber2regindex index.
+   Step 1: Fill.}
+  for i:=0 to regcount-1 do
+    std_regname_index[i]:=i;
+  {Step 2: Sort. We use a Shell-Metzner sort.}
+  p:=regcount_bsstart;
+  repeat
+    for h:=0 to regcount-p-1 do
+      begin
+        i:=h;
+        repeat
+          j:=i+p;
+          if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+            break;
+          t:=std_regname_index[i];
+          std_regname_index[i]:=std_regname_index[j];
+          std_regname_index[j]:=t;
+          if i<p then
+            break;
+          dec(i,p);
+        until false;
+      end;
+    p:=p shr 1;
+  until p=0;
+end;
+
+
+procedure read_spreg_file;
+
+var infile:text;
+
+begin
+   { open dat file }
+   assign(infile,'avr32reg.dat');
+   reset(infile);
+   while not(eof(infile)) do
+     begin
+        { handle comment }
+        readln(infile,s);
+        inc(line);
+        while (s[1]=' ') do
+         delete(s,1,1);
+        if (s='') or (s[1]=';') then
+          continue;
+
+        i:=1;
+        names[regcount]:=readstr;
+        readcomma;
+        regtypes[regcount]:=readstr;
+        readcomma;
+        subtypes[regcount]:=readstr;
+        readcomma;
+        supregs[regcount]:=readstr;
+        readcomma;
+        stdnames[regcount]:=readstr;
+        readcomma;
+        stabs[regcount]:=readstr;
+        readcomma;
+        dwarf[regcount]:=readstr;
+        { Create register number }
+        if supregs[regcount][1]<>'$' then
+          begin
+            writeln('Missing $ before number, at line ',line);
+            writeln('Line: "',s,'"');
+            halt(1);
+          end;
+        numbers[regcount]:=regtypes[regcount]+copy(subtypes[regcount],2,255)+'00'+copy(supregs[regcount],2,255);
+        if i<length(s) then
+          begin
+            writeln('Extra chars at end of line, at line ',line);
+            writeln('Line: "',s,'"');
+            halt(1);
+          end;
+        inc(regcount);
+        if regcount>max_regcount then
+          begin
+            writeln('Error: Too much registers, please increase maxregcount in source');
+            halt(2);
+          end;
+     end;
+   close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+    norfile,stdfile,supfile,
+    numfile,stabfile,dwarffile,confile,
+    rnifile,srifile:text;
+    first:boolean;
+
+begin
+  { create inc files }
+  openinc(confile,'ravr32con.inc');
+  openinc(supfile,'ravr32sup.inc');
+  openinc(numfile,'ravr32num.inc');
+  openinc(stdfile,'ravr32std.inc');
+  openinc(stabfile,'ravr32sta.inc');
+  openinc(dwarffile,'ravr32dwa.inc');
+  openinc(norfile,'ravr32nor.inc');
+  openinc(rnifile,'ravr32rni.inc');
+  openinc(srifile,'ravr32sri.inc');
+  first:=true;
+  for i:=0 to regcount-1 do
+    begin
+      if not first then
+        begin
+          writeln(numfile,',');
+          writeln(stdfile,',');
+          writeln(stabfile,',');
+          writeln(dwarffile,',');
+          writeln(rnifile,',');
+          writeln(srifile,',');
+        end
+      else
+        first:=false;
+      writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+      writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+      write(numfile,'tregister(',numbers[i],')');
+      write(stdfile,'''',stdnames[i],'''');
+      write(stabfile,stabs[i]);
+      write(dwarffile,dwarf[i]);
+      write(rnifile,regnumber_index[i]);
+      write(srifile,std_regname_index[i]);
+    end;
+  write(norfile,regcount);
+  close(confile);
+  close(supfile);
+  closeinc(numfile);
+  closeinc(stdfile);
+  closeinc(stabfile);
+  closeinc(dwarffile);
+  closeinc(norfile);
+  closeinc(rnifile);
+  closeinc(srifile);
+  writeln('Done!');
+  writeln(regcount,' registers procesed');
+end;
+
+
+begin
+   writeln('Register Table Converter Version ',Version);
+   line:=0;
+   regcount:=0;
+   read_spreg_file;
+   regcount_bsstart:=1;
+   while 2*regcount_bsstart<regcount do
+     regcount_bsstart:=regcount_bsstart*2;
+   build_regnum_index;
+   build_std_regname_index;
+   write_inc_files;
+end.

+ 189 - 0
rtl/avr32/avr32.inc

@@ -0,0 +1,189 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003 by the Free Pascal development team.
+
+    Processor dependent implementation for the system unit for
+    AVR32
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+{$asmmode gas}
+
+{$ifndef FPC_SYSTEM_HAS_MOVE}
+{$define FPC_SYSTEM_FPC_MOVE}
+{$endif FPC_SYSTEM_HAS_MOVE}
+
+{$if not(defined(FPUSOFT)) and not(defined(FPULIBGCC))}
+
+{$define FPC_SYSTEM_HAS_SYSINITFPU}
+{$if not defined(FPUAVR32)}
+Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+end;
+{$else}
+Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  { Enable FPU exceptions, but disable INEXACT, UNDERFLOW, DENORMAL }
+  asm
+    
+  end;  
+end;
+{$endif}
+{$endif}
+
+procedure fpc_cpuinit;
+begin
+  { don't let libraries influence the FPU cw set by the host program }
+  if not IsLibrary then
+    SysInitFPU;
+end;
+
+{****************************************************************************
+                       stack frame related stuff
+****************************************************************************}
+
+{$IFNDEF INTERNAL_BACKTRACE}
+{$define FPC_SYSTEM_HAS_GET_FRAME}
+function get_frame:pointer;assembler;nostackframe;
+asm
+  mov    r12,sp
+end;
+{$ENDIF not INTERNAL_BACKTRACE}
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
+function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
+label Lg_a_null;
+asm
+  tst r12,r12
+  breq Lg_a_null
+  ld.w r12,r12[0]
+Lg_a_null:
+end;
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
+function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
+label Lgnf_null;
+asm
+  tst r12,r12
+  breq Lgnf_null
+  ld.w r12,r12[-4]
+Lgnf_null:
+end;
+
+
+{$define FPC_SYSTEM_HAS_SPTR}
+Function Sptr : pointer;assembler;nostackframe;
+asm
+  mov    r12,sp
+end;
+
+
+{$ifndef FPC_SYSTEM_HAS_FILLCHAR}
+{$define FPC_SYSTEM_HAS_FILLCHAR}
+Procedure FillChar(var x;count:longint;value:byte);assembler;nostackframe;
+label Lloop;
+asm
+Lloop:
+  st.b r12++,value
+  sub count,1
+  brne Lloop
+end;
+{$endif FPC_SYSTEM_HAS_FILLCHAR}
+
+function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
+label Loop;
+asm
+Loop:
+  ssrf 5
+  ld.w r10,target
+  sub r10,1
+  stcond target,r10
+  brne Loop
+  
+  mov r12,r10
+end;
+
+
+function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
+label Loop;
+asm
+Loop:
+  ssrf 5
+  ld.w r10,target
+  sub r10,-1
+  stcond target,r10
+  brne Loop
+  
+  mov r12,r10
+end;
+
+
+function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+label Loop;
+asm
+Loop:
+  ssrf 5
+  ld.w r10,target
+  stcond target,source
+  brne Loop
+  
+  mov r12,r10
+end;
+
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+label Loop;
+asm
+Loop:
+  ssrf 5
+  ld.w r10,target
+  add r1,r10,source
+  stcond target,r1
+  brne Loop
+  
+  mov r12,r10
+end;
+
+
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
+label Loop,doExit;
+asm
+Loop:
+  ssrf 5
+  ld.w r10,target
+  cp.w r10,comperand
+  brne doExit
+  stcond target,newvalue
+  brne Loop
+doExit:
+  mov r12,r10
+end;
+
+{$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
+function declocked(var l: longint) : boolean; inline;
+begin
+  Result:=InterLockedDecrement(l) = 0;
+end;
+
+{$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
+procedure inclocked(var l: longint); inline;
+begin
+  InterLockedIncrement(l);
+end;
+
+procedure fpc_cpucodeinit;
+begin
+
+end;
+
+{include hand-optimized assembler division code}
+{ $i divide.inc}
+

+ 20 - 0
rtl/avr32/int64p.inc

@@ -0,0 +1,20 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    This file contains some helper routines for int64 and qword
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+{ $define FPC_SYSTEM_HAS_MUL_QWORD}
+{function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;assembler;nostackframe;[public,alias: 'FPC_MUL_QWORD']; compilerproc;
+asm
+   
+end;}

+ 6 - 0
rtl/avr32/makefile.cpu

@@ -0,0 +1,6 @@
+#
+# Here we set processor dependent include file names.
+#
+
+CPUNAMES=avr32 math set
+CPUINCNAMES=$(addsuffix .inc,$(CPUNAMES))

+ 52 - 0
rtl/avr32/math.inc

@@ -0,0 +1,52 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003 by the Free Pascal development team.
+
+    Implementation of mathematical Routines (only for real)
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+    (* atn isn't supported by the linux fpe it seems
+    {$define FPC_SYSTEM_HAS_ARCTAN}
+    function fpc_arctan_real(d : extended) : extended;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    *)
+    (* lgn isn't supported by the linux fpe it seems
+    {$define FPC_SYSTEM_HAS_LN}
+    function fpc_ln_real(d : extended) : extended;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    *)
+    (* sind isn't supported by the linux fpe it seems
+    {$define FPC_SYSTEM_HAS_SIN}
+    function fpc_sin_real(d : extended) : extended;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    *)
+    (* cos isn't supported by the linux fpe it seems
+    {$define FPC_SYSTEM_HAS_COS}
+    function fpc_cos_real(d : extended) : extended;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    *)

+ 15 - 0
rtl/avr32/set.inc

@@ -0,0 +1,15 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003 by the Free Pascal development team.
+
+    Include file with set operations called by the compiler
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}

+ 26 - 0
rtl/avr32/setjump.inc

@@ -0,0 +1,26 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003 by the Free Pascal development team.
+
+    SetJmp and LongJmp implementation for exception handling
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+function fpc_setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJMP'];nostackframe; compilerproc;
+  asm
+  end;
+
+
+procedure fpc_longjmp(var S : jmp_buf;value : longint);assembler;[Public, alias : 'FPC_LONGJMP']; compilerproc;
+  asm
+  end;
+
+

+ 25 - 0
rtl/avr32/setjumph.inc

@@ -0,0 +1,25 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003 by the Free Pascal development team.
+
+    SetJmp/Longjmp declarations
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+type
+   jmp_buf = packed record
+   end;
+   pjmp_buf = ^jmp_buf;
+
+function setjmp(var S : jmp_buf) : longint;[external name 'FPC_SETJMP'];
+procedure longjmp(var S : jmp_buf;value : longint);[external name 'FPC_LONGJMP'];
+
+

+ 4 - 0
rtl/embedded/Makefile.fpc

@@ -51,6 +51,10 @@ ifeq ($(ARCH),arm)
 CPU_UNITS=lpc21x4 at91sam7x256 stellaris stm32f103
 endif
 
+ifeq ($(ARCH),avr32)
+CPU_UNITS=at32uc3b1256
+endif
+
 ifeq ($(ARCH),i386)
 CPU_UNITS=multiboot
 endif

+ 299 - 0
rtl/embedded/avr32/at32uc3b1256.pas

@@ -0,0 +1,299 @@
+unit at32uc3b1256;
+
+interface
+
+const
+ USB_BASE      = $FFFE0000;
+ HMATRIX_BASE  = $FFFE1000;
+ FLASHC_BASE   = $FFFE1400;
+ PDCA_BASE     = $FFFF0000;
+ INTC_BASE     = $FFFF0800;
+ PM_BASE       = $FFFF0C00;
+ RTC_BASE      = $FFFF0D00;
+ WDT_BASE      = $FFFF0D30;
+ EIC_BASE      = $FFFF0D80;
+ GPIO_BASE     = $FFFF1000;
+ USART0_BASE   = $FFFF1400;
+ USART1_BAse   = $FFFF1800;
+ USART2_BASE   = $FFFF1C00;
+ SPI0_BASE     = $FFFF2400;
+ TWI_BASE      = $FFFF2C00;
+ PWM_BASE      = $FFFF3000;
+ SSC_BASE      = $FFFF3400;
+ TC_BASE       = $FFFF3800;
+ ADC_BASE      = $FFFF3C00;
+ ABDAC_BASE    = $FFFF4000;
+
+var
+ { Power management }
+ PM_MCCTRL: longword       absolute PM_BASE+$000;
+ PM_CKSEL: longword        absolute PM_BASE+$004;
+ PM_CPUMASK: longword      absolute PM_BASE+$008;
+ PM_HSBMASK: longword      absolute PM_BASE+$00C;
+ PM_PBAMASK: longword      absolute PM_BASE+$010;
+ PM_PBBMASK: longword      absolute PM_BASE+$014;
+ PM_PLL0: longword         absolute PM_BASE+$020;
+ PM_PLL1: longword         absolute PM_BASE+$024;
+ PM_OSCCTRL0: longword     absolute PM_BASE+$028;
+ PM_OSCCTRL1: longword     absolute PM_BASE+$02C;
+ PM_OSCCTRL32: longword    absolute PM_BASE+$030;
+ PM_IER: longword          absolute PM_BASE+$040;
+ PM_IDR: longword          absolute PM_BASE+$044;
+ PM_IMR: longword          absolute PM_BASE+$048;
+ PM_ISR: longword          absolute PM_BASE+$04C;
+ PM_ICR: longword          absolute PM_BASE+$050;
+ PM_POSCSR: longword       absolute PM_BASE+$054;
+ PM_GCCTRL: longword       absolute PM_BASE+$060;
+ PM_RCCR: longword         absolute PM_BASE+$0C0;
+ PM_BGCR: longword         absolute PM_BASE+$0C4;
+ PM_VREGCR: longword       absolute PM_BASE+$0C8;
+ PM_BOD: longword          absolute PM_BASE+$0D0;
+ PM_RCAUSE: longword       absolute PM_BASE+$140;
+ PM_AWEN: longword         absolute PM_BASE+$144;
+ PM_GPLP0: longword        absolute PM_BASE+$200;
+ PM_GPLP1: longword        absolute PM_BASE+$204;
+ 
+ { RTC }
+ RTC_CTRL: longword        absolute RTC_BASE+$000;
+ RTC_VAL: longword         absolute RTC_BASE+$004;
+ RTC_TOP: longword         absolute RTC_BASE+$008;
+ RTC_IER: longword         absolute RTC_BASE+$010;
+ RTC_IDR: longword         absolute RTC_BASE+$014;
+ RTC_IMR: longword         absolute RTC_BASE+$018;
+ RTC_ISR: longword         absolute RTC_BASE+$01C;
+ RTC_ICR: longword         absolute RTC_BASE+$020;
+ 
+ { WDT }
+ WDT_CTRL: longword        absolute WDT_BASE+$000;
+ WDT_CLR: longword         absolute WDT_BASE+$004;
+ 
+ { INTC }
+ INTC_IPR: array[0..63] of longword absolute INTC_BASE+$000;
+ INTC_IRR: array[0..63] of longword absolute INTC_BASE+$100;
+ INTC_ICR3: longword       absolute INTC_BASE+$200;
+ INTC_ICR2: longword       absolute INTC_BASE+$204;
+ INTC_ICR1: longword       absolute INTC_BASE+$208;
+ INTC_ICR0: longword       absolute INTC_BASE+$20C;
+ 
+ { EIC }
+ EIC_IER: longword         absolute EIC_BASE+$000;
+ EIC_IDR: longword         absolute EIC_BASE+$004;
+ EIC_IMR: longword         absolute EIC_BASE+$008;
+ EIC_ISR: longword         absolute EIC_BASE+$00C;
+ EIC_ICR: longword         absolute EIC_BASE+$010;
+ EIC_MODE: longword        absolute EIC_BASE+$014;
+ EIC_EDGE: longword        absolute EIC_BASE+$018;
+ EIC_LEVEL: longword       absolute EIC_BASE+$01C;
+ EIC_FILTER: longword      absolute EIC_BASE+$020;
+ EIC_TEST: longword        absolute EIC_BASE+$024;
+ EIC_ASYNC: longword       absolute EIC_BASE+$028;
+ EIC_SCAN: longword        absolute EIC_BASE+$02C;
+ EIC_EN: longword          absolute EIC_BASE+$030;
+ EIC_DIS: longword         absolute EIC_BASE+$034;
+ EIC_CTRL: longword        absolute EIC_BASE+$038;
+ 
+ { FLASHC }
+ FLASHC_FCR: longword      absolute FLASHC_BASE+$000;
+ FLASHC_FCMD: longword     absolute FLASHC_BASE+$004;
+ FLASHC_FSR: longword      absolute FLASHC_BASE+$008;
+ FLASHC_FGPFRHI: longword  absolute FLASHC_BASE+$00C;
+ FLASHC_FGPFRLO: longword  absolute FLASHC_BASE+$010;
+ 
+ { DMA }
+type
+ TDMA_registers = packed record
+  MAR, PSR, TCR, MARR,
+  TCRR, CR, MR, SR,
+  IER, IDR, IMR, ISR: longword;
+  res: array[0..3] of longword;
+ end;
+
+var
+ DMA: array[0..6] of TDMA_registers absolute PDCA_BASE;
+ 
+type
+ TGPIO_Registers = packed record
+  GPER,
+  GPERS,
+  GPERC,
+  GPERT,
+  PMR0,
+  PMR0S,
+  PMR0C,
+  PMR0T,
+  PMR1,
+  PMR1S,
+  PMR1C,
+  PMR1T: longword;
+  res0: array[0..3] of longword;
+  ODER,
+  ODERS,
+  ODERC,
+  ODERT,
+  OVR,
+  OVRS,
+  OVRC,
+  OVRT,
+  PVR: longword;
+  res1: array[0..2] of longword;
+  PUER,
+  PUERS,
+  PUERC,
+  PUERT: longword;
+  res2: array[0..3] of longword;
+  IER,
+  IERS,
+  IERC,
+  IERT,
+  IMR0,
+  IMR0S,
+  IMR0C,
+  IMR0T,
+  IMR1,
+  IMR1S,
+  IMR1C,
+  IMR1T,
+  GFER,
+  GFERS,
+  GFERC,
+  GFERT,
+  IFR,
+  res3,
+  IFRC,
+  res4: longword;
+ end;
+
+var
+ GPIO0: TGPIO_Registers absolute GPIO_BASE+$000;
+ GPIO1: TGPIO_Registers absolute GPIO_BASE+$100;
+ 
+ { USART }
+type
+ TUSART_registers = packed record
+  CR,
+  MR,
+  IER,
+  IDR,
+  IMR,
+  CSR,
+  RHR,
+  THR,
+  BRGR,
+  RTOR,
+  TTGR: longword;
+  res0: array[0..4] of longword;
+  FIDI,
+  NER,
+  res1,
+  IFR,
+  MAN: longword;
+  res2: array[0..41] of longword;
+  VERSION: longword;
+ end;
+
+var
+ USART0: TUSART_registers absolute USART0_BASE;
+ USART1: TUSART_registers absolute USART1_BASE;
+ USART2: TUSART_registers absolute USART2_BASE;
+
+ { USBB }
+type
+ TUSB_DMA = packed record
+  NEXTDESC,
+  ADDR,
+  CONTROL,
+  STATUS: longword;
+ end;
+
+var
+ USBB_UDCON: longword                     absolute USB_BASE+$0000;
+ USBB_UDINT: longword                     absolute USB_BASE+$0004;
+ USBB_UDINTCLR: longword                  absolute USB_BASE+$0008;
+ USBB_UDINTSET: longword                  absolute USB_BASE+$000C;
+ USBB_UDINTE: longword                    absolute USB_BASE+$0010;
+ USBB_UDINTECLR: longword                 absolute USB_BASE+$0014;
+ USBB_UDINTESET: longword                 absolute USB_BASE+$0018;
+ USBB_UERST: longword                     absolute USB_BASE+$001C;
+ USBB_UDFNUM: longword                    absolute USB_BASE+$0020;
+ USBB_UECFG: array[0..6] of longword      absolute USB_BASE+$0100;
+ USBB_UESTA: array[0..6] of longword      absolute USB_BASE+$0130;
+ USBB_UESTACLR: array[0..7] of longword   absolute USB_BASE+$0160;
+ USBB_UESTASET: array[0..7] of longword   absolute USB_BASE+$0190;
+ USBB_UECON: array[0..7] of longword      absolute USB_BASE+$01C0;
+ USBB_UECONSET: array[0..7] of longword   absolute USB_BASE+$01F0;
+ USBB_UECONCLR: array[0..7] of longword   absolute USB_BASE+$0220;
+ USBB_UDDMA: array[1..6] of TUSB_DMA      absolute USB_BASE+$0310;
+
+implementation
+
+procedure PASCALMAIN; external name 'PASCALMAIN';
+
+var
+ _data: record end; external name '_data';
+ _edata: record end; external name '_edata';
+ _etext: record end; external name '_etext';
+ _bss_start: record end; external name '_bss_start';
+ _bss_end: record end; external name '_bss_end';
+ _stack_top: record end; external name '_stack_top';
+
+procedure _FPC_haltproc; assembler; nostackframe; public name '_haltproc';
+asm
+.Lhalt:
+	rjmp .Lhalt
+end;
+
+procedure DefaultHandler; assembler; nostackframe; public name 'DefaultHandler';
+asm
+end;
+
+procedure StartCode; nostackframe; assembler; [public, alias: '_START'];// interrupt 0;
+asm
+   // Update stack
+   lddpc sp, .L_stack_top
+   
+   // Set EVBA
+   lddpc r0, .L_evba_base
+   mtsr 4, r0 // EVBA
+   
+   // copy initialized data from flash to ram
+   lddpc r1,.L_etext
+   lddpc r2,.L_data
+   lddpc r3,.L_edata
+.Lcopyloop:
+   cp.w r2,r3
+   brhi .Lecopyloop
+   ld.w r0, r1++
+   st.w r2++, r0
+   bral .Lcopyloop
+.Lecopyloop:
+
+   // clear onboard ram
+   lddpc r1,.L_bss_start
+   lddpc r2,.L_bss_end
+   mov r0, 0
+.Lzeroloop:
+   cp.w r1,r2
+   brhi .Lezeroloop
+   st.w r1++, r0
+   bral .Lzeroloop
+.Lezeroloop:
+
+   bral PASCALMAIN
+   
+.L_bss_start:
+   .long _bss_start
+.L_bss_end:
+   .long _bss_end
+.L_etext:
+   .long _etext
+.L_data:
+   .long _data
+.L_edata:
+   .long _edata
+.L_evba_base:
+   .long 0x80000004
+.L_stack_top:
+   .long _stack_top
+end;
+
+end.

+ 3 - 0
rtl/embedded/rtl.cfg

@@ -33,3 +33,6 @@
 #ifdef CPUARM
 -SfSOFTFPU
 #endif CPUARM
+#ifdef CPUAVR32
+-SfSOFTFPU
+#endif CPUAVR32

+ 7 - 0
rtl/inc/system.inc

@@ -233,6 +233,13 @@ function do_isdevice(handle:thandle):boolean;forward;
   {$define SYSPROCDEFINED}
 {$endif cpuavr}
 
+{$ifdef cpuavr32}
+  {$ifdef SYSPROCDEFINED}
+    {$Error Can't determine processor type !}
+  {$endif}
+  {$i avr32.inc}  { Case dependent, don't change }
+  {$define SYSPROCDEFINED}
+{$endif cpuavr32}   
 
 procedure fillchar(var x;count : SizeInt;value : boolean);
 begin

+ 21 - 0
rtl/inc/systemh.inc

@@ -238,6 +238,27 @@ Type
   FarPointer = Pointer;
 {$endif CPUARM}
 
+{$ifdef CPUAVR32}
+  {$define DEFAULT_DOUBLE}
+
+  {$define FPC_INCLUDE_SOFTWARE_MOD_DIV}
+  {$define FPC_INCLUDE_SOFTWARE_SHIFT_INT64}
+  {$define FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE}
+
+  {$ifndef FPUNONE}
+    ValReal = Real;
+  {$endif}
+  
+  {$define SUPPORT_SINGLE}
+  {$define SUPPORT_DOUBLE}
+  
+  { map comp to int64, but this doesn't mean we compile the comp support in! }
+  Comp = Int64;
+  PComp = ^Comp;
+
+  FarPointer = Pointer;
+{$endif CPUAVR32} 
+
 {$ifdef CPU64}
   SizeInt = Int64;
   SizeUInt = QWord;

+ 36 - 36
utils/fpcm/fpcmmain.pp

@@ -63,7 +63,7 @@ interface
 
     type
       TCpu=(
-        c_i386,c_m68k,c_powerpc,c_sparc,c_x86_64,c_arm,c_powerpc64,c_avr,c_armeb,c_armel,c_mips,c_mipsel,c_mips64,c_mips64el
+        c_i386,c_m68k,c_powerpc,c_sparc,c_x86_64,c_arm,c_powerpc64,c_avr,c_armeb,c_armel,c_mips,c_mipsel,c_mips64,c_mips64el,c_avr32
       );
 
       TOS=(
@@ -78,15 +78,15 @@ interface
 
     const
       CpuStr : array[TCpu] of string=(
-        'i386','m68k','powerpc','sparc','x86_64','arm','powerpc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el'
+        'i386','m68k','powerpc','sparc','x86_64','arm','powerpc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'avr32'
       );
 
       CpuSuffix : array[TCpu] of string=(
-        '_i386','_m68k','_powerpc','_sparc','_x86_64','_arm','_powerpc64','avr','_armeb', '_armel', '_mips', '_mipsel', '_mips64', '_mips64el'
+        '_i386','_m68k','_powerpc','_sparc','_x86_64','_arm','_powerpc64','avr','_armeb', '_armel', '_mips', '_mipsel', '_mips64', '_mips64el', '_avr32'
       );
 
       ppcSuffix : array[TCpu] of string=(
-        '386','m68k','ppc','sparc','x86_64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el'
+        '386','m68k','ppc','sparc','x86_64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'avr32'
       );
 
       OSStr : array[TOS] of string=(
@@ -107,38 +107,38 @@ interface
 
       { This table is kept OS,Cpu because it is easier to maintain (PFV) }
       OSCpuPossible : array[TOS,TCpu] of boolean = (
-        { os          i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb  armel  mips   mipsel mips64 misp64el}
-        { linux }   ( true,  true,  true,  true,  true,  true,  true,  false, true,  false, false, true,  false, false),
-        { go32v2 }  ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { win32 }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { os2 }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { freebsd } ( true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false),
-        { beos }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { haiku }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { netbsd }  ( true,  true,  true,  true,  false, false, false, false, false, false, false, false, false, false),
-        { amiga }   ( false, true,  true,  false, false, false, false, false, false, false, false, false, false, false),
-        { atari }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-        { solaris } ( true,  false, false, true,  true,  false, false, false, false, false, false, false, false, false),
-        { qnx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { netware } ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { openbsd } ( true,  true,  false, false, false, false, false, false, false, false, false, false, false, false),
-        { wdosx }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { palmos }  ( false, true,  false, false, false, true,  false, false, false, false, false, false, false, false),
-        { macos }   ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false),
-        { darwin }  ( true,  false, true,  false, true,  true,  true,  false, false, false, false, false, false, false),
-        { emx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { watcom }  ( true,  false, false, false ,false, false, false, false, false, false, false, false, false, false),
-        { morphos } ( false, false, true,  false ,false, false, false, false, false, false, false, false, false, false),
-        { netwlibc }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { win64   } ( false, false, false, false, true,  false, false, false, false, false, false, false, false, false),
-        { wince    }( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false),
-        { gba    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false),
-        { nds    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false),
-        { embedded }( true,  true,  true,  true,  true,  true,  true,  true,  true , false, false, false, false, false),
-        { symbian } ( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false),
-        { nativent }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-        { iphonesim }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),        
-        { wii }     ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false)        
+        { os          i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb  armel  mips   mipsel mips64 misp64el avr32}
+        { linux }   ( true,  true,  true,  true,  true,  true,  true,  false, true,  false, false, true,  false, false,   false),
+        { go32v2 }  ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { win32 }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { os2 }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { freebsd } ( true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false,   false),
+        { beos }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { haiku }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { netbsd }  ( true,  true,  true,  true,  false, false, false, false, false, false, false, false, false, false,   false),
+        { amiga }   ( false, true,  true,  false, false, false, false, false, false, false, false, false, false, false,   false),
+        { atari }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { solaris } ( true,  false, false, true,  true,  false, false, false, false, false, false, false, false, false,   false),
+        { qnx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { netware } ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { openbsd } ( true,  true,  false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { wdosx }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { palmos }  ( false, true,  false, false, false, true,  false, false, false, false, false, false, false, false,   false),
+        { macos }   ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false,   false),
+        { darwin }  ( true,  false, true,  false, true,  true,  true,  false, false, false, false, false, false, false,   false),
+        { emx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { watcom }  ( true,  false, false, false ,false, false, false, false, false, false, false, false, false, false,   false),
+        { morphos } ( false, false, true,  false ,false, false, false, false, false, false, false, false, false, false,   false),
+        { netwlibc }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { win64   } ( false, false, false, false, true,  false, false, false, false, false, false, false, false, false,   false),
+        { wince    }( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false,   false),
+        { gba    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false,   false),
+        { nds    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false,   false),
+        { embedded }( true,  true,  true,  true,  true,  true,  true,  true,  true , false, false, false, false, false,   true ),
+        { symbian } ( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false,   false),
+        { nativent }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false),
+        { iphonesim }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,  false),
+        { wii }     ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false,   false)
       );
 
     type