Bladeren bron

Merged with trunk, and fixed some errors introduced.

git-svn-id: branches/laksen/spc32@33690 -
Jeppe Johansen 9 jaren geleden
bovenliggende
commit
8b8f905d46
100 gewijzigde bestanden met toevoegingen van 22343 en 7491 verwijderingen
  1. 398 52
      .gitattributes
  2. 18 27
      .gitignore
  3. 130 16
      Makefile
  4. 10 9
      Makefile.fpc
  5. 244 35
      compiler/Makefile
  6. 36 36
      compiler/Makefile.fpc
  7. 94 36
      compiler/aarch64/a64att.inc
  8. 59 1
      compiler/aarch64/a64atts.inc
  9. 159 43
      compiler/aarch64/a64ins.dat
  10. 94 36
      compiler/aarch64/a64op.inc
  11. 168 161
      compiler/aarch64/a64reg.dat
  12. 1 1
      compiler/aarch64/a64tab.inc
  13. 466 1143
      compiler/aarch64/aasmcpu.pas
  14. 302 0
      compiler/aarch64/agcpugas.pas
  15. 25 7
      compiler/aarch64/aoptcpub.pas
  16. 2213 0
      compiler/aarch64/cgcpu.pas
  17. 200 38
      compiler/aarch64/cpubase.pas
  18. 23 2
      compiler/aarch64/cpuinfo.pas
  19. 18 20
      compiler/aarch64/cpunode.pas
  20. 465 527
      compiler/aarch64/cpupara.pas
  21. 68 0
      compiler/aarch64/cpupi.pas
  22. 70 0
      compiler/aarch64/cputarg.pas
  23. 229 0
      compiler/aarch64/hlcgcpu.pas
  24. 402 0
      compiler/aarch64/ncpuadd.pas
  25. 199 0
      compiler/aarch64/ncpucnv.pas
  26. 184 0
      compiler/aarch64/ncpuinl.pas
  27. 196 0
      compiler/aarch64/ncpumat.pas
  28. 142 0
      compiler/aarch64/ncpumem.pas
  29. 175 0
      compiler/aarch64/ncpuset.pas
  30. 5 0
      compiler/aarch64/ra64con.inc
  31. 162 157
      compiler/aarch64/ra64dwa.inc
  32. 1 1
      compiler/aarch64/ra64nor.inc
  33. 6 1
      compiler/aarch64/ra64num.inc
  34. 101 96
      compiler/aarch64/ra64rni.inc
  35. 48 43
      compiler/aarch64/ra64sri.inc
  36. 162 157
      compiler/aarch64/ra64sta.inc
  37. 6 1
      compiler/aarch64/ra64std.inc
  38. 5 0
      compiler/aarch64/ra64sup.inc
  39. 88 0
      compiler/aarch64/racpu.pas
  40. 1053 0
      compiler/aarch64/racpugas.pas
  41. 171 0
      compiler/aarch64/rgcpu.pas
  42. 4 0
      compiler/aarch64/symcpu.pas
  43. 65 24
      compiler/aasmbase.pas
  44. 1950 0
      compiler/aasmcnst.pas
  45. 74 25
      compiler/aasmdata.pas
  46. 360 321
      compiler/aasmtai.pas
  47. 231 386
      compiler/aggas.pas
  48. 0 268
      compiler/alpha/aasmcpu.pas
  49. 0 126
      compiler/alpha/agaxpgas.pas
  50. 0 38
      compiler/alpha/aoptcpu.pas
  51. 0 38
      compiler/alpha/aoptcpuc.pas
  52. 0 168
      compiler/alpha/cgcpu.pas
  53. 0 431
      compiler/alpha/cpubase.pas
  54. 0 68
      compiler/alpha/cpuinfo.pas
  55. 0 56
      compiler/alpha/cpunode.pas
  56. 0 290
      compiler/alpha/cpupara.pas
  57. 0 0
      compiler/alpha/radirect.pas
  58. 0 65
      compiler/alpha/rasm.pas
  59. 0 69
      compiler/alpha/rgcpu.pas
  60. 0 211
      compiler/alpha/symcpu.pas
  61. 8 15
      compiler/aopt.pas
  62. 31 1
      compiler/aoptbase.pas
  63. 143 44
      compiler/aoptobj.pas
  64. 21 21
      compiler/aoptutils.pas
  65. 563 164
      compiler/arm/aasmcpu.pas
  66. 88 27
      compiler/arm/agarmgas.pas
  67. 294 151
      compiler/arm/aoptcpu.pas
  68. 8 5
      compiler/arm/aoptcpub.pas
  69. 141 118
      compiler/arm/armatt.inc
  70. 23 0
      compiler/arm/armatts.inc
  71. 1391 347
      compiler/arm/armins.dat
  72. 1 1
      compiler/arm/armnop.inc
  73. 141 118
      compiler/arm/armop.inc
  74. 9 2
      compiler/arm/armreg.dat
  75. 6359 430
      compiler/arm/armtab.inc
  76. 281 293
      compiler/arm/cgcpu.pas
  77. 44 13
      compiler/arm/cpubase.pas
  78. 81 1
      compiler/arm/cpuelf.pas
  79. 575 241
      compiler/arm/cpuinfo.pas
  80. 28 25
      compiler/arm/cpupara.pas
  81. 1 0
      compiler/arm/cpupi.pas
  82. 228 3
      compiler/arm/hlcgcpu.pas
  83. 82 47
      compiler/arm/narmadd.pas
  84. 3 2
      compiler/arm/narmcal.pas
  85. 16 18
      compiler/arm/narmcnv.pas
  86. 18 18
      compiler/arm/narmcon.pas
  87. 125 16
      compiler/arm/narminl.pas
  88. 12 26
      compiler/arm/narmmat.pas
  89. 4 3
      compiler/arm/narmmem.pas
  90. 29 12
      compiler/arm/narmset.pas
  91. 253 93
      compiler/arm/raarmgas.pas
  92. 7 0
      compiler/arm/rarmcon.inc
  93. 7 0
      compiler/arm/rarmdwa.inc
  94. 1 1
      compiler/arm/rarmnor.inc
  95. 8 1
      compiler/arm/rarmnum.inc
  96. 8 1
      compiler/arm/rarmrni.inc
  97. 8 1
      compiler/arm/rarmsri.inc
  98. 7 0
      compiler/arm/rarmsta.inc
  99. 9 2
      compiler/arm/rarmstd.inc
  100. 7 0
      compiler/arm/rarmsup.inc

File diff suppressed because it is too large
+ 398 - 52
.gitattributes


+ 18 - 27
.gitignore

@@ -1344,6 +1344,24 @@ packages/fcl-net/src/*.o
 packages/fcl-net/src/*.ppu
 packages/fcl-net/src/*.s
 packages/fcl-net/src/Package.fpc
+packages/fcl-net/src/amiga/*.bak
+packages/fcl-net/src/amiga/*.exe
+packages/fcl-net/src/amiga/*.o
+packages/fcl-net/src/amiga/*.ppu
+packages/fcl-net/src/amiga/*.s
+packages/fcl-net/src/amiga/Package.fpc
+packages/fcl-net/src/amiga/build-stamp.*
+packages/fcl-net/src/amiga/fpcmade.*
+packages/fcl-net/src/amiga/units
+packages/fcl-net/src/aros/*.bak
+packages/fcl-net/src/aros/*.exe
+packages/fcl-net/src/aros/*.o
+packages/fcl-net/src/aros/*.ppu
+packages/fcl-net/src/aros/*.s
+packages/fcl-net/src/aros/Package.fpc
+packages/fcl-net/src/aros/build-stamp.*
+packages/fcl-net/src/aros/fpcmade.*
+packages/fcl-net/src/aros/units
 packages/fcl-net/src/fpcmade.*
 packages/fcl-net/src/netware/*.bak
 packages/fcl-net/src/netware/*.exe
@@ -1801,15 +1819,6 @@ packages/gdbint/src/Package.fpc
 packages/gdbint/src/build-stamp.*
 packages/gdbint/src/fpcmade.*
 packages/gdbint/src/units
-packages/gdbint/tests/*.bak
-packages/gdbint/tests/*.exe
-packages/gdbint/tests/*.o
-packages/gdbint/tests/*.ppu
-packages/gdbint/tests/*.s
-packages/gdbint/tests/Package.fpc
-packages/gdbint/tests/build-stamp.*
-packages/gdbint/tests/fpcmade.*
-packages/gdbint/tests/units
 packages/gdbint/units
 packages/gdbm/*.bak
 packages/gdbm/*.exe
@@ -2723,15 +2732,6 @@ packages/imlib/*.ppu
 packages/imlib/*.s
 packages/imlib/Package.fpc
 packages/imlib/build-stamp.*
-packages/imlib/examples/*.bak
-packages/imlib/examples/*.exe
-packages/imlib/examples/*.o
-packages/imlib/examples/*.ppu
-packages/imlib/examples/*.s
-packages/imlib/examples/Package.fpc
-packages/imlib/examples/build-stamp.*
-packages/imlib/examples/fpcmade.*
-packages/imlib/examples/units
 packages/imlib/fpcmade.*
 packages/imlib/src/*.bak
 packages/imlib/src/*.exe
@@ -2742,15 +2742,6 @@ packages/imlib/src/Package.fpc
 packages/imlib/src/build-stamp.*
 packages/imlib/src/fpcmade.*
 packages/imlib/src/units
-packages/imlib/tests/*.bak
-packages/imlib/tests/*.exe
-packages/imlib/tests/*.o
-packages/imlib/tests/*.ppu
-packages/imlib/tests/*.s
-packages/imlib/tests/Package.fpc
-packages/imlib/tests/build-stamp.*
-packages/imlib/tests/fpcmade.*
-packages/imlib/tests/units
 packages/imlib/units
 packages/ldap/*.bak
 packages/ldap/*.exe

+ 130 - 16
Makefile

@@ -1,11 +1,11 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2014-04-01 rev 27428]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2015-09-05 rev 31523]
 #
 default: help
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-msdos spc32-embedded
-BSDs = freebsd netbsd openbsd darwin
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-msdos i8086-win16 aarch64-linux aarch64-darwin spc32-embedded
+BSDs = freebsd netbsd openbsd darwin dragonfly
 UNIXs = linux $(BSDs) solaris qnx haiku aix
-LIMIT83fs = go32v2 os2 emx watcom msdos
+LIMIT83fs = go32v2 os2 emx watcom msdos win16
 OSNeedsComspecToRunBatch = go32v2 watcom
 FORCE:
 .PHONY: FORCE
@@ -184,6 +184,12 @@ $(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t
 endif
 override FPCOPT+=-Cp$(SUBARCH)
 endif
+ifeq ($(FULL_TARGET),avr-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for avr-embedded, a sub-architecture (e.g. SUBARCH=avr25 or SUBARCH=avr35) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
 ifeq ($(FULL_TARGET),mipsel-embedded)
 ifeq ($(SUBARCH),)
 $(error When compiling for mipsel-embedded, a sub-architecture (e.g. SUBARCH=pic32mx) must be defined)
@@ -326,9 +332,8 @@ FPCFPMAKE=$(FPC)
 endif
 endif
 override PACKAGE_NAME=fpc
-override PACKAGE_VERSION=2.7.1
-REQUIREDVERSION=2.6.4
-REQUIREDVERSION2=2.6.2
+override PACKAGE_VERSION=3.1.1
+REQUIREDVERSION=3.0.0
 ifndef inOS2
 override FPCDIR:=$(BASEDIR)
 export FPCDIR
@@ -379,6 +384,9 @@ endif
 ifeq ($(CPU_TARGET),avr)
 PPSUF=avr
 endif
+ifeq ($(CPU_TARGET),aarch64)
+PPSUF=a64
+endif
 ifeq ($(CPU_TARGET),spc32)
 PPSUF=spc32
 endif
@@ -470,7 +478,7 @@ endif
 endif
 BuildOnlyBaseCPUs=jvm
 ifneq ($(wildcard utils),)
-NOUTILSTARGETS=embedded gba $(BuildOnlyBaseCPUs)
+NOUTILSTARGETS=embedded gba nds msdos win16 $(BuildOnlyBaseCPUs)
 ifeq ($(findstring $(OS_TARGET),$(NOUTILSTARGETS)),)
 ifdef BUILDFULLNATIVE
 UTILS=1
@@ -546,6 +554,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override TARGET_DIRS+=compiler rtl utils packages ide installer
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override TARGET_DIRS+=compiler rtl utils packages ide installer
 endif
@@ -633,6 +644,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override TARGET_DIRS+=compiler rtl utils packages ide installer
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override TARGET_DIRS+=compiler rtl utils packages ide installer
 endif
@@ -702,6 +722,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override TARGET_DIRS+=compiler rtl utils packages ide installer
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override TARGET_DIRS+=compiler rtl utils packages ide installer
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override TARGET_DIRS+=compiler rtl utils packages ide installer
 endif
@@ -948,6 +977,12 @@ EXEEXT=
 HASSHAREDLIB=1
 SHORTSUFFIX=lnx
 endif
+ifeq ($(OS_TARGET),dragonfly)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=df
+endif
 ifeq ($(OS_TARGET),freebsd)
 BATCHEXT=.sh
 EXEEXT=
@@ -993,6 +1028,11 @@ EXEEXT=
 SHAREDLIBEXT=.library
 SHORTSUFFIX=amg
 endif
+ifeq ($(OS_TARGET),aros)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=aros
+endif
 ifeq ($(OS_TARGET),morphos)
 EXEEXT=
 SHAREDLIBEXT=.library
@@ -1090,6 +1130,16 @@ STATICLIBPREFIX=
 STATICLIBEXT=.a
 SHORTSUFFIX=d16
 endif
+ifeq ($(OS_TARGET),embedded)
+EXEEXT=.bin
+SHORTSUFFIX=emb
+endif
+ifeq ($(OS_TARGET),win16)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w16
+endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
 FPCMADE=fpcmade.$(SHORTSUFFIX)
 ZIPSUFFIX=$(SHORTSUFFIX)
@@ -1356,6 +1406,7 @@ endif
 ifeq ($(OS_SOURCE),openbsd)
 override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
 override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPMAKE_BUILD_OPT+=-FD$(NEW_BINUTILS_PATH)
 endif
 ifndef CROSSBOOTSTRAP
 ifneq ($(BINUTILSPREFIX),)
@@ -1368,6 +1419,7 @@ endif
 ifndef CROSSCOMPILE
 ifneq ($(BINUTILSPREFIX),)
 override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+override FPMAKE_BUILD_OPT+=-XP$(BINUTILSPREFIX)
 endif
 endif
 ifdef UNITDIR
@@ -1457,8 +1509,8 @@ endif
 ifdef CREATESHARED
 override FPCOPT+=-Cg
 endif
-ifneq ($(findstring $(OS_TARGET),freebsd openbsd netbsd linux solaris),)
-ifeq ($(CPU_TARGET),x86_64)
+ifneq ($(findstring $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
+ifneq ($(findstring $(CPU_TARGET),x86_64 mips mipsel),)
 override FPCOPT+=-Cg
 endif
 endif
@@ -1467,6 +1519,9 @@ endif
 ifdef OPT
 override FPCOPT+=$(OPT)
 endif
+ifdef FPMAKEBUILDOPT
+override FPMAKE_BUILD_OPT+=$(FPMAKEBUILDOPT)
+endif
 ifdef FPCOPTDEF
 override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
 endif
@@ -1565,7 +1620,7 @@ endif
 fpc_sourceinstall: distclean
 	$(MKDIR) $(INSTALL_SOURCEDIR)
 	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
-fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+fpc_exampleinstall: $(EXAMPLEINSTALLTARGET) $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
 ifdef HASEXAMPLES
 	$(MKDIR) $(INSTALL_EXAMPLEDIR)
 endif
@@ -1737,6 +1792,10 @@ endif
 ifdef DEBUGSYMEXT
 	-$(DEL) *$(DEBUGSYMEXT)
 endif
+ifdef LOCALFPMAKEBIN
+	-$(DEL) $(LOCALFPMAKEBIN)
+	-$(DEL) $(FPMAKEBINOBJ)
+endif
 fpc_distclean: cleanall
 .PHONY: fpc_baseinfo
 override INFORULES+=fpc_baseinfo
@@ -2029,6 +2088,14 @@ TARGET_DIRS_PACKAGES=1
 TARGET_DIRS_IDE=1
 TARGET_DIRS_INSTALLER=1
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 TARGET_DIRS_COMPILER=1
 TARGET_DIRS_RTL=1
@@ -2261,6 +2328,30 @@ TARGET_DIRS_PACKAGES=1
 TARGET_DIRS_IDE=1
 TARGET_DIRS_INSTALLER=1
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 TARGET_DIRS_COMPILER=1
 TARGET_DIRS_RTL=1
@@ -2445,6 +2536,30 @@ TARGET_DIRS_PACKAGES=1
 TARGET_DIRS_IDE=1
 TARGET_DIRS_INSTALLER=1
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+TARGET_DIRS_COMPILER=1
+TARGET_DIRS_RTL=1
+TARGET_DIRS_UTILS=1
+TARGET_DIRS_PACKAGES=1
+TARGET_DIRS_IDE=1
+TARGET_DIRS_INSTALLER=1
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 TARGET_DIRS_COMPILER=1
 TARGET_DIRS_RTL=1
@@ -2749,8 +2864,7 @@ override TARGET_DIRS:=$(wildcard $(TARGET_DIRS))
 help:
 	@$(ECHO)
 	@$(ECHO) Targets
-	@$(ECHO)    all         Alias for build
-	@$(ECHO)    build       Build a new compiler and all packages
+	@$(ECHO)    all         Build a new compiler and all packages
 	@$(ECHO)    install     Install newly build files
 	@$(ECHO)    zipinstall  Create zip/tar of installed files
 	@$(ECHO)    singlezipinstall  Alias for zipinstall
@@ -2763,14 +2877,14 @@ BUILDSTAMP=build-stamp.$(FULL_TARGET)
 .PHONY: all clean distclean build buildbase install installbase
 .PHONY: installother zipinstallbase zipinstallotherzipinstall
 .PHONY: singlezipinstall versioncheckstartingcompiler
-versioncheckstartingcompiler: 
+versioncheckstartingcompiler:
 ifndef CROSSCOMPILE
 ifneq ($(FPC_VERSION),$(REQUIREDVERSION))
 ifneq ($(FPC_VERSION),$(REQUIREDVERSION2))
 ifndef OVERRIDEVERSIONCHECK
-	$(error The only supported starting compiler version is $(REQUIREDVERSION). You are trying to build with $(FPC_VERSION). If you are absolutely sure that the current compiler is built from the exact same version/revision, you can try to use OVERRIDEVERSIONCHECK=1 to override )
+	$(error The only supported starting compiler version is $(REQUIREDVERSION). You are trying to build with $(FPC_VERSION).)
 else
-	@$(ECHO) You have overriden the starting compiler versioncheck while using starting compiler version $(FPC_VERSION). This situation is not supported and strange things and errors may happen. Remove OVERRIDEVERSIONCHECK=1 to fix this. 
+	@$(ECHO) You have overriden the starting compiler versioncheck while using starting compiler version $(FPC_VERSION). This situation is not supported and strange things and errors may happen. Remove OVERRIDEVERSIONCHECK=1 to fix this.
 endif
 endif
 endif

+ 10 - 9
Makefile.fpc

@@ -4,7 +4,7 @@
 
 [package]
 name=fpc
-version=2.7.1
+version=3.1.1
 
 [target]
 dirs=compiler rtl utils packages ide installer
@@ -20,8 +20,7 @@ fpcdir=.
 rule=help
 
 [prerules]
-REQUIREDVERSION=2.6.4
-REQUIREDVERSION2=2.6.2
+REQUIREDVERSION=3.0.0
 
 
 # make versions < 3.77 (OS2 version) are buggy
@@ -79,6 +78,9 @@ endif
 ifeq ($(CPU_TARGET),avr)
 PPSUF=avr
 endif
+ifeq ($(CPU_TARGET),aarch64)
+PPSUF=a64
+endif
 ifeq ($(CPU_TARGET),spc32)
 PPSUF=spc32
 endif
@@ -207,7 +209,7 @@ endif
 BuildOnlyBaseCPUs=jvm
 
 ifneq ($(wildcard utils),)
-NOUTILSTARGETS=embedded gba $(BuildOnlyBaseCPUs)
+NOUTILSTARGETS=embedded gba nds msdos win16 $(BuildOnlyBaseCPUs)
 ifeq ($(findstring $(OS_TARGET),$(NOUTILSTARGETS)),)
 ifdef BUILDFULLNATIVE
 UTILS=1
@@ -233,8 +235,7 @@ override TARGET_DIRS:=$(wildcard $(TARGET_DIRS))
 help:
         @$(ECHO)
         @$(ECHO) Targets
-        @$(ECHO)    all         Alias for build
-        @$(ECHO)    build       Build a new compiler and all packages
+        @$(ECHO)    all         Build a new compiler and all packages
         @$(ECHO)    install     Install newly build files
         @$(ECHO)    zipinstall  Create zip/tar of installed files
         @$(ECHO)    singlezipinstall  Alias for zipinstall
@@ -266,14 +267,14 @@ BUILDSTAMP=build-stamp.$(FULL_TARGET)
 .PHONY: installother zipinstallbase zipinstallotherzipinstall
 .PHONY: singlezipinstall versioncheckstartingcompiler
 
-versioncheckstartingcompiler: 
+versioncheckstartingcompiler:
 ifndef CROSSCOMPILE
 ifneq ($(FPC_VERSION),$(REQUIREDVERSION))
 ifneq ($(FPC_VERSION),$(REQUIREDVERSION2))
 ifndef OVERRIDEVERSIONCHECK
-	$(error The only supported starting compiler version is $(REQUIREDVERSION). You are trying to build with $(FPC_VERSION). If you are absolutely sure that the current compiler is built from the exact same version/revision, you can try to use OVERRIDEVERSIONCHECK=1 to override )
+	$(error The only supported starting compiler version is $(REQUIREDVERSION). You are trying to build with $(FPC_VERSION).)
 else
-	@$(ECHO) You have overriden the starting compiler versioncheck while using starting compiler version $(FPC_VERSION). This situation is not supported and strange things and errors may happen. Remove OVERRIDEVERSIONCHECK=1 to fix this. 
+	@$(ECHO) You have overriden the starting compiler versioncheck while using starting compiler version $(FPC_VERSION). This situation is not supported and strange things and errors may happen. Remove OVERRIDEVERSIONCHECK=1 to fix this.
 endif
 endif
 endif

+ 244 - 35
compiler/Makefile

@@ -1,11 +1,11 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2014-04-01 rev 27428]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2015-09-05 rev 31523]
 #
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-msdos spc32-embedded
-BSDs = freebsd netbsd openbsd darwin
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-msdos i8086-win16 aarch64-linux aarch64-darwin spc32-embedded
+BSDs = freebsd netbsd openbsd darwin dragonfly
 UNIXs = linux $(BSDs) solaris qnx haiku aix
-LIMIT83fs = go32v2 os2 emx watcom msdos
+LIMIT83fs = go32v2 os2 emx watcom msdos win16
 OSNeedsComspecToRunBatch = go32v2 watcom
 FORCE:
 .PHONY: FORCE
@@ -184,6 +184,12 @@ $(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t
 endif
 override FPCOPT+=-Cp$(SUBARCH)
 endif
+ifeq ($(FULL_TARGET),avr-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for avr-embedded, a sub-architecture (e.g. SUBARCH=avr25 or SUBARCH=avr35) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
 ifeq ($(FULL_TARGET),mipsel-embedded)
 ifeq ($(SUBARCH),)
 $(error When compiling for mipsel-embedded, a sub-architecture (e.g. SUBARCH=pic32mx) must be defined)
@@ -326,13 +332,10 @@ FPCFPMAKE=$(FPC)
 endif
 endif
 override PACKAGE_NAME=compiler
-override PACKAGE_VERSION=2.7.1
+override PACKAGE_VERSION=3.1.1
 unexport FPC_VERSION FPC_COMPILERINFO
-CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086 spc32
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086 aarch64 spc32
 ALLTARGETS=$(CYCLETARGETS)
-ifdef ALPHA
-PPC_TARGET=alpha
-endif
 ifdef POWERPC
 PPC_TARGET=powerpc
 endif
@@ -375,6 +378,9 @@ endif
 ifdef I8086
 PPC_TARGET=i8086
 endif
+ifdef AARCH64
+PPC_TARGET=aarch64
+endif
 ifndef PPC_TARGET
 PPC_TARGET=$(CPU_TARGET)
 endif
@@ -436,11 +442,9 @@ MSGFILES=$(wildcard msg/error*.msg)
 ifeq ($(CPC_TARGET),i386)
 CPUSUF=386
 endif
-ifeq ($(CPC_TARGET),alpha)
-CPUSUF=axp
-endif
 ifeq ($(CPC_TARGET),m68k)
 CPUSUF=68k
+ALLOW_WARNINGS=1
 endif
 ifeq ($(CPC_TARGET),powerpc)
 CPUSUF=ppc
@@ -465,6 +469,7 @@ CPUSUF=mipsel
 endif
 ifeq ($(CPC_TARGET),avr)
 CPUSUF=avr
+ALLOW_WARNINGS=1
 endif
 ifeq ($(CPC_TARGET),spc32)
 CPUSUF=spc32
@@ -475,6 +480,9 @@ endif
 ifeq ($(CPC_TARGET),i8086)
 CPUSUF=8086
 endif
+ifeq ($(CPC_TARGET),aarch64)
+CPUSUF=a64
+endif
 NOCPUDEF=1
 MSGFILE=msg/error$(FPCLANG).msg
 SVNVERSION:=$(firstword $(wildcard $(addsuffix /svnversion$(SRCEXEEXT),$(SEARCHPATH))))
@@ -483,7 +491,7 @@ ifneq ($(REVINC),)
 override LOCALOPT+=-dREVINC
 ifeq ($(REVSTR),)
 ifneq ($(SVNVERSION),)
-REVSTR:=$(shell $(SVNVERSION) -c .)
+REVSTR:=$(subst r,,$(subst r1:,,r$(shell $(SVNVERSION) -c .)))
 export REVSTR
 else
 ifeq ($(REVINC),force)
@@ -507,16 +515,11 @@ ifeq ($(PPC_TARGET),powerpc64)
 override LOCALOPT+=-Fuppcgen
 endif
 ifeq ($(PPC_TARGET),m68k)
-override LOCALOPT+=-dNOOPT
+override LOCALOPT+=
 endif
 ifeq ($(PPC_TARGET),sparc)
 override LOCALOPT+=
 endif
-ifeq ($(PPC_TARGET),m68k)
-ifeq ($(OS_TARGET),amiga)
-override LOCALOPT+=-Ct
-endif
-endif
 ifeq ($(PPC_TARGET),arm)
 override LOCALOPT+=
 endif
@@ -524,14 +527,14 @@ ifeq ($(PPC_TARGET),mipsel)
 override LOCALOPT+=-Fumips
 endif
 ifeq ($(PPC_TARGET),jvm)
-override LOCALOPT+=-Fujvm -dNOOPT
+override LOCALOPT+=-Fujvm
 endif
 ifeq ($(PPC_TARGET),i8086)
 override LOCALOPT+=-Fux86
 endif
 OPTWPOCOLLECT=-OWdevirtcalls,optvmts -FW$(BASEDIR)/pp1.wpo
 OPTWPOPERFORM=-Owdevirtcalls,optvmts -Fw$(BASEDIR)/pp1.wpo
-ifneq ($(findstring $(OS_TARGET),darwin linux freebsd solaris),)
+ifneq ($(findstring $(OS_TARGET),darwin linux dragonfly freebsd solaris),)
 ifdef LINKSMART
 ifdef CREATESMART
 OPTWPOCOLLECT+=-OWsymbolliveness -Xs-
@@ -551,6 +554,12 @@ endif
 ifeq ($(OS_TARGET),msdos)
 NoNativeBinaries=1
 endif
+ifeq ($(OS_TARGET),nds)
+NoNativeBinaries=1
+endif
+ifeq ($(OS_TARGET),win16)
+NoNativeBinaries=1
+endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_DIRS+=utils
 endif
@@ -620,6 +629,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override TARGET_DIRS+=utils
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override TARGET_DIRS+=utils
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override TARGET_DIRS+=utils
 endif
@@ -707,6 +719,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override TARGET_DIRS+=utils
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override TARGET_DIRS+=utils
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override TARGET_DIRS+=utils
 endif
@@ -776,6 +797,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override TARGET_DIRS+=utils
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override TARGET_DIRS+=utils
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override TARGET_DIRS+=utils
 endif
@@ -848,6 +878,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override TARGET_PROGRAMS+=pp
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override TARGET_PROGRAMS+=pp
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override TARGET_PROGRAMS+=pp
 endif
@@ -935,6 +968,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override TARGET_PROGRAMS+=pp
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override TARGET_PROGRAMS+=pp
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override TARGET_PROGRAMS+=pp
 endif
@@ -1004,6 +1046,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override TARGET_PROGRAMS+=pp
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override TARGET_PROGRAMS+=pp
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override TARGET_PROGRAMS+=pp
 endif
@@ -1077,6 +1128,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
@@ -1164,6 +1218,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
@@ -1233,6 +1296,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
@@ -1305,6 +1377,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
@@ -1392,6 +1467,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
@@ -1461,6 +1545,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
@@ -1533,6 +1626,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override COMPILER_TARGETDIR+=.
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override COMPILER_TARGETDIR+=.
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override COMPILER_TARGETDIR+=.
 endif
@@ -1620,6 +1716,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override COMPILER_TARGETDIR+=.
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override COMPILER_TARGETDIR+=.
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override COMPILER_TARGETDIR+=.
 endif
@@ -1689,6 +1794,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override COMPILER_TARGETDIR+=.
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override COMPILER_TARGETDIR+=.
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override COMPILER_TARGETDIR+=.
 endif
@@ -1761,6 +1875,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
@@ -1848,6 +1965,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
@@ -1917,6 +2043,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
@@ -2162,6 +2297,12 @@ EXEEXT=
 HASSHAREDLIB=1
 SHORTSUFFIX=lnx
 endif
+ifeq ($(OS_TARGET),dragonfly)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=df
+endif
 ifeq ($(OS_TARGET),freebsd)
 BATCHEXT=.sh
 EXEEXT=
@@ -2207,6 +2348,11 @@ EXEEXT=
 SHAREDLIBEXT=.library
 SHORTSUFFIX=amg
 endif
+ifeq ($(OS_TARGET),aros)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=aros
+endif
 ifeq ($(OS_TARGET),morphos)
 EXEEXT=
 SHAREDLIBEXT=.library
@@ -2304,6 +2450,16 @@ STATICLIBPREFIX=
 STATICLIBEXT=.a
 SHORTSUFFIX=d16
 endif
+ifeq ($(OS_TARGET),embedded)
+EXEEXT=.bin
+SHORTSUFFIX=emb
+endif
+ifeq ($(OS_TARGET),win16)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w16
+endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
 FPCMADE=fpcmade.$(SHORTSUFFIX)
 ZIPSUFFIX=$(SHORTSUFFIX)
@@ -2628,6 +2784,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 REQUIRE_PACKAGES_RTL=1
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+REQUIRE_PACKAGES_RTL=1
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 REQUIRE_PACKAGES_RTL=1
 endif
@@ -2715,6 +2874,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 REQUIRE_PACKAGES_RTL=1
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+REQUIRE_PACKAGES_RTL=1
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 REQUIRE_PACKAGES_RTL=1
 endif
@@ -2784,6 +2952,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 REQUIRE_PACKAGES_RTL=1
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 REQUIRE_PACKAGES_RTL=1
 endif
@@ -2837,6 +3014,7 @@ endif
 ifeq ($(OS_SOURCE),openbsd)
 override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
 override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPMAKE_BUILD_OPT+=-FD$(NEW_BINUTILS_PATH)
 endif
 ifndef CROSSBOOTSTRAP
 ifneq ($(BINUTILSPREFIX),)
@@ -2849,6 +3027,7 @@ endif
 ifndef CROSSCOMPILE
 ifneq ($(BINUTILSPREFIX),)
 override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+override FPMAKE_BUILD_OPT+=-XP$(BINUTILSPREFIX)
 endif
 endif
 ifdef UNITDIR
@@ -2938,8 +3117,8 @@ endif
 ifdef CREATESHARED
 override FPCOPT+=-Cg
 endif
-ifneq ($(findstring $(OS_TARGET),freebsd openbsd netbsd linux solaris),)
-ifeq ($(CPU_TARGET),x86_64)
+ifneq ($(findstring $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
+ifneq ($(findstring $(CPU_TARGET),x86_64 mips mipsel),)
 override FPCOPT+=-Cg
 endif
 endif
@@ -2948,6 +3127,9 @@ endif
 ifdef OPT
 override FPCOPT+=$(OPT)
 endif
+ifdef FPMAKEBUILDOPT
+override FPMAKE_BUILD_OPT+=$(FPMAKEBUILDOPT)
+endif
 ifdef FPCOPTDEF
 override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
 endif
@@ -3139,7 +3321,7 @@ endif
 fpc_sourceinstall: distclean
 	$(MKDIR) $(INSTALL_SOURCEDIR)
 	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
-fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+fpc_exampleinstall: $(EXAMPLEINSTALLTARGET) $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
 ifdef HASEXAMPLES
 	$(MKDIR) $(INSTALL_EXAMPLEDIR)
 endif
@@ -3311,6 +3493,10 @@ endif
 ifdef DEBUGSYMEXT
 	-$(DEL) *$(DEBUGSYMEXT)
 endif
+ifdef LOCALFPMAKEBIN
+	-$(DEL) $(LOCALFPMAKEBIN)
+	-$(DEL) $(FPMAKEBINOBJ)
+endif
 fpc_distclean: cleanall
 .PHONY: fpc_baseinfo
 override INFORULES+=fpc_baseinfo
@@ -3488,6 +3674,9 @@ endif
 ifeq ($(FULL_TARGET),i386-android)
 TARGET_DIRS_UTILS=1
 endif
+ifeq ($(FULL_TARGET),i386-aros)
+TARGET_DIRS_UTILS=1
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 TARGET_DIRS_UTILS=1
 endif
@@ -3575,6 +3764,15 @@ endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 TARGET_DIRS_UTILS=1
 endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+TARGET_DIRS_UTILS=1
+endif
 ifeq ($(FULL_TARGET),arm-linux)
 TARGET_DIRS_UTILS=1
 endif
@@ -3644,6 +3842,15 @@ endif
 ifeq ($(FULL_TARGET),i8086-msdos)
 TARGET_DIRS_UTILS=1
 endif
+ifeq ($(FULL_TARGET),i8086-win16)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+TARGET_DIRS_UTILS=1
+endif
 ifeq ($(FULL_TARGET),spc32-embedded)
 TARGET_DIRS_UTILS=1
 endif
@@ -3775,7 +3982,7 @@ INSTALLEXEFILE=$(PPCROSSNAME)
 else
 INSTALLEXEFILE=$(EXENAME)
 endif
-PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 alpha vis ia64 mips mipsel avr jvm i8086 spc32
+PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 spc32
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS)))
 .PHONY: $(PPC_TARGETS) $(INSTALL_TARGETS)
 $(PPC_TARGETS):
@@ -3810,11 +4017,14 @@ ppuclean:
 tempclean:
 	-$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC) pp1.wpo pp2.wpo
 execlean :
-	-$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppcspc32$(EXEEXT) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
+	-$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT)
+	-$(DEL) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppca64$(EXEEXT) ppcspc32$(EXEEXT)
+	-$(DEL) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
 $(addsuffix _clean,$(ALLTARGETS)):
 	-$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
 	-$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
-	-$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppcspc32$(EXEEXT) $(EXENAME))
+	-$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT))
+	-$(DEL) $(addprefix $(subst _clean,,$@)/,ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppca64$(EXEEXT) ppcspc32$(EXEEXT) $(EXENAME))
 cycleclean: cleanall $(addsuffix _clean,$(CPC_TARGET))
 	-$(DEL) $(EXENAME)
 clean: tempclean execlean cleanall $(addsuffix _clean,$(CPC_TARGET)) $(addsuffix _clean,$(TARGET_DIRS))
@@ -3847,9 +4057,6 @@ insdat: insdatx86 insdatarm insdataarch64
 regdatarm : arm/armreg.dat
 	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmreg.pp
 	cd arm && ..$(PATHSEP)utils$(PATHSEP)mkarmreg$(SRCEXEEXT)
-regdatia64 : ia64/ia64reg.dat
-	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkia64reg.pp
-	cd ia64 && ..$(PATHSEP)utils$(PATHSEP)mkia64reg$(SRCEXEEXT)
 regdatsp : sparc/spreg.dat
 	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkspreg.pp
 	cd sparc && ..$(PATHSEP)utils$(PATHSEP)mkspreg$(SRCEXEEXT)
@@ -3966,13 +4173,11 @@ cycle:
 	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
 ifndef CROSSINSTALL
 	$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl CYCLELEVEL=3
-ifneq ($(OS_TARGET),embedded)
-ifneq ($(OS_TARGET),gba)
+ifndef NoNativeBinaries
 	$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler CYCLELEVEL=3
 endif
 endif
 endif
-endif
 else
 cycle: override FPC=
 cycle:
@@ -3997,10 +4202,10 @@ full: fullcycle
 fullcycle:
 	$(MAKE) cycle
 	$(MAKE) ppuclean
-ifneq ($(CPU_SOURCE),x86_64)
+ifneq ($(OS_SOURCE),win64)
 	$(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
 else
-	$(MAKE) $(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS))) 'FPC=$(BASEDIR)/$(EXENAME)'
+	$(MAKE) $(filter-out i8086,$(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))) 'FPC=$(BASEDIR)/$(EXENAME)'
 endif
 htmldocs:
 	$(PASDOC) -p -h -o html$(PATHSEP)$(PPC_TARGET) -d fpc -d gdb -d $(PPC_TARGET) -u $(PPC_TARGET) $(PPC_TARGET)$(PATHSEP)*.pas systems$(PATHSEP)*.pas *.pas
@@ -4027,7 +4232,11 @@ endif
 	$(INSTALLEXE) $(INSTALLEXEFILE) $(PPCCPULOCATION)/$(INSTALLEXEFILE)
 endif
 fullinstall:
+ifneq ($(OS_SOURCE),win64)
 	$(MAKE) $(addsuffix _exe_install,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))
+else
+	$(MAKE) $(addsuffix _exe_install,$(filter-out i8086,$(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))))
+endif
 install: quickinstall
 ifndef CROSSINSTALL
 ifdef UNIXHier

+ 36 - 36
compiler/Makefile.fpc

@@ -4,7 +4,7 @@
 
 [package]
 name=compiler
-version=2.7.1
+version=3.1.1
 
 [target]
 programs=pp
@@ -32,15 +32,12 @@ 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 jvm i8086 spc32
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086 aarch64 spc32
 
 # All supported targets used for clean
 ALLTARGETS=$(CYCLETARGETS)
 
-# Allow ALPHA, POWERPC, POWERPC64, M68K, I386, jvm defines for target cpu
-ifdef ALPHA
-PPC_TARGET=alpha
-endif
+# Allow POWERPC, POWERPC64, M68K, I386, jvm defines for target cpu
 ifdef POWERPC
 PPC_TARGET=powerpc
 endif
@@ -83,6 +80,9 @@ endif
 ifdef I8086
 PPC_TARGET=i8086
 endif
+ifdef AARCH64
+PPC_TARGET=aarch64
+endif
 
 # Default is to generate a compiler for the same
 # platform as CPU_TARGET (a native compiler)
@@ -172,11 +172,9 @@ MSGFILES=$(wildcard msg/error*.msg)
 ifeq ($(CPC_TARGET),i386)
 CPUSUF=386
 endif
-ifeq ($(CPC_TARGET),alpha)
-CPUSUF=axp
-endif
 ifeq ($(CPC_TARGET),m68k)
 CPUSUF=68k
+ALLOW_WARNINGS=1
 endif
 ifeq ($(CPC_TARGET),powerpc)
 CPUSUF=ppc
@@ -201,6 +199,7 @@ CPUSUF=mipsel
 endif
 ifeq ($(CPC_TARGET),avr)
 CPUSUF=avr
+ALLOW_WARNINGS=1
 endif
 ifeq ($(CPC_TARGET),spc32)
 CPUSUF=spc32
@@ -211,6 +210,9 @@ endif
 ifeq ($(CPC_TARGET),i8086)
 CPUSUF=8086
 endif
+ifeq ($(CPC_TARGET),aarch64)
+CPUSUF=a64
+endif
 
 # Do not define the default -d$(CPU_TARGET) because that
 # will conflict with our -d$(CPC_TARGET)
@@ -231,7 +233,7 @@ override LOCALOPT+=-dREVINC
 # svnversion executable is available
 ifeq ($(REVSTR),)
 ifneq ($(SVNVERSION),)
-REVSTR:=$(shell $(SVNVERSION) -c .)
+REVSTR:=$(subst r,,$(subst r1:,,r$(shell $(SVNVERSION) -c .)))
 export REVSTR
 else
 ifeq ($(REVINC),force)
@@ -267,7 +269,7 @@ endif
 
 # m68k specific
 ifeq ($(PPC_TARGET),m68k)
-override LOCALOPT+=-dNOOPT
+override LOCALOPT+=
 endif
 
 # Sparc specific
@@ -275,13 +277,6 @@ ifeq ($(PPC_TARGET),sparc)
 override LOCALOPT+=
 endif
 
-# m68k specific with low stack
-ifeq ($(PPC_TARGET),m68k)
-ifeq ($(OS_TARGET),amiga)
-override LOCALOPT+=-Ct
-endif
-endif
-
 # ARM specific
 ifeq ($(PPC_TARGET),arm)
 override LOCALOPT+=
@@ -294,7 +289,7 @@ endif
 
 # jvm specific
 ifeq ($(PPC_TARGET),jvm)
-override LOCALOPT+=-Fujvm -dNOOPT
+override LOCALOPT+=-Fujvm
 endif
 
 # i8086 specific
@@ -306,7 +301,7 @@ OPTWPOCOLLECT=-OWdevirtcalls,optvmts -FW$(BASEDIR)/pp1.wpo
 OPTWPOPERFORM=-Owdevirtcalls,optvmts -Fw$(BASEDIR)/pp1.wpo
 # symbol liveness WPO requires nm, smart linking and no stripping (the latter
 # is forced by the Makefile when necessary)
-ifneq ($(findstring $(OS_TARGET),darwin linux freebsd solaris),)
+ifneq ($(findstring $(OS_TARGET),darwin linux dragonfly freebsd solaris),)
 ifdef LINKSMART
 ifdef CREATESMART
 OPTWPOCOLLECT+=-OWsymbolliveness -Xs-
@@ -329,6 +324,12 @@ endif
 ifeq ($(OS_TARGET),msdos)
 NoNativeBinaries=1
 endif
+ifeq ($(OS_TARGET),nds)
+NoNativeBinaries=1
+endif
+ifeq ($(OS_TARGET),win16)
+NoNativeBinaries=1
+endif
 
 [rules]
 #####################################################################
@@ -403,7 +404,7 @@ endif
 # CPU targets
 #####################################################################
 
-PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 alpha vis ia64 mips mipsel avr jvm i8086 spc32
+PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 spc32
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS)))
 
 .PHONY: $(PPC_TARGETS) $(INSTALL_TARGETS)
@@ -458,12 +459,15 @@ tempclean:
         -$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC) pp1.wpo pp2.wpo
 
 execlean :
-        -$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppcspc32$(EXEEXT) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
+        -$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT)
+        -$(DEL) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppca64$(EXEEXT) ppcspc32$(EXEEXT)
+        -$(DEL) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
 
 $(addsuffix _clean,$(ALLTARGETS)):
         -$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
         -$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
-        -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppcspc32$(EXEEXT) $(EXENAME))
+        -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT))
+        -$(DEL) $(addprefix $(subst _clean,,$@)/,ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppca64$(EXEEXT) ppcspc32$(EXEEXT) $(EXENAME))
 
 cycleclean: cleanall $(addsuffix _clean,$(CPC_TARGET))
         -$(DEL) $(EXENAME)
@@ -515,10 +519,6 @@ regdatarm : arm/armreg.dat
 	    $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmreg.pp
         cd arm && ..$(PATHSEP)utils$(PATHSEP)mkarmreg$(SRCEXEEXT)
 
-regdatia64 : ia64/ia64reg.dat
-            $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkia64reg.pp
-        cd ia64 && ..$(PATHSEP)utils$(PATHSEP)mkia64reg$(SRCEXEEXT)
-
 regdatsp : sparc/spreg.dat
             $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkspreg.pp
         cd sparc && ..$(PATHSEP)utils$(PATHSEP)mkspreg$(SRCEXEEXT)
@@ -688,14 +688,10 @@ cycle:
 # ppc<ARCH> (target native)
 ifndef CROSSINSTALL
         $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl CYCLELEVEL=3
-# building a native compiler for embedded targets is not possible
-ifneq ($(OS_TARGET),embedded)
-# building a native compiler for the arm-gba target is not possible
-ifneq ($(OS_TARGET),gba)
+ifndef NoNativeBinaries
         $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler CYCLELEVEL=3
 endif
 endif
-endif
 
 endif
 
@@ -721,7 +717,6 @@ cycle:
 # ppc<ARCH> (target native)
 ifndef CROSSINSTALL
         $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(RTLOPT) $(CROSSOPT)' rtlclean rtl CYCLELEVEL=3
-# building a native compiler for JVM and embedded targets is not possible
 ifndef NoNativeBinaries
         $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(strip $(LOCALOPT) $(CROSSOPT))' cycleclean compiler CYCLELEVEL=3
 endif
@@ -748,17 +743,18 @@ cvstest:
 # 2. remove all .ppufiles
 # 3. build all supported cross compilers except the
 #    current PPC_TARGET which was already build
-#
+# unless FPC_SUPPORT_X87_TYPES_ON_WIN64 is set,
+# win64 cannot compile i386 or i8086 compiler
 
 full: fullcycle
 
 fullcycle:
         $(MAKE) cycle
         $(MAKE) ppuclean
-ifneq ($(CPU_SOURCE),x86_64)
+ifneq ($(OS_SOURCE),win64)
         $(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
 else
-        $(MAKE) $(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS))) 'FPC=$(BASEDIR)/$(EXENAME)'
+        $(MAKE) $(filter-out i8086,$(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))) 'FPC=$(BASEDIR)/$(EXENAME)'
 endif
 
 #####################################################################
@@ -805,7 +801,11 @@ endif
 endif
 
 fullinstall:
+ifneq ($(OS_SOURCE),win64)
         $(MAKE) $(addsuffix _exe_install,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))
+else
+        $(MAKE) $(addsuffix _exe_install,$(filter-out i8086,$(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))))
+endif
 
 install: quickinstall
 ifndef CROSSINSTALL

+ 94 - 36
compiler/aarch64/a64att.inc

@@ -1,14 +1,37 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
+'none',
 'b',
-'cb',
-'tb',
+'cbz',
+'cbnz',
+'tbz',
+'tbnz',
 'bl',
 'blr',
 'br',
 'ret',
+'brk',
+'hlt',
+'hvc',
+'smc',
+'svc',
+'eret',
+'dcps1',
+'dcps2',
+'dcps3',
+'drps',
+'dc',
+'at',
+'tlbi',
+'hint',
+'clrex',
+'dsb',
+'dmb',
+'isb',
 'ldr',
 'str',
+'ldur',
+'stur',
 'ldp',
 'stp',
 'ldnp',
@@ -16,40 +39,66 @@
 'ldtr',
 'sttr',
 'ldxr',
+'ldxp',
 'stxr',
+'stxp',
 'ldar',
 'stlr',
 'ldaxr',
 'stlxr',
+'stlxp',
+'ld1',
+'ld2',
+'ld3',
+'ld4',
+'st1',
+'st2',
+'st3',
+'st4',
+'ld1r',
+'ld2r',
+'ld3r',
+'ld4r',
 'prfm',
+'prfum',
 'add',
-'adc',
 'sub',
-'sbc',
 'cmp',
 'cmn',
-'mov',
 'and',
-'bic',
 'eor',
-'eon',
 'orr',
 'orn',
 'tst',
-'mvn',
+'movz',
+'movn',
 'movk',
+'mrs',
+'msr',
 'adrp',
 'adr',
 'bfm',
 'sbfm',
 'ubfm',
 'extr',
-'sxt',
-'uxt',
+'adc',
+'sbc',
+'bic',
+'eon',
 'asrv',
-'llslv',
+'lslv',
 'lsrv',
 'rorv',
+'madd',
+'msub',
+'smaddl',
+'smsubl',
+'smulh',
+'umaddl',
+'umsubl',
+'umulh',
+'sdiv',
+'udiv',
 'cls',
 'clz',
 'rbit',
@@ -62,33 +111,39 @@
 'csneg',
 'ccmn',
 'ccmp',
-'madd',
-'msub',
-'smaddl',
-'smsubl',
-'smulh',
-'umaddl',
-'umsubl',
-'umulh',
-'sdiv',
-'udiv',
-'neg',
+'nop',
+'yield',
+'wfe',
+'wfi',
+'sev',
+'sevl',
+'mov',
+'bfi',
+'bfxil',
+'sbfiz',
+'sbfx',
+'ubfiz',
+'ubfx',
 'asr',
 'lsl',
 'lsr',
 'ror',
-'cset',
-'csetm',
-'cinc',
-'cinv',
-'cneg',
+'sxt',
+'uxt',
+'neg',
 'ngc',
+'mvn',
 'mneg',
 'mul',
 'smnegl',
 'smull',
 'umnegl',
 'umull',
+'cset',
+'csetm',
+'cinc',
+'cinv',
+'cneg',
 'fmov',
 'fcvt',
 'fcvtas',
@@ -103,13 +158,13 @@
 'fcvtzu',
 'scvtf',
 'ucvtf',
-'fprinta',
-'fprinti',
-'fprintm',
-'fprintn',
-'fprintp',
-'fprintx',
-'fprintz',
+'frinta',
+'frinti',
+'frintm',
+'frintn',
+'frintp',
+'frintx',
+'frintz',
 'fabs',
 'fneg',
 'fsqrt',
@@ -129,5 +184,8 @@
 'fcmpe',
 'fccmp',
 'fcmmpe',
-'fcsel'
+'fcsel',
+'umov',
+'ins',
+'movi'
 );

+ 59 - 1
compiler/aarch64/a64atts.inc

@@ -1,4 +1,4 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
 attsufNONE,
 attsufNONE,
@@ -129,5 +129,63 @@ 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
 );

+ 159 - 43
compiler/aarch64/a64ins.dat

@@ -1,8 +1,15 @@
+; invalid
+[NONE]
+
 [B]
 
-[CB]
+[CBZ]
+
+[CBNZ]
 
-[TB]
+[TBZ]
+
+[TBNZ]
 
 [BL]
 
@@ -12,10 +19,50 @@
 
 [RET]
 
+[BRK]
+
+[HLT]
+
+[HVC]
+
+[SMC]
+
+[SVC]
+
+[ERET]
+
+[DCPS1]
+
+[DCPS2]
+
+[DCPS3]
+
+[DRPS]
+
+[DC]
+
+[AT]
+
+[TLBI]
+
+[HINT]
+
+[CLREX]
+
+[DSB]
+
+[DMB]
+
+[ISB]
+
 [LDR]
 
 [STR]
 
+[LDUR]
+
+[STUR]
+
 [LDP]
 
 [STP]
@@ -30,8 +77,12 @@
 
 [LDXR]
 
+[LDXP]
+
 [STXR]
 
+[STXP]
+
 [LDAR]
 
 [STLR]
@@ -40,40 +91,64 @@
 
 [STLXR]
 
+[STLXP]
+
+[LD1]
+
+[LD2]
+
+[LD3]
+
+[LD4]
+
+[ST1]
+
+[ST2]
+
+[ST3]
+
+[ST4]
+
+[LD1R]
+
+[LD2R]
+
+[LD3R]
+
+[LD4R]
+
 [PRFM]
 
-[ADD]
+[PRFUM]
 
-[ADC]
+[ADD]
 
 [SUB]
 
-[SBC]
-
 [CMP]
 
 [CMN]
 
-[MOV]
-
 [AND]
 
-[BIC]
-
 [EOR]
 
-[EON]
-
 [ORR]
 
 [ORN]
 
 [TST]
 
-[MVN]
+[MOVZ]
+
+[MOVN]
 
 [MOVK]
 
+[MRS]
+
+[MSR]
+
 [ADRP]
 
 [ADR]
@@ -86,18 +161,42 @@
 
 [EXTR]
 
-[SXT]
+[ADC]
 
-[UXT]
+[SBC]
+
+[BIC]
+
+[EON]
 
 [ASRV]
 
-[LLSLV]
+[LSLV]
 
 [LSRV]
 
 [RORV]
 
+[MADD]
+
+[MSUB]
+
+[SMADDL]
+
+[SMSUBL]
+
+[SMULH]
+
+[UMADDL]
+
+[UMSUBL]
+
+[UMULH]
+
+[SDIV]
+
+[UDIV]
+
 [CLS]
 
 [CLZ]
@@ -122,29 +221,33 @@
 
 [CCMP]
 
-[MADD]
+; Aliases
+; they are not generated by the compiler, they are only used for inline assembler
+[NOP]
 
-[MSUB]
+[YIELD]
 
-[SMADDL]
+[WFE]
 
-[SMSUBL]
+[WFI]
 
-[SMULH]
+[SEV]
 
-[UMADDL]
+[SEVL]
 
-[UMSUBL]
+[MOV]
 
-[UMULH]
+[BFI]
 
-[SDIV]
+[BFXIL]
 
-[UDIV]
+[SBFIZ]
 
-; Aliases
-; they are not generated by the compiler, they are only used for inline assembler
-[NEG]
+[SBFX]
+
+[UBFIZ]
+
+[UBFX]
 
 [ASR]
 
@@ -154,18 +257,16 @@
 
 [ROR]
 
-[CSET]
-
-[CSETM]
-
-[CINC]
+[SXT]
 
-[CINV]
+[UXT]
 
-[CNEG]
+[NEG]
 
 [NGC]
 
+[MVN]
+
 [MNEG]
 
 [MUL]
@@ -178,6 +279,16 @@
 
 [UMULL]
 
+[CSET]
+
+[CSETM]
+
+[CINC]
+
+[CINV]
+
+[CNEG]
+
 [FMOV]
 
 [FCVT]
@@ -206,19 +317,19 @@
 
 [UCVTF]
 
-[FPRINTA]
+[FRINTA]
 
-[FPRINTI]
+[FRINTI]
 
-[FPRINTM]
+[FRINTM]
 
-[FPRINTN]
+[FRINTN]
 
-[FPRINTP]
+[FRINTP]
 
-[FPRINTX]
+[FRINTX]
 
-[FPRINTZ]
+[FRINTZ]
 
 [FABS]
 
@@ -260,3 +371,8 @@
 
 [FCSEL]
 
+[UMOV]
+
+[INS]
+
+[MOVI]

+ 94 - 36
compiler/aarch64/a64op.inc

@@ -1,14 +1,37 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
+A_NONE,
 A_B,
-A_CB,
-A_TB,
+A_CBZ,
+A_CBNZ,
+A_TBZ,
+A_TBNZ,
 A_BL,
 A_BLR,
 A_BR,
 A_RET,
+A_BRK,
+A_HLT,
+A_HVC,
+A_SMC,
+A_SVC,
+A_ERET,
+A_DCPS1,
+A_DCPS2,
+A_DCPS3,
+A_DRPS,
+A_DC,
+A_AT,
+A_TLBI,
+A_HINT,
+A_CLREX,
+A_DSB,
+A_DMB,
+A_ISB,
 A_LDR,
 A_STR,
+A_LDUR,
+A_STUR,
 A_LDP,
 A_STP,
 A_LDNP,
@@ -16,40 +39,66 @@ A_STNP,
 A_LDTR,
 A_STTR,
 A_LDXR,
+A_LDXP,
 A_STXR,
+A_STXP,
 A_LDAR,
 A_STLR,
 A_LDAXR,
 A_STLXR,
+A_STLXP,
+A_LD1,
+A_LD2,
+A_LD3,
+A_LD4,
+A_ST1,
+A_ST2,
+A_ST3,
+A_ST4,
+A_LD1R,
+A_LD2R,
+A_LD3R,
+A_LD4R,
 A_PRFM,
+A_PRFUM,
 A_ADD,
-A_ADC,
 A_SUB,
-A_SBC,
 A_CMP,
 A_CMN,
-A_MOV,
 A_AND,
-A_BIC,
 A_EOR,
-A_EON,
 A_ORR,
 A_ORN,
 A_TST,
-A_MVN,
+A_MOVZ,
+A_MOVN,
 A_MOVK,
+A_MRS,
+A_MSR,
 A_ADRP,
 A_ADR,
 A_BFM,
 A_SBFM,
 A_UBFM,
 A_EXTR,
-A_SXT,
-A_UXT,
+A_ADC,
+A_SBC,
+A_BIC,
+A_EON,
 A_ASRV,
-A_LLSLV,
+A_LSLV,
 A_LSRV,
 A_RORV,
+A_MADD,
+A_MSUB,
+A_SMADDL,
+A_SMSUBL,
+A_SMULH,
+A_UMADDL,
+A_UMSUBL,
+A_UMULH,
+A_SDIV,
+A_UDIV,
 A_CLS,
 A_CLZ,
 A_RBIT,
@@ -62,33 +111,39 @@ A_CSINV,
 A_CSNEG,
 A_CCMN,
 A_CCMP,
-A_MADD,
-A_MSUB,
-A_SMADDL,
-A_SMSUBL,
-A_SMULH,
-A_UMADDL,
-A_UMSUBL,
-A_UMULH,
-A_SDIV,
-A_UDIV,
-A_NEG,
+A_NOP,
+A_YIELD,
+A_WFE,
+A_WFI,
+A_SEV,
+A_SEVL,
+A_MOV,
+A_BFI,
+A_BFXIL,
+A_SBFIZ,
+A_SBFX,
+A_UBFIZ,
+A_UBFX,
 A_ASR,
 A_LSL,
 A_LSR,
 A_ROR,
-A_CSET,
-A_CSETM,
-A_CINC,
-A_CINV,
-A_CNEG,
+A_SXT,
+A_UXT,
+A_NEG,
 A_NGC,
+A_MVN,
 A_MNEG,
 A_MUL,
 A_SMNEGL,
 A_SMULL,
 A_UMNEGL,
 A_UMULL,
+A_CSET,
+A_CSETM,
+A_CINC,
+A_CINV,
+A_CNEG,
 A_FMOV,
 A_FCVT,
 A_FCVTAS,
@@ -103,13 +158,13 @@ A_FCVTZS,
 A_FCVTZU,
 A_SCVTF,
 A_UCVTF,
-A_FPRINTA,
-A_FPRINTI,
-A_FPRINTM,
-A_FPRINTN,
-A_FPRINTP,
-A_FPRINTX,
-A_FPRINTZ,
+A_FRINTA,
+A_FRINTI,
+A_FRINTM,
+A_FRINTN,
+A_FRINTP,
+A_FRINTX,
+A_FRINTZ,
 A_FABS,
 A_FNEG,
 A_FSQRT,
@@ -129,5 +184,8 @@ A_FCMP,
 A_FCMPE,
 A_FCCMP,
 A_FCMMPE,
-A_FCSEL
+A_FCSEL,
+A_UMOV,
+A_INS,
+A_MOVI
 );

+ 168 - 161
compiler/aarch64/a64reg.dat

@@ -70,169 +70,176 @@ W30,$01,$04,$1E,w30,30,30
 X30,$01,$05,$1E,x30,30,30
 WZR,$01,$04,$1F,wzr,31,31
 XZR,$01,$05,$1F,xzr,31,31
+; sp and zr share the same register number, but we still have to be able to
+; differentiate them because some instructions can be encoded with both ->
+; use a different superregister after all
+WSP,$01,$04,$20,wsp,31,31
+SP,$01,$05,$20,sp,31,31
 
 
 ; vfp registers
-B0,$04,$01,$00,b0,0,0
-H0,$04,$03,$00,h0,0,0
-S0,$04,$09,$00,s0,0,0
-D0,$04,$0a,$00,d0,0,0
-Q0,$04,$05,$00,q0,0,0
-B1,$04,$01,$01,b1,1,1
-H1,$04,$03,$01,h1,1,1
-S1,$04,$09,$01,s1,1,1
-D1,$04,$0a,$01,d1,1,1
-Q1,$04,$05,$01,q1,1,1
-B2,$04,$01,$02,b2,2,2
-H2,$04,$03,$02,h2,2,2
-S2,$04,$09,$02,s2,2,2
-D2,$04,$0a,$02,d2,2,2
-Q2,$04,$05,$02,q2,2,2
-B3,$04,$01,$03,b3,3,3
-H3,$04,$03,$03,h3,3,3
-S3,$04,$09,$03,s3,3,3
-D3,$04,$0a,$03,d3,3,3
-Q3,$04,$05,$03,q3,3,3
-B4,$04,$01,$04,b4,4,4
-H4,$04,$03,$04,h4,4,4
-S4,$04,$09,$04,s4,4,4
-D4,$04,$0a,$04,d4,4,4
-Q4,$04,$05,$04,q4,4,4
-B5,$04,$01,$05,b5,5,5
-H5,$04,$03,$05,h5,5,5
-S5,$04,$09,$05,s5,5,5
-D5,$04,$0a,$05,d5,5,5
-Q5,$04,$05,$05,q5,5,5
-B6,$04,$01,$06,b6,6,6
-H6,$04,$03,$06,h6,6,6
-S6,$04,$09,$06,s6,6,6
-D6,$04,$0a,$06,d6,6,6
-Q6,$04,$05,$06,q6,6,6
-B7,$04,$01,$07,b7,7,7
-H7,$04,$03,$07,h7,7,7
-S7,$04,$09,$07,s7,7,7
-D7,$04,$0a,$07,d7,7,7
-Q7,$04,$05,$07,q7,7,7
-B8,$04,$01,$08,b8,8,8
-H8,$04,$03,$08,h8,8,8
-S8,$04,$09,$08,s8,8,8
-D8,$04,$0a,$08,d8,8,8
-Q8,$04,$05,$08,q8,8,8
-B9,$04,$01,$09,b9,9,9
-H9,$04,$03,$09,h9,9,9
-S9,$04,$09,$09,s9,9,9
-D9,$04,$0a,$09,d9,9,9
-Q9,$04,$05,$09,q9,9,9
-B10,$04,$01,$0A,b10,10,10
-H10,$04,$03,$0A,h10,10,10
-S10,$04,$09,$0A,s10,10,10
-D10,$04,$0a,$0A,d10,10,10
-Q10,$04,$05,$0A,q10,10,10
-B11,$04,$01,$0B,b11,11,11
-H11,$04,$03,$0B,h11,11,11
-S11,$04,$09,$0B,s11,11,11
-D11,$04,$0a,$0B,d11,11,11
-Q11,$04,$05,$0B,q11,11,11
-B12,$04,$01,$0C,b12,12,12
-H12,$04,$03,$0C,h12,12,12
-S12,$04,$09,$0C,s12,12,12
-D12,$04,$0a,$0C,d12,12,12
-Q12,$04,$05,$0C,q12,12,12
-B13,$04,$01,$0D,b13,13,13
-H13,$04,$03,$0D,h13,13,13
-S13,$04,$09,$0D,s13,13,13
-D13,$04,$0a,$0D,d13,13,13
-Q13,$04,$05,$0D,q13,13,13
-B14,$04,$01,$0E,b14,14,14
-H14,$04,$03,$0E,h14,14,14
-S14,$04,$09,$0E,s14,14,14
-D14,$04,$0a,$0E,d14,14,14
-Q14,$04,$05,$0E,q14,14,14
-B15,$04,$01,$0F,b15,15,15
-H15,$04,$03,$0F,h15,15,15
-S15,$04,$09,$0F,s15,15,15
-D15,$04,$0a,$0F,d15,15,15
-Q15,$04,$05,$0F,q15,15,15
-B16,$04,$01,$10,b16,16,16
-H16,$04,$03,$10,h16,16,16
-S16,$04,$09,$10,s16,16,16
-D16,$04,$0a,$10,d16,16,16
-Q16,$04,$05,$10,q16,16,16
-B17,$04,$01,$11,b17,17,17
-H17,$04,$03,$11,h17,17,17
-S17,$04,$09,$11,s17,17,17
-D17,$04,$0a,$11,d17,17,17
-Q17,$04,$05,$11,q17,17,17
-B18,$04,$01,$12,b18,18,18
-H18,$04,$03,$12,h18,18,18
-S18,$04,$09,$12,s18,18,18
-D18,$04,$0a,$12,d18,18,18
-Q18,$04,$05,$12,q18,18,18
-B19,$04,$01,$13,b19,19,19
-H19,$04,$03,$13,h19,19,19
-S19,$04,$09,$13,s19,19,19
-D19,$04,$0a,$13,d19,19,19
-Q19,$04,$05,$13,q19,19,19
-B20,$04,$01,$14,b20,20,20
-H20,$04,$03,$14,h20,20,20
-S20,$04,$09,$14,s20,20,20
-D20,$04,$0a,$14,d20,20,20
-Q20,$04,$05,$14,q20,20,20
-B21,$04,$01,$15,b21,21,21
-H21,$04,$03,$15,h21,21,21
-S21,$04,$09,$15,s21,21,21
-D21,$04,$0a,$15,d21,21,21
-Q21,$04,$05,$15,q21,21,21
-B22,$04,$01,$16,b22,22,22
-H22,$04,$03,$16,h22,22,22
-S22,$04,$09,$16,s22,22,22
-D22,$04,$0a,$16,d22,22,22
-Q22,$04,$05,$16,q22,22,22
-B23,$04,$01,$17,b23,23,23
-H23,$04,$03,$17,h23,23,23
-S23,$04,$09,$17,s23,23,23
-D23,$04,$0a,$17,d23,23,23
-Q23,$04,$05,$17,q23,23,23
-B24,$04,$01,$18,b24,24,24
-H24,$04,$03,$18,h24,24,24
-S24,$04,$09,$18,s24,24,24
-D24,$04,$0a,$18,d24,24,24
-Q24,$04,$05,$18,q24,24,24
-B25,$04,$01,$19,b25,25,25
-H25,$04,$03,$19,h25,25,25
-S25,$04,$09,$19,s25,25,25
-D25,$04,$0a,$19,d25,25,25
-Q25,$04,$05,$19,q25,25,25
-B26,$04,$01,$1A,b26,26,26
-H26,$04,$03,$1A,h26,26,26
-S26,$04,$09,$1A,s26,26,26
-D26,$04,$0a,$1A,d26,26,26
-Q26,$04,$05,$1A,q26,26,26
-B27,$04,$01,$1B,b27,27,27
-H27,$04,$03,$1B,h27,27,27
-S27,$04,$09,$1B,s27,27,27
-D27,$04,$0a,$1B,d27,27,27
-Q27,$04,$05,$1B,q27,27,27
-B28,$04,$01,$1C,b28,28,28
-H28,$04,$03,$1C,h28,28,28
-S28,$04,$09,$1C,s28,28,28
-D28,$04,$0a,$1C,d28,28,28
-Q28,$04,$05,$1C,q28,28,28
-B29,$04,$01,$1D,b29,29,29
-H29,$04,$03,$1D,h29,29,29
-S29,$04,$09,$1D,s29,29,29
-D29,$04,$0a,$1D,d29,29,29
-Q29,$04,$05,$1D,q29,29,29
-B30,$04,$01,$1E,b30,30,30
-H30,$04,$03,$1E,h30,30,30
-S30,$04,$09,$1E,s30,30,30
-D30,$04,$0a,$1E,d30,30,30
-Q30,$04,$05,$1E,q30,30,30
-B31,$04,$01,$1F,b31,31,31
-H31,$04,$03,$1F,h31,31,31
-S31,$04,$09,$1F,s31,31,31
-D31,$04,$0a,$1F,d31,31,31
-Q31,$04,$05,$1F,q31,31,31
+B0,$04,$01,$00,b0,64,64
+H0,$04,$03,$00,h0,64,64
+S0,$04,$09,$00,s0,64,64
+D0,$04,$0a,$00,d0,64,64
+Q0,$04,$05,$00,q0,64,64
+B1,$04,$01,$01,b1,65,65
+H1,$04,$03,$01,h1,65,65
+S1,$04,$09,$01,s1,65,65
+D1,$04,$0a,$01,d1,65,65
+Q1,$04,$05,$01,q1,65,65
+B2,$04,$01,$02,b2,66,66
+H2,$04,$03,$02,h2,66,66
+S2,$04,$09,$02,s2,66,66
+D2,$04,$0a,$02,d2,66,66
+Q2,$04,$05,$02,q2,66,66
+B3,$04,$01,$03,b3,67,67
+H3,$04,$03,$03,h3,67,67
+S3,$04,$09,$03,s3,67,67
+D3,$04,$0a,$03,d3,67,67
+Q3,$04,$05,$03,q3,67,67
+B4,$04,$01,$04,b4,68,68
+H4,$04,$03,$04,h4,68,68
+S4,$04,$09,$04,s4,68,68
+D4,$04,$0a,$04,d4,68,68
+Q4,$04,$05,$04,q4,68,68
+B5,$04,$01,$05,b5,69,69
+H5,$04,$03,$05,h5,69,69
+S5,$04,$09,$05,s5,69,69
+D5,$04,$0a,$05,d5,69,69
+Q5,$04,$05,$05,q5,69,69
+B6,$04,$01,$06,b6,70,70
+H6,$04,$03,$06,h6,70,70
+S6,$04,$09,$06,s6,70,70
+D6,$04,$0a,$06,d6,70,70
+Q6,$04,$05,$06,q6,70,70
+B7,$04,$01,$07,b7,71,71
+H7,$04,$03,$07,h7,71,71
+S7,$04,$09,$07,s7,71,71
+D7,$04,$0a,$07,d7,71,71
+Q7,$04,$05,$07,q7,71,71
+B8,$04,$01,$08,b8,72,72
+H8,$04,$03,$08,h8,72,72
+S8,$04,$09,$08,s8,72,72
+D8,$04,$0a,$08,d8,72,72
+Q8,$04,$05,$08,q8,72,72
+B9,$04,$01,$09,b9,73,73
+H9,$04,$03,$09,h9,73,73
+S9,$04,$09,$09,s9,73,73
+D9,$04,$0a,$09,d9,73,73
+Q9,$04,$05,$09,q9,73,73
+B10,$04,$01,$0A,b10,74,74
+H10,$04,$03,$0A,h10,74,74
+S10,$04,$09,$0A,s10,74,74
+D10,$04,$0a,$0A,d10,74,74
+Q10,$04,$05,$0A,q10,74,74
+B11,$04,$01,$0B,b11,75,75
+H11,$04,$03,$0B,h11,75,75
+S11,$04,$09,$0B,s11,75,75
+D11,$04,$0a,$0B,d11,75,75
+Q11,$04,$05,$0B,q11,75,75
+B12,$04,$01,$0C,b12,76,76
+H12,$04,$03,$0C,h12,76,76
+S12,$04,$09,$0C,s12,76,76
+D12,$04,$0a,$0C,d12,76,76
+Q12,$04,$05,$0C,q12,76,76
+B13,$04,$01,$0D,b13,77,77
+H13,$04,$03,$0D,h13,77,77
+S13,$04,$09,$0D,s13,77,77
+D13,$04,$0a,$0D,d13,77,77
+Q13,$04,$05,$0D,q13,77,77
+B14,$04,$01,$0E,b14,78,78
+H14,$04,$03,$0E,h14,78,78
+S14,$04,$09,$0E,s14,78,78
+D14,$04,$0a,$0E,d14,78,78
+Q14,$04,$05,$0E,q14,78,78
+B15,$04,$01,$0F,b15,79,79
+H15,$04,$03,$0F,h15,79,79
+S15,$04,$09,$0F,s15,79,79
+D15,$04,$0a,$0F,d15,79,79
+Q15,$04,$05,$0F,q15,79,79
+B16,$04,$01,$10,b16,80,80
+H16,$04,$03,$10,h16,80,80
+S16,$04,$09,$10,s16,80,80
+D16,$04,$0a,$10,d16,80,80
+Q16,$04,$05,$10,q16,80,80
+B17,$04,$01,$11,b17,81,81
+H17,$04,$03,$11,h17,81,81
+S17,$04,$09,$11,s17,81,81
+D17,$04,$0a,$11,d17,81,81
+Q17,$04,$05,$11,q17,81,81
+B18,$04,$01,$12,b18,82,82
+H18,$04,$03,$12,h18,82,82
+S18,$04,$09,$12,s18,82,82
+D18,$04,$0a,$12,d18,82,82
+Q18,$04,$05,$12,q18,82,82
+B19,$04,$01,$13,b19,83,83
+H19,$04,$03,$13,h19,83,83
+S19,$04,$09,$13,s19,83,83
+D19,$04,$0a,$13,d19,83,83
+Q19,$04,$05,$13,q19,83,83
+B20,$04,$01,$14,b20,84,84
+H20,$04,$03,$14,h20,84,84
+S20,$04,$09,$14,s20,84,84
+D20,$04,$0a,$14,d20,84,84
+Q20,$04,$05,$14,q20,84,84
+B21,$04,$01,$15,b21,85,85
+H21,$04,$03,$15,h21,85,85
+S21,$04,$09,$15,s21,85,85
+D21,$04,$0a,$15,d21,85,85
+Q21,$04,$05,$15,q21,85,85
+B22,$04,$01,$16,b22,86,86
+H22,$04,$03,$16,h22,86,86
+S22,$04,$09,$16,s22,86,86
+D22,$04,$0a,$16,d22,86,86
+Q22,$04,$05,$16,q22,86,86
+B23,$04,$01,$17,b23,87,87
+H23,$04,$03,$17,h23,87,87
+S23,$04,$09,$17,s23,87,87
+D23,$04,$0a,$17,d23,87,87
+Q23,$04,$05,$17,q23,87,87
+B24,$04,$01,$18,b24,88,88
+H24,$04,$03,$18,h24,88,88
+S24,$04,$09,$18,s24,88,88
+D24,$04,$0a,$18,d24,88,88
+Q24,$04,$05,$18,q24,88,88
+B25,$04,$01,$19,b25,89,89
+H25,$04,$03,$19,h25,89,89
+S25,$04,$09,$19,s25,89,89
+D25,$04,$0a,$19,d25,89,89
+Q25,$04,$05,$19,q25,89,89
+B26,$04,$01,$1A,b26,90,90
+H26,$04,$03,$1A,h26,90,90
+S26,$04,$09,$1A,s26,90,90
+D26,$04,$0a,$1A,d26,90,90
+Q26,$04,$05,$1A,q26,90,90
+B27,$04,$01,$1B,b27,91,91
+H27,$04,$03,$1B,h27,91,91
+S27,$04,$09,$1B,s27,91,91
+D27,$04,$0a,$1B,d27,91,91
+Q27,$04,$05,$1B,q27,91,91
+B28,$04,$01,$1C,b28,92,92
+H28,$04,$03,$1C,h28,92,92
+S28,$04,$09,$1C,s28,92,92
+D28,$04,$0a,$1C,d28,92,92
+Q28,$04,$05,$1C,q28,92,92
+B29,$04,$01,$1D,b29,93,93
+H29,$04,$03,$1D,h29,93,93
+S29,$04,$09,$1D,s29,93,93
+D29,$04,$0a,$1D,d29,93,93
+Q29,$04,$05,$1D,q29,93,93
+B30,$04,$01,$1E,b30,94,94
+H30,$04,$03,$1E,h30,94,94
+S30,$04,$09,$1E,s30,94,94
+D30,$04,$0a,$1E,d30,94,94
+Q30,$04,$05,$1E,q30,94,94
+B31,$04,$01,$1F,b31,95,95
+H31,$04,$03,$1F,h31,95,95
+S31,$04,$09,$1F,s31,95,95
+D31,$04,$0a,$1F,d31,95,95
+Q31,$04,$05,$1F,q31,95,95
 
 NZCV,$05,$00,$00,nzcv,0,0
-
+FPCR,$05,$00,$01,fpcr,0,0
+FPSR,$05,$00,$02,fpsr,0,0
+TPIDR_EL0,$05,$00,$03,tpidr_el0,0,0

+ 1 - 1
compiler/aarch64/a64tab.inc

@@ -1,4 +1,4 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
 
 );

+ 466 - 1143
compiler/aarch64/aasmcpu.pas

@@ -1,7 +1,7 @@
 {
     Copyright (c) 2003-2012 by Florian Klaempfl and others
 
-    Contains the assembler object for ARM64
+    Contains the assembler object for Aarch64
 
     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
@@ -149,9 +149,6 @@ uses
 
       pinsentry=^tinsentry;
 
-{    const
-      InsTab : array[0..instabentries-1] of TInsEntry={$i a64tab.inc} }
-
     var
       InsTabCache : PInsTabCache;
 
@@ -159,6 +156,7 @@ uses
       taicpu = class(tai_cpu_abstract_sym)
          oppostfix : TOpPostfix;
          procedure loadshifterop(opidx:longint;const so:tshifterop);
+         procedure loadconditioncode(opidx: longint; const c: tasmcond);
          constructor op_none(op : tasmop);
 
          constructor op_reg(op : tasmop;_op1 : tregister);
@@ -167,15 +165,21 @@ uses
 
          constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
          constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+         constructor op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
          constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+         constructor op_reg_const_shifterop(op : tasmop;_op1: tregister; _op2: aint;_op3 : tshifterop);
 
          constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
          constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
          constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+         constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3, _op4: aint);
+         constructor op_reg_reg_const_shifterop(op : tasmop;_op1,_op2 : tregister; _op3: aint; const _op4 : tshifterop);
          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_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
+         constructor op_reg_reg_reg_cond(op : tasmop;_op1,_op2,_op3 : tregister; const _op4: tasmcond);
+
 
          { this is for Jmp instructions }
          constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
@@ -188,6 +192,7 @@ uses
          function is_same_reg_move(regtype: Tregistertype):boolean; override;
 
          function spilling_get_operation_type(opnr: longint): topertype;override;
+         function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
 
          { assembler }
       public
@@ -203,28 +208,29 @@ uses
          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;
+    type
+      tsimplereftype =
+         { valid reference }
+        (sr_simple,
+         { invalid reference, should not be generated by the code generator (but
+           can be encountered via inline assembly, where it must be rejected) }
+         sr_internal_illegal,
+         { invalid reference, may be generated by the code generator and then
+           must be simplified (also rejected in inline assembly) }
+         sr_complex);
+
+    function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
+    function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
+    function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
+
+    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 setcondition(i : taicpu;c : tasmcond) : taicpu;
@@ -261,6 +267,21 @@ implementation
       end;
 
 
+    procedure taicpu.loadconditioncode(opidx: longint; const c: tasmcond);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+          begin
+            if typ<>top_conditioncode then
+              begin
+                clearop(opidx);
+              end;
+            cc:=c;
+            typ:=top_conditioncode;
+          end;
+      end;
+
+
 {*****************************************************************************
                                  taicpu Constructors
 *****************************************************************************}
@@ -314,6 +335,16 @@ implementation
       end;
 
 
+    constructor taicpu.op_reg_const_shifterop(op: tasmop; _op1: tregister; _op2: aint; _op3: tshifterop);
+      begin
+        inherited create(op);
+        ops:=3;
+        loadreg(0,_op1);
+        loadconst(1,_op2);
+        loadshifterop(2,_op3);
+      end;
+
+
     constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
       begin
          inherited create(op);
@@ -323,6 +354,15 @@ implementation
       end;
 
 
+    constructor taicpu.op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
+      begin
+        inherited create(op);
+        ops:=2;
+        loadreg(0,_op1);
+        loadconditioncode(1,_op2);
+      end;
+
+
     constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
       begin
          inherited create(op);
@@ -354,6 +394,28 @@ implementation
       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,aint(_op3));
+         loadconst(3,aint(_op4));
+       end;
+
+
+     constructor taicpu.op_reg_reg_const_shifterop(op: tasmop; _op1, _op2: tregister; _op3: aint; const _op4: tshifterop);
+       begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadconst(2,aint(_op3));
+         loadshifterop(3,_op4);
+       end;
+
+
      constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
        begin
          inherited create(op);
@@ -384,7 +446,7 @@ implementation
       end;
 
 
-     constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+     constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
       begin
          inherited create(op);
          ops:=4;
@@ -394,6 +456,16 @@ implementation
          loadshifterop(3,_op4);
       end;
 
+     constructor taicpu.op_reg_reg_reg_cond(op: tasmop; _op1, _op2, _op3: tregister; const _op4: tasmcond);
+       begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+         loadconditioncode(3,_op4);
+       end;
+
 
     constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
       begin
@@ -454,85 +526,403 @@ implementation
       end;
 
 
-    function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+    function spilling_create_op(op: tasmop; const ref: treference; r: tregister): taicpu;
+      const
+        { invalid sizes for aarch64 are 0 }
+        subreg2bytesize: array[TSubRegister] of byte =
+          (0,0,0,0,4,8,0,0,0,4,8,0,0,0);
       var
-        op: tasmop;
+        scalefactor: byte;
       begin
+        scalefactor:=subreg2bytesize[getsubreg(r)];
+        if scalefactor=0 then
+          internalerror(2014120301);
+        if (ref.offset>4095*scalefactor) or
+           ((ref.offset>255) and
+            ((ref.offset mod scalefactor)<>0)) or
+           (ref.offset<-256) then
+          internalerror(2014120302);
         case getregtype(r) of
-          R_INTREGISTER :
-            result:=taicpu.op_reg_ref(A_LDR,r,ref);
-          R_MMREGISTER :
-            begin
-              case getsubreg(r) of
-                R_SUBFD:
-                  op:=A_LDR;
-                R_SUBFS:
-                  op:=A_LDR;
-                else
-                  internalerror(2009112905);
-              end;
-              result:=taicpu.op_reg_ref(op,r,ref);
-            end;
+          R_INTREGISTER,
+          R_MMREGISTER:
+            result:=taicpu.op_reg_ref(op,r,ref);
           else
             internalerror(200401041);
         end;
       end;
 
 
-    function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+    function is_valid_load_symbol(op: tasmop; oppostfix: toppostfix; const ref: treference): tsimplereftype;
+      begin
+        result:=sr_complex;
+        if not assigned(ref.symboldata) and
+           not(ref.refaddr in [addr_gotpageoffset,addr_gotpage,addr_pageoffset,addr_page]) then
+          exit;
+        { can't use pre-/post-indexed mode here (makes no sense either) }
+        if ref.addressmode<>AM_OFFSET then
+          exit;
+        { "ldr literal" must be a 32/64 bit LDR and have a symbol }
+        if assigned(ref.symboldata) and
+           ((op<>A_LDR) or
+            not(oppostfix in [PF_NONE,PF_W,PF_SW]) or
+            not assigned(ref.symbol)) then
+          exit;
+        { if this is a (got) page offset load, we must have a base register and a
+          symbol }
+        if (ref.refaddr in [addr_gotpageoffset,addr_pageoffset]) and
+           (not assigned(ref.symbol) or
+            (ref.base=NR_NO) or
+            (ref.index<>NR_NO) or
+            (ref.offset<>0)) then
+          begin
+            result:=sr_internal_illegal;
+            exit;
+          end;
+        { cannot have base or index register (we generate these kind of
+          references internally, they should never end up here with an
+          extra base or offset) }
+        if (ref.refaddr in [addr_gotpage,addr_page]) and
+           (ref.base<>NR_NO) or
+           (ref.index<>NR_NO) then
+          begin
+            result:=sr_internal_illegal;
+            exit;
+          end;
+        result:=sr_simple;
+      end;
+
+
+    function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
       var
-        op: tasmop;
+        maxoffs: asizeint;
+        accesssize: longint;
       begin
-        case getregtype(r) of
-          R_INTREGISTER :
-            result:=taicpu.op_reg_ref(A_STR,r,ref);
-          R_MMREGISTER :
-            begin
-              case getsubreg(r) of
-                R_SUBFD:
-                  op:=A_STR;
-                R_SUBFS:
-                  op:=A_STR;
+        result:=sr_internal_illegal;
+        { post-indexed is only allowed for vector and immediate loads/stores }
+        if (ref.addressmode=AM_POSTINDEXED) and
+           not(op in [A_LD1,A_LD2,A_LD3,A_LD4,A_ST1,A_ST2,A_ST3,A_ST4]) and
+           (not(op in [A_LDR,A_STR,A_LDP,A_STP]) or
+            (ref.base=NR_NO) or
+            (ref.index<>NR_NO)) then
+          exit;
+
+        { can only have a shift mode if we have an index }
+        if (ref.index=NR_NO) and
+           (ref.shiftmode<>SM_None) then
+          exit;
+
+        { the index can never be the stack pointer }
+        if ref.index=NR_SP then
+          exit;
+
+        { no instruction supports an index without a base }
+        if (ref.base=NR_NO) and
+           (ref.index<>NR_NO) then
+          begin
+            result:=sr_complex;
+            exit;
+          end;
+
+        { LDR literal or GOT entry: 32 or 64 bit, label }
+        if assigned(ref.symboldata) or
+           assigned(ref.symbol) then
+          begin
+            { we generate these kind of references internally; at least for now,
+              they should never end up here with an extra base or offset or so }
+            result:=is_valid_load_symbol(op,oppostfix,ref);
+            exit;
+          end;
+
+        { any other reference cannot be gotpage/gotpageoffset/pic }
+        if ref.refaddr in [addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset,addr_pic] then
+          exit;
+
+        { base & index:
+            * index cannot be the stack pointer
+            * offset must be 0
+            * can scale with the size of the access
+            * can zero/sign extend 32 bit index register, and/or multiple by
+              access size
+            * no pre/post-indexing
+        }
+        if (ref.base<>NR_NO) and
+           (ref.index<>NR_NO) then
+          begin
+            if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
+              exit;
+            case op of
+              { this holds for both integer and fpu/vector loads }
+              A_LDR,A_STR:
+                if (ref.offset=0) and
+                   (((ref.shiftmode=SM_None) and
+                     (ref.shiftimm=0)) or
+                    ((ref.shiftmode in [SM_LSL,SM_UXTW,SM_SXTW]) and
+                     (ref.shiftimm=tcgsizep2size[size]))) then
+                  result:=sr_simple
                 else
-                  internalerror(2009112904);
-              end;
-              result:=taicpu.op_reg_ref(op,r,ref);
+                  result:=sr_complex;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110704);
+              { these don't support base+index }
+              A_LDUR,A_STUR,
+              A_LDP,A_STP:
+                result:=sr_complex;
+              else
+                { nothing: result is already sr_internal_illegal };
+            end;
+            exit;
+          end;
+
+        { base + immediate offset. Variants:
+            * LDR*/STR*:
+              - pre- or post-indexed with signed 9 bit immediate
+              - regular with unsiged scaled immediate (multiple of access
+                size), in the range 0 to (12 bit * access_size)-1
+            * LDP/STP
+              - pre- or post-indexed with signed 9 bit immediate
+              - regular with signed 9 bit immediate
+            * LDUR*/STUR*:
+              - regular with signed 9 bit immediate
+        }
+        if ref.base<>NR_NO then
+          begin
+            accesssize:=1 shl tcgsizep2size[size];
+            case op of
+              A_LDR,A_STR:
+                begin
+                  if (ref.addressmode=AM_OFFSET) and
+                     (ref.offset>=0) and
+                     (ref.offset<(((1 shl 12)-1)*accesssize)) and
+                     ((ref.offset mod accesssize)=0) then
+                    result:=sr_simple
+                  else if (ref.offset>=-256) and
+                     (ref.offset<=255) then
+                    begin
+                      { non pre-/post-indexed regular loads/stores can only be
+                        performed using LDUR/STUR }
+                      if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
+                        result:=sr_simple
+                      else
+                        result:=sr_complex
+                    end
+                  else
+                    result:=sr_complex;
+                end;
+              A_LDP,A_LDNP,
+              A_STP,A_STNP:
+                begin
+                  { only supported for 32/64 bit }
+                  if not(oppostfix in [PF_W,PF_SW,PF_None]) then
+                    exit;
+                  { offset must be a multple of the access size }
+                  if (ref.offset mod accesssize)<>0 then
+                    exit;
+                  { offset must fit in a signed 7 bit offset }
+                  if (ref.offset>=-(1 shl (6+tcgsizep2size[size]))) and
+                     (ref.offset<=(1 shl (6+tcgsizep2size[size]))-1) then
+                    result:=sr_simple
+                  else
+                    result:=sr_complex;
+                end;
+              A_LDUR,A_STUR:
+                begin
+                  if (ref.addressmode=AM_OFFSET) and
+                     (ref.offset>=-256) and
+                     (ref.offset<=255) then
+                    result:=sr_simple
+                  else
+                    result:=sr_complex;
+                end;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110907);
+              A_LDAR,
+              A_LDAXR,
+              A_LDXR,
+              A_LDXP,
+              A_STLR,
+              A_STLXR,
+              A_STLXP,
+              A_STXP,
+              A_STXR:
+                begin
+                  if (ref.addressmode=AM_OFFSET) and
+                     (ref.offset=0) then
+                    result:=sr_simple;
+                end
+              else
+                { nothing: result is already sr_internal_illegal };
             end;
+            exit;
+          end;
+        { absolute addresses are not supported, have to load them first into
+          a register }
+        result:=sr_complex;
+      end;
+
+
+    function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
+      begin
+        case opc of
+          A_ADD,
+          A_AND,
+          A_EON,
+          A_EOR,
+          A_ORN,
+          A_ORR,
+          A_SUB:
+            result:=opnr=3;
+          A_BIC,
+          A_CMN,
+          A_CMP,
+          A_MOVK,
+          A_MOVZ,
+          A_MOVN,
+          A_MVN,
+          A_NEG,
+          A_TST:
+            result:=opnr=2;
           else
-            internalerror(200401041);
+            result:=false;
         end;
       end;
 
 
+    function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
+      begin
+        case opc of
+          A_ADD,
+          A_SUB,
+          A_NEG,
+          A_AND,
+          A_TST,
+          A_CMN,
+          A_CMP:
+            begin
+              result:=false;
+              if not useszr then
+                result:=
+                  (sm in shiftedregmodes) and
+                  ((shiftimm in [0..31]) or
+                   (is64bit and
+                    (shiftimm in [32..63])));
+              if not usessp then
+                result:=
+                  result or
+                  ((sm in extendedregmodes) and
+                   (shiftimm in [0..4]));
+            end;
+          A_BIC,
+          A_EON,
+          A_EOR,
+          A_MVN,
+          A_ORN,
+          A_ORR:
+            result:=
+              (sm in shiftedregmodes) and
+              (shiftimm in [0..31*(ord(is64bit)+1)+ord(is64bit)]);
+          A_MOVK,
+          A_MOVZ,
+          A_MOVN:
+            result:=
+              (sm=SM_LSL) and
+              ((shiftimm in [0,16]) or
+               (is64bit and
+                (shiftimm in [32,48])));
+          else
+            result:=false;
+        end;
+      end;
+
+
+    function spilling_create_load(const ref: treference; r: tregister): taicpu;
+      var
+        op: tasmop;
+      begin
+        if (ref.index<>NR_NO) or
+           (ref.offset<-256) or
+           (ref.offset>255) then
+          op:=A_LDR
+        else
+          op:=A_LDUR;
+        result:=spilling_create_op(op,ref,r);
+      end;
+
+
+    function spilling_create_store(r: tregister; const ref: treference): taicpu;
+      var
+        op: tasmop;
+      begin
+        if (ref.index<>NR_NO) or
+           (ref.offset<-256) or
+           (ref.offset>255) then
+          op:=A_STR
+        else
+          op:=A_STUR;
+        result:=spilling_create_op(op,ref,r);
+      end;
+
+
     function taicpu.spilling_get_operation_type(opnr: longint): topertype;
       begin
         case opcode of
-          A_ADC,A_ADD,A_AND,A_BIC,
-          A_EOR,A_CLZ,A_RBIT,
-          A_LDR,
-          A_MOV,A_MVN,A_MUL,
-          A_ORR,A_SBC,A_SUB,
-          A_UXT,A_SXT:
+          A_B,A_BL,
+          A_CMN,A_CMP,
+          A_CCMN,A_CCMP,
+          A_TST:
+            result:=operand_read;
+          A_STR,A_STUR:
             if opnr=0 then
-              result:=operand_write
+              result:=operand_read
             else
+              { check for pre/post indexed in spilling_get_operation_type_ref }
               result:=operand_read;
-          A_B,A_BL,
-          A_CMN,A_CMP,A_TST:
-            result:=operand_read;
-          A_STR:
-            { important is what happens with the involved registers }
+          A_STLXP,
+          A_STLXR,
+          A_STXP,
+          A_STXR:
             if opnr=0 then
-              result := operand_read
+              result:=operand_write
             else
-              { check for pre/post indexed }
-              result := operand_read;
-          else
-            internalerror(200403151);
+              result:=operand_read;
+          A_STP:
+            begin
+              if opnr in [0,1] then
+                result:=operand_read
+              else
+                { check for pre/post indexed in spilling_get_operation_type_ref }
+                result:=operand_read;
+            end;
+           A_LDP,
+           A_LDXP:
+             begin
+               if opnr in [0,1] then
+                 result:=operand_write
+               else
+                 { check for pre/post indexed in spilling_get_operation_type_ref }
+                 result:=operand_read;
+             end;
+           else
+             if opnr=0 then
+               result:=operand_write
+             else
+               result:=operand_read;
         end;
       end;
 
 
+    function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+      begin
+        result:=operand_read;
+        if (oper[opnr]^.ref^.base = reg) and
+          (oper[opnr]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
+           result:=operand_readwrite;
+      end;
+
+
     procedure BuildInsTabCache;
       var
         i : longint;
@@ -673,14 +1063,9 @@ implementation
                                         if (tai_const(hp).consttype=aitconst_64bit) then
                                           inc(extradataoffset);
                                       end;
-                                    ait_comp_64bit,
-                                    ait_real_64bit:
-                                      begin
-                                        inc(extradataoffset);
-                                      end;
-                                    ait_real_80bit:
+                                    ait_realconst:
                                       begin
-                                        inc(extradataoffset,2);
+                                        inc(extradataoffset,((tai_realconst(hp).savesize-4+3) div 4));
                                       end;
                                   end;
                                   if (hp.typ=ait_const) then
@@ -734,18 +1119,9 @@ implementation
                   if (tai_const(curtai).consttype=aitconst_64bit) then
                     inc(curinspos);
                 end;
-              ait_real_32bit:
+              ait_realconst:
                 begin
-                  inc(curinspos);
-                end;
-              ait_comp_64bit,
-              ait_real_64bit:
-                begin
-                  inc(curinspos,2);
-                end;
-              ait_real_80bit:
-                begin
-                  inc(curinspos,3);
+                  inc(curinspos,(tai_realconst(hp).savesize+3) div 4);
                 end;
             end;
             { special case for case jump tables }
@@ -1069,22 +1445,12 @@ implementation
         { 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;
 
 
@@ -1097,18 +1463,15 @@ implementation
     function taicpu.Pass1(objdata:TObjData):longint;
       begin
         Pass1:=0;
-        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);
+        { GenCode(objdata); }
       end;
 
 
@@ -1132,1046 +1495,6 @@ implementation
       end;
 
 
-    function  taicpu.InsEnd:longint;
-      begin
-        Result:=0; { unimplemented }
-      end;
-
-
-    procedure taicpu.create_ot(objdata:TObjData);
-      begin
-      end;
-
-
-    function taicpu.Matches(p:PInsEntry):longint;
-      begin
-      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;
-      begin
-      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);
-
-              { set s if necessary }
-              if oppostfix=PF_S then
-                bytes:=bytes or (1 shl 20);
-            end;
-          #$ff:
-            internalerror(2005091101);
-          else
-            internalerror(2005091102);
-        end;
-        { we're finished, write code }
-        objdata.writebytes(bytes,sizeof(bytes));
-      end;
-
-
-{$ifdef dummy}
-(*
-static void gencode (long segment, long offset, int bits,
-                     insn *ins, char *codes, long insn_end)
-{
-    int has_S_code;             /* S - setflag */
-    int has_B_code;             /* B - setflag */
-    int has_T_code;             /* T - setflag */
-    int has_W_code;             /* ! => W flag */
-    int has_F_code;             /* ^ => S flag */
-    int keep;
-    unsigned char c;
-    unsigned char bytes[4];
-    long          data, size;
-    static int cc_code[] =      /* bit pattern of cc */
-  {                             /* order as enum in  */
-    0x0E, 0x03, 0x02, 0x00,     /* nasm.h            */
-    0x0A, 0x0C, 0x08, 0x0D,
-    0x09, 0x0B, 0x04, 0x01,
-    0x05, 0x07, 0x06,
-  };
-
-
-#ifdef DEBUG
-static char *CC[] =
-  {                                    /* condition code names */
-    "AL", "CC", "CS", "EQ",
-    "GE", "GT", "HI", "LE",
-    "LS", "LT", "MI", "NE",
-    "PL", "VC", "VS", "",
-    "S"
-};
-
-
-    has_S_code = (ins->condition & C_SSETFLAG);
-    has_B_code = (ins->condition & C_BSETFLAG);
-    has_T_code = (ins->condition & C_TSETFLAG);
-    has_W_code = (ins->condition & C_EXSETFLAG);
-    has_F_code = (ins->condition & C_FSETFLAG);
-    ins->condition = (ins->condition & 0x0F);
-
-
-    if (rt_debug)
-      {
-    printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
-            CC[ins->condition & 0x0F]);
-    if (has_S_code)
-      printf ("S");
-    if (has_B_code)
-      printf ("B");
-    if (has_T_code)
-      printf ("T");
-    if (has_W_code)
-      printf ("!");
-    if (has_F_code)
-      printf ("^");
-
-    printf ("\n");
-
-    c = *codes;
-
-    printf ("   (%d)  decode - '0x%02X'\n", ins->operands, c);
-
-
-    bytes[0] = 0xB;
-    bytes[1] = 0xE;
-    bytes[2] = 0xE;
-    bytes[3] = 0xF;
-      }
-
-    // First condition code in upper nibble
-    if (ins->condition < C_NONE)
-      {
-        c = cc_code[ins->condition] << 4;
-      }
-    else
-      {
-        c = cc_code[C_AL] << 4; // is often ALWAYS but not always
-      }
-
-
-    switch (keep = *codes)
-      {
-        case 1:
-          // B, BL
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-
-          if (ins->oprs[0].segment != segment)
-            {
-              // fais une relocation
-              c = 1;
-              data = 0; // Let the linker locate ??
-            }
-          else
-            {
-              c = 0;
-              data = ins->oprs[0].offset - (offset + 8);
-
-              if (data % 4)
-                {
-                  errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
-                }
-            }
-
-          if (data >= 0x1000)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-
-          data = data >> 2;
-          bytes[1] = (data >> 16) & 0xFF;
-          bytes[2] = (data >> 8)  & 0xFF;
-          bytes[3] = (data )      & 0xFF;
-
-          if (c == 1)
-            {
-//            out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
-              out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
-            }
-          else
-            {
-              out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
-            }
-          return;
-
-        case 2:
-          // SWI
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-          data = ins->oprs[0].offset;
-          bytes[1] = (data >> 16) & 0xFF;
-          bytes[2] = (data >> 8) & 0xFF;
-          bytes[3] = (data) & 0xFF;
-          out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-        case 3:
-          // BX
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-          bytes[1] = *codes++;
-          bytes[2] = *codes++;
-          bytes[3] = *codes++;
-          c = regval (&ins->oprs[0],1);
-          if (c == 15)  // PC
-            {
-              errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
-            }
-          else if (c > 15)
-            {
-              errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
-            }
-
-          bytes[3] |= (c & 0x0F);
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 4:         // AND Rd,Rn,Rm
-        case 5:         // AND Rd,Rn,Rm,<shift>Rs
-        case 6:         // AND Rd,Rn,Rm,<shift>imm
-        case 7:         // AND Rd,Rn,<shift>imm
-          ++codes;
-#ifdef DEBUG
-          if (rt_debug)
-            {
-              printf ("         decode - '0x%02X'\n", keep);
-              printf ("           code - '0x%02X'\n", (unsigned char) ( *codes));
-            }
-#endif
-          bytes[0] = c | *codes;
-          ++codes;
-
-          bytes[1] = *codes;
-          if (has_S_code)
-            bytes[1] |= 0x10;
-          c = regval (&ins->oprs[1],1);
-          // Rn in low nibble
-          bytes[1] |= c;
-
-          // Rd in high nibble
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          if (keep != 7)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[2],1);
-            }
-
-          // Shifts if any
-          if (keep == 5 || keep == 6)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 5)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[3],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 6)
-                {
-                  c = (ins->oprs[3].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[3]) << 5;
-
-              bytes[3] |= c;
-            }
-
-          // reg,reg,imm
-          if (keep == 7)
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[2].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 8:         // MOV Rd,Rm
-        case 9:         // MOV Rd,Rm,<shift>Rs
-        case 0xA:       // MOV Rd,Rm,<shift>imm
-        case 0xB:       // MOV Rd,<shift>imm
-          ++codes;
-#ifdef DEBUG
-          if (rt_debug)
-            {
-              printf ("         decode - '0x%02X'\n", keep);
-              printf ("           code - '0x%02X'\n", (unsigned char) ( *codes));
-            }
-#endif
-          bytes[0] = c | *codes;
-          ++codes;
-
-          bytes[1] = *codes;
-          if (has_S_code)
-            bytes[1] |= 0x10;
-
-          // Rd in high nibble
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          if (keep != 0x0B)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[1],1);
-            }
-
-          // Shifts if any
-          if (keep == 0x09 || keep == 0x0A)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 0x09)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[2],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 0x0A)
-                {
-                  c = (ins->oprs[2].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[2]) << 5;
-
-              bytes[3] |= c;
-            }
-
-          // reg,imm
-          if (keep == 0x0B)
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[1].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-
-        case 0xC:       // CMP Rn,Rm
-        case 0xD:       // CMP Rn,Rm,<shift>Rs
-        case 0xE:       // CMP Rn,Rm,<shift>imm
-        case 0xF:       // CMP Rn,<shift>imm
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes;
-
-          // Implicit S code
-          bytes[1] |= 0x10;
-
-          c = regval (&ins->oprs[0],1);
-          // Rn in low nibble
-          bytes[1] |= c;
-
-          // No destination
-          bytes[2] = 0;
-
-          if (keep != 0x0B)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[1],1);
-            }
-
-          // Shifts if any
-          if (keep == 0x0D || keep == 0x0E)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 0x0D)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[2],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 0x0E)
-                {
-                  c = (ins->oprs[2].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[2]) << 5;
-
-              bytes[3] |= c;
-            }
-
-          // reg,imm
-          if (keep == 0x0F)
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[1].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 0x10:      // MRS Rd,<psr>
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          c = regval (&ins->oprs[0],1);
-
-          bytes[2] = c << 4;
-
-          bytes[3] = 0;
-
-          c = ins->oprs[1].basereg;
-
-          if (c == R_CPSR || c == R_SPSR)
-            {
-              if (c == R_SPSR)
-                {
-                  bytes[1] |= 0x40;
-                }
-            }
-          else
-            {
-              errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-
-          return;
-
-        case 0x11:      // MSR <psr>,Rm
-        case 0x12:      // MSR <psrf>,Rm
-        case 0x13:      // MSR <psrf>,#expression
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          bytes[2] = *codes;
-
-
-          if (keep == 0x11 || keep == 0x12)
-            {
-              // Rm
-              c = regval (&ins->oprs[1],1);
-
-              bytes[3] = c;
-            }
-          else
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[1].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          c = ins->oprs[0].basereg;
-
-          if ( keep == 0x11)
-            {
-              if ( c == R_CPSR || c == R_SPSR)
-                {
-                if ( c== R_SPSR)
-                  {
-                    bytes[1] |= 0x40;
-                  }
-                }
-            else
-              {
-                errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
-              }
-            }
-          else
-            {
-              if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
-                {
-                  if ( c== R_SPSR_FLG)
-                    {
-                      bytes[1] |= 0x40;
-                    }
-                }
-              else
-                {
-                  errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
-                }
-            }
-          break;
-
-        case 0x14:      // MUL  Rd,Rm,Rs
-        case 0x15:      // MULA Rd,Rm,Rs,Rn
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          bytes[3] = *codes;
-
-          // Rd
-          bytes[1] |= regval (&ins->oprs[0],1);
-          if (has_S_code)
-            bytes[1] |= 0x10;
-
-          // Rm
-          bytes[3] |= regval (&ins->oprs[1],1);
-
-          // Rs
-          bytes[2] = regval (&ins->oprs[2],1);
-
-          if (keep == 0x15)
-            {
-              bytes[2] |= regval (&ins->oprs[3],1) << 4;
-            }
-          break;
-
-        case 0x16:      // SMLAL RdHi,RdLo,Rm,Rs
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          bytes[3] = *codes;
-
-          // RdHi
-          bytes[1] |= regval (&ins->oprs[1],1);
-          if (has_S_code)
-            bytes[1] |= 0x10;
-
-          // RdLo
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          // Rm
-          bytes[3] |= regval (&ins->oprs[2],1);
-
-          // Rs
-          bytes[2] |= regval (&ins->oprs[3],1);
-
-          break;
-
-        case 0x17:      // LDR Rd, expression
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-          if (has_T_code)
-            {
-              errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
-            }
-          if (has_W_code)
-            {
-              errfunc (ERR_NONFATAL, "'!' not allowed");
-            }
-
-          // Rn - implicit R15
-          bytes[1] |= 0xF;
-
-          if (ins->oprs[1].segment != segment)
-            {
-              errfunc (ERR_NONFATAL, "label not in same segment");
-            }
-
-          data = ins->oprs[1].offset - (offset + 8);
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          if (data >= 0x1000)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-
-          bytes[2] |= ((data & 0xF00) >> 8);
-          bytes[3] = data & 0xFF;
-          break;
-
-        case 0x18:      // LDR Rd, [Rn]
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-          if (has_T_code)
-            {
-              bytes[1] |= 0x20;         // write-back
-            }
-          else
-            {
-              bytes[0] |= 0x01;         // implicit pre-index mode
-            }
-
-          if (has_W_code)
-            {
-              bytes[1] |= 0x20;         // write-back
-            }
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (c == 0x15)                // R15
-            data = -8;
-          else
-            data = 0;
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          bytes[2] |= ((data & 0xF00) >> 8);
-          bytes[3] = data & 0xFF;
-          break;
-
-        case 0x19:      // LDR Rd, [Rn,#expression]
-        case 0x20:      // LDR Rd, [Rn,Rm]
-        case 0x21:      // LDR Rd, [Rn,Rm,shift]
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (ins->oprs[ins->operands-1].bracket)       // FIXME: Bracket on last operand -> pre-index  <--
-            {
-              bytes[0] |= 0x01;         // pre-index mode
-              if (has_W_code)
-                {
-                  bytes[1] |= 0x20;
-                }
-              if (has_T_code)
-                {
-                  errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
-                }
-            }
-          else
-            {
-              if (has_T_code)           // Forced write-back in post-index mode
-                {
-                  bytes[1] |= 0x20;
-                }
-              if (has_W_code)
-                {
-                  errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
-                }
-            }
-
-          if (keep == 0x19)
-            {
-              data = ins->oprs[2].offset;
-
-              if (data < 0)
-                {
-                  data = -data;
-                }
-              else
-                {
-                  bytes[1] |= 0x80;
-                }
-
-              if (data >= 0x1000)
-                {
-                  errfunc (ERR_NONFATAL, "too long offset");
-                }
-
-              bytes[2] |= ((data & 0xF00) >> 8);
-              bytes[3] = data & 0xFF;
-            }
-          else
-            {
-              if (ins->oprs[2].minus == 0)
-                {
-                  bytes[1] |= 0x80;
-                }
-              c = regval (&ins->oprs[2],1);
-              bytes[3] = c;
-
-              if (keep == 0x21)
-                {
-                  c = ins->oprs[3].offset;
-                  if (c > 0x1F)
-                    {
-                      errfunc (ERR_NONFATAL, "too large shiftvalue");
-                      c = c & 0x1F;
-                    }
-
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  bytes[3] |= shiftval (&ins->oprs[3]) << 5;
-                }
-            }
-
-          break;
-
-        case 0x22:      // LDRH Rd, expression
-          ++codes;
-
-          bytes[0] = c | 0x01;          // Implicit pre-index
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          // Rn - implicit R15
-          bytes[1] |= 0xF;
-
-          if (ins->oprs[1].segment != segment)
-            {
-              errfunc (ERR_NONFATAL, "label not in same segment");
-            }
-
-          data = ins->oprs[1].offset - (offset + 8);
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          if (data >= 0x100)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-          bytes[3] = *codes++;
-
-          bytes[2] |= ((data & 0xF0) >> 4);
-          bytes[3] |= data & 0xF;
-          break;
-
-        case 0x23:      // LDRH Rd, Rn
-          ++codes;
-
-          bytes[0] = c | 0x01;          // Implicit pre-index
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (c == 0x15)                // R15
-            data = -8;
-          else
-            data = 0;
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          if (data >= 0x100)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-          bytes[3] = *codes++;
-
-          bytes[2] |= ((data & 0xF0) >> 4);
-          bytes[3] |= data & 0xF;
-          break;
-
-        case 0x24:      // LDRH Rd, Rn, expression
-        case 0x25:      // LDRH Rd, Rn, Rm
-          ++codes;
-
-          bytes[0] = c;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (ins->oprs[ins->operands-1].bracket)       // FIXME: Bracket on last operand -> pre-index  <--
-            {
-              bytes[0] |= 0x01;         // pre-index mode
-              if (has_W_code)
-                {
-                  bytes[1] |= 0x20;
-                }
-            }
-          else
-            {
-              if (has_W_code)
-                {
-                  errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
-                }
-            }
-
-          bytes[3] = *codes++;
-
-          if (keep == 0x24)
-            {
-              data = ins->oprs[2].offset;
-
-              if (data < 0)
-                {
-                  data = -data;
-                }
-              else
-                {
-                  bytes[1] |= 0x80;
-                }
-
-              if (data >= 0x100)
-                {
-                  errfunc (ERR_NONFATAL, "too long offset");
-                }
-
-              bytes[2] |= ((data & 0xF0) >> 4);
-              bytes[3] |= data & 0xF;
-            }
-          else
-            {
-              if (ins->oprs[2].minus == 0)
-                {
-                  bytes[1] |= 0x80;
-                }
-              c = regval (&ins->oprs[2],1);
-              bytes[3] |= c;
-
-            }
-          break;
-
-        case 0x26:      // LDM/STM Rn, {reg-list}
-          ++codes;
-
-          bytes[0] = c;
-
-          bytes[0] |= ( *codes >> 4) & 0xF;
-          bytes[1] = ( *codes << 4) & 0xF0;
-          ++codes;
-
-          if (has_W_code)
-            {
-              bytes[1] |= 0x20;
-            }
-          if (has_F_code)
-            {
-              bytes[1] |= 0x40;
-            }
-
-          // Rn
-          bytes[1] |= regval (&ins->oprs[0],1);
-
-          data = ins->oprs[1].basereg;
-
-          bytes[2] = ((data >> 8) & 0xFF);
-          bytes[3] = (data & 0xFF);
-
-          break;
-
-        case 0x27:      // SWP Rd, Rm, [Rn]
-          ++codes;
-
-          bytes[0] = c;
-
-          bytes[0] |= *codes++;
-
-          bytes[1] = regval (&ins->oprs[2],1);
-          if (has_B_code)
-            {
-              bytes[1] |= 0x40;
-            }
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          bytes[3] = *codes++;
-          bytes[3] |= regval (&ins->oprs[1],1);
-          break;
-
-        default:
-          errfunc (ERR_FATAL, "unknown decoding of instruction");
-
-          bytes[0] = c;
-          // And a fix nibble
-          ++codes;
-          bytes[0] |= *codes++;
-
-         if ( *codes == 0x01)           // An I bit
-           {
-
-           }
-         if ( *codes == 0x02)           // An I bit
-           {
-
-           }
-         ++codes;
-      }
-    out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-}
-
-*)
-{$endif dummy}
-
 begin
   cai_align:=tai_align;
 end.

+ 302 - 0
compiler/aarch64/agcpugas.pas

@@ -0,0 +1,302 @@
+{
+    Copyright (c) 2003,2014 by Florian Klaempfl and Jonas Maebe
+
+    This unit implements an asm for AArch64
+
+    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 AArch64
+}
+
+unit agcpugas;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       globtype,systems,
+       aasmtai,
+       aggas,
+       cpubase,cpuinfo;
+
+    type
+      TAArch64InstrWriter=class(TCPUInstrWriter)
+        procedure WriteInstruction(hp : tai);override;
+      end;
+
+      TAArch64Assembler=class(TGNUassembler)
+        constructor create(info: pasminfo; smart: boolean); override;
+      end;
+
+      TAArch64AppleAssembler=class(TAppleGNUassembler)
+        constructor create(info: pasminfo; smart: boolean); override;
+      end;
+
+
+    const
+      gas_shiftmode2str : array[tshiftmode] of string[4] = (
+        '','lsl','lsr','asr',
+        'uxtb','uxth','uxtw','uxtx',
+        'sxtb','sxth','sxtw','sxtx');
+
+    const 
+      cputype_to_gas_march : array[tcputype] of string = (
+        '', // cpu_none
+        'armv8'
+      );
+
+  implementation
+
+    uses
+       cutils,globals,verbose,
+       assemble,
+       aasmcpu,
+       itcpugas,
+       cgbase,cgutils;
+
+
+{****************************************************************************}
+{                      AArch64 Assembler writer                              }
+{****************************************************************************}
+
+    constructor TAArch64Assembler.create(info: pasminfo; smart: boolean);
+      begin
+        inherited;
+        InstrWriter := TAArch64InstrWriter.create(self);
+      end;
+
+{****************************************************************************}
+{                      Apple AArch64 Assembler writer                        }
+{****************************************************************************}
+
+    constructor TAArch64AppleAssembler.create(info: pasminfo; smart: boolean);
+      begin
+        inherited;
+        InstrWriter := TAArch64InstrWriter.create(self);
+      end;
+
+
+{****************************************************************************}
+{                  Helper routines for Instruction Writer                    }
+{****************************************************************************}
+
+    function getreferencestring(asminfo: pasminfo; var ref : treference) : string;
+      const
+        darwin_addrpage2str: array[addr_page..addr_gotpageoffset] of string[11] =
+           ('@PAGE','@PAGEOFF','@GOTPAGE','@GOTPAGEOFF');
+        linux_addrpage2str: array[addr_page..addr_gotpageoffset] of string[10] =
+           ('',':lo12:',':got:',':got_lo12:');
+      begin
+        if ref.base=NR_NO then
+          begin
+            case ref.refaddr of
+              addr_gotpage,
+              addr_page,
+              addr_gotpageoffset,
+              addr_pageoffset:
+                begin
+                  if not assigned(ref.symbol) or
+                     (ref.base<>NR_NO) or
+                     (ref.index<>NR_NO) or
+                     (ref.shiftmode<>SM_None) or
+                     (ref.offset<>0) then
+                    internalerror(2014121501);
+                  if target_info.system in systems_darwin then
+                    result:=ref.symbol.name+darwin_addrpage2str[ref.refaddr]
+                  else
+                    result:=linux_addrpage2str[ref.refaddr]+ref.symbol.name
+                end
+              else
+                internalerror(2015022301);
+            end
+          end
+        else
+          begin
+            result:='['+gas_regname(ref.base);
+            if ref.addressmode=AM_POSTINDEXED then
+              result:=result+']';
+            if ref.index<>NR_NO then
+              begin
+                if (ref.offset<>0) or
+                   assigned(ref.symbol) then
+                  internalerror(2014121504);
+                result:=result+', '+gas_regname(ref.index);
+                case ref.shiftmode of
+                  SM_None: ;
+                  SM_LSL,
+                  SM_UXTW, SM_UXTX, SM_SXTW, SM_SXTX:
+                    begin
+                      result:=result+', '+gas_shiftmode2str[ref.shiftmode];
+                      if (ref.shiftmode=SM_LSL) or
+                         (ref.shiftimm<>0) then
+                        result:=result+' #'+tostr(ref.shiftimm);
+                    end
+                  else
+                    internalerror(2014121505);
+                end;
+              end
+            else
+              begin
+                if assigned(ref.symbol) then
+                  begin
+                    case ref.refaddr of
+                      addr_gotpageoffset,
+                      addr_pageoffset:
+                        begin
+                          if target_info.system in systems_darwin then
+                            result:=result+', '+ref.symbol.name+darwin_addrpage2str[ref.refaddr]
+                          else
+                            result:=result+', '+linux_addrpage2str[ref.refaddr]+ref.symbol.name
+                        end
+                      else
+                        { todo: not yet generated/don't know syntax }
+                        internalerror(2014121506);
+                    end;
+                  end
+                else
+                  begin
+                    if ref.refaddr<>addr_no then
+                      internalerror(2014121506);
+                    if (ref.offset<>0) then
+                      result:=result+', #'+tostr(ref.offset);
+                  end;
+              end;
+            case ref.addressmode of
+              AM_OFFSET:
+                result:=result+']';
+              AM_PREINDEXED:
+                result:=result+']!';
+            end;
+          end;
+      end;
+
+
+    function getopstr(asminfo: pasminfo; hp: taicpu; opnr: longint; const o: toper): string;
+      begin
+        case o.typ of
+          top_reg:
+            { we cannot yet represent "umov w0, v4.s[0]" or "ins v4.d[0], x1",
+              so for now we use "s4" or "d4" instead -> translate here }
+            if ((hp.opcode=A_INS) or
+                (hp.opcode=A_UMOV)) and
+               (getregtype(hp.oper[opnr]^.reg)=R_MMREGISTER) then
+              begin
+                case getsubreg(hp.oper[opnr]^.reg) of
+                  R_SUBMMS:
+                    getopstr:='v'+tostr(getsupreg(hp.oper[opnr]^.reg))+'.S[0]';
+                  R_SUBMMD:
+                    getopstr:='v'+tostr(getsupreg(hp.oper[opnr]^.reg))+'.D[0]';
+                  else
+                    internalerror(2014122907);
+                end;
+              end
+            else
+              getopstr:=gas_regname(o.reg);
+          top_shifterop:
+            begin
+              getopstr:=gas_shiftmode2str[o.shifterop^.shiftmode];
+              if o.shifterop^.shiftimm<>0 then
+                getopstr:=getopstr+' #'+tostr(o.shifterop^.shiftimm)
+            end;
+          top_const:
+            if o.val>=0 then
+              getopstr:='#'+tostr(o.val)
+            else
+              getopstr:='#0x'+hexStr(o.val,16);
+          top_conditioncode:
+            getopstr:=cond2str[o.cc];
+          top_ref:
+            if is_calljmp(hp.opcode) then
+              begin
+                if o.ref^.refaddr<>addr_full then
+                  internalerror(2014122220);
+                if not assigned(o.ref^.symbol) or
+                   assigned(o.ref^.relsymbol) or
+                   (o.ref^.base<>NR_NO) or
+                   (o.ref^.index<>NR_NO) or
+                   (o.ref^.offset<>0) then
+                  internalerror(2014122221);
+                getopstr:=o.ref^.symbol.name;
+              end
+            else
+              getopstr:=getreferencestring(asminfo,o.ref^);
+          else
+            internalerror(2014121507);
+        end;
+      end;
+
+
+    procedure TAArch64InstrWriter.WriteInstruction(hp : tai);
+      var
+        op: TAsmOp;
+        s: string;
+        i: byte;
+        sep: string[3];
+      begin
+        op:=taicpu(hp).opcode;
+        s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix];
+        if taicpu(hp).condition<>C_NONE then
+          s:=s+'.'+cond2str[taicpu(hp).condition];
+        if taicpu(hp).ops<>0 then
+          begin
+            sep:=#9;
+            for i:=0 to taicpu(hp).ops-1 do
+              begin
+                 // debug code
+                 // writeln(s);
+                 // writeln(taicpu(hp).fileinfo.line);
+                 s:=s+sep+getopstr(owner.asminfo,taicpu(hp),i,taicpu(hp).oper[i]^);
+                 sep:=',';
+              end;
+          end;
+        owner.writer.AsmWriteLn(s);
+      end;
+
+
+    const
+       as_aarch64_gas_info : tasminfo =
+          (
+            id     : as_gas;
+            idtxt  : 'AS';
+            asmbin : 'as';
+            asmcmd : '-o $OBJ $EXTRAOPT $ASM';
+            supported_targets : [system_aarch64_linux];
+            flags : [af_needar,af_smartlink_sections];
+            labelprefix : '.L';
+            comment : '// ';
+            dollarsign: '$';
+          );
+
+       as_aarch64_clang_darwin_info : tasminfo =
+          (
+            id     : as_clang;
+            idtxt  : 'CLANG';
+            asmbin : 'clang';
+            asmcmd : '-c -o $OBJ $EXTRAOPT -arch arm64 $DARWINVERSION -x assembler $ASM';
+            supported_targets : [system_aarch64_darwin];
+            flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
+            labelprefix : 'L';
+            comment : '# ';
+            dollarsign: '$';
+          );
+
+
+begin
+  RegisterAssembler(as_aarch64_gas_info,TAArch64Assembler);
+  RegisterAssembler(as_aarch64_clang_darwin_info,TAArch64AppleAssembler);
+end.

+ 25 - 7
compiler/aarch64/aoptcpub.pas

@@ -118,17 +118,35 @@ Implementation
     End;
 
 
-  function TAoptBaseCpu.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
+  function TAoptBaseCpu.RegModifiedByInstruction(reg: tregister; p1: tai): boolean;
     var
-      i : Longint;
+      i: longint;
+      preg: tregister;
     begin
       result:=false;
       for i:=0 to taicpu(p1).ops-1 do
-        if (taicpu(p1).oper[i]^.typ=top_reg) and (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
-          begin
-            result:=true;
-            exit;
-          end;
+        case taicpu(p1).oper[i]^.typ of
+          top_reg:
+            begin
+              preg:=taicpu(p1).oper[i]^.reg;
+              if (getregtype(preg)=getregtype(reg)) and
+                 (getsupreg(preg)=getsupreg(reg)) and
+                 (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
+                begin
+                  result:=true;
+                  exit;
+                end;
+            end;
+          top_ref:
+            begin
+              if (taicpu(p1).oper[i]^.ref^.addressmode<>am_offset) and
+                 (reg=taicpu(p1).oper[i]^.ref^.base) then
+                begin
+                  result:=true;
+                  exit
+                end;
+            end;
+        end;
     end;
 
 End.

+ 2213 - 0
compiler/aarch64/cgcpu.pas

@@ -0,0 +1,2213 @@
+{
+    Copyright (c) 2014 by Jonas Maebe
+
+    This unit implements the code generator for AArch64
+
+    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,parabase,
+       cgbase,cgutils,cgobj,
+       aasmbase,aasmtai,aasmdata,aasmcpu,
+       cpubase,cpuinfo,
+       node,symconst,SymType,symdef,
+       rgcpu;
+
+    type
+      tcgaarch64=class(tcg)
+       protected
+        { changes register size without adding register allocation info }
+        function makeregsize(reg: tregister; size: tcgsize): tregister; overload;
+       public
+        { simplifies "ref" so it can be used with "op". If "ref" can be used
+          with a different load/Store operation that has the same meaning as the
+          original one, "op" will be replaced with the alternative }
+        procedure make_simple_ref(list:TAsmList; var op: tasmop; size: tcgsize; oppostfix: toppostfix; var ref: treference; preferred_newbasereg: tregister);
+        function getfpuregister(list: TAsmList; size: Tcgsize): Tregister; override;
+        procedure handle_reg_imm12_reg(list: TAsmList; op: Tasmop; size: tcgsize; src: tregister; a: tcgint; dst: tregister; tmpreg: tregister; setflags, usedest: boolean);
+        procedure init_register_allocators;override;
+        procedure done_register_allocators;override;
+        function  getmmregister(list:TAsmList;size:tcgsize):tregister;override;
+        function handle_load_store(list:TAsmList; op: tasmop; size: tcgsize; oppostfix: toppostfix; reg: tregister; ref: treference):treference;
+        procedure a_call_name(list:TAsmList;const s:string; weak: boolean);override;
+        procedure a_call_reg(list:TAsmList;Reg:tregister);override;
+        { General purpose instructions }
+        procedure maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
+        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_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg: tregister);override;
+        procedure a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference); override;
+        procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister;const ref: TReference);override;
+        procedure a_load_reg_ref_unaligned(list: TAsmList; fromsize, tosize: tcgsize; register: tregister; const ref: treference); override;
+        procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);override;
+        procedure a_load_ref_reg_unaligned(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; register: tregister); override;
+        procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);override;
+        procedure a_loadaddr_ref_reg(list: TAsmList; const ref: TReference; r: tregister);override;
+        { fpu move instructions (not used, all floating point is vector unit-based) }
+        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+        procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);override;
+        procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister; shuffle: pmmshuffle);override;
+        procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference; shuffle: pmmshuffle);override;
+
+        procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle); override;
+        procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle); override;
+
+        procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle); override;
+
+        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
+        { 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_always(list: TAsmList; l: TAsmLabel);override;
+        procedure a_jmp_name(list: TAsmList; const s: string);override;
+        procedure a_jmp_cond(list: TAsmList; cond: TOpCmp; 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_overflowcheck(list: TAsmList; const loc: tlocation; def: tdef);override;
+        procedure g_overflowcheck_loc(list: TAsmList; const loc: tlocation; def: tdef; ovloc: tlocation);override;
+        procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);override;
+        procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);override;
+        procedure g_maybe_got_init(list: TAsmList); override;
+        procedure g_restore_registers(list: TAsmList);override;
+        procedure g_save_registers(list: TAsmList);override;
+        procedure g_concatcopy_move(list: TAsmList; const source, dest: treference; len: tcgint);
+        procedure g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);override;
+        procedure g_adjust_self_value(list: TAsmList; procdef: tprocdef; ioffset: tcgint);override;
+       private
+        function save_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister): longint;
+        procedure load_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister);
+      end;
+
+    procedure create_codegen;
+
+    const
+      TOpCG2AsmOpReg: array[topcg] of TAsmOp = (
+        A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NEG,A_MVN,A_ORR,A_ASRV,A_LSLV,A_LSRV,A_SUB,A_EOR,A_NONE,A_RORV
+      );
+      TOpCG2AsmOpImm: array[topcg] of TAsmOp = (
+        A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NEG,A_MVN,A_ORR,A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_NONE,A_ROR
+      );
+      TOpCmp2AsmCond: 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
+      );
+
+
+implementation
+
+  uses
+    globals,verbose,systems,cutils,
+    paramgr,fmodule,
+    symtable,symsym,
+    tgobj,
+    procinfo,cpupi;
+
+
+    procedure tcgaarch64.make_simple_ref(list:TAsmList; var op: tasmop; size: tcgsize; oppostfix: toppostfix; var ref: treference; preferred_newbasereg: tregister);
+      var
+        href: treference;
+        so: tshifterop;
+        accesssize: longint;
+      begin
+        if (ref.base=NR_NO) then
+          begin
+            if ref.shiftmode<>SM_None then
+              internalerror(2014110701);
+            ref.base:=ref.index;
+            ref.index:=NR_NO;
+          end;
+        { no abitrary scale factor support (the generic code doesn't set it,
+          AArch-specific code shouldn't either) }
+        if not(ref.scalefactor in [0,1]) then
+          internalerror(2014111002);
+
+        case simple_ref_type(op,size,oppostfix,ref) of
+          sr_simple:
+            exit;
+          sr_internal_illegal:
+            internalerror(2014121702);
+          sr_complex:
+            { continue } ;
+        end;
+
+        if assigned(ref.symbol) then
+          begin
+            { internal "load symbol" instructions should already be valid }
+            if assigned(ref.symboldata) or
+               (ref.refaddr in [addr_pic,addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset]) then
+              internalerror(2014110802);
+            { no relative symbol support (needed) yet }
+            if assigned(ref.relsymbol) then
+              internalerror(2014111001);
+            { loading a symbol address (whether it's in the GOT or not) consists
+              of two parts: first load the page on which it is located, then
+              either the offset in the page or load the value at that offset in
+              the page. This final GOT-load can be relaxed by the linker in case
+              the variable itself can be stored directly in the GOT }
+            if (preferred_newbasereg=NR_NO) or
+               (ref.base=preferred_newbasereg) or
+               (ref.index=preferred_newbasereg) then
+              preferred_newbasereg:=getaddressregister(list);
+            { load the (GOT) page }
+            reference_reset_symbol(href,ref.symbol,0,8);
+            if ((ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) and
+                (ref.symbol.bind in [AB_LOCAL,AB_GLOBAL])) or
+               ((ref.symbol.typ=AT_DATA) and
+                (ref.symbol.bind=AB_LOCAL)) then
+              href.refaddr:=addr_page
+            else
+              href.refaddr:=addr_gotpage;
+            list.concat(taicpu.op_reg_ref(A_ADRP,preferred_newbasereg,href));
+            { load the GOT entry (= address of the variable) }
+            reference_reset_base(href,preferred_newbasereg,0,sizeof(pint));
+            href.symbol:=ref.symbol;
+            { code symbols defined in the current compilation unit do not
+              have to be accessed via the GOT }
+            if ((ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) and
+                (ref.symbol.bind in [AB_LOCAL,AB_GLOBAL])) or
+               ((ref.symbol.typ=AT_DATA) and
+                (ref.symbol.bind=AB_LOCAL)) then
+              begin
+                href.base:=NR_NO;
+                href.refaddr:=addr_pageoffset;
+                list.concat(taicpu.op_reg_reg_ref(A_ADD,preferred_newbasereg,preferred_newbasereg,href));
+              end
+            else
+              begin
+                href.refaddr:=addr_gotpageoffset;
+                { use a_load_ref_reg() rather than directly encoding the LDR,
+                  so that we'll check the validity of the reference }
+                a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,preferred_newbasereg);
+              end;
+            { set as new base register }
+            if ref.base=NR_NO then
+              ref.base:=preferred_newbasereg
+            else if ref.index=NR_NO then
+              ref.index:=preferred_newbasereg
+            else
+              begin
+                { make sure it's valid in case ref.base is SP -> make it
+                  the second operand}
+                a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,preferred_newbasereg,ref.base,preferred_newbasereg);
+                ref.base:=preferred_newbasereg
+              end;
+            ref.symbol:=nil;
+          end;
+
+        { base & index }
+        if (ref.base<>NR_NO) and
+           (ref.index<>NR_NO) then
+          begin
+            case op of
+              A_LDR, A_STR:
+                begin
+                  if (ref.shiftmode=SM_None) and
+                     (ref.shiftimm<>0) then
+                    internalerror(2014110805);
+                  { wrong shift? (possible in case of something like
+                     array_of_2byte_rec[x].bytefield -> shift will be set 1, but
+                     the final load is a 1 byte -> can't use shift after all }
+                  if (ref.shiftmode in [SM_LSL,SM_UXTW,SM_SXTW]) and
+                     ((ref.shiftimm<>BsfDWord(tcgsizep2size[size])) or
+                      (ref.offset<>0)) then
+                    begin
+                      if preferred_newbasereg=NR_NO then
+                        preferred_newbasereg:=getaddressregister(list);
+                      { "add" supports a superset of the shift modes supported by
+                        load/store instructions }
+                      shifterop_reset(so);
+                      so.shiftmode:=ref.shiftmode;
+                      so.shiftimm:=ref.shiftimm;
+                      list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,preferred_newbasereg,ref.base,ref.index,so));
+                      reference_reset_base(ref,preferred_newbasereg,ref.offset,ref.alignment);
+                      { possibly still an invalid offset -> fall through }
+                    end
+                  else if ref.offset<>0 then
+                    begin
+                      if (preferred_newbasereg=NR_NO) or
+                         { we keep ref.index, so it must not be overwritten }
+                         (ref.index=preferred_newbasereg) then
+                        preferred_newbasereg:=getaddressregister(list);
+                      { add to the base and not to the index, because the index
+                        may be scaled; this works even if the base is SP }
+                      a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,preferred_newbasereg);
+                      ref.offset:=0;
+                      ref.base:=preferred_newbasereg;
+                      { finished }
+                      exit;
+                    end
+                  else
+                    { valid -> exit }
+                    exit;
+                end;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110704);
+              { these don't support base+index }
+              A_LDUR,A_STUR,
+              A_LDP,A_STP:
+                begin
+                  { these either don't support pre-/post-indexing, or don't
+                    support it with base+index }
+                  if ref.addressmode<>AM_OFFSET then
+                    internalerror(2014110911);
+                  if preferred_newbasereg=NR_NO then
+                    preferred_newbasereg:=getaddressregister(list);
+                  if ref.shiftmode<>SM_None then
+                    begin
+                      { "add" supports a superset of the shift modes supported by
+                        load/store instructions }
+                      shifterop_reset(so);
+                      so.shiftmode:=ref.shiftmode;
+                      so.shiftimm:=ref.shiftimm;
+                      list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,preferred_newbasereg,ref.base,ref.index,so));
+                    end
+                  else
+                    a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,ref.index,ref.base,preferred_newbasereg);
+                  reference_reset_base(ref,preferred_newbasereg,ref.offset,ref.alignment);
+                  { fall through to the handling of base + offset, since the
+                    offset may still be too big }
+                end;
+              else
+                internalerror(2014110901);
+            end;
+          end;
+
+        { base + offset }
+        if ref.base<>NR_NO then
+          begin
+            { valid offset for LDUR/STUR -> use that }
+            if (ref.addressmode=AM_OFFSET) and
+               (op in [A_LDR,A_STR]) and
+               (ref.offset>=-256) and
+               (ref.offset<=255) then
+              begin
+                if op=A_LDR then
+                  op:=A_LDUR
+                else
+                  op:=A_STUR
+              end
+            { if it's not a valid LDUR/STUR, use LDR/STR }
+            else if (op in [A_LDUR,A_STUR]) and
+               ((ref.offset<-256) or
+                (ref.offset>255) or
+                (ref.addressmode<>AM_OFFSET)) then
+              begin
+                if op=A_LDUR then
+                  op:=A_LDR
+                else
+                  op:=A_STR
+              end;
+            case op of
+              A_LDR,A_STR:
+                begin
+                  case ref.addressmode of
+                    AM_PREINDEXED:
+                      begin
+                        { since the loaded/stored register cannot be the same
+                          as the base register, we can safely add the
+                          offset to the base if it doesn't fit}
+                        if (ref.offset<-256) or
+                            (ref.offset>255) then
+                          begin
+                            a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base);
+                            ref.offset:=0;
+                          end;
+                      end;
+                    AM_POSTINDEXED:
+                      begin
+                        { cannot emulate post-indexing if we have to fold the
+                          offset into the base register }
+                        if (ref.offset<-256) or
+                            (ref.offset>255) then
+                          internalerror(2014110909);
+                        { ok }
+                      end;
+                    AM_OFFSET:
+                      begin
+                        { unsupported offset -> fold into base register }
+                        accesssize:=1 shl tcgsizep2size[size];
+                        if (ref.offset<0) or
+                           (ref.offset>(((1 shl 12)-1)*accesssize)) or
+                           ((ref.offset mod accesssize)<>0) then
+                          begin
+                            if preferred_newbasereg=NR_NO then
+                              preferred_newbasereg:=getaddressregister(list);
+                            { can we split the offset beween an
+                              "add/sub (imm12 shl 12)" and the load (also an
+                              imm12)?
+                              -- the offset from the load will always be added,
+                                that's why the lower bound has a smaller range
+                                than the upper bound; it must also be a multiple
+                                of the access size }
+                            if (ref.offset>=-(((1 shl 12)-1) shl 12)) and
+                               (ref.offset<=((1 shl 12)-1) shl 12 + ((1 shl 12)-1)) and
+                               ((ref.offset mod accesssize)=0) then
+                              begin
+                                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,(ref.offset shr 12) shl 12,ref.base,preferred_newbasereg);
+                                ref.offset:=ref.offset-(ref.offset shr 12) shl 12;
+                              end
+                            else
+                              begin
+                                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,preferred_newbasereg);
+                                ref.offset:=0;
+                              end;
+                            reference_reset_base(ref,preferred_newbasereg,ref.offset,ref.alignment);
+                          end;
+                      end
+                    else
+                      internalerror(2014110904);
+                  end;
+                end;
+              A_LDP,A_STP:
+                begin
+                  { unsupported offset -> fold into base register (these
+                    instructions support all addressmodes) }
+                  if (ref.offset<-(1 shl (6+tcgsizep2size[size]))) or
+                     (ref.offset>(1 shl (6+tcgsizep2size[size]))-1) then
+                    begin
+                      case ref.addressmode of
+                        AM_POSTINDEXED:
+                          { don't emulate post-indexing if we have to fold the
+                            offset into the base register }
+                          internalerror(2014110910);
+                        AM_PREINDEXED:
+                          { this means the offset must be added to the current
+                            base register }
+                          preferred_newbasereg:=ref.base;
+                        AM_OFFSET:
+                          if preferred_newbasereg=NR_NO then
+                            preferred_newbasereg:=getaddressregister(list);
+                      end;
+                      a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,preferred_newbasereg);
+                      reference_reset_base(ref,preferred_newbasereg,0,ref.alignment);
+                    end
+                end;
+              A_LDUR,A_STUR:
+                begin
+                  { valid, checked above }
+                end;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110908);
+              else
+                internalerror(2014110708);
+            end;
+            { done }
+            exit;
+          end;
+
+        { only an offset -> change to base (+ offset 0) }
+        if preferred_newbasereg=NR_NO then
+          preferred_newbasereg:=getaddressregister(list);
+        a_load_const_reg(list,OS_ADDR,ref.offset,preferred_newbasereg);
+        reference_reset_base(ref,preferred_newbasereg,0,newalignment(8,ref.offset));
+      end;
+
+
+    function tcgaarch64.makeregsize(reg: tregister; size: tcgsize): tregister;
+      var
+        subreg:Tsubregister;
+      begin
+        subreg:=cgsize2subreg(getregtype(reg),size);
+        result:=reg;
+        setsubreg(result,subreg);
+      end;
+
+
+    function tcgaarch64.getfpuregister(list: TAsmList; size: Tcgsize): Tregister;
+      begin
+        internalerror(2014122110);
+        { squash warning }
+        result:=NR_NO;
+      end;
+
+
+    function tcgaarch64.handle_load_store(list: TAsmList; op: tasmop; size: tcgsize; oppostfix: toppostfix; reg: tregister; ref: treference):treference;
+      begin
+        make_simple_ref(list,op,size,oppostfix,ref,NR_NO);
+        list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
+        result:=ref;
+      end;
+
+
+    procedure tcgaarch64.handle_reg_imm12_reg(list: TAsmList; op: Tasmop; size: tcgsize; src: tregister; a: tcgint; dst: tregister; tmpreg: tregister; setflags, usedest: boolean);
+      var
+        instr: taicpu;
+        so: tshifterop;
+        hadtmpreg: boolean;
+      begin
+        { imm12 }
+        if (a>=0) and
+           (a<=((1 shl 12)-1)) then
+          if usedest then
+            instr:=taicpu.op_reg_reg_const(op,dst,src,a)
+          else
+            instr:=taicpu.op_reg_const(op,src,a)
+        { imm12 lsl 12 }
+        else if (a and not(((tcgint(1) shl 12)-1) shl 12))=0 then
+          begin
+            so.shiftmode:=SM_LSL;
+            so.shiftimm:=12;
+            if usedest then
+              instr:=taicpu.op_reg_reg_const_shifterop(op,dst,src,a shr 12,so)
+            else
+              instr:=taicpu.op_reg_const_shifterop(op,src,a shr 12,so)
+          end
+        else
+          begin
+            { todo: other possible optimizations (e.g. load 16 bit constant in
+                register and then add/sub/cmp/cmn shifted the rest) }
+            if tmpreg=NR_NO then
+              begin
+                hadtmpreg:=false;
+                tmpreg:=getintregister(list,size);
+              end
+            else
+              begin
+                hadtmpreg:=true;
+                getcpuregister(list,tmpreg);
+              end;
+            a_load_const_reg(list,size,a,tmpreg);
+            if usedest then
+              instr:=taicpu.op_reg_reg_reg(op,dst,src,tmpreg)
+            else
+              instr:=taicpu.op_reg_reg(op,src,tmpreg);
+            if hadtmpreg then
+              ungetcpuregister(list,tmpreg);
+          end;
+        if setflags then
+          setoppostfix(instr,PF_S);
+        list.concat(instr);
+      end;
+
+
+{****************************************************************************
+                              Assembler code
+****************************************************************************}
+
+    procedure tcgaarch64.init_register_allocators;
+      begin
+        inherited init_register_allocators;
+
+        rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+            [RS_X0,RS_X1,RS_X2,RS_X3,RS_X4,RS_X5,RS_X6,RS_X7,RS_X8,
+             RS_X9,RS_X10,RS_X11,RS_X12,RS_X13,RS_X14,RS_X15,RS_X16,RS_X17,
+             RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28
+             { maybe we can enable this in the future for leaf functions (it's
+               the frame pointer)
+             ,RS_X29 }],
+            first_int_imreg,[]);
+
+        rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBMMD,
+            [RS_Q0,RS_Q1,RS_Q2,RS_Q3,RS_Q4,RS_Q5,RS_Q6,RS_Q7,
+             RS_Q8,RS_Q9,RS_Q10,RS_Q11,RS_Q12,RS_Q13,RS_Q14,RS_Q15,
+             RS_Q16,RS_Q17,RS_Q18,RS_Q19,RS_Q20,RS_Q21,RS_Q22,RS_Q23,
+             RS_Q24,RS_Q25,RS_Q26,RS_Q27,RS_Q28,RS_Q29,RS_Q30,RS_Q31],
+            first_mm_imreg,[]);
+      end;
+
+
+    procedure tcgaarch64.done_register_allocators;
+      begin
+        rg[R_INTREGISTER].free;
+        rg[R_FPUREGISTER].free;
+        rg[R_MMREGISTER].free;
+        inherited done_register_allocators;
+      end;
+
+
+    function tcgaarch64.getmmregister(list: TAsmList; size: tcgsize):tregister;
+      begin
+        case size of
+          OS_F32:
+            result:=rg[R_MMREGISTER].getregister(list,R_SUBMMS);
+          OS_F64:
+            result:=rg[R_MMREGISTER].getregister(list,R_SUBMMD)
+          else
+            internalerror(2014102701);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_call_name(list: TAsmList; const s: string; weak: boolean);
+      begin
+        if not weak then
+          list.concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(s)))
+        else
+          list.concat(taicpu.op_sym(A_BL,current_asmdata.WeakRefAsmSymbol(s)));
+      end;
+
+
+    procedure tcgaarch64.a_call_reg(list:TAsmList;Reg:tregister);
+      begin
+        list.concat(taicpu.op_reg(A_BLR,reg));
+      end;
+
+
+    {********************** load instructions ********************}
+
+    procedure tcgaarch64.a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg : tregister);
+      var
+        preva: tcgint;
+        opc: tasmop;
+        shift,maxshift: byte;
+        so: tshifterop;
+        reginited: boolean;
+        mask: tcgint;
+      begin
+        { if we load a value into a 32 bit register, it is automatically
+          zero-extended to 64 bit }
+        if (high(a)=0) and
+           (size in [OS_64,OS_S64]) then
+          begin
+            size:=OS_32;
+            reg:=makeregsize(reg,size);
+          end;
+        { values <= 32 bit are stored in a 32 bit register }
+        if not(size in [OS_64,OS_S64]) then
+          a:=cardinal(a);
+
+        if size in [OS_64,OS_S64] then
+          begin
+            mask:=-1;
+            maxshift:=64;
+          end
+        else
+          begin
+            mask:=$ffffffff;
+            maxshift:=32;
+          end;
+        { single movn enough? (to be extended) }
+        shift:=16;
+        preva:=a;
+        repeat
+          if (a shr shift)=(mask shr shift) then
+            begin
+              if shift=16 then
+                list.concat(taicpu.op_reg_const(A_MOVN,reg,not(word(preva))))
+              else
+                begin
+                  shifterop_reset(so);
+                  so.shiftmode:=SM_LSL;
+                  so.shiftimm:=shift-16;
+                  list.concat(taicpu.op_reg_const_shifterop(A_MOVN,reg,not(word(preva)),so));
+                end;
+              exit;
+            end;
+          { only try the next 16 bits if the current one is all 1 bits, since
+            the movn will set all lower bits to 1 }
+          if word(a shr (shift-16))<>$ffff then
+            break;
+          inc(shift,16);
+        until shift=maxshift;
+        reginited:=false;
+        shift:=0;
+        { can be optimized later to use more movn }
+        repeat
+          { leftover is shifterconst? (don't check if we can represent it just
+            as effectively with movz/movk, as this check is expensive) }
+          if ((shift<tcgsize2size[size]*(8 div 2)) and
+              (word(a)<>0) and
+              ((a shr 16)<>0)) and
+             is_shifter_const(a shl shift,size) then
+            begin
+              if reginited then
+                list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,a shl shift))
+              else
+                list.concat(taicpu.op_reg_reg_const(A_ORR,reg,makeregsize(NR_XZR,size),a shl shift));
+              exit;
+            end;
+          { set all 16 bit parts <> 0 }
+          if (word(a)<>0) or
+             ((shift=0) and
+              (a=0)) then
+            if shift=0 then
+              begin
+                list.concat(taicpu.op_reg_const(A_MOVZ,reg,word(a)));
+                reginited:=true;
+              end
+            else
+              begin
+                shifterop_reset(so);
+                so.shiftmode:=SM_LSL;
+                so.shiftimm:=shift;
+                if not reginited then
+                  begin
+                    opc:=A_MOVZ;
+                    reginited:=true;
+                  end
+                else
+                  opc:=A_MOVK;
+                list.concat(taicpu.op_reg_const_shifterop(opc,reg,word(a),so));
+              end;
+            preva:=a;
+            a:=a shr 16;
+           inc(shift,16);
+        until word(preva)=preva;
+        if not reginited then
+          internalerror(2014102702);
+      end;
+
+
+    procedure tcgaarch64.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
+      var
+        reg: tregister;
+      begin
+        { use the zero register if possible }
+        if a=0 then
+          begin
+            if size in [OS_64,OS_S64] then
+              reg:=NR_XZR
+            else
+              reg:=NR_WZR;
+            a_load_reg_ref(list,size,size,reg,ref);
+          end
+        else
+          inherited;
+      end;
+
+
+    procedure tcgaarch64.a_load_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+      var
+        oppostfix:toppostfix;
+        hreg: tregister;
+      begin
+        if tcgsize2Size[fromsize]>=tcgsize2Size[tosize] then
+          fromsize:=tosize
+        { have a 32 bit register but need a 64 bit one? }
+        else if tosize in [OS_64,OS_S64] then
+          begin
+            { sign extend if necessary }
+            if fromsize in [OS_S8,OS_S16,OS_S32] then
+              begin
+                { can't overwrite reg, may be a constant reg }
+                hreg:=getintregister(list,tosize);
+                a_load_reg_reg(list,fromsize,tosize,reg,hreg);
+                reg:=hreg;
+              end
+            else
+              { top 32 bit are zero by default }
+              reg:=makeregsize(reg,OS_64);
+            fromsize:=tosize;
+          end;
+        if (ref.alignment<>0) and
+           (ref.alignment<tcgsize2size[tosize]) then
+          begin
+            a_load_reg_ref_unaligned(list,fromsize,tosize,reg,ref);
+          end
+        else
+          begin
+            case tosize of
+              { signed integer registers }
+              OS_8,
+              OS_S8:
+                oppostfix:=PF_B;
+              OS_16,
+              OS_S16:
+                oppostfix:=PF_H;
+              OS_32,
+              OS_S32,
+              OS_64,
+              OS_S64:
+                oppostfix:=PF_None;
+              else
+                InternalError(200308299);
+            end;
+            handle_load_store(list,A_STR,tosize,oppostfix,reg,ref);
+          end;
+      end;
+
+
+    procedure tcgaarch64.a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+      var
+        oppostfix:toppostfix;
+      begin
+        if tcgsize2Size[fromsize]>=tcgsize2Size[tosize] then
+          fromsize:=tosize;
+        { ensure that all bits of the 32/64 register are always correctly set:
+           * default behaviour is always to zero-extend to the entire (64 bit)
+             register -> unsigned 8/16/32 bit loads only exist with a 32 bit
+             target register, as the upper 32 bit will be zeroed implicitly
+             -> always make target register 32 bit
+           * signed loads exist both with 32 and 64 bit target registers,
+             depending on whether the value should be sign extended to 32 or
+             to 64 bit (if sign extended to 32 bit, the upper 32 bits of the
+             corresponding 64 bit register are again zeroed) -> no need to
+             change anything (we only have 32 and 64 bit registers), except that
+             when loading an OS_S32 to a 32 bit register, we don't need/can't
+             use sign extension
+        }
+        if fromsize in [OS_8,OS_16,OS_32] then
+          reg:=makeregsize(reg,OS_32);
+        if (ref.alignment<>0) and
+           (ref.alignment<tcgsize2size[fromsize]) then
+          begin
+            a_load_ref_reg_unaligned(list,fromsize,tosize,ref,reg);
+            exit;
+          end;
+        case fromsize of
+          { signed integer registers }
+          OS_8:
+            oppostfix:=PF_B;
+          OS_S8:
+            oppostfix:=PF_SB;
+          OS_16:
+            oppostfix:=PF_H;
+          OS_S16:
+            oppostfix:=PF_SH;
+          OS_S32:
+            if getsubreg(reg)=R_SUBD then
+              oppostfix:=PF_NONE
+            else
+              oppostfix:=PF_SW;
+          OS_32,
+          OS_64,
+          OS_S64:
+            oppostfix:=PF_None;
+          else
+            InternalError(200308297);
+        end;
+        handle_load_store(list,A_LDR,fromsize,oppostfix,reg,ref);
+
+        { clear upper 16 bits if the value was negative }
+        if (fromsize=OS_S8) and (tosize=OS_16) then
+          a_load_reg_reg(list,fromsize,tosize,reg,reg);
+      end;
+
+
+    procedure tcgaarch64.a_load_ref_reg_unaligned(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; register: tregister);
+      var
+        href: treference;
+        hreg1, hreg2, tmpreg: tregister;
+      begin
+        if fromsize in [OS_64,OS_S64] then
+          begin
+            { split into two 32 bit loads }
+            hreg1:=getintregister(list,OS_32);
+            hreg2:=getintregister(list,OS_32);
+            if target_info.endian=endian_big then
+              begin
+                tmpreg:=hreg1;
+                hreg1:=hreg2;
+                hreg2:=tmpreg;
+              end;
+            { can we use LDP? }
+            if (ref.alignment=4) and
+               (simple_ref_type(A_LDP,OS_32,PF_None,ref)=sr_simple) then
+              list.concat(taicpu.op_reg_reg_ref(A_LDP,hreg1,hreg2,ref))
+            else
+              begin
+                a_load_ref_reg(list,OS_32,OS_32,ref,hreg1);
+                href:=ref;
+                inc(href.offset,4);
+                a_load_ref_reg(list,OS_32,OS_32,href,hreg2);
+              end;
+            a_load_reg_reg(list,OS_32,OS_64,hreg1,register);
+            list.concat(taicpu.op_reg_reg_const_const(A_BFI,register,makeregsize(hreg2,OS_64),32,32));
+          end
+       else
+         inherited;
+      end;
+
+
+    procedure tcgaarch64.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
+      var
+        instr: taicpu;
+      begin
+        { we use both 32 and 64 bit registers -> insert conversion when when
+          we have to truncate/sign extend inside the (32 or 64 bit) register
+          holding the value, and when we sign extend from a 32 to a 64 bit
+          register }
+        if (tcgsize2size[fromsize]>tcgsize2size[tosize]) or
+           ((tcgsize2size[fromsize]=tcgsize2size[tosize]) and
+            (fromsize<>tosize) and
+            not(fromsize in [OS_32,OS_S32,OS_64,OS_S64])) or
+           ((fromsize in [OS_S8,OS_S16,OS_S32]) and
+            (tosize in [OS_64,OS_S64])) or
+           { needs to mask out the sign in the top 16 bits }
+           ((fromsize=OS_S8) and
+            (tosize=OS_16)) then
+          begin
+            case tosize of
+              OS_8:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_UXT,reg2,makeregsize(reg1,OS_32)),PF_B));
+              OS_16:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_UXT,reg2,makeregsize(reg1,OS_32)),PF_H));
+              OS_S8:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_B));
+              OS_S16:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_H));
+              { while "mov wN, wM" automatically inserts a zero-extension and
+                hence we could encode a 64->32 bit move like that, the problem
+                is that we then can't distinguish 64->32 from 32->32 moves, and
+                the 64->32 truncation could be removed altogether... So use a
+                different instruction }
+              OS_32,
+              OS_S32:
+                { in theory, reg1 should be 64 bit here (since fromsize>tosize),
+                  but because of the way location_force_register() tries to
+                  avoid superfluous zero/sign extensions, it's not always the
+                  case -> also force reg1 to to 64 bit }
+                list.concat(taicpu.op_reg_reg_const_const(A_UBFIZ,makeregsize(reg2,OS_64),makeregsize(reg1,OS_64),0,32));
+              OS_64,
+              OS_S64:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_W));
+              else
+                internalerror(2002090901);
+            end;
+          end
+        else
+          begin
+            { 32 -> 32 bit move implies zero extension (sign extensions have
+              been handled above) -> also use for 32 <-> 64 bit moves }
+            if not(fromsize in [OS_64,OS_S64]) or
+               not(tosize in [OS_64,OS_S64]) then
+              instr:=taicpu.op_reg_reg(A_MOV,makeregsize(reg2,OS_32),makeregsize(reg1,OS_32))
+            else
+              instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+            list.Concat(instr);
+            { Notify the register allocator that we have written a move instruction so
+             it can try to eliminate it. }
+            add_move_instruction(instr);
+          end;
+      end;
+
+
+    procedure tcgaarch64.a_loadaddr_ref_reg(list: TAsmList; const ref: treference; r: tregister);
+      var
+         href: treference;
+         so: tshifterop;
+         op: tasmop;
+      begin
+        op:=A_LDR;
+        href:=ref;
+        { simplify as if we're going to perform a regular 64 bit load, using
+          "r" as the new base register if possible/necessary }
+        make_simple_ref(list,op,OS_ADDR,PF_None,href,r);
+        { load literal? }
+        if assigned(href.symbol) then
+          begin
+            if (href.base<>NR_NO) or
+               (href.index<>NR_NO) or
+               not assigned(href.symboldata) then
+              internalerror(2014110912);
+            list.concat(taicpu.op_reg_sym_ofs(A_ADR,r,href.symbol,href.offset));
+          end
+        else
+          begin
+            if href.index<>NR_NO then
+              begin
+                if href.shiftmode<>SM_None then
+                  begin
+                    { "add" supports a supperset of the shift modes supported by
+                      load/store instructions }
+                    shifterop_reset(so);
+                    so.shiftmode:=href.shiftmode;
+                    so.shiftimm:=href.shiftimm;
+                    list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,r,href.base,href.index,so));
+                  end
+                else
+                  a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,href.index,href.base,r);
+              end
+            else if href.offset<>0 then
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,href.offset,href.base,r)
+            else
+              a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r);
+          end;
+      end;
+
+
+    procedure tcgaarch64.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+      begin
+        internalerror(2014122107)
+      end;
+
+
+    procedure tcgaarch64.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+      begin
+        internalerror(2014122108)
+      end;
+
+
+    procedure tcgaarch64.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+      begin
+        internalerror(2014122109)
+      end;
+
+
+    procedure tcgaarch64.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister; shuffle: pmmshuffle);
+      var
+        instr: taicpu;
+      begin
+        if assigned(shuffle) and
+           not shufflescalar(shuffle) then
+          internalerror(2014122104);
+        if fromsize=tosize then
+          begin
+            instr:=taicpu.op_reg_reg(A_FMOV,reg2,reg1);
+            { Notify the register allocator that we have written a move
+              instruction so it can try to eliminate it. }
+            add_move_instruction(instr);
+          end
+        else
+          begin
+            if (reg_cgsize(reg1)<>fromsize) or
+               (reg_cgsize(reg2)<>tosize) then
+              internalerror(2014110913);
+            instr:=taicpu.op_reg_reg(A_FCVT,reg2,reg1);
+          end;
+        list.Concat(instr);
+      end;
+
+
+    procedure tcgaarch64.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
+       var
+         tmpreg: tregister;
+       begin
+         if assigned(shuffle) and
+            not shufflescalar(shuffle) then
+           internalerror(2014122105);
+         tmpreg:=NR_NO;
+         if (fromsize<>tosize) then
+           begin
+             tmpreg:=reg;
+             reg:=getmmregister(list,fromsize);
+           end;
+         handle_load_store(list,A_LDR,fromsize,PF_None,reg,ref);
+         if (fromsize<>tosize) then
+           a_loadmm_reg_reg(list,fromsize,tosize,reg,tmpreg,nil);
+       end;
+
+
+     procedure tcgaarch64.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
+       var
+         tmpreg: tregister;
+       begin
+         if assigned(shuffle) and
+            not shufflescalar(shuffle) then
+           internalerror(2014122106);
+         if (fromsize<>tosize) then
+           begin
+             tmpreg:=getmmregister(list,tosize);
+             a_loadmm_reg_reg(list,fromsize,tosize,reg,tmpreg,nil);
+             reg:=tmpreg;
+           end;
+         handle_load_store(list,A_STR,tosize,PF_NONE,reg,ref);
+       end;
+
+
+     procedure tcgaarch64.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle);
+       begin
+         if not shufflescalar(shuffle) then
+           internalerror(2014122801);
+         if not(tcgsize2size[fromsize] in [4,8]) or
+            (tcgsize2size[fromsize]<>tcgsize2size[tosize]) then
+           internalerror(2014122803);
+         list.concat(taicpu.op_reg_reg(A_INS,mmreg,intreg));
+       end;
+
+
+     procedure tcgaarch64.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle);
+       begin
+         if not shufflescalar(shuffle) then
+           internalerror(2014122802);
+         if not(tcgsize2size[fromsize] in [4,8]) or
+            (tcgsize2size[fromsize]<>tcgsize2size[tosize]) then
+           internalerror(2014122804);
+         list.concat(taicpu.op_reg_reg(A_UMOV,intreg,mmreg));
+       end;
+
+
+    procedure tcgaarch64.a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle);
+      begin
+        case op of
+          { "xor Vx,Vx" is used to initialize global regvars to 0 }
+          OP_XOR:
+            begin
+              if (src<>dst) or
+                 (reg_cgsize(src)<>size) or
+                 assigned(shuffle) then
+                internalerror(2015011401);
+              case size of
+                OS_F32,
+                OS_F64:
+                  list.concat(taicpu.op_reg_const(A_MOVI,makeregsize(dst,OS_F64),0));
+                else
+                  internalerror(2015011402);
+              end;
+            end
+          else
+            internalerror(2015011403);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
+      var
+        bitsize,
+        signbit: longint;
+      begin
+        if srcsize in [OS_64,OS_S64] then
+          begin
+            bitsize:=64;
+            signbit:=6;
+          end
+        else
+          begin
+            bitsize:=32;
+            signbit:=5;
+          end;
+        { source is 0 -> dst will have to become 255 }
+        list.concat(taicpu.op_reg_const(A_CMP,src,0));
+        if reverse then
+          begin
+            list.Concat(taicpu.op_reg_reg(A_CLZ,makeregsize(dst,srcsize),src));
+            { xor 31/63 is the same as setting the lower 5/6 bits to
+              "31/63-(lower 5/6 bits of dst)" }
+            list.Concat(taicpu.op_reg_reg_const(A_EOR,dst,dst,bitsize-1));
+          end
+        else
+          begin
+            list.Concat(taicpu.op_reg_reg(A_RBIT,makeregsize(dst,srcsize),src));
+            list.Concat(taicpu.op_reg_reg(A_CLZ,dst,dst));
+          end;
+        { set dst to -1 if src was 0 }
+        list.Concat(taicpu.op_reg_reg_reg_cond(A_CSINV,dst,dst,makeregsize(NR_XZR,dstsize),C_NE));
+        { mask the -1 to 255 if src was 0 (anyone find a two-instruction
+          branch-free version? All of mine are 3...) }
+        list.Concat(setoppostfix(taicpu.op_reg_reg(A_UXT,makeregsize(dst,OS_32),makeregsize(dst,OS_32)),PF_B));
+      end;
+
+
+    procedure tcgaarch64.a_load_reg_ref_unaligned(list: TAsmList; fromsize, tosize: tcgsize; register: tregister; const ref: treference);
+      var
+        href: treference;
+        hreg1, hreg2, tmpreg: tregister;
+      begin
+        if fromsize in [OS_64,OS_S64] then
+          begin
+            { split into two 32 bit stores }
+            hreg1:=getintregister(list,OS_32);
+            hreg2:=getintregister(list,OS_32);
+            a_load_reg_reg(list,OS_32,OS_32,makeregsize(register,OS_32),hreg1);
+            a_op_const_reg_reg(list,OP_SHR,OS_64,32,register,makeregsize(hreg2,OS_64));
+            if target_info.endian=endian_big then
+              begin
+                tmpreg:=hreg1;
+                hreg1:=hreg2;
+                hreg2:=tmpreg;
+              end;
+            { can we use STP? }
+            if (ref.alignment=4) and
+               (simple_ref_type(A_STP,OS_32,PF_None,ref)=sr_simple) then
+              list.concat(taicpu.op_reg_reg_ref(A_STP,hreg1,hreg2,ref))
+            else
+              begin
+                a_load_reg_ref(list,OS_32,OS_32,hreg1,ref);
+                href:=ref;
+                inc(href.offset,4);
+                a_load_reg_ref(list,OS_32,OS_32,hreg2,href);
+              end;
+          end
+       else
+         inherited;
+      end;
+
+
+    procedure tcgaarch64.maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
+      const
+        overflowops = [OP_MUL,OP_IMUL,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,makeregsize(dst,OS_32),makeregsize(dst,OS_32))
+      end;
+
+
+    procedure tcgaarch64.a_op_const_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; reg: tregister);
+      begin
+        optimize_op_const(size,op,a);
+        case op of
+          OP_NONE:
+            exit;
+          OP_MOVE:
+            a_load_const_reg(list,size,a,reg);
+          OP_NEG,OP_NOT:
+            internalerror(200306011);
+          else
+            a_op_const_reg_reg(list,op,size,a,reg,reg);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_op_reg_reg(list:TAsmList;op:topcg;size:tcgsize;src,dst:tregister);
+      begin
+        Case op of
+          OP_NEG,
+          OP_NOT:
+            begin
+              list.concat(taicpu.op_reg_reg(TOpCG2AsmOpReg[op],dst,src));
+              maybeadjustresult(list,op,size,dst);
+            end
+          else
+            a_op_reg_reg_reg(list,op,size,src,dst,dst);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_op_const_reg_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister);
+      var
+        l: tlocation;
+      begin
+        a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,l);
+      end;
+
+
+    procedure tcgaarch64.a_op_reg_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister);
+      var
+        hreg: tregister;
+      begin
+        { no ROLV opcode... }
+        if op=OP_ROL then
+          begin
+            case size of
+              OS_32,OS_S32,
+              OS_64,OS_S64:
+                begin
+                  hreg:=getintregister(list,size);
+                  a_load_const_reg(list,size,tcgsize2size[size]*8,hreg);
+                  a_op_reg_reg(list,OP_SUB,size,src1,hreg);
+                  a_op_reg_reg_reg(list,OP_ROR,size,hreg,src2,dst);
+                  exit;
+                end;
+              else
+                internalerror(2014111005);
+            end;
+          end
+        else if (op=OP_ROR) and
+           not(size in [OS_32,OS_S32,OS_64,OS_S64]) then
+          internalerror(2014111006);
+        if TOpCG2AsmOpReg[op]=A_NONE then
+          internalerror(2014111007);
+        list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOpReg[op],dst,src2,src1));
+        maybeadjustresult(list,op,size,dst);
+      end;
+
+
+    procedure tcgaarch64.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister; setflags : boolean; var ovloc : tlocation);
+      var
+        shiftcountmask: longint;
+        constreg: tregister;
+      begin
+        { add/sub instructions have only positive immediate operands }
+        if (op in [OP_ADD,OP_SUB]) and
+           (a<0) then
+          begin
+            if op=OP_ADD then
+              op:=op_SUB
+            else
+              op:=OP_ADD;
+            { avoid range/overflow error in case a = low(tcgint) }
+{$push}{$r-}{$q-}
+            a:=-a;
+{$pop}
+          end;
+        ovloc.loc:=LOC_VOID;
+        optimize_op_const(size,op,a);
+        case op of
+          OP_NONE:
+            begin
+              a_load_reg_reg(list,size,size,src,dst);
+              exit;
+            end;
+          OP_MOVE:
+            begin
+              a_load_const_reg(list,size,a,dst);
+              exit;
+            end;
+        end;
+        case op of
+          OP_ADD,
+          OP_SUB:
+            begin
+              handle_reg_imm12_reg(list,TOpCG2AsmOpImm[op],size,src,a,dst,NR_NO,setflags,true);
+              { on a 64 bit target, overflows with smaller data types
+                are handled via range errors }
+              if setflags and
+                 (size in [OS_64,OS_S64]) then
+                begin
+                  location_reset(ovloc,LOC_FLAGS,OS_8);
+                  if size=OS_64 then
+                    if op=OP_ADD then
+                      ovloc.resflags:=F_CS
+                    else
+                      ovloc.resflags:=F_CC
+                  else
+                    ovloc.resflags:=F_VS;
+                end;
+            end;
+          OP_OR,
+          OP_AND,
+          OP_XOR:
+            begin
+              if not(size in [OS_64,OS_S64]) then
+                a:=cardinal(a);
+              if is_shifter_const(a,size) then
+                list.concat(taicpu.op_reg_reg_const(TOpCG2AsmOpReg[op],dst,src,a))
+              else
+                begin
+                  constreg:=getintregister(list,size);
+                  a_load_const_reg(list,size,a,constreg);
+                  a_op_reg_reg_reg(list,op,size,constreg,src,dst);
+                end;
+            end;
+          OP_SHL,
+          OP_SHR,
+          OP_SAR:
+            begin
+              if size in [OS_64,OS_S64] then
+                shiftcountmask:=63
+              else
+                shiftcountmask:=31;
+              if (a and shiftcountmask)<>0 Then
+                list.concat(taicpu.op_reg_reg_const(
+                  TOpCG2AsmOpImm[Op],dst,src,a and shiftcountmask))
+              else
+                a_load_reg_reg(list,size,size,src,dst);
+              if (a and not(tcgint(shiftcountmask)))<>0 then
+                internalError(2014112101);
+            end;
+          OP_ROL,
+          OP_ROR:
+            begin
+              case size of
+                OS_32,OS_S32:
+                  if (a and not(tcgint(31)))<>0 then
+                    internalError(2014112102);
+                OS_64,OS_S64:
+                  if (a and not(tcgint(63)))<>0 then
+                    internalError(2014112103);
+                else
+                  internalError(2014112104);
+              end;
+              { there's only a ror opcode }
+              if op=OP_ROL then
+                a:=(tcgsize2size[size]*8)-a;
+              list.concat(taicpu.op_reg_reg_const(A_ROR,dst,src,a));
+            end;
+          OP_MUL,
+          OP_IMUL,
+          OP_DIV,
+          OP_IDIV:
+            begin
+              constreg:=getintregister(list,size);
+              a_load_const_reg(list,size,a,constreg);
+              a_op_reg_reg_reg_checkoverflow(list,op,size,constreg,src,dst,setflags,ovloc);
+            end;
+          else
+            internalerror(2014111403);
+        end;
+        maybeadjustresult(list,op,size,dst);
+      end;
+
+
+    procedure tcgaarch64.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister; setflags : boolean; var ovloc : tlocation);
+      var
+        tmpreg1, tmpreg2: tregister;
+      begin
+        ovloc.loc:=LOC_VOID;
+        { overflow can only occur with 64 bit calculations on 64 bit cpus }
+        if setflags and
+           (size in [OS_64,OS_S64]) then
+          begin
+            case op of
+              OP_ADD,
+              OP_SUB:
+                begin
+                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(TOpCG2AsmOpReg[op],dst,src2,src1),PF_S));
+                  ovloc.loc:=LOC_FLAGS;
+                  if size=OS_64 then
+                    if op=OP_ADD then
+                      ovloc.resflags:=F_CS
+                    else
+                      ovloc.resflags:=F_CC
+                  else
+                    ovloc.resflags:=F_VS;
+                  { finished }
+                  exit;
+                end;
+              OP_MUL:
+                begin
+                  { check whether the upper 64 bit of the 128 bit product is 0 }
+                  tmpreg1:=getintregister(list,OS_64);
+                  list.concat(taicpu.op_reg_reg_reg(A_UMULH,tmpreg1,src2,src1));
+                  list.concat(taicpu.op_reg_const(A_CMP,tmpreg1,0));
+                  ovloc.loc:=LOC_FLAGS;
+                  ovloc.resflags:=F_NE;
+                  { still have to perform the actual multiplication  }
+                end;
+              OP_IMUL:
+                begin
+                  { check whether the upper 64 bits of the 128 bit multiplication
+                    result have the same value as the replicated sign bit of the
+                    lower 64 bits }
+                  tmpreg1:=getintregister(list,OS_64);
+                  list.concat(taicpu.op_reg_reg_reg(A_SMULH,tmpreg1,src2,src1));
+                  { calculate lower 64 bits (afterwards, because dst may be
+                    equal to src1 or src2) }
+                  a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+                  { replicate sign bit }
+                  tmpreg2:=getintregister(list,OS_64);
+                  a_op_const_reg_reg(list,OP_SAR,OS_S64,63,dst,tmpreg2);
+                  list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
+                  ovloc.loc:=LOC_FLAGS;
+                  ovloc.resflags:=F_NE;
+                  { finished }
+                  exit;
+                end;
+              OP_IDIV,
+              OP_DIV:
+                begin
+                  { not handled here, needs div-by-zero check (dividing by zero
+                    just gives a 0 result on aarch64), and low(int64) div -1
+                    check for overflow) }
+                  internalerror(2014122101);
+                end;
+            end;
+          end;
+        a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+      end;
+
+
+
+  {*************** compare instructructions ****************}
+
+    procedure tcgaarch64.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
+      var
+        op: tasmop;
+      begin
+        if a>=0 then
+          op:=A_CMP
+        else
+          op:=A_CMN;
+        { avoid range/overflow error in case a=low(tcgint) }
+{$push}{$r-}{$q-}
+        handle_reg_imm12_reg(list,op,size,reg,abs(a),NR_XZR,NR_NO,false,false);
+{$pop}
+        a_jmp_cond(list,cmp_op,l);
+      end;
+
+
+    procedure tcgaarch64.a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1,reg2: tregister; l: tasmlabel);
+      begin
+        list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
+        a_jmp_cond(list,cmp_op,l);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_always(list: TAsmList; l: TAsmLabel);
+      var
+        ai: taicpu;
+      begin
+        ai:=TAiCpu.op_sym(A_B,current_asmdata.RefAsmSymbol(l.name));
+        ai.is_jmp:=true;
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_name(list: TAsmList; const s: string);
+      var
+        ai: taicpu;
+      begin
+        ai:=TAiCpu.op_sym(A_B,current_asmdata.RefAsmSymbol(s));
+        ai.is_jmp:=true;
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_cond(list: TAsmList; cond: TOpCmp; l: TAsmLabel);
+      var
+        ai: taicpu;
+      begin
+        ai:=TAiCpu.op_sym(A_B,l);
+        ai.is_jmp:=true;
+        ai.SetCondition(TOpCmp2AsmCond[cond]);
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_flags(list: TAsmList; const f: tresflags; l: tasmlabel);
+      var
+        ai : taicpu;
+      begin
+        ai:=Taicpu.op_sym(A_B,l);
+        ai.is_jmp:=true;
+        ai.SetCondition(flags_to_cond(f));
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.g_flags2reg(list: TAsmList; size: tcgsize; const f: tresflags; reg: tregister);
+      begin
+        list.concat(taicpu.op_reg_cond(A_CSET,reg,flags_to_cond(f)));
+      end;
+
+
+    procedure tcgaarch64.g_overflowcheck(list: TAsmList; const loc: tlocation; def: tdef);
+      begin
+        { we need an explicit overflow location, because there are many
+          possibilities (not just the overflow flag, which is only used for
+          signed add/sub) }
+        internalerror(2014112303);
+      end;
+
+
+    procedure tcgaarch64.g_overflowcheck_loc(list: TAsmList; const loc: tlocation; def: tdef; ovloc : tlocation);
+      var
+        hl : tasmlabel;
+        hflags : tresflags;
+      begin
+        if not(cs_check_overflow in current_settings.localswitches) then
+          exit;
+        current_asmdata.getjumplabel(hl);
+        case ovloc.loc of
+          LOC_FLAGS:
+            begin
+              hflags:=ovloc.resflags;
+              inverse_flags(hflags);
+              cg.a_jmp_flags(list,hflags,hl);
+            end;
+          else
+            internalerror(2014112304);
+        end;
+        a_call_name(list,'FPC_OVERFLOW',false);
+        a_label(list,hl);
+      end;
+
+  { *********** entry/exit code and address loading ************ }
+
+    function tcgaarch64.save_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister): longint;
+      var
+        ref: treference;
+        sr: tsuperregister;
+        pairreg: tregister;
+      begin
+        result:=0;
+        reference_reset_base(ref,NR_SP,-16,16);
+        ref.addressmode:=AM_PREINDEXED;
+        pairreg:=NR_NO;
+        { store all used registers pairwise }
+        for sr:=lowsr to highsr do
+          if sr in rg[rt].used_in_proc then
+            if pairreg=NR_NO then
+              pairreg:=newreg(rt,sr,sub)
+            else
+              begin
+                inc(result,16);
+                list.concat(taicpu.op_reg_reg_ref(A_STP,pairreg,newreg(rt,sr,sub),ref));
+                pairreg:=NR_NO
+              end;
+        { one left -> store twice (stack must be 16 bytes aligned) }
+        if pairreg<>NR_NO then
+          begin
+            list.concat(taicpu.op_reg_reg_ref(A_STP,pairreg,pairreg,ref));
+            inc(result,16);
+          end;
+      end;
+
+
+    procedure FixupOffsets(p:TObject;arg:pointer);
+      var
+        sym: tabstractnormalvarsym absolute p;
+      begin
+        if (tsym(p).typ in [paravarsym,localvarsym]) and
+          (sym.localloc.loc=LOC_REFERENCE) and
+          (sym.localloc.reference.base=NR_STACK_POINTER_REG) then
+          begin
+            sym.localloc.reference.base:=NR_FRAME_POINTER_REG;
+            dec(sym.localloc.reference.offset,PLongint(arg)^);
+          end;
+      end;
+
+
+    procedure tcgaarch64.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
+      var
+        ref: treference;
+        totalstackframesize: longint;
+      begin
+        if nostackframe then
+          exit;
+        { stack pointer has to be aligned to 16 bytes at all times }
+        localsize:=align(localsize,16);
+
+        { save stack pointer and return address }
+        reference_reset_base(ref,NR_SP,-16,16);
+        ref.addressmode:=AM_PREINDEXED;
+        list.concat(taicpu.op_reg_reg_ref(A_STP,NR_FP,NR_LR,ref));
+        { initialise frame pointer }
+        a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_SP,NR_FP);
+
+        totalstackframesize:=localsize;
+        { save modified integer registers }
+        inc(totalstackframesize,
+          save_regs(list,R_INTREGISTER,RS_X19,RS_X28,R_SUBWHOLE));
+        { only the lower 64 bits of the modified vector registers need to be
+          saved; if the caller needs the upper 64 bits, it has to save them
+          itself }
+        inc(totalstackframesize,
+          save_regs(list,R_MMREGISTER,RS_D8,RS_D15,R_SUBMMD));
+
+        { allocate stack space }
+        if localsize<>0 then
+          begin
+            localsize:=align(localsize,16);
+            current_procinfo.final_localsize:=localsize;
+            handle_reg_imm12_reg(list,A_SUB,OS_ADDR,NR_SP,localsize,NR_SP,NR_IP0,false,true);
+          end;
+        { By default, we use the frame pointer to access parameters passed via
+          the stack and the stack pointer to address local variables and temps
+          because
+           a) we can use bigger positive than negative offsets (so accessing
+              locals via negative offsets from the frame pointer would be less
+              efficient)
+           b) we don't know the local size while generating the code, so
+              accessing the parameters via the stack pointer is not possible
+              without copying them
+          The problem with this is the get_frame() intrinsic:
+           a) it must return the same value as what we pass as parentfp
+              parameter, since that's how it's used in the TP-style objects unit
+           b) its return value must usable to access all local data from a
+              routine (locals and parameters), since it's all the nested
+              routines have access to
+           c) its return value must be usable to construct a backtrace, as it's
+              also used by the exception handling routines
+
+          The solution we use here, based on something similar that's done in
+          the MIPS port, is to generate all accesses to locals in the routine
+          itself SP-relative, and then after the code is generated and the local
+          size is known (namely, here), we change all SP-relative variables/
+          parameters into FP-relative ones. This means that they'll be accessed
+          less efficiently from nested routines, but those accesses are indirect
+          anyway and at least this way they can be accessed at all
+        }
+        if current_procinfo.has_nestedprocs then
+          begin
+            current_procinfo.procdef.localst.SymList.ForEachCall(@FixupOffsets,@totalstackframesize);
+            current_procinfo.procdef.parast.SymList.ForEachCall(@FixupOffsets,@totalstackframesize);
+          end;
+      end;
+
+
+    procedure tcgaarch64.g_maybe_got_init(list : TAsmList);
+      begin
+        { nothing to do on Darwin or Linux }
+      end;
+
+
+    procedure tcgaarch64.g_restore_registers(list:TAsmList);
+      begin
+        { done in g_proc_exit }
+      end;
+
+
+    procedure tcgaarch64.load_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister);
+      var
+        ref: treference;
+        sr, highestsetsr: tsuperregister;
+        pairreg: tregister;
+        regcount: longint;
+      begin
+        reference_reset_base(ref,NR_SP,16,16);
+        ref.addressmode:=AM_POSTINDEXED;
+        { highest reg stored twice? }
+        regcount:=0;
+        highestsetsr:=RS_NO;
+        for sr:=lowsr to highsr do
+          if sr in rg[rt].used_in_proc then
+            begin
+              inc(regcount);
+              highestsetsr:=sr;
+            end;
+        if odd(regcount) then
+          begin
+            list.concat(taicpu.op_reg_ref(A_LDR,newreg(rt,highestsetsr,sub),ref));
+            highestsetsr:=pred(highestsetsr);
+          end;
+        { load all (other) used registers pairwise }
+        pairreg:=NR_NO;
+        for sr:=highestsetsr downto lowsr do
+          if sr in rg[rt].used_in_proc then
+            if pairreg=NR_NO then
+              pairreg:=newreg(rt,sr,sub)
+            else
+              begin
+                list.concat(taicpu.op_reg_reg_ref(A_LDP,newreg(rt,sr,sub),pairreg,ref));
+                pairreg:=NR_NO
+              end;
+        { There can't be any register left }
+        if pairreg<>NR_NO then
+          internalerror(2014112602);
+      end;
+
+
+
+    procedure tcgaarch64.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
+      var
+        ref: treference;
+        regsstored: boolean;
+        sr: tsuperregister;
+      begin
+        if not nostackframe then
+          begin
+            { if no registers have been stored, we don't have to subtract the
+              allocated temp space from the stack pointer }
+            regsstored:=false;
+            for sr:=RS_X19 to RS_X28 do
+              if sr in rg[R_INTREGISTER].used_in_proc then
+                begin
+                  regsstored:=true;
+                  break;
+                end;
+            if not regsstored then
+              for sr:=RS_D8 to RS_D15 do
+                if sr in rg[R_MMREGISTER].used_in_proc then
+                  begin
+                    regsstored:=true;
+                    break;
+                  end;
+            { restore registers (and stack pointer) }
+            if regsstored then
+              begin
+                if current_procinfo.final_localsize<>0 then
+                  handle_reg_imm12_reg(list,A_ADD,OS_ADDR,NR_SP,current_procinfo.final_localsize,NR_SP,NR_IP0,false,true);
+                load_regs(list,R_MMREGISTER,RS_D8,RS_D15,R_SUBMMD);
+                load_regs(list,R_INTREGISTER,RS_X19,RS_X28,R_SUBWHOLE);
+              end
+            else if current_procinfo.final_localsize<>0 then
+              { restore stack pointer }
+              a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_FP,NR_SP);
+
+            { restore framepointer and return address }
+            reference_reset_base(ref,NR_SP,16,16);
+            ref.addressmode:=AM_POSTINDEXED;
+            list.concat(taicpu.op_reg_reg_ref(A_LDP,NR_FP,NR_LR,ref));
+          end;
+
+        { return }
+        list.concat(taicpu.op_none(A_RET));
+      end;
+
+
+    procedure tcgaarch64.g_save_registers(list : TAsmList);
+      begin
+        { done in g_proc_entry }
+      end;
+
+
+    { ************* concatcopy ************ }
+
+    procedure tcgaarch64.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+      var
+        paraloc1,paraloc2,paraloc3 : TCGPara;
+        pd : tprocdef;
+      begin
+        pd:=search_system_proc('MOVE');
+        paraloc1.init;
+        paraloc2.init;
+        paraloc3.init;
+        paramanager.getintparaloc(list,pd,1,paraloc1);
+        paramanager.getintparaloc(list,pd,2,paraloc2);
+        paramanager.getintparaloc(list,pd,3,paraloc3);
+        a_load_const_cgpara(list,OS_SINT,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_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+        a_call_name(list,'FPC_MOVE',false);
+        dealloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+        dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        paraloc3.done;
+        paraloc2.done;
+        paraloc1.done;
+      end;
+
+
+    procedure tcgaarch64.g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);
+
+      var
+        sourcebasereplaced, destbasereplaced: boolean;
+
+      { get optimal memory operation to use for loading/storing data
+        in an unrolled loop }
+      procedure getmemop(scaledop, unscaledop: tasmop; const startref, endref: treference; opsize: tcgsize; postfix: toppostfix; out memop: tasmop; out needsimplify: boolean);
+        begin
+          if (simple_ref_type(scaledop,opsize,postfix,startref)=sr_simple) and
+             (simple_ref_type(scaledop,opsize,postfix,endref)=sr_simple) then
+            begin
+              memop:=unscaledop;
+              needsimplify:=true;
+            end
+          else if (unscaledop<>A_NONE) and
+             (simple_ref_type(unscaledop,opsize,postfix,startref)=sr_simple) and
+             (simple_ref_type(unscaledop,opsize,postfix,endref)=sr_simple) then
+            begin
+              memop:=unscaledop;
+              needsimplify:=false;
+            end
+          else
+            begin
+              memop:=scaledop;
+              needsimplify:=true;
+            end;
+        end;
+
+      { adjust the offset and/or addressing mode after a load/store so it's
+        correct for the next one of the same size }
+      procedure updaterefafterloadstore(var ref: treference; oplen: longint);
+        begin
+          case ref.addressmode of
+            AM_OFFSET:
+              inc(ref.offset,oplen);
+            AM_POSTINDEXED:
+              { base register updated by instruction, next offset can remain
+                the same }
+              ;
+            AM_PREINDEXED:
+              begin
+                { base register updated by instruction -> next instruction can
+                  use post-indexing with offset = sizeof(operation) }
+                ref.offset:=0;
+                ref.addressmode:=AM_OFFSET;
+              end;
+          end;
+        end;
+
+      { generate a load/store and adjust the reference offset to the next
+        memory location if necessary }
+      procedure genloadstore(list: TAsmList; op: tasmop; reg: tregister; var ref: treference; postfix: toppostfix; opsize: tcgsize);
+        begin
+          list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),postfix));
+          updaterefafterloadstore(ref,tcgsize2size[opsize]);
+        end;
+
+      { generate a dual load/store (ldp/stp) and adjust the reference offset to
+        the next memory location if necessary }
+      procedure gendualloadstore(list: TAsmList; op: tasmop; reg1, reg2: tregister; var ref: treference; postfix: toppostfix; opsize: tcgsize);
+        begin
+          list.concat(setoppostfix(taicpu.op_reg_reg_ref(op,reg1,reg2,ref),postfix));
+          updaterefafterloadstore(ref,tcgsize2size[opsize]*2);
+        end;
+
+      { turn a reference into a pre- or post-indexed reference for use in a
+        load/store of a particular size }
+      procedure makesimpleforcopy(list: TAsmList; var scaledop: tasmop; opsize: tcgsize; postfix: toppostfix; forcepostindexing: boolean; var ref: treference; var basereplaced: boolean);
+        var
+          tmpreg: tregister;
+          scaledoffset: longint;
+          orgaddressmode: taddressmode;
+        begin
+          scaledoffset:=tcgsize2size[opsize];
+          if scaledop in [A_LDP,A_STP] then
+            scaledoffset:=scaledoffset*2;
+          { can we use the reference as post-indexed without changes? }
+          if forcepostindexing then
+            begin
+              orgaddressmode:=ref.addressmode;
+              ref.addressmode:=AM_POSTINDEXED;
+              if (orgaddressmode=AM_POSTINDEXED) or
+                 ((ref.offset=0) and
+                  (simple_ref_type(scaledop,opsize,postfix,ref)=sr_simple)) then
+                begin
+                  { just change the post-indexed offset to the access size }
+                  ref.offset:=scaledoffset;
+                  { and replace the base register if that didn't happen yet
+                    (could be sp or a regvar) }
+                  if not basereplaced then
+                    begin
+                      tmpreg:=getaddressregister(list);
+                      a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg);
+                      ref.base:=tmpreg;
+                      basereplaced:=true;
+                    end;
+                  exit;
+                end;
+              ref.addressmode:=orgaddressmode;
+            end;
+{$ifdef dummy}
+          This could in theory be useful in case you have a concatcopy from
+          e.g. x1+255 to x1+267 *and* the reference is aligned, but this seems
+          very unlikely. Disabled because it still needs fixes, as it
+          also generates pre-indexed loads right now at the very end for the
+          left-over gencopies
+
+          { can we turn it into a pre-indexed reference for free? (after the
+            first operation, it will be turned into an offset one) }
+          if not forcepostindexing and
+             (ref.offset<>0) then
+            begin
+              orgaddressmode:=ref.addressmode;
+              ref.addressmode:=AM_PREINDEXED;
+              tmpreg:=ref.base;
+              if not basereplaced and
+                 (ref.base=tmpreg) then
+                begin
+                  tmpreg:=getaddressregister(list);
+                  a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg);
+                  ref.base:=tmpreg;
+                  basereplaced:=true;
+                end;
+              if simple_ref_type(scaledop,opsize,postfix,ref)<>sr_simple then
+                make_simple_ref(list,scaledop,opsize,postfix,ref,NR_NO);
+              exit;
+            end;
+{$endif dummy}
+          if not forcepostindexing then
+            begin
+              ref.addressmode:=AM_OFFSET;
+              make_simple_ref(list,scaledop,opsize,postfix,ref,NR_NO);
+              { this may still cause problems if the final offset is no longer
+                a simple ref; it's a bit complicated to pass all information
+                through at all places and check that here, so play safe: we
+                currently never generate unrolled copies for more than 64
+                bytes (32 with non-double-register copies) }
+              if ref.index=NR_NO then
+                begin
+                  if ((scaledop in [A_LDP,A_STP]) and
+                      (ref.offset<((64-8)*tcgsize2size[opsize]))) or
+                     ((scaledop in [A_LDUR,A_STUR]) and
+                      (ref.offset<(255-8*tcgsize2size[opsize]))) or
+                     ((scaledop in [A_LDR,A_STR]) and
+                      (ref.offset<((4096-8)*tcgsize2size[opsize]))) then
+                    exit;
+                end;
+            end;
+          tmpreg:=getaddressregister(list);
+          a_loadaddr_ref_reg(list,ref,tmpreg);
+          basereplaced:=true;
+          if forcepostindexing then
+            begin
+              reference_reset_base(ref,tmpreg,scaledoffset,ref.alignment);
+              ref.addressmode:=AM_POSTINDEXED;
+            end
+          else
+            begin
+              reference_reset_base(ref,tmpreg,0,ref.alignment);
+              ref.addressmode:=AM_OFFSET;
+            end
+        end;
+
+      { prepare a reference for use by gencopy. This is done both after the
+        unrolled and regular copy loop -> get rid of post-indexing mode, make
+        sure ref is valid }
+      procedure preparecopy(list: tasmlist; scaledop, unscaledop: tasmop; var ref: treference; opsize: tcgsize; postfix: toppostfix; out op: tasmop; var basereplaced: boolean);
+        var
+          simplify: boolean;
+        begin
+          if ref.addressmode=AM_POSTINDEXED then
+            ref.offset:=tcgsize2size[opsize];
+          getmemop(scaledop,scaledop,ref,ref,opsize,postfix,op,simplify);
+          if simplify then
+            begin
+              makesimpleforcopy(list,scaledop,opsize,postfix,false,ref,basereplaced);
+              op:=scaledop;
+            end;
+        end;
+
+      { generate a copy from source to dest of size opsize/postfix }
+      procedure gencopy(list: TAsmList; var source, dest: treference; postfix: toppostfix; opsize: tcgsize);
+        var
+          reg: tregister;
+          loadop, storeop: tasmop;
+        begin
+          preparecopy(list,A_LDR,A_LDUR,source,opsize,postfix,loadop,sourcebasereplaced);
+          preparecopy(list,A_STR,A_STUR,dest,opsize,postfix,storeop,destbasereplaced);
+          reg:=getintregister(list,opsize);
+          genloadstore(list,loadop,reg,source,postfix,opsize);
+          genloadstore(list,storeop,reg,dest,postfix,opsize);
+        end;
+
+
+      { copy the leftovers after an unrolled or regular copy loop }
+      procedure gencopyleftovers(list: TAsmList; var source, dest: treference; len: longint);
+        begin
+          { stop post-indexing if we did so in the loop, since in that case all
+            offsets definitely can be represented now }
+          if source.addressmode=AM_POSTINDEXED then
+            begin
+              source.addressmode:=AM_OFFSET;
+              source.offset:=0;
+            end;
+          if dest.addressmode=AM_POSTINDEXED then
+            begin
+              dest.addressmode:=AM_OFFSET;
+              dest.offset:=0;
+            end;
+          { transfer the leftovers }
+          if len>=8 then
+            begin
+              dec(len,8);
+              gencopy(list,source,dest,PF_NONE,OS_64);
+            end;
+          if len>=4 then
+            begin
+              dec(len,4);
+              gencopy(list,source,dest,PF_NONE,OS_32);
+            end;
+          if len>=2 then
+            begin
+              dec(len,2);
+              gencopy(list,source,dest,PF_H,OS_16);
+            end;
+          if len>=1 then
+            begin
+              dec(len);
+              gencopy(list,source,dest,PF_B,OS_8);
+            end;
+        end;
+
+
+      const
+        { load_length + loop dec + cbnz }
+        loopoverhead=12;
+        { loop overhead + load + store }
+        totallooplen=loopoverhead + 8;
+      var
+        totalalign: longint;
+        maxlenunrolled: tcgint;
+        loadop, storeop: tasmop;
+        opsize: tcgsize;
+        postfix: toppostfix;
+        tmpsource, tmpdest: treference;
+        scaledstoreop, unscaledstoreop,
+        scaledloadop, unscaledloadop: tasmop;
+        regs: array[1..8] of tregister;
+        countreg: tregister;
+        i, regcount: longint;
+        hl: tasmlabel;
+        simplifysource, simplifydest: boolean;
+      begin
+        if len=0 then
+          exit;
+        sourcebasereplaced:=false;
+        destbasereplaced:=false;
+        { maximum common alignment }
+        totalalign:=max(1,newalignment(source.alignment,dest.alignment));
+        { use a simple load/store? }
+        if (len in [1,2,4,8]) and
+           ((totalalign>=(len div 2)) or
+            (source.alignment=len) or
+            (dest.alignment=len)) then
+          begin
+            opsize:=int_cgsize(len);
+            a_load_ref_ref(list,opsize,opsize,source,dest);
+            exit;
+          end;
+
+        { alignment > length is not useful, and would break some checks below }
+        while totalalign>len do
+          totalalign:=totalalign div 2;
+
+        { operation sizes to use based on common alignment }
+        case totalalign of
+          1:
+            begin
+              postfix:=PF_B;
+              opsize:=OS_8;
+            end;
+          2:
+            begin
+              postfix:=PF_H;
+              opsize:=OS_16;
+            end;
+          4:
+            begin
+              postfix:=PF_None;
+              opsize:=OS_32;
+            end
+          else
+            begin
+              totalalign:=8;
+              postfix:=PF_None;
+              opsize:=OS_64;
+            end;
+        end;
+        { maximum length to handled with an unrolled loop (4 loads + 4 stores) }
+        maxlenunrolled:=min(totalalign,8)*4;
+        { ldp/stp -> 2 registers per instruction }
+        if (totalalign>=4) and
+           (len>=totalalign*2) then
+          begin
+            maxlenunrolled:=maxlenunrolled*2;
+            scaledstoreop:=A_STP;
+            scaledloadop:=A_LDP;
+            unscaledstoreop:=A_NONE;
+            unscaledloadop:=A_NONE;
+          end
+        else
+          begin
+            scaledstoreop:=A_STR;
+            scaledloadop:=A_LDR;
+            unscaledstoreop:=A_STUR;
+            unscaledloadop:=A_LDUR;
+          end;
+        { we only need 4 instructions extra to call FPC_MOVE }
+        if cs_opt_size in current_settings.optimizerswitches then
+          maxlenunrolled:=maxlenunrolled div 2;
+        if (len>maxlenunrolled) and
+           (len>totalalign*8) then
+          begin
+            g_concatcopy_move(list,source,dest,len);
+            exit;
+          end;
+
+        simplifysource:=true;
+        simplifydest:=true;
+        tmpsource:=source;
+        tmpdest:=dest;
+        { can we directly encode all offsets in an unrolled loop? }
+        if len<=maxlenunrolled then
+          begin
+{$ifdef extdebug}
+            list.concat(tai_comment.Create(strpnew('concatcopy unrolled loop; len/opsize/align: '+tostr(len)+'/'+tostr(tcgsize2size[opsize])+'/'+tostr(totalalign))));
+{$endif extdebug}
+            { the leftovers will be handled separately -> -(len mod opsize) }
+            inc(tmpsource.offset,len-(len mod tcgsize2size[opsize]));
+            { additionally, the last regular load/store will be at
+              offset+len-opsize (if len-(len mod opsize)>len) }
+            if tmpsource.offset>source.offset then
+              dec(tmpsource.offset,tcgsize2size[opsize]);
+            getmemop(scaledloadop,unscaledloadop,source,tmpsource,opsize,postfix,loadop,simplifysource);
+            inc(tmpdest.offset,len-(len mod tcgsize2size[opsize]));
+            if tmpdest.offset>dest.offset then
+              dec(tmpdest.offset,tcgsize2size[opsize]);
+            getmemop(scaledstoreop,unscaledstoreop,dest,tmpdest,opsize,postfix,storeop,simplifydest);
+            tmpsource:=source;
+            tmpdest:=dest;
+            { if we can't directly encode all offsets, simplify }
+            if simplifysource then
+              begin
+                loadop:=scaledloadop;
+                makesimpleforcopy(list,loadop,opsize,postfix,false,tmpsource,sourcebasereplaced);
+              end;
+            if simplifydest then
+              begin
+                storeop:=scaledstoreop;
+                makesimpleforcopy(list,storeop,opsize,postfix,false,tmpdest,destbasereplaced);
+              end;
+            regcount:=len div tcgsize2size[opsize];
+            { in case we transfer two registers at a time, we copy an even
+              number of registers }
+            if loadop=A_LDP then
+              regcount:=regcount and not(1);
+            { initialise for dfa }
+            regs[low(regs)]:=NR_NO;
+            { max 4 loads/stores -> max 8 registers (in case of ldp/stdp) }
+            for i:=1 to regcount do
+              regs[i]:=getintregister(list,opsize);
+            if loadop=A_LDP then
+              begin
+                { load registers }
+                for i:=1 to (regcount div 2) do
+                  gendualloadstore(list,loadop,regs[i*2-1],regs[i*2],tmpsource,postfix,opsize);
+                { store registers }
+                for i:=1 to (regcount div 2) do
+                  gendualloadstore(list,storeop,regs[i*2-1],regs[i*2],tmpdest,postfix,opsize);
+              end
+            else
+              begin
+                for i:=1 to regcount do
+                  genloadstore(list,loadop,regs[i],tmpsource,postfix,opsize);
+                for i:=1 to regcount do
+                  genloadstore(list,storeop,regs[i],tmpdest,postfix,opsize);
+              end;
+            { leftover }
+            len:=len-regcount*tcgsize2size[opsize];
+{$ifdef extdebug}
+            list.concat(tai_comment.Create(strpnew('concatcopy unrolled loop leftover: '+tostr(len))));
+{$endif extdebug}
+          end
+        else
+          begin
+{$ifdef extdebug}
+            list.concat(tai_comment.Create(strpnew('concatcopy regular loop; len/align: '+tostr(len)+'/'+tostr(totalalign))));
+{$endif extdebug}
+            { regular loop -> definitely use post-indexing }
+            loadop:=scaledloadop;
+            makesimpleforcopy(list,loadop,opsize,postfix,true,tmpsource,sourcebasereplaced);
+            storeop:=scaledstoreop;
+            makesimpleforcopy(list,storeop,opsize,postfix,true,tmpdest,destbasereplaced);
+            current_asmdata.getjumplabel(hl);
+            countreg:=getintregister(list,OS_32);
+            if loadop=A_LDP then
+              a_load_const_reg(list,OS_32,len div tcgsize2size[opsize]*2,countreg)
+            else
+              a_load_const_reg(list,OS_32,len div tcgsize2size[opsize],countreg);
+            a_label(list,hl);
+            a_op_const_reg(list,OP_SUB,OS_32,1,countreg);
+            if loadop=A_LDP then
+              begin
+                regs[1]:=getintregister(list,opsize);
+                regs[2]:=getintregister(list,opsize);
+                gendualloadstore(list,loadop,regs[1],regs[2],tmpsource,postfix,opsize);
+                gendualloadstore(list,storeop,regs[1],regs[2],tmpdest,postfix,opsize);
+              end
+            else
+              begin
+                regs[1]:=getintregister(list,opsize);
+                genloadstore(list,loadop,regs[1],tmpsource,postfix,opsize);
+                genloadstore(list,storeop,regs[1],tmpdest,postfix,opsize);
+              end;
+            list.concat(taicpu.op_reg_sym_ofs(A_CBNZ,countreg,hl,0));
+            len:=len mod tcgsize2size[opsize];
+          end;
+        gencopyleftovers(list,tmpsource,tmpdest,len);
+      end;
+
+
+    procedure tcgaarch64.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
+      begin
+        { This method is integrated into g_intf_wrapper and shouldn't be called separately }
+        InternalError(2013020102);
+      end;
+
+
+
+    procedure create_codegen;
+      begin
+        cg:=tcgaarch64.Create;
+        cg128:=tcg128.Create;
+      end;
+
+end.

+ 200 - 38
compiler/aarch64/cpubase.pas

@@ -1,7 +1,8 @@
 {
     Copyright (c) 1998-2012 by Florian Klaempfl and Peter Vreman
+    Copyright (c) 2014 by Jonas Maebe and Florian Klaempfl
 
-    Contains the base types for ARM64
+    Contains the base types for Aarch64
 
     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
@@ -68,14 +69,22 @@ unit cpubase;
       { Available Superregisters }
       {$i ra64sup.inc}
 
+      RS_IP0 = RS_X16;
+      RS_IP1 = RS_X17;
+
       R_SUBWHOLE = R_SUBQ;
 
       { Available Registers }
       {$i ra64con.inc}
 
+      NR_IP0 = NR_X16;
+      NR_IP1 = NR_X17;
+
       { Integer Super registers first and last }
       first_int_supreg = RS_X0;
-      first_int_imreg = $20;
+      { xzr and sp take up a separate super register because some instructions
+        are ambiguous otherwise }
+      first_int_imreg = $21;
 
       { Integer Super registers first and last }
       first_fpu_supreg = RS_S0;
@@ -92,7 +101,7 @@ unit cpubase;
         The value of this constant is equal to the constant
         PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
       }
-      std_param_align = 4;
+      std_param_align = 8;
 
       { TODO: Calculate bsstart}
       regnumber_count_bsstart = 128;
@@ -109,7 +118,7 @@ unit cpubase;
         {$i ra64dwa.inc}
       );
       { registers which may be destroyed by calls }
-      VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X29..RS_X30];
+      VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X30];
       VOLATILE_MMREGISTERS =  [RS_D0..RS_D7,RS_D16..RS_D31];
 
     type
@@ -126,16 +135,23 @@ unit cpubase;
       TOpPostfix = (PF_None,
         { update condition flags }
         PF_S,
-        { load/store }
-        PF_B,PF_SB,PF_H,PF_SH
+        { load/store sizes }
+        PF_B,PF_SB,PF_H,PF_SH,PF_W,PF_SW
       );
 
       TOpPostfixes = set of TOpPostfix;
 
     const
-      oppostfix2str : array[TOpPostfix] of string[2] = ('',
+      tcgsizep2size: array[OS_NO..OS_F128] of byte =
+        {OS_NO }
+        (0,
+        {OS_8,OS_16,OS_32,OS_64,OS_128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128}
+            0,    1,    2,    3,     4,    0,     1,     2,     3,      4,
+        {OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,}
+             2,      3,     0,     3,      4);
+      oppostfix2str: array[TOpPostfix] of string[2] = ('',
         's',
-        'b','sb','h','sh');
+        'b','sb','h','sh','w','sw');
 
 {*****************************************************************************
                                 Conditions
@@ -150,13 +166,15 @@ unit cpubase;
       TAsmConds = set of TAsmCond;
 
     const
+      C_CS = C_HS;
+      C_CC = C_LO;
       cond2str : array[TAsmCond] of string[2]=('',
         'eq','ne','hs','lo','mi','pl','vs','vc','hi','ls',
         'ge','lt','gt','le','al','nv'
       );
 
       uppercond2str : array[TAsmCond] of string[2]=('',
-        'EQ','NE','hs','LO','MI','PL','VS','VC','HI','LS',
+        'EQ','NE','HS','LO','MI','PL','VS','VC','HI','LS',
         'GE','LT','GT','LE','AL','NV'
       );
 
@@ -168,12 +186,28 @@ unit cpubase;
       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);
 
+    const
+      F_HS = F_CS;
+      F_LO = F_CC;
+
 {*****************************************************************************
                                 Operands
 *****************************************************************************}
 
+    type
       taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
-      tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR);
+
+      tshiftmode = (SM_None,
+                    { shifted register instructions. LSL can also be used for
+                      the index register of certain loads/stores }
+                    SM_LSL,SM_LSR,SM_ASR,
+                    { extended register instructions: zero/sign extension +
+                        optional shift (interpreted as LSL after extension)
+                       -- the index register of certain loads/stores can be
+                          extended via (s|u)xtw with a shiftval of either 0 or
+                          log2(transfer size of the load/store)
+                    }
+                    SM_UXTB,SM_UXTH,SM_UXTW,SM_UXTX,SM_SXTB,SM_SXTH,SM_SXTW,SM_SXTX);
 
       tupdatereg = (UR_None,UR_Update);
 
@@ -184,12 +218,6 @@ unit cpubase;
         shiftimm : byte;
       end;
 
-      tcpumodeflag = (mfA, mfI, mfF);
-      tcpumodeflags = set of tcpumodeflag;
-
-      tspecialregflag = (srC, srX, srS, srF);
-      tspecialregflags = set of tspecialregflag;
-
 {*****************************************************************************
                                  Constants
 *****************************************************************************}
@@ -201,6 +229,10 @@ unit cpubase;
       maxfpuregs = 32;
       maxaddrregs = 0;
 
+      shiftedregmodes = [SM_LSL,SM_UXTB,SM_UXTH,SM_UXTW,SM_UXTX,SM_SXTB,SM_SXTH,SM_SXTW,SM_SXTX];
+      extendedregmodes = [SM_LSL,SM_LSR,SM_ASR];
+
+
 {*****************************************************************************
                                 Operand Sizes
 *****************************************************************************}
@@ -232,17 +264,23 @@ unit cpubase;
                           Generic Register names
 *****************************************************************************}
 
-      NR_SP = NR_XZR;
-      RS_SP = RS_XZR;
-      NR_WSP = NR_WZR;
-      RS_WSP = RS_WZR;
+
+      NR_FP = NR_X29;
+      RS_FP = RS_X29;
+      NR_WFP = NR_W29;
+      RS_WFP = RS_W29;
+
+      NR_LR = NR_X30;
+      RS_LR = RS_X30;
+      NR_WLR = NR_W30;
+      RS_WLR = RS_W30;
 
       { Stack pointer register }
       NR_STACK_POINTER_REG = NR_SP;
       RS_STACK_POINTER_REG = RS_SP;
-      { Frame pointer register (initialized in tarmprocinfo.init_framepointer) }
-      RS_FRAME_POINTER_REG: tsuperregister = RS_X29;
-      NR_FRAME_POINTER_REG: tregister = NR_X29;
+      { Frame pointer register }
+      NR_FRAME_POINTER_REG = NR_X29;
+      RS_FRAME_POINTER_REG = RS_X29;
       { 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
@@ -307,6 +345,9 @@ unit cpubase;
 
     function dwarf_reg(r:tregister):shortint;
 
+    function is_shifter_const(d: aint; size: tcgsize): boolean;
+
+
   implementation
 
     uses
@@ -329,13 +370,24 @@ unit cpubase;
     function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
         case regtype of
+          R_INTREGISTER:
+            begin
+              case s of
+                { there's only Wn and Xn }
+                OS_64,
+                OS_S64:
+                  cgsize2subreg:=R_SUBWHOLE;
+                else
+                  cgsize2subreg:=R_SUBD;
+                end;
+            end;
           R_MMREGISTER:
             begin
               case s of
                 OS_F32:
-                  cgsize2subreg:=R_SUBFS;
+                  cgsize2subreg:=R_SUBMMS;
                 OS_F64:
-                  cgsize2subreg:=R_SUBFD;
+                  cgsize2subreg:=R_SUBMMD;
                 else
                   internalerror(2009112701);
               end;
@@ -349,18 +401,22 @@ unit cpubase;
     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_INTREGISTER:
+            case getsubreg(reg) of
+              R_SUBD:
+                result:=OS_32
+              else
+                result:=OS_64;
+            end;
           R_MMREGISTER :
             begin
               case getsubreg(reg) of
-                R_SUBFD,
-                R_SUBWHOLE:
+                R_SUBMMD:
                   result:=OS_F64;
-                R_SUBFS:
+                R_SUBMMS:
                   result:=OS_F32;
+                R_SUBMMWHOLE:
+                  result:=OS_M128;
                 else
                   internalerror(2009112903);
               end;
@@ -373,9 +429,7 @@ unit cpubase;
 
     function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
       begin
-        { This isn't 100% perfect because the arm 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_B,A_BLR,A_RET];
+        is_calljmp:=o in [A_B,A_BL,A_BLR,A_RET,A_CBNZ,A_CBZ,A_TBNZ,A_TBZ];
       end;
 
 
@@ -391,8 +445,8 @@ unit cpubase;
 
     function flags_to_cond(const f: TResFlags) : TAsmCond;
       const
-        flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
-          (C_EQ,C_NE,C_HI,C_LO,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+        flag_2_cond: array[TResFlags] of TAsmCond =
+          (C_EQ,C_NE,C_HS,C_LO,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
@@ -434,7 +488,7 @@ unit cpubase;
     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_LO,C_HI,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+          C_NE,C_EQ,C_LO,C_HS,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
@@ -456,4 +510,112 @@ unit cpubase;
       end;
 
 
+    function is_shifter_const(d: aint; size: tcgsize): boolean;
+      var
+         pattern, checkpattern: qword;
+         patternlen, maxbits, replicatedlen: longint;
+         rightmostone, rightmostzero, checkbit, secondrightmostbit: longint;
+      begin
+        result:=false;
+        { patterns with all bits 0 or 1 cannot be represented this way }
+        if (d=0) then
+          exit;
+        case size of
+          OS_64,
+          OS_S64:
+            begin
+              if d=-1 then
+                exit;
+              maxbits:=64;
+            end
+          else
+            begin
+              if longint(d)=-1 then
+                exit;
+              { we'll generate a 32 bit pattern -> ignore upper sign bits in
+                case of negative longint value }
+              d:=cardinal(d);
+              maxbits:=32;
+            end;
+        end;
+        { "The Logical (immediate) instructions accept a bitmask immediate value
+          that is a 32-bit pattern or a 64-bit pattern viewed as a vector of
+          identical elements of size e = 2, 4, 8, 16, 32 or, 64 bits. Each
+          element contains the same sub-pattern, that is a single run of
+          1 to (e - 1) nonzero bits from bit 0 followed by zero bits, then
+          rotated by 0 to (e - 1) bits." (ARMv8 ARM)
+
+          Rather than generating all possible patterns and checking whether they
+          match our constant, we check whether the lowest 2/4/8/... bits are
+          a valid pattern, and if so whether the constant consists of a
+          replication of this pattern. Such a valid pattern has the form of
+          either (regexp notation)
+            * 1+0+1*
+            * 0+1+0* }
+        patternlen:=2;
+        while patternlen<=maxbits do
+          begin
+            { try lowest <patternlen> bits of d as pattern }
+            if patternlen<>64 then
+              pattern:=qword(d) and ((qword(1) shl patternlen)-1)
+            else
+              pattern:=qword(d);
+            { valid pattern? If it contains too many 1<->0 transitions, larger
+              parts of d cannot be a valid pattern either }
+            rightmostone:=BsfQWord(pattern);
+            rightmostzero:=BsfQWord(not(pattern));
+            { pattern all ones or zeroes -> not a valid pattern (but larger ones
+              can still be valid, since we have too few transitions) }
+            if (rightmostone<patternlen) and
+               (rightmostzero<patternlen) then
+              begin
+                if rightmostone>rightmostzero then
+                  begin
+                    { we have .*1*0* -> check next zero position by shifting
+                      out the existing zeroes (shr rightmostone), inverting and
+                      then again looking for the rightmost one position }
+                    checkpattern:=not(pattern);
+                    checkbit:=rightmostone;
+                  end
+                else
+                  begin
+                    { same as above, but for .*0*1* }
+                    checkpattern:=pattern;
+                    checkbit:=rightmostzero;
+                  end;
+                secondrightmostbit:=BsfQWord(checkpattern shr checkbit)+checkbit;
+                { if this position is >= patternlen -> ok (1 transition),
+                  otherwise we now have 2 transitions and have to check for a
+                  third (if there is one, abort)
+
+                  bsf returns 255 if no 1 bit is found, so in that case it's
+                  also ok
+                  }
+                if secondrightmostbit<patternlen then
+                  begin
+                    secondrightmostbit:=BsfQWord(not(checkpattern) shr secondrightmostbit)+secondrightmostbit;
+                    if secondrightmostbit<patternlen then
+                      exit;
+                  end;
+                { ok, this is a valid pattern, now does d consist of a
+                  repetition of this pattern? }
+                replicatedlen:=patternlen;
+                checkpattern:=pattern;
+                while replicatedlen<maxbits do
+                  begin
+                    { douplicate current pattern }
+                    checkpattern:=checkpattern or (checkpattern shl replicatedlen);
+                    replicatedlen:=replicatedlen*2;
+                  end;
+                if qword(d)=checkpattern then
+                  begin
+                    { yes! }
+                    result:=true;
+                    exit;
+                  end;
+              end;
+            patternlen:=patternlen*2;
+          end;
+      end;
+
 end.

+ 23 - 2
compiler/aarch64/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 Type
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts64real = double;
    ts80real = type extended;
@@ -45,8 +48,17 @@ Type
      (ct_none
      );
 
+   tcontrollerdatatype = record
+      controllertypestr, controllerunitstr: string[20];
+      cputype: tcputype; fputype: tfputype;
+      flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize, bootbase, bootsize: dword;
+   end;
+
 
 Const
+   { Is there support for dealing with multiple microcontrollers available }
+   { for this platform? }
+   ControllerSupport = false; (* Not yet at least ;-) *)
    {# Size of native extended floating point type }
    extended_size = 8;
    {# Size of a multimedia register               }
@@ -54,6 +66,15 @@ Const
    { target cpu string (used by compiler options) }
    target_cpu_string = 'aarch64';
 
+   { We know that there are fields after sramsize
+     but we don't care about this warning }
+   {$PUSH}
+    {$WARN 3177 OFF}
+   embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
+   (
+      (controllertypestr:''; controllerunitstr:''; cputype:cpu_none; fputype:fpu_none; flashbase:0; flashsize:0; srambase:0; sramsize:0));
+   {$POP}
+
    { calling conventions supported by the code generator }
    supported_calling_conventions : tproccalloptions = [
      pocall_internproc,
@@ -88,12 +109,12 @@ Const
                                  { 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,cs_opt_reorder_fields,cs_opt_fastmath];
+				  cs_opt_nodecse,cs_opt_reorder_fields,cs_opt_fastmath];
 
    level1optimizerswitches = genericlevel1optimizerswitches;
    level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
      [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
-   level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [cs_opt_scheduler{,cs_opt_loopunroll}];
+   level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [];
 
 Implementation

+ 18 - 20
compiler/alpha/tgcpu.pas → compiler/aarch64/cpunode.pas

@@ -1,7 +1,7 @@
-{
-    Copyright (C) 1998-2000 by Florian Klaempfl
+{******************************************************************************
+    Copyright (c) 2014 by Florian Klaempfl
 
-    This unit handles the temporary variables stuff for Alpha
+    Includes the aarch64 code generator
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -17,26 +17,24 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- ****************************************************************************
-}
-{
-  This unit handles the temporary variables stuff for Alpha.
-}
-unit tgcpu;
+ *****************************************************************************}
+unit cpunode;
 
-{$i fpcdefs.inc}
+{$I fpcdefs.inc}
 
-  interface
-
-    uses
-       tgobj;
-
-    type
-       ttgalpha = class(ttgobj)
-       end;
+interface
+{ This unit is used to define the specific CPU implementations. All needed
+actions are included in the INITALIZATION part of these units. This explains
+the behaviour of such a unit having just a USES clause! }
 
 implementation
 
-begin
-  tg:=ttgalpha.create;
+  uses
+    ncgbas,ncgflw,ncgcal,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncgobjc,
+    ncpuadd,ncpumat,ncpumem,ncpuinl,ncpucnv,ncpuset,
+    { this not really a node }
+    rgcpu,
+    { symtable }
+    symcpu;
+
 end.

+ 465 - 527
compiler/aarch64/cpupara.pas

@@ -1,5 +1,5 @@
 {
-    Copyright (c) 2003-2012 by Florian Klaempfl and others
+    Copyright (c) 2013-2014 by Jonas Maebe, Florian Klaempfl and others
 
     AArch64 specific calling conventions
 
@@ -33,20 +33,25 @@ unit cpupara;
        symconst,symbase,symtype,symdef,parabase,paramgr;
 
     type
-       taarch64paramanager = class(tparamanager)
-          function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
-          function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
-          function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
-          function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
-          function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
-          procedure getintparaloc(pd : tabstractprocdef; 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; forcetempdef: tdef): tcgpara;override;
+       tcpuparamanager = class(tparamanager)
+          function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
+          function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
+          function get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset; override;
+          function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
+          function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;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; forcetempdef: tdef): tcgpara;override;
+          function param_use_paraloc(const cgpara: tcgpara): boolean; override;
          private
-          procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
-          function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-            var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
+          curintreg,
+          curmmreg: tsuperregister;
+          curstackoffset: aword;
+
+          procedure init_para_alloc_values;
+          procedure alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
+
+          procedure create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
        end;
 
   implementation
@@ -56,66 +61,117 @@ unit cpupara;
        rgobj,
        defutil,symsym,symtable;
 
+    const
+      RS_FIRST_INT_PARAM_SUPREG = RS_X0;
+      RS_LAST_INT_PARAM_SUPREG = RS_X7;
+      { Q0/D0/S0/H0/B0 all have the same superregister number }
+      RS_FIRST_MM_PARAM_SUPREG = RS_D0;
+      RS_LAST_MM_PARAM_SUPREG = RS_D7;
+
 
-    function taarch64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+    function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
       begin
         result:=VOLATILE_INTREGISTERS
       end;
 
 
-    function taarch64paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+    function tcpuparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
       begin
         result:=[];
       end;
 
 
-    function taarch64paramanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
+    function tcpuparamanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
       begin
         result:=VOLATILE_MMREGISTERS;
       end;
 
 
-    procedure taarch64paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
+    function is_hfa_internal(p: tdef; var basedef: tdef; var elecount: longint): boolean;
       var
-        paraloc : pcgparalocation;
-        def : tdef;
+        i: longint;
+        sym: tsym;
+        tmpelecount: longint;
       begin
-        if nr<1 then
-          internalerror(2002070801);
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
-        cgpara.reset;
-        cgpara.size:=def_cgsize(def);
-        cgpara.intsize:=tcgsize2size[cgpara.size];
-        cgpara.alignment:=std_param_align;
-        cgpara.def:=def;
-        paraloc:=cgpara.add_location;
-        with paraloc^ do
-          begin
-            size:=OS_INT;
-            { the four first parameters are passed into registers }
-            if nr<=8 then
-              begin
-                loc:=LOC_REGISTER;
-                register:=newreg(R_INTREGISTER,RS_X0+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-9)*8;
-              end;
-          end;
+        result:=false;
+        case p.typ of
+          arraydef:
+            begin
+              if is_special_array(p) then
+                exit;
+              case tarraydef(p).elementdef.typ of
+                floatdef:
+                  begin
+                    { an array of empty records has no influence }
+                    if tarraydef(p).elementdef.size=0 then
+                      begin
+                        result:=true;
+                        exit
+                      end;
+                    tmpelecount:=0;
+                    if not is_hfa_internal(tarraydef(p).elementdef,basedef,tmpelecount) then
+                      exit;
+                    { tmpelecount now contains the number of hfa elements in a
+                      single array element (e.g. 2 if it's an array of a record
+                      containing two singles) -> multiply by number of elements
+                      in the array }
+                    inc(elecount,tarraydef(p).elecount*tmpelecount);
+                    if elecount>4 then
+                      exit;
+                  end;
+                else
+                  result:=is_hfa_internal(tarraydef(p).elementdef,basedef,elecount);
+                end;
+            end;
+          floatdef:
+            begin
+              if not assigned(basedef) then
+                basedef:=p
+              else if basedef<>p then
+                exit;
+              inc(elecount);
+              result:=true;
+            end;
+          recorddef:
+            begin
+              for i:=0 to tabstractrecorddef(p).symtable.symlist.count-1 do
+                begin
+                  sym:=tsym(tabstractrecorddef(p).symtable.symlist[i]);
+                  if sym.typ<>fieldvarsym then
+                    continue;
+                  if not is_hfa_internal(tfieldvarsym(sym).vardef,basedef,elecount) then
+                    exit
+                end;
+              result:=true;
+            end;
+          else
+            exit
+        end;
       end;
 
 
-    function Is_HFA(p : tdef) : boolean;
+    { Returns whether a def is a "homogeneous float array" at the machine level.
+      This means that in the memory layout, the def only consists of maximally
+      4 floating point values that appear consecutively in memory }
+    function is_hfa(p: tdef; out basedef: tdef) : boolean;
+      var
+        elecount: longint;
       begin
         result:=false;
+        basedef:=nil;
+        elecount:=0;
+        result:=is_hfa_internal(p,basedef,elecount);
+        result:=
+          result and
+          (elecount>0) and
+          (elecount<=4) and
+          (p.size=basedef.size*elecount)
       end;
 
 
-    function getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
+    function getparaloc(calloption: tproccalloption; p: tdef): tcgloc;
+      var
+        hfabasedef: tdef;
       begin
          { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
            if push_addr_param for the def is true
@@ -124,7 +180,7 @@ unit cpupara;
             orddef:
               getparaloc:=LOC_REGISTER;
             floatdef:
-              getparaloc:=LOC_MMREGISTER
+              getparaloc:=LOC_MMREGISTER;
             enumdef:
               getparaloc:=LOC_REGISTER;
             pointerdef:
@@ -134,7 +190,10 @@ unit cpupara;
             classrefdef:
               getparaloc:=LOC_REGISTER;
             recorddef:
-              getparaloc:=LOC_REGISTER;
+              if not is_hfa(p,hfabasedef) then
+                getparaloc:=LOC_REGISTER
+              else
+                getparaloc:=LOC_MMREGISTER;
             objectdef:
               getparaloc:=LOC_REGISTER;
             stringdef:
@@ -147,12 +206,12 @@ unit cpupara;
             filedef:
               getparaloc:=LOC_REGISTER;
             arraydef:
-              getparaloc:=LOC_REFERENCE;
-            setdef:
-              if is_smallset(p) then
+              if not is_hfa(p,hfabasedef) then
                 getparaloc:=LOC_REGISTER
               else
-                getparaloc:=LOC_REFERENCE;
+                getparaloc:=LOC_MMREGISTER;
+            setdef:
+              getparaloc:=LOC_REGISTER;
             variantdef:
               getparaloc:=LOC_REGISTER;
             { avoid problems with errornous definitions }
@@ -164,7 +223,9 @@ unit cpupara;
       end;
 
 
-    function taarch64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+    function tcpuparamanager.push_addr_param(varspez: tvarspez; def :tdef; calloption: tproccalloption): boolean;
+      var
+        hfabasedef: tdef;
       begin
         result:=false;
         if varspez in [vs_var,vs_out,vs_constref] then
@@ -174,19 +235,36 @@ unit cpupara;
           end;
         case def.typ of
           objectdef:
-            result:=not(Is_HFA(def) and (is_object(def) and ((varspez=vs_const) or (def.size=0));
+            result:=is_object(def);
           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);
+            { ABI: any composite > 16 bytes that not a hfa/hva
+              Special case: MWPascal, which passes all const parameters by
+                reference for compatibility reasons
+            }
+            result:=
+              ((varspez=vs_const) and
+               (calloption=pocall_mwpascal)) or
+              (not is_hfa(def,hfabasedef) and
+               (def.size>16));
           variantdef,
           formaldef:
             result:=true;
+          { arrays are composites and hence treated the same as records by the
+            ABI (watch out for C, where an array is a pointer)
+            Also: all other platforms pass const arrays by reference. Do the
+              same here, because there is too much hacky code out there that
+              relies on this ("array[0..0] of x" passed as const parameter and
+              then indexed beyond its bounds) }
           arraydef:
-            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
-                             is_open_array(def) or
-                             is_array_of_const(def) or
-                             is_array_constructor(def);
+            result:=
+              (calloption in cdecl_pocalls) or
+              is_open_array(def) or
+              is_array_of_const(def) or
+              is_array_constructor(def) or
+              ((tarraydef(def).highrange>=tarraydef(def).lowrange) and
+               ((varspez=vs_const) or
+                (not is_hfa(def,hfabasedef) and
+                 (def.size>16))));
           setdef :
             result:=def.size>16;
           stringdef :
@@ -195,515 +273,375 @@ unit cpupara;
       end;
 
 
-    function taarch64paramanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
-      var
-        i: longint;
-        sym: tsym;
-        fpufield: boolean;
+    function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
       begin
         if handle_common_ret_in_param(def,pd,result) then
           exit;
-        case def.typ of
-          recorddef:
-            begin
-              result:=def.size>4;
-              if not result and
-                 (target_info.abi in [abi_default,abi_armeb]) then
-                begin
-                  { in case of the old ARM abi (APCS), a struct is returned in
-                    a register only if it is simple. And what is a (non-)simple
-                    struct:
-
-                    "A non-simple type is any non-floating-point type of size
-                     greater than one word (including structures containing only
-                     floating-point fields), and certain single-word structured
-                     types."
-                       (-- ARM APCS documentation)
-
-                    So only floating point types or more than one word ->
-                    definitely non-simple (more than one word is already
-                    checked above). This includes unions/variant records with
-                    overlaid floating point and integer fields.
-
-                    Smaller than one word struct types are simple if they are
-                    "integer-like", and:
-
-                    "A structure is termed integer-like if its size is less than
-                    or equal to one word, and the offset of each of its
-                    addressable subfields is zero."
-                      (-- ARM APCS documentation)
-
-                    An "addressable subfield" is a field of which you can take
-                    the address, which in practive means any non-bitfield.
-                    In Pascal, there is no way to express the difference that
-                    you can have in C between "char" and "int :8". In this
-                    context, we use the fake distinction that a type defined
-                    inside the record itself (such as "a: 0..255;") indicates
-                    a bitpacked field while a field using a different type
-                    (such as "a: byte;") is not.
-                  }
-                  for i:=0 to trecorddef(def).symtable.SymList.count-1 do
-                    begin
-                      sym:=tsym(trecorddef(def).symtable.SymList[i]);
-                      if sym.typ<>fieldvarsym then
-                        continue;
-                      { bitfield -> ignore }
-                      if (trecordsymtable(trecorddef(def).symtable).usefieldalignment=bit_alignment) and
-                         (tfieldvarsym(sym).vardef.typ in [orddef,enumdef]) and
-                         (tfieldvarsym(sym).vardef.owner.defowner=def) then
-                        continue;
-                      { all other fields must be at offset zero }
-                      if tfieldvarsym(sym).fieldoffset<>0 then
-                        begin
-                          result:=true;
-                          exit;
-                        end;
-                      { floating point field -> also by reference }
-                      if tfieldvarsym(sym).vardef.typ=floatdef then
-                        begin
-                          result:=true;
-                          exit;
-                        end;
-                    end;
-                end;
-            end;
-          procvardef:
-            if not tprocvardef(def).is_addressonly then
-              result:=true
-            else
-              result:=false
-          else
-            result:=inherited ret_in_param(def,pd);
-        end;
+        { ABI: if the parameter would be passed in registers, it is returned
+            in those registers; otherwise, it's returned by reference }
+        result:=push_addr_param(vs_value,def,pd.proccalloption);
       end;
 
 
-    procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
-      begin
-        curintreg:=RS_R0;
-        curfloatreg:=RS_F0;
-        curmmreg:=RS_D0;
-        cur_stack_offset:=0;
-        sparesinglereg := NR_NO;
-      end;
-
-
-    function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-        var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
-
+    procedure tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
       var
-        nextintreg,nextfloatreg,nextmmreg : 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_R3) 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;
-
-
+        hp: tparavarsym;
+        i: longint;
       begin
-        result:=0;
-        nextintreg:=curintreg;
-        nextfloatreg:=curfloatreg;
-        nextmmreg:=curmmreg;
-        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 cstylearrayofconst) 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 push_addr_param(hp.varspez,paradef,p.proccalloption) then
-              begin
-                paradef:=getpointerdef(paradef);
-                loc:=LOC_REGISTER;
-                paracgsize := OS_ADDR;
-                paralen := tcgsize2size[OS_ADDR];
-              end
-            else
+            { hidden function result parameter is passed in X8 (doesn't have to
+              be valid on return) according to the ABI
+
+              -- don't follow the ABI for managed types, because
+               a) they are passed in registers as parameters, so we should also
+                  return them in a register to be ABI-compliant (which we can't
+                  because the entire compiler is built around the idea that
+                  they are returned by reference, for ref-counting performance
+                  and Delphi-compatibility reasons)
+               b) there are hacks in the system unit that expect that you can
+                  call
+                    function f: com_interface;
+                  as
+                    procedure p(out o: obj);
+                  That can only work in case we do not use x8 to return them
+                  from the function, but the regular first parameter register.
+
+              As the ABI says this behaviour is ok for C++ classes with a
+              non-trivial copy constructor or destructor, it seems reasonable
+              for us to do this for managed types as well.}
+            if (vo_is_funcret in hp.varoptions) and
+               not is_managed_type(hp.vardef) then
               begin
-                if not is_special_array(paradef) then
-                  paralen := paradef.size
-                else
-                  paralen := tcgsize2size[def_cgsize(paradef)];
-                loc := getparaloc(p.proccalloption,paradef,isvariadic);
-                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
+                hp.paraloc[side].reset;
+                hp.paraloc[side].size:=OS_ADDR;
+                hp.paraloc[side].alignment:=voidpointertype.alignment;
+                hp.paraloc[side].intsize:=voidpointertype.size;
+                hp.paraloc[side].def:=cpointerdef.getreusable_no_free(hp.vardef);
+                with hp.paraloc[side].add_location^ do
                   begin
-                    paracgsize:=def_cgsize(paradef);
-                    { for things like formaldef }
-                    if (paracgsize=OS_NO) then
-                      begin
-                        paracgsize:=OS_ADDR;
-                        paralen:=tcgsize2size[OS_ADDR];
-                        paradef:=voidpointertype;
-                      end;
+                    size:=OS_ADDR;
+                    def:=hp.paraloc[side].def;
+                    loc:=LOC_REGISTER;
+                    register:=NR_X8;
                   end
-              end;
-
-             hp.paraloc[side].size:=paracgsize;
-             hp.paraloc[side].Alignment:=std_param_align;
-             hp.paraloc[side].intsize:=paralen;
-             hp.paraloc[side].def:=paradef;
-             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
-                        { align registers for eabi }
-                        if (target_info.abi in [abi_eabi,abi_eabihf]) and
-                           firstparaloc and
-                           (paradef.alignment=8) then
-                          begin
-                            if (nextintreg in [RS_R1,RS_R3]) then
-                              inc(nextintreg)
-                            else if nextintreg>RS_R3 then
-                              stack_offset:=align(stack_offset,8);
-                          end;
-                        { this is not abi compliant
-                          why? (FK) }
-                        if nextintreg<=RS_R3 then
-                          begin
-                            paraloc^.loc:=LOC_REGISTER;
-                            paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
-                            inc(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
-                        if nextfloatreg<=RS_F3 then
-                          begin
-                            paraloc^.loc:=LOC_FPUREGISTER;
-                            paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
-                            inc(nextfloatreg);
-                          end
-                        else
-                          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;
-                      end;
-                    LOC_MMREGISTER:
-                      begin
-                        if (nextmmreg<=RS_D7) or
-                           ((paraloc^.size = OS_F32) and
-                            (sparesinglereg<>NR_NO)) then
-                          begin
-                            paraloc^.loc:=LOC_MMREGISTER;
-                            case paraloc^.size of
-                              OS_F32:
-                                if sparesinglereg = NR_NO then 
-                                  begin     
-                                    paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
-                                    sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
-                                    inc(nextmmreg);
-                                  end
-                                else
-                                  begin
-                                    paraloc^.register:=sparesinglereg;
-                                    sparesinglereg := NR_NO;
-                                  end;
-                              OS_F64:
-                                begin
-                                  paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
-                                  inc(nextmmreg);
-                                end;
-                              else
-                                internalerror(2012031601);
-                            end;
-                          end
-                        else
-                          begin
-                            { once a floating point parameters has been placed
-                            on the stack we must not pass any more in vfp regs
-                            even if there is a single precision register still
-                            free}
-                            sparesinglereg := NR_NO;
-                            { 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_REFERENCE:
-                      begin
-                        if push_addr_param(hp.varspez,paradef,p.proccalloption) then
-                          begin
-                            paraloc^.size:=OS_ADDR;
-                            assignintreg
-                          end
-                        else
-                          begin
-                            { align stack for eabi }
-                            if (target_info.abi in [abi_eabi,abi_eabihf]) and
-                               firstparaloc and
-                               (paradef.alignment=8) then
-                              stack_offset:=align(stack_offset,8);
-
-                             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;
-                         { on non-Darwin, the framepointer contains the value
-                           of the stack pointer on entry. On Darwin, the
-                           framepointer points to the previously saved
-                           framepointer (which is followed only by the saved
-                           return address -> framepointer + 4 = stack pointer
-                           on entry }
-                         if not(target_info.system in systems_darwin) then
-                           inc(paraloc^.reference.offset,4)
-                         else
-                           inc(paraloc^.reference.offset,8);
-                       end;
-                   end;
-                 dec(paralen,tcgsize2size[paraloc^.size]);
-                 firstparaloc:=false
-               end;
+              end
+            else
+              alloc_para(hp.paraloc[side],p,hp.varspez,side,hp.vardef,isvariadic,
+                (vo_is_parentfp in hp.varoptions) and
+                (po_delphi_nested_cc in p.procoptions));
           end;
-        curintreg:=nextintreg;
-        curfloatreg:=nextfloatreg;
-        curmmreg:=nextmmreg;
-        cur_stack_offset:=stack_offset;
-        result:=cur_stack_offset;
       end;
 
 
-    function  taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+    function  tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
       var
-        paraloc : pcgparalocation;
-        retcgsize  : tcgsize;
+        retcgsize: tcgsize;
       begin
          if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
            exit;
 
-        paraloc:=result.add_location;
-        { Return in FPU register? }
-        if result.def.typ=floatdef then
+         { in this case, it must be returned in registers as if it were passed
+           as the first parameter }
+         init_para_alloc_values;
+         alloc_para(result,p,vs_value,side,result.def,false,false);
+         { sanity check (LOC_VOID for empty records) }
+         if not assigned(result.location) or
+            not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
+           internalerror(2014113001);
+      end;
+
+
+    function tcpuparamanager.param_use_paraloc(const cgpara: tcgpara): boolean;
+      begin
+        { we always set up a stack frame -> we can always access the parameters
+          this way }
+        result:=
+          (cgpara.location^.loc=LOC_REFERENCE) and
+          not assigned(cgpara.location^.next);
+      end;
+
+
+    procedure tcpuparamanager.init_para_alloc_values;
+      begin
+        curintreg:=RS_FIRST_INT_PARAM_SUPREG;
+        curmmreg:=RS_FIRST_MM_PARAM_SUPREG;
+        curstackoffset:=0;
+      end;
+
+
+    procedure tcpuparamanager.alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
+      var
+        hfabasedef, locdef: tdef;
+        paraloc: pcgparalocation;
+        paralen, stackslotlen: asizeint;
+        loc: tcgloc;
+        paracgsize, locsize: tcgsize;
+        firstparaloc: boolean;
+      begin
+        result.reset;
+
+        { currently only support C-style array of const,
+          there should be no location assigned to the vararg array itself }
+        if (p.proccalloption in cstylearrayofconst) and
+           is_array_of_const(paradef) then
           begin
-            if target_info.abi = abi_eabihf then 
-              begin
-                paraloc^.loc:=LOC_MMREGISTER;
-                case retcgsize of
-                  OS_64,
-                  OS_F64:
-                    begin
-                      paraloc^.register:=NR_MM_RESULT_REG;
-                    end;
-                  OS_32,
-                  OS_F32:
-                    begin
-                      paraloc^.register:=NR_S0;
-                    end;
-                  else
-                    internalerror(2012032501);
-                end;
-                paraloc^.size:=retcgsize;
-              end
-            else if (p.proccalloption in [pocall_softfloat]) or
-               (cs_fp_emulation in current_settings.moduleswitches) or
-               (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
-              begin
-                case retcgsize of
-                  OS_64,
-                  OS_F64:
-                    begin
-                      paraloc^.loc:=LOC_REGISTER;
-                      if target_info.endian = endian_big then
-                        paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
-                      else
-                        paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
-                      paraloc^.size:=OS_32;
-                      paraloc:=result.add_location;
-                      paraloc^.loc:=LOC_REGISTER;
-                      if target_info.endian = endian_big then
-                        paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
-                      else
-                        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
-            else
-              begin
-                paraloc^.loc:=LOC_FPUREGISTER;
-                paraloc^.register:=NR_FPU_RESULT_REG;
-                paraloc^.size:=retcgsize;
-              end;
+            paraloc:=result.add_location;
+            { hack: the paraloc must be valid, but is not actually used }
+            paraloc^.loc:=LOC_REGISTER;
+            paraloc^.register:=NR_X0;
+            paraloc^.size:=OS_ADDR;
+            exit;
+          end;
+
+        if push_addr_param(varspez,paradef,p.proccalloption) then
+          begin
+            paradef:=cpointerdef.getreusable_no_free(paradef);
+            loc:=LOC_REGISTER;
+            paracgsize:=OS_ADDR;
+            paralen:=tcgsize2size[OS_ADDR];
           end
-          { Return in register }
         else
           begin
-            if retcgsize in [OS_64,OS_S64] then
-              begin
-                paraloc^.loc:=LOC_REGISTER;
-                if target_info.endian = endian_big then
-                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
-                else
-                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
-                paraloc^.size:=OS_32;
-                paraloc:=result.add_location;
-                paraloc^.loc:=LOC_REGISTER;
-                if target_info.endian = endian_big then
-                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
-                else
-                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
-                paraloc^.size:=OS_32;
-              end
+            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
+               (varspez in [vs_value,vs_const]) then
+              paracgsize:=int_cgsize(paralen)
             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;
+                paracgsize:=def_cgsize(paradef);
+                { for things like formaldef }
+                if paracgsize=OS_NO then
+                  begin
+                    paracgsize:=OS_ADDR;
+                    paralen:=tcgsize2size[OS_ADDR];
+                    paradef:=voidpointertype;
+                  end;
+              end
           end;
+
+          { get hfa basedef if applicable }
+          if not is_hfa(paradef,hfabasedef) then
+            hfabasedef:=nil;
+
+         result.size:=paracgsize;
+         result.alignment:=std_param_align;
+         result.intsize:=paralen;
+         result.def:=paradef;
+
+         { empty record: skipped (explicitly defined by Apple ABI, undefined
+           by general ABI; libffi also skips them in all cases) }
+         if not is_special_array(paradef) and
+            (paradef.size=0) then
+           begin
+             paraloc:=result.add_location;
+             paraloc^.loc:=LOC_VOID;
+             paraloc^.def:=paradef;
+             paraloc^.size:=OS_NO;
+             exit;
+           end;
+
+         { sufficient registers left? }
+         case loc of
+           LOC_REGISTER:
+             begin
+               { In case of po_delphi_nested_cc, the parent frame pointer
+                 is always passed on the stack. }
+               if isdelphinestedcc then
+                 loc:=LOC_REFERENCE
+               else if curintreg+((paralen-1) shr 3)>RS_LAST_INT_PARAM_SUPREG then
+                 begin
+                   { not enough integer registers left -> no more register
+                     parameters, copy all to stack
+                   }
+                   curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
+                   loc:=LOC_REFERENCE;
+                 end;
+             end;
+           LOC_MMREGISTER:
+             begin;
+               { every hfa element must be passed in a separate register }
+               if (assigned(hfabasedef) and
+                   (curmmreg+(paralen div hfabasedef.size)>RS_LAST_MM_PARAM_SUPREG)) or
+                  (curmmreg+((paralen-1) shr 3)>RS_LAST_MM_PARAM_SUPREG) then
+                 begin
+                   { not enough mm registers left -> no more register
+                     parameters, copy all to stack
+                   }
+                   curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
+                   loc:=LOC_REFERENCE;
+                 end;
+             end;
+         end;
+
+         { allocate registers/stack locations }
+         firstparaloc:=true;
+         repeat
+           paraloc:=result.add_location;
+
+           { set paraloc size/def }
+           if assigned(hfabasedef) then
+             begin
+               locsize:=def_cgsize(hfabasedef);
+               locdef:=hfabasedef;
+             end
+           { make sure we don't lose whether or not the type is signed }
+           else if (loc=LOC_REGISTER) and
+                   (paradef.typ<>orddef) then
+             begin
+               locsize:=int_cgsize(paralen);
+               locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
+             end
+           else
+             begin
+               locsize:=paracgsize;
+               locdef:=paradef;
+             end;
+           if locsize in [OS_NO,OS_128,OS_S128] then
+             begin
+               if paralen>4 then
+                 begin
+                   paraloc^.size:=OS_INT;
+                   paraloc^.def:=u64inttype;
+                 end
+               else
+                 begin
+                   { for 3-byte records }
+                   paraloc^.size:=OS_32;
+                   paraloc^.def:=u32inttype;
+                 end;
+             end
+           else
+             begin
+               paraloc^.size:=locsize;
+               paraloc^.def:=locdef;
+             end;
+
+           { paraloc loc }
+           paraloc^.loc:=loc;
+
+           { assign register/stack address }
+           case loc of
+             LOC_REGISTER:
+               begin
+                 paraloc^.register:=newreg(R_INTREGISTER,curintreg,cgsize2subreg(R_INTREGISTER,paraloc^.size));
+                 inc(curintreg);
+                 dec(paralen,tcgsize2size[paraloc^.size]);
+
+                 { "The general ABI specifies that it is the callee's
+                    responsibility to sign or zero-extend arguments having fewer
+                    than 32 bits, and that unused bits in a register are
+                    unspecified. In iOS, however, the caller must perform such
+                    extensions, up to 32 bits." }
+                 if (target_info.abi=abi_aarch64_darwin) and
+                    (side=callerside) and
+                    is_ordinal(paradef) and
+                    (paradef.size<4) then
+                   paraloc^.size:=OS_32;
+
+                 { in case it's a composite, "The argument is passed as though
+                   it had been loaded into the registers from a double-word-
+                   aligned address with an appropriate sequence of LDR
+                   instructions loading consecutive registers from memory" ->
+                   in case of big endian, values in not completely filled
+                   registers must be shifted to the top bits }
+                 if (target_info.endian=endian_big) and
+                    not(paraloc^.size in [OS_64,OS_S64]) and
+                    (paradef.typ in [setdef,recorddef,arraydef,objectdef]) then
+                   paraloc^.shiftval:=-(8-tcgsize2size[paraloc^.size]);
+               end;
+             LOC_MMREGISTER:
+               begin
+                 paraloc^.register:=newreg(R_MMREGISTER,curmmreg,cgsize2subreg(R_MMREGISTER,paraloc^.size));
+                 inc(curmmreg);
+                 dec(paralen,tcgsize2size[paraloc^.size]);
+               end;
+             LOC_REFERENCE:
+               begin
+                  paraloc^.size:=paracgsize;
+                  paraloc^.loc:=LOC_REFERENCE;
+
+                  { the current stack offset may not be properly aligned in
+                    case we're on Darwin have allocated a non-variadic argument
+                    < 8 bytes previously }
+                  if target_info.abi=abi_aarch64_darwin then
+                    curstackoffset:=align(curstackoffset,paraloc^.def.alignment);
+
+                  { on Darwin, non-variadic arguments take up their actual size
+                    on the stack; on other platforms, they take up a multiple of
+                    8 bytes }
+                  if (target_info.abi=abi_aarch64_darwin) and
+                     not isvariadic then
+                    stackslotlen:=paralen
+                  else
+                    stackslotlen:=align(paralen,8);
+
+                  { from the ABI: if arguments occupy partial stack space, they
+                    have to occupy the lowest significant bits of a register
+                    containing that value which is then stored to memory ->
+                    in case of big endian, skip the alignment bytes (if any) }
+                  if target_info.endian=endian_little then
+                    paraloc^.reference.offset:=curstackoffset
+                  else
+                    paraloc^.reference.offset:=curstackoffset+stackslotlen-paralen;
+                  if side=callerside then
+                    paraloc^.reference.index:=NR_STACK_POINTER_REG
+                  else
+                    begin
+                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                      inc(paraloc^.reference.offset,16);
+                    end;
+                  inc(curstackoffset,stackslotlen);
+                  paralen:=0
+               end;
+             else
+               internalerror(2002071002);
+           end;
+         firstparaloc:=false;
+         { <=0 for sign/zero-extended locations }
+         until paralen<=0;
       end;
 
 
-    function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
-      var
-        cur_stack_offset: aword;
-        curintreg, curfloatreg, curmmreg: tsuperregister;
-        sparesinglereg:tregister;
+    function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;
       begin
-        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+        init_para_alloc_values;
 
-        result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
+        create_paraloc_info_intern(p,side,p.paras,false);
+        result:=curstackoffset;
 
         create_funcretloc_info(p,side);
      end;
 
 
-    function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
-      var
-        cur_stack_offset: aword;
-        curintreg, curfloatreg, curmmreg: tsuperregister;
-        sparesinglereg:tregister;
+    function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;
       begin
-        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+        init_para_alloc_values;
 
-        result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
-        if (p.proccalloption in cstylearrayofconst) then
-          { just continue loading the parameters in the registers }
-          result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
+        { non-variadic parameters }
+        create_paraloc_info_intern(p,callerside,p.paras,false);
+        if p.proccalloption in cstylearrayofconst then
+          begin
+            { on Darwin, we cannot use any registers for variadic parameters }
+            if target_info.abi=abi_aarch64_darwin then
+              begin
+                curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
+                curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
+              end;
+            { continue loading the parameters  }
+            create_paraloc_info_intern(p,callerside,varargspara,true);
+            result:=curstackoffset;
+          end
         else
           internalerror(200410231);
       end;
 
 begin
-   paramanager:=taarch64paramanager.create;
+   paramanager:=tcpuparamanager.create;
 end.

+ 68 - 0
compiler/aarch64/cpupi.pas

@@ -0,0 +1,68 @@
+{
+    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.
+
+ ****************************************************************************
+}
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    procinfo,
+    psub;
+
+  type
+    taarch64procinfo=class(tcgprocinfo)
+      constructor create(aparent: tprocinfo); override;
+      procedure set_first_temp_offset; override;
+    end;
+
+implementation
+
+  uses
+    tgobj,
+    cpubase;
+
+  constructor taarch64procinfo.create(aparent: tprocinfo);
+    begin
+      inherited;
+      { use the stack pointer as framepointer, because
+         1) we exactly know the offsets of the temps from the stack pointer
+            after pass 1 (based on the require parameter stack size for called
+            routines), while we don't know it for the frame pointer (it depends
+            on the number of saved registers)
+         2) temp offsets from the stack pointer are positive while those from
+            the frame pointer are negative, and we can directly encode much
+            bigger positive offsets in the instructions
+      }
+      framepointer:=NR_STACK_POINTER_REG;
+    end;
+
+  procedure taarch64procinfo.set_first_temp_offset;
+    begin
+     { leave room for allocated parameters }
+     tg.setfirsttemp(align(maxpushedparasize,16));
+    end;
+
+
+begin
+  cprocinfo:=taarch64procinfo;
+end.

+ 70 - 0
compiler/aarch64/cputarg.pas

@@ -0,0 +1,70 @@
+{
+    Copyright (c) 2001-2002 by Peter Vreman
+
+    Includes the AArch64 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 NOTARGETLINUX}
+      ,t_linux
+    {$endif}
+    {$ifndef NOTARGETBSD}
+      ,t_bsd
+    {$endif}
+
+{**************************************
+             Assemblers
+**************************************}
+
+    {$ifndef NOAGCPUGAS}
+      ,agcpugas
+    {$endif}
+
+{**************************************
+        Assembler Readers
+**************************************}
+
+  {$ifndef NoRaarmgas}
+       ,racpugas
+  {$endif NoRaarmgas}
+
+{**************************************
+             Debuginfo
+**************************************}
+
+  {$ifndef NoDbgDwarf}
+      ,dbgdwarf
+  {$endif NoDbgDwarf}
+      ;
+
+end.

+ 229 - 0
compiler/aarch64/hlcgcpu.pas

@@ -0,0 +1,229 @@
+{
+    Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
+    Member of the Free Pascal development team
+
+    This unit contains routines to create a pass-through high-level code
+    generator. This is used by most regular code generators.
+
+    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 hlcgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    symtype,
+    aasmdata,
+    symdef,
+    cgbase,cgutils,
+    hlcgobj, hlcg2ll;
+
+  type
+    thlcgaarch64 = class(thlcg2ll)
+      procedure a_load_subsetreg_reg(list: TAsmList; subsetsize, tosize: tdef; const sreg: tsubsetregister; destreg: tregister); override;
+      procedure a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tdef; const fromsreg, tosreg: tsubsetregister); override;
+
+      procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+     protected
+      procedure a_load_regconst_subsetreg_intern(list: TAsmList; fromsize, subsetsize: tdef; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
+    end;
+
+  procedure create_hlcodegen;
+
+implementation
+
+  uses
+    verbose,globtype,fmodule,
+    aasmbase,aasmtai,
+    symconst,symsym,defutil,
+    cpubase,aasmcpu,parabase,
+    cgobj,cgcpu;
+
+  procedure thlcgaarch64.a_load_subsetreg_reg(list: TAsmList; subsetsize, tosize: tdef; const sreg: tsubsetregister; destreg: tregister);
+    var
+      op: tasmop;
+      tocgsize: tcgsize;
+      tmpdestreg: tregister;
+    begin
+      tocgsize:=def_cgsize(tosize);
+      if (sreg.startbit<>0) or
+         not(sreg.bitlen in [32,64]) then
+        begin
+          if is_signed(subsetsize) then
+            op:=A_SBFX
+          else
+            op:=A_UBFX;
+          { source and destination register of SBFX/UBFX have to be the same size }
+          if (sreg.subsetregsize in [OS_64,OS_S64]) and
+             not(tocgsize in [OS_64,OS_S64]) then
+            tmpdestreg:=cg.getintregister(list,OS_64)
+          else if not(sreg.subsetregsize in [OS_64,OS_S64]) and
+             (tocgsize in [OS_64,OS_S64]) then
+            tmpdestreg:=cg.getintregister(list,OS_32)
+          else
+            tmpdestreg:=destreg;
+          list.concat(taicpu.op_reg_reg_const_const(op,tmpdestreg,sreg.subsetreg,sreg.startbit,sreg.bitlen));
+          { need to sign extend further or truncate? }
+          if (sreg.subsetregsize=OS_S64) and
+             not(tocgsize in [OS_64,OS_S64]) then
+            cg.a_load_reg_reg(list,OS_S64,tocgsize,tmpdestreg,destreg)
+          else if is_signed(subsetsize) and
+             (tocgsize in [OS_8,OS_16]) then
+            cg.a_load_reg_reg(list,OS_32,tocgsize,tmpdestreg,destreg)
+          else if tmpdestreg<>destreg then
+            cg.a_load_reg_reg(list,def_cgsize(subsetsize),tocgsize,tmpdestreg,destreg)
+        end
+      else
+        cg.a_load_reg_reg(list,def_cgsize(subsetsize),tocgsize,sreg.subsetreg,destreg);
+    end;
+
+
+  procedure makeregssamesize(list: tasmlist; fromsize, tosize: tcgsize; orgfromreg, orgtoreg: tregister; out newfromreg, newtoreg: tregister);
+    begin
+      if (fromsize in [OS_S64,OS_64])<>
+         (tosize in [OS_S64,OS_64]) then
+        begin
+          newfromreg:=cg.makeregsize(list,orgfromreg,OS_64);
+          newtoreg:=cg.makeregsize(list,orgtoreg,OS_64);
+        end
+      else
+        begin
+          newfromreg:=orgfromreg;
+          newtoreg:=orgtoreg;
+        end;
+    end;
+
+
+  procedure thlcgaarch64.a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tdef; const fromsreg, tosreg: tsubsetregister);
+    var
+      fromreg, toreg: tregister;
+
+    begin
+      { BFM can only insert a bitfield that starts at position 0 in the source
+        source or destination register }
+      if (tosreg.startbit=0) and
+         (fromsreg.bitlen>=tosreg.bitlen) then
+        begin
+          makeregssamesize(list,fromsreg.subsetregsize,tosreg.subsetregsize,fromsreg.subsetreg,tosreg.subsetreg,fromreg,toreg);
+          list.concat(taicpu.op_reg_reg_const_const(A_BFXIL,toreg,fromreg,fromsreg.startbit,tosreg.bitlen))
+        end
+      else if (fromsreg.startbit=0) and
+         (fromsreg.bitlen>=tosreg.bitlen) then
+        begin
+          makeregssamesize(list,fromsreg.subsetregsize,tosreg.subsetregsize,fromsreg.subsetreg,tosreg.subsetreg,fromreg,toreg);
+          list.concat(taicpu.op_reg_reg_const_const(A_BFI,toreg,fromreg,tosreg.startbit,tosreg.bitlen))
+        end
+      else
+        inherited;
+    end;
+
+
+  procedure thlcgaarch64.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+    var
+      make_global: boolean;
+      href: treference;
+      hsym: tsym;
+      paraloc: pcgparalocation;
+      op: tasmop;
+    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_library 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));
+
+      { set param1 interface to self  }
+      procdef.init_paraloc_info(callerside);
+      hsym:=tsym(procdef.parast.Find('self'));
+      if not(assigned(hsym) and
+        (hsym.typ=paravarsym)) then
+        internalerror(2010103101);
+      paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+      if assigned(paraloc^.next) then
+        InternalError(2013020101);
+
+      case paraloc^.loc of
+        LOC_REGISTER:
+          tcgaarch64(cg).handle_reg_imm12_reg(list,A_SUB,paraloc^.size,paraloc^.register,ioffset,paraloc^.register,NR_IP0,false,true);
+        else
+          internalerror(2010103102);
+      end;
+
+      if (po_virtualmethod in procdef.procoptions) and
+          not is_objectpascal_helper(procdef.struct) then
+        begin
+          if (procdef.extnumber=$ffff) then
+            Internalerror(200006139);
+          { mov  0(%rdi),%rax ; load vmt}
+          reference_reset_base(href,voidpointertype,paraloc^.register,0,sizeof(pint));
+          getcpuregister(list,NR_IP0);
+          a_load_ref_reg(list,voidpointertype,voidpointertype,href,NR_IP0);
+          { jmp *vmtoffs(%eax) ; method offs }
+          reference_reset_base(href,voidpointertype,NR_IP0,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+          op:=A_LDR;
+          tcgaarch64(cg).make_simple_ref(list,op,OS_ADDR,PF_None,href,NR_IP0);
+          list.concat(taicpu.op_reg_ref(op,NR_IP0,href));
+          ungetcpuregister(list,NR_IP0);
+          list.concat(taicpu.op_reg(A_BR,NR_IP0));
+        end
+      else
+        cg.a_jmp_name(list,procdef.mangledname);
+      list.concat(Tai_symbol_end.Createname(labelname));
+    end;
+
+
+  procedure thlcgaarch64.a_load_regconst_subsetreg_intern(list: TAsmList; fromsize, subsetsize: tdef; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt);
+    var
+      toreg: tregister;
+    begin
+      if slopt in [SL_SETZERO,SL_SETMAX] then
+        inherited
+      else if not(sreg.bitlen in [32,64]) or
+              (sreg.startbit<>0) then
+        begin
+          makeregssamesize(list,def_cgsize(fromsize),sreg.subsetregsize,fromreg,sreg.subsetreg,fromreg,toreg);
+          list.concat(taicpu.op_reg_reg_const_const(A_BFI,toreg,fromreg,sreg.startbit,sreg.bitlen))
+        end
+      else
+        a_load_reg_reg(list,fromsize,subsetsize,fromreg,sreg.subsetreg);
+    end;
+
+
+  procedure create_hlcodegen;
+    begin
+      hlcg:=thlcgaarch64.create;
+      create_codegen;
+    end;
+
+
+end.

+ 402 - 0
compiler/aarch64/ncpuadd.pas

@@ -0,0 +1,402 @@
+{
+    Copyright (c) 2014 Jonas Maebe
+
+    Code generation for add nodes on AArch64
+
+    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 ncpuadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       node,ncgadd,cpubase;
+
+    type
+       taarch64addnode = class(tcgaddnode)
+       private
+          function  GetResFlags(unsigned:Boolean):TResFlags;
+          function  GetFPUResFlags:TResFlags;
+       protected
+          procedure second_addfloat;override;
+          procedure second_cmpfloat;override;
+          procedure second_cmpboolean;override;
+          procedure second_cmpsmallset;override;
+          procedure second_cmpordinal;override;
+          procedure second_addordinal;override;
+          procedure second_add64bit; override;
+          procedure second_cmp64bit; override;
+       public
+          function use_generic_mul32to64: boolean; override;
+       end;
+
+  implementation
+
+    uses
+      systems,
+      cutils,verbose,
+      paramgr,procinfo,
+      aasmtai,aasmdata,aasmcpu,defutil,
+      cgbase,cgcpu,cgutils,
+      cpupara,
+      ncon,nset,nadd,
+      hlcgobj, ncgutil,cgobj;
+
+{*****************************************************************************
+                               taarch64addnode
+*****************************************************************************}
+
+    function taarch64addnode.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;
+                    else
+                      internalerror(2014082010);
+                  end
+                else
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_LT;
+                    lten:
+                      GetResFlags:=F_LE;
+                    gtn:
+                      GetResFlags:=F_GT;
+                    gten:
+                      GetResFlags:=F_GE;
+                    else
+                      internalerror(2014082011);
+                  end;
+              end
+            else
+              begin
+                if nf_swapped in Flags then
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_HI;
+                    lten:
+                      GetResFlags:=F_HS;
+                    gtn:
+                      GetResFlags:=F_LO;
+                    gten:
+                      GetResFlags:=F_LS;
+                    else
+                      internalerror(2014082012);
+                  end
+                else
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_LO;
+                    lten:
+                      GetResFlags:=F_LS;
+                    gtn:
+                      GetResFlags:=F_HI;
+                    gten:
+                      GetResFlags:=F_HS;
+                    else
+                      internalerror(2014082013);
+                  end;
+              end;
+        end;
+      end;
+
+
+    function taarch64addnode.GetFPUResFlags:TResFlags;
+      begin
+        case NodeType of
+          equaln:
+            result:=F_EQ;
+          unequaln:
+            result:=F_NE;
+          else
+            begin
+              if nf_swapped in Flags then
+                case NodeType of
+                  ltn:
+                    result:=F_GT;
+                  lten:
+                    result:=F_GE;
+                  gtn:
+                    result:=F_LO;
+                  gten:
+                    result:=F_LS;
+                  else
+                    internalerror(2014082014);
+                end
+              else
+                case NodeType of
+                  ltn:
+                    result:=F_LO;
+                  lten:
+                    result:=F_LS;
+                  gtn:
+                    result:=F_GT;
+                  gten:
+                    result:=F_GE;
+                  else
+                    internalerror(2014082015);
+                end;
+            end;
+        end;
+      end;
+
+
+    procedure taarch64addnode.second_addfloat;
+      var
+        op : TAsmOp;
+      begin
+        pass_left_right;
+        if nf_swapped in flags then
+          swapleftright;
+
+        { force fpureg as location, left right doesn't matter
+          as both will be in a fpureg }
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+
+        location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+        location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+
+        case nodetype of
+          addn :
+            begin
+              op:=A_FADD;
+            end;
+          muln :
+            begin
+              op:=A_FMUL;
+            end;
+          subn :
+            begin
+              op:=A_FSUB;
+            end;
+          slashn :
+            begin
+              op:=A_FDIV;
+            end;
+          else
+            internalerror(200306014);
+        end;
+
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+           location.register,left.location.register,right.location.register));
+      end;
+
+
+    procedure taarch64addnode.second_cmpfloat;
+      begin
+        pass_left_right;
+        if nf_swapped in flags then
+          swapleftright;
+
+        { force fpureg as location, left right doesn't matter
+          as both will be in a fpureg }
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getfpuresflags;
+
+        { signalling compare so we can get exceptions }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCMPE,
+             left.location.register,right.location.register));
+      end;
+
+
+    procedure taarch64addnode.second_cmpboolean;
+      begin
+        pass_left_right;
+        force_reg_left_right(true,true);
+
+        if right.location.loc=LOC_CONSTANT then
+          begin
+            if right.location.value>=0 then
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMP,left.location.size,left.location.register,right.location.value,NR_XZR,NR_NO,false,false)
+            else
+              { avoid overflow if value=low(int64) }
+{$push}{$r-}{$q-}
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMN,left.location.size,left.location.register,-right.location.value,NR_XZR,NR_NO,false,false)
+{$pop}
+          end
+        else
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(true);
+      end;
+
+
+    procedure taarch64addnode.second_cmpsmallset;
+      var
+        tmpreg : tregister;
+        op: tasmop;
+      begin
+        pass_left_right;
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+
+        force_reg_left_right(true,true);
+
+        if right.location.loc=LOC_CONSTANT then
+          begin
+            { when doing a cmp/cmn on 32 bit, we care whether the *lower 32 bit*
+              is a positive/negative value -> sign extend }
+            if not(right.location.size in [OS_64,OS_S64]) then
+              right.location.value:=longint(right.location.value);
+            if right.location.value>=0 then
+              op:=A_CMP
+            else
+              op:=A_CMN;
+          end
+        else
+          { for DFA }
+          op:=A_NONE;
+
+        case nodetype of
+          equaln,
+          unequaln:
+            begin
+              if right.location.loc=LOC_CONSTANT then
+                tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),left.location.register,abs(right.location.value),NR_XZR,NR_NO,false,false)
+              else
+                current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+              location.resflags:=getresflags(true);
+            end;
+          lten,
+          gten:
+            begin
+              if (not(nf_swapped in flags) and
+                  (nodetype=lten)) or
+                 ((nf_swapped in flags) and
+                  (nodetype=gten)) then
+                swapleftright;
+              { we can't handle left as a constant yet }
+              if left.location.loc=LOC_CONSTANT then
+                hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+              tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
+              if right.location.loc=LOC_CONSTANT then
+                begin
+                  hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,right.location.value,left.location.register,tmpreg);
+                  tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),tmpreg,abs(right.location.value),NR_XZR,NR_NO,false,false)
+                end
+              else
+                begin
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
+                end;
+              location.resflags:=F_EQ;
+            end;
+          else
+            internalerror(2012042701);
+        end;
+      end;
+
+
+    procedure taarch64addnode.second_cmpordinal;
+      var
+        unsigned : boolean;
+      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 right.location.value>=0 then
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMP,left.location.size,left.location.register,right.location.value,NR_XZR,NR_NO,false,false)
+            else
+{$push}{$r-}{$q-}
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMN,left.location.size,left.location.register,-right.location.value,NR_XZR,NR_NO,false,false)
+{$pop}
+          end
+        else
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(unsigned);
+      end;
+
+
+    procedure taarch64addnode.second_addordinal;
+      const
+        multops: array[boolean] of TAsmOp = (A_SMULL,A_UMULL);
+      var
+        unsigned: boolean;
+      begin
+        { 32x32->64 multiplication }
+        if (nodetype=muln) and
+           is_32bit(left.resultdef) and
+           is_32bit(right.resultdef) and
+           is_64bit(resultdef) then
+          begin
+            unsigned:=not(is_signed(left.resultdef)) or
+                      not(is_signed(right.resultdef));
+            pass_left_right;
+            force_reg_left_right(true,true);
+            { force_reg_left_right can leave right as a LOC_CONSTANT (we can't
+              say "a constant register is okay, but an ordinal constant isn't) }
+            if right.location.loc=LOC_CONSTANT then
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+            location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+            location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(multops[unsigned],location.register,left.location.register,right.location.register));
+          end
+        else
+          inherited second_addordinal;
+      end;
+
+
+    procedure taarch64addnode.second_add64bit;
+      begin
+        second_addordinal;
+      end;
+
+
+    procedure taarch64addnode.second_cmp64bit;
+      begin
+        second_cmpordinal;
+      end;
+
+
+    function taarch64addnode.use_generic_mul32to64: boolean;
+      begin
+        result:=false;
+      end;
+
+
+begin
+  caddnode:=taarch64addnode;
+end.

+ 199 - 0
compiler/aarch64/ncpucnv.pas

@@ -0,0 +1,199 @@
+{
+    Copyright (c) 2014 by Jonas Maebe
+
+    Generate AArch64 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 ncpucnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ncnv,ncgcnv;
+
+    type
+      taarch64typeconvnode = class(TCgTypeConvNode)
+        protected
+         function typecheck_int_to_real: tnode; override;
+         function first_int_to_real: tnode; override;
+
+        { procedure second_int_to_int;override; }
+        { procedure second_string_to_string;override; }
+        { procedure second_cstring_to_pchar;override; }
+        { procedure second_string_to_chararray;override; }
+        { procedure second_array_to_pointer;override; }
+        { procedure second_pointer_to_array;override; }
+        { procedure second_chararray_to_string;override; }
+        { procedure second_char_to_string;override; }
+         procedure second_int_to_real;override;
+        { procedure second_real_to_real;override; }
+        { procedure second_cord_to_pointer;override; }
+        { procedure second_proc_to_procvar;override; }
+        { procedure second_bool_to_int;override; }
+         procedure second_int_to_bool;override;
+        { procedure second_load_smallset;override;  }
+        { procedure second_ansistring_to_pchar;override; }
+        { procedure second_pchar_to_string;override; }
+        { procedure second_class_to_intf;override; }
+        { procedure second_char_to_char;override; }
+      end;
+
+implementation
+
+  uses
+    verbose,globals,
+    symdef,aasmdata,aasmbase,
+    defutil,
+    cgbase,cgutils,procinfo,
+    cpubase,aasmcpu,
+    pass_2,cgobj,
+    hlcgobj;
+
+
+{*****************************************************************************
+                             FirstTypeConv
+*****************************************************************************}
+
+  function taarch64typeconvnode.typecheck_int_to_real: tnode;
+    begin
+      { aarch64 supports converting everything to floating point, even fixed
+        point! Unfortunately, it only supports fixed point with a power-of-2
+        fraction, which is not the case for currency.
+
+        Generate the division by 10000 via nodes so the 10000.0 constant can
+        be reused. }
+      if is_currency(resultdef) and
+         not(nf_is_currency in flags) then
+        begin
+          { convert the equivalent int64 value to double without conversion
+            (internal typecast -> will set nf_is_currency flag) }
+          result:=ctypeconvnode.create_internal(left,s64floattype);
+          { turn into currency with conversion, which will divide by 10000
+            (regular typecast) }
+          result:=ctypeconvnode.create(result,s64currencytype);
+          exit;
+        end;
+      { The only other thing we have to take care of: convert values < 32 bit
+        to 32 bit }
+      if left.resultdef.size<4 then
+        begin
+          if is_signed(left.resultdef) then
+            inserttypeconv(left,s32inttype)
+          else
+            inserttypeconv(left,u32inttype)
+        end;
+      result:=inherited;
+    end;
+
+
+  function taarch64typeconvnode.first_int_to_real: tnode;
+    begin
+      result:=nil;
+      expectloc:=LOC_MMREGISTER;
+    end;
+
+
+{*****************************************************************************
+                             SecondTypeConv
+*****************************************************************************}
+
+  procedure taarch64typeconvnode.second_int_to_real;
+    var
+      op: tasmop;
+    begin
+      location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+      location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+      hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+      if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+        internalerror(2014120401);
+      case left.location.size of
+        OS_32,
+        OS_64:
+          op:=A_UCVTF;
+        OS_S32,
+        OS_S64,
+        { for currency and comp }
+        OS_F64:
+          op:=A_SCVTF;
+        else
+          internalerror(2014120402);
+      end;
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+      { no scaling for currency, that's handled in pass_typecheck }
+    end;
+
+
+  procedure taarch64typeconvnode.second_int_to_bool;
+    var
+      resflags: tresflags;
+      hlabel: tasmlabel;
+    begin
+      if (nf_explicit in flags) and
+         not(left.expectloc in [LOC_FLAGS,LOC_JUMP]) then
+        begin
+          inherited;
+          exit;
+        end;
+
+      { can't use the generic code, as it assumes that OP_OR automatically sets
+        the flags. We can also do things more efficiently directly }
+
+      secondpass(left);
+      if codegenerror then
+       exit;
+
+      case left.location.loc of
+        LOC_SUBSETREG,
+        LOC_CSUBSETREG,
+        LOC_SUBSETREF,
+        LOC_CSUBSETREF,
+        LOC_CREFERENCE,
+        LOC_REFERENCE,
+        LOC_REGISTER,
+        LOC_CREGISTER,
+        LOC_JUMP:
+          begin
+             hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+             current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,0));
+             resflags:=F_NE;
+          end;
+        LOC_FLAGS :
+          resflags:=left.location.resflags;
+        else
+          internalerror(2014122902);
+      end;
+      { load flags to register }
+      location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+      location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+      if is_cbool(resultdef) then
+        begin
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_cond(A_CSETM,location.register,flags_to_cond(resflags)));
+            { truncate? (in case cbools are ever made unsigned) }
+            if resultdef.size<4 then
+              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,location.size,location.register,location.register);
+        end
+      else
+        cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register);
+      cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+    end;
+
+
+begin
+   ctypeconvnode:=taarch64typeconvnode;
+end.

+ 184 - 0
compiler/aarch64/ncpuinl.pas

@@ -0,0 +1,184 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generates ARM inline 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 ncpuinl;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ninl,ncginl;
+
+    type
+      taarch64inlinenode = class(tcgInlineNode)
+        function first_abs_real: tnode; override;
+        function first_sqr_real: tnode; override;
+        function first_sqrt_real: tnode; override;
+        function first_round_real: tnode; override;
+        function first_trunc_real: tnode; override;
+        procedure second_abs_real; override;
+        procedure second_sqr_real; override;
+        procedure second_sqrt_real; override;
+        procedure second_abs_long; override;
+        procedure second_round_real; override;
+        procedure second_trunc_real; override;
+        procedure second_get_frame; override;
+      private
+        procedure load_fpu_location;
+      end;
+
+
+implementation
+
+    uses
+      globtype,verbose,globals,
+      cpuinfo, defutil,symdef,aasmdata,aasmcpu,
+      cgbase,cgutils,pass_1,pass_2,
+      cpubase,ncgutil,cgobj,cgcpu, hlcgobj;
+
+{*****************************************************************************
+                              taarch64inlinenode
+*****************************************************************************}
+
+    procedure taarch64inlinenode.load_fpu_location;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_copy(location,left.location);
+        location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+        location.loc:=LOC_MMREGISTER;
+      end;
+
+
+    function taarch64inlinenode.first_abs_real : tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_sqr_real : tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_sqrt_real : tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_round_real: tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_trunc_real: tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    procedure taarch64inlinenode.second_abs_real;
+      begin
+        load_fpu_location;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABS,location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_sqr_real;
+      begin
+        load_fpu_location;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FMUL,location.register,left.location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_sqrt_real;
+      begin
+        load_fpu_location;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT,location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_abs_long;
+      var
+        opsize : tcgsize;
+        hp : taicpu;
+      begin
+        secondpass(left);
+        opsize:=def_cgsize(left.resultdef);
+        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+        location:=left.location;
+        location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+
+        current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_NEG,location.register,left.location.register),PF_S));
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_cond(A_CSEL,location.register,location.register,left.location.register,C_GE));
+      end;
+
+
+    procedure taarch64inlinenode.second_round_real;
+      var
+        hreg: tregister;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+        hreg:=cg.getmmregister(current_asmdata.CurrAsmList,left.location.size);
+        { round as floating point using current rounding mode }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRINTX,hreg,left.location.register));
+        { convert to signed integer rounding towards zero (there's no "round to
+          integer using current rounding mode") }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCVTZS,location.register,hreg));
+      end;
+
+
+    procedure taarch64inlinenode.second_trunc_real;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+        { convert to signed integer rounding towards zero }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCVTZS,location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_get_frame;
+      begin
+        location_reset(location,LOC_CREGISTER,OS_ADDR);
+        { this routine is used to get the frame pointer for backtracing
+          purposes. current_procinfo.framepointer is set to SP because that one
+          is used to access temps. On most platforms these two frame pointers
+          are the same, but not on AArch64. }
+        location.register:=NR_FRAME_POINTER_REG;
+      end;
+
+begin
+  cinlinenode:=taarch64inlinenode;
+end.

+ 196 - 0
compiler/aarch64/ncpumat.pas

@@ -0,0 +1,196 @@
+{
+    Copyright (c) 1998-2002, 2014 by Florian Klaempfl and Jonas Maebe
+
+    Generate AArch64 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 ncpumat;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,nmat,ncgmat;
+
+    type
+      taarch64moddivnode = class(tmoddivnode)
+         function pass_1: tnode; override;
+         procedure pass_generate_code;override;
+      end;
+
+      taarch64notnode = class(tcgnotnode)
+         procedure second_boolean;override;
+      end;
+
+      taarch64unaryminusnode = class(tcgunaryminusnode)
+         procedure second_float; override;
+      end;
+
+implementation
+
+    uses
+      globtype,systems,constexp,
+      cutils,verbose,globals,
+      symconst,symdef,
+      aasmbase,aasmcpu,aasmtai,aasmdata,
+      defutil,
+      cgbase,cgobj,hlcgobj,pass_2,procinfo,
+      ncon,
+      cpubase,
+      ncgutil,cgcpu,cgutils;
+
+{*****************************************************************************
+                             taarch64moddivnode
+*****************************************************************************}
+
+    function taarch64moddivnode.pass_1: tnode;
+      begin
+        result:=inherited pass_1;
+        if not assigned(result) then
+          include(current_procinfo.flags,pi_do_call);
+      end;
+
+
+    procedure taarch64moddivnode.pass_generate_code;
+      var
+         op         : tasmop;
+         tmpreg,
+         numerator,
+         divider,
+         resultreg  : tregister;
+         hl : tasmlabel;
+         overflowloc: tlocation;
+      begin
+       secondpass(left);
+       secondpass(right);
+
+       { set result location }
+       location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+       location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+       resultreg:=location.register;
+
+       { put numerator in register }
+       hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+       numerator:=left.location.register;
+
+       { load divider in a register }
+       hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+       divider:=right.location.register;
+
+       { start division }
+       if is_signed(left.resultdef) then
+         op:=A_SDIV
+       else
+         op:=A_UDIV;
+       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,numerator,divider));
+
+       { no divide-by-zero detection available in hardware, emulate (if it's a
+         constant, this will have been detected earlier already) }
+       if (right.nodetype<>ordconstn) then
+         begin
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,
+             right.location.register,0));
+
+           current_asmdata.getjumplabel(hl);
+           current_asmdata.CurrAsmList.concat(taicpu.op_cond_sym(A_B,C_NE,hl));
+           cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIVBYZERO',false);
+           cg.a_label(current_asmdata.CurrAsmList,hl);
+         end;
+
+       { in case of overflow checking, also check for low(int64) div (-1)
+         (no hardware support for this either) }
+       if (cs_check_overflow in current_settings.localswitches) and
+          is_signed(left.resultdef) and
+          ((right.nodetype<>ordconstn) or
+           (tordconstnode(right).value=-1)) then
+         begin
+           { num=ffff... and div=8000... <=>
+             num xor not(div xor 8000...) = 0
+             (and we have the "eon" operation, which performs "xor not(...)" }
+           tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
+           hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,left.resultdef,low(int64),left.location.register,tmpreg);
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_EON,
+             tmpreg,left.location.register,tmpreg));
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,tmpreg,0));
+           { now the zero/equal flag is set in case we divided low(int64) by
+             (-1) }
+           location_reset(overflowloc,LOC_FLAGS,OS_NO);
+           overflowloc.resflags:=F_EQ;
+           cg.g_overflowcheck_loc(current_asmdata.CurrAsmList,location,resultdef,overflowloc);
+         end;
+
+       { in case of modulo, multiply result again by the divider and subtract
+         from the numerator }
+       if nodetype=modn then
+         current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MSUB,resultreg,
+           resultreg,divider,numerator));
+    end;
+
+
+{*****************************************************************************
+                               taarch64notnode
+*****************************************************************************}
+
+    procedure taarch64notnode.second_boolean;
+      begin
+        if not handle_locjump then
+          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
+                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,
+                    left.location.register,0));
+                  location_reset(location,LOC_FLAGS,OS_NO);
+                  location.resflags:=F_EQ;
+               end;
+              else
+                internalerror(2003042401);
+            end;
+          end;
+      end;
+
+
+{*****************************************************************************
+                                   taarch64unaryminusnode
+*****************************************************************************}
+
+    procedure taarch64unaryminusnode.second_float;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+        location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FNEG,location.register,left.location.register));
+      end;
+
+begin
+   cmoddivnode:=taarch64moddivnode;
+   cnotnode:=taarch64notnode;
+   cunaryminusnode:=taarch64unaryminusnode;
+end.

+ 142 - 0
compiler/aarch64/ncpumem.pas

@@ -0,0 +1,142 @@
+{
+    Copyright (c) 2014 by Jonas Maebe
+
+    Generate AArch64 code 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 ncpumem;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    globtype,
+    cgbase,
+    symtype,
+    node,nmem,ncgmem;
+
+  type
+    taarch64loadparentfpnode = class(tcgloadparentfpnode)
+      procedure pass_generate_code; override;
+    end;
+
+    taarch64vecnode = class(tcgvecnode)
+     protected
+      function valid_index_size(size: tcgsize): boolean; override;
+     public
+       procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint); override;
+    end;
+
+implementation
+
+  uses
+    cutils,verbose,
+    defutil,
+    aasmdata,cpubase,
+    cgutils,
+    cgobj;
+
+  { taarch64loadparentfpnode }
+
+  procedure taarch64loadparentfpnode.pass_generate_code;
+    begin
+      inherited pass_generate_code;
+      { see the comments in tcgaarch64.g_proc_entry }
+      if (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
+         (location.register=NR_STACK_POINTER_REG) then
+        if (kind=lpf_forpara) then
+          location.register:=NR_FRAME_POINTER_REG
+        else
+          begin
+            { load stack pointer in a different register, as many instructions
+              cannot directly work with the stack pointer. The register
+              allocator can merge them if possible }
+            location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+            cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_STACK_POINTER_REG,location.register);
+            location.loc:=LOC_REGISTER;
+          end;
+    end;
+
+
+  { taarch64vecnode }
+
+  function taarch64vecnode.valid_index_size(size: tcgsize): boolean;
+    begin
+      { all sizes are ok if we handle the "reference reg mul", because
+         a) we use a 64 bit register for 64 bit values, and a 32 bit one (that
+            we can sign/zero-extend inside the reference) for smaller values
+         b) for values < 32 bit, the entire 32 bit register always contains the
+            sign/zero-extended version of the value }
+      result:=
+        not is_packed_array(left.resultdef) and
+        (get_mul_size in [1,2,4,8,16]);
+    end;
+
+
+  procedure taarch64vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
+    var
+      base: tregister;
+      oldoffset: asizeint;
+      shift: byte;
+    begin
+      { we can only scale the index by shl 0..4 }
+      if not(l in [1,2,4,8,16]) then
+        begin
+          inherited;
+          exit;
+        end;
+      { we need a base set and an index available }
+      if (location.reference.base=NR_NO) or
+         (location.reference.index<>NR_NO) then
+        begin
+          { don't integrate the offset yet, make_simple_ref() may be able to
+            handle it more efficiently later (unless an offset is all we have
+            -> optimization for someone that wants to add support for AArch64
+            embedded targets) }
+          oldoffset:=location.reference.offset;
+          location.reference.offset:=0;
+          base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+          cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,base);
+          reference_reset_base(location.reference,base,oldoffset,location.reference.alignment);
+        end;
+      shift:=BsfDWord(l);
+      location.reference.index:=maybe_const_reg;
+      { sign/zero-extend? }
+      if regsize.size=8 then
+        if shift<>0 then
+          location.reference.shiftmode:=SM_LSL
+        else
+          location.reference.shiftmode:=SM_NONE
+      else if is_signed(regsize) then
+        location.reference.shiftmode:=SM_SXTW
+      else if shift<>0 then
+        location.reference.shiftmode:=SM_UXTW
+      else
+        { the upper 32 bits are always already zero-extended -> just use 64 bit
+          register }
+        location.reference.index:=cg.makeregsize(current_asmdata.CurrAsmList,location.reference.index,OS_64);
+      location.reference.shiftimm:=shift;
+      location.reference.alignment:=newalignment(location.reference.alignment,l);
+    end;
+
+
+begin
+  cloadparentfpnode:=taarch64loadparentfpnode;
+  cvecnode:=taarch64vecnode;
+end.

+ 175 - 0
compiler/aarch64/ncpuset.pas

@@ -0,0 +1,175 @@
+{
+    Copyright (c) 2015 by Jonas Maebe
+
+    Generate AArch64 assembler for in set/case 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 ncpuset;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,aasmdata,globtype;
+
+    type
+       taarch64casenode = class(tcgcasenode)
+         protected
+           procedure optimizevalues(var max_linear_list: aint; var max_dist: aword);override;
+           function  has_jumptable: boolean;override;
+           procedure genjumptable(hp: pcaselabel ;min_, max_: aint);override;
+       end;
+
+
+implementation
+
+    uses
+      systems,
+      verbose,globals,constexp,
+      symconst,symdef,defutil,
+      paramgr,
+      cpuinfo,
+      pass_2,cgcpu,
+      ncon,
+      tgobj,ncgutil,regvars,rgobj,aasmcpu,
+      procinfo,
+      cgutils;
+
+{*****************************************************************************
+                            TCGCASENODE
+*****************************************************************************}
+
+
+    procedure taarch64casenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
+      begin
+        max_linear_list:=10;
+      end;
+    
+
+    function taarch64casenode.has_jumptable: boolean;
+      begin
+        has_jumptable:=true;
+      end;
+
+
+    procedure taarch64casenode.genjumptable(hp: pcaselabel; min_, max_: aint);
+      var
+        last: TConstExprInt;
+        tablelabel: TAsmLabel;
+        basereg,indexreg,jumpreg: TRegister;
+        href: TReference;
+        opcgsize: tcgsize;
+        sectype: TAsmSectiontype;
+        jtitemconsttype: taiconst_type;
+
+      procedure genitem(list:TAsmList;t : pcaselabel);
+        var
+          i : aint;
+        begin
+          if assigned(t^.less) then
+            genitem(list,t^.less);
+          { fill possible hole }
+          i:=last.svalue+1;
+          while i<=t^._low.svalue-1 do
+            begin
+              list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,elselabel));
+              inc(i);
+            end;
+          i:=t^._low.svalue;
+          while i<=t^._high.svalue do
+            begin
+              list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,blocklabel(t^.blockid)));
+              inc(i);
+            end;
+          last:=t^._high;
+          if assigned(t^.greater) then
+            genitem(list,t^.greater);
+        end;
+
+      begin
+        if not(target_info.system in systems_darwin) then
+          jtitemconsttype:=aitconst_32bit
+        else
+          { see https://gmplib.org/list-archives/gmp-bugs/2012-December/002836.html }
+          jtitemconsttype:=aitconst_darwin_dwarf_delta32;
+
+        last:=min_;
+        opcgsize:=def_cgsize(opsize);
+        { a <= x <= b <-> unsigned(x-a) <= (b-a) }
+        cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opcgsize,aint(min_),hregister);
+        if not(jumptable_no_range) then
+          begin
+             { case expr greater than max_ => goto elselabel }
+             cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opcgsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
+             min_:=0;
+          end;
+        { local label in order to avoid using GOT }
+        current_asmdata.getlabel(tablelabel,alt_data);
+        indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_ADDR);
+        cg.a_load_reg_reg(current_asmdata.CurrAsmList,opcgsize,OS_ADDR,hregister,indexreg);
+        { load table address }
+        reference_reset_symbol(href,tablelabel,0,4);
+        basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+        cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
+        { load table slot, 32-bit sign extended }
+        reference_reset_base(href,basereg,0,4);
+        href.index:=indexreg;
+        href.shiftmode:=SM_LSL;
+        href.shiftimm:=2;
+        jumpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+        cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,jumpreg);
+        { add table address }
+        cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,basereg,jumpreg);
+        { and finally jump }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_BR,jumpreg));
+        { generate jump table }
+        if not(target_info.system in systems_darwin) then
+          sectype:=sec_rodata
+        else
+          begin
+            { on Mac OS X, dead code stripping ("smart linking") happens based on
+              global symbols: every global/static symbol (symbols that do not
+              start with "L") marks the start of a new "subsection" that is
+              discarded by the linker if there are no references to this symbol.
+              This means that if you put the jump table in the rodata section, it
+              will become part of the block of data associated with the previous
+              non-L-label in the rodata section and stay or be thrown away
+              depending on whether that block of data is referenced. Therefore,
+              jump tables must be added in the code section and since aktlocaldata
+              is inserted right after the routine, it will become part of the
+              same subsection that contains the routine's code }
+            sectype:=sec_code;
+          end;
+        new_section(current_procinfo.aktlocaldata,sectype,current_procinfo.procdef.mangledname,4);
+        if target_info.system in systems_darwin then
+          begin
+            { additionally, these tables are now marked via ".data_region jt32"
+              and ".end_data_region" }
+            current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_data_region,'jt32'));
+          end;
+        current_procinfo.aktlocaldata.concat(Tai_label.Create(tablelabel));
+        genitem(current_procinfo.aktlocaldata,hp);
+        if target_info.system in systems_darwin then
+          current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_end_data_region,''));
+      end;
+
+
+begin
+   ccasenode:=taarch64casenode;
+end.

+ 5 - 0
compiler/aarch64/ra64con.inc

@@ -64,6 +64,8 @@ NR_W30 = tregister($0104001E);
 NR_X30 = tregister($0105001E);
 NR_WZR = tregister($0104001F);
 NR_XZR = tregister($0105001F);
+NR_WSP = tregister($01040020);
+NR_SP = tregister($01050020);
 NR_B0 = tregister($04010000);
 NR_H0 = tregister($04030000);
 NR_S0 = tregister($04090000);
@@ -225,3 +227,6 @@ NR_S31 = tregister($0409001F);
 NR_D31 = tregister($040a001F);
 NR_Q31 = tregister($0405001F);
 NR_NZCV = tregister($05000000);
+NR_FPCR = tregister($05000001);
+NR_FPSR = tregister($05000002);
+NR_TPIDR_EL0 = tregister($05000003);

+ 162 - 157
compiler/aarch64/ra64dwa.inc

@@ -64,164 +64,169 @@
 30,
 31,
 31,
+31,
+31,
+64,
+64,
+64,
+64,
+64,
+65,
+65,
+65,
+65,
+65,
+66,
+66,
+66,
+66,
+66,
+67,
+67,
+67,
+67,
+67,
+68,
+68,
+68,
+68,
+68,
+69,
+69,
+69,
+69,
+69,
+70,
+70,
+70,
+70,
+70,
+71,
+71,
+71,
+71,
+71,
+72,
+72,
+72,
+72,
+72,
+73,
+73,
+73,
+73,
+73,
+74,
+74,
+74,
+74,
+74,
+75,
+75,
+75,
+75,
+75,
+76,
+76,
+76,
+76,
+76,
+77,
+77,
+77,
+77,
+77,
+78,
+78,
+78,
+78,
+78,
+79,
+79,
+79,
+79,
+79,
+80,
+80,
+80,
+80,
+80,
+81,
+81,
+81,
+81,
+81,
+82,
+82,
+82,
+82,
+82,
+83,
+83,
+83,
+83,
+83,
+84,
+84,
+84,
+84,
+84,
+85,
+85,
+85,
+85,
+85,
+86,
+86,
+86,
+86,
+86,
+87,
+87,
+87,
+87,
+87,
+88,
+88,
+88,
+88,
+88,
+89,
+89,
+89,
+89,
+89,
+90,
+90,
+90,
+90,
+90,
+91,
+91,
+91,
+91,
+91,
+92,
+92,
+92,
+92,
+92,
+93,
+93,
+93,
+93,
+93,
+94,
+94,
+94,
+94,
+94,
+95,
+95,
+95,
+95,
+95,
 0,
 0,
 0,
-0,
-0,
-1,
-1,
-1,
-1,
-1,
-2,
-2,
-2,
-2,
-2,
-3,
-3,
-3,
-3,
-3,
-4,
-4,
-4,
-4,
-4,
-5,
-5,
-5,
-5,
-5,
-6,
-6,
-6,
-6,
-6,
-7,
-7,
-7,
-7,
-7,
-8,
-8,
-8,
-8,
-8,
-9,
-9,
-9,
-9,
-9,
-10,
-10,
-10,
-10,
-10,
-11,
-11,
-11,
-11,
-11,
-12,
-12,
-12,
-12,
-12,
-13,
-13,
-13,
-13,
-13,
-14,
-14,
-14,
-14,
-14,
-15,
-15,
-15,
-15,
-15,
-16,
-16,
-16,
-16,
-16,
-17,
-17,
-17,
-17,
-17,
-18,
-18,
-18,
-18,
-18,
-19,
-19,
-19,
-19,
-19,
-20,
-20,
-20,
-20,
-20,
-21,
-21,
-21,
-21,
-21,
-22,
-22,
-22,
-22,
-22,
-23,
-23,
-23,
-23,
-23,
-24,
-24,
-24,
-24,
-24,
-25,
-25,
-25,
-25,
-25,
-26,
-26,
-26,
-26,
-26,
-27,
-27,
-27,
-27,
-27,
-28,
-28,
-28,
-28,
-28,
-29,
-29,
-29,
-29,
-29,
-30,
-30,
-30,
-30,
-30,
-31,
-31,
-31,
-31,
-31,
 0

+ 1 - 1
compiler/aarch64/ra64nor.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from a64reg.dat }
-226
+231

+ 6 - 1
compiler/aarch64/ra64num.inc

@@ -64,6 +64,8 @@ tregister($0104001E),
 tregister($0105001E),
 tregister($0104001F),
 tregister($0105001F),
+tregister($01040020),
+tregister($01050020),
 tregister($04010000),
 tregister($04030000),
 tregister($04090000),
@@ -224,4 +226,7 @@ tregister($0403001F),
 tregister($0409001F),
 tregister($040a001F),
 tregister($0405001F),
-tregister($05000000)
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003)

+ 101 - 96
compiler/aarch64/ra64rni.inc

@@ -32,6 +32,7 @@
 59,
 61,
 63,
+65,
 2,
 4,
 6,
@@ -64,102 +65,7 @@
 60,
 62,
 64,
-65,
-70,
-75,
-80,
-85,
-90,
-95,
-100,
-105,
-110,
-115,
-120,
-125,
-130,
-135,
-140,
-145,
-150,
-155,
-160,
-165,
-170,
-175,
-180,
-185,
-190,
-195,
-200,
-205,
-210,
-215,
-220,
 66,
-71,
-76,
-81,
-86,
-91,
-96,
-101,
-106,
-111,
-116,
-121,
-126,
-131,
-136,
-141,
-146,
-151,
-156,
-161,
-166,
-171,
-176,
-181,
-186,
-191,
-196,
-201,
-206,
-211,
-216,
-221,
-69,
-74,
-79,
-84,
-89,
-94,
-99,
-104,
-109,
-114,
-119,
-124,
-129,
-134,
-139,
-144,
-149,
-154,
-159,
-164,
-169,
-174,
-179,
-184,
-189,
-194,
-199,
-204,
-209,
-214,
-219,
-224,
 67,
 72,
 77,
@@ -224,4 +130,103 @@
 213,
 218,
 223,
-225
+71,
+76,
+81,
+86,
+91,
+96,
+101,
+106,
+111,
+116,
+121,
+126,
+131,
+136,
+141,
+146,
+151,
+156,
+161,
+166,
+171,
+176,
+181,
+186,
+191,
+196,
+201,
+206,
+211,
+216,
+221,
+226,
+69,
+74,
+79,
+84,
+89,
+94,
+99,
+104,
+109,
+114,
+119,
+124,
+129,
+134,
+139,
+144,
+149,
+154,
+159,
+164,
+169,
+174,
+179,
+184,
+189,
+194,
+199,
+204,
+209,
+214,
+219,
+224,
+70,
+75,
+80,
+85,
+90,
+95,
+100,
+105,
+110,
+115,
+120,
+125,
+130,
+135,
+140,
+145,
+150,
+155,
+160,
+165,
+170,
+175,
+180,
+185,
+190,
+195,
+200,
+205,
+210,
+215,
+220,
+225,
+227,
+228,
+229,
+230

+ 48 - 43
compiler/aarch64/ra64sri.inc

@@ -1,8 +1,39 @@
 { don't edit, this file is generated from a64reg.dat }
 0,
-65,
+67,
+72,
+117,
+122,
+127,
+132,
+137,
+142,
+147,
+152,
+157,
+162,
+77,
+167,
+172,
+177,
+182,
+187,
+192,
+197,
+202,
+207,
+212,
+82,
+217,
+222,
+87,
+92,
+97,
+102,
+107,
+112,
 70,
-115,
+75,
 120,
 125,
 130,
@@ -12,8 +43,8 @@
 150,
 155,
 160,
-75,
 165,
+80,
 170,
 175,
 180,
@@ -23,15 +54,18 @@
 200,
 205,
 210,
-80,
 215,
-220,
 85,
+220,
+225,
 90,
 95,
 100,
 105,
 110,
+115,
+228,
+229,
 68,
 73,
 118,
@@ -64,9 +98,9 @@
 103,
 108,
 113,
-66,
+227,
 71,
-116,
+76,
 121,
 126,
 131,
@@ -76,8 +110,8 @@
 151,
 156,
 161,
-76,
 166,
+81,
 171,
 176,
 181,
@@ -87,16 +121,16 @@
 201,
 206,
 211,
-81,
 216,
-221,
 86,
+221,
+226,
 91,
 96,
 101,
 106,
 111,
-225,
+116,
 69,
 74,
 119,
@@ -129,38 +163,8 @@
 104,
 109,
 114,
-67,
-72,
-117,
-122,
-127,
-132,
-137,
-142,
-147,
-152,
-157,
-162,
-77,
-167,
-172,
-177,
-182,
-187,
-192,
-197,
-202,
-207,
-212,
-82,
-217,
-222,
-87,
-92,
-97,
-102,
-107,
-112,
+66,
+230,
 1,
 3,
 21,
@@ -192,6 +196,7 @@
 15,
 17,
 19,
+65,
 63,
 2,
 4,

+ 162 - 157
compiler/aarch64/ra64sta.inc

@@ -64,164 +64,169 @@
 30,
 31,
 31,
+31,
+31,
+64,
+64,
+64,
+64,
+64,
+65,
+65,
+65,
+65,
+65,
+66,
+66,
+66,
+66,
+66,
+67,
+67,
+67,
+67,
+67,
+68,
+68,
+68,
+68,
+68,
+69,
+69,
+69,
+69,
+69,
+70,
+70,
+70,
+70,
+70,
+71,
+71,
+71,
+71,
+71,
+72,
+72,
+72,
+72,
+72,
+73,
+73,
+73,
+73,
+73,
+74,
+74,
+74,
+74,
+74,
+75,
+75,
+75,
+75,
+75,
+76,
+76,
+76,
+76,
+76,
+77,
+77,
+77,
+77,
+77,
+78,
+78,
+78,
+78,
+78,
+79,
+79,
+79,
+79,
+79,
+80,
+80,
+80,
+80,
+80,
+81,
+81,
+81,
+81,
+81,
+82,
+82,
+82,
+82,
+82,
+83,
+83,
+83,
+83,
+83,
+84,
+84,
+84,
+84,
+84,
+85,
+85,
+85,
+85,
+85,
+86,
+86,
+86,
+86,
+86,
+87,
+87,
+87,
+87,
+87,
+88,
+88,
+88,
+88,
+88,
+89,
+89,
+89,
+89,
+89,
+90,
+90,
+90,
+90,
+90,
+91,
+91,
+91,
+91,
+91,
+92,
+92,
+92,
+92,
+92,
+93,
+93,
+93,
+93,
+93,
+94,
+94,
+94,
+94,
+94,
+95,
+95,
+95,
+95,
+95,
 0,
 0,
 0,
-0,
-0,
-1,
-1,
-1,
-1,
-1,
-2,
-2,
-2,
-2,
-2,
-3,
-3,
-3,
-3,
-3,
-4,
-4,
-4,
-4,
-4,
-5,
-5,
-5,
-5,
-5,
-6,
-6,
-6,
-6,
-6,
-7,
-7,
-7,
-7,
-7,
-8,
-8,
-8,
-8,
-8,
-9,
-9,
-9,
-9,
-9,
-10,
-10,
-10,
-10,
-10,
-11,
-11,
-11,
-11,
-11,
-12,
-12,
-12,
-12,
-12,
-13,
-13,
-13,
-13,
-13,
-14,
-14,
-14,
-14,
-14,
-15,
-15,
-15,
-15,
-15,
-16,
-16,
-16,
-16,
-16,
-17,
-17,
-17,
-17,
-17,
-18,
-18,
-18,
-18,
-18,
-19,
-19,
-19,
-19,
-19,
-20,
-20,
-20,
-20,
-20,
-21,
-21,
-21,
-21,
-21,
-22,
-22,
-22,
-22,
-22,
-23,
-23,
-23,
-23,
-23,
-24,
-24,
-24,
-24,
-24,
-25,
-25,
-25,
-25,
-25,
-26,
-26,
-26,
-26,
-26,
-27,
-27,
-27,
-27,
-27,
-28,
-28,
-28,
-28,
-28,
-29,
-29,
-29,
-29,
-29,
-30,
-30,
-30,
-30,
-30,
-31,
-31,
-31,
-31,
-31,
 0

+ 6 - 1
compiler/aarch64/ra64std.inc

@@ -64,6 +64,8 @@
 'x30',
 'wzr',
 'xzr',
+'wsp',
+'sp',
 'b0',
 'h0',
 's0',
@@ -224,4 +226,7 @@
 's31',
 'd31',
 'q31',
-'nzcv'
+'nzcv',
+'fpcr',
+'fpsr',
+'tpidr_el0'

+ 5 - 0
compiler/aarch64/ra64sup.inc

@@ -64,6 +64,8 @@ RS_W30 = $1E;
 RS_X30 = $1E;
 RS_WZR = $1F;
 RS_XZR = $1F;
+RS_WSP = $20;
+RS_SP = $20;
 RS_B0 = $00;
 RS_H0 = $00;
 RS_S0 = $00;
@@ -225,3 +227,6 @@ RS_S31 = $1F;
 RS_D31 = $1F;
 RS_Q31 = $1F;
 RS_NZCV = $00;
+RS_FPCR = $01;
+RS_FPSR = $02;
+RS_TPIDR_EL0 = $03;

+ 88 - 0
compiler/aarch64/racpu.pas

@@ -0,0 +1,88 @@
+{
+    Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+    Copyright (c) 2014 by Jonas Maebe
+
+    Handles the common AArch64 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 racpu;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      cgbase,
+      cpubase,
+      aasmtai,aasmdata,
+      rautils;
+
+    type
+      TAArch64Operand=class(TOperand)
+      end;
+
+      TAArch64Instruction=class(TInstruction)
+        oppostfix : toppostfix;
+        function ConcatInstruction(p:TAsmList) : tai;override;
+        function Is64bit: boolean;
+        function cgsize: tcgsize;
+      end;
+
+  implementation
+
+    uses
+      verbose,
+      aasmcpu;
+
+    function TAArch64Instruction.ConcatInstruction(p:TAsmList) : tai;
+      begin
+        result:=inherited ConcatInstruction(p);
+        taicpu(result).oppostfix:=oppostfix;
+      end;
+
+
+    function TAArch64Instruction.Is64bit: boolean;
+      begin
+        result:=
+          (operands[1].opr.typ=OPR_REGISTER) and
+          (getsubreg(operands[1].opr.reg)=R_SUBQ);
+      end;
+
+    function TAArch64Instruction.cgsize: tcgsize;
+      begin
+        if ops<1 then
+          internalerror(2014122001);
+        if operands[1].opr.typ<>OPR_REGISTER then
+          internalerror(2014122002);
+        result:=reg_cgsize(operands[1].opr.reg);
+        { a 32 bit integer register could actually be 16 or 8 bit }
+        if result=OS_32 then
+          case oppostfix of
+            PF_B:
+              result:=OS_8;
+            PF_SB:
+              result:=OS_S8;
+            PF_H:
+              result:=OS_16;
+            PF_SH:
+              result:=OS_S16;
+          end;
+      end;
+
+
+end.

+ 1053 - 0
compiler/aarch64/racpugas.pas

@@ -0,0 +1,1053 @@
+{
+    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+    Copyright (c) 2014 by Jonas Maebe
+
+    Does the parsing for the AArch64 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 racpugas;
+
+{$i fpcdefs.inc}
+
+  Interface
+
+    uses
+      raatt,racpu,
+      cpubase;
+
+    type
+      taarch64attreader = 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: taarch64operand; is64bit: boolean);
+        procedure BuildOperand(oper: taarch64operand; is64bit: boolean);
+        function TryBuildShifterOp(instr: taarch64instruction; opnr: longint) : boolean;
+        procedure BuildOpCode(instr: taarch64instruction);
+        procedure ReadSym(oper: taarch64operand; is64bit: boolean);
+        procedure ConvertCalljmp(instr: taarch64instruction);
+        function ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
+      end;
+
+
+  Implementation
+
+    uses
+      { helpers }
+      cutils,
+      { global }
+      globtype,verbose,
+      systems,aasmbase,aasmtai,aasmdata,aasmcpu,
+      { symtable }
+      symconst,symsym,
+      procinfo,
+      rabase,rautils,
+      cgbase,cgutils;
+
+
+    function taarch64attreader.is_register(const s:string):boolean;
+      type
+        treg2str = record
+          name : string[3];
+          reg : tregister;
+        end;
+
+      const
+        extraregs : array[0..3] of treg2str = (
+          (name: 'FP' ; reg: NR_FP),
+          (name: 'LR' ; reg: NR_LR),
+          (name: 'IP0'; reg: NR_IP0),
+          (name: 'IP1'; reg: NR_IP1));
+
+      var
+        i : longint;
+
+      begin
+        result:=inherited is_register(s);
+        { reg found?
+          possible aliases are always 2 or 3 chars
+        }
+        if result or not(length(s) in [2,3]) 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 taarch64attreader.ReadSym(oper: taarch64operand; is64bit: boolean);
+      var
+         tempstr, mangledname : string;
+         typesize,l,k: aint;
+      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,is64bit);
+            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 taarch64attreader.BuildReference(oper: taarch64operand; is64bit: boolean);
+
+      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);
+            if (actasmtoken=AS_NOT) then
+              begin
+                oper.opr.ref.addressmode:=AM_PREINDEXED;
+                Consume(AS_NOT);
+              end;
+          end;
+          if not(actasmtoken in [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;
+
+
+      function is_shifter_ref_operation(var a : tshiftmode) : boolean;
+        begin
+          a:=SM_NONE;
+          if (actasmpattern='LSL') then
+            a:=SM_LSL
+          else if (actasmpattern='UXTW') then
+            a:=SM_UXTW
+          else if (actasmpattern='SXTW') then
+            a:=SM_SXTW
+          else if (actasmpattern='SXTX') then
+            a:=SM_SXTX;
+          is_shifter_ref_operation:=not(a=SM_NONE);
+        end;
+
+
+      procedure read_index_shift(require_rbracket : boolean);
+        var
+          shift: aint;
+        begin
+          case actasmtoken of
+            AS_COMMA :
+              begin
+                Consume(AS_COMMA);
+                if not(actasmtoken=AS_ID) then
+                  do_error;
+                if is_shifter_ref_operation(oper.opr.ref.shiftmode) then
+                  begin
+                    Consume(actasmtoken);
+                    if actasmtoken=AS_HASH then
+                      begin
+                        Consume(AS_HASH);
+                        shift:=BuildConstExpression(false,true);
+                        if not(shift in [0,2+ord(is64bit)]) then
+                          do_error;
+                        oper.opr.ref.shiftimm:=shift;
+                        test_end(require_rbracket);
+                      end;
+                   end
+                 else
+                   begin
+                     do_error;
+                     exit;
+                   end;
+              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
+                if getsupreg(actasmregister)=RS_XZR then
+                  Message1(asmr_e_invalid_ref_register,actasmpattern);
+                oper.opr.ref.index:=actasmregister;
+                Consume(AS_REGISTER);
+                read_index_shift(require_rbracket);
+                exit;
+              end;
+            AS_HASH : // constant
+              begin
+                Consume(AS_HASH);
+(*
+                if actasmtoken=AS_COLON then
+                  begin
+                    consume(AS_COLON);
+                    { GNU-style lower 12 bits of address of non-GOT-based
+                      access }
+                    if (actasmpattern='LO12') then
+                      begin
+                        consume(actasmtoken);
+                        consume(AS_COLON);
+                        if not oper.SetupVar(actasmpattern,false) then
+                          begin
+                            do_error;
+                            exit
+                          end;
+                        consume(AS_ID);
+                        oper.opr.ref.refaddr:=addr_??? (not gotpageoffset);
+                      end
+                    else
+                      begin
+                        do_error;
+                        exit
+                      end;
+                  end
+                else
+*)
+                  begin
+                    o_int:=BuildConstExpression(false,true);
+                    inc(oper.opr.ref.offset,o_int);
+                  end;
+                test_end(require_rbracket);
+                exit;
+              end;
+            AS_ID :
+              begin
+                recname:=actasmpattern;
+                Consume(AS_ID);
+                { Apple-style got page offset }
+                if actasmtoken=AS_AT then
+                  begin
+                    if not oper.SetupVar(recname,false) then
+                      begin
+                        do_error;
+                        exit
+                      end;
+                    consume(AS_AT);
+                    if actasmpattern='GOTPAGEOFF' then
+                      begin
+                        consume(actasmtoken);
+                        oper.opr.ref.refaddr:=addr_gotpageoffset;
+                      end
+                    else if actasmpattern='PAGEOFF' then
+                      begin
+                        consume(actasmtoken);
+                        oper.opr.ref.refaddr:=addr_pageoffset;
+                      end
+                    else
+                      begin
+                        do_error;
+                        exit
+                      end;
+                  end
+                else
+                  begin
+                    BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
+                    inc(oper.opr.ref.offset,o_int);
+                  end;
+                test_end(require_rbracket);
+                exit;
+              end;
+            AS_AT:
+              begin
+                do_error;
+                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;
+
+
+      procedure try_prepostindexed;
+        begin
+          Consume(AS_RBRACKET);
+          case actasmtoken of
+            AS_COMMA :
+              begin // post-indexed
+                Consume(AS_COMMA);
+                oper.opr.ref.addressmode:=AM_POSTINDEXED;
+                read_index(false);
+                exit;
+              end;
+            AS_NOT :
+              begin   // pre-indexed
+                Consume(AS_NOT);
+                oper.opr.ref.addressmode:=AM_PREINDEXED;
+                test_end(false);
+                exit;
+              end;
+            else
+              begin
+                test_end(false);
+                exit;
+              end;
+          end; // case
+        end;
+
+      begin
+        Consume(AS_LBRACKET);
+        oper.opr.ref.addressmode:=AM_OFFSET; // assume "neither PRE nor POST inc"
+        if actasmtoken=AS_REGISTER then
+          begin
+            if getsupreg(actasmregister)=RS_XZR then
+              Message1(asmr_e_invalid_ref_register,actasmpattern);
+            oper.opr.ref.base:=actasmregister;
+            Consume(AS_REGISTER);
+            case actasmtoken of
+              AS_RBRACKET :
+                begin
+                  try_prepostindexed;
+                  exit;
+                end;
+              AS_COMMA :
+                begin
+                  Consume(AS_COMMA);
+                  read_index(true);
+                  exit;
+                end;
+              else
+                begin
+                  Message(asmr_e_invalid_reference_syntax);
+                  RecoverConsume(false);
+                end;
+            end;
+          end
+        else
+          Begin
+            case actasmtoken of
+              AS_ID :
+                begin
+                  { TODO: local variables and parameters }
+                  Message(asmr_e_invalid_reference_syntax);
+                  RecoverConsume(false);
+                  exit;
+                end;
+              else
+                begin // elsecase
+                  Message(asmr_e_invalid_reference_syntax);
+                  RecoverConsume(false);
+                  exit;
+                end;
+            end;
+          end;
+      end;
+
+
+    function taarch64attreader.TryBuildShifterOp(instr: taarch64instruction; opnr: longint): boolean;
+
+      procedure handlepara(sm : tshiftmode);
+        begin
+          consume(AS_ID);
+          fillchar(instr.operands[opnr].opr,sizeof(instr.operands[opnr].opr),0);
+          instr.operands[opnr].opr.typ:=OPR_SHIFTEROP;
+          instr.operands[opnr].opr.shifterop.shiftmode:=sm;
+          if (sm=SM_LSL) or
+             (actasmtoken=AS_HASH) then
+            begin
+              consume(AS_HASH);
+              instr.operands[opnr].opr.shifterop.shiftimm:=BuildConstExpression(false,false);
+            end;
+        end;
+
+      const
+        shiftmode2str: array[SM_LSL..SM_SXTX] of string[4] =
+          ('LSL','LSR','ASR',
+           'UXTB','UXTH','UXTW','UXTX',
+           'SXTB','SXTH','SXTW','SXTX');
+      var
+        sm: tshiftmode;
+        i: longint;
+        usessp,
+        useszr: boolean;
+      begin
+        result:=false;
+        if (actasmtoken=AS_ID) then
+          begin
+            for sm:=low(shiftmode2str) to high(shiftmode2str) do
+              if actasmpattern=shiftmode2str[sm] then
+                begin
+                  handlepara(sm);
+                  if instr.operands[1].opr.typ=OPR_REGISTER then
+                    begin
+                      { the possible shifter ops depend on whether this
+                        instruction uses sp and/or zr }
+                      usessp:=false;
+                      useszr:=false;
+                      for i:=low(instr.operands) to pred(opnr) do
+                        begin
+                          if (instr.operands[1].opr.typ=OPR_REGISTER) then
+                            case getsupreg(instr.operands[1].opr.reg) of
+                              RS_XZR:
+                                useszr:=true;
+                              RS_SP:
+                                usessp:=true;
+                            end;
+                        end;
+                      result:=valid_shifter_operand(instr.opcode,useszr,usessp,instr.Is64bit,sm,instr.operands[opnr].opr.shifterop.shiftimm);
+                    end
+                end;
+          end;
+      end;
+
+
+    function taarch64attreader.ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
+      begin
+        case actopcode of
+          A_CSEL,A_CSINC,A_CSINV,A_CSNEG,A_CSET,A_CSETM,
+          A_CINC,A_CINV,A_CNEG,A_CCMN,A_CCMP,
+          A_B:
+            begin
+              { search for condition, conditions are always 2 chars }
+              if (is_operand<>(actopcode=A_B)) and
+                 (length(hs)>1) then
+                begin
+                  { workaround for DFA bug }
+                  result:=low(tasmcond);
+                  for result:=low(tasmcond) to high(tasmcond) do
+                    begin
+                      if hs=uppercond2str[result] then
+                        exit;
+                    end;
+                end;
+            end;
+        end;
+        result:=C_None;;
+      end;
+
+
+    Procedure taarch64attreader.BuildOperand(oper: taarch64operand; is64bit: boolean);
+      var
+        expr: string;
+        typesize, l: aint;
+
+        procedure MaybeAddGotAddrMode;
+          begin
+            if actasmtoken=AS_AT then
+              begin
+                consume(AS_AT);
+                if actasmpattern='GOTPAGE' then
+                  oper.opr.ref.refaddr:=addr_gotpage
+                else if actasmpattern='GOTPAGEOFF' then
+                  oper.opr.ref.refaddr:=addr_gotpageoffset
+                else if actasmpattern='PAGE' then
+                  oper.opr.ref.refaddr:=addr_page
+                else if actasmpattern='PAGEOFF' then
+                  oper.opr.ref.refaddr:=addr_pageoffset
+                else
+                  Message(asmr_e_expr_illegal);
+                consume(actasmtoken);
+              end
+            else
+              oper.opr.ref.refaddr:=addr_pic;
+          end;
+
+        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 if (actopcode=A_ADR) or
+               (actopcode=A_ADRP) then
+              begin
+                oper.InitRef;
+                MaybeAddGotAddrMode;
+                oper.opr.ref.symbol:=hl;
+                if (actasmtoken in [AS_PLUS, AS_MINUS]) then
+                  begin
+                    l:=BuildConstExpression(true,false);
+                    oper.opr.ref.offset:=l;
+                  end;
+              end;
+          end;
+
+
+        procedure MaybeRecordOffset;
+          var
+            mangledname: string;
+            hasdot  : boolean;
+            l,
+            toffset,
+            tsize   : aint;
+          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(is64bit: boolean):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,is64bit);
+                end;
+              AS_LPAREN:
+                BuildReference(oper,is64bit);
+              AS_ID: { only a variable is allowed ... }
+                Begin
+                  ReadSym(oper,is64bit);
+                  case actasmtoken of
+                    AS_end,
+                    AS_SEPARATOR,
+                    AS_COMMA: ;
+                    AS_LPAREN:
+                      BuildReference(oper,is64bit);
+                  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;
+        icond: tasmcond;
+      Begin
+        expr:='';
+        case actasmtoken of
+          AS_LBRACKET: { Memory reference or constant expression }
+            Begin
+              oper.InitRef;
+              BuildReference(oper,is64bit);
+            end;
+
+          AS_HASH: { Constant expression  }
+            Begin
+              Consume(AS_HASH);
+              BuildConstantOperand(oper);
+            end;
+
+          (*
+          AS_INTNUM,
+          AS_MINUS,
+          AS_PLUS:
+            Begin
+              { Constant memory offset }
+              { This must absolutely be followed by (  }
+              oper.InitRef;
+              oper.opr.ref.offset:=BuildConstExpression(True,False);
+              if actasmtoken<>AS_LPAREN then
+                begin
+                  ofs:=oper.opr.ref.offset;
+                  BuildConstantOperand(oper);
+                  inc(oper.opr.val,ofs);
+                end
+              else
+                BuildReference(oper,is64bit);
+            end;
+          *)
+          AS_ID: { A constant expression, or a Variable ref.  }
+            Begin
+              { Condition code? }
+              icond:=ToConditionCode(actasmpattern,true);
+              if icond<>C_None then
+                begin
+                  oper.opr.typ:=OPR_COND;
+                  oper.opr.cc:=icond;
+                  consume(AS_ID);
+                end
+              else
+              { 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,is64bit);
+                       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
+                       else
+                         MaybeAddGotAddrMode;
+                     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,is64bit);
+            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 in [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;
+
+{*****************************************************************************
+                                taarch64attreader
+*****************************************************************************}
+
+    procedure taarch64attreader.BuildOpCode(instr: taarch64instruction);
+      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;
+        Consume(AS_OPCODE);
+
+        { We are reading operands, so opcode will be an AS_ID }
+        operandnum:=1;
+        { Zero operand opcode ?  }
+        if actasmtoken in [AS_SEPARATOR,AS_end] then
+         begin
+           instr.Ops:=0;
+           exit;
+         end;
+        { Read the operands }
+        repeat
+          case actasmtoken of
+            AS_COMMA: { Operand delimiter }
+              Begin
+                { operandnum and not operandnum+1, because tinstruction is
+                  one-based and taicpu is zero-based)
+                }
+                if can_be_shifter_operand(instr.opcode,operandnum) then
+                  begin
+                    Consume(AS_COMMA);
+                    if not TryBuildShifterOp(instr,operandnum+1) 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
+            begin
+              BuildOperand(taarch64operand(instr.operands[operandnum]),instr.Is64bit);
+              instr.Ops:=operandnum;
+              if instr.operands[operandnum].opr.typ=OPR_REFERENCE then
+                if simple_ref_type(instr.opcode,instr.cgsize,instr.oppostfix,instr.operands[operandnum].opr.ref)<>sr_simple then
+                  Message(asmr_e_invalid_reference_syntax);
+                ;
+            end;
+          end; { end case }
+        until false;
+      end;
+
+
+    function taarch64attreader.is_asmopcode(const s: string):boolean;
+
+      const
+        { sorted by length so longer postfixes will match first }
+        postfix2strsorted : array[1..7] of string[3] = (
+          'SB','SH','SW',
+          'B','H','W',
+          'S');
+
+        postfixsorted : array[1..7] of TOpPostfix = (
+          PF_SB,PF_SH,PF_SW,
+          PF_B,PF_H,PF_W,
+          PF_S);
+
+      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 opcode }
+        actopcode:=A_None;
+        actcondition:=C_None;
+
+        { b.cond ? }
+        if (length(hs)=4) and
+           (hs[1]='B') and
+           (hs[2]='.') then
+          begin
+            actopcode:=A_B;
+            actasmtoken:=AS_OPCODE;
+            actcondition:=ToConditionCode(copy(hs,3,length(actasmpattern)-2),false);
+            if actcondition<>C_None then
+              is_asmopcode:=true;
+            exit;
+          end;
+
+        maxlen:=max(length(hs),7);
+        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;
+
+        { check for postfix }
+        if length(hs)>0 then
+          begin
+            for j:=low(postfixsorted) to high(postfixsorted) do
+              begin
+                if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                  begin
+                    actoppostfix:=postfixsorted[j];
+                    { strip postfix }
+                    delete(hs,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 taarch64attreader.ConvertCalljmp(instr: taarch64instruction);
+      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) or
+              (instr.Operands[1].opr.ref.refaddr<>addr_pic) then
+              Message(asmr_e_syn_operand);
+            instr.Operands[1].opr:=newopr;
+          end;
+      end;
+
+    procedure taarch64attreader.handleopcode;
+      var
+        instr: taarch64instruction;
+      begin
+        instr:=taarch64instruction.Create(taarch64operand);
+        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_arm_att_info : tasmmodeinfo =
+          (
+            id    : asmmode_arm_gas;
+            idtxt : 'GAS';
+            casmreader : taarch64attreader;
+          );
+
+  asmmode_arm_standard_info : tasmmodeinfo =
+          (
+            id    : asmmode_standard;
+            idtxt : 'STANDARD';
+            casmreader : taarch64attreader;
+          );
+
+initialization
+  RegisterAsmMode(asmmode_arm_att_info);
+  RegisterAsmMode(asmmode_arm_standard_info);
+end.

+ 171 - 0
compiler/aarch64/rgcpu.pas

@@ -0,0 +1,171 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    This unit implements the SPARC 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,aasmcpu,aasmtai,aasmdata,
+      cgbase,cgutils,
+      cpubase,
+      globtype,
+      rgobj;
+
+    type
+      trgcpu=class(trgobj)
+        procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
+        procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
+       protected
+        procedure do_spill_op(list: tasmlist; op: tasmop; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
+      end;
+
+      trgintcpu=class(trgcpu)
+        procedure add_cpu_interferences(p: tai); override;
+      end;
+
+
+implementation
+
+    uses
+      verbose,cutils,
+      cgobj;
+
+    procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
+      begin
+        do_spill_op(list,A_LDR,pos,spilltemp,tempreg,orgsupreg);
+      end;
+
+
+    procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
+      begin
+        do_spill_op(list,A_STR,pos,spilltemp,tempreg,orgsupreg);
+      end;
+
+
+    procedure trgcpu.do_spill_op(list: tasmlist; op: tasmop; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
+      var
+        helpins  : tai;
+        tmpref   : treference;
+        helplist : TAsmList;
+        hreg     : tregister;
+        isload   : boolean;
+      begin
+        isload:=op=A_LDR;
+        { offset out of range for regular load/store? }
+        if simple_ref_type(op,reg_cgsize(tempreg),PF_None,spilltemp)<>sr_simple then
+          begin
+            helplist:=TAsmList.create;
+
+            if getregtype(tempreg)=R_INTREGISTER then
+              hreg:=tempreg
+            else
+              hreg:=cg.getaddressregister(helplist);
+
+            cg.a_load_const_reg(helplist,OS_ADDR,spilltemp.offset,hreg);
+            reference_reset_base(tmpref,spilltemp.base,0,sizeof(pint));
+            tmpref.index:=hreg;
+            if isload then
+              helpins:=spilling_create_load(tmpref,tempreg)
+            else
+              helpins:=spilling_create_store(tempreg,tmpref);
+            helplist.concat(helpins);
+            add_cpu_interferences(helpins);
+            list.insertlistafter(pos,helplist);
+            helplist.free;
+          end
+        else if isload then
+          inherited do_spill_read(list,pos,spilltemp,tempreg,orgsupreg)
+        else
+          inherited do_spill_written(list,pos,spilltemp,tempreg,orgsupreg)
+      end;
+
+
+    procedure trgintcpu.add_cpu_interferences(p: tai);
+     var
+       i, j: longint;
+     begin
+       if p.typ=ait_instruction then
+         begin
+           { add interferences for instructions that can have SP as a register
+             operand }
+           case taicpu(p).opcode of
+             A_MOV:
+               { all operands can be SP }
+               exit;
+             A_ADD,
+             A_SUB,
+             A_CMP,
+             A_CMN:
+               { ok as destination or first source in immediate or extended
+                 register form }
+               if (taicpu(p).oper[taicpu(p).ops-1]^.typ<>top_shifterop) or
+                  valid_shifter_operand(taicpu(p).opcode,false,true,
+                    reg_cgsize(taicpu(p).oper[0]^.reg) in [OS_64,OS_S64],
+                    taicpu(p).oper[taicpu(p).ops-1]^.shifterop^.shiftmode,
+                    taicpu(p).oper[taicpu(p).ops-1]^.shifterop^.shiftimm) then
+                 begin
+                   if taicpu(p).oper[taicpu(p).ops-1]^.typ=top_shifterop then
+                     i:=taicpu(p).ops-2
+                   else
+                     i:=taicpu(p).ops-1;
+                   if (taicpu(p).oper[i]^.typ=top_reg) then
+                     add_edge(getsupreg(taicpu(p).oper[i]^.reg),RS_SP);
+                   exit;
+                 end;
+             A_AND,
+             A_EOR,
+             A_ORR,
+             A_TST:
+               { ok in immediate form }
+               if taicpu(p).oper[taicpu(p).ops-1]^.typ=top_const then
+                 exit;
+           end;
+           { add interferences for other registers }
+           for i:=0 to taicpu(p).ops-1 do
+             begin
+               case taicpu(p).oper[i]^.typ of
+                 top_reg:
+                   if getregtype(taicpu(p).oper[i]^.reg)=R_INTREGISTER then
+                     add_edge(getsupreg(taicpu(p).oper[i]^.reg),RS_SP);
+                 top_ref:
+                   begin
+                     { sp can always be base, never be index }
+                     if taicpu(p).oper[i]^.ref^.index<>NR_NO then
+                       add_edge(getsupreg(taicpu(p).oper[i]^.ref^.index),RS_SP);
+                     { in case of write back, the base register must be
+                       different from the loaded/stored register }
+                     if (taicpu(p).oper[i]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
+                        (taicpu(p).oper[i]^.ref^.base<>NR_NO) then
+                       begin
+                         for j:=pred(i) downto 0 do
+                           if taicpu(p).oper[j]^.typ=TOP_REG then
+                             add_edge(getsupreg(taicpu(p).oper[j]^.reg),getsupreg(taicpu(p).oper[i]^.ref^.base));
+                       end;
+                   end;
+               end;
+             end;
+         end;
+     end;
+
+end.

+ 4 - 0
compiler/aarch64/symcpu.pas

@@ -94,6 +94,9 @@ type
   tcpuunitsym = class(tunitsym)
   end;
 
+  tcpuprogramparasym = class(tprogramparasym)
+  end;
+
   tcpunamespacesym = class(tnamespacesym)
   end;
 
@@ -162,6 +165,7 @@ begin
   { used tsym classes }
   clabelsym:=tcpulabelsym;
   cunitsym:=tcpuunitsym;
+  cprogramparasym:=tcpuprogramparasym;
   cnamespacesym:=tcpunamespacesym;
   cprocsym:=tcpuprocsym;
   ctypesym:=tcputypesym;

+ 65 - 24
compiler/aasmbase.pas

@@ -40,7 +40,12 @@ interface
        TAsmsymbind=(
          AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL,AB_WEAK_EXTERNAL,
          { global in the current program/library, but not visible outside it }
-         AB_PRIVATE_EXTERN,AB_LAZY,AB_IMPORT);
+         AB_PRIVATE_EXTERN,AB_LAZY,AB_IMPORT,
+         { a symbol that's internal to the compiler and used as a temp }
+         AB_TEMP,
+         { a global symbol that points to another global symbol and is only used
+           to allow indirect loading in case of packages and indirect imports }
+         AB_INDIRECT,AB_EXTERNAL_INDIRECT);
 
        TAsmsymtype=(
          AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION,AT_LABEL,
@@ -62,6 +67,10 @@ interface
 
     const
        asmlabeltypeprefix : array[TAsmLabeltype] of char = ('j','a','d','l','f','t','c');
+       asmsymbindname : array[TAsmsymbind] of string[23] = ('none', 'external','common',
+       'local','global','weak external','private external','lazy','import','internal temp',
+       'indirect','external indirect');
+       asmsymbindindirect = [AB_INDIRECT,AB_EXTERNAL_INDIRECT];
 
     type
        TAsmSectiontype=(sec_none,
@@ -94,6 +103,8 @@ interface
          sec_debug_info,
          sec_debug_line,
          sec_debug_abbrev,
+         sec_debug_aranges,
+         sec_debug_ranges,
          { Yury: "sec_fpc is intended for storing fpc specific data
                   which must be recognized and processed specially by linker.
                   Currently fpc version string, dummy links to stab sections
@@ -142,9 +153,13 @@ interface
          sec_objc_nlcatlist,
          sec_objc_protolist,
          { stack segment for 16-bit DOS }
-         sec_stack
+         sec_stack,
+         { initial heap segment for 16-bit DOS }
+         sec_heap
        );
 
+       TObjCAsmSectionType = sec_objc_class..sec_objc_protolist;
+
        TAsmSectionOrder = (secorder_begin,secorder_default,secorder_end);
 
        TAsmSymbol = class(TFPHashObject)
@@ -160,6 +175,10 @@ interface
 {$endif AVR}
          bind       : TAsmsymbind;
          typ        : TAsmsymtype;
+{$ifdef llvm}
+         { have we generated a declaration for this symbol? }
+         declared   : boolean;
+{$endif llvm}
          { Alternate symbol which can be used for 'renaming' needed for
            asm inlining. Also used for external and common solving during linking }
          altsymbol  : TAsmSymbol;
@@ -177,12 +196,21 @@ interface
        TAsmLabel = class(TAsmSymbol)
        protected
          function getname:TSymStr;override;
+         {$push}{$warnings off}
+         { new visibility section to let "warnings off" take effect }
+       protected
+         { this constructor is only supposed to be used internally by
+           createstatoc/createlocal -> disable warning that constructors should
+           be public }
+         constructor create_non_global(AList: TFPHashObjectList; nr: longint; ltyp: TAsmLabelType; const prefix: TSymStr);
        public
+         {$pop}
          labelnr   : longint;
          labeltype : TAsmLabelType;
          is_set    : boolean;
-         constructor Createlocal(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
-         constructor Createglobal(AList:TFPHashObjectList;const modulename:TSymStr;nr:longint;ltyp:TAsmLabelType);
+         constructor Createlocal(AList: TFPHashObjectList; nr: longint; ltyp: TAsmLabelType);
+         constructor Createstatic(AList: TFPHashObjectList; nr: longint; ltyp: TAsmLabelType);
+         constructor Createglobal(AList: TFPHashObjectList; const modulename: TSymStr; nr: longint; ltyp: TAsmLabelType);
          function getaltcopy(AList:TFPHashObjectList;altnr: longint): TAsmSymbol; override;
        end;
 
@@ -195,7 +223,7 @@ interface
     function EncodeUleb128(a: qword;out buf) : byte;
     function EncodeSleb128(a: int64;out buf) : byte;
 
-    function ReplaceForbiddenAsmSymbolChars(const s: string): string;
+    function ReplaceForbiddenAsmSymbolChars(const s: ansistring): ansistring;
 
     { dummy default noop callback }
     procedure default_global_used;
@@ -346,7 +374,7 @@ implementation
       end;
 
 
-    function ReplaceForbiddenAsmSymbolChars(const s: string): string;
+    function ReplaceForbiddenAsmSymbolChars(const s: ansistring): ansistring;
       var
         i : longint;
         rchar: char;
@@ -409,22 +437,15 @@ implementation
                                  TAsmLabel
 *****************************************************************************}
 
-    constructor TAsmLabel.Createlocal(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
-      var
-        asmtyp: TAsmsymtype;
+    constructor TAsmLabel.Createlocal(AList: TFPHashObjectList; nr: longint; ltyp: TAsmLabelType);
       begin
-        case ltyp of
-          alt_addr:
-            asmtyp:=AT_ADDR;
-          alt_data:
-            asmtyp:=AT_DATA;
-          else
-            asmtyp:=AT_LABEL;
-        end;
-        inherited Create(AList,target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,asmtyp);
-        labelnr:=nr;
-        labeltype:=ltyp;
-        is_set:=false;
+        create_non_global(AList,nr,ltyp,target_asm.labelprefix);
+      end;
+
+
+    constructor TAsmLabel.Createstatic(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
+      begin
+        create_non_global(AList,nr,ltyp,'_$$fpclocal$_l');
       end;
 
 
@@ -464,8 +485,28 @@ implementation
         increfs;
       end;
 
-	procedure default_global_used;
-	  begin
-	  end;
+
+    constructor TAsmLabel.create_non_global(AList: TFPHashObjectList; nr: longint; ltyp: TAsmLabelType; const prefix: TSymStr);
+      var
+        asmtyp: TAsmsymtype;
+      begin
+        case ltyp of
+          alt_addr:
+            asmtyp:=AT_ADDR;
+          alt_data:
+            asmtyp:=AT_DATA;
+          else
+            asmtyp:=AT_LABEL;
+        end;
+        inherited Create(AList,prefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,asmtyp);
+        labelnr:=nr;
+        labeltype:=ltyp;
+        is_set:=false;
+      end;
+
+
+    procedure default_global_used;
+      begin
+      end;
 
 end.

+ 1950 - 0
compiler/aasmcnst.pas

@@ -0,0 +1,1950 @@
+{
+    Copyright (c) 2014 by Jonas Maebe, member of the Free Pascal development
+    team
+
+    This unit implements typed constant data elements at the assembler level
+
+    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 aasmcnst;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  cclasses,globtype,constexp,
+  aasmbase,aasmdata,aasmtai,
+  symconst,symbase,symtype,symdef,symsym;
+
+type
+   { typed const: integer/floating point/string/pointer/... const along with
+     tdef info }
+   ttypedconstkind = (tck_simple, tck_array, tck_record);
+
+   { the type of the element and its def }
+   tai_abstracttypedconst = class abstract (tai)
+    private
+     procedure setdef(def: tdef);
+    protected
+     fadetyp: ttypedconstkind;
+     { the def of this element }
+     fdef: tdef;
+    public
+     constructor create(_adetyp: ttypedconstkind; _def: tdef);
+     property adetyp: ttypedconstkind read fadetyp;
+     property def: tdef read fdef write setdef;
+   end;
+
+   { a simple data element; the value is stored as a tai }
+   tai_simpletypedconst = class(tai_abstracttypedconst)
+   private
+     procedure setval(AValue: tai);
+    protected
+     fval: tai;
+    public
+     constructor create(_adetyp: ttypedconstkind; _def: tdef; _val: tai);
+     property val: tai read fval write setval;
+   end;
+
+
+   { an aggregate data element (record or array). Values are stored as an
+     array of tsimpledataelement. }
+   tai_aggregatetypedconst = class(tai_abstracttypedconst)
+    public type
+     { iterator to walk over all individual items in the aggregate }
+     tadeenumerator = class(tobject)
+      private
+       fvalues: tfplist;
+       fvaluespos: longint;
+       function getcurrent: tai_abstracttypedconst;
+      public
+       constructor create(data: tai_aggregatetypedconst);
+       function movenext: boolean;
+       procedure reset;
+       property current: tai_abstracttypedconst read getcurrent;
+     end;
+
+    protected
+     fvalues: tfplist;
+     fisstring: boolean;
+
+     { converts the existing data to a single tai_string }
+     procedure convert_to_string;
+     procedure add_to_string(strtai: tai_string; othertai: tai);
+    public
+     constructor create(_adetyp: ttypedconstkind; _fdef: tdef);
+     function getenumerator: tadeenumerator;
+     procedure addvalue(val: tai_abstracttypedconst);
+     function valuecount: longint;
+     procedure insertvaluebeforepos(val: tai_abstracttypedconst; pos: longint);
+     function replacevalueatpos(val: tai_abstracttypedconst; pos: longint): tai_abstracttypedconst;
+     { change the type to a record, regardless of how the aggregate was created;
+       the size of the original type and the record must match }
+     procedure changetorecord(_def: trecorddef);
+     procedure finish;
+     destructor destroy; override;
+   end;
+
+
+    tasmlabofs = record
+      lab: tasmlabel;
+      ofs: asizeint;
+    end;
+
+   { flags for the finalisation of the typed const builder asmlist }
+   ttcasmlistoption = (
+     { the tasmsymbol is a tasmlabel }
+     tcalo_is_lab,
+     { start a new section (e.g., because we don't know the current section
+       type) }
+     tcalo_new_section,
+     { this symbol is the start of a block of data that should be
+       dead-stripable/smartlinkable; may imply starting a new section, but
+       not necessarily (depends on what the platform requirements are) }
+     tcalo_make_dead_strippable,
+     { this symbol should never be removed by the linker }
+     tcalo_no_dead_strip,
+     { start of a vectorized but individually dead strippable list of elements,
+       like the resource strings of a unit: they have to stay in this order,
+       but individual elements can be removed }
+     tcalo_vectorized_dead_strip_start,
+     { item in the above list }
+     tcalo_vectorized_dead_strip_item,
+     { end of the above list }
+     tcalo_vectorized_dead_strip_end,
+     { symbol should be weakle defined }
+     tcalo_weak
+   );
+   ttcasmlistoptions = set of ttcasmlistoption;
+
+
+   { information about aggregates we are parsing }
+   taggregateinformation = class
+    private
+     fnextfieldname: TIDString;
+     function getcuroffset: asizeint;
+     procedure setnextfieldname(AValue: TIDString);
+    protected
+     { type of the aggregate }
+     fdef: tdef;
+     { type of the aggregate }
+     ftyp: ttypedconstkind;
+     { symtable entry of the previously emitted field in case of a
+       record/object (nil if none emitted yet), used to insert alignment bytes
+       if necessary for variant records and objects }
+     fcurfield,
+     { field corresponding to the data that will be emitted next in case of a
+       record/object (nil if not set), used to handle variant records and
+       objects }
+     fnextfield: tfieldvarsym;
+     { similar as the fcurfield/fnextfield above, but instead of fieldvarsyms
+       these are indices in the symlist of a recorddef that correspond to
+       fieldvarsyms. These are used only for non-variant records, simply
+       traversing the fields in order. We could use the above method here as
+       well, but to find the next field we'd always have to use
+       symlist.indexof(fcurfield), which would be quite slow. These have -1 as
+       value if they're not set }
+     fcurindex,
+     fnextindex: longint;
+     { anonymous record that is being built as we add constant data }
+     fanonrecord: boolean;
+
+     property curindex: longint read fcurindex write fcurindex;
+     property nextindex: longint read fnextindex write fnextindex;
+    public
+     constructor create(_def: tdef; _typ: ttypedconstkind); virtual;
+     { calculated padding bytes for alignment if needed, and add the def of the
+       next field in case we are constructing an anonymous record }
+     function prepare_next_field(nextfielddef: tdef): asizeint; virtual;
+
+     property def: tdef read fdef;
+     property typ: ttypedconstkind read ftyp;
+     property curfield: tfieldvarsym read fcurfield write fcurfield;
+     property nextfield: tfieldvarsym read fnextfield write fnextfield;
+     property nextfieldname: TIDString write setnextfieldname;
+     property curoffset: asizeint read getcuroffset;
+     property anonrecord: boolean read fanonrecord write fanonrecord;
+   end;
+   taggregateinformationclass = class of taggregateinformation;
+
+   { information about a placeholder element that has been added, and which has
+     to be replaced later with a real data element }
+   ttypedconstplaceholder = class abstract
+     def: tdef;
+     constructor create(d: tdef);
+     { same usage as ttai_typedconstbuilder.emit_tai }
+     procedure replace(ai: tai; d: tdef); virtual; abstract;
+   end;
+
+   { Warning: never directly create a ttai_typedconstbuilder instance,
+     instead create a cai_typedconstbuilder (this class can be overridden) }
+   ttai_typedconstbuilder = class abstract
+    { class type to use when creating new aggregate information instances }
+    protected class var
+     caggregateinformation: taggregateinformationclass;
+    private
+     function getcurragginfo: taggregateinformation;
+     procedure set_next_field(AValue: tfieldvarsym);
+     procedure set_next_field_name(AValue: TIDString);
+    protected
+     { temporary list in which all data is collected }
+     fasmlist: tasmlist;
+     { options for the final asmlist }
+     foptions: ttcasmlistoptions;
+
+     { while queueing elements of a compound expression, this is the current
+       offset in the top-level array/record }
+     fqueue_offset: asizeint;
+     fqueued_def: tdef;
+
+     { array of caggregateinformation instances }
+     faggregateinformation: tfpobjectlist;
+
+    { Support for generating data that is only referenced from the typed
+      constant data that we are currently generated. Such data can all be put
+      in the same dead-strippable unit, as it's either all included or none of
+      it is included. This data can be spread over multiple kinds of sections
+      though (e.g. rodata and rodata_no_rel), so per section keep track whether
+      we already started a dead-strippable unit and if so, what the section
+      name was (so that on platforms that perform the dead stripping based on
+      sections, we put all data for one typed constant into a single section
+      with the same name) }
+    protected type
+     tinternal_data_section_info = record
+       secname: TSymStr;
+       sectype: TAsmSectiontype;
+     end;
+    protected var
+     { all internally generated data must be stored in the same list, as it must
+       be consecutive (if it's spread over multiple lists, we don't know in
+       which order they'll be concatenated) -> keep track of this list }
+     finternal_data_asmlist: tasmlist;
+     { kind of the last section we started in the finternal_data_asmlist, to
+       avoid creating unnecessary section statements }
+     finternal_data_current_section: TAsmSectiontype;
+     { info about in which kinds of sections we have already emitted internal
+       data, and what their names were }
+     finternal_data_section_info: array of tinternal_data_section_info;
+
+     { ensure that finalize_asmlist is called only once }
+     fasmlist_finalized: boolean;
+     { ensure that if it's vectorized dead strippable data, we called
+       finalize_vectorized_dead_strip_asmlist instead of finalize_asmlist }
+     fvectorized_finalize_called: boolean;
+
+     { returns whether def must be handled as an aggregate on the current
+       platform }
+     function aggregate_kind(def: tdef): ttypedconstkind; virtual;
+     { finalize the asmlist: add the necessary symbols etc }
+     procedure finalize_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: shortint; const options: ttcasmlistoptions); virtual;
+     { functionality of the above for vectorized dead strippable sections }
+     procedure finalize_vectorized_dead_strip_asmlist(def: tdef; const basename, itemname: TSymStr; st: tsymtable; alignment: shortint; options: ttcasmlistoptions); virtual;
+
+     { called by the public emit_tai() routines to actually add the typed
+       constant data; the public ones also take care of adding extra padding
+       bytes etc (by calling this one) }
+     procedure do_emit_tai(p: tai; def: tdef); virtual;
+
+     { calls prepare_next_field() and adds the padding bytes in the current
+       location }
+     procedure pad_next_field(nextfielddef: tdef);
+
+     { returns the index in finternal_data_section_info of the info for the
+       section of type typ. Returns -1 if there is no such info yet }
+     function get_internal_data_section_index(typ: TAsmSectiontype): longint;
+
+     { get a start label for an internal data section (at the start of a
+       potentially dead-strippable part) }
+     function get_internal_data_section_start_label: tasmlabel; virtual;
+     { get a label in the middle of an internal data section (no dead
+       stripping) }
+     function get_internal_data_section_internal_label: tasmlabel; virtual;
+
+     { easy access to the top level aggregate information instance }
+     property curagginfo: taggregateinformation read getcurragginfo;
+    public
+     constructor create(const options: ttcasmlistoptions); virtual;
+     destructor destroy; override;
+
+    public
+     { returns a builder for generating data that is only referrenced by the
+       typed constant date we are currently generating (e.g. string data for a
+       pchar constant). Also returns the label that will be placed at the start
+       of that data. list is the tasmlist to which the data will be added.
+       secname can be empty to use a default }
+     procedure start_internal_data_builder(list: tasmlist; sectype: TAsmSectiontype; const secname: TSymStr; out tcb: ttai_typedconstbuilder; out l: tasmlabel);
+     { finish a previously started internal data builder, including
+       concatenating all generated data to the provided list and freeing the
+       builder }
+     procedure finish_internal_data_builder(var tcb: ttai_typedconstbuilder; l: tasmlabel; def: tdef; alignment: longint);
+
+     { add a simple constant data element (p) to the typed constant.
+       def is the type of the added value }
+     procedure emit_tai(p: tai; def: tdef); virtual;
+     { same as above, for a special case: when the def is a procvardef and we
+       want to use it explicitly as a procdef (i.e., not as a record with a
+       code and data pointer in case of a complex procvardef) }
+     procedure emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef); virtual;
+
+    protected
+     procedure maybe_emit_tail_padding(def: tdef); virtual;
+     function emit_string_const_common(stringtype: tstringtype; len: asizeint; encoding: tstringencoding; var startlab: tasmlabel):tasmlabofs;
+     function get_dynstring_def_for_type(stringtype: tstringtype; winlikewidestring: boolean): tstringdef;
+     procedure begin_aggregate_internal(def: tdef; anonymous: boolean); virtual;
+     procedure end_aggregate_internal(def: tdef; anonymous: boolean); virtual;
+     { when building an anonymous record, we cannot immediately insert the
+       alignment before it in case it's nested, since we only know the required
+       alignment once all fields have been inserted -> mark the location before
+       the anonymous record, and insert the alignment once it's finished }
+     procedure mark_anon_aggregate_alignment; virtual; abstract;
+     procedure insert_marked_aggregate_alignment(def: tdef); virtual; abstract;
+     class function get_vectorized_dead_strip_section_symbol(const basename: string; st: tsymtable; define, start: boolean): tasmsymbol; virtual;
+    public
+     class function get_vectorized_dead_strip_custom_section_name(const basename: TSymStr; st: tsymtable; out secname: TSymStr): boolean; virtual;
+     { get the start/end symbol for a dead stripable vectorized section, such
+       as the resourcestring data of a unit }
+     class function get_vectorized_dead_strip_section_symbol_start(const basename: string; st: tsymtable; define: boolean): tasmsymbol; virtual;
+     class function get_vectorized_dead_strip_section_symbol_end(const basename: string; st: tsymtable; define: boolean): tasmsymbol; virtual;
+
+     class function get_dynstring_rec_name(typ: tstringtype; winlike: boolean; len: asizeint): string;
+     { the datalist parameter specifies where the data for the string constant
+       will be emitted (via an internal data builder) }
+     function emit_ansistring_const(datalist: TAsmList; data: pchar; len: asizeint; encoding: tstringencoding): tasmlabofs;
+     function emit_unicodestring_const(datalist: TAsmList; data: pointer; encoding: tstringencoding; winlike: boolean):tasmlabofs;
+     { emits a tasmlabofs as returned by emit_*string_const }
+     procedure emit_string_offset(const ll: tasmlabofs; const strlength: longint; const st: tstringtype; const winlikewidestring: boolean; const charptrdef: tdef);virtual;
+
+     { emit a shortstring constant, and return its def }
+     function emit_shortstring_const(const str: shortstring): tdef;
+     { emit a pchar string constant (the characters, not a pointer to them), and return its def }
+     function emit_pchar_const(str: pchar; len: pint): tdef;
+     { emit a guid constant }
+     procedure emit_guid_const(const guid: tguid);
+     { emit a procdef constant }
+     procedure emit_procdef_const(pd: tprocdef);
+     { emit an ordinal constant }
+     procedure emit_ord_const(value: int64; def: tdef);
+
+     { begin a potential aggregate type. Must be called for any type
+       that consists of multiple tai constant data entries, or that
+       represents an aggregate at the Pascal level (a record, a non-dynamic
+       array, ... }
+     procedure maybe_begin_aggregate(def: tdef);
+     { end a potential aggregate type. Must be paired with every
+       maybe_begin_aggregate }
+     procedure maybe_end_aggregate(def: tdef);
+     { similar as above, but in case
+        a) it's definitely a record
+        b) the def of the record should be automatically constructed based on
+           the types of the emitted fields
+
+        packrecords: same as "pacrecords x"
+        recordalign: specify the (minimum) alignment of the start of the record
+          (no equivalent in source code), used as an alternative for explicit
+          align statements. Use "1" if it should be calculated based on the
+          fields
+        recordalignmin: same as "codealign recordmin=x"
+        maxcrecordalign: specify maximum C record alignment (no equivalent in
+          source code)
+     }
+     function begin_anonymous_record(const optionalname: string; packrecords, recordalign, recordalignmin, maxcrecordalign: shortint): trecorddef; virtual;
+     function end_anonymous_record: trecorddef; virtual;
+
+     { add a placeholder element at the current position that later can be
+       filled in with the actual data (via ttypedconstplaceholder.replace)
+
+       useful in case you have table preceded by the number of elements, and
+       you cound the elements while building the table }
+     function emit_placeholder(def: tdef): ttypedconstplaceholder; virtual; abstract;
+    protected
+     { common code to check whether a placeholder can be added at the current
+       position }
+     procedure check_add_placeholder(def: tdef);
+    public
+     { The next group of routines are for constructing complex expressions.
+       While parsing a typed constant these operators are encountered from
+       outer to inner, so that is also the order in which they should be
+       added to the queue. Only one queue can be active at a time. }
+     { Init the queue. Gives an internalerror if a queue was already active }
+     procedure queue_init(todef: tdef); virtual;
+     { queue an array/string indexing operation (performs all range checking,
+       so it doesn't have to be duplicated in all descendents). }
+     procedure queue_vecn(def: tdef; const index: tconstexprint); virtual;
+     { queue a subscripting operation }
+     procedure queue_subscriptn(def: tabstractrecorddef; vs: tfieldvarsym); virtual;
+     { queue indexing a record recursively via several field names. The fields
+       are specified in the inner to outer order (i.e., def.field1.field2) }
+     function queue_subscriptn_multiple_by_name(def: tabstractrecorddef; const fields: array of TIDString): tdef;
+     { queue a type conversion operation }
+     procedure queue_typeconvn(fromdef, todef: tdef); virtual;
+     { finalise the queue (so a new one can be created) and flush the
+        previously queued operations, applying them in reverse order on a...}
+     { ... procdef }
+     procedure queue_emit_proc(pd: tprocdef); virtual;
+     { ... staticvarsym }
+     procedure queue_emit_staticvar(vs: tstaticvarsym); virtual;
+     { ... labelsym }
+     procedure queue_emit_label(l: tlabelsym); virtual;
+     { ... constsym }
+     procedure queue_emit_const(cs: tconstsym); virtual;
+     { ... asmsym/asmlabel }
+     procedure queue_emit_asmsym(sym: tasmsymbol; def: tdef); virtual;
+     { ... an ordinal constant }
+     procedure queue_emit_ordconst(value: int64; def: tdef); virtual;
+    protected
+     { returns whether queue_init has been called without a corresponding
+       queue_emit_* to finish it }
+     function queue_is_active: boolean;
+    public
+
+     { finalize the internal asmlist (if necessary) and return it.
+       This asmlist will be freed when the builder is destroyed, so add its
+       contents to another list first. This property should only be accessed
+       once all data has been added. }
+     function get_final_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: longint): tasmlist;
+     function get_final_asmlist_vectorized_dead_strip(def: tdef; const basename, itemname: TSymStr; st: TSymtable; alignment: longint): tasmlist;
+
+     { returns the offset of the string data relative to ansi/unicode/widestring
+       constant labels. On most platforms, this is 0 (with the header at a
+       negative offset), but on some platforms such negative offsets are not
+       supported this is equal to the header size }
+     class function get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint; virtual;
+
+     { set the fieldvarsym whose data we will emit next; needed
+       in case of variant records, so we know which part of the variant gets
+       initialised. Also in case of objects, because the fieldvarsyms are spread
+       over the symtables of the entire inheritance tree }
+     property next_field: tfieldvarsym write set_next_field;
+     { set the name of the next field that will be emitted for an anonymous
+       record (also if that field is a nested anonymous record) }
+     property next_field_name: TIDString write set_next_field_name;
+    protected
+     { this one always return the actual offset, called by the above (and
+       overridden versions) }
+     class function get_string_header_size(typ: tstringtype; winlikewidestring: boolean): pint;
+   end;
+   ttai_typedconstbuilderclass = class of ttai_typedconstbuilder;
+
+   tlowlevelaggregateinformation = class(taggregateinformation)
+    protected
+     fanonrecmarker: tai;
+    public
+     property anonrecmarker: tai read fanonrecmarker write fanonrecmarker;
+   end;
+
+   tlowleveltypedconstplaceholder = class(ttypedconstplaceholder)
+     list: tasmlist;
+     insertpos: tai;
+     constructor create(l: tasmlist; pos: tai; d: tdef);
+     procedure replace(ai: tai; d: tdef); override;
+   end;
+
+   ttai_lowleveltypedconstbuilder = class(ttai_typedconstbuilder)
+    protected
+     procedure mark_anon_aggregate_alignment; override;
+     procedure insert_marked_aggregate_alignment(def: tdef); override;
+     procedure finalize_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: shortint; const options: ttcasmlistoptions); override;
+    public
+     { set the default value for caggregateinformation (= tlowlevelaggregateinformation) }
+     class constructor classcreate;
+     function emit_placeholder(def: tdef): ttypedconstplaceholder; override;
+   end;
+
+   var
+     ctai_typedconstbuilder: ttai_typedconstbuilderclass;
+
+implementation
+
+   uses
+     verbose,globals,systems,widestr,
+     fmodule,
+     symtable,defutil;
+
+{****************************************************************************
+                       taggregateinformation
+ ****************************************************************************}
+
+    function taggregateinformation.getcuroffset: asizeint;
+      var
+        field: tfieldvarsym;
+      begin
+        if assigned(curfield) then
+          result:=curfield.fieldoffset+curfield.vardef.size
+        else if curindex<>-1 then
+          begin
+            field:=tfieldvarsym(tabstractrecorddef(def).symtable.symlist[curindex]);
+            result:=field.fieldoffset+field.vardef.size
+          end
+        else
+          result:=0
+      end;
+
+
+    procedure taggregateinformation.setnextfieldname(AValue: TIDString);
+      begin
+        if (fnextfieldname<>'') or
+           not anonrecord then
+          internalerror(2015071503);
+        fnextfieldname:=AValue;
+      end;
+
+
+    constructor taggregateinformation.create(_def: tdef; _typ: ttypedconstkind);
+      begin
+        fdef:=_def;
+        ftyp:=_typ;
+        fcurindex:=-1;
+        fnextindex:=-1;
+      end;
+
+
+    function taggregateinformation.prepare_next_field(nextfielddef: tdef): asizeint;
+      var
+        sym: tsym;
+        currentoffset,nextoffset: asizeint;
+        i: longint;
+      begin
+        { get the next field and its offset, and make that next field the current
+          one }
+        if assigned(nextfield) then
+          begin
+            nextoffset:=nextfield.fieldoffset;
+            currentoffset:=curoffset;
+            curfield:=nextfield;
+          end
+        else
+          begin
+            { must set nextfield for unions and objects, as we cannot
+              automatically detect the "next" field in that case }
+            if ((def.typ=recorddef) and
+                trecorddef(def).isunion) or
+               is_object(def) then
+              internalerror(2014091202);
+            { if we are constructing this record as data gets emitted, add a field
+              for this data }
+            if anonrecord then
+              begin
+                trecorddef(def).add_field_by_def(fnextfieldname,nextfielddef);
+                fnextfieldname:='';
+              end
+            else if fnextfieldname<>'' then
+              internalerror(2015071501);
+            currentoffset:=curoffset;
+            { find next field }
+            i:=curindex;
+            repeat
+              inc(i);
+              sym:=tsym(tabstractrecorddef(def).symtable.symlist[i]);
+            until (sym.typ=fieldvarsym) and
+              not(sp_static in sym.symoptions);
+            curfield:=tfieldvarsym(sym);
+            nextoffset:=curfield.fieldoffset;
+            curindex:=i;
+          end;
+        { need padding? }
+        result:=nextoffset-currentoffset;
+      end;
+
+
+{****************************************************************************
+                             ttypedconstplaceholder
+ ****************************************************************************}
+
+    constructor ttypedconstplaceholder.create(d: tdef);
+      begin
+        def:=d;
+      end;
+
+{****************************************************************************
+                            tai_abstracttypedconst
+ ****************************************************************************}
+
+   procedure tai_abstracttypedconst.setdef(def: tdef);
+     begin
+       { should not be changed, rewrite the calling code if this happens }
+       if assigned(fdef) then
+         Internalerror(2014080203);
+       fdef:=def;
+     end;
+
+   constructor tai_abstracttypedconst.create(_adetyp: ttypedconstkind; _def: tdef);
+     begin
+       inherited create;
+       typ:=ait_typedconst;
+       fadetyp:=_adetyp;
+       fdef:=_def;
+     end;
+
+
+{****************************************************************************
+                                tai_simpletypedconst
+ ****************************************************************************}
+
+    procedure tai_simpletypedconst.setval(AValue: tai);
+      begin
+        fval:=AValue;
+      end;
+
+
+   constructor tai_simpletypedconst.create(_adetyp: ttypedconstkind; _def: tdef; _val: tai);
+     begin
+       inherited create(_adetyp,_def);
+       fval:=_val;
+     end;
+
+
+{****************************************************************************
+              tai_aggregatetypedconst.tadeenumerator
+ ****************************************************************************}
+
+   constructor tai_aggregatetypedconst.tadeenumerator.create(data: tai_aggregatetypedconst);
+     begin
+       fvalues:=data.fvalues;
+       fvaluespos:=-1;
+     end;
+
+
+   function tai_aggregatetypedconst.tadeenumerator.getcurrent: tai_abstracttypedconst;
+     begin
+       result:=tai_abstracttypedconst(fvalues[fvaluespos]);
+     end;
+
+
+   function tai_aggregatetypedconst.tadeenumerator.movenext: boolean;
+     begin
+       if fvaluespos<pred(fvalues.count) then
+         begin
+           inc(fvaluespos);
+           result:=true
+         end
+       else
+         result:=false;
+     end;
+
+
+   procedure tai_aggregatetypedconst.tadeenumerator.reset;
+     begin
+       fvaluespos:=0
+     end;
+
+
+{****************************************************************************
+                            tai_aggregatetypedconst
+ ****************************************************************************}
+
+   procedure tai_aggregatetypedconst.convert_to_string;
+     var
+       ai: tai_abstracttypedconst;
+       newstr: tai_string;
+     begin
+       newstr:=tai_string.Create('');
+       for ai in self do
+          begin
+            if ai.adetyp<>tck_simple then
+              internalerror(2014070103);
+            add_to_string(newstr,tai_simpletypedconst(ai).val);
+            ai.free;
+          end;
+       fvalues.count:=0;
+       { the "nil" def will be replaced with an array def of the appropriate
+         size once we're finished adding data, so we don't create intermediate
+         arraydefs all the time }
+       fvalues.add(tai_simpletypedconst.create(tck_simple,nil,newstr));
+     end;
+
+   procedure tai_aggregatetypedconst.add_to_string(strtai: tai_string; othertai: tai);
+     begin
+       case othertai.typ of
+         ait_string:
+           begin
+             strtai.str:=reallocmem(strtai.str,strtai.len+tai_string(othertai).len+1);
+             { also copy null terminator }
+             move(tai_string(othertai).str[0],strtai.str[strtai.len],tai_string(othertai).len+1);
+             { the null terminator is not part of the string data }
+             strtai.len:=strtai.len+tai_string(othertai).len;
+           end;
+         ait_const:
+           begin
+             if tai_const(othertai).size<>1 then
+               internalerror(2014070101);
+             strtai.str:=reallocmem(strtai.str,strtai.len+1);
+             strtai.str[strtai.len]:=ansichar(tai_const(othertai).value);
+             strtai.str[strtai.len+1]:=#0;
+             inc(strtai.len);
+           end;
+         else
+           internalerror(2014070102);
+       end;
+     end;
+
+
+   constructor tai_aggregatetypedconst.create(_adetyp: ttypedconstkind; _fdef: tdef);
+     begin
+       inherited;
+       fisstring:=false;
+       fvalues:=tfplist.create;
+     end;
+
+
+   function tai_aggregatetypedconst.getenumerator: tadeenumerator;
+     begin
+       result:=tadeenumerator.create(self);
+     end;
+
+
+   procedure tai_aggregatetypedconst.addvalue(val: tai_abstracttypedconst);
+     begin
+       { merge string constants and ordinal constants added in an array of
+         char, to unify the length and the string data }
+       if fisstring or
+          ((val.adetyp=tck_simple) and
+           (tai_simpletypedconst(val).val.typ=ait_string)) then
+         begin
+           if not fisstring and
+              (fvalues.count>0) then
+             convert_to_string;
+           fisstring:=true;
+           case fvalues.count of
+             0: fvalues.add(val);
+             1:
+               begin
+                 add_to_string(tai_string(tai_simpletypedconst(fvalues[0]).val),tai_simpletypedconst(val).val);
+                 val.free
+               end
+             else
+               internalerror(2014070104);
+           end;
+         end
+       else
+         fvalues.add(val);
+     end;
+
+
+   function tai_aggregatetypedconst.valuecount: longint;
+     begin
+       result:=fvalues.count;
+     end;
+
+
+   procedure tai_aggregatetypedconst.insertvaluebeforepos(val: tai_abstracttypedconst; pos: longint);
+     begin
+       fvalues.insert(pos,val);
+     end;
+
+
+   function tai_aggregatetypedconst.replacevalueatpos(val: tai_abstracttypedconst; pos: longint): tai_abstracttypedconst;
+     begin
+       result:=tai_abstracttypedconst(fvalues[pos]);
+       fvalues[pos]:=val;
+     end;
+
+
+   procedure tai_aggregatetypedconst.changetorecord(_def: trecorddef);
+     begin
+       { must be a record of the same size as the current data }
+       if assigned(fdef) and
+          (fdef.size<>_def.size) then
+         internalerror(2015122402);
+       fdef:=_def;
+       fadetyp:=tck_record;
+     end;
+
+
+   procedure tai_aggregatetypedconst.finish;
+     begin
+       if fisstring then
+         begin
+           { set the def: an array of char with the same length as the string
+             data }
+           if fvalues.count<>1 then
+             internalerror(2014070105);
+           tai_simpletypedconst(fvalues[0]).fdef:=
+             carraydef.getreusable(cansichartype,
+               tai_string(tai_simpletypedconst(fvalues[0]).val).len);
+         end;
+     end;
+
+
+   destructor tai_aggregatetypedconst.destroy;
+     begin
+       fvalues.free;
+       inherited destroy;
+     end;
+
+
+ {*****************************************************************************
+                              ttai_typedconstbuilder
+ *****************************************************************************}
+
+   function ttai_typedconstbuilder.getcurragginfo: taggregateinformation;
+     begin
+       if assigned(faggregateinformation) and
+          (faggregateinformation.count>0) then
+         result:=taggregateinformation(faggregateinformation[faggregateinformation.count-1])
+       else
+         result:=nil;
+     end;
+
+
+   procedure ttai_typedconstbuilder.set_next_field(AValue: tfieldvarsym);
+     var
+       info: taggregateinformation;
+     begin
+       info:=curagginfo;
+       if not assigned(info) then
+         internalerror(2014091206);
+       info.nextfield:=AValue;
+     end;
+
+
+    procedure ttai_typedconstbuilder.set_next_field_name(AValue: TIDString);
+      var
+        info: taggregateinformation;
+      begin
+        info:=curagginfo;
+        if not assigned(info) then
+          internalerror(2015071502);
+        info.nextfieldname:='$'+AValue;
+      end;
+
+
+   procedure ttai_typedconstbuilder.pad_next_field(nextfielddef: tdef);
+     var
+       fillbytes: asizeint;
+     begin
+       fillbytes:=curagginfo.prepare_next_field(nextfielddef);
+       while fillbytes>0 do
+         begin
+           do_emit_tai(tai_const.create_8bit(0),u8inttype);
+           dec(fillbytes);
+         end;
+     end;
+
+
+   function ttai_typedconstbuilder.get_internal_data_section_index(typ: TAsmSectiontype): longint;
+     begin
+       { avoid wrong warning by -Oodfa }
+       result:=-1;
+       for result:=low(finternal_data_section_info) to high(finternal_data_section_info) do
+         if finternal_data_section_info[result].sectype=typ then
+           exit;
+       result:=-1;
+     end;
+
+
+   function ttai_typedconstbuilder.get_internal_data_section_start_label: tasmlabel;
+     begin
+       { on Darwin, dead code/data stripping happens based on non-temporary
+         labels (any label that doesn't start with "L" -- it doesn't have
+         to be global) }
+       if target_info.system in systems_darwin then
+         current_asmdata.getstaticdatalabel(result)
+       else if create_smartlink_library then
+         current_asmdata.getglobaldatalabel(result)
+       else
+         current_asmdata.getlocaldatalabel(result);
+     end;
+
+
+   function ttai_typedconstbuilder.get_internal_data_section_internal_label: tasmlabel;
+     begin
+       if create_smartlink_library then
+         { all labels need to be global in case they're in another object }
+         current_asmdata.getglobaldatalabel(result)
+       else
+         { no special requirement for the label -> just get a local one }
+         current_asmdata.getlocaldatalabel(result);
+     end;
+
+
+   function ttai_typedconstbuilder.aggregate_kind(def: tdef): ttypedconstkind;
+     begin
+       if (def.typ in [recorddef,filedef,variantdef]) or
+          is_object(def) or
+          ((def.typ=procvardef) and
+           not tprocvardef(def).is_addressonly) then
+         result:=tck_record
+       else if ((def.typ=arraydef) and
+           not is_dynamic_array(def)) or
+          ((def.typ=setdef) and
+           not is_smallset(def)) or
+          is_shortstring(def) then
+         result:=tck_array
+       else
+         result:=tck_simple;
+     end;
+
+
+   procedure ttai_typedconstbuilder.finalize_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: shortint; const options: ttcasmlistoptions);
+     var
+       prelist: tasmlist;
+     begin
+       { have we finished all aggregates? }
+       if (getcurragginfo<>nil) and
+          { in case of syntax errors, the aggregate may not have been finished }
+          (ErrorCount=0) then
+         internalerror(2015072301);
+
+       { must call finalize_vectorized_dead_strip_asmlist() instead }
+       if (([tcalo_vectorized_dead_strip_start,
+             tcalo_vectorized_dead_strip_item,
+             tcalo_vectorized_dead_strip_end]*options)<>[]) and
+          not fvectorized_finalize_called then
+         internalerror(2015110602);
+
+       prelist:=tasmlist.create;
+       { only now add items based on the symbolname, because it may be
+         modified by the "section" specifier in case of a typed constant }
+
+       { both in case the data should be dead strippable and never dead
+         stripped, it should be in a separate section (so this property doesn't
+         affect other data) }
+       if ([tcalo_no_dead_strip,tcalo_make_dead_strippable]*options)<>[] then
+         begin
+           maybe_new_object_file(prelist);
+           { we always need a new section here, since if we started a new
+             object file then we have to say what the section is, and otherwise
+             we need a new section because that's how the dead stripping works }
+           new_section(prelist,section,secname,const_align(alignment));
+         end
+       else if tcalo_new_section in options then
+         new_section(prelist,section,secname,const_align(alignment))
+       else
+         prelist.concat(cai_align.Create(const_align(alignment)));
+
+       { On Darwin, use .reference to ensure the data doesn't get dead stripped.
+         On other platforms, the data must be in the .fpc section (which is
+         kept via the linker script) }
+       if tcalo_no_dead_strip in options then
+         begin
+           if target_info.system in systems_darwin then
+             prelist.concat(tai_directive.Create(asd_reference,sym.name))
+           else if section<>sec_fpc then
+             internalerror(2015101402);
+         end;
+
+       if not(tcalo_is_lab in options) then
+         if sym.bind=AB_LOCAL then
+           prelist.concat(tai_symbol.Create(sym,0))
+         else
+           prelist.concat(tai_symbol.Create_Global(sym,0))
+       else
+         prelist.concat(tai_label.Create(tasmlabel(sym)));
+
+       if tcalo_weak in options then
+         prelist.concat(tai_directive.Create(asd_weak_definition,sym.name));
+       { insert the symbol information before the data }
+       fasmlist.insertlist(prelist);
+       { end of the symbol }
+       fasmlist.concat(tai_symbol_end.Createname(sym.name));
+       { free the temporary list }
+       prelist.free;
+     end;
+
+
+   procedure ttai_typedconstbuilder.finalize_vectorized_dead_strip_asmlist(def: tdef; const basename, itemname: TSymStr; st: tsymtable; alignment: shortint; options: ttcasmlistoptions);
+     var
+       sym: tasmsymbol;
+       secname: TSymStr;
+       sectype: TAsmSectiontype;
+       customsecname: boolean;
+     begin
+       fvectorized_finalize_called:=true;
+       sym:=nil;
+       customsecname:=get_vectorized_dead_strip_custom_section_name(basename,st,secname);
+       if customsecname then
+         sectype:=sec_user
+       else
+         sectype:=sec_data;
+       if tcalo_vectorized_dead_strip_start in options then
+         begin
+           { the start and end names are predefined }
+           if itemname<>'' then
+             internalerror(2015110801);
+           sym:=get_vectorized_dead_strip_section_symbol_start(basename,st,true);
+           if not customsecname then
+             secname:=make_mangledname(basename,st,'1_START');
+         end
+       else if tcalo_vectorized_dead_strip_end in options then
+         begin
+           { the start and end names are predefined }
+           if itemname<>'' then
+             internalerror(2015110802);
+           sym:=get_vectorized_dead_strip_section_symbol_end(basename,st,true);
+           if not customsecname then
+             secname:=make_mangledname(basename,st,'3_END');
+         end
+       else if tcalo_vectorized_dead_strip_item in options then
+         begin
+           sym:=current_asmdata.DefineAsmSymbol(make_mangledname(basename,st,itemname),AB_GLOBAL,AT_DATA);
+           if not customsecname then
+             secname:=make_mangledname(basename,st,'2_'+itemname);
+           exclude(options,tcalo_vectorized_dead_strip_item);
+         end;
+       finalize_asmlist(sym,def,sectype,secname,alignment,options);
+     end;
+
+
+   procedure ttai_typedconstbuilder.do_emit_tai(p: tai; def: tdef);
+     begin
+       { by default we don't care about the type }
+       fasmlist.concat(p);
+     end;
+
+
+   function ttai_typedconstbuilder.get_final_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: longint): tasmlist;
+     begin
+       if not fasmlist_finalized then
+         begin
+           finalize_asmlist(sym,def,section,secname,alignment,foptions);
+           fasmlist_finalized:=true;
+         end;
+       result:=fasmlist;
+     end;
+
+
+   function ttai_typedconstbuilder.get_final_asmlist_vectorized_dead_strip(def: tdef; const basename, itemname: TSymStr; st: TSymtable; alignment: longint): tasmlist;
+     begin
+       if not fasmlist_finalized then
+         begin
+           finalize_vectorized_dead_strip_asmlist(def,basename,itemname,st,alignment,foptions);
+           fasmlist_finalized:=true;
+         end;
+       result:=fasmlist;
+     end;
+
+
+   class function ttai_typedconstbuilder.get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint;
+     begin
+       { darwin's linker does not support negative offsets }
+       if not(target_info.system in systems_darwin) then
+         result:=0
+       else
+         result:=get_string_header_size(typ,winlikewidestring);
+     end;
+
+
+   class function ttai_typedconstbuilder.get_string_header_size(typ: tstringtype; winlikewidestring: boolean): pint;
+     const
+       ansistring_header_size =
+         { encoding }
+         2 +
+         { elesize }
+         2 +
+{$ifdef cpu64bitaddr}
+         { alignment }
+         4 +
+{$endif cpu64bitaddr}
+         { reference count }
+         sizeof(pint) +
+         { length }
+         sizeof(pint);
+       unicodestring_header_size = ansistring_header_size;
+     begin
+       case typ of
+         st_ansistring:
+           result:=ansistring_header_size;
+         st_unicodestring:
+           result:=unicodestring_header_size;
+         st_widestring:
+           if winlikewidestring then
+             result:=0
+           else
+             result:=unicodestring_header_size;
+         else
+           result:=0;
+       end;
+     end;
+
+
+   constructor ttai_typedconstbuilder.create(const options: ttcasmlistoptions);
+     begin
+       inherited create;
+       fasmlist:=tasmlist.create;
+       foptions:=options;
+       { queue is empty }
+       fqueue_offset:=low(fqueue_offset);
+       finternal_data_current_section:=sec_none;
+     end;
+
+
+   destructor ttai_typedconstbuilder.destroy;
+     begin
+       { the queue should have been flushed if it was used }
+       if fqueue_offset<>low(fqueue_offset) then
+         internalerror(2014062901);
+       faggregateinformation.free;
+       fasmlist.free;
+       inherited destroy;
+     end;
+
+
+   procedure ttai_typedconstbuilder.start_internal_data_builder(list: tasmlist; sectype: TAsmSectiontype; const secname: TSymStr; out tcb: ttai_typedconstbuilder; out l: tasmlabel);
+     var
+       options: ttcasmlistoptions;
+       foundsec: longint;
+     begin
+       options:=[tcalo_is_lab];
+       { Add a section header if the previous one was different. We'll use the
+         same section name in case multiple items are added to the same kind of
+         section (rodata, rodata_no_rel, ...), so that everything will still
+         end up in the same section even if there are multiple section headers }
+       if finternal_data_current_section<>sectype then
+         include(options,tcalo_new_section);
+       finternal_data_current_section:=sectype;
+       l:=nil;
+       { did we already create a section of this type for the internal data of
+         this builder? }
+       foundsec:=get_internal_data_section_index(sectype);
+       if foundsec=-1 then
+         begin
+           { we only need to start a dead-strippable section of data at the
+             start of the first subsection of this kind for this block.
+
+             exception: if dead stripping happens based on objects/libraries,
+             then we only have to create a new object file for the first
+             internal data section of any kind (all the rest will simply be put
+             in the same object file) }
+           if create_smartlink then
+             begin
+               if not create_smartlink_library or
+                  (length(finternal_data_section_info)=0) then
+                 include(options,tcalo_make_dead_strippable);
+               { on Darwin, dead code/data stripping happens based on non-
+                 temporary labels (any label that doesn't start with "L" -- it
+                 doesn't have to be global) -> add a non-temporary lobel at the
+                 start of every kind of subsection created in this builder }
+               if target_info.system in systems_darwin then
+                 l:=get_internal_data_section_start_label;
+             end;
+           foundsec:=length(finternal_data_section_info);
+           setlength(finternal_data_section_info,foundsec+1);
+           finternal_data_section_info[foundsec].sectype:=sectype;
+         end;
+       if not assigned(finternal_data_asmlist) and
+          (cs_create_smart in current_settings.moduleswitches) then
+         begin
+           l:=get_internal_data_section_start_label;
+           { the internal data list should only be assigned by this routine,
+             the first time that an internal data block is started }
+           if not assigned(list) or
+              assigned(finternal_data_asmlist) then
+             internalerror(2015032101);
+           finternal_data_asmlist:=list;
+         end
+       { all internal data for this tcb must go to the same list (otherwise all
+         data we want to add to the dead-strippable block is not guaranteed to
+         be sequential and e.g. in the same object file in case of library-based
+         dead stripping) }
+       else if (assigned(finternal_data_asmlist) and
+           (list<>finternal_data_asmlist)) or
+           not assigned(list) then
+         internalerror(2015032101);
+       finternal_data_asmlist:=list;
+       if not assigned(l) then
+         l:=get_internal_data_section_internal_label;
+       { first section of this kind -> set name }
+       if finternal_data_section_info[foundsec].secname='' then
+         if secname='' then
+           finternal_data_section_info[foundsec].secname:=l.Name
+         else
+           finternal_data_section_info[foundsec].secname:=secname
+       { if the name is specified multiple times, it must match }
+       else if (secname<>'') and
+               (finternal_data_section_info[foundsec].secname<>secname) then
+         internalerror(2015032401);
+       tcb:=ttai_typedconstbuilderclass(classtype).create(options);
+     end;
+
+
+   procedure ttai_typedconstbuilder.finish_internal_data_builder(var tcb: ttai_typedconstbuilder; l: tasmlabel; def: tdef; alignment: longint);
+     begin
+       finternal_data_asmlist.concatList(tcb.get_final_asmlist(l,def,
+         finternal_data_current_section,
+         finternal_data_section_info[get_internal_data_section_index(finternal_data_current_section)].secname,
+         alignment));
+       tcb.free;
+       tcb:=nil;
+     end;
+
+
+   procedure ttai_typedconstbuilder.emit_tai(p: tai; def: tdef);
+     var
+       kind: ttypedconstkind;
+       info: taggregateinformation;
+     begin
+       { these elements can be aggregates themselves, e.g. a shortstring can
+         be emitted as a series of bytes and char arrays }
+       kind:=aggregate_kind(def);
+       info:=curagginfo;
+       if (kind<>tck_simple) and
+          (not assigned(info) or
+           (info.typ<>kind)) then
+         internalerror(2014091001);
+       { if we're emitting a record, handle the padding bytes, and in case of
+         an anonymous record also add the next field }
+       if assigned(info) then
+         begin
+           { queue_init already adds padding }
+           if not queue_is_active and
+               (is_record(info.def) or
+                is_object(info.def)) and
+              { may add support for these later }
+              not is_packed_record_or_object(info.def) then
+             pad_next_field(def);
+         end;
+       { emit the data }
+       do_emit_tai(p,def);
+     end;
+
+
+   procedure ttai_typedconstbuilder.emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef);
+     begin
+       { nothing special by default, since we don't care about the type }
+       emit_tai(p,pvdef);
+     end;
+
+
+   procedure ttai_typedconstbuilder.maybe_emit_tail_padding(def: tdef);
+     var
+       info: taggregateinformation;
+       fillbytes: asizeint;
+     begin
+       info:=curagginfo;
+       if not assigned(info) then
+         internalerror(2014091002);
+       if def<>info.def then
+         internalerror(2014091205);
+       if (is_record(def) or
+           is_object(def)) and
+          not is_packed_record_or_object(def) then
+         begin
+           fillbytes:=def.size-info.curoffset;
+           while fillbytes>0 do
+             begin
+               do_emit_tai(Tai_const.Create_8bit(0),u8inttype);
+               dec(fillbytes)
+             end;
+         end;
+     end;
+
+
+   function ttai_typedconstbuilder.emit_string_const_common(stringtype: tstringtype; len: asizeint; encoding: tstringencoding; var startlab: tasmlabel): tasmlabofs;
+     var
+       string_symofs: asizeint;
+       charptrdef: tdef;
+       elesize: word;
+     begin
+       result.lab:=startlab;
+       result.ofs:=0;
+       { pack the data, so that we don't add unnecessary null bytes after the
+         constant string }
+       begin_anonymous_record('$'+get_dynstring_rec_name(stringtype,false,len),1,sizeof(TConstPtrUInt),1,1);
+       string_symofs:=get_string_symofs(stringtype,false);
+       { encoding }
+       emit_tai(tai_const.create_16bit(encoding),u16inttype);
+       inc(result.ofs,2);
+       { element size }
+       case stringtype of
+         st_ansistring:
+           begin
+             elesize:=1;
+             charptrdef:=charpointertype;
+           end;
+         st_unicodestring:
+           begin
+             elesize:=2;
+             charptrdef:=widecharpointertype;
+           end
+         else
+           internalerror(2014080401);
+       end;
+       emit_tai(tai_const.create_16bit(elesize),u16inttype);
+       inc(result.ofs,2);
+{$ifdef cpu64bitaddr}
+       { dummy for alignment }
+       emit_tai(tai_const.create_32bit(0),u32inttype);
+       inc(result.ofs,4);
+{$endif cpu64bitaddr}
+       emit_tai(tai_const.create_pint(-1),ptrsinttype);
+       inc(result.ofs,sizeof(pint));
+       emit_tai(tai_const.create_pint(len),ptrsinttype);
+       inc(result.ofs,sizeof(pint));
+       if string_symofs=0 then
+         begin
+           { results in slightly more efficient code }
+           emit_tai(tai_label.create(result.lab),charptrdef);
+           result.ofs:=0;
+           { create new label of the same kind (including whether or not the
+             name starts with target_asm.labelprefix in case it's AB_LOCAL,
+             so we keep the difference depending on whether the original was
+             allocated via getstatic/getlocal/getglobal datalabel) }
+           startlab:=tasmlabel.create(current_asmdata.AsmSymbolDict,startlab.name+'$strlab',startlab.bind,startlab.typ);
+         end;
+       { sanity check }
+       if result.ofs<>string_symofs then
+         internalerror(2012051701);
+     end;
+
+
+   function ttai_typedconstbuilder.get_dynstring_def_for_type(stringtype: tstringtype; winlikewidestring: boolean): tstringdef;
+     begin
+       if stringtype=st_ansistring then
+         result:=tstringdef(cansistringtype)
+       else if (stringtype=st_unicodestring) or
+               ((stringtype=st_widestring) and
+                not winlikewidestring) then
+         result:=tstringdef(cunicodestringtype)
+       else if stringtype=st_widestring then
+         result:=tstringdef(cwidestringtype)
+       else
+         internalerror(2015122101);
+     end;
+
+
+   procedure ttai_typedconstbuilder.begin_aggregate_internal(def: tdef; anonymous: boolean);
+     var
+       info: taggregateinformation;
+       tck: ttypedconstkind;
+     begin
+       tck:=aggregate_kind(def);
+       if tck=tck_simple then
+         exit;
+       if not assigned(faggregateinformation) then
+         faggregateinformation:=tfpobjectlist.create
+       { if we're starting an anonymous record, we can't align it yet because
+         the alignment depends on the fields that will be added -> we'll do
+         it at the end }
+       else if not anonymous then
+         begin
+           { add padding if necessary, and update the current field/offset }
+           info:=curagginfo;
+           if (is_record(curagginfo.def) or
+               is_object(curagginfo.def)) and
+              not is_packed_record_or_object(curagginfo.def) then
+             begin
+               if queue_is_active then
+                 internalerror(2015073001);
+               pad_next_field(def);
+             end;
+         end
+       { if this is the outer record, no padding is required; the alignment
+         has to be specified explicitly in that case via get_final_asmlist() }
+       else if assigned(curagginfo) and
+               (curagginfo.def.typ=recorddef) then
+         { mark where we'll have to insert the padding bytes at the end }
+         mark_anon_aggregate_alignment;
+       info:=caggregateinformation.create(def,aggregate_kind(def));
+       faggregateinformation.add(info);
+     end;
+
+
+   procedure ttai_typedconstbuilder.end_aggregate_internal(def: tdef; anonymous: boolean);
+     var
+       info: taggregateinformation;
+       tck: ttypedconstkind;
+     begin
+       tck:=aggregate_kind(def);
+       if tck=tck_simple then
+         exit;
+       { add tail padding if necessary }
+       maybe_emit_tail_padding(def);
+       { pop and free the information }
+       info:=curagginfo;
+       faggregateinformation.count:=faggregateinformation.count-1;
+       info.free;
+     end;
+
+
+   class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol(const basename: string; st: tsymtable; define, start: boolean): tasmsymbol;
+     var
+       name: TSymStr;
+     begin
+       if start then
+         name:=make_mangledname(basename,st,'START')
+       else
+         name:=make_mangledname(basename,st,'END');
+       if define then
+         result:=current_asmdata.DefineAsmSymbol(name,AB_GLOBAL,AT_DATA)
+       else
+         result:=current_asmdata.RefAsmSymbol(name,AT_DATA)
+     end;
+
+
+   class function ttai_typedconstbuilder.get_vectorized_dead_strip_custom_section_name(const basename: TSymStr; st: tsymtable; out secname: TSymStr): boolean;
+     begin
+       result:=false;
+     end;
+
+
+   class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol_start(const basename: string; st: tsymtable; define: boolean): tasmsymbol;
+     begin
+       result:=get_vectorized_dead_strip_section_symbol(basename,st,define,true);
+     end;
+
+
+   class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol_end(const basename: string; st: tsymtable; define: boolean): tasmsymbol;
+     begin
+       result:=get_vectorized_dead_strip_section_symbol(basename,st,define,false);
+     end;
+
+
+   class function ttai_typedconstbuilder.get_dynstring_rec_name(typ: tstringtype; winlike: boolean; len: asizeint): string;
+     begin
+       case typ of
+         st_ansistring:
+           result:='ansistrrec';
+         st_unicodestring,
+         st_widestring:
+           if (typ=st_unicodestring) or
+              not winlike then
+             result:='unicodestrrec'
+           else
+             result:='widestrrec';
+         else
+           internalerror(2014080402);
+       end;
+       result:=result+tostr(len);
+     end;
+
+
+   function ttai_typedconstbuilder.emit_ansistring_const(datalist: TAsmList; data: pchar; len: asizeint; encoding: tstringencoding): tasmlabofs;
+     var
+       s: PChar;
+       startlab: tasmlabel;
+       ansistrrecdef: trecorddef;
+       datadef: tdef;
+       datatcb: ttai_typedconstbuilder;
+     begin
+       start_internal_data_builder(datalist,sec_rodata_norel,'',datatcb,startlab);
+       result:=datatcb.emit_string_const_common(st_ansistring,len,encoding,startlab);
+
+       getmem(s,len+1);
+       move(data^,s^,len);
+       s[len]:=#0;
+       { terminating zero included }
+       datadef:=carraydef.getreusable(cansichartype,len+1);
+       datatcb.maybe_begin_aggregate(datadef);
+       datatcb.emit_tai(tai_string.create_pchar(s,len+1),datadef);
+       datatcb.maybe_end_aggregate(datadef);
+       ansistrrecdef:=datatcb.end_anonymous_record;
+       finish_internal_data_builder(datatcb,startlab,ansistrrecdef,const_align(sizeof(pointer)));
+     end;
+
+
+   function ttai_typedconstbuilder.emit_unicodestring_const(datalist: TAsmList; data: pointer; encoding: tstringencoding; winlike: boolean):tasmlabofs;
+     var
+       i, strlength: longint;
+       string_symofs: asizeint;
+       startlab: tasmlabel;
+       datadef: tdef;
+       datatcb: ttai_typedconstbuilder;
+       unicodestrrecdef: trecorddef;
+     begin
+       start_internal_data_builder(datalist,sec_rodata_norel,'',datatcb,startlab);
+       strlength:=getlengthwidestring(pcompilerwidestring(data));
+       if winlike then
+         begin
+           result.lab:=startlab;
+           datatcb.begin_anonymous_record('$'+get_dynstring_rec_name(st_widestring,true,strlength),
+             4,4,
+             targetinfos[target_info.system]^.alignment.recordalignmin,
+             targetinfos[target_info.system]^.alignment.maxCrecordalign);
+           datatcb.emit_tai(Tai_const.Create_32bit(strlength*cwidechartype.size),s32inttype);
+           { can we optimise by placing the string constant label at the
+             required offset? }
+           string_symofs:=get_string_symofs(st_widestring,true);
+           if string_symofs=0 then
+             begin
+               { yes }
+               datatcb.emit_tai(Tai_label.Create(result.lab),widecharpointertype);
+               { allocate a separate label for the start of the data (see
+                 emit_string_const_common() for explanation) }
+               startlab:=tasmlabel.create(current_asmdata.AsmSymbolDict,startlab.name+'$strlab',startlab.bind,startlab.typ);
+             end
+           else
+             internalerror(2015031502);
+           result.ofs:=string_symofs;
+         end
+       else
+         begin
+           result:=datatcb.emit_string_const_common(st_unicodestring,strlength,encoding,startlab);
+         end;
+       if cwidechartype.size = 2 then
+         begin
+           datadef:=carraydef.getreusable(cwidechartype,strlength+1);
+           datatcb.maybe_begin_aggregate(datadef);
+           for i:=0 to strlength-1 do
+             datatcb.emit_tai(Tai_const.Create_16bit(pcompilerwidestring(data)^.data[i]),cwidechartype);
+           { ending #0 }
+           datatcb.emit_tai(Tai_const.Create_16bit(0),cwidechartype);
+           datatcb.maybe_end_aggregate(datadef);
+           unicodestrrecdef:=datatcb.end_anonymous_record;
+         end
+       else
+         { code generation for other sizes must be written }
+         internalerror(200904271);
+       finish_internal_data_builder(datatcb,startlab,unicodestrrecdef,const_align(sizeof(pint)));
+     end;
+
+
+   procedure ttai_typedconstbuilder.emit_string_offset(const ll: tasmlabofs; const strlength: longint; const st: tstringtype; const winlikewidestring: boolean; const charptrdef: tdef);
+     begin
+       emit_tai(Tai_const.Create_sym_offset(ll.lab,ll.ofs),get_dynstring_def_for_type(st,winlikewidestring));
+     end;
+
+
+   function ttai_typedconstbuilder.emit_shortstring_const(const str: shortstring): tdef;
+     begin
+       { we use an arraydef instead of a shortstringdef, because we don't have
+         functionality in place yet to reuse shortstringdefs of the same length
+         and neither the lowlevel nor the llvm typedconst builder cares about
+         this difference }
+       result:=carraydef.getreusable(cansichartype,length(str)+1);
+       maybe_begin_aggregate(result);
+       emit_tai(Tai_const.Create_8bit(length(str)),u8inttype);
+       if str<>'' then
+         emit_tai(Tai_string.Create(str),carraydef.getreusable(cansichartype,length(str)));
+       maybe_end_aggregate(result);
+     end;
+
+
+   function ttai_typedconstbuilder.emit_pchar_const(str: pchar; len: pint): tdef;
+     begin
+       result:=carraydef.getreusable(cansichartype,len+1);
+       maybe_begin_aggregate(result);
+       if len=0 then
+         emit_tai(Tai_const.Create_8bit(0),cansichartype)
+       else
+         emit_tai(Tai_string.Create_pchar(str,len+1),result);
+       maybe_end_aggregate(result);
+     end;
+
+
+   procedure ttai_typedconstbuilder.emit_guid_const(const guid: tguid);
+     var
+       i: longint;
+     begin
+       maybe_begin_aggregate(rec_tguid);
+       { variant record -> must specify which fields get initialised }
+       next_field:=tfieldvarsym(rec_tguid.symtable.symlist[0]);
+       emit_tai(Tai_const.Create_32bit(longint(guid.D1)),u32inttype);
+       next_field:=tfieldvarsym(rec_tguid.symtable.symlist[1]);
+       emit_tai(Tai_const.Create_16bit(guid.D2),u16inttype);
+       next_field:=tfieldvarsym(rec_tguid.symtable.symlist[2]);
+       emit_tai(Tai_const.Create_16bit(guid.D3),u16inttype);
+       next_field:=tfieldvarsym(rec_tguid.symtable.symlist[3]);
+       { the array }
+       maybe_begin_aggregate(tfieldvarsym(rec_tguid.symtable.symlist[3]).vardef);
+       for i:=Low(guid.D4) to High(guid.D4) do
+         emit_tai(Tai_const.Create_8bit(guid.D4[i]),u8inttype);
+       maybe_end_aggregate(tfieldvarsym(rec_tguid.symtable.symlist[3]).vardef);
+       maybe_end_aggregate(rec_tguid);
+     end;
+
+   procedure ttai_typedconstbuilder.emit_procdef_const(pd: tprocdef);
+     begin
+       emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd));
+     end;
+
+
+   procedure ttai_typedconstbuilder.emit_ord_const(value: int64; def: tdef);
+     begin
+       case def.size of
+         1:
+           emit_tai(Tai_const.Create_8bit(byte(value)),def);
+         2:
+           emit_tai(Tai_const.Create_16bit(word(value)),def);
+         4:
+           emit_tai(Tai_const.Create_32bit(longint(value)),def);
+         8:
+           emit_tai(Tai_const.Create_64bit(value),def);
+         else
+           internalerror(2014100501);
+       end;
+     end;
+
+
+   procedure ttai_typedconstbuilder.maybe_begin_aggregate(def: tdef);
+     begin
+       begin_aggregate_internal(def,false);
+     end;
+
+
+   procedure ttai_typedconstbuilder.maybe_end_aggregate(def: tdef);
+     begin
+       end_aggregate_internal(def,false);
+     end;
+
+
+   function ttai_typedconstbuilder.begin_anonymous_record(const optionalname: string; packrecords, recordalign, recordalignmin, maxcrecordalign: shortint): trecorddef;
+     var
+       anonrecorddef: trecorddef;
+       typesym: ttypesym;
+     begin
+       { if the name is specified, we create a typesym with that name in order
+         to ensure we can find it again later with that name -> reuse here as
+         well if possible (and that also avoids duplicate type name issues) }
+       if optionalname<>'' then
+         begin
+           typesym:=try_search_current_module_type(optionalname);
+           if assigned(typesym) then
+             begin
+               if typesym.typedef.typ<>recorddef then
+                 internalerror(2015071401);
+               result:=trecorddef(typesym.typedef);
+               maybe_begin_aggregate(result);
+               exit;
+             end;
+         end;
+       { create skeleton def }
+       anonrecorddef:=crecorddef.create_global_internal(optionalname,packrecords,recordalignmin,maxcrecordalign);
+       trecordsymtable(anonrecorddef.symtable).recordalignment:=recordalign;
+       { generic aggregate housekeeping }
+       begin_aggregate_internal(anonrecorddef,true);
+       { mark as anonymous record }
+       curagginfo.anonrecord:=true;
+       { in case a descendent wants to do something with the anonrecorddef too }
+       result:=anonrecorddef;
+     end;
+
+
+   function ttai_typedconstbuilder.end_anonymous_record: trecorddef;
+     var
+       info: taggregateinformation;
+       anonrecord: boolean;
+     begin
+       info:=curagginfo;
+       if not assigned(info) or
+          (info.def.typ<>recorddef) then
+         internalerror(2014080201);
+       result:=trecorddef(info.def);
+       { make a copy, as we need it after info has been freed by
+         maybe_end_aggregate(result) }
+       anonrecord:=info.anonrecord;
+       { finalise the record skeleton (all fields have been added already by
+         emit_tai()) -- anonrecord may not be set in case we reused an earlier
+         constructed def }
+       if anonrecord then
+         trecordsymtable(result.symtable).addalignmentpadding;
+       end_aggregate_internal(result,true);
+       if anonrecord and
+          assigned(curagginfo) and
+          (curagginfo.def.typ=recorddef) then
+         insert_marked_aggregate_alignment(result);
+     end;
+
+
+   procedure ttai_typedconstbuilder.check_add_placeholder(def: tdef);
+     begin
+       { it only makes sense to add a placeholder inside an aggregate
+         (otherwise there can be but one element)
+
+         we cannot add a placeholder in the middle of a queued expression
+         either
+
+         the placeholder cannot be an aggregate }
+       if not assigned(curagginfo) or
+          queue_is_active or
+          (aggregate_kind(def)<>tck_simple) then
+         internalerror(2015091001);
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_init(todef: tdef);
+     var
+       info: taggregateinformation;
+     begin
+       { nested call to init? }
+       if fqueue_offset<>low(fqueue_offset) then
+         internalerror(2014062101);
+
+       { insert padding bytes before starting the queue, so that the first
+         padding byte won't be interpreted as the emitted value for this queue }
+       info:=curagginfo;
+       if assigned(info) then
+         begin
+           if ((info.def.typ=recorddef) or
+               is_object(info.def)) and
+              { may add support for these later }
+              not is_packed_record_or_object(info.def) then
+             pad_next_field(todef);
+         end;
+
+       fqueue_offset:=0;
+       fqueued_def:=todef;
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_vecn(def: tdef; const index: tconstexprint);
+     var
+       elelen,
+       vecbase: asizeint;
+       v: tconstexprint;
+     begin
+       elelen:=1;
+       vecbase:=0;
+       case def.typ of
+         stringdef :
+           ;
+         arraydef :
+           begin
+             if not is_packed_array(def) then
+               begin
+                 elelen:=tarraydef(def).elesize;
+                 vecbase:=tarraydef(def).lowrange;
+               end
+             else
+               Message(parser_e_packed_dynamic_open_array);
+           end;
+         else
+           Message(parser_e_illegal_expression);
+       end;
+       { Prevent overflow }
+       v:=index-vecbase;
+       if (v<int64(low(fqueue_offset))) or (v>int64(high(fqueue_offset))) then
+         message3(type_e_range_check_error_bounds,tostr(v),tostr(low(fqueue_offset)),tostr(high(fqueue_offset)));
+       if high(fqueue_offset)-fqueue_offset div elelen>v then
+         inc(fqueue_offset,elelen*v.svalue)
+       else
+         message3(type_e_range_check_error_bounds,tostr(index),tostr(vecbase),tostr(high(fqueue_offset)-fqueue_offset div elelen+vecbase))
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_subscriptn(def: tabstractrecorddef; vs: tfieldvarsym);
+     begin
+       inc(fqueue_offset,vs.fieldoffset);
+     end;
+
+
+   function ttai_typedconstbuilder.queue_subscriptn_multiple_by_name(def: tabstractrecorddef; const fields: array of TIDString): tdef;
+     var
+       syms,
+       parentdefs: tfplist;
+       sym: tsym;
+       curdef: tdef;
+       i: longint;
+     begin
+       result:=nil;
+       if length(fields)=0 then
+         internalerror(2015071601);
+       syms:=tfplist.Create;
+       syms.count:=length(fields);
+       parentdefs:=tfplist.create;
+       parentdefs.Count:=length(fields);
+       curdef:=def;
+       for i:=low(fields) to high(fields) do
+         begin
+           sym:=search_struct_member_no_helper(tabstractrecorddef(curdef),fields[i]);
+           if not assigned(sym) or
+              (sym.typ<>fieldvarsym) or
+              ((i<>high(fields)) and
+               not(tfieldvarsym(sym).vardef.typ in [objectdef,recorddef])) then
+             internalerror(2015071505);
+           syms[i]:=sym;
+           parentdefs[i]:=curdef;
+           curdef:=tfieldvarsym(sym).vardef;
+           result:=curdef;
+         end;
+       for i:=high(fields) downto low(fields) do
+         queue_subscriptn(tabstractrecorddef(parentdefs[i]),tfieldvarsym(syms[i]));
+       syms.free;
+       parentdefs.free;
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_typeconvn(fromdef, todef: tdef);
+     begin
+       { do nothing }
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_emit_proc(pd: tprocdef);
+     begin
+       if fqueue_offset<>0 then
+         internalerror(2014092101);
+       emit_procdef_const(pd);
+       fqueue_offset:=low(fqueue_offset);
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_emit_staticvar(vs: tstaticvarsym);
+     begin
+       { pointerdef because we are emitting a pointer to the staticvarsym
+         data, not the data itself }
+       emit_tai(Tai_const.Createname(vs.mangledname,fqueue_offset),cpointerdef.getreusable(vs.vardef));
+       fqueue_offset:=low(fqueue_offset);
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_emit_label(l: tlabelsym);
+     begin
+       emit_tai(Tai_const.Createname(l.mangledname,fqueue_offset),voidcodepointertype);
+       fqueue_offset:=low(fqueue_offset);
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_emit_const(cs: tconstsym);
+     var
+       resourcestrrec: trecorddef;
+     begin
+       if cs.consttyp<>constresourcestring then
+         internalerror(2014062102);
+       if fqueue_offset<>0 then
+         internalerror(2014062103);
+       { warning: update if/when the type of resource strings changes }
+       case cs.consttyp of
+         constresourcestring:
+           begin
+             resourcestrrec:=trecorddef(search_system_type('TRESOURCESTRINGRECORD').typedef);
+             queue_subscriptn_multiple_by_name(resourcestrrec,['CURRENTVALUE']);
+             queue_emit_asmsym(current_asmdata.RefAsmSymbol(
+               make_mangledname('RESSTR',cs.owner,cs.name),AT_DATA),resourcestrrec
+             );
+           end;
+         { can these occur? }
+         constord,
+         conststring,constreal,
+         constset,constpointer,constnil,
+         constwstring,constguid:
+           internalerror(2015090903);
+         else
+           internalerror(2015090904);
+       end;
+       fqueue_offset:=low(fqueue_offset);
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_emit_asmsym(sym: tasmsymbol; def: tdef);
+     begin
+       { pointerdef, because "sym" represents the address of whatever the
+         data is }
+       def:=cpointerdef.getreusable(def);
+       emit_tai(Tai_const.Create_sym_offset(sym,fqueue_offset),def);
+       fqueue_offset:=low(fqueue_offset);
+     end;
+
+
+   procedure ttai_typedconstbuilder.queue_emit_ordconst(value: int64; def: tdef);
+     begin
+       emit_ord_const(value,def);
+       fqueue_offset:=low(fqueue_offset);
+     end;
+
+
+   function ttai_typedconstbuilder.queue_is_active: boolean;
+     begin
+       result:=fqueue_offset<>low(fqueue_offset)
+     end;
+
+
+   {****************************************************************************
+                         tlowleveltypedconstplaceholder
+   ****************************************************************************}
+
+   constructor tlowleveltypedconstplaceholder.create(l: tasmlist; pos: tai; d: tdef);
+     begin
+       inherited create(d);
+       list:=l;
+       insertpos:=pos;
+     end;
+
+
+   procedure tlowleveltypedconstplaceholder.replace(ai: tai; d: tdef);
+     begin
+       if d<>def then
+         internalerror(2015091001);
+       list.insertafter(ai,insertpos);
+       list.remove(insertpos);
+       insertpos.free;
+     end;
+
+
+{****************************************************************************
+                           tai_abstracttypedconst
+ ****************************************************************************}
+
+   class constructor ttai_lowleveltypedconstbuilder.classcreate;
+     begin
+       caggregateinformation:=tlowlevelaggregateinformation;
+     end;
+
+
+   function ttai_lowleveltypedconstbuilder.emit_placeholder(def: tdef): ttypedconstplaceholder;
+     var
+       p: tai;
+     begin
+       check_add_placeholder(def);
+       p:=tai_marker.Create(mark_position);
+       emit_tai(p,def);
+       result:=tlowleveltypedconstplaceholder.create(fasmlist,p,def);
+     end;
+
+
+   procedure ttai_lowleveltypedconstbuilder.mark_anon_aggregate_alignment;
+     var
+       marker: tai_marker;
+     begin
+       marker:=tai_marker.Create(mark_position);
+       fasmlist.concat(marker);
+       tlowlevelaggregateinformation(curagginfo).anonrecmarker:=marker;
+     end;
+
+
+   procedure ttai_lowleveltypedconstbuilder.insert_marked_aggregate_alignment(def: tdef);
+     var
+       info: tlowlevelaggregateinformation;
+       fillbytes: asizeint;
+     begin
+       info:=tlowlevelaggregateinformation(curagginfo);
+       if not assigned(info.anonrecmarker) then
+         internalerror(2014091401);
+       fillbytes:=info.prepare_next_field(def);
+       while fillbytes>0 do
+         begin
+           fasmlist.insertafter(tai_const.create_8bit(0),info.anonrecmarker);
+           dec(fillbytes);
+         end;
+       fasmlist.remove(info.anonrecmarker);
+       info.anonrecmarker.free;
+       info.anonrecmarker:=nil;
+     end;
+
+   procedure ttai_lowleveltypedconstbuilder.finalize_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: shortint; const options: ttcasmlistoptions);
+     begin
+       inherited;
+       { The darwin/ppc64 assembler or linker seems to have trouble       }
+       { if a section ends with a global label without any data after it. }
+       { So for safety, just put a dummy value here.                      }
+       { Further, the regular linker also kills this symbol when turning  }
+       { on smart linking in case no value appears after it, so put the   }
+       { dummy byte there always                                          }
+       { Update: the Mac OS X 10.6 linker orders data that needs to be    }
+       { relocated before all other data, so make this data relocatable,  }
+       { otherwise the end label won't be moved with the rest             }
+       if (tcalo_vectorized_dead_strip_end in options) and
+          (target_info.system in (systems_darwin+systems_aix)) then
+         fasmlist.concat(Tai_const.create_sym(sym));
+     end;
+
+
+
+begin
+  ctai_typedconstbuilder:=ttai_lowleveltypedconstbuilder;
+end.
+

+ 74 - 25
compiler/aasmdata.pas

@@ -46,6 +46,8 @@ interface
       TAsmListType=(
         al_start,
         al_stabs,
+        { pure assembler routines }
+        al_pure_assembler,
         al_procedures,
         al_globals,
         al_const,
@@ -60,6 +62,8 @@ interface
         al_dwarf_info,
         al_dwarf_abbrev,
         al_dwarf_line,
+        al_dwarf_aranges,
+        al_dwarf_ranges,
         al_picdata,
         al_indirectpicdata,
         al_resourcestrings,
@@ -97,6 +101,7 @@ interface
       AsmListTypeStr : array[TAsmListType] of string[24] =(
         'al_begin',
         'al_stabs',
+        'al_pure_assembler',
         'al_procedures',
         'al_globals',
         'al_const',
@@ -111,6 +116,8 @@ interface
         'al_dwarf_info',
         'al_dwarf_abbrev',
         'al_dwarf_line',
+        'al_dwarf_aranges',
+        'al_dwarf_ranges',
         'al_picdata',
         'al_indirectpicdata',
         'al_resourcestrings',
@@ -122,8 +129,6 @@ interface
     type
       TAsmList = class(tlinkedlist)
          constructor create;
-         constructor create_without_marker;
-         function  empty : boolean;
          function  getlasttaifilepos : pfileposinfo;
       end;
 
@@ -168,14 +173,24 @@ interface
         function  DefineAsmSymbolByClass(symclass: TAsmSymbolClass; const s : TSymStr;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
         function  DefineAsmSymbol(const s : TSymStr;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
         function  WeakRefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype=AT_NONE) : TAsmSymbol;
-        function  RefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype=AT_NONE) : TAsmSymbol;
+        function  RefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype=AT_NONE;indirect:boolean=false) : TAsmSymbol;
         function  GetAsmSymbol(const s : TSymStr) : TAsmSymbol;
         { create new assembler label }
         procedure getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
         procedure getjumplabel(out l : TAsmLabel);
         procedure getglobaljumplabel(out l : TAsmLabel);
         procedure getaddrlabel(out l : TAsmLabel);
-        procedure getdatalabel(out l : TAsmLabel);
+        { visible from outside current object }
+        procedure getglobaldatalabel(out l : TAsmLabel);
+        { visible only inside current object, but doesn't start with
+          target_asm.label_prefix (treated the Darwin linker as the start of a
+          dead-strippable data block) }
+        procedure getstaticdatalabel(out l : TAsmLabel);
+        { visible only inside the current object and does start with
+          target_asm.label_prefix (not treated by the Darwin linker as the start
+          of a dead-strippable data block, and references to such labels are
+          also ignored to determine whether a data block should be live) }
+        procedure getlocaldatalabel(out l : TAsmLabel);
         { generate an alternative (duplicate) symbol }
         procedure GenerateAltSymbol(p:TAsmSymbol);
         procedure ResetAltSymbols;
@@ -206,6 +221,7 @@ implementation
 
     uses
       verbose,
+      symconst,
       aasmtai;
 
 {$ifdef MEMDEBUG}
@@ -284,20 +300,6 @@ implementation
     constructor TAsmList.create;
       begin
         inherited create;
-        { make sure the optimizer won't remove the first tai of this list}
-        insert(tai_marker.create(mark_BlockStart));
-      end;
-
-    constructor TAsmList.create_without_marker;
-      begin
-        inherited create;
-      end;
-
-    function TAsmList.empty : boolean;
-      begin
-        { there is always a mark_BlockStart available,
-          see TAsmList.create }
-        result:=(count<=1);
       end;
 
 
@@ -409,8 +411,12 @@ implementation
     function TAsmData.DefineAsmSymbolByClass(symclass: TAsmSymbolClass; const s : TSymStr;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
       var
         hp : TAsmSymbol;
+        namestr : TSymStr;
       begin
-        hp:=TAsmSymbol(FAsmSymbolDict.Find(s));
+        namestr:=s;
+        if _bind in asmsymbindindirect then
+          namestr:=namestr+suffix_indirect;
+        hp:=TAsmSymbol(FAsmSymbolDict.Find(namestr));
         if assigned(hp) then
          begin
            { Redefine is allowed, but the types must be the same. The redefine
@@ -422,12 +428,27 @@ implementation
                  internalerror(200603261);
              end;
            hp.typ:=_typ;
+           { Changing bind from AB_GLOBAL to AB_LOCAL is wrong
+             if bind is already AB_GLOBAL or AB_EXTERNAL,
+             GOT might have been used, so change might be harmful. }
+           if (_bind<>hp.bind) and (hp.getrefs>0) then
+             begin
+{$ifdef extdebug}
+               { the changes that matter must become internalerrors, the rest
+                 should be ignored; a used cannot change anything about this,
+                 so printing a warning/hint is not useful }
+               if (_bind=AB_LOCAL) then
+                 Message3(asmw_w_changing_bind_type,namestr,asmsymbindname[hp.bind],asmsymbindname[_bind])
+               else
+                 Message3(asmw_h_changing_bind_type,namestr,asmsymbindname[hp.bind],asmsymbindname[_bind]);
+{$endif extdebug}
+             end;
            hp.bind:=_bind;
          end
         else
          begin
            { Not found, insert it. }
-           hp:=symclass.create(AsmSymbolDict,s,_bind,_typ);
+           hp:=symclass.create(AsmSymbolDict,namestr,_bind,_typ);
          end;
         result:=hp;
       end;
@@ -439,14 +460,27 @@ implementation
       end;
 
 
-    function TAsmData.RefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype=AT_NONE) : TAsmSymbol;
+    function TAsmData.RefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype;indirect:boolean) : TAsmSymbol;
+      var
+        namestr : TSymStr;
+        bind : tasmsymbind;
       begin
-        result:=TAsmSymbol(FAsmSymbolDict.Find(s));
+        namestr:=s;
+        if indirect then
+          begin
+            namestr:=namestr+suffix_indirect;
+            bind:=AB_EXTERNAL_INDIRECT;
+          end
+        else
+          begin
+            bind:=AB_EXTERNAL;
+          end;
+        result:=TAsmSymbol(FAsmSymbolDict.Find(namestr));
         if not assigned(result) then
-          result:=TAsmSymbol.create(AsmSymbolDict,s,AB_EXTERNAL,_typ)
+          result:=TAsmSymbol.create(AsmSymbolDict,namestr,bind,_typ)
         { one normal reference removes the "weak" character of a symbol }
         else if (result.bind=AB_WEAK_EXTERNAL) then
-          result.bind:=AB_EXTERNAL;
+          result.bind:=bind;
       end;
 
 
@@ -511,13 +545,28 @@ implementation
         inc(FNextLabelNr[alt_jump]);
       end;
 
-    procedure TAsmData.getdatalabel(out l : TAsmLabel);
+
+    procedure TAsmData.getglobaldatalabel(out l : TAsmLabel);
       begin
         l:=TAsmLabel.createglobal(AsmSymbolDict,name^,FNextLabelNr[alt_data],alt_data);
         inc(FNextLabelNr[alt_data]);
       end;
 
 
+    procedure TAsmData.getstaticdatalabel(out l : TAsmLabel);
+      begin
+        l:=TAsmLabel.createstatic(AsmSymbolDict,FNextLabelNr[alt_data],alt_data);
+        inc(FNextLabelNr[alt_data]);
+      end;
+
+
+    procedure TAsmData.getlocaldatalabel(out l: TAsmLabel);
+      begin
+        l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_data],alt_data);
+        inc(FNextLabelNr[alt_data]);
+      end;
+
+
     procedure TAsmData.getaddrlabel(out l : TAsmLabel);
       begin
         l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_addr],alt_addr);

File diff suppressed because it is too large
+ 360 - 321
compiler/aasmtai.pas


File diff suppressed because it is too large
+ 231 - 386
compiler/aggas.pas


+ 0 - 268
compiler/alpha/aasmcpu.pas

@@ -1,268 +0,0 @@
-{
-    Copyright (c) 1998-2000 by Florian Klaempfl
-
-    Implements the assembler classes specific for the Alpha
-
-    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.
-
- ****************************************************************************
-}
-{
-  Implements the assembler classes specific for the Alpha.
-}
-unit aasmcpu;
-
-{$i fpcdefs.inc}
-
-  interface
-
-    uses
-       aasmbase,globals,verbose,
-       cpubase,aasmtai,aasmdata,aasmsym;
-
-    type
-      tai_frame = class(tai)
-         G,R : TRegister;
-         LS,LU : longint;
-        Constructor Create (GP : Tregister; Localsize : Longint; RA : TRegister; L : longint);
-        end;
-
-
-      taicpu = class(tai_cpu_abstract_sym)
-         constructor op_none(op : tasmop);
-
-         constructor op_reg(op : tasmop;_op1 : tregister);
-         constructor op_const(op : tasmop;_op1 : longint);
-         constructor op_ref(op : tasmop;_op1 : preference);
-
-         constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
-         constructor op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
-         constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
-
-         constructor op_const_reg(op : tasmop;_op1 : longint;_op2 : tregister);
-         constructor op_const_const(op : tasmop;_op1,_op2 : longint);
-         constructor op_const_ref(op : tasmop;_op1 : longint;_op2 : preference);
-
-         constructor op_ref_reg(op : tasmop;_op1 : preference;_op2 : tregister);
-         { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
-         constructor op_ref_ref(op : tasmop;_op1,_op2 : preference);
-
-         constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
-         constructor op_reg_const_reg(op : tasmop;_op1 : tregister;_op2 : longint;_op3 : tregister);
-         constructor op_const_ref_reg(op : tasmop;_op1 : longint;_op2 : preference;_op3 : tregister);
-         constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; _op3 : preference);
-         constructor op_const_reg_ref(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : preference);
-         constructor op_reg_ref_const(op : tasmop;_op1 : tregister;_op2 : preference;_op3 : longint);
-
-         { 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_sym_ofs_reg(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
-         constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
-      end;
-
-      tai_align = class(tai_align_abstract)
-        { nothing to add }
-      end;
-
-    procedure InitAsm;
-    procedure DoneAsm;
-
-implementation
-
-
-{*****************************************************************************
-                                 taicpu Constructors
-*****************************************************************************}
-
-
-    constructor taicpu.op_none(op : tasmop);
-      begin
-         inherited create(op);
-      end;
-
-
-    constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
-      begin
-         inherited create(op);
-         ops:=1;
-      end;
-
-
-    constructor taicpu.op_const(op : tasmop;_op1 : longint);
-      begin
-         inherited create(op);
-         ops:=1;
-      end;
-
-
-    constructor taicpu.op_ref(op : tasmop;_op1 : preference);
-      begin
-         inherited create(op);
-         ops:=1;
-      end;
-
-
-    constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_const_reg(op : tasmop;_op1 : longint;_op2 : tregister);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_const_const(op : tasmop;_op1,_op2 : longint);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_const_ref(op : tasmop;_op1 : longint;_op2 : preference);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-    constructor taicpu.op_ref_reg(op : tasmop;_op1 : preference;_op2 : tregister);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_ref_ref(op : tasmop;_op1,_op2 : preference);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
-      begin
-         inherited create(op);
-         ops:=3;
-      end;
-
-    constructor taicpu.op_reg_const_reg(op : tasmop;_op1 : tregister;_op2 : longint;_op3 : tregister);
-      begin
-         inherited create(op);
-         ops:=3;
-      end;
-
-     constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister;_op3 : preference);
-      begin
-         inherited create(op);
-         ops:=3;
-      end;
-
-     constructor taicpu.op_const_ref_reg(op : tasmop;_op1 : longint;_op2 : preference;_op3 : tregister);
-      begin
-         inherited create(op);
-         ops:=3;
-      end;
-
-     constructor taicpu.op_const_reg_ref(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : preference);
-      begin
-         inherited create(op);
-         ops:=3;
-      end;
-
-     constructor taicpu.op_reg_ref_const(op : tasmop;_op1 : tregister;_op2 : preference;_op3 : longint);
-      begin
-         inherited create(op);
-         ops:=3;
-      end;
-
-
-    constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
-      begin
-         inherited create(op);
-         condition:=cond;
-         ops:=1;
-      end;
-
-
-    constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
-      begin
-         inherited create(op);
-         ops:=1;
-      end;
-
-
-    constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
-      begin
-         inherited create(op);
-         ops:=1;
-      end;
-
-
-    constructor taicpu.op_sym_ofs_reg(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-
-    constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
-      begin
-         inherited create(op);
-         ops:=2;
-      end;
-
-    Constructor tai_frame.create (GP : Tregister; Localsize : Longint; RA : TRegister; L : longint);
-
-    begin
-      Inherited Create;
-      typ:=ait_frame;
-      G:=GP;
-      R:=RA;
-      LS:=LocalSize;
-      LU:=L;
-    end;
-
-    procedure InitAsm;
-      begin
-      end;
-
-
-    procedure DoneAsm;
-      begin
-      end;
-
-
-    end.

+ 0 - 126
compiler/alpha/agaxpgas.pas

@@ -1,126 +0,0 @@
-{
-    Copyright (c) 1998-2000 by Florian Klaempfl
-
-    This unit implements an asm for the DEC Alpha
-
-    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 agaxpgas;
-
-  {$i fpcdefs.inc}
-
-  interface
-
-    uses
-       globals,systems,aasmbase,aasmtai,aasmdata,
-       aggas,cpubase;
-
-    type
-      TAXPGNUAssembler=class(TGNUAssembler)
-        procedure WriteInstruction(hp : tai);override;
-      end;
-
-    const
-       gas_reg2str : array[tregister] of string[4] = (
-         '',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '','',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '',''
-       );
-
-  implementation
-
-    const
-       op2str : array[tasmop] of string[14] = (
-          'addf','addg','addl','addq',
-          'adds','addt','amask','and','beq','bge',
-          'bgt','bic','bis','blbc','blbs','ble',
-          'blt','bne','br','bsr','call_pal','cmoveq',
-          'cmovge','cmovgt','cmovlbc','cmovlbs','cmovle','cmovlt',
-          'cmovne','cmpbge','cmpeq','cmpgeq','cmpgle','cmpglt',
-          'cmple','cmplt','cmpteq','cmptle','cmptlt','cmptun',
-          'cmpule','cmpult','cpys','cpyse','cpysn','ctlz',
-          'ctpop','cttz','cvtdg','cvtgd','cvtgf','cvtgq',
-          'cvtlq','cvtqf','cvtqg','cvtql','cvtqs','cvtqt',
-          'cvtst','cvttq','cvtts','divf','divg','divs',
-          'divt','ecb','eqv','excb','extbl','extlh',
-          'extll','extqh','extql','extwh','extwl','fbeq',
-          'fbge','fbgt','fble','fblt','fbne','fcmoveq',
-          'fcmovge','fcmovgt','fcmovle','fcmovlt','fcmovne','fetch',
-          'fetch_m','ftois','ftoit','implver','insbl','inslh',
-          'insll','insqh','insql','inswh','inswl','itoff',
-          'itofs','itoft','jmp','jsr','jsr_coroutine','lda',
-          'ldah','ldbu','ldwu','ldf','ldg','ldl',
-          'ldl_l','ldq','ldq_l','ldq_u','lds','ldt',
-          'maxsb8','maxsw4','maxub8','maxuw4','mb','mf_fpcr',
-          'minsb8','minsw4','minub8','minuw4','mskbl','msklh',
-          'mskll','mskqh','mskql','mskwh','mskwl','mt_fpcr',
-          'mulf','mulg','mull','mulq',
-          'muls','mult','ornot','perr','pklb','pkwb',
-          'rc','ret','rpcc','rs','s4addl','s4addq',
-          's4subl','s4subq','s8addl','s8addq','s8subl','s8subq',
-          'sextb','sextw','sll','sqrtf','sqrtg','sqrts',
-          'sqrtt','sra','srl','stb','stf','stg',
-          'sts','stl','stl_c','stq','stq_c','stq_u',
-          'stt','stw','subf','subg','subl',
-          'subq','subs','subt','trapb','umulh','unpkbl',
-          'unpkbw','wh64','wmb','xor','zap','zapnot',
-          'ldgp');
-
-      procedure TAXPGNUAssembler.WriteInstruction (hp : tai);
-        begin
-(*
-               op:=paicpu(hp)^.opcode;
-               calljmp:=is_calljmp(op);
-             { call maybe not translated to calll }
-               s:=#9+att_op2str[op]+cond2str[paicpu(hp)^.condition];
-               if (not calljmp) and
-                  (not att_nosuffix[op]) and
-                  not(
-                   (paicpu(hp)^.oper[0].typ=top_reg) and
-                   (paicpu(hp)^.oper[0].reg in [R_ST..R_ST7])
-                  ) then
-                s:=s+att_opsize2str[paicpu(hp)^.opsize];
-             { process operands }
-               if paicpu(hp)^.ops<>0 then
-                begin
-                { call and jmp need an extra handling                          }
-                { this code is only called if jmp isn't a labeled instruction }
-                  if calljmp then
-                   s:=s+#9+getopstr_jmp(paicpu(hp)^.oper[0])
-                  else
-                   begin
-                     for i:=0to paicpu(hp)^.ops-1 do
-                      begin
-                        if i=0 then
-                         sep:=#9
-                        else
-                         sep:=',';
-                        s:=s+sep+getopstr(paicpu(hp)^.oper[i])
-                      end;
-                   end;
-                end;
-               AsmWriteLn(s);
-*)
-             end;
-
-end.

+ 0 - 38
compiler/alpha/aoptcpu.pas

@@ -1,38 +0,0 @@
-{
-    Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
-    Development Team
-
-    This unit implements the Alpha 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;
-
-Interface
-
-uses cpubase, aoptobj, aoptcpub;
-
-Type
-  TAOptCpu = Object(TAoptObj)
-    { uses the same constructor as TAopObj }
-  End;
-
-Implementation
-
-End.

+ 0 - 38
compiler/alpha/aoptcpuc.pas

@@ -1,38 +0,0 @@
- {
-    Copyright (c) 1998-2000 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.

+ 0 - 168
compiler/alpha/cgcpu.pas

@@ -1,168 +0,0 @@
-{
-    Copyright (c) 1998-2000 by Florian Klaempfl
-
-    This unit implements the code generator for the Alpha
-
-    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 code generator for the Alpha.
-}
-unit cgcpu;
-
-{$i fpcdefs.inc}
-
-interface
-
-uses
-   cgbase,cgobj,aasmbase,aasmtai,aasmdata,aasmcpu,cginfo,cpubase,cpuinfo;
-
-type
-pcgalpha = ^tcgalpha;
-tcgalpha = class(tcg)
-  procedure a_call_name(list : TAsmList;const s : string);override;
-  procedure a_load_const_reg(list : TAsmList;size : tcgsize;a : aword;register : tregister);override;
-  procedure a_load_reg_ref(list : TAsmList;size : tcgsize;register : tregister;const ref : treference);override;
-  procedure a_load_ref_reg(list : TAsmList;size : tcgsize;const ref : treference;register : tregister);override;
-  procedure a_load_reg_reg(list : TAsmList;fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
-  procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;
-    reg : tregister;  l : tasmlabel);override;
-  procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
-  procedure a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister;l : tasmlabel);
-  procedure a_cmp_ref_const_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;
-    reg : tregister; l : tasmlabel);
-  procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
-  procedure g_stackframe_entry(list : TAsmList;localsize : longint);override;
-  procedure g_maybe_loadself(list : TAsmList);override;
-  procedure g_restore_frame_pointer(list : TAsmList);override;
-end;
-
-procedure create_codegen;
-
-implementation
-
-uses
-   globtype,globals;
-
-procedure tcgalpha.g_stackframe_entry(list : TAsmList;localsize : longint);
-
-begin
-   list.concat(taicpu.op_reg_ref(A_LDGP,Global_pointer,new_reference(R_27,0)));
-   list.concat(taicpu.op_reg_ref(A_LDA,stack_pointer_reg,new_reference(stack_pointer_reg,-LocalSize)));
-   If LocalSize<>0 then
-     list.concat(tai_frame.create(Global_pointer,LocalSize,R_27,0));
-   { Always generate a frame pointer. }
-   list.concat(taicpu.op_reg_reg_reg(A_BIS,stack_pointer_reg,stack_pointer_reg,frame_pointer_reg));
-end;
-
-procedure g_exitcode(list : TAsmList;parasize : longint; nostackframe,inlined : boolean);
-
-begin
-   { Restore stack pointer from frame pointer }
-   list.Concat (taicpu.op_reg_reg_reg(A_BIS,frame_pointer_reg,frame_pointer_reg,stack_pointer_reg));
-   { Restore previous stack position}
-   list.Concat (taicpu.op_reg_const_reg(A_ADDQ,stack_pointer_reg,Parasize,stack_pointer_reg));
-   { return... }
-   list.Concat(taicpu.op_reg_ref_const(A_RET,stack_pointer_reg,new_reference(Return_pointer,0),1));
-    { end directive
-    Concat (paiend,init(''));
-    }
-end;
-
-procedure tcgalpha.a_call_name(list : TAsmList;const s : string);
-
-  begin
-     { list^.concat(taicpu,op_sym(A_CALL,S_NO,newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)))); }
-     {!!!!!!!!!1 offset is ignored }
-     abstract;
-  end;
-
-procedure tcgalpha.a_load_const_reg(list : TAsmList;size : tcgsize;a : aword;register : tregister);
-
-begin
-end;
-
-
-procedure tcgalpha.a_load_reg_ref(list : TAsmList;size : tcgsize;register : tregister;const ref : treference);
-
-begin
-end;
-
-
-procedure tcgalpha.a_load_ref_reg(list : TAsmList;size : tcgsize;const ref : treference;register : tregister);
-
-begin
-end;
-
-
-procedure tcgalpha.a_load_reg_reg(list : TAsmList;fromsize, tosize : tcgsize;reg1,reg2 : tregister);
-
-begin
-end;
-
-
-procedure tcgalpha.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
-  l : tasmlabel);
-
-begin
-end;
-
-
-procedure tcgalpha.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
-
-begin
-end;
-
-
-procedure tcgalpha.a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister;l : tasmlabel);
-
-begin
-end;
-
-
-procedure tcgalpha.a_cmp_ref_const_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;
-  reg : tregister; l : tasmlabel);
-
-begin
-end;
-
-
-procedure tcgalpha.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
-
-begin
-end;
-
-
-procedure tcgalpha.g_maybe_loadself(list : TAsmList);
-
-begin
-end;
-
-
-procedure tcgalpha.g_restore_frame_pointer(list : TAsmList);
-
-begin
-end;
-
-
-procedure create_codegen;
-  begin
-    cg:=tcgalpha.create;
-    cg128:=tcg128.create;
-  end;
-
-end.

+ 0 - 431
compiler/alpha/cpubase.pas

@@ -1,431 +0,0 @@
-{
-    Copyright (C) 1998-2000 by Florian Klaempfl
-
-    This unit implements an asmlistitem class for the Alpha 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.
-
- ****************************************************************************
-}
-{
-  This unit implements an asmlistitem class for the Alpha architecture.
-}
-unit cpubase;
-
-{$i fpcdefs.inc}
-
-  interface
-
-    uses
-       cutils,cclasses,globals,aasmbase,cpuinfo,cginfo;
-
-    type
-       { all registers }
-       TRegister = (R_NO,  { R_NO is Mandatory, signifies no register }
-                    R_0,R_1,R_2,R_3,R_4,R_5,R_6,R_7,R_8,R_9,
-                    R_10,R_11,R_12,R_13,R_14,R_15,R_16,R_17,R_18,R_19,
-                    R_20,R_21,R_22,R_23,R_24,R_25,R_26,R_27,R_28,R_29,
-                    R_30,R_31,
-                    R_F0,R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,
-                    R_F10,R_F11,R_F12,R_F13,R_F14,R_F15,R_F16,R_F17,R_F18,R_F19,
-                    R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,
-                    R_F30,R_F31);
-
-       tasmop = (A_ADDF,A_ADDG,A_ADDL,A_ADDQ,
-                 A_ADDS,A_ADDT,A_AMASK,A_AND,A_BEQ,A_BGE,
-                 A_BGT,A_BIC,A_BIS,A_BLBC,A_BLBS,A_BLE,
-                 A_BLT,A_BNE,A_BR,A_BSR,A_CALL_PAL,A_CMOVEQ,
-                 A_CMOVGE,A_CMOVGT,A_CMOVLBC,A_CMOVLBS,A_CMOVLE,A_CMOVLT,
-                 A_CMOVNE,A_CMPBGE,A_CMPEQ,A_CMPGEQ,A_CMPGLE,A_CMPGLT,
-                 A_CMPLE,A_CMPLT,A_CMPTEQ,A_CMPTLE,A_CMPTLT,A_CMPTUN,
-                 A_CMPULE,A_CMPULT,A_CPYS,A_CPYSE,A_CPYSN,A_CTLZ,
-                 A_CTPOP,A_CTTZ,A_CVTDG,A_CVTGD,A_CVTGF,A_CVTGQ,
-                 A_CVTLQ,A_CVTQF,A_CVTQG,A_CVTQL,A_CVTQS,A_CVTQT,
-                 A_CVTST,A_CVTTQ,A_CVTTS,A_DIVF,A_DIVG,A_DIVS,
-                 A_DIVT,A_ECB,A_EQV,A_EXCB,A_EXTBL,A_EXTLH,
-                 A_EXTLL,A_EXTQH,A_EXTQL,A_EXTWH,A_EXTWL,A_FBEQ,
-                 A_FBGE,A_FBGT,A_FBLE,A_FBLT,A_FBNE,A_FCMOVEQ,
-                 A_FCMOVGE,A_FCMOVGT,A_FCMOVLE,A_FCMOVLT,A_FCMOVNE,A_FETCH,
-                 A_FETCH_M,A_FTOIS,A_FTOIT,A_IMPLVER,A_INSBL,A_INSLH,
-                 A_INSLL,A_INSQH,A_INSQL,A_INSWH,A_INSWL,A_ITOFF,
-                 A_ITOFS,A_ITOFT,A_JMP,A_JSR,A_JSR_COROUTINE,A_LDA,
-                 A_LDAH,A_LDBU,A_LDWU,A_LDF,A_LDG,A_LDL,
-                 A_LDL_L,A_LDQ,A_LDQ_L,A_LDQ_U,A_LDS,A_LDT,
-                 A_MAXSB8,A_MAXSW4,A_MAXUB8,A_MAXUW4,A_MB,A_MF_FPCR,
-                 A_MINSB8,A_MINSW4,A_MINUB8,A_MINUW4,A_MSKBL,A_MSKLH,
-                 A_MSKLL,A_MSKQH,A_MSKQL,A_MSKWH,A_MSKWL,A_MT_FPCR,
-                 A_MULF,A_MULG,A_MULL,A_MULQ,
-                 A_MULS,A_MULT,A_ORNOT,A_PERR,A_PKLB,A_PKWB,
-                 A_RC,A_RET,A_RPCC,A_RS,A_S4ADDL,A_S4ADDQ,
-                 A_S4SUBL,A_S4SUBQ,A_S8ADDL,A_S8ADDQ,A_S8SUBL,A_S8SUBQ,
-                 A_SEXTB,A_SEXTW,A_SLL,A_SQRTF,A_SQRTG,A_SQRTS,
-                 A_SQRTT,A_SRA,A_SRL,A_STB,A_STF,A_STG,
-                 A_STS,A_STL,A_STL_C,A_STQ,A_STQ_C,A_STQ_U,
-                 A_STT,A_STW,A_SUBF,A_SUBG,A_SUBL,
-                 A_SUBQ,A_SUBS,A_SUBT,A_TRAPB,A_UMULH,
-                 A_UNPKBL,A_UNPKBW,A_WH64,A_WMB,A_XOR,A_ZAP,
-                 A_ZAPNOT
-                 { Psuedo code understood by the gnu assembler }
-                 ,A_LDGP);
-
-    const
-       firstop = low(tasmop);
-       lastop  = high(tasmop);
-
-       std_reg2str : array[tregister] of string[4] = (
-         '',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '','',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '','','','','','','','','','',
-         '',''
-       );
-
-
-    type
-       TAsmCond =
-        (
-         C_None,C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
-         C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,C_NS,C_NZ,C_O,C_P,
-         C_PE,C_PO,C_S,C_Z
-        );
-
-        TRegisterset = Set of TRegister;
-
-        tregister64 = tregister;
-
-    Const
-       Firstreg = R_0;
-       LastReg = R_F31;
-
-
-{*****************************************************************************
-                          Default generic sizes
-*****************************************************************************}
-
-       { Defines the default address size for a processor, }
-       OS_ADDR = OS_64;
-       { the natural int size for a processor,
-         has to match osuinttype/ossinttype as initialized in psystem }
-       OS_INT = OS_64;
-       { the maximum float size for a processor,           }
-       OS_FLOAT = OS_F80;
-       { the size of a vector register for a processor     }
-       OS_VECTOR = OS_M64;
-
-       stack_pointer_reg = R_30;
-       frame_pointer_reg = R_15;
-       self_pointer_reg = R_16;
-       accumulator   = R_0;
-  {the return_result_reg, is used inside the called function to store its return
-  value when that is a scalar value otherwise a pointer to the address of the
-  result is placed inside it}
-        return_result_reg               =       accumulator;
-
-  {the function_result_reg contains the function result after a call to a scalar
-  function othewise it contains a pointer to the returned result}
-        function_result_reg     =       accumulator;
-       fpu_result_reg = R_F0;
-       global_pointer = R_29;
-       return_pointer = R_26;
-       { it is used to pass the offset to the destructor helper routine }
-       vmt_offset_reg = R_1;
-
-     { low and high of the available maximum width integer general purpose }
-     { registers                                                           }
-       LoGPReg = R_0;
-       HiGPReg = R_31;
-
-       { low and high of every possible width general purpose register (same as
-         above on most architctures apart from the 80x86)                       }
-       LoReg = R_0;
-       HiReg = R_31;
-
-       maxfpuregs = 32;
-
-       max_operands = 4;
-
-       registers_saved_on_cdecl = [R_9..R_14,R_F2..R_F9];
-
-       maxvarregs = 6;
-       varregs : Array [1..maxvarregs] of Tregister =
-                 (R_9,R_10,R_11,R_12,R_13,R_14);
-
-       maxfpuvarregs = 8;
-
-       { Registers which are defined as scratch and no need to save across
-         routine calls or in assembler blocks.
-       }
-       max_scratch_regs = 2;
-       scratch_regs : array[1..max_scratch_regs] of tregister = (R_1,R_2);
-
-{*****************************************************************************
-                               GDB Information
-*****************************************************************************}
-
-       {  Register indexes for stabs information, when some
-         parameters or variables are stored in registers.
-       }
-       stab_regindex : array[tregister] of shortint =
-          (0,
-           0,0,0,0,0,0,0,0,0,0,
-           0,0,0,0,0,0,0,0,0,0,
-           0,0,0,0,0,0,0,0,0,0,
-           0,0,
-           0,0,0,0,0,0,0,0,0,0,
-           0,0,0,0,0,0,0,0,0,0,
-           0,0,0,0,0,0,0,0,0,0,
-           0,0
-          );
-
-{*****************************************************************************
-                                   Flags
-*****************************************************************************}
-       type
-       { The Alpha doesn't have flags but some generic code depends on this type. }
-       TResFlags = (F_NO);
-
-
-       { reference record }
-       pparareference = ^tparareference;
-       tparareference = packed record
-          index       : tregister;
-          offset      : longint;
-       end;
-
-       trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
-
-       TReference = record
-         offset : aword;
-         symbol : tasmsymbol;
-         base : tregister;
-         { The index isn't used by the alpha port, but some generic code depends on it }
-         index : tregister;
-         is_immediate : boolean;
-         offsetfixup : word; {needed for inline}
-         options     : trefoptions;
-         { the boundary to which the reference is surely aligned }
-         alignment : byte;
-       end;
-       PReference = ^TReference;
-
-       TLoc=(
-              LOC_INVALID,      { added for tracking problems}
-              LOC_CONSTANT,     { constant value }
-              LOC_JUMP,         { boolean results only, jump to false or true label }
-              LOC_FLAGS,        { boolean results only, flags are set }
-              LOC_CREFERENCE,   { in memory constant value reference (cannot change) }
-              LOC_REFERENCE,    { in memory value }
-              LOC_REGISTER,     { in a processor register }
-              LOC_CREGISTER,    { Constant register which shouldn't be modified }
-              LOC_FPUREGISTER,  { FPU stack }
-              LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
-              LOC_SSEREGISTER,
-              LOC_CSSEREGISTER,
-              LOC_CMMREGISTER,
-              LOC_MMREGISTER
-            );
-
-      { tparamlocation describes where a parameter for a procedure is stored.
-        References are given from the caller's point of view. The usual
-        TLocation isn't used, because contains a lot of unnessary fields.
-      }
-      tparalocation = packed record
-         size : TCGSize;
-         loc  : TLoc;
-         sp_fixup : longint;
-         case TLoc of
-            LOC_REFERENCE : (reference : tparareference);
-            { segment in reference at the same place as in loc_register }
-            LOC_REGISTER,LOC_CREGISTER : (
-              case longint of
-                1 : (register,register64.reghi : tregister);
-                { overlay a register64.reglo }
-                2 : (register64.reglo : tregister);
-                { overlay a 64 Bit register type }
-                3 : (reg64 : tregister64);
-                4 : (register64 : tregister64);
-              );
-      end;
-
-      tlocation = packed record
-         loc  : TLoc;
-         size : TCGSize;
-         case TLoc of
-            LOC_CONSTANT : (
-              case longint of
-                1 : (value : AWord);
-                { can't do this, this layout depends on the host cpu. Use }
-                { lo(valueqword)/hi(valueqword) instead (JM)              }
-                { 2 : (valuelow, valuehigh:AWord);                        }
-                { overlay a complete 64 Bit value }
-                3 : (valueqword : qword);
-              );
-            LOC_CREFERENCE,
-            LOC_REFERENCE : (reference : treference);
-            { segment in reference at the same place as in loc_register }
-            LOC_REGISTER,LOC_CREGISTER : (
-              case longint of
-                1 : (register,register64.reghi,segment : tregister);
-                { overlay a register64.reglo }
-                2 : (register64.reglo : tregister);
-                { overlay a 64 Bit register type }
-                3 : (reg64 : tregister64);
-                4 : (register64 : tregister64);
-              );
-      end;
-
-{*****************************************************************************
-                                Operands
-*****************************************************************************}
-
-
-        { Types of operand }
-        toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
-
-        toper=record
-          ot  : longint;
-          case typ : toptype of
-           top_none   : ();
-           top_reg    : (reg:tregister);
-           top_ref    : (ref:preference);
-           top_const  : (val:longint);
-           top_symbol : (sym:tasmsymbol;symofs:longint);
-        end;
-
-   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.
-      }
-      std_saved_registers = [];
-      { 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 = 8;
-
-      { offsets for the integer and floating point registers }
-      INT_REG = 0;
-      FLOAT_REG = 32;
-
-      { operator qualifiers }
-      OQ_CHOPPED_ROUNDING            = $01;  { /C }
-      OQ_ROUNDING_MODE_DYNAMIC       = $02;  { /D }
-      OQ_ROUND_TOWARD_MINUS_INFINITY = $04;  { /M }
-      OQ_INEXACT_RESULT_ENABLE        = $08; { /I }
-      OQ_SOFTWARE_COMPLETION_ENABLE  = $10;  { /S }
-      OQ_FLOATING_UNDERFLOW_ENABLE   = $20;  { /U }
-      OQ_INTEGER_OVERFLOW_ENABLE     = $40;  { /V }
-
-
-{*****************************************************************************
-                   Opcode propeties (needed for optimizer)
-*****************************************************************************}
-
-{$ifndef NOOPT}
-Type
-{What an instruction can change}
-  TInsChange = (Ch_None);
-{$endif}
-
-
-{ resets all values of ref to defaults }
-procedure reset_reference(var ref : treference);
-{ set mostly used values of a new reference }
-function new_reference(base : tregister;offset : longint) : preference;
-function newreference(const r : treference) : preference;
-procedure disposereference(var r : preference);
-
-function reg2str(r : tregister) : string;
-
-{*****************************************************************************
-                                  Init/Done
-*****************************************************************************}
-
-  procedure InitCpu;
-  procedure DoneCpu;
-
-implementation
-
-uses
-   verbose;
-
-function reg2str(r : tregister) : string;
-
-  begin
-     if r in [R_0..R_31] then
-       reg2str:='R'+tostr(longint(r)-longint(R_0))
-     else if r in [R_F0..R_F31] then
-       reg2str:='F'+tostr(longint(r)-longint(R_F0))
-     else internalerror(38991);
-  end;
-
-procedure reset_reference(var ref : treference);
-begin
-  FillChar(ref,sizeof(treference),0);
-end;
-
-
-function new_reference(base : tregister;offset : longint) : preference;
-var
-  r : preference;
-begin
-  new(r);
-  FillChar(r^,sizeof(treference),0);
-  r^.offset:=offset;
-  r^.alignment:=8;
-  new_reference:=r;
-end;
-
-function newreference(const r : treference) : preference;
-
-var
-   p : preference;
-begin
-   new(p);
-   p^:=r;
-   newreference:=p;
-end;
-
-procedure disposereference(var r : preference);
-
-begin
-  dispose(r);
-  r:=Nil;
-end;
-
-{*****************************************************************************
-                                  Init/Done
-*****************************************************************************}
-
-  procedure InitCpu;
-    begin
-    end;
-
-  procedure DoneCpu;
-    begin
-    end;
-
-end.

+ 0 - 68
compiler/alpha/cpuinfo.pas

@@ -1,68 +0,0 @@
-{
-    This file is part of the Free Pascal run time library.
-    Copyright (c) 1998-2000 by the Free Pascal development team
-
-    Basic Processor information about the Alpha
-
-    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.
-
- **********************************************************************}
-{
-  Basic Processor information about the Alpha
-}
-Unit CPUInfo;
-
-{$i fpcdefs.inc}
-
-Interface
-
-Type
-   { Natural integer register type and size for the target machine }
-{$ifdef FPC}
-   AWord = Qword;
-{$else FPC}
-   AWord = Longint;
-{$endif FPC}
-   PAWord = ^AWord;
-
-   { This must be an ordinal type with the same size as a pointer
-     Note: Must be unsigned! Otherwise, ugly code like
-     pointer(-1) will result in a pointer with the value
-     $fffffffffffffff on a 32bit machine if the compiler uses
-     int64 constants internally (JM)                              }
-   TConstPtrUInt = qword;
-
-   bestreal = extended;
-   ts32real = single;
-   ts64real = double;
-   ts80real = extended;
-   ts64comp = extended;
-
-   pbestreal=^bestreal;
-
-   { possible supported processors for this target }
-   tcputype =
-      (cpu_none,
-       ClassEV7,
-       ClassEV8
-      );
-
-Const
-   { Size of native extended type }
-   extended_size = 16;
-   {# Size of a pointer                           }
-   aint_size  = 8;
-   {# Size of a multimedia register               }
-   mmreg_size = 8;
-
-   { target cpu string (used by compiler options) }
-   target_cpu_string = 'alpha';
-
-Implementation
-
-end.

+ 0 - 56
compiler/alpha/cpunode.pas

@@ -1,56 +0,0 @@
-{
-    Copyright (c) 2000-2002 by Florian Klaempfl
-
-    Imports the Alpha code generator
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
-}
-{
-  This unit imports the Alpha code generator.
-}
-unit cpunode;
-
-{$i fpcdefs.inc}
-
-  interface
-
-  implementation
-
-    uses
-       { generic nodes }
-       ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,
-       { to be able to only parts of the generic code,
-         the processor specific nodes must be included
-         after the generic one (FK)
-       }
-//       naxpadd,
-//       naxpcal,
-//       naxpcon,
-//       naxpflw,
-//       naxpmem,
-//       naxpset,
-//       naxpinl,
-//       nppcopt,
-       { this not really a node }
-//       naxpobj,
-//       naxpmat,
-//       naxpcnv,
-         { symtable }
-         symcpu
-       ;
-
-end.

+ 0 - 290
compiler/alpha/cpupara.pas

@@ -1,290 +0,0 @@
-{
-    Copyright (c) 2002 by Florian Klaempfl
-
-    Alpha specific calling conventions
-
-    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.
- ****************************************************************************
-}
-{ Alpha specific calling conventions are handled by this unit
-}
-unit cpupara;
-
-{$i fpcdefs.inc}
-
-  interface
-
-    uses
-       cpubase,
-       symconst,symbase,symtype,symdef,paramgr;
-
-    type
-       talphaparamanager = class(tparamanager)
-          function getintparaloc(nr : longint) : tparalocation;override;
-          procedure create_param_loc_info(p : tabstractprocdef);override;
-          function getfuncretparaloc(p : tabstractprocdef) : tparalocation;override;
-       end;
-
-  implementation
-
-    uses
-       verbose,
-       globtype,
-       cpuinfo,cginfo,cgbase,
-       defbase;
-
-    function talphaparamanager.getintparaloc(nr : longint) : tparalocation;
-
-      begin
-         fillchar(result,sizeof(tparalocation),0);
-         if nr<1 then
-           internalerror(2002070801)
-         else if nr<=8 then
-           begin
-              result.loc:=LOC_REGISTER;
-              result.register:=tregister(longint(R_2)+nr);
-           end
-         else
-           begin
-              result.loc:=LOC_REFERENCE;
-              result.reference.index:=stack_pointer_reg;
-              result.reference.offset:=(nr-8)*4;
-           end;
-      end;
-
-    function getparaloc(p : tdef) : tloc;
-
-      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_FPUREGISTER;
-            enumdef:
-              getparaloc:=LOC_REGISTER;
-            pointerdef:
-              getparaloc:=LOC_REGISTER;
-            formaldef:
-              getparaloc:=LOC_REGISTER;
-            classrefdef:
-              getparaloc:=LOC_REGISTER;
-            recorddef:
-              getparaloc:=LOC_REFERENCE;
-            objectdef:
-              if is_object(p) then
-                getparaloc:=LOC_REFERENCE
-              else
-                getparaloc:=LOC_REGISTER;
-            stringdef:
-              if is_shortstring(p) or is_longstring(p) then
-                getparaloc:=LOC_REFERENCE
-              else
-                getparaloc:=LOC_REGISTER;
-            procvardef:
-              if (po_methodpointer in tprocvardef(p).procoptions) then
-                getparaloc:=LOC_REFERENCE
-              else
-                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_REFERENCE;
-            { avoid problems with errornous definitions }
-            errordef:
-              getparaloc:=LOC_REGISTER;
-            else
-              internalerror(2002071001);
-         end;
-      end;
-
-    procedure talphaparamanager.create_param_loc_info(p : tabstractprocdef);
-
-      var
-         nextintreg,nextfloatreg,nextmmreg : tregister;
-         stack_offset : aword;
-         hp : tparaitem;
-         loc : tloc;
-         is_64bit: boolean;
-
-      begin
-         nextintreg:=R_3;
-         nextfloatreg:=R_F1;
-         // nextmmreg:=R_M1;
-         stack_offset:=0;
-         { pointer for structured results ? }
-         if not is_void(p.returndef) then
-           begin
-              if not(ret_in_reg(p.returndef)) then
-                inc(nextintreg);
-           end;
-
-         { frame pointer for nested procedures? }
-         { inc(nextintreg);                     }
-         { constructor? }
-         { destructor? }
-         hp:=tparaitem(p.para.last);
-         while assigned(hp) do
-           begin
-              loc:=getparaloc(hp.paratype.def);
-              hp.paraloc.sp_fixup:=0;
-              case loc of
-                 LOC_REGISTER:
-                   begin
-                      hp.paraloc.size := def_cgsize(hp.paratype.def);
-                      { for things like formaldef }
-                      if hp.paraloc.size = OS_NO then
-                        hp.paraloc.size := OS_ADDR;
-                      is_64bit := hp.paraloc.size in [OS_64,OS_S64];
-                      if nextintreg<=tregister(ord(R_10)-ord(is_64bit))  then
-                        begin
-                           hp.paraloc.loc:=LOC_REGISTER;
-                           hp.paraloc.register64.reglo:=nextintreg;
-                           inc(nextintreg);
-                           if is_64bit then
-                             begin
-                               hp.paraloc.register64.reghi:=nextintreg;
-                               inc(nextintreg);
-                             end;
-                        end
-                      else
-                         begin
-                            nextintreg := R_11;
-                            hp.paraloc.loc:=LOC_REFERENCE;
-                            hp.paraloc.reference.index:=stack_pointer_reg;
-                            hp.paraloc.reference.offset:=stack_offset;
-                            if not is_64bit then
-                              inc(stack_offset,4)
-                            else
-                              inc(stack_offset,8);
-                        end;
-                   end;
-                 LOC_FPUREGISTER:
-                   begin
-                      if hp.paratyp in [vs_var,vs_out] then
-                        begin
-                            if nextintreg<=R_10 then
-                             begin
-                                hp.paraloc.size:=OS_ADDR;
-                                hp.paraloc.loc:=LOC_REGISTER;
-                                hp.paraloc.register:=nextintreg;
-                                inc(nextintreg);
-                             end
-                           else
-                              begin
-                                 {!!!!!!!}
-                                 hp.paraloc.size:=def_cgsize(hp.paratype.def);
-                                 internalerror(2002071006);
-                             end;
-                        end
-                      else if nextfloatreg<=R_F10 then
-                        begin
-                           hp.paraloc.size:=def_cgsize(hp.paratype.def);
-                           hp.paraloc.loc:=LOC_FPUREGISTER;
-                           hp.paraloc.register:=nextfloatreg;
-                           inc(nextfloatreg);
-                        end
-                      else
-                         begin
-                            {!!!!!!!}
-                             hp.paraloc.size:=def_cgsize(hp.paratype.def);
-                            internalerror(2002071004);
-                        end;
-                   end;
-                 LOC_REFERENCE:
-                   begin
-                      hp.paraloc.size:=OS_ADDR;
-                      if push_addr_param(hp.paratype.def,p.proccalloption in [pocall_cdecl,pocall_cppdecl]) or (hp.paratyp in [vs_var,vs_out]) then
-                        begin
-                           if nextintreg<=R_10 then
-                             begin
-                                hp.paraloc.loc:=LOC_REGISTER;
-                                hp.paraloc.register:=nextintreg;
-                                inc(nextintreg);
-                             end
-                           else
-                              begin
-                                 hp.paraloc.loc:=LOC_REFERENCE;
-                                 hp.paraloc.reference.index:=stack_pointer_reg;
-                                 hp.paraloc.reference.offset:=stack_offset;
-                                 inc(stack_offset,4);
-                             end;
-                        end
-                      else
-                        begin
-                           hp.paraloc.loc:=LOC_REFERENCE;
-                           hp.paraloc.reference.index:=stack_pointer_reg;
-                           hp.paraloc.reference.offset:=stack_offset;
-                           inc(stack_offset,hp.paratype.def.size);
-                        end;
-                   end;
-                 else
-                   internalerror(2002071002);
-              end;
-              hp:=tparaitem(hp.previous);
-           end;
-      end;
-
-    function talphaparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
-      begin
-         case p.returndef.typ of
-            orddef,
-            enumdef:
-              begin
-                getfuncretparaloc.loc:=LOC_REGISTER;
-                getfuncretparaloc.register:=R_3;
-                getfuncretparaloc.size:=def_cgsize(p.returndef);
-                if getfuncretparaloc.size in [OS_S64,OS_64] then
-                  getfuncretparaloc.register64.reghi:=R_4;
-              end;
-            floatdef:
-              begin
-                getfuncretparaloc.loc:=LOC_FPUREGISTER;
-                getfuncretparaloc.register:=R_F1;
-                getfuncretparaloc.size:=def_cgsize(p.returndef);
-              end;
-            pointerdef,
-            formaldef,
-            classrefdef,
-            recorddef,
-            objectdef,
-            stringdef,
-            procvardef,
-            filedef,
-            arraydef,
-            errordef:
-              begin
-                getfuncretparaloc.loc:=LOC_REGISTER;
-                getfuncretparaloc.register:=R_3;
-                getfuncretparaloc.size:=OS_ADDR;
-              end;
-            else
-              internalerror(2002090903);
-        end;
-      end;
-
-
-begin
-   paramanager:=talphaparamanager.create;
-end.

+ 0 - 0
compiler/alpha/radirect.pas


+ 0 - 65
compiler/alpha/rasm.pas

@@ -1,65 +0,0 @@
-{
-    Copyright (c) 1998-2002 by The Free Pascal Team
-
-    This unit does the parsing process for the 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.
-
- ****************************************************************************
-}
-{
-  This unit does the parsing process for the inline assembler.
-}
-Unit Rasm;
-
-{$i fpcdefs.inc}
-
-Interface
-
-uses
-  node;
-
-   {
-     This routine is called to parse the instructions in assembler
-     blocks. It returns a complete list of directive and instructions
-   }
-   function assemble: tnode;
-
-
-Implementation
-
-    uses
-       { common }
-       cutils,cclasses,
-       { global }
-       globtype,globals,verbose,
-       systems,
-       { aasm }
-       cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
-       { symtable }
-       symconst,symbase,symtype,symsym,symtable,
-       { pass 1 }
-       nbas,
-       { parser }
-       scanner
-       // ,rautils
-       ;
-
-    function assemble : tnode;
-     begin
-     end;
-
-Begin
-end.

+ 0 - 69
compiler/alpha/rgcpu.pas

@@ -1,69 +0,0 @@
-{
-    Copyright (c) 1998-2002 by Florian Klaempfl
-
-    This unit implements the powerpc 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,
-       cpubase,
-       rgobj;
-
-     type
-       trgcpu = class(trgobj)
-         function getcpuregisterint(list: TAsmList; reg: tregister): tregister; override;
-         procedure ungetregisterint(list: TAsmList; reg: tregister); override;
-       end;
-
-  implementation
-
-    uses
-      cgobj;
-
-    function trgcpu.getcpuregisterint(list: TAsmList; reg: tregister): tregister;
-
-      begin
-        if reg = R_0 then
-          begin
-            cg.a_reg_alloc(list,reg);
-            result := reg;
-          end
-        else result := inherited getcpuregisterint(list,reg);
-      end;
-
-
-    procedure trgcpu.ungetregisterint(list: TAsmList; reg: tregister);
-
-      begin
-        if reg = R_0 then
-          cg.a_reg_dealloc(list,reg)
-        else
-          inherited ungetregisterint(list,reg);
-      end;
-
-initialization
-  rg := trgcpu.create;
-end.

+ 0 - 211
compiler/alpha/symcpu.pas

@@ -1,211 +0,0 @@
-{
-    Copyright (c) 2014 by Florian Klaempfl
-
-    Symbol table overrides for Alpha
-
-    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 symcpu;
-
-{$i fpcdefs.inc}
-
-interface
-
-uses
-  symtype,symdef,symsym;
-
-type
-  { defs }
-  tcpufiledef = class(tfiledef)
-  end;
-  tcpufiledefclass = class of tcpufiledef;
-
-  tcpuvariantdef = class(tvariantdef)
-  end;
-  tcpuvariantdefclass = class of tcpuvariantdef;
-
-  tcpuformaldef = class(tformaldef)
-  end;
-  tcpuformaldefclass = class of tcpuformaldef;
-
-  tcpuforwarddef = class(tforwarddef)
-  end;
-  tcpuforwarddefclass = class of tcpuforwarddef;
-
-  tcpuundefineddef = class(tundefineddef)
-  end;
-  tcpuundefineddefclass = class of tcpuundefineddef;
-
-  tcpuerrordef = class(terrordef)
-  end;
-  tcpuerrordefclass = class of tcpuerrordef;
-
-  tcpupointerdef = class(tpointerdef)
-  end;
-  tcpupointerdefclass = class of tcpupointerdef;
-
-  tcpurecorddef = class(trecorddef)
-  end;
-  tcpurecorddefclass = class of tcpurecorddef;
-
-  tcpuimplementedinterface = class(timplementedinterface)
-  end;
-  tcpuimplementedinterfaceclass = class of tcpuimplementedinterface;
-
-  tcpuobjectdef = class(tobjectdef)
-  end;
-  tcpuobjectdefclass = class of tcpuobjectdef;
-
-  tcpuclassrefdef = class(tclassrefdef)
-  end;
-  tcpuclassrefdefclass = class of tcpuclassrefdef;
-
-  tcpuarraydef = class(tarraydef)
-  end;
-  tcpuarraydefclass = class of tcpuarraydef;
-
-  tcpuorddef = class(torddef)
-  end;
-  tcpuorddefclass = class of tcpuorddef;
-
-  tcpufloatdef = class(tfloatdef)
-  end;
-  tcpufloatdefclass = class of tcpufloatdef;
-
-  tcpuprocvardef = class(tprocvardef)
-  end;
-  tcpuprocvardefclass = class of tcpuprocvardef;
-
-  tcpuprocdef = class(tprocdef)
-  end;
-  tcpuprocdefclass = class of tcpuprocdef;
-
-  tcpustringdef = class(tstringdef)
-  end;
-  tcpustringdefclass = class of tcpustringdef;
-
-  tcpuenumdef = class(tenumdef)
-  end;
-  tcpuenumdefclass = class of tcpuenumdef;
-
-  tcpusetdef = class(tsetdef)
-  end;
-  tcpusetdefclass = class of tcpusetdef;
-
-  { syms }
-  tcpulabelsym = class(tlabelsym)
-  end;
-  tcpulabelsymclass = class of tcpulabelsym;
-
-  tcpuunitsym = class(tunitsym)
-  end;
-  tcpuunitsymclass = class of tcpuunitsym;
-
-  tcpunamespacesym = class(tnamespacesym)
-  end;
-  tcpunamespacesymclass = class of tcpunamespacesym;
-
-  tcpuprocsym = class(tprocsym)
-  end;
-  tcpuprocsymclass = class of tcpuprocsym;
-
-  tcputypesym = class(ttypesym)
-  end;
-  tcpuypesymclass = class of tcputypesym;
-
-  tcpufieldvarsym = class(tfieldvarsym)
-  end;
-  tcpufieldvarsymclass = class of tcpufieldvarsym;
-
-  tcpulocalvarsym = class(tlocalvarsym)
-  end;
-  tcpulocalvarsymclass = class of tcpulocalvarsym;
-
-  tcpuparavarsym = class(tparavarsym)
-  end;
-  tcpuparavarsymclass = class of tcpuparavarsym;
-
-  tcpustaticvarsym = class(tstaticvarsym)
-  end;
-  tcpustaticvarsymclass = class of tcpustaticvarsym;
-
-  tcpuabsolutevarsym = class(tabsolutevarsym)
-  end;
-  tcpuabsolutevarsymclass = class of tcpuabsolutevarsym;
-
-  tcpupropertysym = class(tpropertysym)
-  end;
-  tcpupropertysymclass = class of tcpupropertysym;
-
-  tcpuconstsym = class(tconstsym)
-  end;
-  tcpuconstsymclass = class of tcpuconstsym;
-
-  tcpuenumsym = class(tenumsym)
-  end;
-  tcpuenumsymclass = class of tcpuenumsym;
-
-  tcpusyssym = class(tsyssym)
-  end;
-  tcpusyssymclass = class of tcpusyssym;
-
-
-const
-  pbestrealtype : ^tdef = @s64floattype;
-
-
-implementation
-
-begin
-  { used tdef classes }
-  cfiledef:=tcpufiledef;
-  cvariantdef:=tcpuvariantdef;
-  cformaldef:=tcpuformaldef;
-  cforwarddef:=tcpuforwarddef;
-  cundefineddef:=tcpuundefineddef;
-  cerrordef:=tcpuerrordef;
-  cpointerdef:=tcpupointerdef;
-  crecorddef:=tcpurecorddef;
-  cimplementedinterface:=tcpuimplementedinterface;
-  cobjectdef:=tcpuobjectdef;
-  cclassrefdef:=tcpuclassrefdef;
-  carraydef:=tcpuarraydef;
-  corddef:=tcpuorddef;
-  cfloatdef:=tcpufloatdef;
-  cprocvardef:=tcpuprocvardef;
-  cprocdef:=tcpuprocdef;
-  cstringdef:=tcpustringdef;
-  cenumdef:=tcpuenumdef;
-  csetdef:=tcpusetdef;
-
-  { used tsym classes }
-  clabelsym:=tcpulabelsym;
-  cunitsym:=tcpuunitsym;
-  cnamespacesym:=tcpunamespacesym;
-  cprocsym:=tcpuprocsym;
-  ctypesym:=tcputypesym;
-  cfieldvarsym:=tcpufieldvarsym;
-  clocalvarsym:=tcpulocalvarsym;
-  cparavarsym:=tcpuparavarsym;
-  cstaticvarsym:=tcpustaticvarsym;
-  cabsolutevarsym:=tcpuabsolutevarsym;
-  cpropertysym:=tcpupropertysym;
-  cconstsym:=tcpuconstsym;
-  cenumsym:=tcpuenumsym;
-  csyssym:=tcpusyssym;
-end.
-

+ 8 - 15
compiler/aopt.pas

@@ -40,13 +40,17 @@ Unit aopt;
         Constructor create(_AsmL: TAsmList); virtual; reintroduce;
 
         { call the necessary optimizer procedures }
-        Procedure Optimize;
+        Procedure Optimize;virtual;
         Destructor destroy;override;
 
       private
         procedure FindLoHiLabels;
+
+        { Builds a table with the locations of the labels in the TAsmList.
+          Also fixes some RegDeallocs like "# %eax released; push (%eax)"  }
         Procedure BuildLabelTableAndFixRegAlloc;
         procedure clear;
+      protected
         procedure pass_1;
       End;
       TAsmOptimizerClass = class of TAsmOptimizer;
@@ -121,9 +125,8 @@ Unit aopt;
           End
       End;
 
+
     Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
-    { Builds a table with the locations of the labels in the TAsmList.       }
-    { Also fixes some RegDeallocs like "# %eax released; push (%eax)"           }
     Var p,hp1, hp2: tai;
         Regs: TAllUsedRegs;
         LabelIdx : longint;
@@ -187,7 +190,7 @@ Unit aopt;
                         hp2 := nil;
                         While Not(assigned(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next)))) And
                               GetNextInstruction(hp1, hp1) And
-                              RegInInstruction(tai_regalloc(p).Reg, hp1) Do
+                              InstructionLoadsFromReg(tai_regalloc(p).Reg, hp1) Do
                           hp2 := hp1;
                         { move deallocations }
                         If hp2 <> nil Then
@@ -277,14 +280,6 @@ Unit aopt;
                 if pass = 0 then
                   PeepHoleOptPass1;
               end;
-            If (cs_opt_asmcse in current_settings.optimizerswitches) Then
-              Begin
-//                DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
-                { data flow analyzer }
-//                DFA.DoDFA;
-                { common subexpression elimination }
-      {          CSE;}
-              End;
             { more peephole optimizations }
             if (cs_opt_peephole in current_settings.optimizerswitches) then
               begin
@@ -337,7 +332,7 @@ Unit aopt;
 
     procedure TAsmScheduler.SchedulerPass1;
       var
-        p,hp1,hp2 : tai;
+        p : tai;
       begin
         p:=BlockStart;
         while p<>BlockEnd Do
@@ -352,9 +347,7 @@ Unit aopt;
     procedure TAsmScheduler.Optimize;
       Var
         HP: tai;
-        pass: longint;
       Begin
-        pass:=0;
         BlockStart := tai(AsmL.First);
         While Assigned(BlockStart) Do
           Begin

+ 31 - 1
compiler/aoptbase.pas

@@ -95,6 +95,16 @@ unit aoptbase;
 
         { returns true if reg is modified by any instruction between p1 and p2 }
         function RegModifiedBetween(reg: TRegister; p1, p2: tai): Boolean;
+
+        { returns true if reg is loaded with a new value by hp }
+        function RegLoadedWithNewValue(reg: tregister; hp: tai): boolean; Virtual;
+
+        { returns true if hp loads a value from reg }
+        function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; Virtual;
+
+        { compares reg1 and reg2 having the same type and being the same super registers
+          so the register size is neglected }
+        function SuperRegistersEqual(reg1,reg2 : TRegister) : Boolean;
     end;
 
     function labelCanBeSkipped(p: tai_label): boolean;
@@ -102,7 +112,7 @@ unit aoptbase;
   implementation
 
     uses
-      globtype,globals,aoptcpub;
+      verbose,globtype,globals,aoptcpub;
 
   constructor taoptbase.create;
     begin
@@ -285,6 +295,26 @@ unit aoptbase;
   end;
 
 
+  function TAoptBase.RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean;
+    begin
+      result:=false;
+      internalerror(2016012401);
+    end;
+
+
+  function TAoptBase.InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean;
+    begin
+      { save approximation }
+      Result:=true;
+    end;
+
+
+  function TAOptBase.SuperRegistersEqual(reg1,reg2 : TRegister) : Boolean;
+  Begin
+    Result:=(getregtype(reg1) = getregtype(reg2)) and
+            (getsupreg(reg1) = getsupreg(Reg2));
+  end;
+
   { ******************* Processor dependent stuff *************************** }
 
   Function TAOptBase.RegMaxSize(Reg: TRegister): TRegister;

+ 143 - 44
compiler/aoptobj.pas

@@ -315,6 +315,10 @@ Unit AoptObj;
         { reg used after p? }
         function RegUsedAfterInstruction(reg: Tregister; p: tai; var AllUsedRegs: TAllUsedRegs): Boolean;
 
+        { returns true if reg reaches it's end of life at p, this means it is either
+          reloaded with a new value or it is deallocated afterwards }
+        function RegEndOfLife(reg: TRegister;p: taicpu): boolean;
+
        { traces sucessive jumps to their final destination and sets it, e.g.
          je l1                je l3
          <code>               <code>
@@ -335,14 +339,16 @@ Unit AoptObj;
         procedure RemoveDelaySlot(hp1: tai);
 
         { peephole optimizer }
-        procedure PrePeepHoleOpts;
-        procedure PeepHoleOptPass1;
+        procedure PrePeepHoleOpts; virtual;
+        procedure PeepHoleOptPass1; virtual;
         procedure PeepHoleOptPass2; virtual;
-        procedure PostPeepHoleOpts;
+        procedure PostPeepHoleOpts; virtual;
 
         { processor dependent methods }
         // if it returns true, perform a "continue"
+        function PrePeepHoleOptsCpu(var p: tai): boolean; virtual;
         function PeepHoleOptPass1Cpu(var p: tai): boolean; virtual;
+        function PeepHoleOptPass2Cpu(var p: tai): boolean; virtual;
         function PostPeepHoleOptsCpu(var p: tai): boolean; virtual;
       End;
 
@@ -361,7 +367,7 @@ Unit AoptObj;
 
     function JumpTargetOp(ai: taicpu): poper; inline;
       begin
-{$ifdef MIPS}
+{$if defined(MIPS)}
         { MIPS branches can have 1,2 or 3 operands, target label is the last one. }
         result:=ai.oper[ai.ops-1];
 {$else MIPS}
@@ -859,8 +865,6 @@ Unit AoptObj;
 
 
       procedure TAOptObj.UpdateUsedRegs(p : Tai);
-        var
-          i : TRegisterType;
         begin
           { this code is based on TUsedRegs.Update to avoid multiple passes through the asmlist,
             the code is duplicated here }
@@ -1041,6 +1045,9 @@ Unit AoptObj;
         Repeat
           While Assigned(StartPai) And
                 ((StartPai.typ in (SkipInstr - [ait_regAlloc])) Or
+{$if defined(MIPS) or defined(SPARC)}
+                ((startpai.typ=ait_instruction) and (taicpu(startpai).opcode=A_NOP)) or
+{$endif MIPS or SPARC}
                  ((StartPai.typ = ait_label) and
                   Not(Tai_Label(StartPai).labsym.Is_Used))) Do
             StartPai := Tai(StartPai.Next);
@@ -1075,8 +1082,7 @@ Unit AoptObj;
              (StartPai.typ = ait_regAlloc) Then
             Begin
               if (tai_regalloc(StartPai).ratype=ra_alloc) and
-                (getregtype(tai_regalloc(StartPai).Reg) = getregtype(Reg)) and
-                (getsupreg(tai_regalloc(StartPai).Reg) = getsupreg(Reg)) then
+                SuperRegistersEqual(tai_regalloc(StartPai).Reg,Reg) then
                begin
                  Result:=tai_regalloc(StartPai);
                  exit;
@@ -1116,15 +1122,25 @@ Unit AoptObj;
        End;
 
 
-      function TAOptObj.RegUsedAfterInstruction(reg: Tregister; p: tai;
-       var AllUsedRegs: TAllUsedRegs): Boolean;
-       begin
-         AllUsedRegs[getregtype(reg)].Update(tai(p.Next),true);
-         RegUsedAfterInstruction :=
-           (AllUsedRegs[getregtype(reg)].IsUsed(reg)); { optimization and
-              (not(getNextInstruction(p,p)) or
-               not(regLoadedWithNewValue(supreg,false,p))); }
-       end;
+    function TAOptObj.RegUsedAfterInstruction(reg: Tregister; p: tai;var AllUsedRegs: TAllUsedRegs): Boolean;
+      begin
+        AllUsedRegs[getregtype(reg)].Update(tai(p.Next),true);
+        RegUsedAfterInstruction :=
+          AllUsedRegs[getregtype(reg)].IsUsed(reg) and
+          not(regLoadedWithNewValue(reg,p)) and
+          (
+            not(GetNextInstruction(p,p)) or
+            InstructionLoadsFromReg(reg,p) or
+            not(regLoadedWithNewValue(reg,p))
+          );
+      end;
+
+
+    function TAOptObj.RegEndOfLife(reg : TRegister;p : taicpu) : boolean;
+      begin
+         Result:=assigned(FindRegDealloc(reg,tai(p.Next))) or
+           RegLoadedWithNewValue(reg,p);
+      end;
 
 
     function SkipLabels(hp: tai; var hp2: tai): boolean;
@@ -1163,7 +1179,7 @@ Unit AoptObj;
 
 {$push}
 {$r-}
-    function tAOptObj.getlabelwithsym(sym: tasmlabel): tai;
+    function TAOptObj.getlabelwithsym(sym: tasmlabel): tai;
       begin
         if (int64(sym.labelnr) >= int64(labelinfo^.lowlabel)) and
            (int64(sym.labelnr) <= int64(labelinfo^.highlabel)) then   { range check, a jump can go past an assembler block! }
@@ -1173,12 +1189,29 @@ Unit AoptObj;
       end;
 {$pop}
 
-    function IsJumpToLabel(hp: taicpu): boolean;
+
+    { Returns True if hp is an unconditional jump to a label }
+    function IsJumpToLabelUncond(hp: taicpu): boolean;
       begin
+{$if defined(avr)}
+        result:=(hp.opcode in aopt_uncondjmp) and
+{$else avr}
         result:=(hp.opcode=aopt_uncondjmp) and
-{$ifdef arm}
+{$endif avr}
+{$if defined(arm) or defined(aarch64)}
           (hp.condition=c_None) and
-{$endif arm}
+{$endif arm or aarch64}
+          (hp.ops>0) and
+          (JumpTargetOp(hp)^.typ = top_ref) and
+          (JumpTargetOp(hp)^.ref^.symbol is TAsmLabel);
+      end;
+
+
+    { Returns True if hp is any jump to a label }
+    function IsJumpToLabel(hp: taicpu): boolean;
+      begin
+        result:=hp.is_jmp and
+          (hp.ops>0) and
           (JumpTargetOp(hp)^.typ = top_ref) and
           (JumpTargetOp(hp)^.ref^.symbol is TAsmLabel);
       end;
@@ -1217,8 +1250,11 @@ Unit AoptObj;
        the level parameter denotes how deeep we have already followed the jump,
        to avoid endless loops with constructs such as "l5: ; jmp l5"           }
 
-      var p1, p2: tai;
+      var p1: tai;
+          {$if not defined(MIPS) and not defined(JVM)}
+          p2: tai;
           l: tasmlabel;
+          {$endif}
 
       begin
         GetfinalDestination := false;
@@ -1232,8 +1268,8 @@ Unit AoptObj;
                (taicpu(p1).is_jmp) then
               if { the next instruction after the label where the jump hp arrives}
                  { is unconditional or of the same type as hp, so continue       }
-                 IsJumpToLabel(taicpu(p1))
-{$ifndef MIPS}
+                 IsJumpToLabelUncond(taicpu(p1))
+{$if not defined(MIPS) and not defined(JVM)}
 { for MIPS, it isn't enough to check the condition; first operands must be same, too. }
                  or
                  conditions_equal(taicpu(p1).condition,hp.condition) or
@@ -1247,10 +1283,10 @@ Unit AoptObj;
                   SkipLabels(p1,p2) and
                   (p2.typ = ait_instruction) and
                   (taicpu(p2).is_jmp) and
-                   (IsJumpToLabel(taicpu(p2)) or
+                   (IsJumpToLabelUncond(taicpu(p2)) or
                    (conditions_equal(taicpu(p2).condition,hp.condition))) and
                   SkipLabels(p1,p1))
-{$endif MIPS}
+{$endif not MIPS and not JVM}
                  then
                 begin
                   { quick check for loops of the form "l5: ; jmp l5 }
@@ -1259,11 +1295,19 @@ Unit AoptObj;
                     exit;
                   if not GetFinalDestination(taicpu(p1),succ(level)) then
                     exit;
+{$if defined(aarch64)}
+                  { can't have conditional branches to
+                    global labels on AArch64, because the
+                    offset may become too big }
+                  if not(taicpu(hp).condition in [C_None,C_AL,C_NV]) and
+                     (tasmlabel(JumpTargetOp(taicpu(p1))^.ref^.symbol).bind<>AB_LOCAL) then
+                    exit;
+{$endif aarch64}
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
                   JumpTargetOp(hp)^.ref^.symbol:=JumpTargetOp(taicpu(p1))^.ref^.symbol;
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).increfs;
                 end
-{$ifndef MIPS}
+{$if not defined(MIPS) and not defined(JVM)}
               else
                 if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
                   if not FindAnyLabel(p1,l) then
@@ -1294,14 +1338,26 @@ Unit AoptObj;
                       if not GetFinalDestination(hp,succ(level)) then
                         exit;
                     end;
-{$endif not MIPS}
+{$endif not MIPS and not JVM}
           end;
         GetFinalDestination := true;
       end;
 
 
     procedure TAOptObj.PrePeepHoleOpts;
+      var
+        p: tai;
       begin
+        p := BlockStart;
+        ClearUsedRegs;
+        while (p <> BlockEnd) Do
+          begin
+            UpdateUsedRegs(tai(p.next));
+            if PrePeepHoleOptsCpu(p) then
+              continue;
+            UpdateUsedRegs(p);
+            p:=tai(p.next);
+          end;
       end;
 
 
@@ -1339,11 +1395,15 @@ Unit AoptObj;
                         { the following if-block removes all code between a jmp and the next label,
                           because it can never be executed
                         }
-                        if IsJumpToLabel(taicpu(p)) then
+                        if IsJumpToLabelUncond(taicpu(p)) then
                           begin
                             hp2:=p;
                             while GetNextInstruction(hp2, hp1) and
-                                  (hp1.typ <> ait_label) do
+                                  (hp1.typ <> ait_label)
+{$ifdef JVM}
+                                  and (hp1.typ <> ait_jcatch)
+{$endif}
+                                  do
                               if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
                                 begin
                                   if (hp1.typ = ait_instruction) and
@@ -1355,10 +1415,10 @@ Unit AoptObj;
                                     no-line-info-start/end etc }
                                   if hp1.typ<>ait_marker then
                                     begin
-  {$if defined(SPARC) or defined(MIPS) }
+{$if defined(SPARC) or defined(MIPS) }
                                       if (hp1.typ=ait_instruction) and (taicpu(hp1).is_jmp) then
                                         RemoveDelaySlot(hp1);
-  {$endif SPARC or MIPS }
+{$endif SPARC or MIPS }
                                       asml.remove(hp1);
                                       hp1.free;
                                       stoploop:=false;
@@ -1368,18 +1428,19 @@ Unit AoptObj;
                                 end
                               else break;
                             end;
-                        { remove jumps to a label coming right after them }
                         if GetNextInstruction(p, hp1) then
                           begin
                             SkipEntryExitMarker(hp1,hp1);
-                            if FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp1) and
+                            { remove unconditional jumps to a label coming right after them }
+                            if IsJumpToLabelUncond(taicpu(p)) and
+                              FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp1) and
           { TODO: FIXME removing the first instruction fails}
                                 (p<>blockstart) then
                               begin
                                 tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol).decrefs;
-  {$if defined(SPARC) or defined(MIPS)}
+{$if defined(SPARC) or defined(MIPS)}
                                 RemoveDelaySlot(p);
-  {$endif SPARC or MIPS}
+{$endif SPARC or MIPS}
                                 hp2:=tai(hp1.next);
                                 asml.remove(p);
                                 p.free;
@@ -1389,17 +1450,31 @@ Unit AoptObj;
                               end
                             else if assigned(hp1) then
                               begin
+                                { change the following jumps:
+                                    jmp<cond> lab_1         jmp<cond_inverted> lab_2
+                                    jmp       lab_2  >>>    <code>
+                                  lab_1:                  lab_2:
+                                    <code>
+                                  lab_2:
+                                }
                                 if hp1.typ = ait_label then
                                   SkipLabels(hp1,hp1);
                                 if (tai(hp1).typ=ait_instruction) and
-                                    IsJumpToLabel(taicpu(hp1)) and
-                                    GetNextInstruction(hp1, hp2) and
-                                    FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp2) then
+                                  IsJumpToLabelUncond(taicpu(hp1)) and
+                                  GetNextInstruction(hp1, hp2) and
+                                  IsJumpToLabel(taicpu(p)) and
+                                  FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp2) then
                                   begin
                                     if (taicpu(p).opcode=aopt_condjmp)
-  {$ifdef arm}
+{$if defined(arm) or defined(aarch64)}
                                       and (taicpu(p).condition<>C_None)
-  {$endif arm}
+{$endif arm or aarch64}
+{$if defined(aarch64)}
+                                      { can't have conditional branches to
+                                        global labels on AArch64, because the
+                                        offset may become too big }
+                                      and (tasmlabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).bind=AB_LOCAL)
+{$endif aarch64}
                                       and (inverse_cond(taicpu(p).condition)<>C_None)
                                     then
                                       begin
@@ -1411,9 +1486,9 @@ Unit AoptObj;
 
                                          taicpu(p).oper[0]^.ref^.symbol.increfs;
                                         }
-  {$if defined(SPARC) or defined(MIPS)}
+{$if defined(SPARC) or defined(MIPS)}
                                         RemoveDelaySlot(hp1);
-  {$endif SPARC or MIPS}
+{$endif SPARC or MIPS}
                                         asml.remove(hp1);
                                         hp1.free;
                                         stoploop:=false;
@@ -1426,7 +1501,7 @@ Unit AoptObj;
                                         continue;
                                       end;
                                   end
-                                else
+                                else if IsJumpToLabel(taicpu(p)) then
                                   GetFinalDestination(taicpu(p),0);
                               end;
                           end;
@@ -1445,7 +1520,19 @@ Unit AoptObj;
 
 
     procedure TAOptObj.PeepHoleOptPass2;
+      var
+        p: tai;
       begin
+        p := BlockStart;
+        ClearUsedRegs;
+        while (p <> BlockEnd) Do
+          begin
+            UpdateUsedRegs(tai(p.next));
+            if PeepHoleOptPass2Cpu(p) then
+              continue;
+            UpdateUsedRegs(p);
+            p:=tai(p.next);
+          end;
       end;
 
 
@@ -1466,12 +1553,24 @@ Unit AoptObj;
       end;
 
 
+    function TAOptObj.PrePeepHoleOptsCpu(var p : tai) : boolean;
+      begin
+        result := false;
+      end;
+
+
     function TAOptObj.PeepHoleOptPass1Cpu(var p: tai): boolean;
       begin
         result := false;
       end;
 
 
+    function TAOptObj.PeepHoleOptPass2Cpu(var p : tai) : boolean;
+      begin
+        result := false;
+      end;
+
+
     function TAOptObj.PostPeepHoleOptsCpu(var p: tai): boolean;
       begin
         result := false;

+ 21 - 21
compiler/vis/cpunode.pas → compiler/aoptutils.pas

@@ -1,7 +1,7 @@
 {
-    Copyright (c) 2000-2002 by Florian Klaempfl
+    Copyright (c) 1998-2016 by Florian Klaempfl and Jonas Maebe
 
-    Includes the Virtual instrution set code generator
+    This unit contains helper procedures for the assembler peephole optimizer
 
     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
@@ -19,31 +19,31 @@
 
  ****************************************************************************
 }
-unit cpunode;
+
+unit aoptutils;
 
 {$i fpcdefs.inc}
 
   interface
 
+    uses
+      aasmtai,aasmcpu;
+
+    function MatchOpType(const p : taicpu;type0: toptype) : Boolean;
+    function MatchOpType(const p : taicpu;type0,type1 : toptype) : Boolean;
+
   implementation
 
-    uses
-       { generic nodes }
-       ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,
-       { to be able to only parts of the generic code,
-         the processor specific nodes must be included
-         after the generic one (FK)
-       }
-//       nvisadd,
-//       nviscal,
-//       nviscon,
-//       nvisflw,
-//       nvismem,
-//       nvisinl,
-//       nvismat,
-//       nviscnv,
-       { symtable }
-       symcpu
-       ;
+    function MatchOpType(const p : taicpu; type0: toptype) : Boolean;
+      begin
+        Result:=(p.oper[0]^.typ=type0);
+      end;
+
+
+    function MatchOpType(const p : taicpu; type0,type1 : toptype) : Boolean;
+      begin
+        Result:=(p.oper[0]^.typ=type0) and (p.oper[0]^.typ=type1);
+      end;
 
 end.
+

File diff suppressed because it is too large
+ 563 - 164
compiler/arm/aasmcpu.pas


+ 88 - 27
compiler/arm/agarmgas.pas

@@ -29,24 +29,27 @@ unit agarmgas;
   interface
 
     uses
-       globtype,
+       globtype,systems,
        aasmtai,
        aggas,
        cpubase,cpuinfo;
 
     type
       TARMGNUAssembler=class(TGNUassembler)
-        constructor create(smart: boolean); override;
+        constructor create(info: pasminfo; smart: boolean); override;
         function MakeCmdLine: TCmdStr; override;
         procedure WriteExtraHeader; override;
       end;
 
       TArmInstrWriter=class(TCPUInstrWriter)
+        unified_syntax: boolean;
+
         procedure WriteInstruction(hp : tai);override;
       end;
 
       TArmAppleGNUAssembler=class(TAppleGNUassembler)
-        constructor create(smart: boolean); override;
+        constructor create(info: pasminfo; smart: boolean); override;
+        procedure WriteExtraHeader; override;
       end;
 
 
@@ -79,7 +82,6 @@ unit agarmgas;
 
     uses
        cutils,globals,verbose,
-       systems,
        assemble,
        aasmcpu,
        itcpugas,
@@ -89,10 +91,12 @@ unit agarmgas;
 {                         GNU Arm Assembler writer                           }
 {****************************************************************************}
 
-    constructor TArmGNUAssembler.create(smart: boolean);
+    constructor TArmGNUAssembler.create(info: pasminfo; smart: boolean);
       begin
-        inherited create(smart);
+        inherited;
         InstrWriter := TArmInstrWriter.create(self);
+        if GenerateThumb2Code then
+          TArmInstrWriter(InstrWriter).unified_syntax:=true;
       end;
 
 
@@ -109,13 +113,14 @@ unit agarmgas;
           result:='-mfpu=vfpv3-d16 '+result;
         if (current_settings.fputype = fpu_fpv4_s16) then
           result:='-mfpu=fpv4-sp-d16 '+result;
+        if (current_settings.fputype = fpu_vfpv4) then
+          result:='-mfpu=vfpv4 '+result;
 
         if GenerateThumb2Code then
           result:='-march='+cputype_to_gas_march[current_settings.cputype]+' -mthumb -mthumb-interwork '+result
         else if GenerateThumbCode then
           result:='-march='+cputype_to_gas_march[current_settings.cputype]+' -mthumb -mthumb-interwork '+result
-        // EDSP instructions in RTL require armv5te at least to not generate error
-        else if current_settings.cputype >= cpu_armv5te then
+        else
           result:='-march='+cputype_to_gas_march[current_settings.cputype]+' '+result;
 
         if target_info.abi = abi_eabihf then
@@ -126,18 +131,27 @@ unit agarmgas;
     procedure TArmGNUAssembler.WriteExtraHeader;
       begin
         inherited WriteExtraHeader;
-        if GenerateThumb2Code then
-          AsmWriteLn(#9'.syntax unified');
+        if TArmInstrWriter(InstrWriter).unified_syntax then
+          writer.AsmWriteLn(#9'.syntax unified');
       end;
 
 {****************************************************************************}
 {                      GNU/Apple ARM Assembler writer                        }
 {****************************************************************************}
 
-    constructor TArmAppleGNUAssembler.create(smart: boolean);
+    constructor TArmAppleGNUAssembler.create(info: pasminfo; smart: boolean);
       begin
-        inherited create(smart);
+        inherited;
         InstrWriter := TArmInstrWriter.create(self);
+        TArmInstrWriter(InstrWriter).unified_syntax:=true;
+      end;
+
+
+    procedure TArmAppleGNUAssembler.WriteExtraHeader;
+      begin
+        inherited WriteExtraHeader;
+        if TArmInstrWriter(InstrWriter).unified_syntax then
+          writer.AsmWriteLn(#9'.syntax unified');
       end;
 
 
@@ -208,7 +222,7 @@ unit agarmgas;
       var
         hs : string;
         first : boolean;
-        r : tsuperregister;
+        r, rs : tsuperregister;
       begin
         case o.typ of
           top_reg:
@@ -230,14 +244,44 @@ unit agarmgas;
             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;
+              if R_SUBFS=o.subreg then
+                begin
+                  for r:=0 to 31 do // S0 to S31
+                    if r in o.regset^ then
+                      begin
+                        if not(first) then
+                          getopstr:=getopstr+',';
+                        if odd(r) then
+                          rs:=(r shr 1)+RS_S1
+                        else
+                          rs:=(r shr 1)+RS_S0;
+                        getopstr:=getopstr+gas_regname(newreg(o.regtyp,rs,o.subreg));
+                        first:=false;
+                      end;
+                end
+              else if R_SUBFD=o.subreg then
+                begin
+                  for r:=0 to 31 do
+                    if r in o.regset^ then
+                      begin
+                        if not(first) then
+                          getopstr:=getopstr+',';
+                        rs:=r+RS_D0;
+                        getopstr:=getopstr+gas_regname(newreg(o.regtyp,rs,o.subreg));
+                        first:=false;
+                      end;
+                end
+              else
+                begin
+                  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;
               getopstr:=getopstr+'}';
               if o.usermode then
                 getopstr:=getopstr+'^';
@@ -289,15 +333,17 @@ unit agarmgas;
         sep: string[3];
     begin
       op:=taicpu(hp).opcode;
+      postfix:='';
       if GenerateThumb2Code then
         begin
-          postfix:='';
           if taicpu(hp).wideformat then
             postfix:='.w';
-
+        end;
+      if unified_syntax then
+        begin
           if taicpu(hp).ops = 0 then
             s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
-          else if (taicpu(hp).opcode>=A_VABS) and (taicpu(hp).opcode<=A_VSUB) then
+          else if taicpu(hp).oppostfix in [PF_8..PF_U32F64] then
             s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
           else
             s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix]+cond2str[taicpu(hp).condition]+postfix; // Conditional infixes are deprecated in unified syntax
@@ -314,7 +360,7 @@ unit agarmgas;
                // writeln(taicpu(hp).fileinfo.line);
 
                { LDM and STM use references as first operand but they are written like a register }
-               if (i=0) and (op in [A_LDM,A_STM,A_FSTM,A_FLDM]) then
+               if (i=0) and (op in [A_LDM,A_STM,A_FSTM,A_FLDM,A_VSTM,A_VLDM,A_SRS,A_RFE]) then
                  begin
                    case taicpu(hp).oper[0]^.typ of
                      top_ref:
@@ -345,7 +391,7 @@ unit agarmgas;
                sep:=',';
             end;
         end;
-      owner.AsmWriteLn(s);
+      owner.writer.AsmWriteLn(s);
     end;
 
 
@@ -368,7 +414,7 @@ unit agarmgas;
        as_arm_gas_darwin_info : tasminfo =
           (
             id     : as_darwin;
-            idtxt  : 'AS-Darwin';
+            idtxt  : 'AS-DARWIN';
             asmbin : 'as';
             asmcmd : '-o $OBJ $EXTRAOPT $ASM -arch $ARCH';
             supported_targets : [system_arm_darwin];
@@ -379,7 +425,22 @@ unit agarmgas;
           );
 
 
+       as_arm_clang_darwin_info : tasminfo =
+          (
+            id     : as_clang;
+            idtxt  : 'CLANG';
+            asmbin : 'clang';
+            asmcmd : '-c -o $OBJ $EXTRAOPT -arch $ARCH $DARWINVERSION -x assembler $ASM';
+            supported_targets : [system_arm_darwin];
+            flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
+            labelprefix : 'L';
+            comment : '# ';
+            dollarsign: '$';
+          );
+
+
 begin
   RegisterAssembler(as_arm_gas_info,TARMGNUAssembler);
   RegisterAssembler(as_arm_gas_darwin_info,TArmAppleGNUAssembler);
+  RegisterAssembler(as_arm_clang_darwin_info,TArmAppleGNUAssembler);
 end.

+ 294 - 151
compiler/arm/aoptcpu.pas

@@ -30,7 +30,7 @@ Unit aoptcpu;
 
 Interface
 
-uses cgbase, cpubase, aasmtai, aasmcpu,aopt, aoptobj;
+uses cgbase, cgutils, cpubase, aasmtai, aasmcpu,aopt, aoptobj;
 
 Type
   TCpuAsmOptimizer = class(TAsmOptimizer)
@@ -39,21 +39,22 @@ Type
     procedure PeepHoleOptPass2;override;
     Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override;
     function RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string): boolean;
-    function RegUsedAfterInstruction(reg: Tregister; p: tai;
-                                     var AllUsedRegs: TAllUsedRegs): Boolean;
-    { returns true if reg reaches it's end of life at p, this means it is either
-      reloaded with a new value or it is deallocated afterwards }
-    function RegEndOfLife(reg: TRegister;p: taicpu): boolean;
+    function RemoveSuperfluousVMov(const p : tai; movp : tai; const optimizer : string) : boolean;
+
     { gets the next tai object after current that contains info relevant
       to the optimizer in p1 which used the given register or does a
       change in program flow.
       If there is none, it returns false and
       sets p1 to nil                                                     }
-    Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
+    Function GetNextInstructionUsingReg(Current: tai; Out Next: tai; reg: TRegister): Boolean;
+    Function GetNextInstructionUsingRef(Current: tai; Out Next: tai; const ref: TReference; StopOnStore: Boolean = true): Boolean;
 
     { outputs a debug message into the assembler file }
     procedure DebugMsg(const s: string; p: tai);
 
+    function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; override;
+
+    function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
   protected
     function LookForPreindexedPattern(p: taicpu): boolean;
     function LookForPostindexedPattern(p: taicpu): boolean;
@@ -79,7 +80,7 @@ Implementation
     cutils,verbose,globtype,globals,
     systems,
     cpuinfo,
-    cgobj,cgutils,procinfo,
+    cgobj,procinfo,
     aasmbase,aasmdata;
 
   function CanBeCond(p : tai) : boolean;
@@ -92,7 +93,11 @@ Implementation
         (taicpu(p).opcode<>A_CBZ) and
         (taicpu(p).opcode<>A_CBNZ) and
         (taicpu(p).opcode<>A_PLD) and
-        ((taicpu(p).opcode<>A_BLX) or
+        (((taicpu(p).opcode<>A_BLX) and
+          { BL may need to be converted into BLX by the linker -- could possibly
+            be allowed in case it's to a local symbol of which we know that it
+            uses the same instruction set as the current one }
+          (taicpu(p).opcode<>A_BL)) or
          (taicpu(p).oper[0]^.typ=top_reg));
     end;
 
@@ -166,67 +171,6 @@ Implementation
       end;
     end;
 
-  function regLoadedWithNewValue(reg: tregister; hp: tai): boolean;
-  var
-    p: taicpu;
-  begin
-    p := taicpu(hp);
-    regLoadedWithNewValue := false;
-    if not ((assigned(hp)) and (hp.typ = ait_instruction)) then
-      exit;
-
-    case p.opcode of
-      { These operands do not write into a register at all }
-      A_CMP, A_CMN, A_TST, A_TEQ, A_B, A_BL, A_BX, A_BLX, A_SWI, A_MSR, A_PLD:
-        exit;
-      {Take care of post/preincremented store and loads, they will change their base register}
-      A_STR, A_LDR:
-        begin
-          regLoadedWithNewValue :=
-            (taicpu(p).oper[1]^.typ=top_ref) and
-            (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
-            (taicpu(p).oper[1]^.ref^.base = reg);
-          {STR does not load into it's first register}
-          if p.opcode = A_STR then exit;
-        end;
-      { These four are writing into the first 2 register, UMLAL and SMLAL will also read from them }
-      A_UMLAL, A_UMULL, A_SMLAL, A_SMULL:
-        regLoadedWithNewValue :=
-          (p.oper[1]^.typ = top_reg) and
-          (p.oper[1]^.reg = reg);
-      {Loads to oper2 from coprocessor}
-      {
-      MCR/MRC is currently not supported in FPC
-      A_MRC:
-        regLoadedWithNewValue :=
-          (p.oper[2]^.typ = top_reg) and
-          (p.oper[2]^.reg = reg);
-      }
-      {Loads to all register in the registerset}
-      A_LDM:
-        regLoadedWithNewValue := (getsupreg(reg) in p.oper[1]^.regset^);
-      A_POP:
-        regLoadedWithNewValue := (getsupreg(reg) in p.oper[0]^.regset^) or
-                                 (reg=NR_STACK_POINTER_REG);
-    end;
-
-    if regLoadedWithNewValue then
-      exit;
-
-    case p.oper[0]^.typ of
-      {This is the case}
-      top_reg:
-        regLoadedWithNewValue := (p.oper[0]^.reg = reg) or
-          { LDRD }
-          (p.opcode=A_LDR) and (p.oppostfix=PF_D) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg));
-      {LDM/STM might write a new value to their index register}
-      top_ref:
-        regLoadedWithNewValue :=
-          (taicpu(p).oper[0]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
-          (taicpu(p).oper[0]^.ref^.base = reg);
-    end;
-  end;
-
 
   function AlignedToQWord(const ref : treference) : boolean;
     begin
@@ -248,44 +192,6 @@ Implementation
     end;
 
 
-  function instructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
-  var
-    p: taicpu;
-    i: longint;
-  begin
-    instructionLoadsFromReg := false;
-    if not (assigned(hp) and (hp.typ = ait_instruction)) then
-      exit;
-    p:=taicpu(hp);
-
-    i:=1;
-    {For these instructions we have to start on oper[0]}
-    if (p.opcode in [A_STR, A_LDM, A_STM, A_PLD,
-                        A_CMP, A_CMN, A_TST, A_TEQ,
-                        A_B, A_BL, A_BX, A_BLX,
-                        A_SMLAL, A_UMLAL]) then i:=0;
-
-    while(i<p.ops) do
-      begin
-        case p.oper[I]^.typ of
-          top_reg:
-            instructionLoadsFromReg := (p.oper[I]^.reg = reg) or
-              { STRD }
-              ((i=0) and (p.opcode=A_STR) and (p.oppostfix=PF_D) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg)));
-          top_regset:
-            instructionLoadsFromReg := (getsupreg(reg) in p.oper[I]^.regset^);
-          top_shifterop:
-            instructionLoadsFromReg := p.oper[I]^.shifterop^.rs = reg;
-          top_ref:
-            instructionLoadsFromReg :=
-              (p.oper[I]^.ref^.base = reg) or
-              (p.oper[I]^.ref^.index = reg);
-        end;
-        if instructionLoadsFromReg then exit; {Bailout if we found something}
-        Inc(I);
-      end;
-  end;
-
   function isValidConstLoadStoreOffset(const aoffset: longint; const pf: TOpPostfix) : boolean;
     begin
       if GenerateThumb2Code then
@@ -296,36 +202,158 @@ Implementation
                   (abs(aoffset)<256);
     end;
 
-  function TCpuAsmOptimizer.RegUsedAfterInstruction(reg: Tregister; p: tai;
-    var AllUsedRegs: TAllUsedRegs): Boolean;
+
+  function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
+    var
+      p: taicpu;
+      i: longint;
     begin
-      AllUsedRegs[getregtype(reg)].Update(tai(p.Next),true);
-      RegUsedAfterInstruction :=
-        AllUsedRegs[getregtype(reg)].IsUsed(reg) and
-        not(regLoadedWithNewValue(reg,p)) and
-        (
-          not(GetNextInstruction(p,p)) or
-          instructionLoadsFromReg(reg,p) or
-          not(regLoadedWithNewValue(reg,p))
-        );
+      instructionLoadsFromReg := false;
+      if not (assigned(hp) and (hp.typ = ait_instruction)) then
+        exit;
+      p:=taicpu(hp);
+
+      i:=1;
+      {For these instructions we have to start on oper[0]}
+      if (p.opcode in [A_STR, A_LDM, A_STM, A_PLD,
+                          A_CMP, A_CMN, A_TST, A_TEQ,
+                          A_B, A_BL, A_BX, A_BLX,
+                          A_SMLAL, A_UMLAL]) then i:=0;
+
+      while(i<p.ops) do
+        begin
+          case p.oper[I]^.typ of
+            top_reg:
+              instructionLoadsFromReg := (p.oper[I]^.reg = reg) or
+                { STRD }
+                ((i=0) and (p.opcode=A_STR) and (p.oppostfix=PF_D) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg)));
+            top_regset:
+              instructionLoadsFromReg := (getsupreg(reg) in p.oper[I]^.regset^);
+            top_shifterop:
+              instructionLoadsFromReg := p.oper[I]^.shifterop^.rs = reg;
+            top_ref:
+              instructionLoadsFromReg :=
+                (p.oper[I]^.ref^.base = reg) or
+                (p.oper[I]^.ref^.index = reg);
+          end;
+          if instructionLoadsFromReg then exit; {Bailout if we found something}
+          Inc(I);
+        end;
     end;
 
 
-  function TCpuAsmOptimizer.RegEndOfLife(reg : TRegister;p : taicpu) : boolean;
+  function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
+    var
+      p: taicpu;
     begin
-       Result:=assigned(FindRegDealloc(reg,tai(p.Next))) or
-         RegLoadedWithNewValue(reg,p);
+      p := taicpu(hp);
+      Result := false;
+      if not ((assigned(hp)) and (hp.typ = ait_instruction)) then
+        exit;
+
+      case p.opcode of
+        { These operands do not write into a register at all }
+        A_CMP, A_CMN, A_TST, A_TEQ, A_B, A_BL, A_BX, A_BLX, A_SWI, A_MSR, A_PLD,
+        A_VCMP:
+          exit;
+        {Take care of post/preincremented store and loads, they will change their base register}
+        A_STR, A_LDR:
+          begin
+            Result := false;
+            { actually, this does not apply here because post-/preindexed does not mean that a register
+              is loaded with a new value, it is only modified
+              (taicpu(p).oper[1]^.typ=top_ref) and
+              (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
+              (taicpu(p).oper[1]^.ref^.base = reg);
+            }
+            { STR does not load into it's first register }
+            if p.opcode = A_STR then
+              exit;
+          end;
+        A_VSTR:
+          begin
+            Result := false;
+            exit;
+          end;
+        { These four are writing into the first 2 register, UMLAL and SMLAL will also read from them }
+        A_UMLAL, A_UMULL, A_SMLAL, A_SMULL:
+          Result :=
+            (p.oper[1]^.typ = top_reg) and
+            (p.oper[1]^.reg = reg);
+        {Loads to oper2 from coprocessor}
+        {
+        MCR/MRC is currently not supported in FPC
+        A_MRC:
+          Result :=
+            (p.oper[2]^.typ = top_reg) and
+            (p.oper[2]^.reg = reg);
+        }
+        {Loads to all register in the registerset}
+        A_LDM, A_VLDM:
+          Result := (getsupreg(reg) in p.oper[1]^.regset^);
+        A_POP:
+          Result := (getsupreg(reg) in p.oper[0]^.regset^) or
+                                   (reg=NR_STACK_POINTER_REG);
+      end;
+
+      if Result then
+        exit;
+
+      case p.oper[0]^.typ of
+        {This is the case}
+        top_reg:
+          Result := (p.oper[0]^.reg = reg) or
+            { LDRD }
+            (p.opcode=A_LDR) and (p.oppostfix=PF_D) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg));
+        {LDM/STM might write a new value to their index register}
+        top_ref:
+          Result :=
+            (taicpu(p).oper[0]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
+            (taicpu(p).oper[0]^.ref^.base = reg);
+      end;
     end;
 
 
   function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
-    var Next: tai; reg: TRegister): Boolean;
+    Out Next: tai; reg: TRegister): Boolean;
+    begin
+      Next:=Current;
+      repeat
+        Result:=GetNextInstruction(Next,Next);
+      until not (Result) or
+            not(cs_opt_level3 in current_settings.optimizerswitches) or
+            (Next.typ<>ait_instruction) or
+            RegInInstruction(reg,Next) or
+            is_calljmp(taicpu(Next).opcode) or
+            RegModifiedByInstruction(NR_PC,Next);
+    end;
+
+  function TCpuAsmOptimizer.GetNextInstructionUsingRef(Current: tai;
+    Out Next: tai; const ref: TReference; StopOnStore: Boolean = true): Boolean;
     begin
       Next:=Current;
       repeat
         Result:=GetNextInstruction(Next,Next);
-      until not(cs_opt_level3 in current_settings.optimizerswitches) or not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
-        (is_calljmp(taicpu(Next).opcode)) or (RegInInstruction(NR_PC,Next));
+        if Result and
+           (Next.typ=ait_instruction) and
+           (taicpu(Next).opcode in [A_LDR, A_STR]) and
+           (
+            ((taicpu(Next).ops = 2) and
+             (taicpu(Next).oper[1]^.typ = top_ref) and
+             RefsEqual(taicpu(Next).oper[1]^.ref^,ref)) or
+            ((taicpu(Next).ops = 3) and { LDRD/STRD }
+             (taicpu(Next).oper[2]^.typ = top_ref) and
+             RefsEqual(taicpu(Next).oper[2]^.ref^,ref))
+           ) then
+            {We've found an instruction LDR or STR with the same reference}
+            exit;
+      until not(Result) or
+            (Next.typ<>ait_instruction) or
+            not(cs_opt_level3 in current_settings.optimizerswitches) or
+            is_calljmp(taicpu(Next).opcode) or
+            (StopOnStore and (taicpu(Next).opcode in [A_STR, A_STM])) or
+            RegModifiedByInstruction(NR_PC,Next);
+      Result:=false;
     end;
 
 {$ifdef DEBUG_AOPTCPU}
@@ -411,6 +439,69 @@ Implementation
         end;
     end;
 
+
+  function TCpuAsmOptimizer.RemoveSuperfluousVMov(const p: tai; movp: tai; const optimizer: string):boolean;
+    var
+      alloc,
+      dealloc : tai_regalloc;
+      hp1 : tai;
+    begin
+      Result:=false;
+      if (MatchInstruction(movp, A_VMOV, [taicpu(p).condition], [taicpu(p).oppostfix]) or
+          ((taicpu(p).oppostfix in [PF_F64F32,PF_F64S16,PF_F64S32,PF_F64U16,PF_F64U32]) and MatchInstruction(movp, A_VMOV, [taicpu(p).condition], [PF_F64])) or
+          ((taicpu(p).oppostfix in [PF_F32F64,PF_F32S16,PF_F32S32,PF_F32U16,PF_F32U32]) and MatchInstruction(movp, A_VMOV, [taicpu(p).condition], [PF_F32]))
+         ) and
+         (taicpu(movp).ops=2) and
+         MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and
+         { the destination register of the mov might not be used beween p and movp }
+         not(RegUsedBetween(taicpu(movp).oper[0]^.reg,p,movp)) and
+         { Take care to only do this for instructions which REALLY load to the first register.
+           Otherwise
+             vstr reg0, [reg1]
+             vmov reg2, reg0
+           will be optimized to
+             vstr reg2, [reg1]
+         }
+         regLoadedWithNewValue(taicpu(p).oper[0]^.reg, p) then
+        begin
+          dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(movp.Next));
+          if assigned(dealloc) then
+            begin
+              DebugMsg('Peephole '+optimizer+' removed superfluous vmov', movp);
+              result:=true;
+
+              { taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation
+                and remove it if possible }
+              asml.Remove(dealloc);
+              alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.previous));
+              if assigned(alloc) then
+                begin
+                  asml.Remove(alloc);
+                  alloc.free;
+                  dealloc.free;
+                end
+              else
+                asml.InsertAfter(dealloc,p);
+
+              { try to move the allocation of the target register }
+              GetLastInstruction(movp,hp1);
+              alloc:=FindRegAlloc(taicpu(movp).oper[0]^.reg,tai(hp1.Next));
+              if assigned(alloc) then
+                begin
+                  asml.Remove(alloc);
+                  asml.InsertBefore(alloc,p);
+                  { adjust used regs }
+                  IncludeRegInUsedRegs(taicpu(movp).oper[0]^.reg,UsedRegs);
+                end;
+
+              { finally get rid of the mov }
+              taicpu(p).loadreg(0,taicpu(movp).oper[0]^.reg);
+              asml.remove(movp);
+              movp.free;
+            end;
+        end;
+    end;
+
   {
     optimize
       add/sub reg1,reg1,regY/const
@@ -482,7 +573,8 @@ Implementation
       hp1 : tai;
     begin
       Result:=false;
-      if (p.oper[1]^.ref^.addressmode=AM_OFFSET) and
+      if (p.oper[1]^.typ = top_ref) and
+        (p.oper[1]^.ref^.addressmode=AM_OFFSET) and
         (p.oper[1]^.ref^.index=NR_NO) and
         (p.oper[1]^.ref^.offset=0) and
         GetNextInstructionUsingReg(p, hp1, p.oper[1]^.ref^.base) and
@@ -538,6 +630,7 @@ Implementation
       TmpUsedRegs: TAllUsedRegs;
       tempop: tasmop;
       oldreg: tregister;
+      dealloc: tai_regalloc;
 
     function IsPowerOf2(const value: DWord): boolean; inline;
       begin
@@ -607,12 +700,17 @@ Implementation
                       str reg1,ref
                       mov reg2,reg1
                     }
-                    if (taicpu(p).oper[1]^.ref^.addressmode=AM_OFFSET) and
+                    if (taicpu(p).oper[1]^.typ = top_ref) and
+                       (taicpu(p).oper[1]^.ref^.addressmode=AM_OFFSET) and
                        (taicpu(p).oppostfix=PF_None) and
-                       GetNextInstruction(p,hp1) and
-                       MatchInstruction(hp1, A_LDR, [taicpu(p).condition, C_None], [PF_None]) and
-                       RefsEqual(taicpu(p).oper[1]^.ref^,taicpu(hp1).oper[1]^.ref^) and
-                       (taicpu(hp1).oper[1]^.ref^.addressmode=AM_OFFSET) then
+                       (taicpu(p).condition=C_None) and
+                       GetNextInstructionUsingRef(p,hp1,taicpu(p).oper[1]^.ref^) and
+                       MatchInstruction(hp1, A_LDR, [taicpu(p).condition], [PF_None]) and
+                       (taicpu(hp1).oper[1]^.typ=top_ref) and
+                       (taicpu(hp1).oper[1]^.ref^.addressmode=AM_OFFSET) and
+                       not(RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+                       ((taicpu(hp1).oper[1]^.ref^.index=NR_NO) or not (RegModifiedBetween(taicpu(hp1).oper[1]^.ref^.index, p, hp1))) and
+                       ((taicpu(hp1).oper[1]^.ref^.base=NR_NO) or not (RegModifiedBetween(taicpu(hp1).oper[1]^.ref^.base, p, hp1))) then
                       begin
                         if taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg then
                           begin
@@ -633,7 +731,7 @@ Implementation
                       str reg1,ref
                       str reg2,ref
                       into
-                      strd reg1,ref
+                      strd reg1,reg2,ref
                     }
                     else if (GenerateARMCode or GenerateThumb2Code) and
                        (CPUARM_HAS_EDSP in cpu_capabilities[current_settings.cputype]) and
@@ -654,6 +752,9 @@ Implementation
                       begin
                         DebugMsg('Peephole StrStr2Strd done', p);
                         taicpu(p).oppostfix:=PF_D;
+                        taicpu(p).loadref(2,taicpu(p).oper[1]^.ref^);
+                        taicpu(p).loadreg(1, taicpu(hp1).oper[0]^.reg);
+                        taicpu(p).ops:=3;
                         asml.remove(hp1);
                         hp1.free;
                         result:=true;
@@ -667,7 +768,8 @@ Implementation
                       ldr reg2,ref
                       into ...
                     }
-                    if (taicpu(p).oper[1]^.ref^.addressmode=AM_OFFSET) and
+                    if (taicpu(p).oper[1]^.typ = top_ref) and
+                       (taicpu(p).oper[1]^.ref^.addressmode=AM_OFFSET) and
                        GetNextInstruction(p,hp1) and
                        { ldrd is not allowed here }
                        MatchInstruction(hp1, A_LDR, [taicpu(p).condition, C_None], [taicpu(p).oppostfix,PF_None]-[PF_D]) then
@@ -700,7 +802,7 @@ Implementation
                           end
                         {
                            ...
-                           ldrd reg1,ref
+                           ldrd reg1,reg1+1,ref
                         }
                         else if (GenerateARMCode or GenerateThumb2Code) and
                           (CPUARM_HAS_EDSP in cpu_capabilities[current_settings.cputype]) and
@@ -718,6 +820,9 @@ Implementation
                           AlignedToQWord(taicpu(p).oper[1]^.ref^) then
                           begin
                             DebugMsg('Peephole LdrLdr2Ldrd done', p);
+                            taicpu(p).loadref(2,taicpu(p).oper[1]^.ref^);
+                            taicpu(p).loadreg(1, taicpu(hp1).oper[0]^.reg);
+                            taicpu(p).ops:=3;
                             taicpu(p).oppostfix:=PF_D;
                             asml.remove(hp1);
                             hp1.free;
@@ -1200,12 +1305,19 @@ Implementation
                        (taicpu(p).oppostfix = PF_NONE) and
                        GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
                        MatchInstruction(hp1, [A_LDR, A_STR], [taicpu(p).condition], []) and
+                       (taicpu(hp1).oper[1]^.typ = top_ref) and
                        { We can change the base register only when the instruction uses AM_OFFSET }
                        ((taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) or
                          ((taicpu(hp1).oper[1]^.ref^.addressmode = AM_OFFSET) and
                           (taicpu(hp1).oper[1]^.ref^.base = taicpu(p).oper[0]^.reg))
                        ) and
                        not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
+
+                       // Make sure that Thumb code doesn't propagate a high register into a reference
+                       ((GenerateThumbCode and
+                         (getsupreg(taicpu(p).oper[1]^.reg) < RS_R8)) or
+                        (not GenerateThumbCode)) and
+
                        RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
                       begin
                         DebugMsg('Peephole MovLdr2Ldr done', hp1);
@@ -1216,6 +1328,13 @@ Implementation
                         if taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg then
                           taicpu(hp1).oper[1]^.ref^.index := taicpu(p).oper[1]^.reg;
 
+                        dealloc:=FindRegDeAlloc(taicpu(p).oper[1]^.reg, taicpu(p.Next));
+                        if Assigned(dealloc) then
+                          begin
+                            asml.remove(dealloc);
+                            asml.InsertAfter(dealloc,hp1);
+                          end;
+
                         GetNextInstruction(p, hp1);
                         asml.remove(p);
                         p.free;
@@ -1382,6 +1501,9 @@ Implementation
                            (not GenerateThumb2Code)
                          )
                        ) and
+                       { Only fold if both registers are used. Otherwise we are folding p with itself }
+                       (taicpu(hp1).oper[1]^.ref^.index<>NR_NO) and
+                       (taicpu(hp1).oper[1]^.ref^.base<>NR_NO) and
                        { Only fold if there isn't another shifterop already, and offset is zero. }
                        (taicpu(hp1).oper[1]^.ref^.offset = 0) and
                        (taicpu(hp1).oper[1]^.ref^.shiftmode = SM_None) and
@@ -1577,13 +1699,14 @@ Implementation
                               and reg1,reg0,2^n-1
                               mov reg2,reg1, lsl imm1
                               =>
-                              mov reg2,reg1, lsl imm1
+                              mov reg2,reg0, lsl imm1
                               if imm1>i
                             }
-                            else if i>32-taicpu(hp1).oper[2]^.shifterop^.shiftimm then
+                            else if (i>32-taicpu(hp1).oper[2]^.shifterop^.shiftimm) and
+                                    not(RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) then
                               begin
                                 DebugMsg('Peephole AndLsl2Lsl done', p);
-                                taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[0]^.reg;
+                                taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[1]^.reg;
                                 GetNextInstruction(p, hp1);
                                 asml.Remove(p);
                                 p.free;
@@ -1600,7 +1723,8 @@ Implementation
                       to
                       str/ldr reg3,[reg1,const2+/-const1]
                     }
-                    if (taicpu(p).opcode in [A_ADD,A_SUB]) and
+                    if (not GenerateThumbCode) and
+                       (taicpu(p).opcode in [A_ADD,A_SUB]) and
                        (taicpu(p).ops>2) and
                        (taicpu(p).oper[1]^.typ = top_reg) and
                        (taicpu(p).oper[2]^.typ = top_const) then
@@ -1609,6 +1733,7 @@ Implementation
                         while GetNextInstructionUsingReg(hp1, hp1, taicpu(p).oper[0]^.reg) and
                           { we cannot check NR_DEFAULTFLAGS for modification yet so don't allow a condition }
                           MatchInstruction(hp1, [A_LDR, A_STR], [C_None], []) and
+                          (taicpu(hp1).oper[1]^.typ = top_ref) and
                           (taicpu(hp1).oper[1]^.ref^.base=taicpu(p).oper[0]^.reg) and
                           { don't optimize if the register is stored/overwritten }
                           (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[1]^.reg) and
@@ -1695,6 +1820,8 @@ Implementation
                       (taicpu(p).oper[2]^.typ = top_reg) and
                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
                       MatchInstruction(hp1,[A_ADD,A_SUB],[C_None],[PF_None]) and
+                      (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) and
+                      (not RegModifiedBetween(taicpu(p).oper[2]^.reg, p, hp1)) and
 
                       (((taicpu(hp1).opcode=A_ADD) and (current_settings.cputype>=cpu_armv4)) or
                        ((taicpu(hp1).opcode=A_SUB) and (current_settings.cputype in [cpu_armv6t2,cpu_armv7,cpu_armv7a,cpu_armv7r,cpu_armv7m,cpu_armv7em]))) and
@@ -2086,7 +2213,19 @@ Implementation
                         DebugMsg('Peephole Bl2B done', p);
                       end;
                   end;
-
+                A_VADD,
+                A_VMUL,
+                A_VDIV,
+                A_VSUB,
+                A_VSQRT,
+                A_VNEG,
+                A_VCVT,
+                A_VABS:
+                  begin
+                    if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                      RemoveSuperfluousVMov(p, hp1, 'VOpVMov2VOp') then
+                      Result:=true;
+                  end
               end;
           end;
       end;
@@ -2288,7 +2427,7 @@ Implementation
     { set of opcode which might or do write to memory }
     { TODO : extend armins.dat to contain r/w info }
     opcode_could_mem_write = [A_B,A_BL,A_BLX,A_BKPT,A_BX,A_STR,A_STRB,A_STRBT,
-                              A_STRH,A_STRT,A_STF,A_SFM,A_STM,A_FSTS,A_FSTD];
+                              A_STRH,A_STRT,A_STF,A_SFM,A_STM,A_FSTS,A_FSTD,A_VSTR,A_VSTM];
 
 
   { adjust the register live information when swapping the two instructions p and hp1,
@@ -2380,7 +2519,7 @@ Implementation
     begin
       result:=true;
 
-      list:=TAsmList.create_without_marker;
+      list:=TAsmList.create;
       p:=BlockStart;
       while p<>BlockEnd Do
         begin
@@ -2401,6 +2540,7 @@ Implementation
                ) or
                { try to prove that the memory accesses don't overlapp }
                ((taicpu(p).opcode in [A_STRB,A_STRH,A_STR]) and
+                (taicpu(p).oper[1]^.typ = top_ref) and
                 (taicpu(p).oper[1]^.ref^.base=taicpu(hp1).oper[1]^.ref^.base) and
                 (taicpu(p).oppostfix=PF_None) and
                 (taicpu(hp1).oppostfix=PF_None) and
@@ -2426,18 +2566,24 @@ Implementation
             { first instruction might not change the register used as index }
             ((taicpu(hp1).oper[1]^.ref^.index=NR_NO) or
              not(RegModifiedByInstruction(taicpu(hp1).oper[1]^.ref^.index,p))
-            ) then
+            ) and
+            { if we modify the basereg AND the first instruction used that reg, we can not schedule }
+            ((taicpu(hp1).oper[1]^.ref^.addressmode = AM_OFFSET) or
+             not(instructionLoadsFromReg(taicpu(hp1).oper[1]^.ref^.base,p))) then
             begin
               hp3:=tai(p.Previous);
               hp5:=tai(p.next);
               asml.Remove(p);
-              { if there is a reg. dealloc instruction associated with p, move it together with p }
+              { if there is a reg. dealloc instruction or address labels (e.g. for GOT-less PIC)
+                associated with p, move it together with p }
 
               { before the instruction? }
               while assigned(hp3) and (hp3.typ<>ait_instruction) do
                 begin
-                  if (hp3.typ=ait_regalloc) and (tai_regalloc(hp3).ratype in [ra_dealloc]) and
-                    RegInInstruction(tai_regalloc(hp3).reg,p) then
+                  if ( (hp3.typ=ait_regalloc) and (tai_regalloc(hp3).ratype in [ra_dealloc]) and
+                    RegInInstruction(tai_regalloc(hp3).reg,p) )
+                    or ( (hp3.typ=ait_label) and (tai_label(hp3).labsym.typ=AT_ADDR) )
+                  then
                     begin
                       hp4:=hp3;
                       hp3:=tai(hp3.Previous);
@@ -2483,7 +2629,7 @@ Implementation
 {$endif DEBUG_PREREGSCHEDULER}
               asml.InsertBefore(hp1,insertpos);
               asml.InsertListBefore(insertpos,list);
-              p:=tai(p.next)
+              p:=tai(p.next);
             end
           else if p.typ=ait_instruction then
             p:=hp1
@@ -2560,8 +2706,7 @@ Implementation
   function TCpuThumb2AsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
     var
       hp : taicpu;
-      hp1,hp2 : tai;
-      oldreg : TRegister;
+      //hp1,hp2 : tai;
     begin
       result:=false;
       if inherited PeepHoleOptPass1Cpu(p) then
@@ -2688,10 +2833,8 @@ Implementation
   procedure TCpuThumb2AsmOptimizer.PeepHoleOptPass2;
     var
       p,hp1,hp2: tai;
-      l,l2 : longint;
+      l : longint;
       condition : tasmcond;
-      hp3: tai;
-      WasLast: boolean;
       { UsedRegs, TmpUsedRegs: TRegSet; }
 
     begin

+ 8 - 5
compiler/arm/aoptcpub.pas

@@ -124,11 +124,14 @@ Implementation
     begin
       result:=false;
       for i:=0 to taicpu(p1).ops-1 do
-        if (taicpu(p1).oper[i]^.typ=top_reg) and (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
-          begin
-            result:=true;
-            exit;
-          end;
+        case taicpu(p1).oper[i]^.typ of
+          top_reg:
+            if (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
+              exit(true);
+          top_ref:
+            if (taicpu(p1).spilling_get_operation_type_ref(i,Reg)<>operand_read) then
+              exit(true);
+        end;
     end;
 
 End.

+ 141 - 118
compiler/arm/armatt.inc

@@ -1,12 +1,9 @@
 { don't edit, this file is generated from armins.dat }
 (
 'none',
-'abs',
-'acs',
-'asn',
-'atn',
 'adc',
 'add',
+'addw',
 'adf',
 'adr',
 'and',
@@ -17,24 +14,18 @@
 'bkpt',
 'bx',
 'cdp',
-'cmf',
-'cmfe',
 'cmn',
 'cmp',
+'cmf',
+'cmfe',
+'stf',
+'ldf',
+'lfm',
 'clz',
-'cnf',
-'cos',
 'cps',
 'cpsid',
 'cpsie',
-'dvf',
 'eor',
-'exp',
-'fdv',
-'flt',
-'fix',
-'fml',
-'frd',
 'ldc',
 'ldm',
 'ldrbt',
@@ -44,41 +35,32 @@
 'ldrsb',
 'ldrsh',
 'ldrt',
-'ldf',
-'lfm',
-'lgn',
-'log',
 'mcr',
+'mcr2',
+'mrc',
+'mrc2',
+'mcrr',
+'mcrr2',
+'mrrc',
+'mrrc2',
 'mla',
 'mov',
-'mrc',
 'mrs',
 'msr',
-'mnf',
-'muf',
 'mul',
 'mvf',
 'mvn',
+'vmov',
 'nop',
+'orn',
 'orr',
-'rdf',
-'rfs',
-'rfc',
-'rmf',
-'rpw',
 'rsb',
 'rsc',
-'rsf',
-'rnd',
-'pol',
 'sbc',
 'sfm',
 'sin',
 'smlal',
 'smull',
-'sqt',
-'suf',
-'stf',
 'stm',
 'str',
 'strb',
@@ -89,16 +71,14 @@
 'swi',
 'swp',
 'swpb',
-'tan',
 'teq',
 'tst',
 'umlal',
 'umull',
 'wfs',
 'ldrd',
-'mcrr',
-'mrrc',
 'pld',
+'pldw',
 'qadd',
 'qdadd',
 'qdsub',
@@ -113,6 +93,12 @@
 'smlaltt',
 'smlawb',
 'smlawt',
+'vldm',
+'vstm',
+'vpop',
+'vpush',
+'vldr',
+'vstr',
 'smulbb',
 'smulbt',
 'smultb',
@@ -120,67 +106,13 @@
 'smulwb',
 'smulwt',
 'strd',
-'fabsd',
-'fabss',
-'faddd',
-'fadds',
-'fcmpd',
-'fcmped',
-'fcmpes',
-'fcmpezd',
-'fcmpezs',
-'fcmps',
-'fcmpzd',
-'fcmpzs',
-'fcpyd',
-'fcpys',
-'fcvtds',
-'fcvtsd',
-'fdivd',
-'fdivs',
-'fldd',
-'fldm',
-'flds',
-'fmacd',
-'fmacs',
-'fmdhr',
-'fmdlr',
-'fmrdh',
-'fmrdl',
-'fmrs',
-'fmrx',
-'fmscd',
-'fmscs',
-'fmsr',
-'fmstat',
-'fmuld',
-'fmuls',
-'fmxr',
-'fnegd',
-'fnegs',
-'fnmacd',
-'fnmacs',
-'fnmscd',
-'fnmscs',
-'fnmuld',
-'fnmuls',
-'fsitod',
-'fsitos',
-'fsqrtd',
-'fsqrts',
+'ldrht',
+'strht',
+'ldrsbt',
+'ldrsht',
 'fstd',
 'fstm',
 'fsts',
-'fsubd',
-'fsubs',
-'ftosid',
-'ftosis',
-'ftouid',
-'ftouis',
-'fuitod',
-'fuitos',
-'fmdrr',
-'fmrrd',
 'bfc',
 'bfi',
 'clrex',
@@ -188,8 +120,13 @@
 'ldrexb',
 'ldrexd',
 'ldrexh',
+'strex',
+'strexb',
+'strexd',
+'strexh',
 'mls',
-'pkh',
+'pkhbt',
+'pkhtb',
 'pli',
 'qadd16',
 'qadd8',
@@ -212,6 +149,8 @@
 'lsr',
 'lsl',
 'ror',
+'rrx',
+'umaal',
 'shadd16',
 'shadd8',
 'shasx',
@@ -228,54 +167,108 @@
 'smuad',
 'smusd',
 'srs',
+'rfe',
 'ssat',
 'ssat16',
 'ssax',
 'ssub16',
 'ssub8',
-'strex',
-'strexb',
-'strexd',
-'strexh',
 'sxtab',
 'sxtab16',
 'sxtah',
+'ubfx',
+'uxtab',
+'uxtab16',
+'uxtah',
 'sxtb',
 'sxtb16',
+'sxth',
 'uxtb',
+'uxtb16',
 'uxth',
-'sxth',
 'uadd16',
 'uadd8',
 'uasx',
-'ubfx',
 'uhadd16',
 'uhadd8',
 'uhasx',
 'uhsax',
 'uhsub16',
 'uhsub8',
-'umaal',
 'uqadd16',
 'uqadd8',
 'uqasx',
 'uqsax',
 'uqsub16',
 'uqsub8',
-'uqsad8',
-'uqsada8',
+'usad8',
+'usada8',
 'usat',
 'usat16',
 'usax',
 'usub16',
 'usub8',
-'uxtab',
-'uxtab16',
-'uxtah',
-'uxtb16',
 'wfe',
 'wfi',
 'yield',
+'fabsd',
+'fabss',
+'faddd',
+'fadds',
+'fcmpd',
+'fcmps',
+'fcmped',
+'fcmpes',
+'fcmpzd',
+'fcmpzs',
+'fcmpezd',
+'fcmpezs',
+'fcpyd',
+'fcpys',
+'fcvtds',
+'fcvtsd',
+'fdivd',
+'fdivs',
+'fldd',
+'fldm',
+'flds',
+'fmacd',
+'fmacs',
+'fmdhr',
+'fmdlr',
+'fmrdh',
+'fmrdl',
+'fmrs',
+'fmrx',
+'fmscd',
+'fmscs',
+'fmsr',
+'fmstat',
+'fmuld',
+'fmuls',
+'fmxr',
+'fnegd',
+'fnegs',
+'fnmacd',
+'fnmacs',
+'fnmscd',
+'fnmscs',
+'fnmuld',
+'fnmuls',
+'fsitod',
+'fsitos',
+'fsqrtd',
+'fsqrts',
+'fsubd',
+'fsubs',
+'ftosid',
+'ftosis',
+'ftouid',
+'ftouis',
+'fuitod',
+'fuitos',
+'fmdrr',
+'fmrrd',
 'pop',
 'push',
 'sdiv',
@@ -306,29 +299,59 @@
 'vcmp',
 'vcmpe',
 'vcvt',
+'vcvtr',
 'vdiv',
-'vldm',
-'vldr',
-'vmov',
 'vmrs',
 'vmsr',
-'vmul',
 'vmla',
 'vmls',
+'vmul',
 'vnmla',
 'vnmls',
+'vnmul',
 'vfma',
 'vfms',
 'vfnma',
 'vfnms',
 'vneg',
-'vnmul',
-'vpop',
-'vpush',
 'vsqrt',
-'vstm',
-'vstr',
 'vsub',
+'dmb',
+'isb',
+'dsb',
+'smc',
 'neg',
-'svc'
+'svc',
+'bxj',
+'udf',
+'tan',
+'sqt',
+'suf',
+'rsf',
+'rnd',
+'pol',
+'rdf',
+'rfs',
+'rfc',
+'wfc',
+'rmf',
+'rpw',
+'mnf',
+'muf',
+'abs',
+'acs',
+'asn',
+'atn',
+'cnf',
+'cnfe',
+'cos',
+'dvf',
+'exp',
+'fdv',
+'flt',
+'fix',
+'fml',
+'frd',
+'lgn',
+'log'
 );

+ 23 - 0
compiler/arm/armatts.inc

@@ -330,5 +330,28 @@ 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
 );

+ 1391 - 347
compiler/arm/armins.dat

@@ -85,713 +85,1757 @@
 [NONE]
 void                  void                            none
 
-[ABScc]
+[ADCcc]
+reglo,reglo                 \x6B\x41\x40                  THUMB,ARMv4T
 
-[ACScc]
+reg32,immshifter            \x80\xF1\x40\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\x40\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
 
-[ASNcc]
+reg32,reg32,reg32           \4\x0\xA0                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xA0                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\xA0                     ARM32,ARMv4
 
-[ATNcc]
+[ADDcc]
+reg32,reg32                 \x61\x44\x0                   THUMB,ARMv4T
+reglo,reglo,reglo           \x60\x18\x0                   THUMB,ARMv4T
 
-[ADCcc]
-reg32,reg32,reg32        \4\x0\xA0                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\xA0                     ARM7
-reg32,reg32,reg32,imm    \6\x0\xA0                     ARM7
-reg32,reg32,imm          \7\x2\xA0                     ARM7
+reglo,immshifter            \x60\x1C\x0                   THUMB,ARMv4T
+reglo,reglo,immshifter      \x60\x1C\x0                   THUMB,ARMv4T
+reglo,immshifter            \x6B\x30\x0                   THUMB,ARMv4T
 
-[ADDcc]
-reg32,reg32,reg32        \4\x0\x80                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x80                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x80                     ARM7
-reg32,reg32,imm          \7\x2\x80                     ARM7
+reglo,regsp,immshifter      \x64\xA8\x00                  THUMB,ARMv4T
+regsp,regsp,immshifter      \x64\xB0\x00                  THUMB,ARMv4T
+reg32,regsp,reg32           \x64\x44\x68                  THUMB,ARMv4T
+regsp,reg32                 \x64\x44\x85                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF1\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32                 \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \4\x0\x80                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x80                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\x80                     ARM32,ARMv4
+
+[ADDWcc]
+reg32,reg32,immshifter      \x81\xF2\x0\x0\x0             THUMB32,ARMv6T2
 
 [ADFcc]
+fpureg,fpureg,fpureg        \xA1\0\x0                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x0                     ARM32,FPA
 
 [ADRcc]
+;reg32,immshifter           \x33\x2\x0F                   ARM32,ARMv4
+;reg32,imm32                \x33\x2\x0F                   ARM32,ARMv4
+reglo,immshifter            \x67\xA0\x0\2                 THUMB,ARMv4T
+reglo,memam6                \x67\xA0\x0\2                 THUMB,ARMv4T
+
+reg32,imm32                 \x81\xF2\xAF\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,immshifter            \x81\xF2\xAF\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x81\xF2\xAF\x0\x0            THUMB32,WIDE,ARMv6T2
+
+reg32,memam2                \x33\x2\x0F                   ARM32,ARMv4
 
 [ANDcc]
-reg32,reg32,reg32        \4\x0\x00                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x00                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x00                     ARM7
-reg32,reg32,imm          \7\x2\x00                     ARM7
+reglo,reglo                 \x6B\x40\x00                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF0\x0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \x4\x0\x00                    ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x0\x00                    ARM32,ARMv4
+reg32,reg32,immshifter      \x7\x2\x00                    ARM32,ARMv4
 
 [Bcc]
-mem32                    \1\x0A                        ARM7
-imm24                    \1\x0A                        ARM7
+imm24                       \x62\xE0\x0                   THUMB,ARMv4T
+immshifter                  \x62\xE0\x0                   THUMB,ARMv4T
+mem32                       \x62\xE0\x0                   THUMB,ARMv4T
+
+imm24                       \x63\xD0\x0                   THUMB,ARMv4T
+immshifter                  \x63\xD0\x0                   THUMB,ARMv4T
+mem32                       \x63\xD0\x0                   THUMB,ARMv4T
+
+imm24                       \x1\x0A                       ARM32,ARMv4
+mem32                       \x1\x0A                       ARM32,ARMv4
 
 [BICcc]
-reg32,reg32,reg32        \4\x1\xC0                     ARM7
-reg32,reg32,reg32,reg32  \5\x1\xC0                     ARM7
-reg32,reg32,reg32,imm    \6\x1\xC0                     ARM7
-reg32,reg32,imm          \7\x3\xC0                     ARM7
+reglo,reglo                 \x6B\x43\x80                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF0\x20\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x20\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \x6\x1\xC0                    ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x1\xC0                    ARM32,ARMv4
+reg32,reg32,immshifter      \x7\x3\xC0                    ARM32,ARMv4
 
 [BLcc]
-mem32                    \1\x0B                        ARM7
-imm24                    \1\x0B                        ARM7
+imm24                    \x8D\xF0\xD0                   THUMB,THUMB32,ARMv4T
+immshifter               \x8D\xF0\xD0                   THUMB,THUMB32,ARMv4T
+mem32                    \x8D\xF0\xD0                   THUMB,THUMB32,ARMv4T
+
+imm24                    \x1\x0B                        ARM32,ARMv4
+mem32                    \x1\x0B                        ARM32,ARMv4
 
 [BLX]
-mem32                    \xff                        ARM7
-imm24                    \xff                        ARM7
+reg32                    \x62\x47\x80                   THUMB,ARMv4T
+
+immshifter               \x8D\xF0\xC0                   THUMB32,ARMv6T2
+imm24                    \x8D\xF0\xC0                   THUMB32,ARMv6T2
+mem32                    \x8D\xF0\xC0                   THUMB32,ARMv6T2
+
+imm24                    \x28\xFA                       ARM32,ARMv5T
+mem32                    \x28\xFA                       ARM32,ARMv5T
+reg32                    \3\x01\x2F\xFF\x30             ARM32,ARMv5T
 
 [BKPTcc]
+immshifter               \x60\xBE\x0                   THUMB,ARMv5T
+imm                      \x31\x1\x20\x70               ARM32,ARMv5T
+immshifter               \x31\x1\x20\x70               ARM32,ARMv5T
 
 [BXcc]
-reg32                    \3\x01\x2F\xFF\x10            ARM7
+reg32                    \x62\x47\x0                   THUMB,ARMv4T
+
+reg32                    \3\x01\x2F\xFF\x10            ARM32,ARMv4T
 
 [CDP]
-reg8,reg8           \300\1\x10\101                ARM7
+reg8,reg8                \300\1\x10\101                ARM32,ARMv4
 
-[CMFcc]
+[CMNcc]
+reglo,reglo             \x6B\x42\xC0                     THUMB,ARMv4T
 
-[CMFEcc]
+reg32,immshifter        \x80\xF1\x10\x0F\x00             THUMB32,ARMv6T2
+reg32,reg32             \x80\xEB\x10\x0F\x00             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop   \x80\xEB\x10\x0F\x00             THUMB32,WIDE,ARMv6T2
 
-[CMNcc]
-reg32,reg32              \xC\x1\x60                     ARM7
-reg32,reg32,reg32        \xD\x1\x60                     ARM7
-reg32,reg32,imm          \xE\x1\x60                     ARM7
-reg32,imm                \xF\x3\x60                     ARM7
+reg32,reg32             \xC\x1\x60                       ARM32,ARMv4
+reg32,reg32,shifterop   \xE\x1\x60                       ARM32,ARMv4
+reg32,immshifter        \xF\x1\x60                       ARM32,ARMv4
 
 [CMPcc]
-reg32,reg32              \xC\x1\x40                     ARM7
-reg32,reg32,reg32        \xD\x1\x40                     ARM7
-reg32,reg32,imm          \xE\x1\x40                     ARM7
-reg32,imm                \xF\x3\x40                     ARM7
+reglo,reglo             \x6B\x42\x80                     THUMB,ARMv4T
+reg32,reg32             \x61\x45\x0                      THUMB,ARMv4T
 
-[CLZcc]
-reg32,reg32              \x27\x01\x01                   ARM7
+reglo,immshifter        \x6B\x28\x0                      THUMB,ARMv4T
 
-[CNFcc]
+reg32,immshifter         \x80\xF1\xB0\x0F\x00           THUMB32,WIDE,ARMv6T2
+reg32,reg32              \x80\xEB\xB0\x0F\x00           THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop    \x80\xEB\xB0\x0F\x00           THUMB32,WIDE,ARMv6T2
 
-[COScc]
+reg32,reg32              \xC\x1\x40                     ARM32,ARMv4
+reg32,reg32,shifterop    \xE\x1\x40                     ARM32,ARMv4
+reg32,immshifter         \xF\x3\x40                     ARM32,ARMv4
 
-[CPS]
-[CPSID]
-[CPSIE]
+[CMFcc]
+fpureg,fpureg            \xA2\xE\x90                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\x90                    ARM32,FPA
 
-[DVFcc]
+[CMFEcc]
+fpureg,fpureg            \xA2\xE\xC0                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\xC0                    ARM32,FPA
 
-[EORcc]
-reg32,reg32,reg32        \4\x0\x20                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x20                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x20                     ARM7
-reg32,reg32,imm          \7\x2\x20                     ARM7
+[STFcc]
+fpureg,memam2            \xA0\xC\x00\x1\x0              ARM32,FPA
 
-[EXPcc]
+[LDFcc]
+fpureg,memam2            \xA0\xC\x10\x1\x0              ARM32,FPA
 
-[FDVcc]
+[LFMcc]
+fpureg,imm32,memam2      \xA0\xC\x10\x2\x0              ARM32,FPA
+fpureg,immshifter,memam2 \xA0\xC\x10\x2\x0              ARM32,FPA
 
-[FLTcc]
+[CLZcc]
+reg32,reg32              \x80\xFA\xB0\xF0\x80           THUMB32,ARMv6T2
+reg32,reg32              \x32\x01\x6F\xF\x10            ARM32,ARMv4
 
-[FIXcc]
+[CPS]
+immshifter               \x8F\xF3\xAF\x81\x00           THUMB32,ARMv6T2
+immshifter               \x46\xF1\x2\x0\x0              ARM32,ARMv6
 
-[FMLcc]
+[CPSID]
+modeflags                \x6C\xB6\x70                   THUMB,ARMv6
+modeflags                \x8F\xF3\xAF\x86\x00           THUMB32,WIDE,ARMv6T2
+modeflags,immshifter     \x8F\xF3\xAF\x87\x00           THUMB32,WIDE,ARMv6T2
+modeflags                \x46\xF1\xC\x0\x0              ARM32,ARMv6
+modeflags,immshifter     \x46\xF1\xE\x0\x0              ARM32,ARMv6
 
-[FRDcc]
+[CPSIE]
+modeflags                \x6C\xB6\x60                   THUMB,ARMv6
+modeflags                \x8F\xF3\xAF\x84\x00           THUMB32,WIDE,ARMv6T2
+modeflags,immshifter     \x8F\xF3\xAF\x85\x00           THUMB32,WIDE,ARMv6T2
+modeflags                \x46\xF1\x8\x0\x0              ARM32,ARMv6
+modeflags,immshifter     \x46\xF1\xA\x0\x0              ARM32,ARMv6
+
+[EORcc]
+reglo,reglo                 \x6B\x40\x40                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF0\x80\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x80\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \4\x0\x20                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x20                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\x20                     ARM32,ARMv4
 
 [LDC]
-reg32,reg32         \321\300\1\x11\101            ARM7
+reg32,reg32         \321\300\1\x11\101            ARM32,ARMv4
 
 [LDMcc]
-memam4,reglist		   \x26\x81			ARM7
+memam4,reglist              \x69\xC8            THUMB,ARMv4T
+reglo,reglist               \x69\xC8            THUMB,ARMv4T
+
+memam4,reglist              \x8C\xE8\x10\x0\x0  THUMB32,WIDE,ARMv6T2
+reg32,reglist               \x8C\xE8\x10\x0\x0  THUMB32,WIDE,ARMv6T2
+
+memam4,reglist		          \x26\x81			   ARM32,ARMv4
+reg32,reglist		          \x26\x81			   ARM32,ARMv4
 
 [LDRBTcc]
+reg32,memam2              \x88\xF8\x10\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x17\x04\x70                   ARM32,ARMv4
+reg32,immshifter          \x17\x04\x70                   ARM32,ARMv4
 
 [LDRBcc]
-reg32,memam2              \x17\x07\x10                            ARM7
+reglo,memam3              \x65\x5C\x0\0                  THUMB,ARMv4T
+reglo,memam4              \x66\x78\x0\0                  THUMB,ARMv4T
+reg32,memam2              \x88\xF8\x10\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2              \x17\x04\x50                   ARM32,ARMv4
 
 [LDRcc]
-reg32,memam2              \x17\x05\x10                   ARM7
-; reg32,imm32              \x17\x05\x10                   ARM7
-; reg32,reg32              \x18\x04\x10                   ARM7
-; reg32,reg32,imm32        \x19\x04\x10                   ARM7
-; reg32,reg32,reg32        \x20\x06\x10                   ARM7
-; reg32,reg32,reg32,imm32  \x21\x06\x10                   ARM7
+reglo,memam3              \x65\x58\x0\2                  THUMB,ARMv4T
+reglo,memam4              \x66\x68\x0\2                  THUMB,ARMv4T
+reglo,memam5              \x67\x98\x0\2                  THUMB,ARMv4T
+reglo,memam6              \x67\x48\x0\2                  THUMB,ARMv4T
+reg32,memam2              \x88\xF8\x50\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2              \x17\x04\x10                   ARM32,ARMv4
 
 [LDRHcc]
-reg32,imm32              \x22\x50\xB0               ARM7
-reg32,reg32              \x23\x50\xB0               ARM7
-reg32,reg32,imm32        \x24\x50\xB0                   ARM7
-reg32,reg32,reg32        \x25\x10\xB0                   ARM7
+reglo,memam3              \x65\x5A\x0\1                  THUMB,ARMv4T
+reglo,memam4              \x66\x88\x0\1                  THUMB,ARMv4T
+reg32,memam2              \x88\xF8\x30\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2              \x22\x10\xB0                   ARM32,ARMv4
 
 [LDRSBcc]
-reg32,imm32              \x22\x50\xD0               ARM7
-reg32,reg32              \x23\x50\xD0               ARM7
-reg32,reg32,imm32        \x24\x50\xD0                   ARM7
-reg32,reg32,reg32        \x25\x10\xD0                   ARM7
+reglo,memam3              \x65\x56\x0\0                  THUMB,ARMv4T
+reg32,memam2              \x88\xF9\x10\x0\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x22\x10\xD0                   ARM32,ARMv4
+reg32,reg32               \x23\x50\xD0                   ARM32,ARMv4
+reg32,reg32,imm32         \x24\x50\xD0                   ARM32,ARMv4
+reg32,reg32,reg32         \x25\x10\xD0                   ARM32,ARMv4
 
 [LDRSHcc]
-reg32,imm32              \x22\x50\xF0               ARM7
-reg32,reg32              \x23\x50\xF0               ARM7
-reg32,reg32,imm32        \x24\x50\xF0                   ARM7
-reg32,reg32,reg32        \x25\x10\xF0                   ARM7
+reglo,memam3              \x65\x5E\x0\1                  THUMB,ARMv4T
+reg32,memam2              \x88\xF9\x30\x0\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x22\x10\xF0                   ARM32,ARMv4
 
 [LDRTcc]
+reg32,memam2              \x88\xF8\x50\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x17\x04\x30                   ARM32,ARMv4
 
-[LDFcc]
+[MCRcc]
+regf,immshifter,reg32,regf,regf              \x1C\xE\x0\x1     ARM32,ARMv4
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xE\x0\x1     ARM32,ARMv4
 
-[LFMcc]
-reg32,imm8,fpureg        \xF0\x02\x01                   FPA
+[MCR2cc]
+regf,immshifter,reg32,regf,regf              \x1C\xFE\x0\x1    ARM32,ARMv5T
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xFE\x0\x1    ARM32,ARMv5T
 
-[LGNcc]
+[MRCcc]
+regf,immshifter,reg32,regf,regf              \x1C\xE\x10\x1    ARM32,ARMv4
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xE\x10\x1    ARM32,ARMv4
 
-[LOGcc]
+[MRC2cc]
+regf,immshifter,reg32,regf,regf              \x1C\xFE\x10\x1   ARM32,ARMv5T
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xFE\x10\x1   ARM32,ARMv5T
+
+[MCRRcc]
+regf,immshifter,reg32,reg32,regf             \x1D\xC\x40\x0    ARM32,ARMv5TE
+
+[MCRR2cc]
+regf,immshifter,reg32,reg32,regf             \x1D\xFC\x40\x0   ARM32,ARMv6
+
+[MRRCcc]
+regf,immshifter,reg32,reg32,regf             \x1D\xC\x50\x0    ARM32,ARMv5TE
 
-[MCR]
-; reg32,mem32         \320\301\1\x13\110            ARM7
+[MRRC2cc]
+regf,immshifter,reg32,reg32,regf             \x1D\xFC\x50\x0   ARM32,ARMv6
 
 [MLAcc]
-reg32,reg32,reg32,reg32  \x15\x00\x20\x90               ARM7
+reg32,reg32,reg32,reg32  \x80\xFB\x0\x0\x0              THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32  \x15\x00\x20\x9                ARM32,ARMv4
 
 [MOVcc]
-; reg32,shifterop              \x8\x0\0xd                   ARM7
-; reg32,immshifter             \x8\x0\0xd                  ARM7
-; reg32,reg32,reg32        \x9\x1\xA0                     ARM7
-; reg32,reg32,imm          \xA\x1\xA0                     ARM7
-; reg32,imm                \xB\x3\xA0                     ARM7
+reglo,reglo             \x6B\x0\x0                       THUMB,ARMv4T
+reg32,reg32             \x61\x46\x00                     THUMB,ARMv4T
+
+reglo,immshifter        \x6B\x20\x0                      THUMB,ARMv4T
+
+reg32,immshifter        \x80\xF0\x4F\x0\x0               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32             \x80\xEA\x4F\x0\x0               THUMB32,WIDE,ARMv6T2
 
-[MRC]
-; reg32,reg32         \321\301\1\x13\110                  ARM7
+reg32,shifterop         \x8\x1\xA0                       ARM32,ARMv4
+reg32,reg32,shifterop   \xA\x1\xA0                       ARM32,ARMv4
+reg32,immshifter        \xB\x1\xA0                       ARM32,ARMv4
 
 [MRScc]
-reg32,reg32         \x10\x01\x0F                        ARM7
+reg32,regf          \x96\xF3\xEF\x80\x0                 THUMB32,ARMv6
+reg32,regf          \x10\x01\x0F                        ARM32,ARMv4
 
 [MSRcc]
-reg32,reg32         \x11\x01\x29\xF0                    ARM7
-regf,reg32          \x12\x01\x28\xF0                    ARM7
-regf,imm            \x13\x03\x28\xF0                    ARM7
+regf,reg32          \x96\xF3\x80\x80\x0                 THUMB32,ARMv6
 
-[MNFcc]
-
-[MUFcc]
+regf,reg32          \x12\x01\x20\xF0                    ARM32,ARMv4
+regf,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
+regs,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 
 [MULcc]
-reg32,reg32,reg32        \x14\x00\x00\x90          ARM7
+reglo,reglo            \x64\x43\x40              THUMB,ARMv4T
+reglo,reglo,reglo      \x64\x43\x40              THUMB,ARMv4T
+reg32,reg32            \x80\xFB\x00\xF0\x00      THUMB32,ARMv6T2
+reg32,reg32,reg32      \x80\xFB\x00\xF0\x00      THUMB32,ARMv6T2
+reg32,reg32,reg32      \x14\x00\x00\x90          ARM32,ARMv4
 
 [MVFcc]
-fpureg,fpureg              \xF2                      FPA
-fpureg,immfpu              \xF2                      FPA
+fpureg,fpureg               \xA1\1\x1                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x1                     ARM32,FPA
 
 [MVNcc]
-; reg32,reg32         \x8\x0\0xf                     ARM7
-; reg32,reg32,reg32   \x9\x1\xE0                     ARM7
-; reg32,reg32,imm     \xA\x1\xE0                     ARM7
-; reg32,imm           \xB\x3\xE0                     ARM7
+reglo,reglo             \x6B\x43\xc0                    THUMB,ARMv4T
 
-[NOP]
+reg32,immshifter        \x80\xF0\x6F\x0\x0               THUMB32,ARMv6T2
+reg32,reg32             \x80\xEA\x6F\x0\x0               THUMB32,WIDE,ARMv6T2
 
-[ORRcc]
-reg32,reg32,reg32        \4\x1\x80                     ARM7
-reg32,reg32,reg32,reg32  \5\x1\x80                     ARM7
-reg32,reg32,reg32,imm    \6\x1\x80                     ARM7
-reg32,reg32,imm          \7\x3\x80                     ARM7
+reg32,reg32            \x8\x1\xE0                       ARM32,ARMv4
+reg32,reg32,shifterop  \xA\x1\xE0                       ARM32,ARMv4
+reg32,immshifter       \xB\x1\xE0                       ARM32,ARMv4
 
-[RDFcc]
+[VMOVcc]
+vreg,vreg         \x90\xEE\xB0\xA\x40            THUMB32,VFPv2
+vreg,vreg         \x40\xE\xB0\xA\x40            ARM32,VFPv2
 
-[RFScc]
+reg32,vreg        \x90\xEE\x10\xA\x10            THUMB32,VFPv2
+vreg,reg32        \x90\xEE\x00\xA\x10            THUMB32,VFPv2
+reg32,vreg        \x40\xE\x10\xA\x10            ARM32,VFPv2
+vreg,reg32        \x40\xE\x00\xA\x10            ARM32,VFPv2
 
-[RFCcc]
+reg32,reg32,vreg,vreg \x90\xEC\x50\xA\x10        THUMB32,VFPv2
+vreg,vreg,reg32,reg32 \x90\xEC\x40\xA\x10        THUMB32,VFPv2
+reg32,reg32,vreg,vreg \x40\xC\x50\xA\x10        ARM32,VFPv2
+vreg,vreg,reg32,reg32 \x40\xC\x40\xA\x10        ARM32,VFPv2
 
-[RMFcc]
+reg32,reg32,vreg      \x90\xEC\x50\xB\x10        THUMB32,VFPv2
+vreg,reg32,reg32      \x90\xEC\x40\xB\x10        THUMB32,VFPv2
+reg32,reg32,vreg      \x40\xC\x50\xB\x10        ARM32,VFPv2
+vreg,reg32,reg32      \x40\xC\x40\xB\x10        ARM32,VFPv2
 
-[RPWcc]
+[NOP]
+void                    \x61\xBF\x0                  THUMB,ARMv6T2
+void                    \x2F\x03\x20\xF0\x0          ARM32,ARMv6K
+; Before ARMv6K use mov r0,r0
+void                    \x2F\xE1\xA0\x0\x0           ARM32,ARMv4
+
+[ORNcc]
+reg32,immshifter            \x80\xF0\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
 
-[RSBcc]
-reg32,reg32,reg32        \4\x0\x60                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x60                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x60                     ARM7
-reg32,reg32,imm          \7\x2\x60                     ARM7
+[ORRcc]
+reglo,reglo                  \x6B\x43\x00            THUMB,ARMv4T
 
-[RSCcc]
-reg32,reg32,reg32        \4\x0\xE0                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\xE0                     ARM7
-reg32,reg32,reg32,imm    \6\x0\xE0                     ARM7
-reg32,reg32,imm          \7\x2\xE0                     ARM7
+reg32,immshifter            \x80\xF0\x40\x0\x0       THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x40\x0\x0       THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
 
-[RSFcc]
+reg32,reg32,reg32            \4\x1\x80               ARM32,ARMv4
+reg32,reg32,reg32,reg32      \5\x1\x80               ARM32,ARMv4
+reg32,reg32,reg32,shifterop  \6\x1\x80               ARM32,ARMv4
+reg32,reg32,immshifter       \7\x3\x80               ARM32,ARMv4
 
-[RNDcc]
+[RSBcc]
+reglo,reglo,immzero         \x6B\x42\x40                  THUMB,ARMv4T
 
-[POLcc]
+reg32,immshifter            \x80\xF1\xC0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32                 \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\xC0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+
+reg32,reg32,reg32            \6\x0\x60                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop  \6\x0\x60                     ARM32,ARMv4
+reg32,reg32,immshifter       \7\x0\x60                     ARM32,ARMv4
+
+[RSCcc]
+reg32,reg32,reg32            \4\x0\xE0                     ARM32,ARMv4
+reg32,reg32,reg32,reg32      \5\x0\xE0                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop  \6\x0\xE0                     ARM32,ARMv4
+reg32,reg32,immshifter       \7\x2\xE0                     ARM32,ARMv4
 
 [SBCcc]
-reg32,reg32,reg32        \4\x0\xC0                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\xC0                     ARM7
-reg32,reg32,reg32,imm    \6\x0\xC0                     ARM7
-reg32,reg32,imm          \7\x2\xC0                     ARM7
+reglo,reglo                 \x6B\x41\x80                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF1\x60\x0\x0             THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\x60\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \4\x0\xC0                     ARM32,ARMv4
+reg32,reg32,reg32,reg32     \5\x0\xC0                     ARM32,ARMv4
+reg32,reg32,reg32,imm       \6\x0\xC0                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xC0                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\xC0                     ARM32,ARMv4
 
 [SFMcc]
-reg32,imm8,fpureg        \xF0\x02\x00                   FPA
+fpureg,imm32,memam2      \xA0\xC\x00\x2\x0              ARM32,FPA
+fpureg,immshifter,memam2 \xA0\xC\x00\x2\x0              ARM32,FPA
 
 [SINcc]
+fpureg,fpureg               \xA1\1\x11                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x11                    ARM32,FPA
 
 [SMLALcc]
-reg32,reg32,reg32,reg32  \x16\x00\xE0\x90		 ARM7
+reg32,reg32,reg32,reg32     \x85\xFB\xC0\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\xE0\x9               ARM32,ARMv4
 
 [SMULLcc]
-reg32,reg32,reg32,reg32  \x16\x00\xC0\x90		 ARM7
-
-[SQTcc]
+reg32,reg32,reg32,reg32     \x85\xFB\x80\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\xC0\x9               ARM32,ARMv4
 
-[SUFcc]
+[STMcc]
+memam4,reglist              \x69\xC0            THUMB,ARMv4T
+reglo,reglist               \x69\xC0            THUMB,ARMv4T
 
-[STFcc]
+memam4,reglist              \x8C\xE8\x00\x0\x0  THUMB32,WIDE,ARMv6T2
+reg32,reglist               \x8C\xE8\x00\x0\x0  THUMB32,WIDE,ARMv6T2
 
-[STMcc]
-memam4,reglist		   \x26\x80			ARM7
+memam4,reglist		          \x26\x80			   ARM32,ARMv4
+reg32,reglist		          \x26\x80			   ARM32,ARMv4
 
 [STRcc]
-reg32,memam2              \x17\x04\x00                   ARM7
-; reg32,imm32              \x17\x05\x00                   ARM7
-; reg32,reg32              \x18\x04\x00                   ARM7
-; reg32,reg32,imm32        \x19\x04\x00                   ARM7
-; reg32,reg32,reg32        \x20\x06\x00                   ARM7
-; reg32,reg32,reg32,imm32  \x21\x06\x00                   ARM7
+reglo,memam3                \x65\x50\x0\2                  THUMB,ARMv4T
+reglo,memam4                \x66\x60\x0\2                  THUMB,ARMv4T
+reglo,memam5                \x67\x90\x0\2                  THUMB,ARMv4T
+reg32,memam2                \x88\xF8\x40\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x17\x04\x00                   ARM32,ARMv4
 
 [STRBcc]
-reg32,memam2              \x17\x06\x00                           ARM7
+reglo,memam3                \x65\x54\x0\0                  THUMB,ARMv4T
+reglo,memam4                \x66\x70\x0\0                  THUMB,ARMv4T
+reg32,memam2                \x88\xF8\x00\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x17\x04\x40                   ARM32,ARMv4
 
 [STRBTcc]
+reg32,memam2                \x88\xF8\x00\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2                \x17\x04\x60                   ARM32,ARMv4
+reg32,immshifter            \x17\x04\x60                   ARM32,ARMv4
 
-; A dummy since it is parsed as STR{cond}H
 [STRHcc]
-reg32,imm32              \x22\x40\xB0              ARM7
-reg32,reg32              \x23\x40\xB0               ARM7
-reg32,reg32,imm32        \x24\x40\xB0                   ARM7
-reg32,reg32,reg32        \x25\x00\xB0                   ARM7
+reglo,memam3                \x65\x52\x0\1                  THUMB,ARMv4T
+reglo,memam4                \x66\x80\x0\1                  THUMB,ARMv4T
+reg32,memam2                \x88\xF8\x20\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x22\x00\xB0                   ARM32,ARMv4
 
 [STRTcc]
+reg32,memam2                \x88\xF8\x40\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2                \x17\x04\x20                   ARM32,ARMv4
 
 [SUBcc]
-reg32,reg32,shifterop     \4\x0\x40                     ARM7
-reg32,reg32,immshifter    \4\x0\x40                     ARM7
-reg32,reg32,reg32        \4\x0\x40                     ARM7
-; reg32,reg32,reg32,reg32  \5\x0\x40                     ARM7
-; reg32,reg32,reg32,imm    \6\x0\x40                     ARM7
-; reg32,reg32,imm          \7\x2\x40                     ARM7
+regsp,immshifter            \x64\xB0\x80                   THUMB,ARMv4T
+regsp,regsp,immshifter      \x64\xB0\x80                   THUMB,ARMv4T
+reglo,reglo                 \x60\x1A\x0                    THUMB,ARMv4T
+reglo,reglo,reglo           \x60\x1A\x0                    THUMB,ARMv4T
+
+reglo,immshifter            \x60\x1E\x0                    THUMB,ARMv4T
+reglo,reglo,immshifter      \x60\x1E\x0                    THUMB,ARMv4T
+reglo,imm8                  \x6B\x38\x0                    THUMB,ARMv4T
+reglo,immshifter            \x6B\x38\x0                    THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF1\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32                 \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,shifterop       \x4\x0\x40                     ARM32,ARMv4
+reg32,reg32,immshifter      \x4\x0\x40                     ARM32,ARMv4
+reg32,reg32,reg32           \x4\x0\x40                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x0\x40                     ARM32,ARMv4
 
 [SWIcc]
-imm                 \2\x0F                        ARM7
+; Old alias for SVC
 
 [SWPcc]
-reg32,reg32,reg32   \x27\x01\x90                   ARM7
+reg32,reg32,memam2          \x27\x10\x09                   ARM32,ARMv4
 
 [SWPBcc]
-reg32,reg32,reg32   \x27\x01\x90                   ARM7
-
-[TANcc]
+reg32,reg32,memam2          \x27\x14\x09                   ARM32,ARMv4
 
 [TEQcc]
-reg32,reg32         \xC\x1\x20                     ARM7
-reg32,reg32,reg32   \xD\x1\x20                     ARM7
-reg32,reg32,imm     \xE\x1\x20                     ARM7
-reg32,imm           \xF\x3\x20                     ARM7
+reg32,immshifter      \x80\xF0\x90\x0F\x00           THUMB32,ARMv6T2
+reg32,reg32           \x80\xEA\x90\x0F\x00           THUMB32,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x90\x0F\x00           THUMB32,ARMv6T2
+
+reg32,reg32           \xC\x1\x20                     ARM32,ARMv4
+reg32,reg32,reg32     \xD\x1\x20                     ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x20                     ARM32,ARMv4
+reg32,immshifter      \xF\x3\x20                     ARM32,ARMv4
 
 [TSTcc]
-reg32,reg32         \xC\x1\x00                     ARM7
-reg32,reg32,reg32   \xD\x1\x00                     ARM7
-reg32,reg32,imm     \xE\x1\x00                     ARM7
-reg32,imm           \xF\x3\x00                     ARM7
+reglo,reglo           \x6B\x42\x00                   THUMB,ARMv4T
+
+reg32,immshifter      \x80\xF0\x10\x0F\x00           THUMB32,ARMv6T2
+reg32,reg32           \x80\xEA\x10\x0F\x00           THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x10\x0F\x00           THUMB32,WIDE,ARMv6T2
+
+reg32,reg32           \xC\x1\x00                     ARM32,ARMv4
+reg32,reg32,reg32     \xD\x1\x00                     ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x00                     ARM32,ARMv4
+reg32,immshifter      \xF\x3\x00                     ARM32,ARMv4
 
 [UMLALcc]
-reg32,reg32,reg32,reg32  \x16\x00\xA0\x90		 ARM7
+reg32,reg32,reg32,reg32     \x85\xFB\xE0\x0\x00     THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\xA0\x9         ARM32,ARMv4
 
 [UMULLcc]
-reg32,reg32,reg32,reg32  \x16\x00\x80\x90		 ARM7
+reg32,reg32,reg32,reg32     \x85\xFB\xA0\x0\x0      THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\x80\x9         ARM32,ARMv4
 
 [WFScc]
+reg32                      \xA2\xE\x2               ARM32,FPA
 
 ; EDSP instructions
 [LDRDcc]
-
-[MCRRcc]
-
-[MRRCcc]
+reg32,reg32,memam2         \x89\xE8\x50\x0\x0                  THUMB32,ARMv6T2
+reg32,reg32,memam2         \x19\x0\x0\x0\xD0                   ARM32,ARMv4
 
 [PLD]
+memam2                     \x87\xF8\x10\xF0\x0                 THUMB32,ARMv6T2
+memam2                     \x25\xF5\x50\xF0\x0                 ARM32,ARMv5TE
+
+[PLDW]
+memam2                     \x87\xF8\x30\xF0\x0                 THUMB32,ARMv7
+memam2                     \x25\xF5\x10\xF0\x0                 ARM32,ARMv7
 
 [QADDcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\x80                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x00\x05                    ARM32,ARMv5TE
 
 [QDADDcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\x90                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x40\x05                    ARM32,ARMv5TE
 
 [QDSUBcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\xB0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x60\x05                    ARM32,ARMv5TE
 
 [QSUBcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\xA0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x20\x05                    ARM32,ARMv5TE
 
 [SMLABBcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\x8                     ARM32,ARMv5TE
 
 [SMLABTcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\xC                     ARM32,ARMv5TE
 
 [SMLATBcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\xA                     ARM32,ARMv5TE
 
 [SMLATTcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\xE                     ARM32,ARMv5TE
 
 [SMLALBBcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\x8                     ARM32,ARMv5TE
 
 [SMLALBTcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\xC                     ARM32,ARMv5TE
 
 [SMLALTBcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\xA                     ARM32,ARMv5TE
 
 [SMLALTTcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\xE                     ARM32,ARMv5TE
 
 [SMLAWBcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x30\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x1\x20\x8                      ARM32,ARMv5TE
 
 [SMLAWTcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x30\x0\x10                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x1\x20\xC                      ARM32,ARMv5TE
+
+[VLDMcc]
+memam4,reglist		      \x94\xEC\x10\xA		         THUMB32,VFPv2
+reg32,reglist		      \x94\xEC\x10\xA		         THUMB32,VFPv2
+memam4,reglist		      \x44\xC\x10\xA		         ARM32,VFPv2
+reg32,reglist		      \x44\xC\x10\xA		         ARM32,VFPv2
+
+[VSTMcc]
+memam4,reglist		      \x94\xEC\x00\xA		         THUMB32,VFPv2
+reg32,reglist		      \x94\xEC\x00\xA		         THUMB32,VFPv2
+memam4,reglist		      \x44\xC\x00\xA		         ARM32,VFPv2
+reg32,reglist		      \x44\xC\x00\xA		         ARM32,VFPv2
+
+[VPOP]
+reglist		            \x94\xEC\xBD\xA		         THUMB32,VFPv2
+reglist		            \x44\xC\xBD\xA		         ARM32,VFPv2
+
+[VPUSH]
+reglist		            \x94\xED\x2D\xA		         THUMB32,VFPv2
+reglist		            \x44\xD\x2D\xA		         ARM32,VFPv2
+
+[VLDRcc]
+vreg,memam2             \x95\xED\x10\xA             THUMB32,VFPv2
+vreg,memam2             \x45\xD\x10\xA             ARM32,VFPv2
+
+[VSTRcc]
+vreg,memam2             \x95\xED\x0\xA              THUMB32,VFPv2
+vreg,memam2             \x45\xD\x0\xA              ARM32,VFPv2
 
 [SMULBBcc]
+reg32,reg32,reg32           \x15\x01\x60\x8\x0                  ARM32,ARMv5TE
 
 [SMULBTcc]
+reg32,reg32,reg32           \x15\x01\x60\xC\x0                  ARM32,ARMv5TE
 
 [SMULTBcc]
+reg32,reg32,reg32           \x15\x01\x60\xA\x0                  ARM32,ARMv5TE
 
 [SMULTTcc]
+reg32,reg32,reg32           \x15\x01\x60\xE\x0                  ARM32,ARMv5TE
 
 [SMULWBcc]
+reg32,reg32,reg32           \x14\x1\x20\xA0                     ARM32,ARMv5TE
 
 [SMULWTcc]
+reg32,reg32,reg32           \x14\x1\x20\xE0                     ARM32,ARMv5TE
 
 [STRDcc]
+reg32,reg32,memam2         \x89\xE8\x40\x0\x0                  THUMB32,ARMv6T2
+reg32,reg32,memam2         \x19\x0\x0\x0\xF0                   ARM32,ARMv4
 
-;
-; vfp instructions
-;
-[FABSDcc]
+[LDRHTcc]
+reg32,memam2               \x88\xF8\x30\xE\x0\0                THUMB32,ARMv6T2
+reg32,memam2               \x19\x0\x30\x0\xB0                  ARM32,ARMv4
 
-[FABSScc]
+[STRHTcc]
+reg32,memam2               \x88\xF8\x20\xE\x0\0                THUMB32,ARMv6T2
 
-[FADDDcc]
+reg32,memam2               \x88\xF8\x20\xE\x0\0                THUMB32,ARMv6T2
+reg32,memam2               \x1E\x0\x20\x0\xB0                  ARM32,ARMv4
 
-[FADDScc]
+[LDRSBTcc]
+reg32,memam2               \x88\xF9\x10\xE\x0\0                THUMB32,ARMv6T2
+reg32,memam2               \x1E\x0\x30\x0\xD0                  ARM32,ARMv4
 
-[FCMPDcc]
+[LDRSHTcc]
+reg32,memam2              \x88\xF9\x30\xE\x0\0                 THUMB32,ARMv6T2
+reg32,memam2              \x1E\x0\x30\x0\xF0                   ARM32,ARMv4
 
-[FCMPEDcc]
+[FSTDcc]
+vreg,memam2             \x95\xED\x0\xA                         THUMB32,VFPv2
+vreg,memam2             \x45\xD\x0\xA                          ARM32,VFPv2
 
-[FCMPEScc]
+[FSTMcc]
+memam4,reglist		      \x94\xEC\x00\xA		                  THUMB32,VFPv2
+reg32,reglist		      \x94\xEC\x00\xA		                  THUMB32,VFPv2
+memam4,reglist		      \x44\xC\x00\xA		                     ARM32,VFPv2
+reg32,reglist		      \x44\xC\x00\xA		                     ARM32,VFPv2
 
-[FCMPEZDcc]
+[FSTScc]
+vreg,memam2             \x95\xED\x0\xA                         THUMB32,VFPv2
+vreg,memam2             \x45\xD\x0\xA                          ARM32,VFPv2
 
-[FCMPEZScc]
+; ARMv6
 
-[FCMPScc]
+[BFCcc]
+reg32,immshifter,immshifter       \x84\xF3\x6F\x0\x0            THUMB32,ARMv6T2
+reg32,immshifter,imm32            \x84\xF3\x6F\x0\x0            THUMB32,ARMv6T2
 
-[FCMPZDcc]
+reg32,immshifter,immshifter       \x2D\x7\xC0\x0\x1F            ARM32,ARMv4
+reg32,immshifter,imm32            \x2D\x7\xC0\x0\x1F            ARM32,ARMv4
 
-[FCMPZScc]
+[BFIcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,immshifter,imm32      \x84\xF3\x60\x0\x0            THUMB32,ARMv6T2
 
-[FCPYDcc]
+reg32,reg32,immshifter,immshifter \x2D\x7\xC0\x0\x10            ARM32,ARMv4
+reg32,reg32,immshifter,imm32      \x2D\x7\xC0\x0\x10            ARM32,ARMv4
 
-[FCPYScc]
+[CLREX]
+void                      \x80\xF3\xBF\x8F\x2F            THUMB32,ARMv7
+void                      \x2F\xF5\x7F\xF0\x1F            ARM32,ARMv6K
 
-[FCVTDScc]
+[LDREXcc]
+reg32,memam6              \x8A\xE8\x50\x0F\x00            THUMB32,ARMv6T2
+reg32,memam6              \x18\x01\x90\x0F\x9F            ARM32,ARMv4
 
-[FCVTSDcc]
+[LDREXBcc]
+reg32,memam6              \x8A\xE8\xD0\x0F\x4F            THUMB32,ARMv7
+reg32,memam6              \x18\x01\xD0\x0F\x9F            ARM32,ARMv4
 
-[FDIVDcc]
+[LDREXDcc]
+reg32,reg32,memam6        \x8A\xE8\xD0\x00\x7F            THUMB32,ARMv7
+reg32,reg32,memam6        \x18\x01\xB0\x0F\x9F            ARM32,ARMv4
 
-[FDIVScc]
+[LDREXHcc]
+reg32,memam6              \x8A\xE8\xD0\x0F\x5F            THUMB32,ARMv7
+reg32,memam6              \x18\x01\xF0\x0F\x9F            ARM32,ARMv4
 
-[FLDDcc]
+[STREXcc]
+reg32,reg32,memam6        \x8B\xE8\x40\x00\x00            THUMB32,ARMv6T2
+reg32,reg32,memam6        \x18\x01\x80\x0F\x90            ARM32,ARMv4
 
-[FLDMcc]
+[STREXBcc]
+reg32,reg32,memam6        \x8B\xE8\xC0\x0F\x40            THUMB32,ARMv7
+reg32,reg32,memam6        \x18\x01\xC0\x0F\x90            ARM32,ARMv4
 
-[FLDScc]
+[STREXDcc]
+reg32,reg32,reg32,memam6  \x8B\xE8\xC0\x00\x70            THUMB32,ARMv7
+reg32,reg32,reg32,memam6  \x18\x01\xA0\x0F\x90            ARM32,ARMv4
 
-[FMACDcc]
+[STREXHcc]
+reg32,reg32,memam6        \x8B\xE8\xC0\x0F\x50            THUMB32,ARMv7
+reg32,reg32,memam6        \x18\x01\xE0\x0F\x90            ARM32,ARMv4
 
-[FMACScc]
+[MLScc]
+reg32,reg32,reg32,reg32   \x80\xFB\x0\x0\x10              THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32   \x15\x00\x60\x9                 ARM32,ARMv6T2
 
-[FMDHRcc]
+[PKHBTcc]
+reg32,reg32,reg32           \x80\xEA\xC0\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x0            THUMB32,ARMv6T2
 
-[FMDLRcc]
+reg32,reg32,reg32           \x16\x6\x80\x1                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\x80\x1                     ARM32,ARMv6
 
-[FMRDHcc]
+[PKHTBcc]
+reg32,reg32,reg32           \x80\xEA\xC0\x0\x10           THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x10           THUMB32,ARMv6T2
 
-[FMRDLcc]
+reg32,reg32,reg32           \x16\x6\x80\x1                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\x80\x5                     ARM32,ARMv6
 
-[FMRScc]
+[PLI]
+memam2                     \x87\xF9\x10\xF0\x0                 THUMB32,ARMv7
+memam2                     \x25\xF4\x50\xF0\x0                 ARM32,ARMv7
 
-[FMRXcc]
+[QADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF1                    ARM32,ARMv6
+[QADD8cc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF9                    ARM32,ARMv6
+[QASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF3                    ARM32,ARMv6
+[QSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF5                    ARM32,ARMv6
+[QSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF7                    ARM32,ARMv6
+[QSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xFF                    ARM32,ARMv6
 
-[FMSCDcc]
+[RBITcc]
+reg32,reg32                \x80\xFA\x90\xF0\xA0                THUMB32,ARMv6T2
+reg32,reg32                \x32\x6\xFF\xF\x30                  ARM32,ARMv6T2
 
-[FMSCScc]
+[REVcc]
+reglo,reglo                \x61\xBA\x00                        THUMB,ARMv6
+reg32,reg32                \x80\xFA\x90\xF0\x80                THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x32\x6\xBF\xF\x30                  ARM32,ARMv6
 
-[FMSRcc]
+[REV16cc]
+reglo,reglo                \x61\xBA\x40                        THUMB,ARMv6
+reg32,reg32                \x80\xFA\x90\xF0\x90                THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x32\x6\xBF\xF\xB0                  ARM32,ARMv6
 
-[FMSTATcc]
+[REVSHcc]
+reglo,reglo                \x61\xBA\xC0                        THUMB,ARMv6
+reg32,reg32                \x80\xFA\x90\xF0\xB0                THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x32\x6\xFF\xF\xB0                  ARM32,ARMv6
 
-[FMULDcc]
+[SADD16cc]
+reg32,reg32,reg32          \x80\xFA\90\xF0\x0                  THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF1                    ARM32,ARMv6
 
-[FMULScc]
+[SADD8cc]
+reg32,reg32,reg32          \x80\xFA\80\xF0\x0                  THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF9                    ARM32,ARMv6
 
-[FMXRcc]
+[SASXcc]
+reg32,reg32,reg32          \x80\xFA\A0\xF0\x0                  THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF3                    ARM32,ARMv6
 
-[FNEGDcc]
+[SBFXcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\x40\x0\x0           THUMB32,ARMv6T2
+reg32,reg32,immshifter,immshifter \x2D\x7\xA0\x0\x50           ARM32,ARMv6T2
 
-[FNEGScc]
+[SELcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x80                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x80\xFB                    ARM32,ARMv6
 
-[FNMACDcc]
+[SETEND]
+immshifter                 \x2B\xF1\x01\x0\x0                  ARM32,ARMv6
 
-[FNMACScc]
+[SEVcc]
+void                       \x64\xBF\x40                        THUMB,ARMv7
+void                       \x2F\x3\x20\xF0\x4                  ARM32,ARMv6K
 
-[FNMSCDcc]
+[ASRcc]
+reglo,immshifter           \x60\x1\x0                          THUMB,ARMv4T
+reglo,reglo,immshifter     \x60\x1\x0                          THUMB,ARMv4T
+reglo,reglo                \x6B\x41\x0                         THUMB,ARMv4T
 
-[FNMSCScc]
+reg32,immshifter           \x82\xEA\x4F\x0\x20                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x20                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x40\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x40\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FNMULDcc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x50                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x40                  ARM32,ARMv4
 
-[FNMULScc]
+[LSRcc]
+reglo,immshifter           \x60\x8\x0                          THUMB,ARMv4T
+reglo,reglo,immshifter     \x60\x8\x0                          THUMB,ARMv4T
+reglo,reglo                \x6B\x40\xC0                        THUMB,ARMv4T
 
-[FSITODcc]
+reg32,immshifter           \x82\xEA\x4F\x0\x10                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x10                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x20\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x20\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FSITOScc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x30                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x20                  ARM32,ARMv4
 
-[FSQRTDcc]
+[LSLcc]
+reglo,immshifter           \x60\x0\x0                          THUMB,ARMv4T
+reglo,reglo,immshifter     \x60\x0\x0                          THUMB,ARMv4T
+reglo,reglo                \x6B\x40\x80                        THUMB,ARMv4T
 
-[FSQRTScc]
+reg32,immshifter           \x82\xEA\x4F\x0\x00                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x00                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FSTDcc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x10                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x00                  ARM32,ARMv4
 
-[FSTMcc]
+[RORcc]
+reglo,reglo                \x6B\x41\xC0                        THUMB,ARMv4T
 
-[FSTScc]
+reg32,immshifter           \x82\xEA\x4F\x0\x30                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x30                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FSUBDcc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x70                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x60                  ARM32,ARMv4
 
-[FSUBScc]
+[RRXcc]
+reg32,reg32                \x80\xEA\x4F\x00\x30                THUMB32,ARMv6T2
+reg32,reg32                \x30\x1\xA0\x0\x60                  ARM32,ARMv4
 
-[FTOSIDcc]
+[UMAALcc]
+reg32,reg32,reg32,reg32     \x85\xFB\xE0\x0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x0\x40\x9                     ARM32,ARMv6
 
-[FTOSIScc]
+[SHADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF1                    ARM32,ARMv6
 
-[FTOUIDcc]
+[SHADD8cc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF9                    ARM32,ARMv6
 
-[FTOUIScc]
+[SHASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF3                    ARM32,ARMv6
 
-[FUITODcc]
+[SHSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF5                    ARM32,ARMv6
 
-[FUITOScc]
+[SHSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF7                    ARM32,ARMv6
 
-[FMDRRcc]
+[SHSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xFF                    ARM32,ARMv6
 
-[FMRRDcc]
+[SMLADcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x20\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x00\x1                      ARM32,ARMv6
 
-; ARMv6
+[SMLALDcc]
+reg32,reg32,reg32,reg32    \x85\xFB\xC0\x0\xC0                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x16\x7\x40\x1                      ARM32,ARMv4
 
-[BFCcc]
+[SMLSDcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x40\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x00\x5                      ARM32,ARMv6
 
-[BFIcc]
+[SMLSLDcc]
+reg32,reg32,reg32,reg32    \x85\xFB\xD0\x0\xC0                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x16\x7\x40\x5                      ARM32,ARMv6
 
-[CLREX]
+[SMMLAcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x50\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x50\x1                      ARM32,ARMv6
 
-[LDREXcc]
-[LDREXBcc]
-[LDREXDcc]
-[LDREXHcc]
+[SMMLScc]
+reg32,reg32,reg32,reg32    \x80\xFB\x60\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x50\xD                      ARM32,ARMv6
 
-[MLScc]
+[SMMULcc]
+reg32,reg32,reg32          \x80\xFB\x50\xF0\x0                 THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x7\x50\x1\xF                   ARM32,ARMv6
 
-[PKHcc]
+[SMUADcc]
+reg32,reg32,reg32          \x80\xFB\x20\xF0\x0                 THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x7\x00\x1\xF                   ARM32,ARMv6
 
-[PLI]
+[SMUSDcc]
+reg32,reg32,reg32          \x80\xFB\x40\xF0\x0                 THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x7\x00\x5\xF                   ARM32,ARMv6
 
-[QADD16cc]
-[QADD8cc]
-[QASXcc]
-[QSAXcc]
-[QSUB16cc]
-[QSUB8cc]
+[SRScc]
+[RFEcc]
 
-[RBITcc]
+[SSATcc]
+reg32,immshifter,reg32            \x83\xF3\x00\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32,shifterop  \x83\xF3\x00\x0\x0          THUMB32,ARMv6T2
 
-[REVcc]
-[REV16cc]
-[REVSHcc]
+reg32,immshifter,reg32            \x2A\x6\xA0\x0\x10          ARM32,ARMv6
+reg32,immshifter,reg32,shifterop  \x2A\x6\xA0\x0\x10          ARM32,ARMv6
 
-[SADD16cc]
-[SADD8cc]
-[SASXcc]
+[SSAT16cc]
+reg32,immshifter,reg32            \x83\xF3\x20\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32            \x2A\x6\xA0\xF\x30          ARM32,ARMv6
 
-[SBFXcc]
+[SSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF5                   ARM32,ARMv6
 
-[SELcc]
+[SSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF7                   ARM32,ARMv6
 
-[SETEND]
+[SSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xFF                   ARM32,ARMv6
 
-[SEVcc]
+[SXTABcc]
+reg32,reg32,reg32           \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
 
-[ASRcc]
+reg32,reg32,reg32           \x16\x06\xA0\x07                  ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\xA0\x07                  ARM32,ARMv6
 
-[LSRcc]
+[SXTAB16cc]
+reg32,reg32,reg32           \x86\xFA\x20\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x20\xF0\x80              THUMB32,ARMv6T2
 
-[LSLcc]
+reg32,reg32,reg32           \x16\x06\x80\x07                  ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\x80\x07                  ARM32,ARMv6
 
-[RORcc]
+[SXTAHcc]
+reg32,reg32,reg32           \x86\xFA\x00\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x00\xF0\x80              THUMB32,ARMv6T2
 
-[SHADD16cc]
-[SHADD8cc]
-[SHASXcc]
-[SHSAXcc]
-[SHSUB16cc]
-[SHSUB8cc]
+reg32,reg32,reg32           \x16\x06\xB0\x07                  ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\xB0\x07                  ARM32,ARMv6
 
-[SMLADcc]
-[SMLALDcc]
-[SMLSDcc]
-[SMLSLDcc]
-[SMMLAcc]
-[SMMLScc]
-[SMMULcc]
-[SMUADcc]
-[SMUSDcc]
+[UBFXcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\xC0\x0\x0          THUMB32,ARMv6T2
+reg32,reg32,immshifter,immshifter \x2D\x7\xE0\x0\x50          ARM32,ARMv4
 
-[SRScc]
+[UXTABcc]
+reg32,reg32,reg32           \x86\xFA\x50\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x50\xF0\x80              THUMB32,ARMv6T2
 
-[SSATcc]
-[SSAT16cc]
-[SSAXcc]
+reg32,reg32,reg32           \x16\x6\xE0\x7                    ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xE0\x7                    ARM32,ARMv6
 
-[SSUB16cc]
-[SSUB8cc]
+[UXTAB16cc]
+reg32,reg32,reg32           \x86\xFA\x30\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x30\xF0\x80              THUMB32,ARMv6T2
 
-[STREXcc]
-[STREXBcc]
-[STREXDcc]
-[STREXHcc]
+reg32,reg32,reg32           \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
+
+reg32,reg32,reg32           \x16\x6\xC0\x7                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xC0\x7                     ARM32,ARMv6
+
+[UXTAHcc]
+reg32,reg32,reg32           \x86\xFA\x10\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x10\xF0\x80              THUMB32,ARMv6T2
+
+reg32,reg32,reg32           \x16\x6\xF0\x7                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xF0\x7                     ARM32,ARMv6
 
-[SXTABcc]
-[SXTAB16cc]
-[SXTAHcc]
 [SXTBcc]
+reglo,reglo                 \x61\xB2\x40                       THUMB,ARMv6
+
+reg32,reg32                 \x86\xFA\x4F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x4F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xAF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xAF\x7                     ARM32,ARMv6
+
 [SXTB16cc]
+reg32,reg32                 \x86\xFA\x2F\xF0\x80               THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x2F\xF0\x80               THUMB32,ARMv6T2
+
+reg32,reg32                 \x1B\x6\x8F\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\x8F\x7                     ARM32,ARMv6
+
+[SXTHcc]
+reglo,reglo                 \x61\xB2\x00                       THUMB,ARMv6
+
+reg32,reg32                 \x86\xFA\x0F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x0F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xBF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xBF\x7                     ARM32,ARMv6
 
 [UXTBcc]
+reglo,reglo                 \x61\xB2\xC0                       THUMB,ARMv6
+
+reg32,reg32                 \x86\xFA\x5F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x5F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xEF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xEF\x7                     ARM32,ARMv6
+
+[UXTB16cc]
+reg32,reg32                 \x86\xFA\x3F\xF0\x80               THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x3F\xF0\x80               THUMB32,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xCF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xCF\x7                     ARM32,ARMv6
+
 [UXTHcc]
+reglo,reglo                 \x61\xB2\x80                       THUMB,ARMv6
 
-[SXTHcc]
+reg32,reg32                 \x86\xFA\x1F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x1F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xFF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xFF\x7                     ARM32,ARMv6
 
 [UADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF1                    ARM32,ARMv6
+
 [UADD8cc]
-[UASXcc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF9                    ARM32,ARMv6
 
-[UBFXcc]
+[UASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF3                    ARM32,ARMv6
 
 [UHADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF1                    ARM32,ARMv6
+
 [UHADD8cc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF9                    ARM32,ARMv6
+
 [UHASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF3                    ARM32,ARMv6
+
 [UHSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF5                    ARM32,ARMv6
+
 [UHSUB16cc]
-[UHSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF7                    ARM32,ARMv6
 
-[UMAALcc]
+[UHSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xFF                    ARM32,ARMv6
 
 [UQADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF1                    ARM32,ARMv6
+
 [UQADD8]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF9                    ARM32,ARMv6
+
 [UQASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF3                    ARM32,ARMv6
+
 [UQSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF5                    ARM32,ARMv6
 
 [UQSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF7                    ARM32,ARMv6
+
 [UQSUB8cc]
-[UQSAD8cc]
-[UQSADA8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xFF                    ARM32,ARMv6
+
+[USAD8cc]
+reg32,reg32,reg32          \x80\xFB\x70\xF0\x00                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x07\x80\x01\xF                 ARM32,ARMv6
+
+[USADA8cc]
+reg32,reg32,reg32,reg32    \x80\xFB\x70\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x07\x80\x01                    ARM32,ARMv6
 
 [USATcc]
+reg32,immshifter,reg32            \x83\xF3\x80\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32,shifterop  \x83\xF3\x80\x0\x0          THUMB32,ARMv6T2
+
+reg32,immshifter,reg32            \x2A\x6\xE0\x0\x10          ARM32,ARMv6
+reg32,immshifter,reg32,shifterop  \x2A\x6\xE0\x0\x10          ARM32,ARMv6
+
 [USAT16cc]
+reg32,immshifter,reg32            \x83\xF3\xA0\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32            \x2A\x6\xE0\xF\x30          ARM32,ARMv6
+
 [USAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF5                    ARM32,ARMv6
 
 [USUB16cc]
-[USUB8cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF7                    ARM32,ARMv6
 
-[UXTABcc]
-[UXTAB16cc]
-[UXTAHcc]
-[UXTB16cc]
+[USUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xFF                    ARM32,ARMv6
 
 [WFEcc]
+void                          \x64\xBF\x20                     THUMB,ARMv7
+void                          \x2F\x3\x20\xF0\x2               ARM32,ARMv6K
+
 [WFIcc]
+void                          \x64\xBF\x30                     THUMB,ARMv7
+void                          \x2F\x3\x20\xF0\x3               ARM32,ARMv6K
+
 [YIELDcc]
+void                          \x64\xBF\x10                     THUMB,ARMv7
+void                          \x2F\x3\x20\xF0\x1               ARM32,ARMv6K
+
+;
+; vfp instructions
+;
+[FABSDcc]
+vreg,vreg               \x92\xEE\xB0\xA\xC0\0        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB0\xA\xC0\0         ARM32,VFPv2
+
+[FABSScc]
+vreg,vreg               \x92\xEE\xB0\xA\xC0\1        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB0\xA\xC0\1         ARM32,VFPv2
+
+[FADDDcc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x0\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x0\0          ARM32,VFPv2
+
+[FADDScc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x0\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x0\1          ARM32,VFPv2
+
+[FCMPDcc]
+vreg,vreg               \x92\xEE\xB4\xA\x40\0        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\x40\0         ARM32,VFPv2
+
+[FCMPScc]
+vreg,vreg               \x92\xEE\xB4\xA\x40\1        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\x40\1         ARM32,VFPv2
+
+[FCMPEDcc]
+vreg,vreg               \x92\xEE\xB4\xA\xC0\0        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\xC0\0         ARM32,VFPv2
+
+[FCMPEScc]
+vreg,vreg               \x92\xEE\xB4\xA\xC0\1        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\xC0\1         ARM32,VFPv2
+
+[FCMPZDcc]
+vreg                    \x92\xEE\xB5\xA\x40\0        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\x40\0         ARM32,VFPv2
+
+[FCMPZScc]
+vreg                    \x92\xEE\xB5\xA\x40\1        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\x40\1         ARM32,VFPv2
+
+[FCMPEZDcc]
+vreg                    \x92\xEE\xB5\xA\xC0\0        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\xC0\0         ARM32,VFPv2
+
+[FCMPEZScc]
+vreg                    \x92\xEE\xB5\xA\xC0\1        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\xC0\1         ARM32,VFPv2
+
+[FCPYDcc]
+vreg,vreg               \x43\xEE\xB0\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB0\xB\x40           ARM32,VFPv2
+
+[FCPYScc]
+vreg,vreg               \x43\xEE\xB0\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB0\xA\x40           ARM32,VFPv2
+
+[FCVTDScc]
+vreg,vreg               \x43\xEE\xB7\xA\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB7\xA\xC0           ARM32,VFPv2
+
+[FCVTSDcc]
+vreg,vreg               \x43\xEE\xB7\xB\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB7\xB\xC0           ARM32,VFPv2
+
+[FDIVDcc]
+vreg,vreg,vreg          \x92\xEE\x80\xA\x0\0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x80\xA\x0\0           ARM32,VFPv2
+
+[FDIVScc]
+vreg,vreg,vreg          \x92\xEE\x80\xA\x0\1          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x80\xA\x0\1           ARM32,VFPv2
+
+[FLDDcc]
+vreg,memam2             \x95\xED\x10\xA               THUMB32,VFPv2
+vreg,memam2             \x45\xD\x10\xA                ARM32,VFPv2
+
+[FLDMcc]
+memam4,reglist		      \x94\xEC\x10\xA		         THUMB32,VFPv2
+reg32,reglist		      \x94\xEC\x10\xA		         THUMB32,VFPv2
+memam4,reglist		      \x44\xC\x10\xA		            ARM32,VFPv2
+reg32,reglist		      \x44\xC\x10\xA		            ARM32,VFPv2
+
+[FLDScc]
+vreg,memam2             \x95\xED\x10\xA               THUMB32,VFPv2
+vreg,memam2             \x45\xD\x10\xA                ARM32,VFPv2
+
+[FMACDcc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x00\0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x00\0           ARM32,VFPv2
+
+[FMACScc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x00\1          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x00\1           ARM32,VFPv2
+
+[FMDHRcc]
+
+[FMDLRcc]
+
+[FMRDHcc]
+
+[FMRDLcc]
+
+[FMRScc]
+reg32,vreg              \x90\xEE\x10\xA\x10           THUMB32,VFPv2
+reg32,vreg              \x40\xE\x10\xA\x10            ARM32,VFPv2
+
+[FMRXcc]
+reg32,regf              \x91\xEE\xF0\xA\x10           THUMB32,VFPv2
+regf,regf               \x91\xEE\xF0\xA\x10           THUMB32,VFPv2
+reg32,regf              \x41\xE\xF0\xA\x10            ARM32,VFPv2
+regf,regf               \x41\xE\xF0\xA\x10            ARM32,VFPv2
+
+[FMSCDcc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x00\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x00\0          ARM32,VFPv2
+
+[FMSCScc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x00\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x00\1          ARM32,VFPv2
+
+[FMSRcc]
+vreg,reg32              \x90\xEE\x00\xA\x10           THUMB32,VFPv2
+vreg,reg32              \x40\xE\x00\xA\x10            ARM32,VFPv2
+
+[FMSTATcc]
+void                    \x80\xEE\xF1\xFA\x10          THUMB32,VFPv2
+void                    \x2F\xE\xF1\xFA\x10           ARM32,VFPv2
+
+[FMULDcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x0\0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x0\0           ARM32,VFPv2
+
+[FMULScc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x0\1          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x0\1           ARM32,VFPv2
+
+[FMXRcc]
+regf,reg32              \x91\xEE\xE0\xA\x10           THUMB32,VFPv2
+regf,reg32              \x41\xE\xE0\xA\x10            ARM32,VFPv2
+
+[FNEGDcc]
+vreg,vreg               \x92\xEE\xB1\xA\x40\0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\x40\0          ARM32,VFPv2
+
+[FNEGScc]
+vreg,vreg               \x92\xEE\xB1\xA\x40\1         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\x40\1          ARM32,VFPv2
+
+[FNMACDcc]
+vreg,vreg,vreg          \x92\xEE\x00\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x00\xA\x40\0          ARM32,VFPv2
+
+[FNMACScc]
+vreg,vreg,vreg          \x92\xEE\x00\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x00\xA\x40\1          ARM32,VFPv2
+
+[FNMSCDcc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x40\0          ARM32,VFPv2
+
+[FNMSCScc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x40\1          ARM32,VFPv2
+
+[FNMULDcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x40\0          ARM32,VFPv2
+
+[FNMULScc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x40\1          ARM32,VFPv2
+
+[FSITODcc]
+vreg,vreg               \x43\xEE\xB8\xB\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xB\xC0           ARM32,VFPv2
+
+[FSITOScc]
+vreg,vreg               \x43\xEE\xB8\xA\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xA\xC0           ARM32,VFPv2
+
+[FSQRTDcc]
+vreg,vreg               \x92\xEE\xB1\xA\xC0\0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\xC0\0          ARM32,VFPv2
+
+[FSQRTScc]
+vreg,vreg               \x92\xEE\xB1\xA\xC0\1         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\xC0\1          ARM32,VFPv2
+
+[FSUBDcc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x40\0          ARM32,VFPv2
+
+[FSUBScc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x40\1          ARM32,VFPv2
+
+[FTOSIDcc]
+vreg,vreg               \x43\xEE\xBD\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBD\xB\x40           ARM32,VFPv2
+
+[FTOSIScc]
+vreg,vreg               \x43\xEE\xBD\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBD\xA\x40           ARM32,VFPv2
+
+[FTOUIDcc]
+vreg,vreg               \x43\xEE\xBC\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBC\xB\x40           ARM32,VFPv2
+
+[FTOUIScc]
+vreg,vreg               \x43\xEE\xBC\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBC\xA\x40           ARM32,VFPv2
+
+[FUITODcc]
+vreg,vreg               \x43\xEE\xB8\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xB\x40           ARM32,VFPv2
+
+[FUITOScc]
+vreg,vreg               \x43\xEE\xB8\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xA\x40           ARM32,VFPv2
+
+[FMDRRcc]
+
+[FMRRDcc]
 
 ; Thumb-2
 
 [POP]
+reglist                       \x69\xBC                   THUMB,ARMv4T
+reglist		                  \x26\x8B		               ARM32,ARMv4
 
 [PUSH]
+reglist                       \x69\xB4                   THUMB,ARMv4T
+reglist		                  \x26\x80		               ARM32,ARMv4
 
 [SDIVcc]
+reg32,reg32,reg32             \x80\xFB\x90\xF0\xF0       THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32             \x15\x07\x10\x01\xF        ARM32,ARMv7
 
 [UDIVcc]
+reg32,reg32,reg32             \x80\xFB\xB0\xF0\xF0       THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32             \x15\x07\x30\x01\xF        ARM32,ARMv7
 
 [MOVTcc]
+reg32,imm                     \x81\xF2\xC0\x0\x0         THUMB32,ARMv6T2
+reg32,immshifter              \x81\xF2\xC0\x0\x0         THUMB32,ARMv6T2
+
+reg32,imm                     \x2C\x3\x40                ARM32,ARMv6T2
+reg32,immshifter              \x2C\x3\x40                ARM32,ARMv6T2
 
 [IT]
+condition                     \x6A\xBF\x08\x00           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITE]
+condition                     \x6A\xBF\x04\x88           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITT]
+condition                     \x6A\xBF\x04\x08           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITEE]
+condition                     \x6A\xBF\x02\xCC           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTE]
+condition                     \x6A\xBF\x02\x4C           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITET]
+condition                     \x6A\xBF\x02\x8C           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTT]
+condition                     \x6A\xBF\x02\x0C           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITEEE]
+condition                     \x6A\xBF\x01\xEE           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTEE]
+condition                     \x6A\xBF\x01\x6E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITETE]
+condition                     \x6A\xBF\x01\xAE           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTTE]
+condition                     \x6A\xBF\x01\x2E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITEET]
+condition                     \x6A\xBF\x01\xCE           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTET]
+condition                     \x6A\xBF\x01\x4E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITETT]
+condition                     \x6A\xBF\x01\x8E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTTT]
+condition                     \x6A\xBF\x01\x0E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
+
+[TBBcc]
+memam2                  \x8E\xE8\xD0\xF0\x00       THUMB32,ARMv6T2
 
-[TBB]
-[TBH]
+[TBHcc]
+memam2                  \x8E\xE8\xD0\xF0\x10       THUMB32,ARMv6T2
 
 [MOVW]
+reg32,imm32             \x2C\x3\x0                 ARM32,ARMv6T2
+reg32,immshifter        \x2C\x3\x0                 ARM32,ARMv6T2
+
+reg32,imm32             \x81\xF2\x40\x0\x0         THUMB32,ARMv6T2
+reg32,immshifter        \x81\xF2\x40\x0\x0         THUMB32,ARMv6T2
 
 [CBZ]
+reglo,immshifter        \x68\xB1                   THUMB,ARMv6T2
+reglo,memam2            \x68\xB1                   THUMB,ARMv6T2
+
 [CBNZ]
+reglo,immshifter        \x68\xB9                   THUMB,ARMv6T2
+reglo,memam2            \x68\xB9                   THUMB,ARMv6T2
+
+; VFP
+[VABScc]
+vreg,vreg               \x92\xEE\xB0\xA\xC0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB0\xA\xC0         ARM32,VFPv2
+
+[VADDcc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x0          ARM32,VFPv2
+
+[VCMPcc]
+vreg,vreg               \x92\xEE\xB4\xA\x40         THUMB32,VFPv2
+vreg,immshifter         \x92\xEE\xB5\xA\x40         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\x40         ARM32,VFPv2
+vreg,immshifter         \x42\xE\xB5\xA\x40         ARM32,VFPv2
+
+[VCMPEcc]
+vreg,vreg               \x92\xEE\xB4\xA\xC0         THUMB32,VFPv2
+vreg,immshifter         \x92\xEE\xB5\xA\xC0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\xC0         ARM32,VFPv2
+vreg,immshifter         \x42\xE\xB5\xA\xC0         ARM32,VFPv2
+
+[VCVTcc]
+vreg,vreg               \x93\xEE\xB8\xA\xC0         THUMB32,VFPv2
+vreg,vreg,immshifter    \x93\xEE\xBA\xA\x40         THUMB32,VFPv3
+vreg,vreg               \x43\xE\xB8\xA\xC0         ARM32,VFPv2
+vreg,vreg,immshifter    \x43\xE\xBA\xA\x40         ARM32,VFPv3
+
+[VCVTRcc]
+vreg,vreg               \x93\xEE\xB8\xA\x40         THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xA\x40         ARM32,VFPv2
+
+[VDIVcc]
+vreg,vreg,vreg          \x92\xEE\x80\xA\x0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x80\xA\x0          ARM32,VFPv2
+
+[VMRScc]
+reg32,regf              \x91\xEE\xF0\xA\x10         THUMB32,VFPv2
+regf,regf               \x91\xEE\xF0\xA\x10         THUMB32,VFPv2
+reg32,regf              \x41\xE\xF0\xA\x10         ARM32,VFPv2
+regf,regf               \x41\xE\xF0\xA\x10         ARM32,VFPv2
+
+[VMSRcc]
+regf,reg32              \x91\xEE\xE0\xA\x10         THUMB32,VFPv2
+regf,reg32              \x41\xE\xE0\xA\x10         ARM32,VFPv2
+
+[VMLAcc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x00          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x00          ARM32,VFPv2
+
+[VMLScc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x40          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x40          ARM32,VFPv2
+
+[VMULcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x0          ARM32,VFPv2
+
+[VNMLAcc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x40         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x40         ARM32,VFPv2
+
+[VNMLScc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x00         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x00         ARM32,VFPv2
+
+[VNMULcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x40         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x40         ARM32,VFPv2
 
-; FPv4-s16 - ARMv7M floating point
-[VABS]
-[VADD]
-[VCMP]
-[VCMPE]
-[VCVT]
-[VDIV]
-[VLDM]
-[VLDR]
-[VMOV]
-[VMRS]
-[VMSR]
-[VMUL]
-[VMLA]
-[VMLS]
-[VNMLA]
-[VNMLS]
 [VFMA]
+vreg,vreg,vreg          \x92\xEE\xA0\xA\x00          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\xA0\xA\x00          ARM32,VFPv4
+
 [VFMS]
+vreg,vreg,vreg          \x92\xEE\xA0\xA\x40          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\xA0\xA\x40          ARM32,VFPv4
+
 [VFNMA]
+vreg,vreg,vreg          \x92\xEE\x90\xA\x40          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\x90\xA\x40          ARM32,VFPv4
+
 [VFNMS]
-[VNEG]
-[VNMUL]
-[VPOP]
-[VPUSH]
+vreg,vreg,vreg          \x92\xEE\x90\xA\x00          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\x90\xA\x00          ARM32,VFPv4
+
+[VNEGcc]
+vreg,vreg               \x92\xEE\xB1\xA\x40         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\x40         ARM32,VFPv2
+
 [VSQRT]
-[VSTM]
-[VSTR]
+vreg,vreg               \x92\xEE\xB1\xA\xC0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\xC0         ARM32,VFPv2
+
 [VSUB]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x40         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x40         ARM32,VFPv2
+
+[DMBcc]
+immshifter        \x80\xF3\xBF\x8F\x50             THUMB32,ARMv7
+immshifter        \x2E\xF5\x7F\xF0\x50             ARM32,ARMv7
+
+[ISBcc]
+immshifter        \x80\xF3\xBF\x8F\x60             THUMB32,ARMv7
+immshifter        \x2E\xF5\x7F\xF0\x60             ARM32,ARMv7
+
+[DSBcc]
+immshifter        \x80\xF3\xBF\x8F\x40             THUMB32,ARMv7
+immshifter        \x2E\xF5\x7F\xF0\x40             ARM32,ARMv7
+
+[SMCcc]
+immshifter        \x2E\x01\x60\x00\x70             ARM32,ARMv7
+imm32             \x2E\x01\x60\x00\x70             ARM32,ARMv7
 
 ; Thumb armv6-m (gcc)
-[NEG]
-[SVC]
+[NEGcc]
+
+[SVCcc]
+immshifter         \x61\xDF\x0                     THUMB,ARMv4T
+imm32              \x61\xDF\x0                     THUMB,ARMv4T
+
+immshifter         \x2\x0F                         ARM32,ARMv4
+imm32              \x2\x0F                         ARM32,ARMv4
+
+[BXJcc]
+reg32              \x80\xF3\xC0\x8F\x0             THUMB32,ARMv6T2
+reg32              \x3\x01\x2F\xFF\x20             ARM32,ARMv5TEJ
+
+; Undefined mnemonic
+[UDF]
+immshifter           \x61\xDE\x0                   THUMB,ARMv4T
+void                 void                          ARM32,ARMv4T
+
+; FPA
+
+
+[TANcc]
+fpureg,fpureg               \xA1\1\x15                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x15                    ARM32,FPA
+
+[SQTcc]
+fpureg,fpureg               \xA1\1\x9                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x9                     ARM32,FPA
+
+[SUFcc]
+fpureg,fpureg,fpureg        \xA1\0\x4                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x4                     ARM32,FPA
+
+[RSFcc]
+fpureg,fpureg,fpureg        \xA1\0\x6                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x6                     ARM32,FPA
+
+[RNDcc]
+fpureg,fpureg               \xA1\1\x7                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x7                     ARM32,FPA
+
+[POLcc]
+fpureg,fpureg,fpureg        \xA1\0\x18                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x18                    ARM32,FPA
+
+[RDFcc]
+fpureg,fpureg,fpureg        \xA1\0\xA                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\xA                     ARM32,FPA
+
+[RFScc]
+reg32                      \xA2\xE\x3               ARM32,FPA
+
+[RFCcc]
+reg32                      \xA2\xE\x5               ARM32,FPA
+
+[WFCcc]
+reg32                      \xA2\xE\x4               ARM32,FPA
+
+[RMFcc]
+fpureg,fpureg,fpureg        \xA1\0\x10                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x10                    ARM32,FPA
 
+[RPWcc]
+fpureg,fpureg,fpureg        \xA1\0\xC                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\xC                     ARM32,FPA
+
+[MNFcc]
+fpureg,fpureg               \xA1\1\x3                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x3                     ARM32,FPA
+
+[MUFcc]
+fpureg,fpureg,fpureg        \xA1\0\x2                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x2                     ARM32,FPA
+
+[ABScc]
+fpureg,fpureg               \xA1\1\x5                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x5                     ARM32,FPA
+
+[ACScc]
+fpureg,fpureg               \xA1\1\x19                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x19                    ARM32,FPA
+
+[ASNcc]
+fpureg,fpureg               \xA1\1\x17                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x17                    ARM32,FPA
+
+[ATNcc]
+fpureg,fpureg               \xA1\1\x1B                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x1B                    ARM32,FPA
+
+[CNFcc]
+fpureg,fpureg            \xA2\xE\xB0                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\xB0                    ARM32,FPA
+
+[CNFEcc]
+fpureg,fpureg            \xA2\xE\xF0                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\xF0                    ARM32,FPA
+
+[COScc]
+fpureg,fpureg               \xA1\1\x13                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x13                    ARM32,FPA
+
+[DVFcc]
+fpureg,fpureg,fpureg        \xA1\0\x8                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x8                     ARM32,FPA
+
+[EXPcc]
+fpureg,fpureg               \xA1\1\xF                     ARM32,FPA
+fpureg,immshifter           \xA1\1\xF                     ARM32,FPA
+
+[FDVcc]
+fpureg,fpureg,fpureg        \xA1\0\x14                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x14                    ARM32,FPA
+
+[FLTcc]
+fpureg,reg32                \xA2\xE\x00                   ARM32,FPA
+
+[FIXcc]
+reg32,fpureg                \xA2\xE\x10                   ARM32,FPA
+
+[FMLcc]
+fpureg,fpureg,fpureg        \xA1\0\x12                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x12                    ARM32,FPA
+
+[FRDcc]
+fpureg,fpureg,fpureg        \xA1\0\x16                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x16                    ARM32,FPA
+
+[LGNcc]
+fpureg,fpureg               \xA1\1\xD                     ARM32,FPA
+fpureg,immshifter           \xA1\1\xD                     ARM32,FPA
+
+[LOGcc]
+fpureg,fpureg               \xA1\1\xB                     ARM32,FPA
+fpureg,immshifter           \xA1\1\xB                     ARM32,FPA

+ 1 - 1
compiler/arm/armnop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from armins.dat }
-105;
+952;

+ 141 - 118
compiler/arm/armop.inc

@@ -1,12 +1,9 @@
 { don't edit, this file is generated from armins.dat }
 (
 A_NONE,
-A_ABS,
-A_ACS,
-A_ASN,
-A_ATN,
 A_ADC,
 A_ADD,
+A_ADDW,
 A_ADF,
 A_ADR,
 A_AND,
@@ -17,24 +14,18 @@ A_BLX,
 A_BKPT,
 A_BX,
 A_CDP,
-A_CMF,
-A_CMFE,
 A_CMN,
 A_CMP,
+A_CMF,
+A_CMFE,
+A_STF,
+A_LDF,
+A_LFM,
 A_CLZ,
-A_CNF,
-A_COS,
 A_CPS,
 A_CPSID,
 A_CPSIE,
-A_DVF,
 A_EOR,
-A_EXP,
-A_FDV,
-A_FLT,
-A_FIX,
-A_FML,
-A_FRD,
 A_LDC,
 A_LDM,
 A_LDRBT,
@@ -44,41 +35,32 @@ A_LDRH,
 A_LDRSB,
 A_LDRSH,
 A_LDRT,
-A_LDF,
-A_LFM,
-A_LGN,
-A_LOG,
 A_MCR,
+A_MCR2,
+A_MRC,
+A_MRC2,
+A_MCRR,
+A_MCRR2,
+A_MRRC,
+A_MRRC2,
 A_MLA,
 A_MOV,
-A_MRC,
 A_MRS,
 A_MSR,
-A_MNF,
-A_MUF,
 A_MUL,
 A_MVF,
 A_MVN,
+A_VMOV,
 A_NOP,
+A_ORN,
 A_ORR,
-A_RDF,
-A_RFS,
-A_RFC,
-A_RMF,
-A_RPW,
 A_RSB,
 A_RSC,
-A_RSF,
-A_RND,
-A_POL,
 A_SBC,
 A_SFM,
 A_SIN,
 A_SMLAL,
 A_SMULL,
-A_SQT,
-A_SUF,
-A_STF,
 A_STM,
 A_STR,
 A_STRB,
@@ -89,16 +71,14 @@ A_SUB,
 A_SWI,
 A_SWP,
 A_SWPB,
-A_TAN,
 A_TEQ,
 A_TST,
 A_UMLAL,
 A_UMULL,
 A_WFS,
 A_LDRD,
-A_MCRR,
-A_MRRC,
 A_PLD,
+A_PLDW,
 A_QADD,
 A_QDADD,
 A_QDSUB,
@@ -113,6 +93,12 @@ A_SMLALTB,
 A_SMLALTT,
 A_SMLAWB,
 A_SMLAWT,
+A_VLDM,
+A_VSTM,
+A_VPOP,
+A_VPUSH,
+A_VLDR,
+A_VSTR,
 A_SMULBB,
 A_SMULBT,
 A_SMULTB,
@@ -120,67 +106,13 @@ A_SMULTT,
 A_SMULWB,
 A_SMULWT,
 A_STRD,
-A_FABSD,
-A_FABSS,
-A_FADDD,
-A_FADDS,
-A_FCMPD,
-A_FCMPED,
-A_FCMPES,
-A_FCMPEZD,
-A_FCMPEZS,
-A_FCMPS,
-A_FCMPZD,
-A_FCMPZS,
-A_FCPYD,
-A_FCPYS,
-A_FCVTDS,
-A_FCVTSD,
-A_FDIVD,
-A_FDIVS,
-A_FLDD,
-A_FLDM,
-A_FLDS,
-A_FMACD,
-A_FMACS,
-A_FMDHR,
-A_FMDLR,
-A_FMRDH,
-A_FMRDL,
-A_FMRS,
-A_FMRX,
-A_FMSCD,
-A_FMSCS,
-A_FMSR,
-A_FMSTAT,
-A_FMULD,
-A_FMULS,
-A_FMXR,
-A_FNEGD,
-A_FNEGS,
-A_FNMACD,
-A_FNMACS,
-A_FNMSCD,
-A_FNMSCS,
-A_FNMULD,
-A_FNMULS,
-A_FSITOD,
-A_FSITOS,
-A_FSQRTD,
-A_FSQRTS,
+A_LDRHT,
+A_STRHT,
+A_LDRSBT,
+A_LDRSHT,
 A_FSTD,
 A_FSTM,
 A_FSTS,
-A_FSUBD,
-A_FSUBS,
-A_FTOSID,
-A_FTOSIS,
-A_FTOUID,
-A_FTOUIS,
-A_FUITOD,
-A_FUITOS,
-A_FMDRR,
-A_FMRRD,
 A_BFC,
 A_BFI,
 A_CLREX,
@@ -188,8 +120,13 @@ A_LDREX,
 A_LDREXB,
 A_LDREXD,
 A_LDREXH,
+A_STREX,
+A_STREXB,
+A_STREXD,
+A_STREXH,
 A_MLS,
-A_PKH,
+A_PKHBT,
+A_PKHTB,
 A_PLI,
 A_QADD16,
 A_QADD8,
@@ -212,6 +149,8 @@ A_ASR,
 A_LSR,
 A_LSL,
 A_ROR,
+A_RRX,
+A_UMAAL,
 A_SHADD16,
 A_SHADD8,
 A_SHASX,
@@ -228,54 +167,108 @@ A_SMMUL,
 A_SMUAD,
 A_SMUSD,
 A_SRS,
+A_RFE,
 A_SSAT,
 A_SSAT16,
 A_SSAX,
 A_SSUB16,
 A_SSUB8,
-A_STREX,
-A_STREXB,
-A_STREXD,
-A_STREXH,
 A_SXTAB,
 A_SXTAB16,
 A_SXTAH,
+A_UBFX,
+A_UXTAB,
+A_UXTAB16,
+A_UXTAH,
 A_SXTB,
 A_SXTB16,
+A_SXTH,
 A_UXTB,
+A_UXTB16,
 A_UXTH,
-A_SXTH,
 A_UADD16,
 A_UADD8,
 A_UASX,
-A_UBFX,
 A_UHADD16,
 A_UHADD8,
 A_UHASX,
 A_UHSAX,
 A_UHSUB16,
 A_UHSUB8,
-A_UMAAL,
 A_UQADD16,
 A_UQADD8,
 A_UQASX,
 A_UQSAX,
 A_UQSUB16,
 A_UQSUB8,
-A_UQSAD8,
-A_UQSADA8,
+A_USAD8,
+A_USADA8,
 A_USAT,
 A_USAT16,
 A_USAX,
 A_USUB16,
 A_USUB8,
-A_UXTAB,
-A_UXTAB16,
-A_UXTAH,
-A_UXTB16,
 A_WFE,
 A_WFI,
 A_YIELD,
+A_FABSD,
+A_FABSS,
+A_FADDD,
+A_FADDS,
+A_FCMPD,
+A_FCMPS,
+A_FCMPED,
+A_FCMPES,
+A_FCMPZD,
+A_FCMPZS,
+A_FCMPEZD,
+A_FCMPEZS,
+A_FCPYD,
+A_FCPYS,
+A_FCVTDS,
+A_FCVTSD,
+A_FDIVD,
+A_FDIVS,
+A_FLDD,
+A_FLDM,
+A_FLDS,
+A_FMACD,
+A_FMACS,
+A_FMDHR,
+A_FMDLR,
+A_FMRDH,
+A_FMRDL,
+A_FMRS,
+A_FMRX,
+A_FMSCD,
+A_FMSCS,
+A_FMSR,
+A_FMSTAT,
+A_FMULD,
+A_FMULS,
+A_FMXR,
+A_FNEGD,
+A_FNEGS,
+A_FNMACD,
+A_FNMACS,
+A_FNMSCD,
+A_FNMSCS,
+A_FNMULD,
+A_FNMULS,
+A_FSITOD,
+A_FSITOS,
+A_FSQRTD,
+A_FSQRTS,
+A_FSUBD,
+A_FSUBS,
+A_FTOSID,
+A_FTOSIS,
+A_FTOUID,
+A_FTOUIS,
+A_FUITOD,
+A_FUITOS,
+A_FMDRR,
+A_FMRRD,
 A_POP,
 A_PUSH,
 A_SDIV,
@@ -306,29 +299,59 @@ A_VADD,
 A_VCMP,
 A_VCMPE,
 A_VCVT,
+A_VCVTR,
 A_VDIV,
-A_VLDM,
-A_VLDR,
-A_VMOV,
 A_VMRS,
 A_VMSR,
-A_VMUL,
 A_VMLA,
 A_VMLS,
+A_VMUL,
 A_VNMLA,
 A_VNMLS,
+A_VNMUL,
 A_VFMA,
 A_VFMS,
 A_VFNMA,
 A_VFNMS,
 A_VNEG,
-A_VNMUL,
-A_VPOP,
-A_VPUSH,
 A_VSQRT,
-A_VSTM,
-A_VSTR,
 A_VSUB,
+A_DMB,
+A_ISB,
+A_DSB,
+A_SMC,
 A_NEG,
-A_SVC
+A_SVC,
+A_BXJ,
+A_UDF,
+A_TAN,
+A_SQT,
+A_SUF,
+A_RSF,
+A_RND,
+A_POL,
+A_RDF,
+A_RFS,
+A_RFC,
+A_WFC,
+A_RMF,
+A_RPW,
+A_MNF,
+A_MUF,
+A_ABS,
+A_ACS,
+A_ASN,
+A_ATN,
+A_CNF,
+A_CNFE,
+A_COS,
+A_DVF,
+A_EXP,
+A_FDV,
+A_FLT,
+A_FIX,
+A_FML,
+A_FRD,
+A_LGN,
+A_LOG
 );

+ 9 - 2
compiler/arm/armreg.dat

@@ -87,7 +87,7 @@ S28,$04,$06,$0E,s28,0,0
 S29,$04,$06,$2E,s29,0,0
 D14,$04,$07,$0E,d14,0,0
 S30,$04,$06,$0F,s30,0,0
-S31,$04,$06,$2F,s21,0,0
+S31,$04,$06,$2F,s31,0,0
 D15,$04,$07,$0F,d15,0,0
 D16,$04,$07,$10,d16,0,0
 D17,$04,$07,$11,d17,0,0
@@ -145,4 +145,11 @@ BASEPRI,$05,$00,$1F,basepri,0,0
 BASEPRI_MAX,$05,$00,$20,basepri_max,0,0
 FAULTMASK,$05,$00,$21,faultmask,0,0
 CONTROL,$05,$00,$22,control,0,0
-
+; VFP registers
+FPSID,$05,$00,$23,fpsid,0,0
+MVFR1,$05,$00,$24,mvfr1,0,0
+MVFR0,$05,$00,$25,mvfr0,0,0
+FPEXC,$05,$00,$26,fpexc,0,0
+APSR_nzcvq,$05,$00,$27,apsr_nzcvq,0,0
+APSR_g,$05,$00,$28,apsr_g,0,0
+APSR_nzcvqg,$05,$00,$29,apsr_nzcvqg,0,0

+ 6359 - 430
compiler/arm/armtab.inc

@@ -3,736 +3,6665 @@
   (
     opcode  : A_NONE;
     ops     : 0;
-    optypes : (ot_none,ot_none,ot_none,ot_none);
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #0;
     flags   : if_none
   ),
+  (
+    opcode  : A_ADC;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
   (
     opcode  : A_ADC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#160;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_ADC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#160;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#160;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#0#160;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#2#160;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#68#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
     opcode  : A_ADD;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#128;
-    flags   : if_arm7
+    optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+    code    : #96#24#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#28#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#28#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#48#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reglo,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #100#168#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #100#176#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_regsp,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #100#68#104;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_regsp,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#68#133;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_ADD;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#128;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#128;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADD;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#0#128;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADD;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#2#128;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ADDW;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #129#242#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ADF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_ADF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#160#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#160#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#175#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#175#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#175#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #51#2#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_AND;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#0;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_AND;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#0;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#0;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_AND;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#0#0;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_AND;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#2#0;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#224#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#224#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#224#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #99#208#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #99#208#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #99#208#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
     opcode  : A_B;
     ops     : 1;
-    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#10;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_B;
     ops     : 1;
-    optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#10;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#67#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
   ),
   (
     opcode  : A_BIC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#1#192;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_BIC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#1#192;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #6#1#192;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_BIC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#1#192;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_BIC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#3#192;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BL;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#208;
+    flags   : if_thumb or if_thumb32 or if_armv4t
+  ),
+  (
+    opcode  : A_BL;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#208;
+    flags   : if_thumb or if_thumb32 or if_armv4t
+  ),
+  (
+    opcode  : A_BL;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#208;
+    flags   : if_thumb or if_thumb32 or if_armv4t
   ),
   (
     opcode  : A_BL;
     ops     : 1;
-    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#11;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_BL;
     ops     : 1;
-    optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#11;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#71#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #40#250;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #40#250;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #3#1#47#255#48;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BKPT;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#190#0;
+    flags   : if_thumb or if_armv5t
+  ),
+  (
+    opcode  : A_BKPT;
+    ops     : 1;
+    optypes : (ot_immediate,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #49#1#32#112;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BKPT;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #49#1#32#112;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#71#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_BX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #3#1#47#255#16;
+    flags   : if_arm32 or if_armv4t
+  ),
+  (
+    opcode  : A_CDP;
+    ops     : 2;
+    optypes : (ot_reg8,ot_reg8,ot_none,ot_none,ot_none,ot_none);
+    code    : #192#1#16#65;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#66#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#16#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#1#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#66#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#69#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#40#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#176#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#176#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#176#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#3#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#144;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CMF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#144;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CMFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#192;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CMFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#192;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_STF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #160#12#0#1#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LDF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #160#12#16#1#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediate or ot_bits32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#16#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#16#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CLZ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#176#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CLZ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#1#111#15#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CPS;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#129#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CPS;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#2#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #108#182#112;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#134#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#135#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#12#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#14#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #108#182#96;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#132#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#133#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#8#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#10#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#2#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #209#192#1#17#65;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#200;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#200;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#16#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#16#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#129;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#129;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#16#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#112;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#112;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#92#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#120#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#16#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#80;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#88#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#104#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam5,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#152#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#72#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#80#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#90#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#136#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#48#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#16#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#86#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#16#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#16#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #35#80#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #36#80#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #37#16#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#94#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#48#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#16#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#80#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#48;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MCR;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#14#0#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MCR;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#14#0#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MCR2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#254#0#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MCR2;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#254#0#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MRC;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#14#16#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MRC;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#14#16#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MRC2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#254#16#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MRC2;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#254#16#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MCRR;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#12#64#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_MCRR2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#252#64#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_MRRC;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#12#80#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_MRRC2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#252#80#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_MLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#0#32#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#70#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#32#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_shifterop,ot_none,ot_none,ot_none,ot_none);
+    code    : #8#1#160;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #10#1#160;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #11#1#160;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #150#243#239#128#0;
+    flags   : if_thumb32 or if_armv6
+  ),
+  (
+    opcode  : A_MRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #16#1#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #150#243#128#128#0;
+    flags   : if_thumb32 or if_armv6
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #18#1#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #19#3#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regs,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #19#3#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#67#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+    code    : #100#67#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#251#0#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#0#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #20#0#0#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MVF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#1;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_MVF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#1;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#67#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#111#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#111#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #8#1#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #10#1#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #11#1#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#176#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#176#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#16#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#0#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#16#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#0#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_vreg,ot_none,ot_none);
+    code    : #144#236#80#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_vreg,ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #144#236#64#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_vreg,ot_none,ot_none);
+    code    : #64#12#80#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_vreg,ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #64#12#64#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #144#236#80#11#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #144#236#64#11#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #64#12#80#11#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #64#12#64#11#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_NOP;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#191#0;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_NOP;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#0;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_NOP;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#225#160#0#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#67#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#1#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #5#1#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#1#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#3#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediatezero,ot_none,ot_none,ot_none);
+    code    : #107#66#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#192#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#192#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #6#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #5#0#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#2#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #5#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate,ot_none,ot_none);
+    code    : #6#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#2#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediate or ot_bits32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#0#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#0#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SIN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#17;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SIN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#17;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#224#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#192#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#80#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#96#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam5,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#144#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#64#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#84#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#112#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#0#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#0#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#82#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#128#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#32#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#0#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#64#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#176#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #100#176#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#26#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+    code    : #96#26#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#30#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#30#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediate or ot_bits8,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#56#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#56#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #4#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #4#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SWP;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #39#16#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SWPB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #39#20#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#144#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#144#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#144#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #13#1#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#3#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#66#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#16#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #13#1#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#3#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#224#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#160#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#160#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#128#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_WFS;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#2;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LDRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #137#232#80#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #25#0#0#0#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_PLD;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #135#248#16#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PLD;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #37#245#80#240#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_PLDW;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #135#248#48#240#0;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_PLDW;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #37#245#16#240#0;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_QADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#0#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_QDADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#144;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QDADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#64#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_QDSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#176;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QDSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#96#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_QSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#160;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#32#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLABB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLABT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#12;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLATB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#10;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLATT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#14;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALBB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALBT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#12;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALTB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#10;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALTT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#14;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLAWB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#48#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAWB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#32#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLAWT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#48#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAWT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#32#12;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPOP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#189#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPOP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#189#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#237#45#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#13#45#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_SMULBB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#8#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULBT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#12#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#10#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULTT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#14#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULWB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #20#1#32#160;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULWT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #20#1#32#224;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_STRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #137#232#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #25#0#0#0#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#48#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #25#0#48#0#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#32#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#32#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #30#0#32#0#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#16#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #30#0#48#0#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#48#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #30#0#48#0#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_FSTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #132#243#111#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #132#243#111#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #45#7#192#0#31;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #45#7#192#0#31;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #132#243#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none);
+    code    : #132#243#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #45#7#192#0#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none);
+    code    : #45#7#192#0#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CLREX;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#47;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_CLREX;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#245#127#240#31;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_LDREX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #138#232#80#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDREX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #24#1#144#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDREXB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #138#232#208#15#79;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_LDREXB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #24#1#208#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDREXD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #138#232#208#0#127;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_LDREXD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#176#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDREXH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #138#232#208#15#95;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_LDREXH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #24#1#240#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #139#232#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STREX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#128#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREXB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #139#232#192#15#64;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_STREXB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#192#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREXD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none);
+    code    : #139#232#192#0#112;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_STREXD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none);
+    code    : #24#1#160#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREXH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #139#232#192#15#80;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_STREXH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#224#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#0#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#0#96#9;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#192#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#192#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#128#5;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PLI;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #135#249#16#240#0;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_PLI;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #37#244#80#240#0;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_QADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_RBIT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#160;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RBIT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#255#15#48;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_REV;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#186#0;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_REV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_REV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#191#15#48;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_REV16;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#186#64;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_REV16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#144;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_REV16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#191#15#176;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_REVSH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#186#192;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_REVSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#176;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_REVSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#255#15#176;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#72#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#64#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#80#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #132#243#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #45#7#160#0#80;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SEL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SEL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#251;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SETEND;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #43#241#1#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SEV;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#64;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_SEV;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#4;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#1#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#1#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#32;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#32;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#64#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#64#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#80;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#8#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#8#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#16;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#16;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#32#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#32#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#48;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#48;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#48;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#112;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#79#0#48;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UMAAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#224#0#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UMAAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#64#9;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMLAD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#0#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMLALD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#192#0#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLALD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#7#64#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SMLSD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLSD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#0#5;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMLSLD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#208#0#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLSLD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#7#64#5;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMMLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#80#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMMLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#80#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMMLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMMLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#80#13;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMMUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#80#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMMUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#80#1#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMUAD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#32#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMUAD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#0#1#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMUSD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#64#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMUSD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#0#5#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #131#243#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#160#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #42#6#160#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#160#15#48;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#160#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#160#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#32#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#32#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#128#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#0#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#0#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#176#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#176#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #132#243#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #45#7#224#0#80;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#80#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#80#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#224#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#224#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#48#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#48#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#192#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#192#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#16#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#16#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#240#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#240#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#64;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#79#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#79#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#175#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#175#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#47#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#47#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#143#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#143#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#0;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#15#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#15#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#191#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#191#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#192;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#95#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#95#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#239#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#239#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#63#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#63#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#207#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#207#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#128;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#31#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#31#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#255#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#255#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#112#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#128#1#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USADA8;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#112#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USADA8;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #131#243#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#224#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #42#6#224#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#160#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#224#15#48;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_WFE;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#32;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_WFE;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#2;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_WFI;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#48;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_WFI;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#3;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_YIELD;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#16;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_YIELD;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#1;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_FABSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#176#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FABSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#176#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FABSS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#176#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FABSS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#176#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPED;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPED;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPES;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPES;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#176#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#176#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#176#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#176#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#183#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#183#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#183#11#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#183#11#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#128#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#128#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#128#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#128#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#16#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#16#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#0#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#0#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSTAT;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#238#241#250#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSTAT;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#14#241#250#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMXR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#224#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMXR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#224#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#11#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#11#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#189#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#189#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#189#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#189#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#188#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#188#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#188#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#188#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_POP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#188;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_POP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#139;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_PUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#180;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_PUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#144#240#240;
+    flags   : if_thumb32 or if_armv7r or if_armv7m
+  ),
+  (
+    opcode  : A_SDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#16#1#15;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_UDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#176#240#240;
+    flags   : if_thumb32 or if_armv7r or if_armv7m
+  ),
+  (
+    opcode  : A_UDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#48#1#15;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#64;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#64;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_IT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#8#0;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_IT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#4#136;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#4#8;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#204;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#76;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#140;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#12;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITEEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#238;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITEEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#110;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITETE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#174;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITETE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#46;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITEET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#206;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITEET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#78;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITETT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#142;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITETT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#14;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TBB;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #142#232#208#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TBH;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #142#232#208#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#0;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#0;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CBZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#177;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_CBZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#177;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_CBNZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#185;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_CBNZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#185;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_VABS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#176#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VABS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#176#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VADD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VADD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #147#238#184#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #147#238#186#10#64;
+    flags   : if_thumb32 or if_vfpv3
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #67#14#186#10#64;
+    flags   : if_arm32 or if_vfpv3
+  ),
+  (
+    opcode  : A_VCVTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #147#238#184#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VDIV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#128#10#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VDIV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#128#10#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#224#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#224#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMLA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#0;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_BLX;
-    ops     : 1;
-    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
-    code    : #15#15;
-    flags   : if_arm7
+    opcode  : A_VMLA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#0;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_BLX;
-    ops     : 1;
-    optypes : (ot_immediate24,ot_none,ot_none,ot_none);
-    code    : #15#15;
-    flags   : if_arm7
+    opcode  : A_VMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_BX;
-    ops     : 1;
-    optypes : (ot_reg32,ot_none,ot_none,ot_none);
-    code    : #3#1#47#255#16;
-    flags   : if_arm7
+    opcode  : A_VMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CDP;
-    ops     : 2;
-    optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
-    code    : #192#1#16#65;
-    flags   : if_arm7
+    opcode  : A_VMUL;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#0;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#96;
-    flags   : if_arm7
+    opcode  : A_VMUL;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#0;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
+    opcode  : A_VNMLA;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#96;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
+    opcode  : A_VNMLA;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#96;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#96;
-    flags   : if_arm7
+    opcode  : A_VNMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#0;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#64;
-    flags   : if_arm7
+    opcode  : A_VNMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#0;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
+    opcode  : A_VNMUL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#64;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
+    opcode  : A_VNMUL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#64;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#64;
-    flags   : if_arm7
+    opcode  : A_VFMA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#160#10#0;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_CLZ;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #39#1#1;
-    flags   : if_arm7
+    opcode  : A_VFMA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#160#10#0;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
+    opcode  : A_VFMS;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#32;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#160#10#64;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#32;
-    flags   : if_arm7
+    opcode  : A_VFMS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#160#10#64;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#32;
-    flags   : if_arm7
+    opcode  : A_VFNMA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#144#10#64;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
+    opcode  : A_VFNMA;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#32;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#144#10#64;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_LDC;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #209#192#1#17#65;
-    flags   : if_arm7
+    opcode  : A_VFNMS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#144#10#0;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_LDM;
-    ops     : 2;
-    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
-    code    : #38#129;
-    flags   : if_arm7
+    opcode  : A_VFNMS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#144#10#0;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_LDRB;
+    opcode  : A_VNEG;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#7#16;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_LDR;
+    opcode  : A_VNEG;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#5#16;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSQRT;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#192;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSQRT;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#192;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSUB;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSUB;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#208;
-    flags   : if_arm7
+    opcode  : A_DMB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#80;
+    flags   : if_thumb32 or if_armv7
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#208;
-    flags   : if_arm7
+    opcode  : A_DMB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#245#127#240#80;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#208;
-    flags   : if_arm7
+    opcode  : A_ISB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#96;
+    flags   : if_thumb32 or if_armv7
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#208;
-    flags   : if_arm7
+    opcode  : A_ISB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#245#127#240#96;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#240;
-    flags   : if_arm7
+    opcode  : A_DSB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#64;
+    flags   : if_thumb32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#240;
-    flags   : if_arm7
+    opcode  : A_DSB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#245#127#240#64;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#240;
-    flags   : if_arm7
+    opcode  : A_SMC;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#1#96#0#112;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#240;
-    flags   : if_arm7
+    opcode  : A_SMC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#1#96#0#112;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LFM;
-    ops     : 3;
-    optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
-    code    : #240#2#1;
-    flags   : if_fpa
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#223#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
-    opcode  : A_MLA;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #21#0#32#144;
-    flags   : if_arm7
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#223#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
-    opcode  : A_MRS;
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BXJ;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#192#143#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BXJ;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #3#1#47#255#32;
+    flags   : if_arm32 or if_armv5tej
+  ),
+  (
+    opcode  : A_UDF;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#222#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_UDF;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #0;
+    flags   : if_arm32 or if_armv4t
+  ),
+  (
+    opcode  : A_TAN;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #16#1#15;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#21;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MSR;
+    opcode  : A_TAN;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #17#1#41#240;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#21;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MSR;
+    opcode  : A_SQT;
     ops     : 2;
-    optypes : (ot_regf,ot_reg32,ot_none,ot_none);
-    code    : #18#1#40#240;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#9;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MSR;
+    opcode  : A_SQT;
     ops     : 2;
-    optypes : (ot_regf,ot_immediate,ot_none,ot_none);
-    code    : #19#3#40#240;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#9;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MUL;
+    opcode  : A_SUF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #20#0#0#144;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#4;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MVF;
-    ops     : 2;
-    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none);
-    code    : #242;
-    flags   : if_fpa
+    opcode  : A_SUF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#4;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MVF;
-    ops     : 2;
-    optypes : (ot_fpureg,ot_immediatefpu,ot_none,ot_none);
-    code    : #242;
-    flags   : if_fpa
+    opcode  : A_RSF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#6;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
+    opcode  : A_RSF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#1#128;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#6;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#1#128;
-    flags   : if_arm7
+    opcode  : A_RND;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#7;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#1#128;
-    flags   : if_arm7
+    opcode  : A_RND;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#7;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
+    opcode  : A_POL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#3#128;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#24;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
+    opcode  : A_POL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#96;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#24;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#96;
-    flags   : if_arm7
+    opcode  : A_RDF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#10;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#96;
-    flags   : if_arm7
+    opcode  : A_RDF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#10;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#96;
-    flags   : if_arm7
+    opcode  : A_RFS;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#3;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#224;
-    flags   : if_arm7
+    opcode  : A_RFC;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#5;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#224;
-    flags   : if_arm7
+    opcode  : A_WFC;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#4;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#224;
-    flags   : if_arm7
+    opcode  : A_RMF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#16;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
+    opcode  : A_RMF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#224;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#16;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
+    opcode  : A_RPW;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#192;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#12;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#192;
-    flags   : if_arm7
+    opcode  : A_RPW;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#12;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#192;
-    flags   : if_arm7
+    opcode  : A_MNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#3;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
+    opcode  : A_MNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#3;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_MUF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#192;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#2;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SFM;
+    opcode  : A_MUF;
     ops     : 3;
-    optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
-    code    : #240#2#0;
-    flags   : if_fpa
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#2;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SMLAL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#224#144;
-    flags   : if_arm7
+    opcode  : A_ABS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#5;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SMULL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#192#144;
-    flags   : if_arm7
+    opcode  : A_ABS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#5;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STM;
+    opcode  : A_ACS;
     ops     : 2;
-    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
-    code    : #38#128;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#25;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STR;
+    opcode  : A_ACS;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#4#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#25;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRB;
+    opcode  : A_ASN;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#6#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#23;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
+    opcode  : A_ASN;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#64#176;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#23;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
+    opcode  : A_ATN;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#64#176;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#27;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#64#176;
-    flags   : if_arm7
+    opcode  : A_ATN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#27;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#0#176;
-    flags   : if_arm7
+    opcode  : A_CNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#176;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SUB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
-    code    : #4#0#64;
-    flags   : if_arm7
+    opcode  : A_CNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#176;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SUB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
-    code    : #4#0#64;
-    flags   : if_arm7
+    opcode  : A_CNFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#240;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SUB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#64;
-    flags   : if_arm7
+    opcode  : A_CNFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#240;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SWI;
-    ops     : 1;
-    optypes : (ot_immediate,ot_none,ot_none,ot_none);
-    code    : #2#15;
-    flags   : if_arm7
+    opcode  : A_COS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#19;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SWP;
+    opcode  : A_COS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#19;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_DVF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #39#1#144;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#8;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SWPB;
+    opcode  : A_DVF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #39#1#144;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#8;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_EXP;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#15;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_EXP;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#15;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_FDV;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#20;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_FDV;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#20;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_FLT;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#0;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FIX;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#0;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#16;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FML;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#18;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FML;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#18;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FRD;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#22;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_FRD;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#22;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LGN;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#13;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_UMLAL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#160#144;
-    flags   : if_arm7
+    opcode  : A_LGN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#13;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_UMULL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#128#144;
-    flags   : if_arm7
+    opcode  : A_LOG;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#11;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LOG;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#11;
+    flags   : if_arm32 or if_fpa
   )
 );

File diff suppressed because it is too large
+ 281 - 293
compiler/arm/cgcpu.pas


+ 44 - 13
compiler/arm/cpubase.pas

@@ -93,7 +93,7 @@ unit cpubase;
       first_mm_imreg     = $30;
 
 { TODO: Calculate bsstart}
-      regnumber_count_bsstart = 64;
+      regnumber_count_bsstart = 128;
 
       regnumber_table : array[tregisterindex] of tregister = (
         {$i rarmnum.inc}
@@ -109,7 +109,7 @@ unit cpubase;
       { registers which may be destroyed by calls }
       VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R14];
       VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
-      VOLATILE_MMREGISTERS =  [RS_D0..RS_D7,RS_D16..RS_D31,RS_S1..RS_S15];
+      VOLATILE_MMREGISTERS =  [RS_D0..RS_D7,RS_D16..RS_D31];
 
       VOLATILE_INTREGISTERS_DARWIN = [RS_R0..RS_R3,RS_R9,RS_R12..RS_R14];
 
@@ -130,6 +130,10 @@ unit cpubase;
         PF_S,
         { floating point size }
         PF_D,PF_E,PF_P,PF_EP,
+        { exchange }
+        PF_X,
+        { rounding }
+        PF_R,
         { load/store }
         PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
         { multiple load/store address modes }
@@ -138,10 +142,18 @@ unit cpubase;
         PF_IAD,PF_DBD,PF_FDD,PF_EAD,
         PF_IAS,PF_DBS,PF_FDS,PF_EAS,
         PF_IAX,PF_DBX,PF_FDX,PF_EAX,
-        { FPv4 postfixes }
-        PF_32,PF_64,PF_F32,PF_F64,
-        PF_F32S32,PF_F32U32,
-        PF_S32F32,PF_U32F32
+        { VFP postfixes }
+        PF_8,PF_16,PF_32,PF_64,
+        PF_I8,PF_I16,PF_I32,PF_I64,
+        PF_S8,PF_S16,PF_S32,PF_S64,
+        PF_U8,PF_U16,PF_U32,PF_U64,
+        PF_P8, // polynomial
+        PF_F32,PF_F64,
+        PF_F32F64,PF_F64F32,
+        PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32,
+        PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64,
+        PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32,
+        PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64
       );
 
       TOpPostfixes = set of TOpPostfix;
@@ -157,14 +169,24 @@ unit cpubase;
       oppostfix2str : array[TOpPostfix] of string[8] = ('',
         's',
         'd','e','p','ep',
+        'x',
+        'r',
         'b','sb','bt','h','sh','t',
         'ia','ib','da','db','fd','fa','ed','ea',
         'iad','dbd','fdd','ead',
         'ias','dbs','fds','eas',
         'iax','dbx','fdx','eax',
-        '.32','.64','.f32','.f64',
-        '.f32.s32','.f32.u32',
-        '.s32.f32','.u32.f32');
+        '.8','.16','.32','.64',
+        '.i8','.i16','.i32','.i64',
+        '.s8','.s16','.s32','.s64',
+        '.u8','.u16','.u32','.u64',
+        '.p8',
+        '.f32','.f64',
+        '.f32.f64','.f64.f32',
+        '.f32.s16','.f32.u16','.s16.f32','.u16.f32',
+        '.f64.s16','.f64.u16','.s16.f64','.u16.f64',
+        '.f32.s32','.f32.u32','.s32.f32','.u32.f32',
+        '.f64.s32','.f64.u32','.s32.f64','.u32.f64');
 
       roundingmode2str : array[TRoundingMode] of string[1] = ('',
         'p','m','z');
@@ -569,7 +591,6 @@ unit cpubase;
       var
         t : aint;
         i : longint;
-        imm : byte;
       begin
         {Loading 0-255 is simple}
         if (d and $FF) = d then
@@ -584,10 +605,20 @@ unit cpubase;
                 ) then
           result:=true
         {Can an 8-bit value be shifted accordingly?}
-        else if is_shifter_const(d,imm) then
-          result:=true
         else
-          result:=false;
+          begin
+            result:=false;
+            for i:=8 to 31 do
+              begin
+                t:=RolDWord(d,i);
+                if ((t and $FF)=t) and
+                   ((t and $80)=$80) then
+                  begin
+                    result:=true;
+                    exit;
+                  end;
+              end;
+          end;
       end;
     
     function is_continuous_mask(d : aint;var lsb, width: byte) : boolean;

+ 81 - 1
compiler/arm/cpuelf.pas

@@ -325,8 +325,19 @@ implementation
           result:=R_ARM_ABS32;
         RELOC_RELATIVE:
           result:=R_ARM_REL32;
+        RELOC_RELATIVE_24:
+          result:=R_ARM_JUMP24;
+        RELOC_RELATIVE_CALL:
+          result:=R_ARM_CALL;
+        RELOC_RELATIVE_24_THUMB:
+          result:=R_ARM_CALL;
+        RELOC_RELATIVE_CALL_THUMB:
+          result:=R_ARM_THM_CALL;
+        RELOC_GOT32:
+          result:=R_ARM_GOT_BREL;
       else
         result:=0;
+        writeln(objrel.typ);
         InternalError(2012110602);
       end;
     end;
@@ -561,6 +572,7 @@ implementation
     rotation:longint;
     residual,g_n:longword;
     curloc: aword;
+    bit_S,bit_I1,bit_I2: aint;
   begin
     data:=objsec.data;
     for i:=0 to objsec.ObjRelocations.Count-1 do
@@ -660,7 +672,21 @@ implementation
                   2) when target is unresolved weak symbol, CALL must be changed to NOP,
                   while JUMP24 behavior is unspecified. }
                 tmp:=sarlongint((address and $00FFFFFF) shl 8,6);
-                tmp:=tmp+relocval-curloc;
+                tmp:=tmp+relocval;
+                if odd(tmp) then    { dest is Thumb? }
+                  begin
+                    if (reltyp=R_ARM_CALL) then
+                      { change BL to BLX, dest bit 1 goes to instruction bit 24 }
+                      address:=(address and $FE000000) or (((tmp-curloc) and 2) shl 23) or $F0000000
+                    else
+                      InternalError(2014092001);
+                  end
+                else if (address and $FF000000)=$FA000000 then
+                  begin
+                    { Change BLX to BL }
+                    address:=(address and $EA000000) or $01000000;
+                  end;
+                tmp:=tmp-curloc;
                 // TODO: check overflow
                 address:=(address and $FF000000) or ((tmp and $3FFFFFE) shr 2);
               end;
@@ -829,6 +855,38 @@ implementation
                   address:=address or (1 shl 23);
               end;
 
+            R_ARM_THM_CALL:
+              begin
+                if (not ElfTarget.relocs_use_addend) then
+                  begin
+                    address:=((address and $ffff) shl 16) or word(address shr 16);
+                    bit_S:=(address shr 26) and 1;
+                    bit_I1:=(bit_S xor ((address shr 13) and 1)) xor 1;
+                    bit_I2:=(bit_S xor ((address shr 11) and 1)) xor 1;
+                    tmp:=((-bit_S) shl 24) or (bit_I1 shl 23) or (bit_I2 shl 22) or (((address shr 16) and $3ff) shl 12) or ((address and $7ff) shl 1);
+                  end
+                else  { TODO: must read the instruction anyway }
+                  tmp:=address;
+                tmp:=tmp+relocval;       { dest address }
+                if odd(tmp) then         { if it's Thumb code, change possible BLX to BL }
+                  address:=address or $1800;
+                tmp:=tmp-curloc;         { now take PC-relative }
+                { TODO: overflow check, different limit for Thumb and Thumb-2 }
+
+                { now encode this mess back }
+                if (address and $5000)=$4000 then
+                  tmp:=(tmp+2) and (not 3);
+
+                bit_S:=(tmp shr 31) and 1;
+                address:=(address and $F800D000) or
+                  (bit_S shl 26) or
+                  (((tmp shr 12) and $3ff) shl 16) or
+                  ((tmp shr 1) and $7FF) or
+                  ((((tmp shr 23) and 1) xor 1 xor bit_S) shl 13) or
+                  ((((tmp shr 22) and 1) xor 1 xor bit_S) shl 11);
+                address:=((address and $ffff) shl 16) or word(address shr 16);
+              end;
+
             R_ARM_TLS_IE32:
               begin
                 relocval:=relocval-tlsseg.mempos+align_aword(TCB_SIZE,tlsseg.align);
@@ -860,6 +918,11 @@ implementation
     end;
 
 
+  function elf_arm_encodeflags: longword;
+    begin
+      result:=EF_ARM_EABI_VER5;
+    end;
+
 {*****************************************************************************
                                     Initialize
 *****************************************************************************}
@@ -882,9 +945,26 @@ implementation
         encodereloc:       @elf_arm_encodeReloc;
         loadreloc:         @elf_arm_loadReloc;
         loadsection:       @elf_arm_loadSection;
+        encodeflags:       @elf_arm_encodeflags;
       );
 
+    as_arm_elf32_info : tasminfo =
+       (
+         id     : as_arm_elf32;
+         idtxt  : 'ELF';
+         asmbin : '';
+         asmcmd : '';
+         supported_targets : [system_arm_embedded,system_arm_darwin,
+                              system_arm_linux,system_arm_gba,
+                              system_arm_nds];
+         flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf];
+         labelprefix : '.L';
+         comment : '';
+         dollarsign: '$';
+       );
+
 initialization
+  RegisterAssembler(as_arm_elf32_info,TElfAssembler);
   ElfTarget:=elf_target_arm;
   ElfExeOutputClass:=TElfExeOutputARM;
 

+ 575 - 241
compiler/arm/cpuinfo.pas

@@ -21,6 +21,9 @@ Interface
 
 Type
    bestreal = double;
+{$if FPC_FULLVERSION>20700}
+   bestrealrec = TDoubleRec;
+{$endif FPC_FULLVERSION>20700}
    ts32real = single;
    ts64real = double;
    ts80real = type extended;
@@ -64,7 +67,8 @@ Type
       fpu_vfpv2,
       fpu_vfpv3,
       fpu_vfpv3_d16,
-      fpu_fpv4_s16
+      fpu_fpv4_s16,
+      fpu_vfpv4
      );
 
    tcontrollertype =
@@ -182,6 +186,28 @@ Type
       ct_at91sam7xc256,
 
       { STMicroelectronics }
+      ct_stm32f030c6,
+      ct_stm32f030c8,
+      ct_stm32f030f4,
+      ct_stm32f030k6,
+      ct_stm32f030r8,
+      ct_stm32f050c4,
+      ct_stm32f050c6,
+      ct_stm32f050f4,
+      ct_stm32f050f6,
+      ct_stm32f050g4,
+      ct_stm32f050g6,
+      ct_stm32f050k4,
+      ct_stm32f050k6,
+      ct_stm32f051c4,
+      ct_stm32f051c6,
+      ct_stm32f051c8,
+      ct_stm32f051k4,
+      ct_stm32f051k6,
+      ct_stm32f051k8,
+      ct_stm32f051r4,
+      ct_stm32f051r6,
+      ct_stm32f051r8,
       ct_stm32f100x4, // LD&MD value line, 4=16,6=32,8=64,b=128
       ct_stm32f100x6,
       ct_stm32f100x8,
@@ -214,6 +240,78 @@ Type
       ct_stm32f107x8, // MD and HD connectivity line, 8=64,B=128,C=256
       ct_stm32f107xB,
       ct_stm32f107xC,
+      ct_stm32f105r8,
+      ct_stm32f105rb,
+      ct_stm32f105rc,
+      ct_stm32f105v8,
+      ct_stm32f105vb,
+      ct_stm32f105vc,
+      ct_stm32f107rb,
+      ct_stm32f107rc,
+      ct_stm32f107vb,
+      ct_stm32f107vc,
+      
+      ct_stm32f401cb,
+      ct_stm32f401rb,
+      ct_stm32f401vb,
+      ct_stm32f401cc,
+      ct_stm32f401rc,
+      ct_stm32f401vc,
+      ct_discoveryf401vc,
+      ct_stm32f401cd,
+      ct_stm32f401rd,
+      ct_stm32f401vd,
+      ct_stm32f401ce,
+      ct_stm32f401re,
+      ct_nucleof401re,
+      ct_stm32f401ve,
+      ct_stm32f407vg,
+      ct_discoveryf407vg,
+      ct_stm32f407ig,
+      ct_stm32f407zg,
+      ct_stm32f407ve,
+      ct_stm32f407ze,
+      ct_stm32f407ie,
+      ct_stm32f411cc,
+      ct_stm32f411rc,
+      ct_stm32f411vc,
+      ct_stm32f411ce,
+      ct_stm32f411re,
+      ct_nucleof411re,
+      ct_stm32f411ve,
+      ct_discoveryf411ve,
+      ct_stm32f429vg,
+      ct_stm32f429zg,
+      ct_stm32f429ig,
+      ct_stm32f429vi,
+      ct_stm32f429zi,
+      ct_discoveryf429zi,
+      ct_stm32f429ii,
+      ct_stm32f429ve,
+      ct_stm32f429ze,
+      ct_stm32f429ie,
+      ct_stm32f429bg,
+      ct_stm32f429bi,
+      ct_stm32f429be,
+      ct_stm32f429ng,
+      ct_stm32f429ni,
+      ct_stm32f429ne,
+      ct_stm32f446mc,
+      ct_stm32f446rc,
+      ct_stm32f446vc,
+      ct_stm32f446zc,
+      ct_stm32f446me,
+      ct_stm32f446re,
+      ct_nucleof446re,
+      ct_stm32f446ve,
+      ct_stm32f446ze,
+
+      ct_stm32f745xe,
+      ct_stm32f745xg,
+      ct_stm32f746xe,
+      ct_stm32f746xg,
+      ct_stm32f756xe,
+      ct_stm32f756xg,
 
       { TI - Fury Class - 64 K Flash, 16 K SRAM Devices }
       ct_lm3s1110,
@@ -302,12 +400,83 @@ Type
       ct_xmc4502x768,
       ct_xmc4504x512,
 
+      { Allwinner }
+      ct_allwinner_a20,
+
+      { Freescale }
+      ct_mk20dx128vfm5,
+      ct_mk20dx128vft5,
+      ct_mk20dx128vlf5,
+      ct_mk20dx128vlh5,
+      ct_teensy30,
+      ct_mk20dx128vmp5,
+
+      ct_mk20dx32vfm5,
+      ct_mk20dx32vft5,
+      ct_mk20dx32vlf5,
+      ct_mk20dx32vlh5,
+      ct_mk20dx32vmp5,
+
+      ct_mk20dx64vfm5,
+      ct_mk20dx64vft5,
+      ct_mk20dx64vlf5,
+      ct_mk20dx64vlh5,
+      ct_mk20dx64vmp5,
+
+      ct_mk20dx128vlh7,
+      ct_mk20dx128vlk7,
+      ct_mk20dx128vll7,
+      ct_mk20dx128vmc7,
+
+      ct_mk20dx256vlh7,
+      ct_mk20dx256vlk7,
+      ct_mk20dx256vll7,
+      ct_mk20dx256vmc7,
+      ct_teensy31,
+      ct_teensy32,
+
+      ct_mk20dx64vlh7,
+      ct_mk20dx64vlk7,
+      ct_mk20dx64vmc7,
+
+      ct_mk22fn512cap12,
+      ct_mk22fn512cbp12,
+      ct_mk22fn512vdc12,
+      ct_mk22fn512vlh12,
+      ct_mk22fn512vll12,
+      ct_mk22fn512vmp12,
+      ct_freedom_k22f,
+
+      ct_mk64fn1m0vdc12,
+      ct_mk64fn1m0vll12,
+      ct_freedom_k64f,
+      ct_mk64fn1m0vlq12,
+      ct_mk64fn1m0vmd12,
+
+      ct_mk64fx512vdc12,
+      ct_mk64fx512vll12,
+      ct_mk64fx512vlq12,
+      ct_mk64fx512vmd12,
+
+      { Atmel }
+      ct_sam3x8e,
+      ct_arduino_due,
+      ct_flip_n_click,
+
       // generic Thumb2 target
       ct_thumb2bare
      );
 
+   tcontrollerdatatype = record
+      controllertypestr, controllerunitstr: string[20];
+      cputype: tcputype; fputype: tfputype;
+      flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize, bootbase, bootsize: dword;
+   end;
 
 Const
+   { Is there support for dealing with multiple microcontrollers available }
+   { for this platform? }
+   ControllerSupport = true;
    {# Size of native extended floating point type }
    extended_size = 12;
    {# Size of a multimedia register               }
@@ -330,7 +499,9 @@ Const
        reference, but that's already done for stdcall) }
      pocall_mwpascal,
      { used for interrupt handling }
-     pocall_interrupt
+     pocall_interrupt,
+     { needed sometimes on android }
+     pocall_hardfloat
    ];
 
    cputypestr : array[tcputype] of string[8] = ('',
@@ -362,7 +533,8 @@ Const
      'VFPV2',
      'VFPV3',
      'VFPV3_D16',
-     'FPV4_S16'
+     'FPV4_S16',
+     'VFPV4'
    );
 
 
@@ -372,269 +544,430 @@ Const
 
    embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
    (
-      (controllertypestr:'';		controllerunitstr:'';	flashbase:0;	flashsize:0;	srambase:0;	sramsize:0),
+      (controllertypestr:'';		controllerunitstr:'';	cputype:cpu_none; fputype:fpu_none; flashbase:0;	flashsize:0;	srambase:0;	sramsize:0),
 
       { LPC 8xx Series}
-      (controllertypestr:'LPC810M021FN8';	controllerunitstr:'LPC8xx';	flashbase:$00000000;	flashsize:$00001000;	srambase:$10000000;	sramsize:$00000400),
-      (controllertypestr:'LPC811M001FDH16';	controllerunitstr:'LPC8xx';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC812M101FDH16';	controllerunitstr:'LPC8xx';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC812M101FD20';	controllerunitstr:'LPC8xx';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC812M101FDH20';	controllerunitstr:'LPC8xx';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC810M021FN8';	  controllerunitstr:'LPC8xx';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00001000;	srambase:$10000000;	sramsize:$00000400),
+      (controllertypestr:'LPC811M001FDH16';	controllerunitstr:'LPC8xx';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC812M101FDH16';	controllerunitstr:'LPC8xx';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC812M101FD20';	controllerunitstr:'LPC8xx';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC812M101FDH20';	controllerunitstr:'LPC8xx';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
 
       { LPC 11xx Series}
-      (controllertypestr:'LPC1110FD20';		controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00001000;	srambase:$10000000;	sramsize:$00000400),
-      (controllertypestr:'LPC1111FDH20/002';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1111FHN33/101';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1111FHN33/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1111FHN33/103';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1111FHN33/201';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1111FHN33/202';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1111FHN33/203';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
-
-      (controllertypestr:'LPC1112FD20/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FDH20/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FDH28/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FHN33/101';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1112FHN33/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1112FHN33/103';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00000800),
-      (controllertypestr:'LPC1112FHN33/201';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FHN24/202';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FHN33/202';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FHN33/203';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FHI33/202';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1112FHI33/203';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-
-      (controllertypestr:'LPC1113FHN33/201';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1113FHN33/202';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1113FHN33/203';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1113FHN33/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1113FHN33/302';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1113FHN33/303';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1113FBD48/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1113FBD48/302';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1113FBD48/303';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
-
-      (controllertypestr:'LPC1114FDH28/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1114FN28/102';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1114FHN33/201';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1114FHN33/202';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1114FHN33/203';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1114FHN33/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FHN33/302';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FHN33/303';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FHN33/333';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$0000E000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FHI33/302';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FHI33/303';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FBD48/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FBD48/302';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FBD48/303';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FBD48/323';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1114FBD48/333';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$0000E000;	srambase:$10000000;	sramsize:$00002000),
-
-      (controllertypestr:'LPC1115FBD48/303';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-
-      (controllertypestr:'LPC11C12FBD48/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC11C14FBD48/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-
-      (controllertypestr:'LPC11C22FBD48/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC11C24FBD48/301';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-
-      (controllertypestr:'LPC11D14FBD100/302';	controllerunitstr:'LPC11XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1110FD20';		    controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00001000;	srambase:$10000000;	sramsize:$00000400),
+      (controllertypestr:'LPC1111FDH20_002';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1111FHN33_101';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1111FHN33_102';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1111FHN33_103';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1111FHN33_201';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1111FHN33_202';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1111FHN33_203';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
+
+      (controllertypestr:'LPC1112FD20_102';	controllerunitstr:'LPC11XX';	  cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FDH20_102';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FDH28_102';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FHN33_101';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1112FHN33_102';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1112FHN33_103';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00000800),
+      (controllertypestr:'LPC1112FHN33_201';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FHN24_202';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FHN33_202';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FHN33_203';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FHI33_202';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1112FHI33_203';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+
+      (controllertypestr:'LPC1113FHN33_201';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1113FHN33_202';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1113FHN33_203';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1113FHN33_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1113FHN33_302';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1113FHN33_303';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1113FBD48_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1113FBD48_302';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1113FBD48_303';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00006000;	srambase:$10000000;	sramsize:$00002000),
+
+      (controllertypestr:'LPC1114FDH28_102';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1114FN28_102';	  controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1114FHN33_201';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1114FHN33_202';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1114FHN33_203';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1114FHN33_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FHN33_302';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FHN33_303';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FHN33_333';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000E000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FHI33_302';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FHI33_303';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FBD48_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FBD48_302';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FBD48_303';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FBD48_323';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1114FBD48_333';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000E000;	srambase:$10000000;	sramsize:$00002000),
+
+      (controllertypestr:'LPC1115FBD48_303';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+
+      (controllertypestr:'LPC11C12FBD48_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC11C14FBD48_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+
+      (controllertypestr:'LPC11C22FBD48_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC11C24FBD48_301';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+
+      (controllertypestr:'LPC11D14FBD100_302';	controllerunitstr:'LPC11XX';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
 
       {LPC 122x Series}
-      (controllertypestr:'LPC1224FBD48/101';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1224FBD48/121';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1224FBD64/101';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1224FBD64/121';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1224FBD48_101';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1224FBD48_121';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1224FBD64_101';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1224FBD64_121';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00001000),
 
-      (controllertypestr:'LPC1225FBD48/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1225FBD48/321';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00014000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1225FBD64/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1225FBD64/321';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00014000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1225FBD48_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1225FBD48_321';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00014000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1225FBD64_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1225FBD64_321';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00014000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1226FBD48/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00018000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1226FBD64/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00018000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1226FBD48_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00018000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1226FBD64_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00018000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1227FBD48/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1227FBD64/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1227FBD48_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1227FBD64_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC12D27FBD100/301';	controllerunitstr:'LPC122X';	flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC12D27FBD100_301';	controllerunitstr:'LPC122X';	cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
 
 
-      (controllertypestr:'LPC1311FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1311FHN33/01';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1311FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1311FHN33_01';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$10000000;	sramsize:$00001000),
 
-      (controllertypestr:'LPC1313FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1313FHN33/01';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1313FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1313FBD48/01';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1313FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1313FHN33_01';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1313FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1313FBD48_01';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1315FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1315FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1315FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1315FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1316FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1316FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1316FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1316FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1317FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1317FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1317FBD64';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1317FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1317FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1317FBD64';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1342FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
-      (controllertypestr:'LPC1342FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1342FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
+      (controllertypestr:'LPC1342FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00004000;	srambase:$10000000;	sramsize:$00001000),
 
-      (controllertypestr:'LPC1343FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1343FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1343FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1343FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1345FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1345FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1345FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1345FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00008000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1346FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1346FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1346FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1346FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$0000C000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC1347FHN33';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1347FBD48';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
-      (controllertypestr:'LPC1347FBD64';	controllerunitstr:'LPC13XX';	flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1347FHN33';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1347FBD48';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1347FBD64';	controllerunitstr:'LPC13XX';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$10000000;	sramsize:$00002000),
 
-      (controllertypestr:'LPC2114';	controllerunitstr:'LPC21x4';	flashbase:$00000000;	flashsize:$00040000;	srambase:$40000000;	sramsize:$00004000),
-      (controllertypestr:'LPC2124';	controllerunitstr:'LPC21x4';	flashbase:$00000000;	flashsize:$00040000;	srambase:$40000000;	sramsize:$00004000),
-      (controllertypestr:'LPC2194';	controllerunitstr:'LPC21x4';	flashbase:$00000000;	flashsize:$00040000;	srambase:$40000000;	sramsize:$00004000),
-      (controllertypestr:'LPC1754';	controllerunitstr:'LPC1754';	flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00004000),
-      (controllertypestr:'LPC1756';	controllerunitstr:'LPC1756';	flashbase:$00000000;	flashsize:$00040000;	srambase:$10000000;	sramsize:$00004000),
-      (controllertypestr:'LPC1758';	controllerunitstr:'LPC1758';	flashbase:$00000000;	flashsize:$00080000;	srambase:$10000000;	sramsize:$00008000),
-      (controllertypestr:'LPC1764';	controllerunitstr:'LPC1764';	flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00004000),
-      (controllertypestr:'LPC1766';	controllerunitstr:'LPC1766';	flashbase:$00000000;	flashsize:$00040000;	srambase:$10000000;	sramsize:$00008000),
-      (controllertypestr:'LPC1768';	controllerunitstr:'LPC1768';	flashbase:$00000000;	flashsize:$00080000;	srambase:$10000000;	sramsize:$00008000),
+      (controllertypestr:'LPC2114';	controllerunitstr:'LPC21x4';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$40000000;	sramsize:$00004000),
+      (controllertypestr:'LPC2124';	controllerunitstr:'LPC21x4';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$40000000;	sramsize:$00004000),
+      (controllertypestr:'LPC2194';	controllerunitstr:'LPC21x4';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$40000000;	sramsize:$00004000),
+      
+      (controllertypestr:'LPC1754';	controllerunitstr:'LPC1754';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00004000),
+      (controllertypestr:'LPC1756';	controllerunitstr:'LPC1756';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$10000000;	sramsize:$00004000),
+      (controllertypestr:'LPC1758';	controllerunitstr:'LPC1758';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00080000;	srambase:$10000000;	sramsize:$00008000),
+      (controllertypestr:'LPC1764';	controllerunitstr:'LPC1764';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00004000),
+      (controllertypestr:'LPC1766';	controllerunitstr:'LPC1766';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$10000000;	sramsize:$00008000),
+      (controllertypestr:'LPC1768';	controllerunitstr:'LPC1768';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00080000;	srambase:$10000000;	sramsize:$00008000),
 
       { AT91 }
-      (controllertypestr:'AT91SAM7S256';	controllerunitstr:'AT91SAM7x256';	flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
-      (controllertypestr:'AT91SAM7SE256';	controllerunitstr:'AT91SAM7x256';	flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
-      (controllertypestr:'AT91SAM7X256';	controllerunitstr:'AT91SAM7x256';	flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
-      (controllertypestr:'AT91SAM7XC256';	controllerunitstr:'AT91SAM7x256';	flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
+      (controllertypestr:'AT91SAM7S256';	controllerunitstr:'AT91SAM7x256';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
+      (controllertypestr:'AT91SAM7SE256';	controllerunitstr:'AT91SAM7x256';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
+      (controllertypestr:'AT91SAM7X256';	controllerunitstr:'AT91SAM7x256';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
+      (controllertypestr:'AT91SAM7XC256';	controllerunitstr:'AT91SAM7x256';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
+
+      { STM32F0 series }
+      (controllertypestr:'STM32F030C6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F030C8';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F030F4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F030K6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F030R8';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F050C4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050C6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050F4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050F6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050G4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050G6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050K4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050K6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051C4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051C6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051C8';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F051K4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051K6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051K8';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F051R4';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051R6';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051R8';     controllerunitstr:'STM32F0XX';        cputype:cpu_armv6m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
 
       { STM32F1 series }
-      (controllertypestr:'STM32F100X4';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
-      (controllertypestr:'STM32F100X6';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
-      (controllertypestr:'STM32F100X8';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
-      (controllertypestr:'STM32F100XB';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00002000),
-      (controllertypestr:'STM32F100XC';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00006000),
-      (controllertypestr:'STM32F100XD';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00008000),
-      (controllertypestr:'STM32F100XE';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00008000),
-      (controllertypestr:'STM32F101X4';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
-      (controllertypestr:'STM32F101X6';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001800),
-      (controllertypestr:'STM32F101X8';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002800),
-      (controllertypestr:'STM32F101XB';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00004000),
-      (controllertypestr:'STM32F101XC';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00008000),
-      (controllertypestr:'STM32F101XD';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$0000C000),
-      (controllertypestr:'STM32F101XE';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$0000C000),
-      (controllertypestr:'STM32F101XF';     controllerunitstr:'STM32F10X_XL';     flashbase:$08000000; flashsize:$000C0000; srambase:$20000000; sramsize:$00014000),
-      (controllertypestr:'STM32F101XG';     controllerunitstr:'STM32F10X_XL';     flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00014000),
-      (controllertypestr:'STM32F102X4';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
-      (controllertypestr:'STM32F102X6';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001800),
-      (controllertypestr:'STM32F102X8';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002800),
-      (controllertypestr:'STM32F102XB';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00004000),
-      (controllertypestr:'STM32F103X4';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
-      (controllertypestr:'STM32F103X6';     controllerunitstr:'STM32F10X_LD';     flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00002800),
-      (controllertypestr:'STM32F103X8';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00005000),
-      (controllertypestr:'STM32F103XB';     controllerunitstr:'STM32F10X_MD';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00005000),
-      (controllertypestr:'STM32F103XC';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$0000C000),
-      (controllertypestr:'STM32F103XD';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00010000),
-      (controllertypestr:'STM32F103XE';     controllerunitstr:'STM32F10X_HD';     flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00010000),
-      (controllertypestr:'STM32F103XF';     controllerunitstr:'STM32F10X_XL';     flashbase:$08000000; flashsize:$000C0000; srambase:$20000000; sramsize:$00018000),
-      (controllertypestr:'STM32F103XG';     controllerunitstr:'STM32F10X_XL';     flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00018000),
-      (controllertypestr:'STM32F107X8';     controllerunitstr:'STM32F10X_CONN';   flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00010000),
-      (controllertypestr:'STM32F107XB';     controllerunitstr:'STM32F10X_CONN';   flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
-      (controllertypestr:'STM32F107XC';     controllerunitstr:'STM32F10X_CONN';   flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
-
-      (controllertypestr:'LM3S1110';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S1133';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S1138';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S1150';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S1162';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S1165';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S1166';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S2110';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S2139';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S6100';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
-      (controllertypestr:'LM3S6110';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'STM32F100X4';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F100X6';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F100X8';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F100XB';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F100XC';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00006000),
+      (controllertypestr:'STM32F100XD';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'STM32F100XE';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'STM32F101X4';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F101X6';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001800),
+      (controllertypestr:'STM32F101X8';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002800),
+      (controllertypestr:'STM32F101XB';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00004000),
+      (controllertypestr:'STM32F101XC';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'STM32F101XD';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$0000C000),
+      (controllertypestr:'STM32F101XE';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$0000C000),
+      (controllertypestr:'STM32F101XF';     controllerunitstr:'STM32F10X_XL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$000C0000; srambase:$20000000; sramsize:$00014000),
+      (controllertypestr:'STM32F101XG';     controllerunitstr:'STM32F10X_XL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00014000),
+      (controllertypestr:'STM32F102X4';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F102X6';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001800),
+      (controllertypestr:'STM32F102X8';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002800),
+      (controllertypestr:'STM32F102XB';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00004000),
+      (controllertypestr:'STM32F103X4';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F103X6';     controllerunitstr:'STM32F10X_LD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00002800),
+      (controllertypestr:'STM32F103X8';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00005000),
+      (controllertypestr:'STM32F103XB';     controllerunitstr:'STM32F10X_MD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00005000),
+      (controllertypestr:'STM32F103XC';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$0000C000),
+      (controllertypestr:'STM32F103XD';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F103XE';     controllerunitstr:'STM32F10X_HD';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F103XF';     controllerunitstr:'STM32F10X_XL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$000C0000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F103XG';     controllerunitstr:'STM32F10X_XL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F107X8';     controllerunitstr:'STM32F10X_CONN';   cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107XB';     controllerunitstr:'STM32F10X_CONN';   cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107XC';     controllerunitstr:'STM32F10X_CONN';   cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+
+      (controllertypestr:'STM32F105R8';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105RB';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105RC';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105V8';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105VB';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105VC';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107RB';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107RC';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107VB';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107VC';     controllerunitstr:'STM32F10X_CL';     cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+    
+      (controllertypestr:'STM32F401CB';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F401RB';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F401VB';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F401CC';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F401RC';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F401VC';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'DISCOVERYF401VC'; controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F401CD';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F401RD';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F401VD';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00060000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F401CE';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F401RE';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'NUCLEOF401RE';    controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F401VE';     controllerunitstr:'STM32F401XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00018000),
+      (controllertypestr:'STM32F407VG';     controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'DISCOVERYF407VG'; controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F407IG';     controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F407ZG';     controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F407VE';     controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F407ZE';     controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F407IE';     controllerunitstr:'STM32F407XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F411CC';     controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F411RC';     controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F411VC';     controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F411CE';     controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F411RE';     controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'NUCLEOF411RE';    controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F411VE';     controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'DISCOVERYF411VE'; controllerunitstr:'STM32F411XE';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F429VG';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429ZG';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429IG';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429VI';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00200000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429ZI';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00200000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'DISCOVERYF429ZI'; controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00200000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429II';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00200000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429VE';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429ZE';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429IE';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429BG';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429BI';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00200000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429BE';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429NG';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429NI';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00200000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F429NE';     controllerunitstr:'STM32F429XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'STM32F446MC';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446RC';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446VC';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446ZC';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446ME';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446RE';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'NUCLEOF446RE';    controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446VE';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'STM32F446ZE';     controllerunitstr:'STM32F446XX';      cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20000000; sramsize:$00020000),
+ 
+      (controllertypestr:'STM32F745XE';     controllerunitstr:'STM32F745';        cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20010000; sramsize:$00040000),
+      (controllertypestr:'STM32F745XG';     controllerunitstr:'STM32F745';        cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20010000; sramsize:$00040000),
+      (controllertypestr:'STM32F746XE';     controllerunitstr:'STM32F746';        cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20010000; sramsize:$00040000),
+      (controllertypestr:'STM32F746XG';     controllerunitstr:'STM32F746';        cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20010000; sramsize:$00040000),
+      (controllertypestr:'STM32F756XE';     controllerunitstr:'STM32F756';        cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00080000; srambase:$20010000; sramsize:$00040000),
+      (controllertypestr:'STM32F756XG';     controllerunitstr:'STM32F756';        cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000; flashsize:$00100000; srambase:$20010000; sramsize:$00040000),
+
+      (controllertypestr:'LM3S1110';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S1133';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S1138';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S1150';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S1162';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S1165';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S1166';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S2110';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S2139';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S6100';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
+      (controllertypestr:'LM3S6110';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00010000;	srambase:$20000000;	sramsize:$00004000),
 
       { TI - 128K Flash, 32K SRAM devices }
-      (controllertypestr:'LM3S1601';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S1608';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S1620';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S1635';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S1636';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S1637';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S1651';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S2601';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S2608';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S2620';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S2637';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S2651';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S6610';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S6611';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S6618';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S6633';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S6637';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
-      (controllertypestr:'LM3S8630';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1601';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1608';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1620';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1635';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1636';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1637';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S1651';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S2601';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S2608';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S2620';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S2637';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S2651';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S6610';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S6611';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S6618';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S6633';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S6637';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM3S8630';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00020000;	srambase:$20000000;	sramsize:$00008000),
 
       { TI - 256K Flash, 64K SRAM devices }
-      (controllertypestr:'LM3S1911';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1918';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1937';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1958';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1960';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1968';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1969';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2911';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2918';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2919';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2939';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2948';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2950';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S2965';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S6911';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S6918';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S6938';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S6950';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S6952';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S6965';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S8930';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S8933';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S8938';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S8962';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S8970';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S8971';	controllerunitstr:'LM3FURY';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1911';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1918';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1937';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1958';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1960';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1968';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1969';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2911';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2918';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2919';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2939';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2948';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2950';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S2965';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S6911';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S6918';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S6938';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S6950';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S6952';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S6965';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S8930';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S8933';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S8938';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S8962';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S8970';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S8971';	controllerunitstr:'LM3FURY';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
 
       { TI - Tempest parts - up to 512 K Flash, 96 K SRAM }
-      (controllertypestr:'LM3S5951';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S5956';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'LM3S1B21';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S2B93';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S5B91';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S9B81';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S9B90';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S9B92';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S9B95';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S9B96';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
-      (controllertypestr:'LM3S5D51';	controllerunitstr:'LM3TEMPEST';	flashbase:$00000000;	flashsize:$00080000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S5951';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S5956';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'LM3S1B21';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S2B93';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S5B91';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S9B81';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S9B90';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S9B92';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S9B95';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S9B96';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00018000),
+      (controllertypestr:'LM3S5D51';	controllerunitstr:'LM3TEMPEST';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00080000;	srambase:$20000000;	sramsize:$00018000),
 
       { TI }
-      (controllertypestr:'LM4F120H5';	controllerunitstr:'LM4F120';	flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00008000),
+      (controllertypestr:'LM4F120H5';	controllerunitstr:'LM4F120';	cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00040000;	srambase:$20000000;	sramsize:$00008000),
 
       { Samsung }
-      (controllertypestr:'SC32442B';	controllerunitstr:'SC32442b';	flashbase:$00000000;	flashsize:$00000000;	srambase:$00000000;	sramsize:$08000000),
+      (controllertypestr:'SC32442B';	controllerunitstr:'SC32442b';	cputype:cpu_armv4t; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00000000;	srambase:$00000000;	sramsize:$08000000),
       
       { Infinion }
-      (controllertypestr:'XMC4500X1024';  controllerunitstr:'XMC4500'; flashbase:$08000000;	flashsize:$00100000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'XMC4500X768';   controllerunitstr:'XMC4500'; flashbase:$08000000;	flashsize:$000C0000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'XMC4502X768';   controllerunitstr:'XMC4502'; flashbase:$08000000;	flashsize:$000C0000;	srambase:$20000000;	sramsize:$00010000),
-      (controllertypestr:'XMC4504X512';   controllerunitstr:'XMC4504'; flashbase:$08000000;	flashsize:$00080000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'XMC4500X1024';  controllerunitstr:'XMC4500'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000;	flashsize:$00100000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'XMC4500X768';   controllerunitstr:'XMC4500'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000;	flashsize:$000C0000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'XMC4502X768';   controllerunitstr:'XMC4502'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000;	flashsize:$000C0000;	srambase:$20000000;	sramsize:$00010000),
+      (controllertypestr:'XMC4504X512';   controllerunitstr:'XMC4504'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$08000000;	flashsize:$00080000;	srambase:$20000000;	sramsize:$00010000),
+
+      { Allwinner }
+      (controllertypestr:'ALLWINNER_A20'; controllerunitstr:'ALLWINNER_A20'; cputype:cpu_armv7a; fputype:fpu_vfpv4; flashbase:$00000000; flashsize:$00000000;  srambase:$40000000; sramsize:$80000000),
+
+      { Freescale }
+      (controllertypestr:'MK20DX128VFM5'; controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX128VFT5'; controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX128VLF5'; controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX128VLH5'; controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'TEENSY30'     ; controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX128VMP5'; controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00002000),
+
+      (controllertypestr:'MK20DX32VFM5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00008000;   srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'MK20DX32VFT5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00008000;   srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'MK20DX32VLF5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00008000;   srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'MK20DX32VLH5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00008000;   srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'MK20DX32VMP5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00008000;   srambase:$20000000; sramsize:$00001000),
+
+      (controllertypestr:'MK20DX64VFM5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX64VFT5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX64VLF5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX64VLH5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX64VMP5';  controllerunitstr:'MK20D5';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+
+      (controllertypestr:'MK20DX128VLH7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00004000),
+      (controllertypestr:'MK20DX128VLK7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00004000),
+      (controllertypestr:'MK20DX128VLL7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00004000),
+      (controllertypestr:'MK20DX128VMC7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00020000;   srambase:$20000000; sramsize:$00004000),
+
+      (controllertypestr:'MK20DX256VLH7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00040000;   srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'MK20DX256VLK7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00040000;   srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'MK20DX256VLL7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00040000;   srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'MK20DX256VMC7'; controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00040000;   srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'TEENSY31';      controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00040000;   srambase:$20000000; sramsize:$00008000),
+      (controllertypestr:'TEENSY32';      controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00040000;   srambase:$20000000; sramsize:$00008000),
+
+      (controllertypestr:'MK20DX64VLH7';  controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX64VLK7';  controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'MK20DX64VMC7';  controllerunitstr:'MK20D7';  cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00010000;   srambase:$20000000; sramsize:$00002000),
+
+      (controllertypestr:'MK22FN512CAP12';controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'MK22FN512CBP12';controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'MK22FN512VDC12';controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'MK22FN512VLH12';controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'MK22FN512VLL12';controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'MK22FN512VMP12';controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'FREEDOM_K22F';  controllerunitstr:'MK22F51212'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;   flashsize:$00080000;   srambase:$20000000; sramsize:$00010000),
+
+      (controllertypestr:'MK64FN1M0VDC12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00100000;   srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'MK64FN1M0VLL12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00100000;   srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'FREEDOM_K64F';  controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00100000;   srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'MK64FN1M0VLQ12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00100000;   srambase:$20000000; sramsize:$00030000),
+      (controllertypestr:'MK64FN1M0VMD12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00100000;   srambase:$20000000; sramsize:$00030000),
+
+      (controllertypestr:'MK64FX512VDC12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00080000;   srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'MK64FX512VLL12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00080000;   srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'MK64FX512VLQ12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00080000;   srambase:$20000000; sramsize:$00020000),
+      (controllertypestr:'MK64FX512VMD12';controllerunitstr:'MK64F12'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000;      flashsize:$00080000;   srambase:$20000000; sramsize:$00020000),
+
+      { Atmel }
+      (controllertypestr:'ATSAM3X8E';     controllerunitstr:'SAM3X8E'; cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00080000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'ARDUINO_DUE';   controllerunitstr:'SAM3X8E'; cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00080000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'FLIP_N_CLICK';  controllerunitstr:'SAM3X8E'; cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00080000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
 
       { Bare bones }
-      (controllertypestr:'THUMB2_BARE';	controllerunitstr:'THUMB2_BARE';	flashbase:$00000000;	flashsize:$00002000;	srambase:$20000000;	sramsize:$00000400)
+      (controllertypestr:'THUMB2_BARE';	controllerunitstr:'THUMB2_BARE';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$20000000;	sramsize:$00000400)
     );
 
-   vfp_scalar = [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16];
+   vfp_scalar = [fpu_vfpv2,fpu_vfpv3,fpu_vfpv4,fpu_vfpv3_d16,fpu_fpv4_s16];
 
    { Supported optimizations, only used for information }
    supported_optimizerswitches = genericlevel1optimizerswitches+
@@ -653,7 +986,8 @@ Const
 
  type
    tcpuflags =
-      (CPUARM_HAS_BX,         { CPU supports the BX instruction                           }
+      (CPUARM_HAS_ALL_MEM,    { CPU supports LDRSB/LDRSH/LDRH/STRH instructions           }
+       CPUARM_HAS_BX,         { CPU supports the BX instruction                           }
        CPUARM_HAS_BLX,        { CPU supports the BLX rX instruction                       }
        CPUARM_HAS_BLX_LABEL,  { CPU supports the BLX <label> instruction                  }
        CPUARM_HAS_CLZ,        { CPU supports the CLZ instruction                          }
@@ -672,23 +1006,23 @@ Const
    cpu_capabilities : array[tcputype] of set of tcpuflags =
      ( { cpu_none     } [],
        { cpu_armv3    } [],
-       { cpu_armv4    } [CPUARM_HAS_UMULL],
-       { cpu_armv4t   } [CPUARM_HAS_BX,CPUARM_HAS_UMULL],
-       { cpu_armv5    } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_UMULL],
-       { cpu_armv5t   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_UMULL],
-       { cpu_armv5te  } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_UMULL],
-       { cpu_armv5tej } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_UMULL],
-       { cpu_armv6    } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX,CPUARM_HAS_UMULL],
-       { cpu_armv6k   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX,CPUARM_HAS_UMULL],
-       { cpu_armv6t2  } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
-       { cpu_armv6z   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX,CPUARM_HAS_UMULL],
-       { cpu_armv6m   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_REV],
+       { cpu_armv4    } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_UMULL],
+       { cpu_armv4t   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_UMULL],
+       { cpu_armv5    } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_CLZ,CPUARM_HAS_UMULL],
+       { cpu_armv5t   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_UMULL],
+       { cpu_armv5te  } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_UMULL],
+       { cpu_armv5tej } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_UMULL],
+       { cpu_armv6    } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX,CPUARM_HAS_UMULL],
+       { cpu_armv6k   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX,CPUARM_HAS_UMULL],
+       { cpu_armv6t2  } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
+       { cpu_armv6z   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX,CPUARM_HAS_UMULL],
+       { cpu_armv6m   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_REV],
        { the identifier armv7 is should not be used, it is considered being equal to armv7a }
-       { cpu_armv7    } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
-       { cpu_armv7a   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
-       { cpu_armv7r   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
-       { cpu_armv7m   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2],
-       { cpu_armv7em  } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2]
+       { cpu_armv7    } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
+       { cpu_armv7a   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
+       { cpu_armv7r   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
+       { cpu_armv7m   } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL],
+       { cpu_armv7em  } [CPUARM_HAS_ALL_MEM,CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_THUMB_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2,CPUARM_HAS_UMULL]
      );
 
    { contains all CPU supporting any kind of thumb instruction set }

+ 28 - 25
compiler/arm/cpupara.pas

@@ -28,17 +28,18 @@ unit cpupara;
 
     uses
        globtype,globals,
+       aasmdata,
        cpuinfo,cpubase,cgbase,cgutils,
        symconst,symtype,symdef,parabase,paramgr;
 
     type
-       tarmparamanager = class(tparamanager)
+       tcpuparamanager = class(tparamanager)
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
-          procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
+          procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; 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; forcetempdef: tdef): tcgpara;override;
@@ -59,7 +60,7 @@ unit cpupara;
        procinfo;
 
 
-    function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+    function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
       begin
         if (target_info.system<>system_arm_darwin) then
           result:=VOLATILE_INTREGISTERS
@@ -68,19 +69,19 @@ unit cpupara;
       end;
 
 
-    function tarmparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+    function tcpuparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
       begin
         result:=VOLATILE_FPUREGISTERS;
       end;
 
 
-    function tarmparamanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
+    function tcpuparamanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
       begin
         result:=VOLATILE_MMREGISTERS;
       end;
 
 
-    procedure tarmparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
+    procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
         paraloc : pcgparalocation;
         psym : tparavarsym;
@@ -91,7 +92,7 @@ unit cpupara;
         psym:=tparavarsym(pd.paras[nr-1]);
         pdef:=psym.vardef;
         if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
-          pdef:=getpointerdef(pdef);
+          pdef:=cpointerdef.getreusable_no_free(pdef);
         cgpara.reset;
         cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
@@ -128,12 +129,12 @@ unit cpupara;
             orddef:
               getparaloc:=LOC_REGISTER;
             floatdef:
-              if (target_info.abi = abi_eabihf) and
+              if ((target_info.abi=abi_eabihf) or (calloption=pocall_hardfloat)) and
                  (not isvariadic) then
                 getparaloc:=LOC_MMREGISTER
               else if (calloption in [pocall_cdecl,pocall_cppdecl,pocall_softfloat]) or
                  (cs_fp_emulation in current_settings.moduleswitches) or
-                 (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
+                 (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv4,fpu_vfpv3_d16,fpu_fpv4_s16]) then
                 { the ARM eabi also allows passing VFP values via VFP registers,
                   but Mac OS X doesn't seem to do that and linux only does it if
                   built with the "-mfloat-abi=hard" option }
@@ -162,7 +163,10 @@ unit cpupara;
             filedef:
               getparaloc:=LOC_REGISTER;
             arraydef:
-              getparaloc:=LOC_REFERENCE;
+              if is_dynamic_array(p) then
+                getparaloc:=LOC_REGISTER
+              else
+                getparaloc:=LOC_REFERENCE;
             setdef:
               if is_smallset(p) then
                 getparaloc:=LOC_REGISTER
@@ -179,7 +183,7 @@ unit cpupara;
       end;
 
 
-    function tarmparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+    function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
       begin
         result:=false;
         if varspez in [vs_var,vs_out,vs_constref] then
@@ -210,11 +214,10 @@ unit cpupara;
       end;
 
 
-    function tarmparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
+    function tcpuparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
       var
         i: longint;
         sym: tsym;
-        fpufield: boolean;
       begin
         if handle_common_ret_in_param(def,pd,result) then
           exit;
@@ -293,7 +296,7 @@ unit cpupara;
       end;
 
 
-    procedure tarmparamanager.init_values(p : tabstractprocdef; side: tcallercallee;
+    procedure tcpuparamanager.init_values(p : tabstractprocdef; side: tcallercallee;
       var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
       begin
         curintreg:=RS_R0;
@@ -308,7 +311,7 @@ unit cpupara;
       end;
 
 
-    function tarmparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+    function tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
         var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
 
       var
@@ -375,7 +378,7 @@ unit cpupara;
 
             if push_addr_param(hp.varspez,paradef,p.proccalloption) then
               begin
-                paradef:=getpointerdef(paradef);
+                paradef:=cpointerdef.getreusable_no_free(paradef);
                 loc:=LOC_REGISTER;
                 paracgsize := OS_ADDR;
                 paralen := tcgsize2size[OS_ADDR];
@@ -469,7 +472,7 @@ unit cpupara;
                             { LOC_REFERENCE always contains everything that's left }
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.size:=int_cgsize(paralen);
-                            paraloc^.def:=getarraydef(u8inttype,paralen);
+                            paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
                             if (side=callerside) then
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                             paraloc^.reference.offset:=stack_offset;
@@ -543,7 +546,7 @@ unit cpupara;
                             { LOC_REFERENCE always contains everything that's left }
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.size:=int_cgsize(paralen);
-                            paraloc^.def:=getarraydef(u8inttype,paralen);
+                            paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
                             if (side=callerside) then
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                             paraloc^.reference.offset:=stack_offset;
@@ -556,7 +559,7 @@ unit cpupara;
                         if push_addr_param(hp.varspez,paradef,p.proccalloption) then
                           begin
                             paraloc^.size:=OS_ADDR;
-                            paraloc^.def:=getpointerdef(paradef);
+                            paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
                             assignintreg
                           end
                         else
@@ -611,7 +614,7 @@ unit cpupara;
       end;
 
 
-    function  tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+    function  tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
       var
         paraloc : pcgparalocation;
         retcgsize  : tcgsize;
@@ -623,7 +626,7 @@ unit cpupara;
         { Return in FPU register? }
         if result.def.typ=floatdef then
           begin
-            if target_info.abi = abi_eabihf then 
+            if (target_info.abi=abi_eabihf) or (p.proccalloption=pocall_hardfloat) then
               begin
                 paraloc^.loc:=LOC_MMREGISTER;
                 case retcgsize of
@@ -645,7 +648,7 @@ unit cpupara;
               end
             else if (p.proccalloption in [pocall_softfloat]) or
                (cs_fp_emulation in current_settings.moduleswitches) or
-               (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
+               (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv4,fpu_vfpv3_d16,fpu_fpv4_s16]) then
               begin
                 case retcgsize of
                   OS_64,
@@ -736,7 +739,7 @@ unit cpupara;
       end;
 
 
-    function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+    function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
       var
         cur_stack_offset: aword;
         curintreg, curfloatreg, curmmreg: tsuperregister;
@@ -750,7 +753,7 @@ unit cpupara;
      end;
 
 
-    function tarmparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+    function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
       var
         cur_stack_offset: aword;
         curintreg, curfloatreg, curmmreg: tsuperregister;
@@ -767,5 +770,5 @@ unit cpupara;
       end;
 
 begin
-   paramanager:=tarmparamanager.create;
+   paramanager:=tcpuparamanager.create;
 end.

+ 1 - 0
compiler/arm/cpupi.pas

@@ -174,6 +174,7 @@ unit cpupi;
                 end;
               fpu_vfpv2,
               fpu_vfpv3,
+              fpu_vfpv4,
               fpu_vfpv3_d16:
                 begin
                   floatsavesize:=0;

+ 228 - 3
compiler/arm/hlcgcpu.pas

@@ -28,18 +28,243 @@ unit hlcgcpu;
 
 interface
 
+  uses
+    aasmdata,
+    symdef,
+    hlcg2ll;
+
+  type
+    tbasehlcgarm = class(thlcg2ll)
+      procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+    end;
+
+    tarmhlcgcpu = class(tbasehlcgarm)
+    end;
+
+    tthumbhlcgcpu = class(tbasehlcgarm)
+      procedure g_external_wrapper(list : TAsmList; procdef : tprocdef; const externalname : string); override;
+    end;
+
   procedure create_hlcodegen;
 
 implementation
 
   uses
-    hlcgobj, hlcg2ll,
-    cgcpu;
+    globals,globtype,verbose,
+    procinfo,fmodule,
+    symconst,
+    aasmbase,aasmtai,aasmcpu, cpuinfo,
+    hlcgobj,
+    cgbase, cgutils, cpubase, cgobj, cgcpu;
+
+  procedure tbasehlcgarm.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+    procedure loadvmttor12;
+      var
+        tmpref,
+        href : treference;
+        l : TAsmLabel;
+      begin
+        reference_reset_base(href,voidpointertype,NR_R0,0,sizeof(pint));
+        if GenerateThumbCode then
+          begin
+            if (href.offset in [0..124]) and ((href.offset mod 4)=0) then
+              begin
+                list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+                cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+              end
+            else
+              begin
+                list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+                { create consts entry }
+                reference_reset(tmpref,4);
+                current_asmdata.getjumplabel(l);
+                current_procinfo.aktlocaldata.Concat(tai_align.Create(4));
+                cg.a_label(current_procinfo.aktlocaldata,l);
+                tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+                current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(href.offset));
+                tmpref.symbol:=l;
+                tmpref.base:=NR_PC;
+                list.concat(taicpu.op_reg_ref(A_LDR,NR_R1,tmpref));
+                href.offset:=0;
+                href.index:=NR_R1;
+                cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+              end;
+          end
+        else
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+      end;
+
+
+    procedure op_onr12methodaddr;
+      var
+        tmpref,
+        href : treference;
+        l : TAsmLabel;
+      begin
+        if (procdef.extnumber=$ffff) then
+          Internalerror(200006139);
+        if GenerateThumbCode then
+          begin
+            reference_reset_base(href,voidpointertype,NR_R0,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+            if (href.offset in [0..124]) and ((href.offset mod 4)=0) then
+              begin
+                list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+                list.concat(taicpu.op_reg_reg(A_MOV,NR_R0,NR_R12));
+                cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+              end
+            else
+              begin
+                list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+                { create consts entry }
+                reference_reset(tmpref,4);
+                current_asmdata.getjumplabel(l);
+                current_procinfo.aktlocaldata.Concat(tai_align.Create(4));
+                cg.a_label(current_procinfo.aktlocaldata,l);
+                tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+                current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(href.offset));
+                tmpref.symbol:=l;
+                tmpref.base:=NR_PC;
+                list.concat(taicpu.op_reg_ref(A_LDR,NR_R1,tmpref));
+                list.concat(taicpu.op_reg_reg(A_MOV,NR_R0,NR_R12));
+                href.offset:=0;
+                href.base:=NR_R0;
+                href.index:=NR_R1;
+                cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R0);
+                list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+                list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0,RS_R1]));
+              end;
+          end
+        else
+          begin
+            reference_reset_base(href,voidpointertype,NR_R12,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+            cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+          end;
+        if not(CPUARM_HAS_BX in cpu_capabilities[current_settings.cputype]) then
+          list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12))
+        else
+          list.concat(taicpu.op_reg(A_BX,NR_R12));
+      end;
+
+    var
+      make_global : boolean;
+      tmpref : treference;
+      l : TAsmLabel;
+    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);
+
+        if GenerateThumbCode or GenerateThumb2Code then
+          list.concat(tai_directive.Create(asd_thumb_func,''));
+
+      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) and
+          not is_objectpascal_helper(procdef.struct) then
+        begin
+          loadvmttor12;
+          op_onr12methodaddr;
+        end
+      { case 0 }
+      else if GenerateThumbCode then
+        begin
+          { bl cannot be used here because it destroys lr }
+
+          list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+
+          { create consts entry }
+          reference_reset(tmpref,4);
+          current_asmdata.getjumplabel(l);
+          current_procinfo.aktlocaldata.Concat(tai_align.Create(4));
+          cg.a_label(current_procinfo.aktlocaldata,l);
+          tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+          current_procinfo.aktlocaldata.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(procdef.mangledname)));
+
+          tmpref.symbol:=l;
+          tmpref.base:=NR_PC;
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_R0);
+          list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+          list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+          list.concat(taicpu.op_reg(A_BX,NR_R12));
+        end
+      else
+        list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+      list.concatlist(current_procinfo.aktlocaldata);
+
+      current_procinfo.Free;
+      current_procinfo:=nil;
+
+      list.concat(Tai_symbol_end.Createname(labelname));
+    end;
+
+
+  { tthumbhlcgcpu }
+
+  procedure tthumbhlcgcpu.g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string);
+    var
+      tmpref : treference;
+      l : tasmlabel;
+    begin
+      { there is no branch instruction on thumb which allows big distances and which leaves LR as it is
+        and which allows to switch the instruction set }
+
+      { create const entry }
+      reference_reset(tmpref,4);
+      current_asmdata.getjumplabel(l);
+      tmpref.symbol:=l;
+      tmpref.base:=NR_PC;
+      list.concat(taicpu.op_regset(A_PUSH,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+      list.concat(taicpu.op_reg_ref(A_LDR,NR_R0,tmpref));
+      list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_R0));
+      list.concat(taicpu.op_regset(A_POP,R_INTREGISTER,R_SUBWHOLE,[RS_R0]));
+      list.concat(taicpu.op_reg(A_BX,NR_R12));
+
+      { append const entry }
+      list.Concat(tai_align.Create(4));
+      list.Concat(tai_label.create(l));
+      list.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(externalname)));
+    end;
+
+
 
   procedure create_hlcodegen;
     begin
-      hlcg:=thlcg2ll.create;
+      if GenerateThumbCode then
+        hlcg:=tthumbhlcgcpu.create
+      else
+        hlcg:=tarmhlcgcpu.create;
       create_codegen;
     end;
 
+begin
+  chlcgobj:=tbasehlcgarm;
 end.

+ 82 - 47
compiler/arm/narmadd.pas

@@ -34,6 +34,7 @@ interface
           function  GetResFlags(unsigned:Boolean):TResFlags;
           function  GetFpuResFlags:TResFlags;
        public
+          function use_fma : boolean;override;
           function pass_1 : tnode;override;
           function use_generic_mul32to64: boolean; override;
           function use_generic_mul64bit: boolean; override;
@@ -85,6 +86,8 @@ interface
                       GetResFlags:=F_LT;
                     gten:
                       GetResFlags:=F_LE;
+                    else
+                      internalerror(201408203);
                   end
                 else
                   case NodeType of
@@ -96,6 +99,8 @@ interface
                       GetResFlags:=F_GT;
                     gten:
                       GetResFlags:=F_GE;
+                    else
+                      internalerror(201408204);
                   end;
               end
             else
@@ -110,6 +115,8 @@ interface
                       GetResFlags:=F_CC;
                     gten:
                       GetResFlags:=F_LS;
+                    else
+                      internalerror(201408205);
                   end
                 else
                   case NodeType of
@@ -121,6 +128,8 @@ interface
                       GetResFlags:=F_HI;
                     gten:
                       GetResFlags:=F_CS;
+                    else
+                      internalerror(201408206);
                   end;
               end;
         end;
@@ -144,14 +153,23 @@ interface
             result:=F_GT;
           gten:
             result:=F_GE;
+          else
+            internalerror(201408207);
         end;
       end;
 
 
+    function tarmaddnode.use_fma : boolean;
+      begin
+       Result:=current_settings.fputype in [fpu_vfpv4];
+      end;
+
+
     procedure tarmaddnode.second_addfloat;
       var
         op : TAsmOp;
         singleprec: boolean;
+        pf: TOpPostfix;
       begin
         pass_left_right;
         if (nf_swapped in flags) then
@@ -189,6 +207,7 @@ interface
             end;
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               { force mmreg as location, left right doesn't matter
@@ -200,33 +219,25 @@ interface
               location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
 
               singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+              if singleprec then
+                pf:=PF_F32
+              else
+                pf:=PF_F64;
               case nodetype of
                 addn :
-                  if singleprec then
-                    op:=A_FADDS
-                  else
-                    op:=A_FADDD;
+                  op:=A_VADD;
                 muln :
-                  if singleprec then
-                    op:=A_FMULS
-                  else
-                    op:=A_FMULD;
+                  op:=A_VMUL;
                 subn :
-                  if singleprec then
-                    op:=A_FSUBS
-                  else
-                    op:=A_FSUBD;
+                  op:=A_VSUB;
                 slashn :
-                  if singleprec then
-                    op:=A_FDIVS
-                  else
-                    op:=A_FDIVD;
+                  op:=A_VDIV;
                 else
                   internalerror(2009111401);
               end;
 
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
-                 location.register,left.location.register,right.location.register));
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op,
+                 location.register,left.location.register,right.location.register),pf));
             end;
           fpu_fpv4_s16:
             begin
@@ -265,6 +276,7 @@ interface
     procedure tarmaddnode.second_cmpfloat;
       var
         op: TAsmOp;
+        pf: TOpPostfix;
       begin
         pass_left_right;
         if (nf_swapped in flags) then
@@ -295,24 +307,26 @@ interface
             end;
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
 
+              if nodetype in [equaln,unequaln] then
+                op:=A_VCMP
+              else
+                op:=A_VCMPE;
+
               if (tfloatdef(left.resultdef).floattype=s32real) then
-                if nodetype in [equaln,unequaln] then
-                  op:=A_FCMPS
-                 else
-                   op:=A_FCMPES
-              else if nodetype in [equaln,unequaln] then
-                op:=A_FCMPD
+                pf:=PF_F32
               else
-                op:=A_FCMPED;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
-                left.location.register,right.location.register));
+                pf:=PF_F64;
+
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op,
+                left.location.register,right.location.register), pf));
               cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
-              current_asmdata.CurrAsmList.concat(taicpu.op_none(A_FMSTAT));
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VMRS,NR_APSR_nzcv,NR_FPSCR));
               location.resflags:=GetFpuResFlags;
             end;
           fpu_fpv4_s16:
@@ -325,8 +339,8 @@ interface
               else
                 op:=A_VCMPE;
 
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
-                left.location.register,right.location.register));
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op,
+                left.location.register,right.location.register),PF_F32));
               cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
               current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_VMRS, NR_APSR_nzcv, NR_FPSCR));
             end;
@@ -379,13 +393,13 @@ interface
               tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
               if right.location.loc = LOC_CONSTANT then
                 begin
-                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_AND,tmpreg,left.location.register,right.location.value));
+                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,OS_32,right.location.value,left.location.register,tmpreg);
                   cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,tmpreg,right.location.value));
                 end
               else
                 begin
-                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
+                  cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,OS_32,left.location.register,right.location.register,tmpreg);
                   cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
                 end;
@@ -402,8 +416,13 @@ interface
         unsigned : boolean;
         oldnodetype : tnodetype;
         dummyreg : tregister;
+        truelabel, falselabel: tasmlabel;
         l: tasmlabel;
+      const
+        lt_zero_swapped: array[boolean] of tnodetype = (ltn, gtn);
       begin
+        truelabel:=nil;
+        falselabel:=nil;
         unsigned:=not(is_signed(left.resultdef)) or
                   not(is_signed(right.resultdef));
 
@@ -411,20 +430,34 @@ interface
 
         { pass_left_right moves possible consts to the right, the only
           remaining case with left consts (currency) can take this path too (KB) }
-        if (nodetype in [equaln,unequaln]) and
-          (right.nodetype=ordconstn) and (tordconstnode(right).value=0) then
+        if (right.nodetype=ordconstn) and
+           (tordconstnode(right).value=0) and
+           ((nodetype in [equaln,unequaln]) or
+            (not(GenerateThumbCode) and is_signed(left.resultdef) and (nodetype = lt_zero_swapped[nf_swapped in Flags]))
+           ) then
           begin
             location_reset(location,LOC_FLAGS,OS_NO);
-            location.resflags:=getresflags(unsigned);
             if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
               hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
-            dummyreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
-            cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
 
-            if GenerateThumbCode then
-              cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reglo,left.location.register64.reghi,dummyreg)
+            cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+            { Optimize for the common case of int64 < 0 }
+            if nodetype in [ltn, gtn] then
+              begin
+                {Just check for the MSB in reghi to be set or not, this is independed from nf_swapped}
+                location.resflags:=F_NE;
+                current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_TST,left.location.register64.reghi, aint($80000000)));
+              end
             else
-              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ORR,dummyreg,left.location.register64.reglo,left.location.register64.reghi),PF_S));
+              begin
+                location.resflags:=getresflags(unsigned);
+                dummyreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+
+                if GenerateThumbCode then
+                  cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reglo,left.location.register64.reghi,dummyreg)
+                else
+                  current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ORR,dummyreg,left.location.register64.reglo,left.location.register64.reghi),PF_S));
+              end;
           end
         else
           begin
@@ -451,17 +484,19 @@ interface
             else
             { operation requiring proper N, Z and V flags ? }
               begin
-                location_reset(location,LOC_JUMP,OS_NO);
+                current_asmdata.getjumplabel(truelabel);
+                current_asmdata.getjumplabel(falselabel);
+                location_reset_jump(location,truelabel,falselabel);
                 cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                 current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
                 { 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);
+                        cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),location.truelabel);
                         { cheat a little bit for the negative test }
                         toggleflag(nf_swapped);
-                        cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrFalseLabel);
+                        cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),location.falselabel);
                         cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         toggleflag(nf_swapped);
                      end;
@@ -472,13 +507,13 @@ interface
                           nodetype:=ltn
                         else
                           nodetype:=gtn;
-                        cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+                        cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),location.truelabel);
                         { 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);
+                        cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),location.falselabel);
                         cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                         nodetype:=oldnodetype;
                      end;
@@ -487,8 +522,8 @@ interface
                 current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
                 { 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);
+                cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),location.truelabel);
+                cg.a_jmp_always(current_asmdata.CurrAsmList,location.falselabel);
                 cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
               end;
           end;

+ 3 - 2
compiler/arm/narmcal.pas

@@ -45,9 +45,10 @@ implementation
   procedure tarmcallnode.set_result_location(realresdef: tstoreddef);
     begin
       if (realresdef.typ=floatdef) and 
-         (target_info.abi <> abi_eabihf) and
+         (target_info.abi<>abi_eabihf) and
+         (procdefinition.proccalloption<>pocall_hardfloat) and
          ((cs_fp_emulation in current_settings.moduleswitches) or
-          (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16])) then
+          (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv4,fpu_vfpv3_d16,fpu_fpv4_s16])) then
         begin
           { keep the fpu values in integer registers for now, the code
             generator will move them to memory or an mmregister when necessary

+ 16 - 18
compiler/arm/narmcnv.pas

@@ -116,6 +116,7 @@ implementation
                 expectloc:=LOC_FPUREGISTER;
               fpu_vfpv2,
               fpu_vfpv3,
+              fpu_vfpv4,
               fpu_vfpv3_d16,
               fpu_fpv4_s16:
                 expectloc:=LOC_MMREGISTER;
@@ -170,9 +171,9 @@ implementation
 
     procedure tarmtypeconvnode.second_int_to_real;
       const
-        signedprec2vfpop: array[boolean,OS_F32..OS_F64] of tasmop =
-          ((A_FUITOS,A_FUITOD),
-           (A_FSITOS,A_FSITOD));
+        signedprec2vfppf: array[boolean,OS_F32..OS_F64] of toppostfix =
+          ((PF_F32U32,PF_F64U32),
+           (PF_F32S32,PF_F64S32));
       var
         instr : taicpu;
         href : treference;
@@ -206,7 +207,7 @@ implementation
                         instr.oppostfix:=PF_D;
                         current_asmdata.CurrAsmList.concat(instr);
 
-                        current_asmdata.getdatalabel(l1);
+                        current_asmdata.getglobaldatalabel(l1);
                         current_asmdata.getjumplabel(l2);
                         reference_reset_symbol(href,l1,0,const_align(8));
 
@@ -242,6 +243,7 @@ implementation
             end;
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
@@ -253,8 +255,9 @@ implementation
                 location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size)
               else
                 location.register:=left.location.register;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(
-                signedprec2vfpop[signed,location.size],location.register,left.location.register));
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VCVT,
+                location.register,left.location.register),
+                signedprec2vfppf[signed,location.size]));
             end;
           fpu_fpv4_s16:
             begin
@@ -282,13 +285,9 @@ implementation
         hregister : tregister;
         href      : treference;
         resflags  : tresflags;
-        hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+        hlabel    : 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;
@@ -306,13 +305,15 @@ implementation
                 hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,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;
+
+         if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
+           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+
          case left.location.loc of
             LOC_CREFERENCE,
             LOC_REFERENCE :
@@ -360,10 +361,10 @@ implementation
               begin
                 hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
                 current_asmdata.getjumplabel(hlabel);
-                cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+                cg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
                 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_label(current_asmdata.CurrAsmList,left.location.falselabel);
                 cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister);
                 cg.a_label(current_asmdata.CurrAsmList,hlabel);
                 tbasecgarm(cg).cgsetflags:=true;
@@ -396,9 +397,6 @@ implementation
          else
 {$endif cpu64bitalu}
            location.register:=hreg1;
-
-         current_procinfo.CurrTrueLabel:=oldTrueLabel;
-         current_procinfo.CurrFalseLabel:=oldFalseLabel;
       end;
 
 

+ 18 - 18
compiler/arm/narmcon.pas

@@ -53,11 +53,11 @@ interface
       { 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);
+        floattype2ait:array[tfloattype] of tairealconsttype=
+          (aitrealconst_s32bit,aitrealconst_s64bit,aitrealconst_s80bit,aitrealconst_s80bit,aitrealconst_s64comp,aitrealconst_s64comp,aitrealconst_s128bit);
       var
          lastlabel : tasmlabel;
-         realait : taitype;
+         realait : tairealconsttype;
          hiloswapped : boolean;
 
       begin
@@ -73,55 +73,55 @@ interface
             current_procinfo.aktlocaldata.concat(Tai_label.Create(lastlabel));
             location.reference.symboldata:=current_procinfo.aktlocaldata.last;
             case realait of
-              ait_real_32bit :
+              aitrealconst_s32bit :
                 begin
-                  current_procinfo.aktlocaldata.concat(Tai_real_32bit.Create(ts32real(value_real)));
+                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s32real(ts32real(value_real)));
                   { range checking? }
                   if floating_point_range_check_error and
-                    (tai_real_32bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s32val=MathInf.Value) then
                     Message(parser_e_range_check_error);
                 end;
 
-              ait_real_64bit :
+              aitrealconst_s64bit :
                 begin
                   if hiloswapped then
-                    current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value_real)))
+                    current_procinfo.aktlocaldata.concat(tai_realconst.create_s64real_hiloswapped(ts64real(value_real)))
                   else
-                    current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create(ts64real(value_real)));
+                    current_procinfo.aktlocaldata.concat(tai_realconst.create_s64real(ts64real(value_real)));
 
                   { range checking? }
                   if floating_point_range_check_error and
-                    (tai_real_64bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s64val=MathInf.Value) then
                     Message(parser_e_range_check_error);
                end;
 
-              ait_real_80bit :
+              aitrealconst_s80bit :
                 begin
-                  current_procinfo.aktlocaldata.concat(Tai_real_80bit.Create(value_real,tfloatdef(resultdef).size));
+                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s80real(value_real,tfloatdef(resultdef).size));
 
                   { range checking? }
                   if floating_point_range_check_error and
-                    (tai_real_80bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s80val=MathInf.Value) then
                     Message(parser_e_range_check_error);
                 end;
 {$ifdef cpufloat128}
-              ait_real_128bit :
+              aitrealconst_s128bit :
                 begin
-                  current_procinfo.aktlocaldata.concat(Tai_real_128bit.Create(value_real));
+                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s128real(value_real));
 
                   { range checking? }
                   if floating_point_range_check_error and
-                    (tai_real_128bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+                    (tai_realconst(current_procinfo.aktlocaldata.last).value.s128val=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 :
+              aitrealconst_s64comp :
                 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)));
+                  current_procinfo.aktlocaldata.concat(tai_realconst.create_s64compreal(round(value_real)));
             else
               internalerror(2005092401);
             end;

+ 125 - 16
compiler/arm/narminl.pas

@@ -33,6 +33,7 @@ interface
         function first_abs_real: tnode; override;
         function first_sqr_real: tnode; override;
         function first_sqrt_real: tnode; override;
+        function first_fma : tnode; override;
         { atn,sin,cos,lgn isn't supported by the linux fpe
         function first_arctan_real: tnode; override;
         function first_ln_real: tnode; override;
@@ -50,6 +51,7 @@ interface
         }
         procedure second_prefetch; override;
         procedure second_abs_long; override;
+        procedure second_fma; override;
       private
         procedure load_fpu_location(out singleprec: boolean);
       end;
@@ -61,7 +63,8 @@ implementation
       globtype,verbose,globals,
       cpuinfo, defutil,symdef,aasmdata,aasmcpu,
       cgbase,cgutils,pass_1,pass_2,
-      cpubase,ncgutil,cgobj,cgcpu, hlcgobj;
+      cpubase,ncgutil,cgobj,cgcpu, hlcgobj,
+      ncal;
 
 {*****************************************************************************
                               tarminlinenode
@@ -85,6 +88,7 @@ implementation
             end;
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16,
           fpu_fpv4_s16:
             begin
@@ -125,6 +129,7 @@ implementation
                 expectloc:=LOC_FPUREGISTER;
               fpu_vfpv2,
               fpu_vfpv3,
+              fpu_vfpv4,
               fpu_vfpv3_d16:
                 expectloc:=LOC_MMREGISTER;
               fpu_fpv4_s16:
@@ -155,6 +160,7 @@ implementation
                 expectloc:=LOC_FPUREGISTER;
               fpu_vfpv2,
               fpu_vfpv3,
+              fpu_vfpv4,
               fpu_vfpv3_d16:
                 expectloc:=LOC_MMREGISTER;
               fpu_fpv4_s16:
@@ -185,6 +191,7 @@ implementation
                 expectloc:=LOC_FPUREGISTER;
               fpu_vfpv2,
               fpu_vfpv3,
+              fpu_vfpv4,
               fpu_vfpv3_d16:
                 expectloc:=LOC_MMREGISTER;
               fpu_fpv4_s16:
@@ -202,6 +209,19 @@ implementation
       end;
 
 
+     function tarminlinenode.first_fma : tnode;
+       begin
+         if (true) and
+           ((is_double(resultdef)) or (is_single(resultdef))) then
+           begin
+             expectloc:=LOC_MMREGISTER;
+             Result:=nil;
+           end
+         else
+           Result:=inherited first_fma;
+       end;
+
+
     { atn,sin,cos,lgn isn't supported by the linux fpe
     function tarminlinenode.first_arctan_real: tnode;
       begin
@@ -234,7 +254,7 @@ implementation
     procedure tarminlinenode.second_abs_real;
       var
         singleprec: boolean;
-        op: TAsmOp;
+        pf: TOpPostfix;
       begin
         load_fpu_location(singleprec);
         case current_settings.fputype of
@@ -244,13 +264,14 @@ implementation
             current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_ABS,location.register,left.location.register),get_fpu_postfix(resultdef)));
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               if singleprec then
-                op:=A_FABSS
+                pf:=PF_F32
               else
-                op:=A_FABSD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+                pf:=PF_F64;
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register),pf));
             end;
           fpu_fpv4_s16:
             current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32));
@@ -270,7 +291,7 @@ implementation
     procedure tarminlinenode.second_sqr_real;
       var
         singleprec: boolean;
-        op: TAsmOp;
+        pf: TOpPostfix;
       begin
         load_fpu_location(singleprec);
         case current_settings.fputype of
@@ -280,13 +301,14 @@ implementation
             current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_MUF,location.register,left.location.register,left.location.register),get_fpu_postfix(resultdef)));
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               if singleprec then
-                op:=A_FMULS
+                pf:=PF_F32
               else
-                op:=A_FMULD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
+                pf:=PF_F64;
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register),pf));
             end;
           fpu_fpv4_s16:
             current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register), PF_F32));
@@ -299,7 +321,7 @@ implementation
     procedure tarminlinenode.second_sqrt_real;
       var
         singleprec: boolean;
-        op: TAsmOp;
+        pf: TOpPostfix;
       begin
         load_fpu_location(singleprec);
         case current_settings.fputype of
@@ -309,16 +331,17 @@ implementation
             current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_SQT,location.register,left.location.register),get_fpu_postfix(resultdef)));
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               if singleprec then
-                op:=A_FSQRTS
+                pf:=PF_F32
               else
-                op:=A_FSQRTD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+                pf:=PF_F64;
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register),pf));
             end;
           fpu_fpv4_s16:
-            current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register));
+            current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register), PF_F32));
         else
           internalerror(2009111402);
         end;
@@ -372,7 +395,7 @@ implementation
                   current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_PLD,ref));
                 end;
               else
-                internalerror(200402021);
+                { nothing to prefetch };
             end;
           end;
       end;
@@ -380,7 +403,6 @@ implementation
     procedure tarminlinenode.second_abs_long;
       var
         opsize : tcgsize;
-        hp : taicpu;
       begin
         if GenerateThumbCode then
           begin
@@ -405,6 +427,93 @@ implementation
         cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
       end;
 
+
+    procedure tarminlinenode.second_fma;
+      const
+        op : array[false..true,false..true] of TAsmOp =
+          { positive product }
+          (
+           { positive third operand }
+           (A_VFMA,
+           { negative third operand }
+            A_VFNMS),
+           { negative product }
+            { positive third operand }
+            (A_VFMS,
+             A_VFNMA)
+           );
+
+      var
+        paraarray : array[1..3] of tnode;
+        i : integer;
+        negop3,
+        negproduct : boolean;
+        oppostfix : TOpPostfix;
+      begin
+         if current_settings.fputype in [fpu_vfpv4] then
+           begin
+             negop3:=false;
+             negproduct:=false;
+             paraarray[1]:=tcallparanode(tcallparanode(tcallparanode(parameters).nextpara).nextpara).paravalue;
+             paraarray[2]:=tcallparanode(tcallparanode(parameters).nextpara).paravalue;
+             paraarray[3]:=tcallparanode(parameters).paravalue;
+
+             { check if a neg. node can be removed
+               this is possible because changing the sign of
+               a floating point number does not affect its absolute
+               value in any way
+             }
+             if paraarray[1].nodetype=unaryminusn then
+               begin
+                 paraarray[1]:=tunarynode(paraarray[1]).left;
+                 { do not release the unused unary minus node, it is kept and release together with the other nodes,
+                   only no code is generated for it }
+                 negproduct:=not(negproduct);
+               end;
+
+             if paraarray[2].nodetype=unaryminusn then
+               begin
+                 paraarray[2]:=tunarynode(paraarray[2]).left;
+                 { do not release the unused unary minus node, it is kept and release together with the other nodes,
+                   only no code is generated for it }
+                 negproduct:=not(negproduct);
+               end;
+
+             if paraarray[3].nodetype=unaryminusn then
+               begin
+                 paraarray[3]:=tunarynode(paraarray[3]).left;
+                 { do not release the unused unary minus node, it is kept and release together with the other nodes,
+                   only no code is generated for it }
+                 negop3:=true;
+               end;
+
+              for i:=1 to 3 do
+               secondpass(paraarray[i]);
+
+             { no memory operand is allowed }
+             for i:=1 to 3 do
+               begin
+                 if not(paraarray[i].location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
+                   hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,paraarray[i].location,paraarray[i].resultdef,true);
+               end;
+
+             location_reset(location,LOC_MMREGISTER,paraarray[1].location.size);
+             location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+
+             hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,paraarray[3].resultdef,resultdef,
+               paraarray[3].location.register,location.register,mms_movescalar);
+             if is_double(resultdef) then
+               oppostfix:=PF_F64
+             else
+               oppostfix:=PF_F32;
+             current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op[negproduct,negop3],
+               location.register,paraarray[1].location.register,paraarray[2].location.register),oppostfix));
+           end
+         else
+           internalerror(2014032301);
+      end;
+
+
 begin
   cinlinenode:=tarminlinenode;
 end.

+ 12 - 26
compiler/arm/narmmat.pas

@@ -286,7 +286,8 @@ implementation
                 resultreg:=cg.getintregister(current_asmdata.CurrAsmList,size);
               end;
 
-            if right.nodetype=ordconstn then
+            if (right.nodetype=ordconstn) and
+               (CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) then
               begin
                 if nodetype=divn then
                   genOrdConstNodeDiv
@@ -309,29 +310,11 @@ implementation
 *****************************************************************************}
 
     procedure tarmnotnode.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);
-
-            if left.location.loc<>LOC_JUMP then
-              internalerror(2012081305);
-
-            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
+        if not handle_locjump then
           begin
             secondpass(left);
             case left.location.loc of
@@ -410,7 +393,7 @@ implementation
 
     procedure tarmunaryminusnode.second_float;
       var
-        op: tasmop;
+        pf: TOpPostfix;
       begin
         secondpass(left);
         case current_settings.fputype of
@@ -426,18 +409,21 @@ implementation
             end;
           fpu_vfpv2,
           fpu_vfpv3,
+          fpu_vfpv4,
           fpu_vfpv3_d16:
             begin
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
               location:=left.location;
               if (left.location.loc=LOC_CMMREGISTER) then
                 location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
-              if (location.size=OS_F32) then
-                op:=A_FNEGS
+
+              if (tfloatdef(left.resultdef).floattype=s32real) then
+                pf:=PF_F32
               else
-                op:=A_FNEGD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
-                location.register,left.location.register));
+                pf:=PF_F64;
+
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG,
+                location.register,left.location.register), pf));
             end;
           fpu_fpv4_s16:
             begin

+ 4 - 3
compiler/arm/narmmem.pas

@@ -27,6 +27,7 @@ interface
 
     uses
       globtype,
+      symtype,
       cgbase,cpubase,nmem,ncgmem;
 
     type
@@ -36,7 +37,7 @@ interface
 
 
       tarmvecnode = class(tcgvecnode)
-        procedure update_reference_reg_mul(maybe_const_reg: tregister; l: aint);override;
+        procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);override;
       end;
 
 implementation
@@ -70,7 +71,7 @@ implementation
                              TARMVECNODE
 *****************************************************************************}
 
-     procedure tarmvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+     procedure tarmvecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
        var
          hreg: tregister;
          hl : longint;
@@ -79,7 +80,7 @@ implementation
             (GenerateThumbCode) or
             { simple constant? }
             (l=1) or ispowerof2(l,hl) or ispowerof2(l+1,hl) or ispowerof2(l-1,hl) then
-           inherited update_reference_reg_mul(maybe_const_reg,l)
+           inherited update_reference_reg_mul(maybe_const_reg,regsize,l)
          else if (location.reference.base<>NR_NO) then
            begin
              hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);

+ 29 - 12
compiler/arm/narmset.pas

@@ -37,7 +37,7 @@ interface
 
        tarminnode = class(tcginnode)
          function pass_1: tnode; override;
-         procedure in_smallset(uopsize: tcgsize; opdef: tdef; setbase: aint); override;
+         procedure in_smallset(opdef: tdef; setbase: aint); override;
        end;
 
       tarmcasenode = class(tcgcasenode)
@@ -51,7 +51,7 @@ interface
 implementation
 
     uses
-      verbose,globals,constexp,defutil,
+      verbose,globals,constexp,defutil,systems,
       aasmbase,aasmtai,aasmdata,aasmcpu,
       cpubase,cpuinfo,
       cgutils,cgobj,ncgutil,
@@ -72,16 +72,25 @@ implementation
         if not(assigned(result)) then
           begin
             if not(checkgenjumps(setparts,numparts,use_small)) and
-              use_small then
+              use_small and
+              (target_info.endian=endian_little) then
               expectloc:=LOC_FLAGS;
           end;
       end;
 
-    procedure tarminnode.in_smallset(uopsize: tcgsize; opdef: tdef; setbase: aint);
+    procedure tarminnode.in_smallset(opdef: tdef; setbase: aint);
       var
         so : tshifterop;
         hregister : tregister;
       begin
+        { the code below needs changes for big endian targets (they start
+          counting from the most significant bit)
+        }
+        if target_info.endian=endian_big then
+          begin
+            inherited;
+            exit;
+          end;
         location_reset(location,LOC_FLAGS,OS_NO);
         location.resflags:=F_NE;
         if (left.location.loc=LOC_CONSTANT) and not(GenerateThumbCode) then
@@ -96,12 +105,12 @@ implementation
           begin
             hlcg.location_force_reg(current_asmdata.CurrAsmList, left.location,
              left.resultdef, opdef, true);
-            register_maybe_adjust_setbase(current_asmdata.CurrAsmList, left.location,
-             setbase);
+            register_maybe_adjust_setbase(current_asmdata.CurrAsmList, opdef,
+             left.location, setbase);
             hlcg.location_force_reg(current_asmdata.CurrAsmList, right.location,
              right.resultdef, right.resultdef, true);
 
-            hregister:=cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+            hregister:=hlcg.getintregister(current_asmdata.CurrAsmList, opdef);
             current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_MOV,hregister,1));
 
             if GenerateThumbCode or GenerateThumb2Code then
@@ -141,6 +150,7 @@ implementation
     procedure tarmcasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
       var
         last : TConstExprInt;
+        tmpreg,
         basereg,
         indexreg : tregister;
         href : treference;
@@ -222,7 +232,7 @@ implementation
           begin
             if cs_create_pic in current_settings.moduleswitches then
               internalerror(2013082102);
-            cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_ADDR,min_+1,indexreg,indexreg);
+            cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_ADDR,min_,indexreg,indexreg);
             current_asmdata.getaddrlabel(tablelabel);
 
             cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,indexreg);
@@ -231,10 +241,17 @@ implementation
             reference_reset_symbol(href,tablelabel,0,4);
             cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList, href, basereg);
 
-            cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_ADDr, indexreg, basereg);
-
-            current_asmdata.CurrAsmList.Concat(taicpu.op_reg(A_BX, basereg));
-
+            reference_reset(href,0);
+            href.base:=basereg;
+            href.index:=indexreg;
+            
+            tmpreg:=cg.getintregister(current_asmdata.CurrAsmList, OS_ADDR);
+            cg.a_load_ref_reg(current_asmdata.CurrAsmList, OS_ADDR, OS_ADDR, href, tmpreg);
+            
+            { do not use BX here to avoid switching into arm mode }
+            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_MOV, NR_PC, tmpreg));
+
+            current_asmdata.CurrAsmList.Concat(tai_align.Create(4));                
             cg.a_label(current_asmdata.CurrAsmList,tablelabel);
             { generate jump table }
             last:=min_;

+ 253 - 93
compiler/arm/raarmgas.pas

@@ -30,6 +30,7 @@ Unit raarmgas;
       cpubase;
 
     type
+
       tarmattreader = class(tattreader)
         actoppostfix : TOpPostfix;
         actwideformat : boolean;
@@ -45,6 +46,13 @@ Unit raarmgas;
         procedure ReadSym(oper : tarmoperand);
         procedure ConvertCalljmp(instr : tarminstruction);
         procedure HandleTargetDirective; override;
+      protected
+        function is_unified: boolean; virtual;
+      end;
+
+      tarmunifiedattreader = class(tarmattreader)
+      protected
+        function is_unified: boolean; override;
       end;
 
 
@@ -54,7 +62,7 @@ Unit raarmgas;
       { helpers }
       cutils,
       { global }
-      globtype,verbose,
+      globtype,globals,verbose,
       systems,aasmbase,aasmtai,aasmdata,aasmcpu,
       { symtable }
       symconst,symsym,
@@ -63,15 +71,21 @@ Unit raarmgas;
       cgbase,cgutils;
 
 
+    function tarmunifiedattreader.is_unified: boolean;
+      begin
+        result:=true;
+      end;
+
+
     function tarmattreader.is_register(const s:string):boolean;
       type
         treg2str = record
-          name : string[2];
+          name : string[3];
           reg : tregister;
         end;
 
       const
-        extraregs : array[0..19] of treg2str = (
+        extraregs : array[0..19+16] of treg2str = (
           (name: 'A1'; reg : NR_R0),
           (name: 'A2'; reg : NR_R1),
           (name: 'A3'; reg : NR_R2),
@@ -91,7 +105,25 @@ Unit raarmgas;
           (name: 'IP'; reg : NR_R12),
           (name: 'SP'; reg : NR_R13),
           (name: 'LR'; reg : NR_R14),
-          (name: 'PC'; reg : NR_R15));
+          (name: 'PC'; reg : NR_R15),
+
+          (name: 'C0'; reg : NR_CR0),
+          (name: 'C1'; reg : NR_CR1),
+          (name: 'C2'; reg : NR_CR2),
+          (name: 'C3'; reg : NR_CR3),
+          (name: 'C4'; reg : NR_CR4),
+          (name: 'C5'; reg : NR_CR5),
+          (name: 'C6'; reg : NR_CR6),
+          (name: 'C7'; reg : NR_CR7),
+          (name: 'C8'; reg : NR_CR8),
+          (name: 'C9'; reg : NR_CR9),
+          (name: 'C10'; reg : NR_CR10),
+          (name: 'C11'; reg : NR_CR11),
+          (name: 'C12'; reg : NR_CR12),
+          (name: 'C13'; reg : NR_CR13),
+          (name: 'C14'; reg : NR_CR14),
+          (name: 'C15'; reg : NR_CR15)
+          );
 
       var
         i : longint;
@@ -101,7 +133,7 @@ Unit raarmgas;
         { reg found?
           possible aliases are always 2 char
         }
-        if result or (length(s)<>2) then
+        if result or (not (length(s) in [2,3])) then
           exit;
         for i:=low(extraregs) to high(extraregs) do
           begin
@@ -117,12 +149,14 @@ Unit raarmgas;
 
     function tarmattreader.is_targetdirective(const s: string): boolean;
       begin
-        if s = '.thumb_func' then
-          result:=true
-        else if s='.thumb_set' then
-          result:=true
-        else
-          Result:=inherited is_targetdirective(s);
+        case s of
+          '.thumb_func',
+          '.code',
+          '.thumb_set':
+            result:=true
+          else
+            Result:=inherited is_targetdirective(s);
+        end;
       end;
 
 
@@ -241,7 +275,9 @@ Unit raarmgas;
                           do_error;
                         oper.opr.ref.shiftimm := shift;
                         test_end(require_rbracket);
-                      end;
+                      end
+                    else
+                      test_end(require_rbracket);
                    end
                  else
                    begin
@@ -528,7 +564,7 @@ Unit raarmgas;
             else if (actasmpattern='ROR') then
               handlepara(SM_ROR)
             else if (actasmpattern='RRX') then
-              handlepara(SM_ROR)
+              handlepara(SM_RRX)
             else
               result:=false;
           end
@@ -785,6 +821,18 @@ Unit raarmgas;
           end;
 
 
+      function getregsetindex(reg: tregister): integer;
+        begin
+          if getsubreg(reg)=R_SUBFS then
+            begin
+              result:=getsupreg(reg)*2;
+              if result>32 then
+                result:=result-63;
+            end
+          else
+            result:=getsupreg(reg);
+        end;
+
       var
         tempreg : tregister;
         ireg : tsuperregister;
@@ -958,7 +1006,7 @@ Unit raarmgas;
                   oper.opr.typ:=OPR_REGISTER;
                   oper.opr.reg:=tempreg;
                 end
-              else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM,A_FLDM,A_FSTM]) then
+              else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM,A_FLDM,A_FSTM,A_VLDM,A_VSTM,A_SRS,A_RFE]) then
                 begin
                   consume(AS_NOT);
                   oper.opr.typ:=OPR_REFERENCE;
@@ -976,11 +1024,11 @@ Unit raarmgas;
               registerset:=[];
               regtype:=R_INVALIDREGISTER;
               subreg:=R_SUBNONE;
-              while true do
+              while actasmtoken<>AS_RSBRACKET do
                 begin
                   if actasmtoken=AS_REGISTER then
                     begin
-                      include(registerset,getsupreg(actasmregister));
+                      include(registerset,getregsetindex(actasmregister));
                       if regtype<>R_INVALIDREGISTER then
                         begin
                           if (getregtype(actasmregister)<>regtype) or
@@ -997,7 +1045,7 @@ Unit raarmgas;
                       if actasmtoken=AS_MINUS then
                         begin
                           consume(AS_MINUS);
-                          for ireg:=getsupreg(tempreg) to getsupreg(actasmregister) do
+                          for ireg:=getregsetindex(tempreg) to getregsetindex(actasmregister) do
                             include(registerset,ireg);
                           consume(AS_REGISTER);
                         end;
@@ -1043,6 +1091,7 @@ Unit raarmgas;
         hreg : tregister;
         flags : tspecialregflags;
       begin
+        hreg:=NR_NO;
         case actasmtoken of
           AS_REGISTER:
             begin
@@ -1136,8 +1185,19 @@ Unit raarmgas;
           case actasmtoken of
             AS_COMMA: { Operand delimiter }
               Begin
-                if ((instr.opcode in [A_MOV, A_MVN, A_CMP, A_CMN, A_TST, A_TEQ]) and (operandnum=2)) or
-                  ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA,A_MRC,A_MCR,A_MCRR,A_MRRC])) then
+                if ((instr.opcode in [A_MOV,A_MVN,A_CMP,A_CMN,A_TST,A_TEQ,
+                                      A_UXTB,A_UXTH,A_UXTB16,
+                                      A_SXTB,A_SXTH,A_SXTB16]) and
+                    (operandnum=2)) or
+                  ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA,A_UMAAL,A_MLS,
+                                                           A_SMLABB,A_SMLABT,A_SMLATB,A_SMLATT,A_SMMLA,A_SMMLS,A_SMLAD,A_SMLALD,A_SMLSD,
+                                                           A_SMLALBB,A_SMLALBT,A_SMLALTB,A_SMLALTT,A_SMLSLD,
+                                                           A_SMLAWB,A_SMLAWT,
+                                                           A_MRC,A_MCR,A_MCRR,A_MRRC,A_MRC2,A_MCR2,A_MCRR2,A_MRRC2,
+                                                           A_STREXD,A_STRD,
+                                                           A_USADA8,
+                                                           A_VMOV,
+                                                           A_SBFX,A_UBFX,A_BFI])) then
                   begin
                     Consume(AS_COMMA);
                     if not(TryBuildShifterOp(instr.Operands[operandnum+1] as tarmoperand)) then
@@ -1159,7 +1219,8 @@ Unit raarmgas;
                 break;
               end;
           else
-            if (instr.opcode = A_MSR) and (operandnum = 1) then
+            if ((instr.opcode = A_MRS) and (operandnum = 2)) or
+               ((instr.opcode = A_MSR) and (operandnum = 1)) then
               BuildSpecialreg(instr.Operands[operandnum] as tarmoperand)
             else
               BuildOperand(instr.Operands[operandnum] as tarmoperand);
@@ -1173,25 +1234,34 @@ Unit raarmgas;
 
       const
         { sorted by length so longer postfixes will match first }
-        postfix2strsorted : array[1..31] of string[3] = (
-          'IAD','DBD','FDD','EAD',
-          'IAS','DBS','FDS','EAS',
-          'IAX','DBX','FDX','EAX',
-          'EP','SB','BT','SH',
-          'IA','IB','DA','DB','FD','FA','ED','EA',
-          'B','D','E','P','T','H','S');
-
-        postfixsorted : array[1..31] of TOpPostfix = (
-          PF_IAD,PF_DBD,PF_FDD,PF_EAD,
-          PF_IAS,PF_DBS,PF_FDS,PF_EAS,
-          PF_IAX,PF_DBX,PF_FDX,PF_EAX,
-          PF_EP,PF_SB,PF_BT,PF_SH,
-          PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
-          PF_B,PF_D,PF_E,PF_P,PF_T,PF_H,PF_S);
+        postfix2strsorted : array[1..70] of string[9] = (
+          '.F32.S32','.F32.U32','.S32.F32','.U32.F32','.F64.S32','.F64.U32','.S32.F64','.U32.F64',
+          '.F32.S16','.F32.U16','.S16.F32','.U16.F32','.F64.S16','.F64.U16','.S16.F64','.U16.F64',
+          '.F32.F64','.F64.F32',
+          '.I16','.I32','.I64','.S16','.S32','.S64','.U16','.U32','.U64','.F32','.F64',
+          'IAD','DBD','FDD','EAD','IAS','DBS','FDS','EAS','IAX','DBX','FDX','EAX',
+          '.16','.32','.64','.I8','.S8','.U8','.P8',
+          'EP','SB','BT','SH','IA','IB','DA','DB','FD','FA','ED','EA',
+          '.8','S','D','E','P','X','R','B','H','T');
+
+        postfixsorted : array[1..70] of TOpPostfix = (
+          PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32,PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64,
+          PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32,PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64,
+          PF_F32F64,PF_F64F32,
+          PF_I16,PF_I32,
+          PF_I64,PF_S16,PF_S32,PF_S64,PF_U16,PF_U32,PF_U64,PF_F32,
+          PF_F64,PF_IAD,PF_DBD,PF_FDD,PF_EAD,
+          PF_IAS,PF_DBS,PF_FDS,PF_EAS,PF_IAX,
+          PF_DBX,PF_FDX,PF_EAX,PF_16,PF_32,
+          PF_64,PF_I8,PF_S8,PF_U8,PF_P8,
+          PF_EP,PF_SB,PF_BT,PF_SH,PF_IA,
+          PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,
+          PF_ED,PF_EA,PF_8,PF_S,PF_D,PF_E,
+          PF_P,PF_X,PF_R,PF_B,PF_H,PF_T);
 
       var
-        j  : longint;
-        hs : string;
+        j, j2 : longint;
+        hs,hs2 : string;
         maxlen : longint;
         icond : tasmcond;
       Begin
@@ -1219,61 +1289,126 @@ Unit raarmgas;
                   end;
               end;
           end;
-        maxlen:=max(length(hs),5);
+        maxlen:=min(length(hs),6);
         actopcode:=A_NONE;
-        for j:=maxlen downto 1 do
+        j2:=maxlen;
+        hs2:=hs;
+        while j2>=1 do
           begin
-            actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
-            if actopcode<>A_NONE then
+            hs:=hs2;
+            while j2>=1 do
               begin
-                actasmtoken:=AS_OPCODE;
-                { strip op code }
-                delete(hs,1,j);
-                break;
+                actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
+                if actopcode<>A_NONE then
+                  begin
+                    actasmtoken:=AS_OPCODE;
+                    { strip op code }
+                    delete(hs,1,j2);
+                    dec(j2);
+                    break;
+                  end;
+                dec(j2);
               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
+            if actopcode=A_NONE then
+              exit;
+
+            if is_unified then
               begin
-                if copy(hs,1,2)=uppercond2str[icond] then
+                { check for postfix }
+                if (length(hs)>0) and (actoppostfix=PF_None) then
                   begin
-                    actcondition:=icond;
-                    { strip condition }
-                    delete(hs,1,2);
-                    break;
+                    for j:=low(postfixsorted) to high(postfixsorted) do
+                      begin
+                        if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                          begin
+                            if not ((length(hs)-length(postfix2strsorted[j])) in [0,2,4]) then
+                              continue;
+
+                            actoppostfix:=postfixsorted[j];
+                            { strip postfix }
+                            delete(hs,1,length(postfix2strsorted[j]));
+                            break;
+                          end;
+                      end;
                   end;
-              end;
-          end;
-        { check for postfix }
-        if length(hs)>0 then
-          begin
-            for j:=low(postfixsorted) to high(postfixsorted) do
+                { 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)>0) and (actoppostfix=PF_None) then
+                  begin
+                    for j:=low(postfixsorted) to high(postfixsorted) do
+                      begin
+                        if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                          begin
+                            if not ((length(hs)-length(postfix2strsorted[j])) = 0) then
+                              continue;
+
+                            actoppostfix:=postfixsorted[j];
+                            { strip postfix }
+                            delete(hs,1,length(postfix2strsorted[j]));
+                            break;
+                          end;
+                      end;
+                  end;
+              end
+            else
               begin
-                if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                { search for condition, conditions are always 2 chars }
+                if length(hs)>1 then
                   begin
-                    actoppostfix:=postfixsorted[j];
-                    { strip postfix }
-                    delete(hs,1,length(postfix2strsorted[j]));
-                    break;
+                    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)>0) and (actoppostfix=PF_None) then
+                  begin
+                    for j:=low(postfixsorted) to high(postfixsorted) do
+                      begin
+                        if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                          begin
+                            actoppostfix:=postfixsorted[j];
+                            { strip postfix }
+                            delete(hs,1,length(postfix2strsorted[j]));
+                            break;
+                          end;
+                      end;
                   end;
               end;
-          end;
-        { check for format postfix }
-        if length(hs)>0 then
-          begin
-            if upcase(copy(hs,1,2)) = '.W' then
+            { check for format postfix }
+            if length(hs)>0 then
               begin
-                actwideformat:=true;
-                delete(hs,1,2);
+                if copy(hs,1,2) = '.W' then
+                  begin
+                    actwideformat:=true;
+                    delete(hs,1,2);
+                  end;
               end;
+            { if we stripped all postfixes, it's a valid opcode }
+            is_asmopcode:=length(hs)=0;
+            if is_asmopcode = true then
+              break;
           end;
-        { if we stripped all postfixes, it's a valid opcode }
-        is_asmopcode:=length(hs)=0;
       end;
 
 
@@ -1293,6 +1428,7 @@ Unit raarmgas;
           end;
       end;
 
+
     procedure tarmattreader.HandleTargetDirective;
       var
         symname,
@@ -1300,22 +1436,38 @@ Unit raarmgas;
         val     : aint;
         symtyp  : TAsmsymtype;
       begin
-        if actasmpattern='.thumb_set' then
-          begin
-            consume(AS_TARGET_DIRECTIVE);
-            BuildConstSymbolExpression(true,false,false, val,symname,symtyp);
-            Consume(AS_COMMA);
-            BuildConstSymbolExpression(true,false,false, val,symval,symtyp);
+        case actasmpattern of
+          '.thumb_set':
+            begin
+              consume(AS_TARGET_DIRECTIVE);
+              BuildConstSymbolExpression(true,false,false, val,symname,symtyp);
+              Consume(AS_COMMA);
+              BuildConstSymbolExpression(true,false,false, val,symval,symtyp);
 
-            curList.concat(tai_thumb_set.create(symname,symval));
-          end
-        else if actasmpattern='.thumb_func' then
-          begin
-            consume(AS_TARGET_DIRECTIVE);
-            curList.concat(tai_thumb_func.create);
-          end
-        else
-          inherited HandleTargetDirective;
+              curList.concat(tai_symbolpair.create(spk_thumb_set,symname,symval));
+            end;
+          '.code':
+            begin
+              consume(AS_TARGET_DIRECTIVE);
+              val:=BuildConstExpression(false,false);
+              if not(val in [16,32]) then
+                Message(asmr_e_invalid_code_value);
+              curList.concat(tai_directive.create(asd_code,tostr(val)));
+            end;
+          '.thumb_func':
+            begin
+              consume(AS_TARGET_DIRECTIVE);
+              curList.concat(tai_directive.create(asd_thumb_func,''));
+            end
+          else
+            inherited HandleTargetDirective;
+        end;
+      end;
+
+
+    function tarmattreader.is_unified: boolean;
+      begin
+        result:=false;
       end;
 
 
@@ -1347,10 +1499,17 @@ const
   asmmode_arm_att_info : tasmmodeinfo =
           (
             id    : asmmode_arm_gas;
-            idtxt : 'GAS';
+            idtxt : 'DIVIDED';
             casmreader : tarmattreader;
           );
 
+  asmmode_arm_att_unified_info : tasmmodeinfo =
+          (
+            id    : asmmode_arm_gas_unified;
+            idtxt : 'UNIFIED';
+            casmreader : tarmunifiedattreader;
+          );
+
   asmmode_arm_standard_info : tasmmodeinfo =
           (
             id    : asmmode_standard;
@@ -1360,5 +1519,6 @@ const
 
 initialization
   RegisterAsmMode(asmmode_arm_att_info);
+  RegisterAsmMode(asmmode_arm_att_unified_info);
   RegisterAsmMode(asmmode_arm_standard_info);
 end.

+ 7 - 0
compiler/arm/rarmcon.inc

@@ -123,3 +123,10 @@ NR_BASEPRI = tregister($0500001F);
 NR_BASEPRI_MAX = tregister($05000020);
 NR_FAULTMASK = tregister($05000021);
 NR_CONTROL = tregister($05000022);
+NR_FPSID = tregister($05000023);
+NR_MVFR1 = tregister($05000024);
+NR_MVFR0 = tregister($05000025);
+NR_FPEXC = tregister($05000026);
+NR_APSR_nzcvq = tregister($05000027);
+NR_APSR_g = tregister($05000028);
+NR_APSR_nzcvqg = tregister($05000029);

+ 7 - 0
compiler/arm/rarmdwa.inc

@@ -122,4 +122,11 @@
 0,
 0,
 0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
 0

+ 1 - 1
compiler/arm/rarmnor.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from armreg.dat }
-124
+131

+ 8 - 1
compiler/arm/rarmnum.inc

@@ -122,4 +122,11 @@ tregister($0500001E),
 tregister($0500001F),
 tregister($05000020),
 tregister($05000021),
-tregister($05000022)
+tregister($05000022),
+tregister($05000023),
+tregister($05000024),
+tregister($05000025),
+tregister($05000026),
+tregister($05000027),
+tregister($05000028),
+tregister($05000029)

+ 8 - 1
compiler/arm/rarmrni.inc

@@ -122,4 +122,11 @@
 120,
 121,
 122,
-123
+123,
+124,
+125,
+126,
+127,
+128,
+129,
+130

+ 8 - 1
compiler/arm/rarmsri.inc

@@ -1,7 +1,10 @@
 { don't edit, this file is generated from armreg.dat }
 0,
 110,
+129,
 92,
+128,
+130,
 120,
 121,
 123,
@@ -65,11 +68,15 @@
 23,
 24,
 122,
+127,
 90,
+124,
 114,
 113,
 111,
 117,
+126,
+125,
 109,
 119,
 118,
@@ -104,7 +111,6 @@
 53,
 28,
 55,
-71,
 56,
 58,
 59,
@@ -116,6 +122,7 @@
 68,
 29,
 70,
+71,
 31,
 32,
 34,

+ 7 - 0
compiler/arm/rarmsta.inc

@@ -122,4 +122,11 @@
 0,
 0,
 0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
 0

+ 9 - 2
compiler/arm/rarmstd.inc

@@ -70,7 +70,7 @@
 's29',
 'd14',
 's30',
-'s21',
+'s31',
 'd15',
 'd16',
 'd17',
@@ -122,4 +122,11 @@
 'basepri',
 'basepri_max',
 'faultmask',
-'control'
+'control',
+'fpsid',
+'mvfr1',
+'mvfr0',
+'fpexc',
+'apsr_nzcvq',
+'apsr_g',
+'apsr_nzcvqg'

+ 7 - 0
compiler/arm/rarmsup.inc

@@ -123,3 +123,10 @@ RS_BASEPRI = $1F;
 RS_BASEPRI_MAX = $20;
 RS_FAULTMASK = $21;
 RS_CONTROL = $22;
+RS_FPSID = $23;
+RS_MVFR1 = $24;
+RS_MVFR0 = $25;
+RS_FPEXC = $26;
+RS_APSR_nzcvq = $27;
+RS_APSR_g = $28;
+RS_APSR_nzcvqg = $29;

Some files were not shown because too many files changed in this diff