浏览代码

merge with trunk

git-svn-id: branches/tg74/avx2@28415 -
tg74 11 年之前
父节点
当前提交
3b09397e34
共有 100 个文件被更改,包括 6477 次插入1990 次删除
  1. 17 3
      .gitattributes
  2. 91 16
      compiler/Makefile
  3. 14 8
      compiler/Makefile.fpc
  4. 2 1
      compiler/aarch64/cpubase.pas
  5. 178 0
      compiler/aarch64/symcpu.pas
  6. 5 1
      compiler/aasmbase.pas
  7. 15 3
      compiler/aasmtai.pas
  8. 95 43
      compiler/aggas.pas
  9. 8 7
      compiler/agjasmin.pas
  10. 4 2
      compiler/alpha/cpunode.pas
  11. 211 0
      compiler/alpha/symcpu.pas
  12. 16 10
      compiler/aopt.pas
  13. 25 10
      compiler/aoptbase.pas
  14. 144 123
      compiler/aoptobj.pas
  15. 58 27
      compiler/arm/aasmcpu.pas
  16. 3 3
      compiler/arm/agarmgas.pas
  17. 322 291
      compiler/arm/aoptcpu.pas
  18. 1 0
      compiler/arm/armatt.inc
  19. 1 0
      compiler/arm/armatts.inc
  20. 2 0
      compiler/arm/armins.dat
  21. 1 0
      compiler/arm/armop.inc
  22. 252 181
      compiler/arm/cgcpu.pas
  23. 17 28
      compiler/arm/cpubase.pas
  24. 10 0
      compiler/arm/cpuelf.pas
  25. 159 90
      compiler/arm/cpuinfo.pas
  26. 3 1
      compiler/arm/cpunode.pas
  27. 28 21
      compiler/arm/cpupara.pas
  28. 63 11
      compiler/arm/cpupi.pas
  29. 74 30
      compiler/arm/narmadd.pas
  30. 4 8
      compiler/arm/narmcon.pas
  31. 31 3
      compiler/arm/narminl.pas
  32. 123 79
      compiler/arm/narmmat.pas
  33. 1 1
      compiler/arm/narmset.pas
  34. 5 0
      compiler/arm/raarmgas.pas
  35. 46 2
      compiler/arm/rgcpu.pas
  36. 215 0
      compiler/arm/symcpu.pas
  37. 32 3
      compiler/assemble.pas
  38. 7 1
      compiler/avr/aasmcpu.pas
  39. 1 1
      compiler/avr/agavrgas.pas
  40. 233 14
      compiler/avr/aoptcpu.pas
  41. 26 8
      compiler/avr/aoptcpub.pas
  42. 173 76
      compiler/avr/cgcpu.pas
  43. 13 4
      compiler/avr/cpubase.pas
  44. 13 10
      compiler/avr/cpuinfo.pas
  45. 3 1
      compiler/avr/cpunode.pas
  46. 60 45
      compiler/avr/cpupara.pas
  47. 11 2
      compiler/avr/cpupi.pas
  48. 24 10
      compiler/avr/raavrgas.pas
  49. 211 0
      compiler/avr/symcpu.pas
  50. 2 0
      compiler/browcol.pas
  51. 69 7
      compiler/cclasses.pas
  52. 30 3
      compiler/cfileutl.pas
  53. 8 13
      compiler/cg64f32.pas
  54. 9 2
      compiler/cgbase.pas
  55. 12 1
      compiler/cghlcpu.pas
  56. 174 28
      compiler/cgobj.pas
  57. 163 5
      compiler/cgutils.pas
  58. 4 0
      compiler/compinnr.inc
  59. 8 1
      compiler/constexp.pas
  60. 1 4
      compiler/crefs.pas
  61. 45 61
      compiler/cresstr.pas
  62. 9 1
      compiler/cstreams.pas
  63. 8 2
      compiler/dbgbase.pas
  64. 15 1
      compiler/dbgdwarf.pas
  65. 16 2
      compiler/dbgstabs.pas
  66. 17 3
      compiler/dbgstabx.pas
  67. 214 7
      compiler/defcmp.pas
  68. 24 28
      compiler/defutil.pas
  69. 335 0
      compiler/dirparse.pas
  70. 7 15
      compiler/finput.pas
  71. 22 17
      compiler/fmodule.pas
  72. 5 3
      compiler/fpcdefs.inc
  73. 11 1
      compiler/fppu.pas
  74. 211 0
      compiler/generic/symcpu.pas
  75. 29 221
      compiler/globals.pas
  76. 36 18
      compiler/globtype.pas
  77. 30 29
      compiler/hlcg2ll.pas
  78. 315 62
      compiler/hlcgobj.pas
  79. 22 10
      compiler/htypechk.pas
  80. 71 16
      compiler/i386/i386att.inc
  81. 68 13
      compiler/i386/i386atts.inc
  82. 71 16
      compiler/i386/i386int.inc
  83. 1 1
      compiler/i386/i386nop.inc
  84. 71 16
      compiler/i386/i386op.inc
  85. 140 85
      compiler/i386/i386prop.inc
  86. 807 9
      compiler/i386/i386tab.inc
  87. 211 0
      compiler/ia64/symcpu.pas
  88. 13 3
      compiler/jvm/cpubase.pas
  89. 4 2
      compiler/jvm/cpunode.pas
  90. 4 4
      compiler/jvm/dbgjasm.pas
  91. 23 14
      compiler/jvm/hlcgcpu.pas
  92. 9 6
      compiler/jvm/jvmdef.pas
  93. 7 34
      compiler/jvm/njvmadd.pas
  94. 6 2
      compiler/jvm/njvmcal.pas
  95. 44 26
      compiler/jvm/njvmcnv.pas
  96. 5 5
      compiler/jvm/njvmcon.pas
  97. 2 2
      compiler/jvm/njvmflw.pas
  98. 2 2
      compiler/jvm/njvminl.pas
  99. 1 1
      compiler/jvm/njvmld.pas
  100. 15 10
      compiler/jvm/njvmmem.pas

+ 17 - 3
.gitattributes

@@ -30,6 +30,7 @@ compiler/aarch64/ra64sri.inc svneol=native#text/plain
 compiler/aarch64/ra64sta.inc svneol=native#text/plain
 compiler/aarch64/ra64std.inc svneol=native#text/plain
 compiler/aarch64/ra64sup.inc svneol=native#text/plain
+compiler/aarch64/symcpu.pas svneol=native#text/plain
 compiler/aasmbase.pas svneol=native#text/plain
 compiler/aasmdata.pas svneol=native#text/plain
 compiler/aasmsym.pas svneol=native#text/plain
@@ -52,6 +53,7 @@ compiler/alpha/cputarg.pas svneol=native#text/plain
 compiler/alpha/radirect.pas svneol=native#text/plain
 compiler/alpha/rasm.pas svneol=native#text/plain
 compiler/alpha/rgcpu.pas svneol=native#text/plain
+compiler/alpha/symcpu.pas svneol=native#text/plain
 compiler/alpha/tgcpu.pas svneol=native#text/plain
 compiler/aopt.pas svneol=native#text/plain
 compiler/aoptbase.pas svneol=native#text/plain
@@ -102,6 +104,7 @@ compiler/arm/rarmsta.inc svneol=native#text/plain
 compiler/arm/rarmstd.inc svneol=native#text/plain
 compiler/arm/rarmsup.inc svneol=native#text/plain
 compiler/arm/rgcpu.pas svneol=native#text/plain
+compiler/arm/symcpu.pas svneol=native#text/plain
 compiler/asmutils.pas svneol=native#text/plain
 compiler/assemble.pas svneol=native#text/plain
 compiler/avr/aasmcpu.pas svneol=native#text/plain
@@ -134,6 +137,7 @@ compiler/avr/ravrsta.inc svneol=native#text/plain
 compiler/avr/ravrstd.inc svneol=native#text/plain
 compiler/avr/ravrsup.inc svneol=native#text/plain
 compiler/avr/rgcpu.pas svneol=native#text/plain
+compiler/avr/symcpu.pas svneol=native#text/plain
 compiler/browcol.pas svneol=native#text/plain
 compiler/bsdcompile -text
 compiler/catch.pas svneol=native#text/plain
@@ -164,6 +168,7 @@ compiler/dbgstabs.pas svneol=native#text/plain
 compiler/dbgstabx.pas svneol=native#text/plain
 compiler/defcmp.pas svneol=native#text/plain
 compiler/defutil.pas svneol=native#text/plain
+compiler/dirparse.pas svneol=native#text/plain
 compiler/elfbase.pas svneol=native#text/plain
 compiler/export.pas svneol=native#text/plain
 compiler/expunix.pas svneol=native#text/plain
@@ -174,6 +179,7 @@ compiler/fpcdefs.inc svneol=native#text/plain
 compiler/fppu.pas svneol=native#text/plain
 compiler/gendef.pas svneol=native#text/plain
 compiler/generic/cpuinfo.pas svneol=native#text/plain
+compiler/generic/symcpu.pas svneol=native#text/plain
 compiler/globals.pas svneol=native#text/plain
 compiler/globstat.pas svneol=native#text/pascal
 compiler/globtype.pas svneol=native#text/plain
@@ -282,6 +288,7 @@ compiler/ia64/aasmcpu.pas svneol=native#text/plain
 compiler/ia64/cpubase.pas svneol=native#text/plain
 compiler/ia64/cpuinfo.pas svneol=native#text/plain
 compiler/ia64/ia64reg.dat svneol=native#text/plain
+compiler/ia64/symcpu.pas svneol=native#text/plain
 compiler/impdef.pas svneol=native#text/plain
 compiler/import.pas svneol=native#text/plain
 compiler/jvm/aasmcpu.pas svneol=native#text/plain
@@ -309,6 +316,7 @@ compiler/jvm/njvmmem.pas svneol=native#text/plain
 compiler/jvm/njvmset.pas svneol=native#text/plain
 compiler/jvm/njvmtcon.pas svneol=native#text/plain
 compiler/jvm/njvmutil.pas svneol=native#text/plain
+compiler/jvm/njvmvmt.pas svneol=native#text/plain
 compiler/jvm/pjvm.pas svneol=native#text/plain
 compiler/jvm/rgcpu.pas svneol=native#text/plain
 compiler/jvm/rjvmcon.inc svneol=native#text/plain
@@ -318,6 +326,7 @@ compiler/jvm/rjvmrni.inc svneol=native#text/plain
 compiler/jvm/rjvmsri.inc svneol=native#text/plain
 compiler/jvm/rjvmstd.inc svneol=native#text/plain
 compiler/jvm/rjvmsup.inc svneol=native#text/plain
+compiler/jvm/symcpu.pas svneol=native#text/plain
 compiler/jvm/tgcpu.pas svneol=native#text/plain
 compiler/ldscript.pas svneol=native#text/plain
 compiler/link.pas svneol=native#text/plain
@@ -327,7 +336,6 @@ compiler/m68k/aoptcpu.pas svneol=native#text/plain
 compiler/m68k/aoptcpub.pas svneol=native#text/plain
 compiler/m68k/aoptcpud.pas svneol=native#text/plain
 compiler/m68k/cgcpu.pas svneol=native#text/plain
-compiler/m68k/cpuasm.pas svneol=native#text/plain
 compiler/m68k/cpubase.pas svneol=native#text/plain
 compiler/m68k/cpuinfo.pas svneol=native#text/plain
 compiler/m68k/cpunode.pas svneol=native#text/plain
@@ -341,6 +349,7 @@ compiler/m68k/n68kadd.pas svneol=native#text/plain
 compiler/m68k/n68kcal.pas svneol=native#text/plain
 compiler/m68k/n68kcnv.pas svneol=native#text/plain
 compiler/m68k/n68kmat.pas svneol=native#text/plain
+compiler/m68k/n68kmem.pas svneol=native#text/plain
 compiler/m68k/r68kcon.inc svneol=native#text/plain
 compiler/m68k/r68kgas.inc svneol=native#text/plain
 compiler/m68k/r68kgri.inc svneol=native#text/plain
@@ -354,6 +363,7 @@ compiler/m68k/r68ksup.inc svneol=native#text/plain
 compiler/m68k/ra68k.pas svneol=native#text/plain
 compiler/m68k/ra68kmot.pas svneol=native#text/plain
 compiler/m68k/rgcpu.pas svneol=native#text/plain
+compiler/m68k/symcpu.pas svneol=native#text/plain
 compiler/macho.pas svneol=native#text/plain
 compiler/machoutils.pas svneol=native#text/plain
 compiler/mips/aasmcpu.pas svneol=native#text/plain
@@ -395,6 +405,7 @@ compiler/mips/rmipssta.inc svneol=native#text/plain
 compiler/mips/rmipsstd.inc svneol=native#text/plain
 compiler/mips/rmipssup.inc svneol=native#text/plain
 compiler/mips/strinst.inc svneol=native#text/plain
+compiler/mips/symcpu.pas svneol=native#text/plain
 compiler/msg/errorct.msg svneol=native#text/plain
 compiler/msg/errord.msg svneol=native#text/plain
 compiler/msg/errorda.msg svneol=native#text/plain
@@ -465,8 +476,10 @@ compiler/ogmacho.pas svneol=native#text/plain
 compiler/ogmap.pas svneol=native#text/plain
 compiler/ognlm.pas svneol=native#text/plain
 compiler/optbase.pas svneol=native#text/plain
+compiler/optconstprop.pas svneol=native#text/pascal
 compiler/optcse.pas svneol=native#text/plain
 compiler/optdead.pas svneol=native#text/plain
+compiler/optdeadstore.pas svneol=native#text/pascal
 compiler/optdfa.pas svneol=native#text/plain
 compiler/options.pas svneol=native#text/plain
 compiler/optloop.pas svneol=native#text/plain
@@ -527,6 +540,7 @@ compiler/powerpc/rppcsri.inc svneol=native#text/plain
 compiler/powerpc/rppcstab.inc svneol=native#text/plain
 compiler/powerpc/rppcstd.inc svneol=native#text/plain
 compiler/powerpc/rppcsup.inc svneol=native#text/plain
+compiler/powerpc/symcpu.pas svneol=native#text/plain
 compiler/powerpc64/aoptcpu.pas svneol=native#text/plain
 compiler/powerpc64/aoptcpub.pas svneol=native#text/plain
 compiler/powerpc64/aoptcpuc.pas svneol=native#text/plain
@@ -563,6 +577,7 @@ compiler/powerpc64/rppcsri.inc svneol=native#text/plain
 compiler/powerpc64/rppcstab.inc svneol=native#text/plain
 compiler/powerpc64/rppcstd.inc svneol=native#text/plain
 compiler/powerpc64/rppcsup.inc svneol=native#text/plain
+compiler/powerpc64/symcpu.pas svneol=native#text/plain
 compiler/pp.lpi svneol=native#text/plain
 compiler/pp.pas svneol=native#text/plain
 compiler/pparautl.pas svneol=native#text/plain
@@ -641,6 +656,7 @@ compiler/sparc/rspstd.inc svneol=native#text/plain
 compiler/sparc/rspsup.inc svneol=native#text/plain
 compiler/sparc/spreg.dat svneol=native#text/plain
 compiler/sparc/strinst.inc svneol=native#text/plain
+compiler/sparc/symcpu.pas svneol=native#text/plain
 compiler/switches.pas svneol=native#text/plain
 compiler/symbase.pas svneol=native#text/plain
 compiler/symconst.pas svneol=native#text/plain
@@ -722,7 +738,6 @@ compiler/utils/fixnasm.pp svneol=native#text/plain
 compiler/utils/fixtab.pp svneol=native#text/plain
 compiler/utils/fpc.mpw svneol=native#text/plain
 compiler/utils/fpc.pp svneol=native#text/plain
-compiler/utils/fpcsubst.pp svneol=native#text/plain
 compiler/utils/fpimpdef.pp svneol=native#text/plain
 compiler/utils/gia64reg.pp svneol=native#text/plain
 compiler/utils/gppc386.pp svneol=native#text/plain
@@ -749,7 +764,6 @@ compiler/utils/ppuutils/ppujson.pp svneol=native#text/plain
 compiler/utils/ppuutils/ppuout.pp svneol=native#text/plain
 compiler/utils/ppuutils/ppuxml.pp svneol=native#text/plain
 compiler/utils/samplecfg svneol=native#text/plain
-compiler/utils/usubst.pp svneol=native#text/plain
 compiler/verbose.pas svneol=native#text/plain
 compiler/version.pas svneol=native#text/plain
 compiler/vis/aasmcpu.pas svneol=native#text/plain

+ 91 - 16
compiler/Makefile

@@ -1,8 +1,8 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2013/09/28]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2014-04-01 rev 27428]
 #
 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 jvm-java jvm-android i8086-msdos
+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
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku aix
 LIMIT83fs = go32v2 os2 emx watcom msdos
@@ -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),mipsel-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for mipsel-embedded, a sub-architecture (e.g. SUBARCH=pic32mx) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
 TARGETSUFFIX=$(OS_TARGET)
 SOURCESUFFIX=$(OS_SOURCE)
@@ -276,7 +282,7 @@ else
 ifeq ($(CPU_TARGET),i386)
 BINUTILSPREFIX=i686-linux-android-
 else
-ifeq ($(CPU_TARGET),mips)
+ifeq ($(CPU_TARGET),mipsel)
 BINUTILSPREFIX=mipsel-linux-android-
 endif
 endif
@@ -402,18 +408,24 @@ override LOCALOPT+=$(OPTLEVEL2)
 override RTLOPT+=$(OPTLEVEL2)
 override LOCALOPT+=$(LOCALOPTLEVEL2)
 override RTLOPT+=$(RTLOPTLEVEL2)
+override LOCALOPT+=$(OPTNEW)
+override RTLOPT+=$(OPTNEW)
 endif
 ifeq ($(CYCLELEVEL),3)
 override LOCALOPT+=$(OPTLEVEL3)
 override RTLOPT+=$(OPTLEVEL3)
 override LOCALOPT+=$(LOCALOPTLEVEL3)
 override RTLOPT+=$(RTLOPTLEVEL3)
+override LOCALOPT+=$(OPTNEW)
+override RTLOPT+=$(OPTNEW)
 endif
 ifeq ($(CYCLELEVEL),4)
 override LOCALOPT+=$(OPTLEVEL4)
 override RTLOPT+=$(OPTLEVEL4)
 override LOCALOPT+=$(LOCALOPTLEVEL4)
 override RTLOPT+=$(RTLOPTLEVEL4)
+override LOCALOPT+=$(OPTNEW)
+override RTLOPT+=$(OPTNEW)
 endif
 endif
 override OPT=
@@ -489,7 +501,7 @@ ifeq ($(PPC_TARGET),powerpc64)
 override LOCALOPT+=-Fuppcgen
 endif
 ifeq ($(PPC_TARGET),m68k)
-override LOCALOPT+=-dNOOPT
+override LOCALOPT+=
 endif
 ifeq ($(PPC_TARGET),sparc)
 override LOCALOPT+=
@@ -743,6 +755,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override TARGET_DIRS+=utils
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+override TARGET_DIRS+=utils
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 override TARGET_DIRS+=utils
 endif
@@ -962,6 +980,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override TARGET_PROGRAMS+=pp
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+override TARGET_PROGRAMS+=pp
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 override TARGET_PROGRAMS+=pp
 endif
@@ -1182,6 +1206,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
 endif
@@ -1401,6 +1431,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
 endif
@@ -1620,6 +1656,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override COMPILER_TARGETDIR+=.
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+override COMPILER_TARGETDIR+=.
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 override COMPILER_TARGETDIR+=.
 endif
@@ -1839,6 +1881,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
 endif
@@ -2229,7 +2277,7 @@ endif
 endif
 ifeq ($(OS_TARGET),msdos)
 STATICLIBPREFIX=
-STATICLIBEXT=.lib
+STATICLIBEXT=.a
 SHORTSUFFIX=d16
 endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
@@ -2421,6 +2469,7 @@ ASNAME=$(BINUTILSPREFIX)as
 LDNAME=$(BINUTILSPREFIX)ld
 ARNAME=$(BINUTILSPREFIX)ar
 RCNAME=$(BINUTILSPREFIX)rc
+NASMNAME=$(BINUTILSPREFIX)nasm
 ifndef ASPROG
 ifdef CROSSBINDIR
 ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
@@ -2449,10 +2498,18 @@ else
 ARPROG=$(ARNAME)
 endif
 endif
+ifndef NASMPROG
+ifdef CROSSBINDIR
+NASMPROG=$(CROSSBINDIR)/$(NASMNAME)$(SRCEXEEXT)
+else
+NASMPROG=$(NASMNAME)
+endif
+endif
 AS=$(ASPROG)
 LD=$(LDPROG)
 RC=$(RCPROG)
 AR=$(ARPROG)
+NASM=$(NASMPROG)
 ifdef inUnix
 PPAS=./ppas$(SRCBATCHEXT)
 else
@@ -2688,6 +2745,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 REQUIRE_PACKAGES_RTL=1
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+REQUIRE_PACKAGES_RTL=1
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 REQUIRE_PACKAGES_RTL=1
 endif
@@ -2877,18 +2940,24 @@ endif
 ifdef ACROSSCOMPILE
 override FPCOPT+=$(CROSSOPT)
 endif
-override COMPILER:=$(FPC) $(FPCOPT)
-ifeq (,$(findstring -s ,$(COMPILER)))
+override COMPILER:=$(strip $(FPC) $(FPCOPT))
+ifneq (,$(findstring -sh ,$(COMPILER)))
+UseEXECPPAS=1
+endif
+ifneq (,$(findstring -s ,$(COMPILER)))
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+UseEXECPPAS=1
+endif
+endif
+ifneq ($(UseEXECPPAS),1)
 EXECPPAS=
 else
-ifeq ($(FULL_SOURCE),$(FULL_TARGET))
 ifdef RUNBATCH
 EXECPPAS:=@$(RUNBATCH) $(PPAS)
 else
 EXECPPAS:=@$(PPAS)
 endif
 endif
-endif
 .PHONY: fpc_exes
 ifndef CROSSINSTALL
 ifneq ($(TARGET_PROGRAMS),)
@@ -3533,6 +3602,12 @@ endif
 ifeq ($(FULL_TARGET),mipsel-linux)
 TARGET_DIRS_UTILS=1
 endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+TARGET_DIRS_UTILS=1
+endif
 ifeq ($(FULL_TARGET),jvm-java)
 TARGET_DIRS_UTILS=1
 endif
@@ -3798,13 +3873,13 @@ ifdef RELEASE
 DOWPOCYCLE=1
 wpocycle:
 	$(RM) $(EXENAME)
-	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOCOLLECT)' compiler
+	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(strip $(LOCALOPT) $(OPTWPOCOLLECT) $(OPTNEW))' compiler
 	$(RM) $(EXENAME)
-	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(RTLOPT) $(OPTWPOPERFORM)' rtlclean rtl
-	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOPERFORM) $(subst pp1.wpo,pp2.wpo,$(OPTWPOCOLLECT))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(strip $(RTLOPT) $(OPTWPOPERFORM) $(OPTNEW))' rtlclean rtl
+	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(strip $(LOCALOPT) $(OPTNEW) $(OPTWPOPERFORM) $(subst pp1.wpo,pp2.wpo,$(OPTWPOCOLLECT)))' $(addsuffix _clean,$(ALLTARGETS)) compiler
 	$(MOVE) $(EXENAME) $(TEMPWPONAME1)
-	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(RTLOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' rtlclean rtl
-	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(LOCALOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(strip $(RTLOPT) $(OPTNEW) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM)))' rtlclean rtl
+	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(strip $(LOCALOPT) $(OPTNEW) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM)))' $(addsuffix _clean,$(ALLTARGETS)) compiler
 	$(COPY) $(EXENAME) $(TEMPWPONAME2)
 endif
 endif
@@ -3873,12 +3948,12 @@ cycle: override FPC=
 cycle:
 	$(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl CYCLELEVEL=1
 	$(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=1
-	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl CYCLELEVEL=
+	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl CYCLELEVEL=2
 	$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
 ifndef CROSSINSTALL
 	$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(RTLOPT) $(CROSSOPT)' rtlclean rtl CYCLELEVEL=3
 ifndef NoNativeBinaries
-	$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(LOCALOPT) $(CROSSOPT)' cycleclean compiler CYCLELEVEL=3
+	$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(strip $(LOCALOPT) $(CROSSOPT))' cycleclean compiler CYCLELEVEL=3
 endif
 endif
 endif

+ 14 - 8
compiler/Makefile.fpc

@@ -138,18 +138,24 @@ override LOCALOPT+=$(OPTLEVEL2)
 override RTLOPT+=$(OPTLEVEL2)
 override LOCALOPT+=$(LOCALOPTLEVEL2)
 override RTLOPT+=$(RTLOPTLEVEL2)
+override LOCALOPT+=$(OPTNEW)
+override RTLOPT+=$(OPTNEW)
 endif
 ifeq ($(CYCLELEVEL),3)
 override LOCALOPT+=$(OPTLEVEL3)
 override RTLOPT+=$(OPTLEVEL3)
 override LOCALOPT+=$(LOCALOPTLEVEL3)
 override RTLOPT+=$(RTLOPTLEVEL3)
+override LOCALOPT+=$(OPTNEW)
+override RTLOPT+=$(OPTNEW)
 endif
 ifeq ($(CYCLELEVEL),4)
 override LOCALOPT+=$(OPTLEVEL4)
 override RTLOPT+=$(OPTLEVEL4)
 override LOCALOPT+=$(LOCALOPTLEVEL4)
 override RTLOPT+=$(RTLOPTLEVEL4)
+override LOCALOPT+=$(OPTNEW)
+override RTLOPT+=$(OPTNEW)
 endif
 endif
 
@@ -255,7 +261,7 @@ endif
 
 # m68k specific
 ifeq ($(PPC_TARGET),m68k)
-override LOCALOPT+=-dNOOPT
+override LOCALOPT+=
 endif
 
 # Sparc specific
@@ -596,13 +602,13 @@ DOWPOCYCLE=1
 wpocycle:
 # don't use cycle_clean, it will delete the compiler utilities again
         $(RM) $(EXENAME)
-        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOCOLLECT)' compiler
+        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(strip $(LOCALOPT) $(OPTWPOCOLLECT) $(OPTNEW))' compiler
         $(RM) $(EXENAME)
-        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(RTLOPT) $(OPTWPOPERFORM)' rtlclean rtl
-        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOPERFORM) $(subst pp1.wpo,pp2.wpo,$(OPTWPOCOLLECT))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(strip $(RTLOPT) $(OPTWPOPERFORM) $(OPTNEW))' rtlclean rtl
+        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(strip $(LOCALOPT) $(OPTNEW) $(OPTWPOPERFORM) $(subst pp1.wpo,pp2.wpo,$(OPTWPOCOLLECT)))' $(addsuffix _clean,$(ALLTARGETS)) compiler
         $(MOVE) $(EXENAME) $(TEMPWPONAME1)
-        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(RTLOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' rtlclean rtl
-        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(LOCALOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(strip $(RTLOPT) $(OPTNEW) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM)))' rtlclean rtl
+        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(strip $(LOCALOPT) $(OPTNEW) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM)))' $(addsuffix _clean,$(ALLTARGETS)) compiler
         $(COPY) $(EXENAME) $(TEMPWPONAME2)
 endif
 endif
@@ -704,14 +710,14 @@ cycle:
         $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl CYCLELEVEL=1
         $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=1
 # ppcross<ARCH> (source native)
-        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl CYCLELEVEL=
+        $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl CYCLELEVEL=2
         $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
 # 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=$(LOCALOPT) $(CROSSOPT)' cycleclean compiler CYCLELEVEL=3
+        $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(strip $(LOCALOPT) $(CROSSOPT))' cycleclean compiler CYCLELEVEL=3
 endif
 endif
 

+ 2 - 1
compiler/aarch64/cpubase.pas

@@ -281,9 +281,10 @@ unit cpubase;
       }
       saved_standard_registers : array[0..9] of tsuperregister =
         (RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28);
+      saved_mm_registers : array[0..7] of tsuperregister = (RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15);
 
       { this is only for the generic code which is not used for this architecture }
-      saved_mm_registers : array[0..7] of tsuperregister = (RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15);
+      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
 
 {*****************************************************************************
                                   Helpers

+ 178 - 0
compiler/aarch64/symcpu.pas

@@ -0,0 +1,178 @@
+{
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Symbol table overrides 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 symcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  symtype,symdef,symsym;
+
+type
+  { defs }
+  tcpufiledef = class(tfiledef)
+  end;
+
+  tcpuvariantdef = class(tvariantdef)
+  end;
+
+  tcpuformaldef = class(tformaldef)
+  end;
+
+  tcpuforwarddef = class(tforwarddef)
+  end;
+
+  tcpuundefineddef = class(tundefineddef)
+  end;
+
+  tcpuerrordef = class(terrordef)
+  end;
+
+  tcpupointerdef = class(tpointerdef)
+  end;
+
+  tcpurecorddef = class(trecorddef)
+  end;
+
+  tcpuimplementedinterface = class(timplementedinterface)
+  end;
+
+  tcpuobjectdef = class(tobjectdef)
+  end;
+
+  tcpuclassrefdef = class(tclassrefdef)
+  end;
+
+  tcpuarraydef = class(tarraydef)
+  end;
+
+  tcpuorddef = class(torddef)
+  end;
+
+  tcpufloatdef = class(tfloatdef)
+  end;
+
+  tcpuprocvardef = class(tprocvardef)
+  end;
+
+  tcpuprocdef = class(tprocdef)
+  end;
+
+  tcpustringdef = class(tstringdef)
+  end;
+
+  tcpuenumdef = class(tenumdef)
+  end;
+
+  tcpusetdef = class(tsetdef)
+  end;
+
+  { syms }
+  tcpulabelsym = class(tlabelsym)
+  end;
+
+  tcpuunitsym = class(tunitsym)
+  end;
+
+  tcpunamespacesym = class(tnamespacesym)
+  end;
+
+  tcpuprocsym = class(tprocsym)
+  end;
+
+  tcputypesym = class(ttypesym)
+  end;
+
+  tcpufieldvarsym = class(tfieldvarsym)
+  end;
+
+  tcpulocalvarsym = class(tlocalvarsym)
+  end;
+
+  tcpuparavarsym = class(tparavarsym)
+  end;
+
+  tcpustaticvarsym = class(tstaticvarsym)
+  end;
+
+  tcpuabsolutevarsym = class(tabsolutevarsym)
+  end;
+
+  tcpupropertysym = class(tpropertysym)
+  end;
+
+  tcpuconstsym = class(tconstsym)
+  end;
+
+  tcpuenumsym = class(tenumsym)
+  end;
+
+  tcpusyssym = class(tsyssym)
+  end;
+
+
+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.
+

+ 5 - 1
compiler/aasmbase.pas

@@ -140,7 +140,11 @@ interface
          sec_objc_nlclasslist,
          sec_objc_catlist,
          sec_objc_nlcatlist,
-         sec_objc_protolist
+         sec_objc_protolist,
+         { stack segment for 16-bit DOS }
+         sec_stack,
+         { initial heap segment for 16-bit DOS }
+         sec_heap
        );
 
        TAsmSectionOrder = (secorder_begin,secorder_default,secorder_end);

+ 15 - 3
compiler/aasmtai.pas

@@ -137,7 +137,10 @@ interface
           aitconst_64bit_unaligned,
           { i8086 far pointer; emits: 'DW symbol, SEG symbol' }
           aitconst_farptr,
-          aitconst_got
+          { offset of symbol's GOT slot in GOT }
+          aitconst_got,
+          { offset of symbol itself from GOT }
+          aitconst_gotoff_symbol
         );
 
     const
@@ -273,7 +276,7 @@ interface
           top_shifterop : (shifterop : pshifterop);
       {$endif defined(arm) or defined(aarch64)}
       {$ifdef m68k}
-          top_regset : (regset:^tcpuregisterset);
+          top_regset : (dataregset,addrregset:^tcpuregisterset);
       {$endif m68k}
       {$ifdef jvm}
           top_single : (sval:single);
@@ -1838,6 +1841,8 @@ implementation
             result:=LengthSleb128(value);
           aitconst_half16bit:
             result:=2;
+          aitconst_gotoff_symbol:
+            result:=4;
           else
             internalerror(200603253);
         end;
@@ -2062,7 +2067,7 @@ implementation
                                TAI_LABEL
  ****************************************************************************}
 
-        constructor tai_label.Create(_labsym : tasmlabel);
+    constructor tai_label.Create(_labsym : tasmlabel);
       begin
         inherited Create;
         typ:=ait_label;
@@ -2626,6 +2631,13 @@ implementation
               top_regset:
                 dispose(regset);
 {$endif ARM}
+{$ifdef m68k}
+              top_regset:
+                begin
+                  dispose(dataregset);
+                  dispose(addrregset);
+                end;
+{$endif m68k}
 {$ifdef jvm}
               top_string:
                 freemem(pcval);

+ 95 - 43
compiler/aggas.pas

@@ -227,7 +227,7 @@ implementation
         );
 
       { Generic unaligned pseudo-instructions, seems ELF specific }
-      use_ua_elf_systems = [system_mipsel_linux,system_mipseb_linux];
+      use_ua_elf_systems = [system_mipsel_linux,system_mipseb_linux,system_mipsel_android,system_mipsel_embedded,system_mipseb_embedded];
       ait_ua_elf_const2str : array[aitconst_16bit_unaligned..aitconst_64bit_unaligned]
         of string[20]=(
           #9'.2byte'#9,#9'.4byte'#9,#9'.8byte'#9
@@ -347,7 +347,9 @@ implementation
           '.objc_nlclasslist',
           '.objc_catlist',
           '.obcj_nlcatlist',
-          '.objc_protolist'
+          '.objc_protolist',
+          '.stack',
+          '.heap'
         );
         secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
           '.text',
@@ -404,7 +406,9 @@ implementation
           '.objc_nlclasslist',
           '.objc_catlist',
           '.obcj_nlcatlist',
-          '.objc_protolist'
+          '.objc_protolist',
+          '.stack',
+          '.heap'
         );
       var
         sep     : string[3];
@@ -652,28 +656,18 @@ implementation
               if not(target_info.system in (systems_darwin+systems_aix)) then
                 begin
 {$ifdef m68k}
-                  if assigned(lasthp) and
-                      (
-                        (lasthp.typ=ait_instruction) and
-                        (taicpu(lasthp).opcode<>A_JMP)
-                      ) or
-                      (
-                        (lasthp.typ=ait_label)
-                      ) then
+                  if not use_op and (lastsectype=sec_code) then
                     begin
-                      if ispowerof2(alignment,i) then
-                        begin
-                          { the Coldfire manual suggests the TBF instruction for
-                            alignments, but somehow QEMU does not interpret that
-                            correctly... }
-                          {if current_settings.cputype in cpu_coldfire then
-                            instr:='0x51fc'
-                          else}
-                            instr:='0x4e71';
-                          AsmWrite(#9'.balignw '+tostr(alignment)+','+instr);
-                        end
-                      else
-                        internalerror(2012102101);
+                      if not ispowerof2(alignment,i) then
+                        internalerror(2014022201);
+                      { the Coldfire manual suggests the TBF instruction for
+                        alignments, but somehow QEMU does not interpret that
+                        correctly... }
+                      {if current_settings.cputype in cpu_coldfire then
+                        instr:='0x51fc'
+                      else}
+                        instr:='0x4e71';
+                      AsmWrite(#9'.balignw '+tostr(alignment)+','+instr);
                     end
                   else
                     begin
@@ -849,7 +843,8 @@ implementation
                        asmwrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
                        asmwrite(',');
                        asmwrite(tostr(tai_datablock(hp).size)+',');
-                       asmwrite('_data.bss_');
+                       asmwrite('_data.bss_,');
+                       asmwriteln(tostr(last_align));
                      end;
                  end
                else
@@ -961,6 +956,32 @@ implementation
                      AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
                      Asmln;
                    end;
+
+                 aitconst_gotoff_symbol:
+                   begin
+                     if (tai_const(hp).sym=nil) then
+                       InternalError(2014022601);
+                     case target_info.cpu of
+
+                       cpu_mipseb,cpu_mipsel:
+                         begin
+                           AsmWrite(#9'.gpword'#9);
+                           AsmWrite(tai_const(hp).sym.name);
+                         end;
+
+                       cpu_i386:
+                         begin
+                           AsmWrite(ait_const2str[aitconst_32bit]);
+                           AsmWrite(tai_const(hp).sym.name);
+                         end;
+                     else
+                       InternalError(2014022602);
+                     end;
+                     if (tai_const(hp).value<>0) then
+                       AsmWrite(tostr_with_plus(tai_const(hp).value));
+                     Asmln;
+                   end;
+
                  aitconst_uleb128bit,
                  aitconst_sleb128bit,
 {$ifdef cpu64bitaddr}
@@ -1013,14 +1034,13 @@ implementation
                          else if (constdef in ait_unaligned_consts) and
                                  (target_info.system in use_ua_elf_systems) then
                            AsmWrite(ait_ua_elf_const2str[constdef])
-                          else if not(target_info.system in systems_aix) or
-                            (constdef<>aitconst_64bit) then
-                           AsmWrite(ait_const2str[constdef])
+                         { we can also have unaligned pointers in packed record
+                           constants, which don't get translated into
+                           unaligned tai -> always use vbyte }
+                         else if target_info.system in systems_aix then
+                            AsmWrite(#9'.vbyte'#9+tostr(tai_const(hp).size)+',')
                          else
-                           { can't use .llong, because that forces 8 byte
-                             alignnment and we sometimes store addresses on
-                             4-byte aligned addresses (e.g. in the RTTI) }
-                           AsmWrite('.vbyte'#9'8,');
+                           AsmWrite(ait_const2str[constdef]);
                          l:=0;
                          t := '';
                          repeat
@@ -1336,11 +1356,17 @@ implementation
 {$endif arm}
            ait_set:
              begin
-               AsmWriteLn(#9'.set '+tai_set(hp).sym^+', '+tai_set(hp).value^);
+               if replaceforbidden then
+                 AsmWriteLn(#9'.set '+ReplaceForbiddenAsmSymbolChars(tai_set(hp).sym^)+', '+ReplaceForbiddenAsmSymbolChars(tai_set(hp).value^))
+               else
+                 AsmWriteLn(#9'.set '+tai_set(hp).sym^+', '+tai_set(hp).value^);
              end;
            ait_weak:
              begin
-               AsmWriteLn(#9'.weak '+tai_weak(hp).sym^);
+               if replaceforbidden then
+                 AsmWriteLn(#9'.weak '+ReplaceForbiddenAsmSymbolChars(tai_weak(hp).sym^))
+               else
+                 AsmWriteLn(#9'.weak '+tai_weak(hp).sym^);
              end;
            ait_symbol_end :
              begin
@@ -1518,6 +1544,7 @@ implementation
 
       begin
         pos:=0;
+        instring:=false;
         for i:=1 to hp.len do
           begin
             if pos=0 then
@@ -1667,9 +1694,12 @@ implementation
 
       for hal:=low(TasmlistType) to high(TasmlistType) do
         begin
-          AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
-          writetree(current_asmdata.asmlists[hal]);
-          AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
+          if not (current_asmdata.asmlists[hal].empty) then
+            begin
+              AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
+              writetree(current_asmdata.asmlists[hal]);
+              AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
+            end;
         end;
 
       { add weak symbol markers }
@@ -1681,14 +1711,16 @@ implementation
          (target_info.system in systems_darwin) then
         AsmWriteLn(#9'.subsections_via_symbols');
 
-      { "no executable stack" marker for Linux }
-      if (target_info.system in (systems_linux + systems_android)) and
+      { "no executable stack" marker }
+      { TODO: used by OpenBSD/NetBSD as well? }
+      if (target_info.system in (systems_linux + systems_android + systems_freebsd)) and
          not(cs_executable_stack in current_settings.moduleswitches) then
         begin
           AsmWriteLn('.section .note.GNU-stack,"",%progbits');
         end;
 
       AsmLn;
+      WriteExtraFooter;
 {$ifdef EXTDEBUG}
       if current_module.mainsource<>'' then
        Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource);
@@ -1791,7 +1823,10 @@ implementation
               end;
             sec_objc_image_info:
               begin
-                result:='.section __OBJC, __image_info, regular, no_dead_strip';
+                if (target_info.system in systems_objc_nfabi) then
+                  result:='.section __DATA,__objc_imageinfo,regular,no_dead_strip'
+                else
+                  result:='.section __OBJC, __image_info, regular, no_dead_strip';
                 exit;
               end;
             sec_objc_cstring_object:
@@ -1820,12 +1855,27 @@ implementation
                     exit;
                   end;
               end;
-            sec_objc_meth_var_names,
+            sec_objc_meth_var_types:
+              begin
+                if (target_info.system in systems_objc_nfabi) then
+                  begin
+                    result:='.section __TEXT,__objc_methtype,cstring_literals';
+                    exit
+                  end;
+              end;
+            sec_objc_meth_var_names:
+              begin
+                if (target_info.system in systems_objc_nfabi) then
+                  begin
+                    result:='.section __TEXT,__objc_methname,cstring_literals';
+                    exit
+                  end;
+              end;
             sec_objc_class_names:
               begin
                 if (target_info.system in systems_objc_nfabi) then
                   begin
-                    result:='.cstring';
+                    result:='.section __TEXT,__objc_classname,cstring_literals';
                     exit
                   end;
               end;
@@ -1969,7 +2019,9 @@ implementation
          sec_none (* sec_objc_nlclasslist *),
          sec_none (* sec_objc_catlist *),
          sec_none (* sec_objc_nlcatlist *),
-         sec_none (* sec_objc_protlist *)
+         sec_none (* sec_objc_protlist *),
+         sec_none (* sec_stack *),
+         sec_none (* sec_heap *)
         );
       begin
         Result := inherited SectionName (SecXTable [AType], AName, AOrder);

+ 8 - 7
compiler/agjasmin.pas

@@ -100,7 +100,7 @@ implementation
       SysUtils,
       cutils,cfileutl,systems,script,
       fmodule,finput,verbose,
-      symtype,symtable,jvmdef,
+      symtype,symcpu,symtable,jvmdef,
       itcpujas,cpubase,cpuinfo,cgutils,
       widestr
       ;
@@ -687,7 +687,8 @@ implementation
        if cs_asm_extern in current_settings.globalswitches then
          Replace(result,'$JASMINJAR',maybequoted(ScriptFixFileName(jasminjar)))
        else
-         Replace(result,'$JASMINJAR',ScriptFixFileName(jasminjar))
+         Replace(result,'$JASMINJAR',ScriptFixFileName(jasminjar));
+       Replace(result,'$EXTRAOPT',asmextraopt);
      end;
 
 
@@ -747,7 +748,7 @@ implementation
             not(po_classmethod in pd.procoptions) and
             not(pd.proctypeoption in [potype_constructor,potype_class_constructor])) then
           result:=result+'final ';
-        result:=result+pd.jvmmangledbasename(false);
+        result:=result+tcpuprocdef(pd).jvmmangledbasename(false);
       end;
 
 
@@ -912,7 +913,7 @@ implementation
 
     procedure TJasminAssembler.WriteProcDef(pd: tprocdef);
       begin
-        if not assigned(pd.exprasmlist) and
+        if not assigned(tcpuprocdef(pd).exprasmlist) and
            not(po_abstractmethod in pd.procoptions) and
            (not is_javainterface(pd.struct) or
             (pd.proctypeoption in [potype_unitinit,potype_unitfinalize])) then
@@ -922,10 +923,10 @@ implementation
         if jvmtypeneedssignature(pd) then
           begin
             AsmWrite('.signature "');
-            AsmWrite(pd.jvmmangledbasename(true));
+            AsmWrite(tcpuprocdef(pd).jvmmangledbasename(true));
             AsmWriteln('"');
           end;
-        WriteTree(pd.exprasmlist);
+        WriteTree(tcpuprocdef(pd).exprasmlist);
         AsmWriteln('.end method');
         AsmLn;
       end;
@@ -1223,7 +1224,7 @@ implementation
          id     : as_jvm_jasmin;
          idtxt  : 'Jasmin';
          asmbin : 'java';
-         asmcmd : '-jar $JASMINJAR $ASM -d $OBJDIR';
+         asmcmd : '-jar $JASMINJAR $ASM $EXTRAOPT -d $OBJDIR';
          supported_targets : [system_jvm_java32,system_jvm_android32];
          flags : [];
          labelprefix : 'L';

+ 4 - 2
compiler/alpha/cpunode.pas

@@ -32,7 +32,7 @@ unit cpunode;
 
     uses
        { generic nodes }
-       ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl
+       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)
@@ -48,7 +48,9 @@ unit cpunode;
        { this not really a node }
 //       naxpobj,
 //       naxpmat,
-//       naxpcnv
+//       naxpcnv,
+         { symtable }
+         symcpu
        ;
 
 end.

+ 211 - 0
compiler/alpha/symcpu.pas

@@ -0,0 +1,211 @@
+{
+    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.
+

+ 16 - 10
compiler/aopt.pas

@@ -267,13 +267,16 @@ Unit aopt;
         pass_1;
         While Assigned(BlockStart) Do
           Begin
-             if pass = 0 then
-               PrePeepHoleOpts;
-            { Peephole optimizations }
-             PeepHoleOptPass1;
-            { Only perform them twice in the first pass }
-             if pass = 0 then
-               PeepHoleOptPass1;
+            if (cs_opt_peephole in current_settings.optimizerswitches) then
+              begin
+                if pass = 0 then
+                  PrePeepHoleOpts;
+                { Peephole optimizations }
+                PeepHoleOptPass1;
+                { Only perform them twice in the first pass }
+                if pass = 0 then
+                  PeepHoleOptPass1;
+              end;
             If (cs_opt_asmcse in current_settings.optimizerswitches) Then
               Begin
 //                DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
@@ -283,9 +286,12 @@ Unit aopt;
       {          CSE;}
               End;
             { more peephole optimizations }
-            PeepHoleOptPass2;
-            { if pass = last_pass then }
-            PostPeepHoleOpts;
+            if (cs_opt_peephole in current_settings.optimizerswitches) then
+              begin
+                PeepHoleOptPass2;
+                { if pass = last_pass then }
+                PostPeepHoleOpts;
+              end;
             { free memory }
             clear;
             { continue where we left off, BlockEnd is either the start of an }

+ 25 - 10
compiler/aoptbase.pas

@@ -67,6 +67,7 @@ unit aoptbase;
         { false and sets last to nil                                     }
         Function GetLastInstruction(Current: tai; Var Last: tai): Boolean;
 
+        function SkipEntryExitMarker(current: tai; var next: tai): boolean;
 
         { processor dependent methods }
 
@@ -116,17 +117,16 @@ unit aoptbase;
 
 
   Function TAOptBase.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
-    Var Count: AWord;
-        TmpResult: Boolean;
+    Var
+      Count: longint;
     Begin
-      TmpResult := False;
-      Count := 0;
-      If (p1.typ = ait_instruction) and assigned(TInstr(p1).oper[0]) Then
-        Repeat
-          TmpResult := RegInOp(Reg, TInstr(p1).oper[Count]^);
-          Inc(Count)
-        Until (TInstr(p1).oper[Count]=nil) or (Count = MaxOps) or TmpResult;
-      RegInInstruction := TmpResult
+      result:=false;
+      if p1.typ<>ait_instruction then
+        exit;
+      for Count:=0 to TInstr(p1).ops-1 do
+        if RegInOp(Reg, TInstr(p1).oper[Count]^) then
+          exit(true);
+      result:=false;
     End;
 
 
@@ -246,6 +246,21 @@ unit aoptbase;
   End;
 
 
+  function TAOptBase.SkipEntryExitMarker(current: tai; var next: tai): boolean;
+    begin
+      result:=true;
+      if current.typ<>ait_marker then
+        exit;
+      next:=current;
+      while GetNextInstruction(next,next) do
+        begin
+          if (next.typ<>ait_marker) or not(tai_marker(next).Kind in [mark_Position,mark_BlockStart]) then
+            exit;
+        end;
+      result:=false;
+    end;
+
+
   Function TAOptBase.RegUsedBetween(reg : TRegister;p1,p2 : tai) : Boolean;
   Begin
     Result:=false;

+ 144 - 123
compiler/aoptobj.pas

@@ -330,6 +330,10 @@ Unit AoptObj;
 
         function getlabelwithsym(sym: tasmlabel): tai;
 
+        { Removes an instruction following hp1 (possibly with reg.deallocations in between),
+          if its opcode is A_NOP. }
+        procedure RemoveDelaySlot(hp1: tai);
+
         { peephole optimizer }
         procedure PrePeepHoleOpts;
         procedure PeepHoleOptPass1;
@@ -1115,7 +1119,7 @@ Unit AoptObj;
       function TAOptObj.RegUsedAfterInstruction(reg: Tregister; p: tai;
        var AllUsedRegs: TAllUsedRegs): Boolean;
        begin
-         AllUsedRegs[getregtype(reg)].Update(tai(p.Next));
+         AllUsedRegs[getregtype(reg)].Update(tai(p.Next),true);
          RegUsedAfterInstruction :=
            (AllUsedRegs[getregtype(reg)].IsUsed(reg)); { optimization and
               (not(getNextInstruction(p,p)) or
@@ -1180,6 +1184,24 @@ Unit AoptObj;
       end;
 
 
+    procedure TAOptObj.RemoveDelaySlot(hp1:tai);
+      var
+        hp2: tai;
+      begin
+        hp2:=tai(hp1.next);
+        while assigned(hp2) and (hp2.typ in SkipInstr) do
+          hp2:=tai(hp2.next);
+        if assigned(hp2) and (hp2.typ=ait_instruction) and
+          (taicpu(hp2).opcode=A_NOP) then
+          begin
+            asml.remove(hp2);
+            hp2.free;
+          end;
+        { Anything except A_NOP must be left in place: these instructions
+          execute before branch, so code stays correct if branch is removed. }
+      end;
+
+
     function TAOptObj.GetFinalDestination(hp: taicpu; level: longint): boolean;
       {traces sucessive jumps to their final destination and sets it, e.g.
        je l1                je l3
@@ -1284,139 +1306,138 @@ Unit AoptObj;
     procedure TAOptObj.PeepHoleOptPass1;
       var
         p,hp1,hp2 : tai;
+        stoploop:boolean;
       begin
-        p := BlockStart;
-        ClearUsedRegs;
-        while (p <> BlockEnd) Do
-          begin
-            { I'am not sure why this is done, UsedRegs should reflect the register usage before the instruction
-              If an instruction needs the information of this, it can easily create a TempUsedRegs (FK)
-            UpdateUsedRegs(tai(p.next));
-            }
-{$ifdef DEBUG_OPTALLOC}
-            if p.Typ=ait_instruction then
-              InsertLLItem(tai(p.Previous),p,tai_comment.create(strpnew(GetAllocationString(UsedRegs))));
-{$endif DEBUG_OPTALLOC}
-            if PeepHoleOptPass1Cpu(p) then
-              begin
-                UpdateUsedRegs(p);
-                continue;
-              end;
-            case p.Typ Of
-              ait_instruction:
+        repeat
+          stoploop:=true;
+          p := BlockStart;
+          ClearUsedRegs;
+          while (p <> BlockEnd) Do
+            begin
+              { I'am not sure why this is done, UsedRegs should reflect the register usage before the instruction
+                If an instruction needs the information of this, it can easily create a TempUsedRegs (FK)
+              UpdateUsedRegs(tai(p.next));
+              }
+  {$ifdef DEBUG_OPTALLOC}
+              if p.Typ=ait_instruction then
+                InsertLLItem(tai(p.Previous),p,tai_comment.create(strpnew(GetAllocationString(UsedRegs))));
+  {$endif DEBUG_OPTALLOC}
+              if PeepHoleOptPass1Cpu(p) then
                 begin
-                  { Handle Jmp Optimizations }
-                  if taicpu(p).is_jmp then
-                    begin
-                      { 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
-                        begin
-                          hp2:=p;
-                          while GetNextInstruction(hp2, hp1) and
-                                (hp1.typ <> ait_label) do
-                            if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
-                              begin
-                                if (hp1.typ = ait_instruction) and
-                                   taicpu(hp1).is_jmp and
-                                   (JumpTargetOp(taicpu(hp1))^.typ = top_ref) and
-                                   (JumpTargetOp(taicpu(hp1))^.ref^.symbol is TAsmLabel) then
-                                   TAsmLabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).decrefs;
-                                { don't kill start/end of assembler block,
-                                  no-line-info-start/end etc }
-                                if hp1.typ<>ait_marker then
-                                  begin
-                                    asml.remove(hp1);
-                                    hp1.free;
-                                  end
-                                else
-                                  hp2:=hp1;
-                              end
-                            else break;
-                          end;
-                      { remove jumps to a label coming right after them }
-                      if GetNextInstruction(p, hp1) then
-                        begin
-                          if 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)}
-                              hp2:=tai(p.next);
-                              asml.remove(hp2);
-                              hp2.free;
-{$endif SPARC or MIPS}
-                              hp2:=tai(hp1.next);
-                              asml.remove(p);
-                              p.free;
-                              p:=hp2;
-                              continue;
-                            end
-                          else
-                            begin
-                              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
+                  stoploop:=false;
+                  UpdateUsedRegs(p);
+                  continue;
+                end;
+              case p.Typ Of
+                ait_instruction:
+                  begin
+                    { Handle Jmp Optimizations }
+                    if taicpu(p).is_jmp then
+                      begin
+                        { 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
+                          begin
+                            hp2:=p;
+                            while GetNextInstruction(hp2, hp1) and
+                                  (hp1.typ <> ait_label) do
+                              if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
                                 begin
-                                  if (taicpu(p).opcode=aopt_condjmp)
-{$ifdef arm}
-                                    and (taicpu(p).condition<>C_None)
-{$endif arm}
-                                  then
+                                  if (hp1.typ = ait_instruction) and
+                                     taicpu(hp1).is_jmp and
+                                     (JumpTargetOp(taicpu(hp1))^.typ = top_ref) and
+                                     (JumpTargetOp(taicpu(hp1))^.ref^.symbol is TAsmLabel) then
+                                     TAsmLabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).decrefs;
+                                  { don't kill start/end of assembler block,
+                                    no-line-info-start/end etc }
+                                  if hp1.typ<>ait_marker then
                                     begin
-                                      taicpu(p).condition:=inverse_cond(taicpu(p).condition);
-                                      tai_label(hp2).labsym.decrefs;
-                                      JumpTargetOp(taicpu(p))^.ref^.symbol:=JumpTargetOp(taicpu(hp1))^.ref^.symbol;
-                                      { when freeing hp1, the reference count
-                                        isn't decreased, so don't increase
-
-                                       taicpu(p).oper[0]^.ref^.symbol.increfs;
-                                      }
-{$if defined(SPARC) or defined(MIPS)}
-                                      { Remove delay slot. Initially is is placed immediately after
-                                        branch, but RA can insert regallocs in between. }
-                                      hp2:=tai(hp1.next);
-                                      while assigned(hp2) and (hp2.typ in SkipInstr) do
-                                        hp2:=tai(hp2.next);
-                                      if assigned(hp2) and (hp2.typ=ait_instruction) and
-                                         (taicpu(hp2).opcode=A_NOP) then
-                                        begin
-                                          asml.remove(hp2);
-                                          hp2.free;
-                                        end
-                                      else
-                                        InternalError(2013070301);
-{$endif SPARC or MIPS}
+  {$if defined(SPARC) or defined(MIPS) }
+                                      if (hp1.typ=ait_instruction) and (taicpu(hp1).is_jmp) then
+                                        RemoveDelaySlot(hp1);
+  {$endif SPARC or MIPS }
                                       asml.remove(hp1);
                                       hp1.free;
-                                      GetFinalDestination(taicpu(p),0);
+                                      stoploop:=false;
                                     end
                                   else
-                                    begin
-                                      GetFinalDestination(taicpu(p),0);
-                                      p:=tai(p.next);
-                                      continue;
-                                    end;
+                                    hp2:=hp1;
                                 end
-                              else
-                                GetFinalDestination(taicpu(p),0);
+                              else break;
                             end;
-                        end;
-                    end
-                  else
-                  { All other optimizes }
-                    begin
-                    end; { if is_jmp }
-                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
+          { TODO: FIXME removing the first instruction fails}
+                                (p<>blockstart) then
+                              begin
+                                tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol).decrefs;
+  {$if defined(SPARC) or defined(MIPS)}
+                                RemoveDelaySlot(p);
+  {$endif SPARC or MIPS}
+                                hp2:=tai(hp1.next);
+                                asml.remove(p);
+                                p.free;
+                                p:=hp2;
+                                stoploop:=false;
+                                continue;
+                              end
+                            else if assigned(hp1) then
+                              begin
+                                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
+                                  begin
+                                    if (taicpu(p).opcode=aopt_condjmp)
+  {$ifdef arm}
+                                      and (taicpu(p).condition<>C_None)
+  {$endif arm}
+                                    then
+                                      begin
+                                        taicpu(p).condition:=inverse_cond(taicpu(p).condition);
+                                        tai_label(hp2).labsym.decrefs;
+                                        JumpTargetOp(taicpu(p))^.ref^.symbol:=JumpTargetOp(taicpu(hp1))^.ref^.symbol;
+                                        { when freeing hp1, the reference count
+                                          isn't decreased, so don't increase
+
+                                         taicpu(p).oper[0]^.ref^.symbol.increfs;
+                                        }
+  {$if defined(SPARC) or defined(MIPS)}
+                                        RemoveDelaySlot(hp1);
+  {$endif SPARC or MIPS}
+                                        asml.remove(hp1);
+                                        hp1.free;
+                                        stoploop:=false;
+                                        GetFinalDestination(taicpu(p),0);
+                                      end
+                                    else
+                                      begin
+                                        GetFinalDestination(taicpu(p),0);
+                                        p:=tai(p.next);
+                                        continue;
+                                      end;
+                                  end
+                                else
+                                  GetFinalDestination(taicpu(p),0);
+                              end;
+                          end;
+                      end
+                    else
+                    { All other optimizes }
+                      begin
+                      end; { if is_jmp }
+                  end;
+              end;
+              UpdateUsedRegs(p);
+              p:=tai(p.next);
             end;
-            UpdateUsedRegs(p);
-            p:=tai(p.next);
-          end;
+        until stoploop or not(cs_opt_level3 in current_settings.optimizerswitches);
       end;
 
 

+ 58 - 27
compiler/arm/aasmcpu.pas

@@ -770,8 +770,7 @@ implementation
             else
               result:=operand_read;
           A_STREX:
-            if opnr in [0,1,2] then
-              result:=operand_write;
+            result:=operand_write;
           else
             internalerror(200403151);
         end;
@@ -870,6 +869,26 @@ implementation
 *)
 
     procedure insertpcrelativedata(list,listtoinsert : TAsmList);
+
+      var
+        limit: longint;
+
+      { FLD/FST VFP instructions have a limit of +/- 1024, not 4096, this
+        function checks the next count instructions if the limit must be
+        decreased }
+      procedure CheckLimit(hp : tai;count : integer);
+        var
+          i : Integer;
+        begin
+          for i:=1 to count do
+            if SimpleGetNextInstruction(hp,hp) and
+               (tai(hp).typ=ait_instruction) and
+               ((taicpu(hp).opcode=A_FLDS) or
+                (taicpu(hp).opcode=A_FLDD) or
+                (taicpu(hp).opcode=A_VLDR)) then
+              limit:=254;
+        end;
+
       var
         curinspos,
         penalty,
@@ -877,7 +896,6 @@ implementation
         { increased for every data element > 4 bytes inserted }
         currentsize,
         extradataoffset,
-        limit: longint;
         curop : longint;
         curtai : tai;
         ai_label : tai_label;
@@ -1032,14 +1050,16 @@ implementation
                 end;
             end;
             { special case for case jump tables }
+            penalty:=0;
             if SimpleGetNextInstruction(curtai,hp) and
               (tai(hp).typ=ait_instruction) then
               begin
                 case taicpu(hp).opcode of
                   A_BX,
-                  A_LDR:
+                  A_LDR,
+                  A_ADD:
                     { approximation if we hit a case jump table }
-                    if ((taicpu(hp).opcode=A_LDR) and not(GenerateThumbCode or GenerateThumb2Code) and
+                    if ((taicpu(hp).opcode in [A_ADD,A_LDR]) and not(GenerateThumbCode or GenerateThumb2Code) and
                        (taicpu(hp).oper[0]^.typ=top_reg) and
                       (taicpu(hp).oper[0]^.reg=NR_PC)) or
                       ((taicpu(hp).opcode=A_BX) and (GenerateThumbCode) and
@@ -1059,18 +1079,33 @@ implementation
                           end;
                       end;
                   A_IT:
-                    if GenerateThumb2Code then
-                      penalty:=multiplier;
+                    begin
+                      if GenerateThumb2Code then
+                        penalty:=multiplier;
+                        { check if the next instruction fits as well
+                          or if we splitted after the it so split before }
+                        CheckLimit(hp,1);
+                    end;
                   A_ITE,
                   A_ITT:
-                    if GenerateThumb2Code then
-                      penalty:=2*multiplier;
+                    begin
+                      if GenerateThumb2Code then
+                        penalty:=2*multiplier;
+                        { check if the next two instructions fit as well
+                          or if we splitted them so split before }
+                        CheckLimit(hp,2);
+                    end;
                   A_ITEE,
                   A_ITTE,
                   A_ITET,
                   A_ITTT:
-                    if GenerateThumb2Code then
-                      penalty:=3*multiplier;
+                    begin
+                      if GenerateThumb2Code then
+                        penalty:=3*multiplier;
+                        { check if the next three instructions fit as well
+                          or if we splitted them so split before }
+                        CheckLimit(hp,3);
+                    end;
                   A_ITEEE,
                   A_ITTEE,
                   A_ITETE,
@@ -1079,22 +1114,17 @@ implementation
                   A_ITTET,
                   A_ITETT,
                   A_ITTTT:
-                    if GenerateThumb2Code then
-                      penalty:=4*multiplier;
-                  else
-                    penalty:=0;
+                    begin
+                      if GenerateThumb2Code then
+                        penalty:=4*multiplier;
+                        { check if the next three instructions fit as well
+                          or if we splitted them so split before }
+                      CheckLimit(hp,4);
+                    end;
                 end;
-              end
-            else
-              penalty:=0;
+              end;
 
-            { FLD/FST VFP instructions have a limit of +/- 1024, not 4096 }
-            if SimpleGetNextInstruction(curtai,hp) and
-               (tai(hp).typ=ait_instruction) and
-               ((taicpu(hp).opcode=A_FLDS) or
-                (taicpu(hp).opcode=A_FLDD) or
-                (taicpu(hp).opcode=A_VLDR)) then
-              limit:=254;
+            CheckLimit(curtai,1);
 
             { don't miss an insert }
             doinsert:=doinsert or
@@ -1138,7 +1168,7 @@ implementation
                 doinsert:=false;
                 current_asmdata.getjumplabel(l);
 
-                { align thumb in thumb .text section to 4 bytes }
+                { align jump in thumb .text section to 4 bytes }
                 if not(curdata.empty) and (GenerateThumbCode) then
                   curdata.Insert(tai_align.Create(4));
                 curdata.insert(taicpu.op_sym(A_B,l));
@@ -1166,7 +1196,7 @@ implementation
             else
               curtai:=tai(curtai.next);
           end;
-        { align thumb in thumb .text section to 4 bytes }
+        { align jump in thumb .text section to 4 bytes }
         if not(curdata.empty) and (GenerateThumbCode or GenerateThumb2Code) then
           curdata.Insert(tai_align.Create(4));
         list.concatlist(curdata);
@@ -2102,6 +2132,7 @@ implementation
 
       begin
         bytes:=$0;
+        i_field:=0;
         { evaluate and set condition code }
 
         { condition code allowed? }

+ 3 - 3
compiler/arm/agarmgas.pas

@@ -296,7 +296,7 @@ unit agarmgas;
             postfix:='.w';
 
           if taicpu(hp).ops = 0 then
-            s:=#9+gas_op2str[op]+' '+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
+            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
             s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
           else
@@ -356,7 +356,7 @@ unit agarmgas;
 
             idtxt  : 'AS';
             asmbin : 'as';
-            asmcmd : '-o $OBJ $ASM';
+            asmcmd : '-o $OBJ $EXTRAOPT $ASM';
             supported_targets : [system_arm_linux,system_arm_wince,system_arm_gba,system_arm_palmos,system_arm_nds,
                                  system_arm_embedded,system_arm_symbian,system_arm_android];
             flags : [af_needar,af_smartlink_sections];
@@ -370,7 +370,7 @@ unit agarmgas;
             id     : as_darwin;
             idtxt  : 'AS-Darwin';
             asmbin : 'as';
-            asmcmd : '-o $OBJ $ASM -arch $ARCH';
+            asmcmd : '-o $OBJ $EXTRAOPT $ASM -arch $ARCH';
             supported_targets : [system_arm_darwin];
             flags : [af_needar,af_smartlink_sections,af_supports_dwarf,af_stabs_use_function_absolute_addresses];
             labelprefix : 'L';

文件差异内容过多而无法显示
+ 322 - 291
compiler/arm/aoptcpu.pas


+ 1 - 0
compiler/arm/armatt.inc

@@ -8,6 +8,7 @@
 'adc',
 'add',
 'adf',
+'adr',
 'and',
 'b',
 'bic',

+ 1 - 0
compiler/arm/armatts.inc

@@ -329,5 +329,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufNONE,
 attsufNONE
 );

+ 2 - 0
compiler/arm/armins.dat

@@ -107,6 +107,8 @@ reg32,reg32,imm          \7\x2\x80                     ARM7
 
 [ADFcc]
 
+[ADRcc]
+
 [ANDcc]
 reg32,reg32,reg32        \4\x0\x00                     ARM7
 reg32,reg32,reg32,reg32  \5\x0\x00                     ARM7

+ 1 - 0
compiler/arm/armop.inc

@@ -8,6 +8,7 @@ A_ATN,
 A_ADC,
 A_ADD,
 A_ADF,
+A_ADR,
 A_AND,
 A_B,
 A_BIC,

+ 252 - 181
compiler/arm/cgcpu.pas

@@ -47,7 +47,6 @@ unit cgcpu;
 
         procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
         procedure a_call_reg(list : TAsmList;reg: tregister);override;
-        procedure a_call_ref(list : TAsmList;ref: treference);override;
 
         { move instructions }
         procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
@@ -94,7 +93,6 @@ unit cgcpu;
         function handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference; virtual;
 
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
-        procedure g_stackpointer_alloc(list : TAsmList;size : longint);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;
@@ -115,11 +113,13 @@ unit cgcpu;
 
         { mla for thumb requires that none of the registers is equal to r13/r15, this method ensures this }
         procedure safe_mla(list: TAsmList;op1,op2,op3,op4 : TRegister);
+
       end;
 
       { tcgarm is shared between normal arm and thumb-2 }
       tcgarm = class(tbasecgarm)
         procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+        procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); 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;
@@ -133,6 +133,9 @@ unit cgcpu;
         procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
 
         procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint); override;
+
+        {Multiply two 32-bit registers into lo and hi 32-bit registers}
+        procedure a_mul_reg_reg_pair(list: tasmlist; size: tcgsize; src1,src2,dstlo,dsthi: tregister); override;
       end;
 
       { normal arm cg }
@@ -177,6 +180,8 @@ unit cgcpu;
         procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg: tregister);override;
 
         procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint); override;
+
+        function handle_load_store(list: TAsmList; op: tasmop; oppostfix: toppostfix; reg: tregister; ref: treference): treference; override;
       end;
 
       tthumbcg64farm = class(tbasecg64farm)
@@ -681,28 +686,32 @@ unit cgcpu;
       end;
 
 
-    procedure tbasecgarm.a_call_ref(list : TAsmList;ref: treference);
-      begin
-        a_reg_alloc(list,NR_R12);
-        a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_R12);
-        a_call_reg(list,NR_R12);
-        a_reg_dealloc(list,NR_R12);
-        include(current_procinfo.flags,pi_do_call);
-      end;
-
-
      procedure tcgarm.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
        begin
           a_op_const_reg_reg(list,op,size,a,reg,reg);
        end;
 
+     procedure tcgarm.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
+       var
+         tmpreg,tmpresreg : tregister;
+         tmpref : treference;
+       begin
+         tmpreg:=getintregister(list,size);
+         tmpresreg:=getintregister(list,size);
+         tmpref:=a_internal_load_ref_reg(list,size,size,ref,tmpreg);
+         a_op_const_reg_reg(list,op,size,a,tmpreg,tmpresreg);
+         a_load_reg_ref(list,size,size,tmpresreg,tmpref);
+       end;
 
      procedure tcgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
        var
          so : tshifterop;
        begin
          if op = OP_NEG then
-             list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0))
+           begin
+             list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
+             maybeadjustresult(list,OP_NEG,size,dst);
+           end
          else if op = OP_NOT then
            begin
              if size in [OS_8, OS_16, OS_S8, OS_S16] then
@@ -725,7 +734,7 @@ unit cgcpu;
                list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
            end
          else
-             a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
+           a_op_reg_reg_reg(list,op,size,src,dst,dst);
        end;
 
 
@@ -891,12 +900,26 @@ unit cgcpu;
 
     procedure tcgarm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
       var
-        shift : byte;
+        shift, lsb, width : byte;
         tmpreg : tregister;
         so : tshifterop;
         l1 : longint;
         imm1, imm2: DWord;
       begin
+        optimize_op_const(size, op, a);
+        case op of
+          OP_NONE:
+            begin
+              if src <> dst then
+                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;
         ovloc.loc:=LOC_VOID;
         if {$ifopt R+}(a<>-2147483648) and{$endif} not setflags and is_shifter_const(-a,shift) then
           case op of
@@ -924,18 +947,13 @@ unit cgcpu;
               begin
                 if a>32 then
                   internalerror(200308294);
-                if a<>0 then
-                  begin
-                    shifterop_reset(so);
-                    so.shiftmode:=opshift2shiftmode(op);
-                    if op = OP_ROL then
-                      so.shiftimm:=32-a
-                    else
-                      so.shiftimm:=a;
-                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
-                  end
+                shifterop_reset(so);
+                so.shiftmode:=opshift2shiftmode(op);
+                if op = OP_ROL then
+                  so.shiftimm:=32-a
                 else
-                 list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+                  so.shiftimm:=a;
+                list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
               end;
             else
               {if (op in [OP_SUB, OP_ADD]) and
@@ -969,11 +987,7 @@ unit cgcpu;
         else
           begin
             { there could be added some more sophisticated optimizations }
-            if (op in [OP_MUL,OP_IMUL,OP_DIV,OP_IDIV]) and (a=1) then
-              a_load_reg_reg(list,size,size,src,dst)
-            else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
-              a_load_const_reg(list,size,0,dst)
-            else if (op in [OP_IMUL,OP_IDIV]) and (a=-1) then
+            if (op in [OP_IMUL,OP_IDIV]) and (a=-1) then
               a_op_reg_reg(list,OP_NEG,size,src,dst)
             { we do this here instead in the peephole optimizer because
               it saves us a register }
@@ -1003,23 +1017,48 @@ unit cgcpu;
               begin
                 { nothing to do on success }
               end
-            { x := y and 0; just clears a register, this sometimes gets generated on 64bit ops.
-              Just using mov x, #0 might allow some easier optimizations down the line. }
-            else if (op = OP_AND) and (dword(a)=0) then
-              list.concat(taicpu.op_reg_const(A_MOV,dst,0))
-            { x := y AND $FFFFFFFF just copies the register, so use mov for better optimizations }
-            else if (op = OP_AND) and (not(dword(a))=0) then
-              list.concat(taicpu.op_reg_reg(A_MOV,dst,src))
             { BIC clears the specified bits, while AND keeps them, using BIC allows to use a
               broader range of shifterconstants.}
             else if (op = OP_AND) and is_shifter_const(not(dword(a)),shift) then
               list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,not(dword(a))))
+            { Doing two shifts instead of two bics might allow the peephole optimizer to fold the second shift
+              into the following instruction}
+            else if (op = OP_AND) and
+                    is_continuous_mask(a, lsb, width) and
+                    ((lsb = 0) or ((lsb + width) = 32)) then
+              begin
+                shifterop_reset(so);
+                if (width = 16) and
+                   (lsb = 0) and
+                   (current_settings.cputype >= cpu_armv6) then
+                  list.concat(taicpu.op_reg_reg(A_UXTH,dst,src))
+                else if (width = 8) and
+                   (lsb = 0) and
+                   (current_settings.cputype >= cpu_armv6) then
+                  list.concat(taicpu.op_reg_reg(A_UXTB,dst,src))
+                else if lsb = 0 then
+                  begin
+                    so.shiftmode:=SM_LSL;
+                    so.shiftimm:=32-width;
+                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+                    so.shiftmode:=SM_LSR;
+                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,dst,so));
+                  end
+                else
+                  begin
+                    so.shiftmode:=SM_LSR;
+                    so.shiftimm:=lsb;
+                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+                    so.shiftmode:=SM_LSL;
+                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,dst,so));
+                  end;
+              end
             else if (op = OP_AND) and split_into_shifter_const(not(dword(a)), imm1, imm2) then
               begin
                 list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,imm1));
                 list.concat(taicpu.op_reg_reg_const(A_BIC,dst,dst,imm2));
               end
-            else if (op in [OP_ADD, OP_SUB, OP_OR]) and
+            else if (op in [OP_ADD, OP_SUB, OP_OR, OP_XOR]) and
                     not(cgsetflags or setflags) and
                     split_into_shifter_const(a, imm1, imm2) then
               begin
@@ -1047,7 +1086,7 @@ unit cgcpu;
         case op of
           OP_NEG,OP_NOT,
           OP_DIV,OP_IDIV:
-            internalerror(200308281);
+            internalerror(200308283);
           OP_SHL,
           OP_SHR,
           OP_SAR,
@@ -1139,20 +1178,40 @@ unit cgcpu;
         maybeadjustresult(list,op,size,dst);
       end;
 
+    procedure tcgarm.a_mul_reg_reg_pair(list: tasmlist; size: tcgsize; src1,src2,dstlo,dsthi: tregister);
+    var
+      asmop: tasmop;
+    begin
+      list.concat(tai_comment.create(strpnew('tcgarm.a_mul_reg_reg_pair called')));
+      case size of
+        OS_32:  asmop:=A_UMULL;
+        OS_S32: asmop:=A_SMULL;
+        else
+          InternalError(2014060802);
+      end;
+      { The caller might omit dstlo or dsthi, when he is not interested in it, we still
+        need valid registers everywhere. In case of dsthi = NR_NO we could fall back to
+        32x32=32 bit multiplication}
+      if (dstlo = NR_NO) then
+        dstlo:=getintregister(list,size);
+      if (dsthi = NR_NO) then
+        dsthi:=getintregister(list,size);
+      list.concat(taicpu.op_reg_reg_reg_reg(asmop, dstlo, dsthi, src1,src2));
+    end;
 
     function tbasecgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
       var
-        tmpreg : tregister;
+        tmpreg1,tmpreg2 : tregister;
         tmpref : treference;
         l : tasmlabel;
       begin
-        tmpreg:=NR_NO;
+        tmpreg1:=NR_NO;
 
         { Be sure to have a base register }
         if (ref.base=NR_NO) then
           begin
             if ref.shiftmode<>SM_None then
-              internalerror(200308294);
+              internalerror(2014020701);
             ref.base:=ref.index;
             ref.index:=NR_NO;
           end;
@@ -1181,7 +1240,7 @@ unit cgcpu;
              (ref.offset>255)
             )
            ) or
-           ((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and
+           (((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) or (op=A_VSTR) or (op=A_VLDR)) and
             ((ref.offset<-1020) or
              (ref.offset>1020) or
              ((abs(ref.offset) mod 4)<>0)
@@ -1205,76 +1264,80 @@ unit cgcpu;
             if (oppostfix in [PF_SB,PF_SH]) and
               (ref.base<>NR_NO) and (ref.index=NR_NO) then
               begin
-                tmpreg:=getintregister(list,OS_ADDR);
-                a_load_const_reg(list,OS_ADDR,0,tmpreg);
-                ref.index:=tmpreg;
+                tmpreg1:=getintregister(list,OS_ADDR);
+                a_load_const_reg(list,OS_ADDR,0,tmpreg1);
+                ref.index:=tmpreg1;
               end;
 
             { "hi" registers cannot be used as base or index }
             if (getsupreg(ref.base) in [RS_R8..RS_R12,RS_R14]) or
               ((ref.base=NR_R13) and (ref.index<>NR_NO)) then
               begin
-                tmpreg:=getintregister(list,OS_ADDR);
-                a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg);
-                ref.base:=tmpreg;
+                tmpreg1:=getintregister(list,OS_ADDR);
+                a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg1);
+                ref.base:=tmpreg1;
               end;
             if getsupreg(ref.index) in [RS_R8..RS_R14] then
               begin
-                tmpreg:=getintregister(list,OS_ADDR);
-                a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.index,tmpreg);
-                ref.index:=tmpreg;
+                tmpreg1:=getintregister(list,OS_ADDR);
+                a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.index,tmpreg1);
+                ref.index:=tmpreg1;
               end;
           end;
 
         { fold if there is base, index and offset, however, don't fold
           for vfp memory instructions because we later fold the index }
-        if not(op in [A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and
+        if not((op in [A_FLDS,A_FLDD,A_FSTS,A_FSTD]) or (op=A_VSTR) or (op=A_VLDR)) and
            (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
           begin
-            if tmpreg<>NR_NO then
-              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
+            if tmpreg1<>NR_NO then
+              begin
+                tmpreg2:=getintregister(list,OS_ADDR);
+                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg1,tmpreg2);
+                tmpreg1:=tmpreg2;
+              end
             else
               begin
-                tmpreg:=getintregister(list,OS_ADDR);
-                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
-                ref.base:=tmpreg;
+                tmpreg1:=getintregister(list,OS_ADDR);
+                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg1);
+                ref.base:=tmpreg1;
               end;
             ref.offset:=0;
           end;
 
         { floating point operations have only limited references
           we expect here, that a base is already set }
-        if (op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and (ref.index<>NR_NO) then
+        if ((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) or (op=A_VSTR) or (op=A_VLDR)) and (ref.index<>NR_NO) then
           begin
             if ref.shiftmode<>SM_none then
               internalerror(200309121);
-            if tmpreg<>NR_NO then
+            if tmpreg1<>NR_NO then
               begin
-                if ref.base=tmpreg then
+                if ref.base=tmpreg1 then
                   begin
                     if ref.signindex<0 then
-                      list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
+                      list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg1,tmpreg1,ref.index))
                     else
-                      list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg1,tmpreg1,ref.index));
                     ref.index:=NR_NO;
                   end
                 else
                   begin
-                    if ref.index<>tmpreg then
+                    if ref.index<>tmpreg1 then
                       internalerror(200403161);
                     if ref.signindex<0 then
-                      list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
+                      list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg1,ref.base,tmpreg1))
                     else
-                      list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
-                    ref.base:=tmpreg;
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg1,ref.base,tmpreg1));
+                    ref.base:=tmpreg1;
                     ref.index:=NR_NO;
                   end;
               end
             else
               begin
-                tmpreg:=getintregister(list,OS_ADDR);
-                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
-                ref.base:=tmpreg;
+                tmpreg1:=getintregister(list,OS_ADDR);
+                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg1,ref.base,ref.index));
+                ref.base:=tmpreg1;
                 ref.index:=NR_NO;
               end;
           end;
@@ -1740,15 +1803,20 @@ unit cgcpu;
          r : byte;
          mmregs,
          regs, saveregs : tcpuregisterset;
+         registerarea,
          r7offset,
          stackmisalignment : pint;
          postfix: toppostfix;
          imm1, imm2: DWord;
+         stack_parameters : Boolean;
       begin
         LocalSize:=align(LocalSize,4);
+        stack_parameters:=current_procinfo.procdef.stack_tainting_parameter(calleeside);
+
         { call instruction does not put anything on the stack }
-        stackmisalignment:=0;
+        registerarea:=0;
         tarmprocinfo(current_procinfo).stackpaddingreg:=High(TSuperRegister);
+        lastfloatreg:=RS_NO;
         if not(nostackframe) then
           begin
             firstfloatreg:=RS_NO;
@@ -1766,7 +1834,7 @@ unit cgcpu;
                         if firstfloatreg=RS_NO then
                           firstfloatreg:=r;
                         lastfloatreg:=r;
-                        inc(stackmisalignment,12);
+                        inc(registerarea,12);
                       end;
                 end;
               fpu_vfpv2,
@@ -1806,16 +1874,16 @@ unit cgcpu;
                    begin
                      for r:=RS_R0 to RS_R15 do
                        if r in regs then
-                         inc(stackmisalignment,4);
+                         inc(registerarea,4);
 
                      { if the stack is not 8 byte aligned, try to add an extra register,
                        so we can avoid the extra sub/add ...,#4 later (KB) }
-                     if ((stackmisalignment mod current_settings.alignment.localalignmax) <> 0) then
+                     if ((registerarea mod current_settings.alignment.localalignmax) <> 0) then
                        for r:=RS_R3 downto RS_R0 do
                          if not(r in regs) then
                            begin
                              regs:=regs+[r];
-                             inc(stackmisalignment,4);
+                             inc(registerarea,4);
                              tarmprocinfo(current_procinfo).stackpaddingreg:=r;
                              break;
                            end;
@@ -1853,7 +1921,7 @@ unit cgcpu;
                     for r:=RS_R0 to RS_R15 do
                       if r in saveregs then
                         begin
-                          inc(stackmisalignment,4);
+                          inc(registerarea,4);
                           if r<RS_FRAME_POINTER_REG then
                             inc(r7offset,4);
                         end;
@@ -1871,19 +1939,26 @@ unit cgcpu;
                       begin
                         for r:=RS_R8 to RS_R11 do
                           if r in saveregs then
-                            inc(stackmisalignment,4);
+                            inc(registerarea,4);
                         list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,saveregs),PF_FD));
                       end;
                   end;
               end;
 
-            stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
+            stackmisalignment:=registerarea mod current_settings.alignment.localalignmax;
             if (LocalSize<>0) or
                ((stackmisalignment<>0) and
                 ((pi_do_call in current_procinfo.flags) or
                  (po_assembler in current_procinfo.procdef.procoptions))) then
               begin
                 localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+                if stack_parameters and (pi_estimatestacksize in current_procinfo.flags) then
+                  begin
+                    if localsize>tarmprocinfo(current_procinfo).stackframesize then
+                      internalerror(2014030901)
+                    else
+                      localsize:=tarmprocinfo(current_procinfo).stackframesize-registerarea;
+                  end;
                 if is_shifter_const(localsize,shift) then
                   begin
                     a_reg_dealloc(list,NR_R12);
@@ -1966,6 +2041,7 @@ unit cgcpu;
          mmregs,
          saveregs,
          regs : tcpuregisterset;
+         registerarea,
          stackmisalignment: pint;
          paddingreg: TSuperRegister;
          mmpostfix: toppostfix;
@@ -1973,9 +2049,11 @@ unit cgcpu;
       begin
         if not(nostackframe) then
           begin
-            stackmisalignment:=0;
+            registerarea:=0;
             firstfloatreg:=RS_NO;
+            lastfloatreg:=RS_NO;
             mmregs:=[];
+            saveregs:=[];
             case current_settings.fputype of
               fpu_fpa,
               fpu_fpa10,
@@ -1991,7 +2069,7 @@ unit cgcpu;
                         lastfloatreg:=r;
                         { floating point register space is already included in
                           localsize below by calc_stackframe_size
-                         inc(stackmisalignment,12);
+                         inc(registerarea,12);
                         }
                       end;
                 end;
@@ -2083,13 +2161,13 @@ unit cgcpu;
                     ref.addressmode:=AM_PREINDEXED;
                     for r:=RS_R8 to RS_R11 do
                       if r in saveregs then
-                        inc(stackmisalignment,4);
+                        inc(registerarea,4);
                     regs:=regs-saveregs;
                   end;
               end;
             for r:=RS_R0 to RS_R15 do
               if r in regs then
-                inc(stackmisalignment,4);
+                inc(registerarea,4);
 
             { reapply the stack padding reg, in case there was one, see the complimentary
               comment in g_proc_entry() (KB) }
@@ -2100,9 +2178,9 @@ unit cgcpu;
               else
                 begin
                   regs:=regs+[paddingreg];
-                  inc(stackmisalignment,4);
+                  inc(registerarea,4);
                 end;
-            stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
+            stackmisalignment:=registerarea mod current_settings.alignment.localalignmax;
             if (current_procinfo.framepointer=NR_STACK_POINTER_REG) or
                (target_info.system in systems_darwin) then
               begin
@@ -2112,7 +2190,11 @@ unit cgcpu;
                     ((pi_do_call in current_procinfo.flags) or
                      (po_assembler in current_procinfo.procdef.procoptions))) then
                   begin
-                    localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+                    if pi_estimatestacksize in current_procinfo.flags then
+                      LocalSize:=tarmprocinfo(current_procinfo).stackframesize-registerarea
+                    else
+                      localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+
                     if is_shifter_const(LocalSize,shift) then
                       list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize))
                     else if split_into_shifter_const(localsize, imm1, imm2) then
@@ -2200,7 +2282,7 @@ unit cgcpu;
         if (tmpref.base=NR_NO) then
           begin
             if tmpref.shiftmode<>SM_None then
-              internalerror(200308294);
+              internalerror(2014020702);
             if tmpref.signindex<0 then
               internalerror(200312023);
             tmpref.base:=tmpref.index;
@@ -2268,6 +2350,7 @@ unit cgcpu;
         cg.a_label(current_procinfo.aktlocaldata,l);
         tmpref.symboldata:=current_procinfo.aktlocaldata.last;
         piclabel:=nil;
+        tmpreg:=NR_NO;
 
         indirection_done:=false;
         if assigned(ref.symbol) then
@@ -2812,12 +2895,6 @@ unit cgcpu;
       end;
 
 
-    procedure tbasecgarm.g_stackpointer_alloc(list: TAsmList; size: longint);
-      begin
-        internalerror(200807237);
-      end;
-
-
     function get_scalar_mm_op(fromsize,tosize : tcgsize) : tasmop;
       const
         convertop : array[OS_F32..OS_F128,OS_F32..OS_F128] of tasmop = (
@@ -3770,7 +3847,7 @@ unit cgcpu;
            OS_S32:
              oppostfix:=PF_None;
            else
-             InternalError(200308297);
+             InternalError(200308298);
          end;
          if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[fromsize]) then
            begin
@@ -3784,8 +3861,8 @@ unit cgcpu;
                    { only complicated references need an extra loadaddr }
                    if assigned(ref.symbol) or
                      (ref.index<>NR_NO) or
-                     (ref.offset<-255) or
-                     (ref.offset>4094) or
+                     (ref.offset<-124) or
+                     (ref.offset>124) or
                      { sometimes the compiler reused registers }
                      (reg=ref.index) or
                      (reg=ref.base) then
@@ -3817,8 +3894,8 @@ unit cgcpu;
                    { only complicated references need an extra loadaddr }
                    if assigned(ref.symbol) or
                      (ref.index<>NR_NO) or
-                     (ref.offset<-255) or
-                     (ref.offset>4092) or
+                     (ref.offset<-124) or
+                     (ref.offset>124) or
                      { sometimes the compiler reused registers }
                      (reg=ref.index) or
                      (reg=ref.base) then
@@ -3967,6 +4044,54 @@ unit cgcpu;
       end;
 
 
+    function tthumbcgarm.handle_load_store(list: TAsmList; op: tasmop; oppostfix: toppostfix; reg: tregister; ref: treference): treference;
+      var
+        href : treference;
+        tmpreg : TRegister;
+      begin
+        href:=ref;
+        if (op in [A_STR,A_STRB,A_STRH]) and
+           (abs(ref.offset)>124) then
+          begin
+            tmpreg:=getintregister(list,OS_ADDR);
+            a_loadaddr_ref_reg(list,ref,tmpreg);
+
+            reference_reset_base(href,tmpreg,0,ref.alignment);
+          end
+        else if (op=A_LDR) and
+           (oppostfix in [PF_None]) and
+           (ref.base<>NR_STACK_POINTER_REG)  and
+           (abs(ref.offset)>124) then
+          begin
+            tmpreg:=getintregister(list,OS_ADDR);
+            a_loadaddr_ref_reg(list,ref,tmpreg);
+
+            reference_reset_base(href,tmpreg,0,ref.alignment);
+          end
+        else if (op=A_LDR) and
+           (oppostfix in [PF_None]) and
+           (ref.base=NR_STACK_POINTER_REG) and
+           (abs(ref.offset)>1020) then
+          begin
+            tmpreg:=getintregister(list,OS_ADDR);
+            a_loadaddr_ref_reg(list,ref,tmpreg);
+
+            reference_reset_base(href,tmpreg,0,ref.alignment);
+          end
+        else if (op=A_LDR) and
+           ((oppostfix in [PF_SH,PF_SB]) or
+            (abs(ref.offset)>124)) then
+          begin
+            tmpreg:=getintregister(list,OS_ADDR);
+            a_loadaddr_ref_reg(list,ref,tmpreg);
+
+            reference_reset_base(href,tmpreg,0,ref.alignment);
+          end;
+
+        Result:=inherited handle_load_store(list, op, oppostfix, reg, href);
+      end;
+
+
     procedure tthumbcgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
       var
         tmpreg,overflowreg : tregister;
@@ -3978,7 +4103,7 @@ unit cgcpu;
           OP_NOT:
             list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
           OP_DIV,OP_IDIV:
-            internalerror(200308281);
+            internalerror(200308284);
           OP_ROL:
             begin
               if not(size in [OS_32,OS_S32]) then
@@ -4165,7 +4290,7 @@ unit cgcpu;
         rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
             [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
 
-        if current_settings.fputype=fpu_fpv4_s16 then
+        if current_settings.fputype in [fpu_fpv4_s16,fpu_vfpv3_d16] then
           rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBFD,
               [RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7,
                RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15
@@ -4252,7 +4377,7 @@ unit cgcpu;
            OS_S32:
              oppostfix:=PF_None;
            else
-             InternalError(200308297);
+             InternalError(200308299);
          end;
          if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[fromsize]) then
            begin
@@ -4396,11 +4521,11 @@ unit cgcpu;
           case op of
             OP_NEG,OP_NOT,
             OP_DIV,OP_IDIV:
-              internalerror(200308281);
+              internalerror(200308285);
             OP_SHL:
               begin
                 if a>32 then
-                  internalerror(200308294);
+                  internalerror(2014020703);
                 if a<>0 then
                   begin
                     shifterop_reset(so);
@@ -4414,7 +4539,7 @@ unit cgcpu;
             OP_ROL:
               begin
                 if a>32 then
-                  internalerror(200308294);
+                  internalerror(2014020704);
                 if a<>0 then
                   begin
                     shifterop_reset(so);
@@ -4428,7 +4553,7 @@ unit cgcpu;
             OP_ROR:
               begin
                 if a>32 then
-                  internalerror(200308294);
+                  internalerror(2014020705);
                 if a<>0 then
                   begin
                     shifterop_reset(so);
@@ -4582,7 +4707,7 @@ unit cgcpu;
         ovloc.loc:=LOC_VOID;
         case op of
            OP_NEG,OP_NOT:
-              internalerror(200308281);
+              internalerror(200308286);
            OP_ROL:
               begin
                 if not(size in [OS_32,OS_S32]) then
@@ -4709,6 +4834,7 @@ unit cgcpu;
         if not(nostackframe) then
           begin
             firstfloatreg:=RS_NO;
+            lastfloatreg:=RS_NO;
             { save floating point registers? }
             for r:=RS_F0 to RS_F7 do
               if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
@@ -4813,6 +4939,7 @@ unit cgcpu;
             stackmisalignment:=0;
             { restore floating point register }
             firstfloatreg:=RS_NO;
+            lastfloatreg:=RS_NO;
             { save floating point registers? }
             for r:=RS_F0 to RS_F7 do
               if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
@@ -4894,7 +5021,8 @@ unit cgcpu;
           list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
       end;
 
-   function tthumb2cgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
+
+    function tthumb2cgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
       var
         tmpreg : tregister;
         tmpref : treference;
@@ -4907,7 +5035,7 @@ unit cgcpu;
         if (ref.base=NR_NO) then
           begin
             if ref.shiftmode<>SM_None then
-              internalerror(200308294);
+              internalerror(2014020706);
             ref.base:=ref.index;
             ref.index:=NR_NO;
           end;
@@ -4937,9 +5065,10 @@ unit cgcpu;
              (ref.offset>255)
             )
            ) or
-           ((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and
+           (((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) or (op=A_VSTR) or (op=A_VLDR)) and
             ((ref.offset<-1020) or
              (ref.offset>1020) or
+             ((abs(ref.offset) mod 4)<>0) or
              { the usual pc relative symbol handling assumes possible offsets of +/- 4095 }
              assigned(ref.symbol)
             )
@@ -5017,7 +5146,7 @@ unit cgcpu;
 
         { floating point operations have only limited references
           we expect here, that a base is already set }
-        if (op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and (ref.index<>NR_NO) then
+        if ((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) or (op=A_VSTR) or (op=A_VLDR)) and (ref.index<>NR_NO) then
           begin
             if ref.shiftmode<>SM_none then
               internalerror(200309121);
@@ -5056,7 +5185,7 @@ unit cgcpu;
       end;
 
 
-     procedure tthumb2cgarm.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister; shuffle: pmmshuffle);
+    procedure tthumb2cgarm.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister; shuffle: pmmshuffle);
       var
         instr: taicpu;
       begin
@@ -5081,85 +5210,26 @@ unit cgcpu;
           end;
       end;
 
-     procedure tthumb2cgarm.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
-      var
-        href: treference;
-        tmpreg: TRegister;
-        so: tshifterop;
-      begin
-        href:=ref;
-
-        if (href.base<>NR_NO) and
-          (href.index<>NR_NO) then
-          begin
-            tmpreg:=getintregister(list,OS_INT);
-            if href.shiftmode<>SM_None then
-              begin
-                so.rs:=href.index;
-                so.shiftimm:=href.shiftimm;
-                so.shiftmode:=href.shiftmode;
-                list.concat(taicpu.op_reg_reg_shifterop(A_ADD,tmpreg,href.base,so));
-              end
-            else
-              a_op_reg_reg_reg(list,OP_ADD,OS_INT,href.index,href.base,tmpreg);
-
-            reference_reset_base(href,tmpreg,href.offset,0);
-          end;
-
-        if assigned(href.symbol) then
-          begin
-            tmpreg:=getintregister(list,OS_INT);
-            a_loadaddr_ref_reg(list,href,tmpreg);
-
-            reference_reset_base(href,tmpreg,0,0);
-          end;
 
+    procedure tthumb2cgarm.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
+      begin
         if fromsize=OS_F32 then
-          list.Concat(setoppostfix(taicpu.op_reg_ref(A_VLDR,reg,href), PF_F32))
+          handle_load_store(list,A_VLDR,PF_F32,reg,ref)
         else
-          list.Concat(setoppostfix(taicpu.op_reg_ref(A_VLDR,reg,href), PF_F64));
+          handle_load_store(list,A_VLDR,PF_F64,reg,ref);
       end;
 
-     procedure tthumb2cgarm.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
-      var
-        href: treference;
-        so: tshifterop;
-        tmpreg: TRegister;
-      begin
-        href:=ref;
-
-        if (href.base<>NR_NO) and
-          (href.index<>NR_NO) then
-          begin
-            tmpreg:=getintregister(list,OS_INT);
-            if href.shiftmode<>SM_None then
-              begin
-                so.rs:=href.index;
-                so.shiftimm:=href.shiftimm;
-                so.shiftmode:=href.shiftmode;
-                list.concat(taicpu.op_reg_reg_shifterop(A_ADD,tmpreg,href.base,so));
-              end
-            else
-              a_op_reg_reg_reg(list,OP_ADD,OS_INT,href.index,href.base,tmpreg);
-
-            reference_reset_base(href,tmpreg,href.offset,0);
-          end;
-
-        if assigned(href.symbol) then
-          begin
-            tmpreg:=getintregister(list,OS_INT);
-            a_loadaddr_ref_reg(list,href,tmpreg);
-
-            reference_reset_base(href,tmpreg,0,0);
-          end;
 
+    procedure tthumb2cgarm.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
+      begin
         if fromsize=OS_F32 then
-          list.Concat(setoppostfix(taicpu.op_reg_ref(A_VSTR,reg,href), PF_32))
+          handle_load_store(list,A_VSTR,PF_F32,reg,ref)
         else
-          list.Concat(setoppostfix(taicpu.op_reg_ref(A_VSTR,reg,href), PF_64));
+          handle_load_store(list,A_VSTR,PF_F64,reg,ref);
       end;
 
-     procedure tthumb2cgarm.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle);
+
+    procedure tthumb2cgarm.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle);
       begin
         if //(shuffle=nil) and
           (tosize=OS_F32) then
@@ -5168,7 +5238,8 @@ unit cgcpu;
           internalerror(2012100813);
       end;
 
-     procedure tthumb2cgarm.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle);
+
+    procedure tthumb2cgarm.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle);
       begin
         if //(shuffle=nil) and
           (fromsize=OS_F32) then

+ 17 - 28
compiler/arm/cpubase.pas

@@ -330,6 +330,7 @@ unit cpubase;
         (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
 
       { this is only for the generic code which is not used for this architecture }
+      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
       saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
 
       { Required parameter alignment when calling a routine declared as
@@ -570,35 +571,23 @@ unit cpubase;
         i : longint;
         imm : byte;
       begin
-        result:=false;
+        {Loading 0-255 is simple}
         if (d and $FF) = d then
-          begin
-            result:=true;
-            exit;
-          end;
-        if ((d and $FF00FF00) = 0) and
-           ((d shr 16)=(d and $FFFF)) then
-          begin
-            result:=true;
-            exit;
-          end;
-        if ((d and $00FF00FF) = 0) and
-           ((d shr 16)=(d and $FFFF)) then
-          begin
-            result:=true;
-            exit;
-          end;
-        if ((d shr 16)=(d and $FFFF)) and
-           ((d shr 8)=(d and $FF)) then
-          begin
-            result:=true;
-            exit;
-          end;
-        if is_shifter_const(d,imm) then
-          begin
-            result:=true;
-            exit;
-          end;
+          result:=true
+        { If top and bottom are equal, check if either all 4 bytes are equal
+          or byte 0 and 2 or byte 1 and 3 are equal }
+        else if ((d shr 16)=(d and $FFFF)) and
+                (
+                  ((d and $FF00FF00) = 0) or
+                  ((d and $00FF00FF) = 0) or
+                  ((d shr 8)=(d and $FF))
+                ) then
+          result:=true
+        {Can an 8-bit value be shifted accordingly?}
+        else if is_shifter_const(d,imm) then
+          result:=true
+        else
+          result:=false;
       end;
     
     function is_continuous_mask(d : aint;var lsb, width: byte) : boolean;

+ 10 - 0
compiler/arm/cpuelf.pas

@@ -168,6 +168,16 @@ implementation
 
     TCB_SIZE = 8;
 
+    { ELF header e_flags }
+    EF_ARM_BE8          = $00800000;
+    EF_ARM_EABIMASK     = $FF000000;
+    EF_ARM_EABI_UNKNOWN = $00000000;
+    EF_ARM_EABI_VER1    = $01000000;
+    EF_ARM_EABI_VER2    = $02000000;
+    EF_ARM_EABI_VER3    = $03000000;
+    EF_ARM_EABI_VER4    = $04000000;
+    EF_ARM_EABI_VER5    = $05000000;
+
   { Using short identifiers to save typing. This ARM thing has more relocations
     than it has instructions... }
   const

+ 159 - 90
compiler/arm/cpuinfo.pas

@@ -182,6 +182,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 +236,16 @@ 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,
 
       { TI - Fury Class - 64 K Flash, 16 K SRAM Devices }
       ct_lm3s1110,
@@ -383,91 +415,91 @@ Const
 
       { 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:'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),
 
       {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';	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:'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';	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:'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';	flashbase:$00000000;	flashsize:$00018000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1226FBD64_301';	controllerunitstr:'LPC122X';	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';	flashbase:$00000000;	flashsize:$00020000;	srambase:$10000000;	sramsize:$00002000),
+      (controllertypestr:'LPC1227FBD64_301';	controllerunitstr:'LPC122X';	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';	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_01';	controllerunitstr:'LPC13XX';	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:'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:'LPC1313FBD48_01';	controllerunitstr:'LPC13XX';	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),
@@ -511,6 +543,30 @@ Const
       (controllertypestr:'AT91SAM7X256';	controllerunitstr:'AT91SAM7x256';	flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
       (controllertypestr:'AT91SAM7XC256';	controllerunitstr:'AT91SAM7x256';	flashbase:$00000000;	flashsize:$00040000;	srambase:$00200000;	sramsize:$00010000),
 
+      { STM32F0 series }
+      (controllertypestr:'STM32F030C6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F030C8';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F030F4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F030K6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F030R8';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F050C4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050C6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050F4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050F6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050G4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050G6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050K4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F050K6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051C4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051C6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051C8';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F051K4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051K6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051K8';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00002000),
+      (controllertypestr:'STM32F051R4';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00004000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051R6';     controllerunitstr:'STM32F0XX';        flashbase:$08000000; flashsize:$00008000; srambase:$20000000; sramsize:$00001000),
+      (controllertypestr:'STM32F051R8';     controllerunitstr:'STM32F0XX';        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),
@@ -545,6 +601,17 @@ Const
       (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:'STM32F105R8';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105RB';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105RC';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105V8';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00010000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105VB';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F105VC';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107RB';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107RC';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00040000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107VB';     controllerunitstr:'STM32F10X_CL';     flashbase:$08000000; flashsize:$00020000; srambase:$20000000; sramsize:$00010000),
+      (controllertypestr:'STM32F107VC';     controllerunitstr:'STM32F10X_CL';     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),
@@ -643,7 +710,7 @@ 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_stackframe,cs_opt_nodecse,cs_opt_reorder_fields,cs_opt_fastmath,cs_opt_forcenostackframe];
 
    level1optimizerswitches = genericlevel1optimizerswitches;
    level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
@@ -663,30 +730,32 @@ Const
        CPUARM_HAS_DMB,        { CPU has memory barrier instructions (DMB, DSB, ISB)       }
        CPUARM_HAS_LDREX,
        CPUARM_HAS_IDIV,
-       CPUARM_HAS_THUMB2
+       CPUARM_HAS_THUMB_IDIV,
+       CPUARM_HAS_THUMB2,
+       CPUARM_HAS_UMULL
       );
 
  const
    cpu_capabilities : array[tcputype] of set of tcpuflags =
      ( { cpu_none     } [],
        { cpu_armv3    } [],
-       { cpu_armv4    } [],
-       { cpu_armv4t   } [CPUARM_HAS_BX],
-       { cpu_armv5    } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ],
-       { cpu_armv5t   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ],
-       { cpu_armv5te  } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP],
-       { cpu_armv5tej } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP],
-       { cpu_armv6    } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX],
-       { cpu_armv6k   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX],
-       { 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],
-       { cpu_armv6z   } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX],
+       { 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],
        { 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],
-       { 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],
-       { 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_DMB,CPUARM_HAS_THUMB2],
-       { 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_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_IDIV,CPUARM_HAS_DMB,CPUARM_HAS_THUMB2]
+       { 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]
      );
 
    { contains all CPU supporting any kind of thumb instruction set }

+ 3 - 1
compiler/arm/cpunode.pas

@@ -41,7 +41,9 @@ unit cpunode;
        narmcnv,
        narmcon,
        narmset,
-       narmmem
+       narmmem,
+       { symtable }
+       symcpu
        ;
 
 

+ 28 - 21
compiler/arm/cpupara.pas

@@ -44,8 +44,8 @@ unit cpupara;
           function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
          private
           procedure init_values(p: tabstractprocdef; side: tcallercallee; var curintreg,
-           curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword;
- var sparesinglereg: tregister);
+            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;
        end;
@@ -54,7 +54,9 @@ unit cpupara;
 
     uses
        verbose,systems,cutils,
-       defutil,symsym,symtable;
+       defutil,symsym,symcpu,symtable,
+       { PowerPC uses procinfo as well in cpupara, so this should not hurt }
+       procinfo;
 
 
     function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
@@ -298,8 +300,8 @@ unit cpupara;
         curfloatreg:=RS_F0;
         curmmreg:=RS_D0;
 
-        if GenerateThumbCode and (side=calleeside) then
-          cur_stack_offset:=(p as tprocdef).total_stackframe_size
+        if (side=calleeside) and (GenerateThumbCode or (pi_estimatestacksize in current_procinfo.flags)) then
+          cur_stack_offset:=(p as tcpuprocdef).total_stackframe_size
         else
           cur_stack_offset:=0;
         sparesinglereg := NR_NO;
@@ -581,13 +583,9 @@ unit cpupara;
                    begin
                      if paraloc^.loc=LOC_REFERENCE then
                        begin
-                         if GenerateThumbCode then
+                         paraloc^.reference.index:=current_procinfo.framepointer;
+                         if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
                            begin
-                             paraloc^.reference.index:=NR_STACK_POINTER_REG;
-                           end
-                         else
-                           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
@@ -714,16 +712,25 @@ unit cpupara;
               begin
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RETURN_REG;
-                if (result.intsize<>3) then
-                  begin
-                    paraloc^.size:=retcgsize;
-                    paraloc^.def:=result.def;
-                  end
-                else
-                  begin
-                    paraloc^.size:=OS_32;
-                    paraloc^.def:=u32inttype;
-                  end;
+                case result.IntSize of
+                  0:
+                    begin
+                      paraloc^.loc:=LOC_VOID;
+                      paraloc^.register:=NR_NO;
+                      paraloc^.size:=OS_NO;
+                      paraloc^.def:=voidpointertype;
+                    end;
+                  3:
+                    begin
+                      paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
+                    end;
+                  else
+                    begin
+                      paraloc^.size:=retcgsize;
+                      paraloc^.def:=result.def;
+                    end;
+                end;
               end;
           end;
       end;

+ 63 - 11
compiler/arm/cpupi.pas

@@ -48,6 +48,7 @@ unit cpupi;
           procedure init_framepointer; override;
           procedure generate_parameter_info;override;
           procedure allocate_got_register(list : TAsmList);override;
+          procedure postprocess_code;override;
        end;
 
 
@@ -57,10 +58,11 @@ unit cpupi;
        globals,systems,
        cpubase,
        tgobj,
-       symconst,symtype,symsym,paramgr,
+       symconst,symtype,symsym,symcpu,paramgr,
        cgutils,
        cgobj,
-       defutil;
+       defutil,
+       aasmcpu;
 
     procedure tarmprocinfo.set_first_temp_offset;
       var
@@ -99,7 +101,7 @@ unit cpupi;
           tg.setfirsttemp(maxpushedparasize);
 
         { estimate stack frame size }
-        if GenerateThumbCode then
+        if GenerateThumbCode or (pi_estimatestacksize in flags) then
           begin
             stackframesize:=maxpushedparasize+32;
             localsize:=0;
@@ -111,10 +113,14 @@ unit cpupi;
             localsize:=0;
             for i:=0 to procdef.parast.SymList.Count-1 do
               if tsym(procdef.parast.SymList[i]).typ=paravarsym then
-                if is_open_string(tabstractnormalvarsym(procdef.parast.SymList[i]).vardef) then
-                  inc(localsize,256)
-                else
-                  inc(localsize,tabstractnormalvarsym(procdef.parast.SymList[i]).getsize);
+                begin
+                  if tabstractnormalvarsym(procdef.parast.SymList[i]).varspez in [vs_var,vs_out,vs_constref] then
+                    inc(localsize,4)
+                  else if is_open_string(tabstractnormalvarsym(procdef.parast.SymList[i]).vardef) then
+                    inc(localsize,256)
+                  else
+                    inc(localsize,tabstractnormalvarsym(procdef.parast.SymList[i]).getsize);
+                end;
 
             inc(stackframesize,localsize);
 
@@ -141,7 +147,7 @@ unit cpupi;
          floatsavesize : aword;
          regs: tcpuregisterset;
       begin
-        if GenerateThumbCode then
+        if GenerateThumbCode or (pi_estimatestacksize in flags) then
           result:=stackframesize
         else
           begin
@@ -154,6 +160,7 @@ unit cpupi;
                 begin
                   { save floating point registers? }
                   firstfloatreg:=RS_NO;
+                  lastfloatreg:=RS_NO;
                   regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
                   for r:=RS_F0 to RS_F7 do
                     if r in regs then
@@ -186,9 +193,48 @@ unit cpupi;
             end;
             floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
             result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
-            floatregstart:=tg.direction*result+maxpushedparasize;
+            { Note: in cgcpu "-floatregstart" is subtracted -> reason based on
+                "adding floatregstart" to avoid double negation
+
+              tg.direction=1 -> no framepointer ->
+                1) save used int registers
+                2) allocate stacksize (= subtracting result, which is positive,
+                   from the stackpointer)
+                3) add floatregstart to the stackpointer to get the offset where
+                   to store the floating point registers (-> floatregstart
+                   should be positive)
+                4) store the floating point registers from this offset with IA
+                   (i.e., this offset and higher addresses -> offset should
+                    point to lower end of area)
+               -> newsp+(result) points to lower end of saved int registers area
+               -> newsp+(result-floatsavesize) points to lower end of float reg
+                  saving area
+
+              tg.direction=-1 -> with framepointer ->
+                1) save stack pointer in framepointer
+                2) save used int registers using stackpointer
+                3) allocate stacksize (= subtracting result, which is positive,
+                   from the stack pointer)
+                4) add floatregstart" to the framepointer to get the offset
+                   where to store the floating point registers (-> floatregstart
+                   should be negative)
+                5) store the floating point registers from this offset with IA
+                   (i.e., this offset and higher addresses -> offset should
+                    point to lower end of area)
+                o in this case, firsttemp starts right after the saved int
+                  registers area (or a bit further, because it's calculated for
+                  the worst-case scenario, when all non-volative integer
+                  registers have to be saved) -> we store the floating point
+                  registers between the last temp and the parameter pushing area
+               -> fp+(-result) points to the top of the stack (= end of
+                  parameter pushing area)
+               -> fp+(-result+maxpushedparasize) points to the start of the
+                  parameter pushing area = lower end of float reg saving area
+            }
             if tg.direction=1 then
-              dec(floatregstart,floatsavesize);
+              floatregstart:=result-aint(floatsavesize)
+            else
+              floatregstart:=-result+maxpushedparasize;
           end;
       end;
 
@@ -210,7 +256,7 @@ unit cpupi;
 
     procedure tarmprocinfo.generate_parameter_info;
       begin
-       procdef.total_stackframe_size:=stackframesize;
+       tcpuprocdef(procdef).total_stackframe_size:=stackframesize;
        inherited generate_parameter_info;
       end;
 
@@ -223,6 +269,12 @@ unit cpupi;
       end;
 
 
+    procedure tarmprocinfo.postprocess_code;
+      begin
+        { because of the limited constant size of the arm, all data access is done pc relative }
+        finalizearmcode(aktproccode,aktlocaldata);
+      end;
+
 begin
    cprocinfo:=tarmprocinfo;
 end.

+ 74 - 30
compiler/arm/narmadd.pas

@@ -32,10 +32,14 @@ interface
        tarmaddnode = class(tcgaddnode)
        private
           function  GetResFlags(unsigned:Boolean):TResFlags;
+          function  GetFpuResFlags:TResFlags;
        public
           function pass_1 : tnode;override;
+          function use_generic_mul32to64: boolean; override;
+          function use_generic_mul64bit: boolean; override;
        protected
           function first_addfloat: tnode; override;
+          procedure second_addordinal;override;
           procedure second_addfloat;override;
           procedure second_cmpfloat;override;
           procedure second_cmpordinal;override;
@@ -123,6 +127,27 @@ interface
       end;
 
 
+    function tarmaddnode.GetFpuResFlags:TResFlags;
+      begin
+        if nf_swapped in Flags then
+          internalerror(2014042001);
+        case NodeType of
+          equaln:
+            result:=F_EQ;
+          unequaln:
+            result:=F_NE;
+          ltn:
+            result:=F_MI;
+          lten:
+            result:=F_LS;
+          gtn:
+            result:=F_GT;
+          gten:
+            result:=F_GE;
+        end;
+      end;
+
+
     procedure tarmaddnode.second_addfloat;
       var
         op : TAsmOp;
@@ -139,8 +164,8 @@ interface
             begin
               { force fpureg as location, left right doesn't matter
                 as both will be in a fpureg }
-              location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
-              location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
 
               location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
               location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
@@ -246,7 +271,7 @@ interface
           swapleftright;
 
         location_reset(location,LOC_FLAGS,OS_NO);
-        location.resflags:=getresflags(true);
+        location.resflags:=getresflags(false);
 
         case current_settings.fputype of
           fpu_fpa,
@@ -255,8 +280,8 @@ interface
             begin
               { force fpureg as location, left right doesn't matter
                 as both will be in a fpureg }
-              location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
-              location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
 
               cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
               if nodetype in [equaln,unequaln] then
@@ -288,6 +313,7 @@ interface
                 left.location.register,right.location.register));
               cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
               current_asmdata.CurrAsmList.concat(taicpu.op_none(A_FMSTAT));
+              location.resflags:=GetFpuResFlags;
             end;
           fpu_fpv4_s16:
             begin
@@ -308,9 +334,6 @@ interface
             { this case should be handled already by pass1 }
             internalerror(2009112404);
         end;
-
-        location_reset(location,LOC_FLAGS,OS_NO);
-        location.resflags:=getresflags(false);
       end;
 
 
@@ -481,11 +504,7 @@ interface
           begin
             asmList := current_asmdata.CurrAsmList;
             pass_left_right;
-
-            if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
-              hlcg.location_force_reg(asmList,left.location,left.resultdef,left.resultdef,true);
-            if not(right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
-              hlcg.location_force_reg(asmList,right.location,right.resultdef,right.resultdef,true);
+            force_reg_left_right(true, (left.location.loc<>LOC_CONSTANT) and (right.location.loc<>LOC_CONSTANT));
             set_result_location_reg;
 
             { shortcuts to register64s }
@@ -507,19 +526,7 @@ interface
       var
         unsigned : boolean;
       begin
-        { prepare for MUL64 inlining }
-        if (not(cs_check_overflow in current_settings.localswitches)) and
-           (nodetype in [muln]) and
-           (is_64bitint(left.resultdef)) and
-           (not (GenerateThumbCode)) then
-          begin
-            result := nil;
-            firstpass(left);
-            firstpass(right);
-            expectloc := LOC_REGISTER;
-          end
-        else
-          result:=inherited pass_1;
+        result:=inherited pass_1;
 
         if not(assigned(result)) then
           begin
@@ -572,13 +579,13 @@ interface
                       procname:=procname+'_le';
                     gtn:
                       begin
-                        procname:=procname+'_le';
-                        notnode:=true;
+                        procname:=procname+'_lt';
+                        swapleftright;
                       end;
                     gten:
                       begin
-                        procname:=procname+'_lt';
-                        notnode:=true;
+                        procname:=procname+'_le';
+                        swapleftright;
                       end;
                     equaln:
                       procname:=procname+'_eq';
@@ -644,6 +651,43 @@ interface
         location.resflags:=getresflags(unsigned);
       end;
 
+    const
+      multops: array[boolean] of TAsmOp = (A_SMULL, A_UMULL);
+
+    procedure tarmaddnode.second_addordinal;
+      var
+        unsigned: boolean;
+      begin
+        if (nodetype=muln) and
+           is_64bit(resultdef) and
+           not(GenerateThumbCode) and
+           (CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) then
+          begin
+            pass_left_right;
+            force_reg_left_right(true, false);
+            set_result_location_reg;
+            unsigned:=not(is_signed(left.resultdef)) or
+                      not(is_signed(right.resultdef));
+            current_asmdata.CurrAsmList.Concat(
+              taicpu.op_reg_reg_reg_reg(multops[unsigned], location.register64.reglo, location.register64.reghi,
+                                        left.location.register,right.location.register));
+          end
+        else
+          inherited second_addordinal;
+      end;
+
+    function tarmaddnode.use_generic_mul32to64: boolean;
+      begin
+        result:=GenerateThumbCode or not(CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]);
+      end;
+
+    function tarmaddnode.use_generic_mul64bit: boolean;
+      begin
+        result:=GenerateThumbCode or
+          not(CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) or
+          (cs_check_overflow in current_settings.localswitches);
+      end;
+
 begin
   caddnode:=tarmaddnode;
 end.

+ 4 - 8
compiler/arm/narmcon.pas

@@ -77,8 +77,7 @@ interface
                 begin
                   current_procinfo.aktlocaldata.concat(Tai_real_32bit.Create(ts32real(value_real)));
                   { range checking? }
-                  if ((cs_check_range in current_settings.localswitches) or
-                    (cs_check_overflow in current_settings.localswitches)) and
+                  if floating_point_range_check_error and
                     (tai_real_32bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
                     Message(parser_e_range_check_error);
                 end;
@@ -91,8 +90,7 @@ interface
                     current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create(ts64real(value_real)));
 
                   { range checking? }
-                  if ((cs_check_range in current_settings.localswitches) or
-                    (cs_check_overflow in current_settings.localswitches)) and
+                  if floating_point_range_check_error and
                     (tai_real_64bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
                     Message(parser_e_range_check_error);
                end;
@@ -102,8 +100,7 @@ interface
                   current_procinfo.aktlocaldata.concat(Tai_real_80bit.Create(value_real,tfloatdef(resultdef).size));
 
                   { range checking? }
-                  if ((cs_check_range in current_settings.localswitches) or
-                    (cs_check_overflow in current_settings.localswitches)) and
+                  if floating_point_range_check_error and
                     (tai_real_80bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
                     Message(parser_e_range_check_error);
                 end;
@@ -113,8 +110,7 @@ interface
                   current_procinfo.aktlocaldata.concat(Tai_real_128bit.Create(value_real));
 
                   { range checking? }
-                  if ((cs_check_range in current_settings.localswitches) or
-                    (cs_check_overflow in current_settings.localswitches)) and
+                  if floating_point_range_check_error and
                     (tai_real_128bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
                     Message(parser_e_range_check_error);
                 end;

+ 31 - 3
compiler/arm/narminl.pas

@@ -60,7 +60,7 @@ implementation
     uses
       globtype,verbose,globals,
       cpuinfo, defutil,symdef,aasmdata,aasmcpu,
-      cgbase,cgutils,pass_2,
+      cgbase,cgutils,pass_1,pass_2,
       cpubase,ncgutil,cgobj,cgcpu, hlcgobj;
 
 {*****************************************************************************
@@ -75,7 +75,7 @@ implementation
           fpu_fpa10,
           fpu_fpa11:
             begin
-              location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
               location_copy(location,left.location);
               if left.location.loc=LOC_CFPUREGISTER then
                 begin
@@ -96,6 +96,11 @@ implementation
                  location.loc := LOC_MMREGISTER;
                end;
             end;
+          fpu_soft:
+            begin
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+              location_copy(location,left.location);
+            end
           else
             internalerror(2009111801);
         end;
@@ -106,7 +111,11 @@ implementation
     function tarminlinenode.first_abs_real : tnode;
       begin
         if (cs_fp_emulation in current_settings.moduleswitches) then
-          result:=inherited first_abs_real
+          begin
+            firstpass(left);
+            expectloc:=LOC_REGISTER;
+            first_abs_real:=nil;
+          end
         else
           begin
             case current_settings.fputype of
@@ -245,6 +254,13 @@ implementation
             end;
           fpu_fpv4_s16:
             current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32));
+          fpu_soft:
+            begin
+              if singleprec then
+                cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_32,tcgint($7fffffff),location.register)
+              else
+                cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_32,tcgint($7fffffff),location.registerhi);
+            end
         else
           internalerror(2009111402);
         end;
@@ -366,14 +382,26 @@ implementation
         opsize : tcgsize;
         hp : taicpu;
       begin
+        if GenerateThumbCode then
+          begin
+            inherited second_abs_long;
+            exit;
+          end;
+
         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);
+
         cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
         current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MOV,location.register,left.location.register), PF_S));
+
+        if GenerateThumb2Code then
+          current_asmdata.CurrAsmList.concat(taicpu.op_cond(A_IT,C_MI));
+
         current_asmdata.CurrAsmList.concat(setcondition(taicpu.op_reg_reg_const(A_RSB,location.register,location.register, 0), C_MI));
+
         cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
       end;
 

+ 123 - 79
compiler/arm/narmmat.pas

@@ -71,19 +71,25 @@ implementation
       var
         power  : longint;
       begin
-        if (right.nodetype=ordconstn) and
-          (nodetype=divn) and
-          (ispowerof2(tordconstnode(right).value,power) or
-           (tordconstnode(right).value=1) or
-           (tordconstnode(right).value=int64(-1))
-          ) and
-          not(is_64bitint(resultdef)) then
+        {We can handle all cases of constant division}
+        if not(cs_check_overflow in current_settings.localswitches) and
+           (right.nodetype=ordconstn) and
+           (nodetype=divn) and
+           not(is_64bitint(resultdef)) and
+           {Only the ARM and thumb2-isa support umull and smull, which are required for arbitary division by const optimization}
+           (GenerateArmCode or
+            GenerateThumb2Code or
+            (ispowerof2(tordconstnode(right).value,power) or
+            (tordconstnode(right).value=1) or
+            (tordconstnode(right).value=int64(-1))
+            )
+           ) then
           result:=nil
-        else if (current_settings.cputype in [cpu_armv7m,cpu_armv7em]) and
+        else if ((GenerateThumbCode or GenerateThumb2Code) and (CPUARM_HAS_THUMB_IDIV in cpu_capabilities[current_settings.cputype])) and
           (nodetype=divn) and
           not(is_64bitint(resultdef)) then
           result:=nil
-        else if (current_settings.cputype in [cpu_armv7m,cpu_armv7em]) and
+        else if ((GenerateThumbCode or GenerateThumb2Code) and (CPUARM_HAS_THUMB_IDIV in cpu_capabilities[current_settings.cputype])) and
           (nodetype=modn) and
           not(is_64bitint(resultdef)) then
           begin
@@ -172,7 +178,10 @@ implementation
                   end
                else
                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,numerator,resultreg)
-             end;
+             end
+           else {Everything else is handled the generic code}
+             cg.g_div_const_reg_reg(current_asmdata.CurrAsmList,def_cgsize(resultdef),
+               tordconstnode(right).value.svalue,numerator,resultreg);
          end;
 
 {
@@ -220,7 +229,7 @@ implementation
         secondpass(left);
         secondpass(right);
 
-        if (current_settings.cputype in [cpu_armv7m,cpu_armv7em]) and
+        if ((GenerateThumbCode or GenerateThumb2Code) and (CPUARM_HAS_THUMB_IDIV in cpu_capabilities[current_settings.cputype])) and
            (nodetype=divn) and
            not(is_64bitint(resultdef)) then
           begin
@@ -355,6 +364,15 @@ implementation
         procname: string[31];
         fdef : tdef;
       begin
+        if (current_settings.fputype=fpu_soft) and
+           (left.resultdef.typ=floatdef) then
+          begin
+            result:=nil;
+            firstpass(left);
+            expectloc:=LOC_REGISTER;
+            exit;
+          end;
+
         if (current_settings.fputype<>fpu_fpv4_s16) or
           (tfloatdef(resultdef).floattype=s32real) then
           exit(inherited pass_1);
@@ -400,7 +418,7 @@ implementation
           fpu_fpa10,
           fpu_fpa11:
             begin
-              location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,false);
               location:=left.location;
               current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSF,
                 location.register,left.location.register,0),
@@ -429,6 +447,19 @@ implementation
                 location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
               current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG,
                 location.register,left.location.register), PF_F32));
+            end;
+          fpu_soft:
+            begin
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+              location:=left.location;
+              case location.size of
+                OS_32:
+                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.register);
+                OS_64:
+                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.registerhi);
+              else
+                internalerror(2014033101);
+              end;
             end
           else
             internalerror(2009112602);
@@ -445,70 +476,80 @@ implementation
 
     procedure tarmshlshrnode.second_64bit;
       var
-        hreg64hi,hreg64lo,shiftreg:Tregister;
         v : TConstExprInt;
-        l1,l2,l3:Tasmlabel;
         so: tshifterop;
+        lreg, resreg: TRegister64;
 
       procedure emit_instr(p: tai);
         begin
           current_asmdata.CurrAsmList.concat(p);
         end;
 
-      {Reg1 gets shifted and moved into reg2, and is set to zero afterwards}
-      procedure shift_more_than_32(reg1, reg2: TRegister; shiftval: Byte ; sm: TShiftMode);
+      {This code is build like it gets called with sm=SM_LSR all the time, for SM_LSL dst* and src* have to be reversed}
+      procedure shift_less_than_32(srchi, srclo, dsthi, dstlo: TRegister; shiftval: Byte; sm: TShiftMode);
         begin
-          shifterop_reset(so); so.shiftimm:=shiftval - 32; so.shiftmode:=sm;
-          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg1, so));
-          emit_instr(taicpu.op_reg_const(A_MOV, reg1, 0));
-        end;
+          shifterop_reset(so);
 
-      procedure shift_less_than_32(reg1, reg2: TRegister; shiftval: Byte; shiftright: boolean);
-        begin
-          shifterop_reset(so); so.shiftimm:=shiftval;
-          if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
-          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg1, reg1, so));
+          so.shiftimm:=shiftval;
+          so.shiftmode:=sm;
+          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, dstlo, srclo, so));
+          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, dsthi, srchi, so));
 
-          if shiftright then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR;
+          if sm = SM_LSR then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR;
           so.shiftimm:=32-shiftval;
-          emit_instr(taicpu.op_reg_reg_reg_shifterop(A_ORR, reg1, reg1, reg2, so));
+          emit_instr(taicpu.op_reg_reg_reg_shifterop(A_ORR, dstlo, dstlo, srchi, so));
 
-          if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
-          so.shiftimm:=shiftval;
-          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg2, so));
         end;
 
-      procedure shift_by_variable(reg1, reg2, shiftval: TRegister; shiftright: boolean);
+      {This code is build like it gets called with sm=SM_LSR all the time, for SM_LSL dst* and src* have to be reversed
+       This will generate
+         mov   shiftval1, shiftval
+         cmp   shiftval1, #64
+         movcs shiftval1, #64
+         rsb   shiftval2, shiftval1, #32
+         mov   dstlo, srclo, lsr shiftval1
+         mov   dsthi, srchi, lsr shiftval1
+         orr   dstlo, srchi, lsl shiftval2
+         subs  shiftval2, shiftval1, #32
+         movpl dstlo, srchi, lsr shiftval2
+      }
+      procedure shift_by_variable(srchi, srclo, dsthi, dstlo, shiftval: TRegister; sm: TShiftMode);
         var
-          shiftval2:TRegister;
+          shiftval1,shiftval2:TRegister;
         begin
           shifterop_reset(so);
+          shiftval1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
           shiftval2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
 
+          cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, shiftval, shiftval1);
+
+          {The ARM barrel shifter only considers the lower 8 bits of a register for the shift}
           cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+          emit_instr(taicpu.op_reg_const(A_CMP, shiftval1, 64));
+          emit_instr(setcondition(taicpu.op_reg_const(A_MOV, shiftval1, 64), C_CS));
+          cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
 
-          {Do we shift more than 32 bits?}
-          emit_instr(setoppostfix(taicpu.op_reg_reg_const(A_RSB, shiftval2, shiftval, 32), PF_S));
+          {Calculate how much the upper register needs to be shifted left}
+          emit_instr(taicpu.op_reg_reg_const(A_RSB, shiftval2, shiftval1, 32));
 
-          {This part cares for 32 bits and more}
-          emit_instr(setcondition(taicpu.op_reg_reg_const(A_SUB, shiftval2, shiftval, 32), C_MI));
-          if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
-          so.rs:=shiftval2;
-          emit_instr(setcondition(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg1, so), C_MI));
+          so.shiftmode:=sm;
+          so.rs:=shiftval1;
+
+          {Shift and zerofill the hi+lo register}
+          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, dstlo, srclo, so));
+          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, dsthi, srchi, so));
 
-          {Less than 32 bits}
-          so.rs:=shiftval;
-          emit_instr(setcondition(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg2, so), C_PL));
-          if shiftright then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR;
+          {Fold in the lower 32-shiftval bits}
+          if sm = SM_LSR then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR;
           so.rs:=shiftval2;
-          emit_instr(setcondition(taicpu.op_reg_reg_reg_shifterop(A_ORR, reg2, reg2, reg1, so), C_PL));
+          emit_instr(taicpu.op_reg_reg_reg_shifterop(A_ORR, dstlo, dstlo, srchi, so));
 
-          cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+          cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+          emit_instr(setoppostfix(taicpu.op_reg_reg_const(A_SUB, shiftval2, shiftval1, 32), PF_S));
 
-          {Final adjustments}
-          if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
-          so.rs:=shiftval;
-          emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg1, reg1, so));
+          so.shiftmode:=sm;
+          emit_instr(setcondition(taicpu.op_reg_reg_shifterop(A_MOV, dstlo, srchi, so), C_PL));
+          cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
         end;
 
       begin
@@ -519,13 +560,17 @@ implementation
         end;
 
         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+        location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
 
         { load left operator in a register }
-        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);
-        hreg64hi:=left.location.register64.reghi;
-        hreg64lo:=left.location.register64.reglo;
-        location.register64.reghi:=hreg64hi;
-        location.register64.reglo:=hreg64lo;
+        if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
+           (left.location.size<>OS_64) then
+          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);
+
+        lreg := left.location.register64;
+        resreg := location.register64;
+        shifterop_reset(so);
 
         { shifting by a constant directly coded: }
         if (right.nodetype=ordconstn) then
@@ -537,8 +582,8 @@ implementation
                 begin
                   {Shift left by one by 2 simple 32bit additions}
                   cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
-                  emit_instr(setoppostfix(taicpu.op_reg_reg_reg(A_ADD, hreg64lo, hreg64lo, hreg64lo), PF_S));
-                  emit_instr(taicpu.op_reg_reg_reg(A_ADC, hreg64hi, hreg64hi, hreg64hi));
+                  emit_instr(setoppostfix(taicpu.op_reg_reg_reg(A_ADD, resreg.reglo, lreg.reglo, lreg.reglo), PF_S));
+                  emit_instr(taicpu.op_reg_reg_reg(A_ADC, resreg.reghi, lreg.reghi, lreg.reghi));
                   cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                 end
               else
@@ -546,42 +591,41 @@ implementation
                   {Shift right by first shifting hi by one and then using RRX (rotate right extended), which rotates through the carry}
                   shifterop_reset(so); so.shiftmode:=SM_LSR; so.shiftimm:=1;
                   cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
-                  emit_instr(setoppostfix(taicpu.op_reg_reg_shifterop(A_MOV, hreg64hi, hreg64hi, so), PF_S));
+                  emit_instr(setoppostfix(taicpu.op_reg_reg_shifterop(A_MOV, resreg.reghi, lreg.reghi, so), PF_S));
                   so.shiftmode:=SM_RRX; so.shiftimm:=0; {RRX does NOT have a shift amount}
-                  emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, hreg64lo, hreg64lo, so));
+                  emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, resreg.reglo, lreg.reglo, so));
                   cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                 end
-            {A 32bit shift just replaces a register and clears the other}
-            else if v = 32 then
+            {Clear one register and use the cg to generate a normal 32-bit shift}
+            else if v >= 32 then
+              if nodetype=shln then
               begin
-                if nodetype=shln then
-                  emit_instr(taicpu.op_reg_const(A_MOV, hreg64hi, 0))
-                else
-                  emit_instr(taicpu.op_reg_const(A_MOV, hreg64lo, 0));
-                location.register64.reghi:=hreg64lo;
-                location.register64.reglo:=hreg64hi;
+                emit_instr(taicpu.op_reg_const(A_MOV, resreg.reglo, 0));
+                cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,v.uvalue-32,lreg.reglo,resreg.reghi);
               end
-            {Shift LESS than 32}
-            else if (v < 32) and (v > 1) then
-              if nodetype=shln then
-                shift_less_than_32(hreg64hi, hreg64lo, v.uvalue, false)
               else
-                shift_less_than_32(hreg64lo, hreg64hi, v.uvalue, true)
-            {More than 32}
-            else if v > 32 then
+              begin
+                emit_instr(taicpu.op_reg_const(A_MOV, resreg.reghi, 0));
+                cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,v.uvalue-32,lreg.reghi,resreg.reglo);
+              end
+            {Shift LESS than 32, thats the tricky one}
+            else if (v < 32) and (v > 1) then
               if nodetype=shln then
-                shift_more_than_32(hreg64lo, hreg64hi, v.uvalue, SM_LSL)
+                shift_less_than_32(lreg.reglo, lreg.reghi, resreg.reglo, resreg.reghi, v.uvalue, SM_LSL)
               else
-                shift_more_than_32(hreg64hi, hreg64lo, v.uvalue, SM_LSR);
+                shift_less_than_32(lreg.reghi, lreg.reglo, resreg.reghi, resreg.reglo, v.uvalue, SM_LSR);
           end
         else
           begin
-            { force right operators in a register }
-            hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,false);
+            { force right operator into a register }
+            if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
+               (right.location.size<>OS_32) then
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,true);
+
             if nodetype = shln then
-              shift_by_variable(hreg64lo,hreg64hi,right.location.register, false)
+              shift_by_variable(lreg.reglo, lreg.reghi, resreg.reglo, resreg.reghi, right.location.register, SM_LSL)
             else
-              shift_by_variable(hreg64hi,hreg64lo,right.location.register, true);
+              shift_by_variable(lreg.reghi, lreg.reglo, resreg.reghi, resreg.reglo, right.location.register, SM_LSR);
           end;
       end;
 

+ 1 - 1
compiler/arm/narmset.pas

@@ -51,7 +51,7 @@ interface
 implementation
 
     uses
-      globals,constexp,defutil,
+      verbose,globals,constexp,defutil,
       aasmbase,aasmtai,aasmdata,aasmcpu,
       cpubase,cpuinfo,
       cgutils,cgobj,ncgutil,

+ 5 - 0
compiler/arm/raarmgas.pas

@@ -556,6 +556,11 @@ Unit raarmgas;
                oper.InitRef;
                oper.opr.ref.symbol:=hl;
                oper.opr.ref.base:=NR_PC;
+               if (actasmtoken in [AS_PLUS, AS_MINUS]) then
+                 begin
+                   l:=BuildConstExpression(true,false);
+                   oper.opr.ref.offset:=l;
+                 end;
              end;
           end;
 

+ 46 - 2
compiler/arm/rgcpu.pas

@@ -43,6 +43,8 @@ unit rgcpu;
        public
          procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
          procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+         function do_spill_replace(list : TAsmList;instr : taicpu;
+           orgreg : tsuperregister;const spilltemp : treference) : boolean;override;
          procedure add_constraints(reg:tregister);override;
          function  get_spill_subreg(r:tregister) : tsubregister;override;
        end;
@@ -126,9 +128,10 @@ unit rgcpu;
                     end;
                 end;
               A_MLA,
+              A_MLS,
               A_MUL:
                 begin
-                  if current_settings.cputype<cpu_armv6 then
+                  if (current_settings.cputype<cpu_armv6) and (taicpu(p).opcode<>A_MLS) then
                     add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
                    add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R13);
                    add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R15);
@@ -136,7 +139,7 @@ unit rgcpu;
                    add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R15);
                    add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R13);
                    add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R15);
-                   if taicpu(p).opcode=A_MLA then
+                   if taicpu(p).opcode<>A_MUL then
                      begin
                        add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R13);
                        add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R15);
@@ -279,6 +282,47 @@ unit rgcpu;
       end;
 
 
+    function trgcpu.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+      var
+        b : byte;
+      begin
+        result:=false;
+        if abs(spilltemp.offset)>4095 then
+          exit;
+
+        if GenerateThumbCode and
+          (abs(spilltemp.offset)>1020) then
+          exit;
+
+        { Replace 'mov  dst,orgreg' with 'ldr  dst,spilltemp'
+          and     'mov  orgreg,src' with 'str  dst,spilltemp' }
+        with instr do
+          begin
+            if (opcode=A_MOV) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
+              begin
+                if (getregtype(oper[0]^.reg)=regtype) and
+                   (get_alias(getsupreg(oper[0]^.reg))=orgreg) and
+                   (get_alias(getsupreg(oper[1]^.reg))<>orgreg) then
+                  begin
+                    { str expects the register in oper[0] }
+                    instr.loadreg(0,oper[1]^.reg);
+                    instr.loadref(1,spilltemp);
+                    opcode:=A_STR;
+                    result:=true;
+                  end
+                else if (getregtype(oper[1]^.reg)=regtype) and
+                   (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
+                   (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
+                  begin
+                    instr.loadref(1,spilltemp);
+                    opcode:=A_LDR;
+                    result:=true;
+                  end;
+              end;
+          end;
+      end;
+
+
     procedure trgcpu.add_constraints(reg:tregister);
       var
         supreg,i : Tsuperregister;

+ 215 - 0
compiler/arm/symcpu.pas

@@ -0,0 +1,215 @@
+{
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Symbol table overrides for ARM
+
+    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,globtype;
+
+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)
+    { the arm paramanager might need to know the total size of the stackframe
+      to avoid cyclic unit dependencies or global variables, this infomatation is
+      stored in total_stackframe_size }
+    total_stackframe_size : aint;
+  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.
+

+ 32 - 3
compiler/assemble.pas

@@ -297,7 +297,7 @@ Implementation
         var
           dir : TRawByteSearchRec;
         begin
-          if findfirst(s+source_info.dirsep+'*'+AExt,faAnyFile,dir) = 0 then
+          if findfirst(FixPath(s,false)+'*'+AExt,faAnyFile,dir) = 0 then
             begin
               repeat
                 DeleteFile(s+source_info.dirsep+dir.name);
@@ -373,7 +373,10 @@ Implementation
         result:=true;
         if (cs_asm_extern in current_settings.globalswitches) then
           begin
-            AsmRes.AddAsmCommand(command,para,name);
+            if SmartAsm then
+              AsmRes.AddAsmCommand(command,para,Name+'('+TosTr(SmartFilesCount)+')')
+            else
+              AsmRes.AddAsmCommand(command,para,name);
             exit;
           end;
         try
@@ -606,13 +609,36 @@ Implementation
            Replace(result,'$NOWARN','')
          else
            Replace(result,'$NOWARN','-W');
+         Replace(result,'$EXTRAOPT',asmextraopt);
       end;
 
 
     procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
+{$ifdef hasamiga}
+      var
+        tempFileName: TPathStr;
+{$endif}
       begin
         if SmartAsm then
          NextSmartName(Aplace);
+{$ifdef hasamiga}
+        { on Amiga/MorphOS try to redirect .s files to the T: assign, which is
+          for temp files, and usually (default setting) located in the RAM: drive.
+          This highly improves assembling speed for complex projects like the
+          compiler itself, especially on hardware with slow disk I/O.
+          Consider this as a poor man's pipe on Amiga, because real pipe handling
+          would be much more complex and error prone to implement. (KB) }
+        if (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) then
+         begin
+          { try to have an unique name for the .s file }
+          tempFileName:=HexStr(GetProcessID shr 4,7)+ExtractFileName(AsmFileName);
+{$ifndef morphos}
+          { old Amiga RAM: handler only allows filenames up to 30 char }
+          if Length(tempFileName) < 30 then
+{$endif}
+          AsmFileName:='T:'+tempFileName;
+         end;
+{$endif}
 {$ifdef hasunix}
         if DoPipe then
          begin
@@ -891,7 +917,6 @@ Implementation
                   move(pstart^,hs[1],len);
                   hs[0]:=chr(len);
                   sym:=objdata.symbolref(hs);
-                  have_first_symbol:=true;
                   { Second symbol? }
                   if assigned(relocsym) then
                     begin
@@ -1358,6 +1383,8 @@ Implementation
         relative_reloc: boolean;
       begin
         fillchar(zerobuf,sizeof(zerobuf),0);
+        fillchar(objsym,sizeof(objsym),0);
+        fillchar(objsymend,sizeof(objsymend),0);
         { main loop }
         while assigned(hp) do
          begin
@@ -1461,6 +1488,8 @@ Implementation
                        { Required for DWARF2 support under Windows }
                        ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_SECREL32);
                      end;
+                   aitconst_gotoff_symbol:
+                     ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF);
                    aitconst_uleb128bit,
                    aitconst_sleb128bit :
                      begin

+ 7 - 1
compiler/avr/aasmcpu.pas

@@ -246,12 +246,16 @@ implementation
       begin
         result:=operand_read;
         case opcode of
+          A_CLR,
+          A_MOV, A_MOVW:
+           if opnr=0 then
+             result:=operand_write;
           A_CP,A_CPC,A_CPI,A_PUSH :
             ;
           else
             begin
               if opnr=0 then
-                result:=operand_write;
+                result:=operand_readwrite;
             end;
         end;
       end;
@@ -416,6 +420,8 @@ implementation
                       end;
                     ait_align:
                       inc(CurrOffset,tai_align(curtai).aligntype);
+                    ait_weak,
+                    ait_set,
                     ait_marker:
                       ;
                     ait_label:

+ 1 - 1
compiler/avr/agavrgas.pas

@@ -203,7 +203,7 @@ unit agavrgas;
 
             idtxt  : 'AS';
             asmbin : 'as';
-            asmcmd : '-o $OBJ $ASM';
+            asmcmd : '-o $OBJ $EXTRAOPT $ASM';
             supported_targets : [system_avr_embedded];
             flags : [af_needar,af_smartlink_sections];
             labelprefix : '.L';

+ 233 - 14
compiler/avr/aoptcpu.pas

@@ -28,10 +28,12 @@ Unit aoptcpu;
 
 Interface
 
-uses cpubase, aasmtai, aopt, aoptcpub;
+uses cpubase, cgbase, aasmtai, aopt, aoptcpub;
 
 Type
   TCpuAsmOptimizer = class(TAsmOptimizer)
+    Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
+
     { uses the same constructor as TAopObj }
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     procedure PeepHoleOptPass2;override;
@@ -40,7 +42,9 @@ Type
 Implementation
 
   uses
-    aasmbase,aasmcpu,cgbase;
+    cpuinfo,
+    aasmbase,aasmcpu,
+    globals,globtype;
 
   function CanBeCond(p : tai) : boolean;
     begin
@@ -48,40 +52,255 @@ Implementation
     end;
 
 
+  function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
+    var Next: tai; reg: TRegister): 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));
+    end;
+
+
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
     var
-      next1: tai;
+      hp1,hp2,hp3: tai;
+      alloc, dealloc: tai_regalloc;
+      i: integer;
     begin
       result := false;
       case p.typ of
         ait_instruction:
           begin
             case taicpu(p).opcode of
+              A_LDI:
+                begin
+                  { turn
+                    ldi reg0, imm
+                    cp reg1, reg0
+                    dealloc reg0
+                    into
+                    cpi reg1, imm
+                  }
+                  if (taicpu(p).ops=2) and
+                     (taicpu(p).oper[0]^.typ=top_reg) and
+                     (taicpu(p).oper[1]^.typ=top_const) and
+                     GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                     (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+                     (taicpu(hp1).opcode=A_CP) and
+                     (taicpu(hp1).ops=2) and
+                     (taicpu(hp1).oper[1]^.typ=top_reg) and
+                     (getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
+                     (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
+                     assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+                    begin
+                      taicpu(hp1).opcode:=A_CPI;
+                      taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
+
+                      alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
+                      dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
+
+                      if assigned(alloc) and assigned(dealloc) then
+                        begin
+                          asml.Remove(alloc);
+                          alloc.Free;
+                          asml.Remove(dealloc);
+                          dealloc.Free;
+                        end;
+
+                      GetNextInstruction(p,hp1);
+                      asml.Remove(p);
+                      p.Free;
+                      p:=hp1;
+
+                      result:=true;
+                    end;
+                end;
+              A_CLR:
+                begin
+                  { turn the common
+                    clr rX
+                    mov/ld rX, rY
+                    into
+                    mov/ld rX, rY
+                  }
+                  if (taicpu(p).ops=1) and
+                     (taicpu(p).oper[0]^.typ=top_reg) and
+                     GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                     (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+                     (hp1.typ=ait_instruction) and
+                     (taicpu(hp1).opcode in [A_MOV,A_LD]) and
+                     (taicpu(hp1).ops>0) and
+                     (taicpu(hp1).oper[0]^.typ=top_reg) and
+                     (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
+                    begin
+                      asml.Remove(p);
+                      p.Free;
+                      p:=hp1;
+                      result:=true;
+                    end
+                  { turn
+                    clr rX
+                    ...
+                    adc rY, rX
+                    into
+                    ...
+                    adc rY, r1
+                  }
+                  else if (taicpu(p).ops=1) and
+                     (taicpu(p).oper[0]^.typ=top_reg) and
+                     GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                     (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+                     (hp1.typ=ait_instruction) and
+                     (taicpu(hp1).opcode in [A_ADC,A_SBC]) and
+                     (taicpu(hp1).ops=2) and
+                     (taicpu(hp1).oper[1]^.typ=top_reg) and
+                     (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
+                     (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
+                     assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+                    begin
+                      taicpu(hp1).oper[1]^.reg:=NR_R1;
+
+                      alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
+                      dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
+
+                      if assigned(alloc) and assigned(dealloc) then
+                        begin
+                          asml.Remove(alloc);
+                          alloc.Free;
+                          asml.Remove(dealloc);
+                          dealloc.Free;
+                        end;
+
+                      GetNextInstruction(p,hp1);
+                      asml.Remove(p);
+                      p.free;
+                      p:=hp1;
+
+                      result:=true;
+                    end;
+                end;
+              A_PUSH:
+                begin
+                  { turn
+                    push reg0
+                    push reg1
+                    pop reg3
+                    pop reg2
+                    into
+                    movw reg2,reg0
+                  }
+                  if (taicpu(p).ops=1) and
+                     (taicpu(p).oper[0]^.typ=top_reg) and
+                     GetNextInstruction(p,hp1) and
+                     (hp1.typ=ait_instruction) and
+                     (taicpu(hp1).opcode=A_PUSH) and
+                     (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
+                     ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
+
+                     GetNextInstruction(hp1,hp2) and
+                     (hp2.typ=ait_instruction) and
+                     (taicpu(hp2).opcode=A_POP) and
+
+                     GetNextInstruction(hp2,hp3) and
+                     (hp3.typ=ait_instruction) and
+                     (taicpu(hp3).opcode=A_POP) and
+                     (getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
+                     ((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
+                    begin
+                      taicpu(p).ops:=2;
+                      taicpu(p).opcode:=A_MOVW;
+
+                      taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
+                      taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
+
+                      asml.Remove(hp1);
+                      hp1.Free;
+                      asml.Remove(hp2);
+                      hp2.Free;
+                      asml.Remove(hp3);
+                      hp3.Free;
+
+                      result:=true;
+                    end;
+                end;
               A_MOV:
                 begin
+                  { turn
+                    mov reg0, reg1
+                    push reg0
+                    dealloc reg0
+                    into
+                    push reg1
+                  }
+                  if (taicpu(p).ops=2) and
+                     (taicpu(p).oper[0]^.typ = top_reg) and
+                     (taicpu(p).oper[1]^.typ = top_reg) and
+                     GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                     (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+                     (hp1.typ = ait_instruction) and
+                     (taicpu(hp1).opcode in [A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_EOR,A_AND,A_OR]) and
+                     RegInInstruction(taicpu(p).oper[0]^.reg, hp1) and
+                     (not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
+                     {(taicpu(hp1).ops=1) and
+                     (taicpu(hp1).oper[0]^.typ = top_reg) and
+                     (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and  }
+                     assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+                    begin
+                      for i := 0 to taicpu(hp1).ops-1 do
+                        if taicpu(hp1).oper[i]^.typ=top_reg then
+                          if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
+                            taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
+
+                      alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
+                      dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
+
+                      if assigned(alloc) and assigned(dealloc) then
+                        begin
+                          asml.Remove(alloc);
+                          alloc.Free;
+                          asml.Remove(dealloc);
+                          dealloc.Free;
+                        end;
+
+                      GetNextInstruction(p,hp1);
+                      asml.Remove(p);
+                      p.free;
+                      p:=hp1;
+                      result:=true;
+                    end
                   { fold
                     mov reg2,reg0
                     mov reg3,reg1
                     to
                     movw reg2,reg0
                   }
-                  if (taicpu(p).ops=2) and
+                  else if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
+                     (taicpu(p).ops=2) and
                      (taicpu(p).oper[0]^.typ = top_reg) and
                      (taicpu(p).oper[1]^.typ = top_reg) and
-                     getnextinstruction(p,next1) and
-                     (next1.typ = ait_instruction) and
-                     (taicpu(next1).opcode = A_MOV) and
-                     (taicpu(next1).ops=2) and
-                     (taicpu(next1).oper[0]^.typ = top_reg) and
-                     (taicpu(next1).oper[1]^.typ = top_reg) and
-                     (getsupreg(taicpu(next1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
+                     getnextinstruction(p,hp1) and
+                     (hp1.typ = ait_instruction) and
+                     (taicpu(hp1).opcode = A_MOV) and
+                     (taicpu(hp1).ops=2) and
+                     (taicpu(hp1).oper[0]^.typ = top_reg) and
+                     (taicpu(hp1).oper[1]^.typ = top_reg) and
+                     (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
                      ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
                      ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
-                     (getsupreg(taicpu(next1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
+                     (getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
                     begin
+                      alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
+                      if assigned(alloc) then
+                        begin
+                          asml.Remove(alloc);
+                          asml.InsertBefore(alloc,p);
+                        end;
+
                       taicpu(p).opcode:=A_MOVW;
-                      asml.remove(next1);
-                      next1.free;
+                      asml.remove(hp1);
+                      hp1.free;
                       result := true;
                     end;
                 end;

+ 26 - 8
compiler/avr/aoptcpub.pas

@@ -36,7 +36,10 @@ Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
 Interface
 
 Uses
-  cpubase,aasmcpu,AOptBase;
+  cpubase,
+  cgbase,
+  aasmcpu,aasmtai,
+  AOptBase;
 
 Type
 
@@ -58,6 +61,7 @@ Type
 { ************************************************************************* }
 
   TAoptBaseCpu = class(TAoptBase)
+    function RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean; override;
   End;
 
 
@@ -103,12 +107,26 @@ Implementation
 { ************************************************************************* }
 { **************************** TCondRegs ********************************** }
 { ************************************************************************* }
-Constructor TCondRegs.init;
-Begin
-End;
-
-Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
-Begin
-End;
+  Constructor TCondRegs.init;
+    Begin
+    End;
+
+  Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+    Begin
+    End;
+
+
+  function TAoptBaseCpu.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
+    var
+      i : Longint;
+    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;
+    end;
 
 End.

+ 173 - 76
compiler/avr/cgcpu.pas

@@ -50,10 +50,10 @@ unit cgcpu;
         procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
         procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
         procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
+        procedure a_load_reg_cgpara(list : TAsmList; size : tcgsize;r : tregister; const cgpara : tcgpara);override;
 
         procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
         procedure a_call_reg(list : TAsmList;reg: tregister);override;
-        procedure a_call_ref(list : TAsmList;ref: treference);override;
 
         procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
         procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
@@ -99,14 +99,12 @@ unit cgcpu;
           tmpreg : tregister) : treference;
 
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
-        procedure g_stackpointer_alloc(list : TAsmList;size : longint);override;
         procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
 
         procedure a_adjust_sp(list: TAsmList; value: longint);
         function GetLoad(const ref : treference) : tasmop;
         function GetStore(const ref: treference): tasmop;
 
-        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
       protected
         procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
         procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
@@ -205,25 +203,138 @@ unit cgcpu;
       end;
 
 
+    procedure tcgavr.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
+
+      procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
+        var
+          ref : treference;
+        begin
+          paramanager.allocparaloc(list,paraloc);
+          case paraloc^.loc of
+             LOC_REGISTER,LOC_CREGISTER:
+               a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
+             LOC_REFERENCE,LOC_CREFERENCE:
+               begin
+                  reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,2);
+                  a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
+               end;
+             else
+               internalerror(2002071004);
+          end;
+        end;
+
+      var
+        i, i2 : longint;
+        hp : PCGParaLocation;
+
+      begin
+{        if use_push(cgpara) then
+          begin
+            if tcgsize2size[cgpara.Size] > 2 then
+              begin
+                if tcgsize2size[cgpara.Size] <> 4 then
+                  internalerror(2013031101);
+                if cgpara.location^.Next = nil then
+                  begin
+                    if tcgsize2size[cgpara.location^.size] <> 4 then
+                      internalerror(2013031101);
+                  end
+                else
+                  begin
+                    if tcgsize2size[cgpara.location^.size] <> 2 then
+                      internalerror(2013031101);
+                    if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
+                      internalerror(2013031101);
+                    if cgpara.location^.Next^.Next <> nil then
+                      internalerror(2013031101);
+                  end;
+
+                if tcgsize2size[cgpara.size]>cgpara.alignment then
+                  pushsize:=cgpara.size
+                else
+                  pushsize:=int_cgsize(cgpara.alignment);
+                pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
+                list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
+                list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
+              end
+            else
+              begin
+                cgpara.check_simple_location;
+                if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+                  pushsize:=cgpara.location^.size
+                else
+                  pushsize:=int_cgsize(cgpara.alignment);
+                list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
+              end;
+
+          end
+        else }
+          begin
+            if not(tcgsize2size[cgpara.Size] in [1..4]) then
+              internalerror(2014011101);
+
+            hp:=cgpara.location;
+
+            i:=0;
+            while i<tcgsize2size[cgpara.Size] do
+              begin
+                if not(assigned(hp)) then
+                  internalerror(2014011102);
+
+                inc(i, tcgsize2size[hp^.Size]);
+
+                if hp^.Loc=LOC_REGISTER then
+                  begin
+                    load_para_loc(r,hp);
+                    hp:=hp^.Next;
+                    r:=GetNextReg(r);
+                  end
+                else
+                  begin
+                    load_para_loc(r,hp);
+
+                    for i2:=1 to tcgsize2size[hp^.Size] do
+                      r:=GetNextReg(r);
+
+                    hp:=hp^.Next;
+                  end;
+              end;
+            if assigned(hp) then
+              internalerror(2014011103);
+          end;
+      end;
+
+
     procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
       var
-        ref: treference;
+        i : longint;
+        hp : PCGParaLocation;
       begin
-        paraloc.check_simple_location;
-        paramanager.allocparaloc(list,paraloc.location);
-        case paraloc.location^.loc of
-          LOC_REGISTER,LOC_CREGISTER:
-            a_load_const_reg(list,size,a,paraloc.location^.register);
-          LOC_REFERENCE:
-            begin
-               reference_reset(ref,paraloc.alignment);
-               ref.base:=paraloc.location^.reference.index;
-               ref.offset:=paraloc.location^.reference.offset;
-               a_load_const_ref(list,size,a,ref);
+        if not(tcgsize2size[paraloc.Size] in [1..4]) then
+          internalerror(2014011101);
+
+        hp:=paraloc.location;
+
+        for i:=1 to tcgsize2size[paraloc.Size] do
+          begin
+            if not(assigned(hp)) or
+              (tcgsize2size[hp^.size]<>1) or
+              (hp^.shiftval<>0) then
+              internalerror(2014011105);
+             case hp^.loc of
+               LOC_REGISTER,LOC_CREGISTER:
+                 a_load_const_reg(list,hp^.size,(a shr (i-1)) and $ff,hp^.register);
+               LOC_REFERENCE,LOC_CREFERENCE:
+                 begin
+                   list.concat(taicpu.op_const(A_PUSH,(a shr (i-1)) and $ff));
+                 end;
+               else
+                 internalerror(2002071004);
             end;
-          else
-            internalerror(2002081101);
-        end;
+            hp:=hp^.Next;
+          end;
+        if assigned(hp) then
+          internalerror(2014011104);
       end;
 
 
@@ -271,26 +382,11 @@ unit cgcpu;
 
     procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
       var
-        ref: treference;
         tmpreg: tregister;
       begin
-        paraloc.check_simple_location;
-        paramanager.allocparaloc(list,paraloc.location);
-        case paraloc.location^.loc of
-          LOC_REGISTER,LOC_CREGISTER:
-            a_loadaddr_ref_reg(list,r,paraloc.location^.register);
-          LOC_REFERENCE:
-            begin
-              reference_reset(ref,paraloc.alignment);
-              ref.base := paraloc.location^.reference.index;
-              ref.offset := paraloc.location^.reference.offset;
-              tmpreg := getintregister(list,OS_ADDR);
-              a_loadaddr_ref_reg(list,r,tmpreg);
-              a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
-            end;
-          else
-            internalerror(2002080701);
-        end;
+        tmpreg:=getaddressregister(list);
+        a_loadaddr_ref_reg(list,r,tmpreg);
+        a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc);
       end;
 
 
@@ -321,19 +417,6 @@ unit cgcpu;
       end;
 
 
-    procedure tcgavr.a_call_ref(list : TAsmList;ref: treference);
-      begin
-        a_reg_alloc(list,NR_ZLO);
-        a_reg_alloc(list,NR_ZHI);
-        a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_ZLO);
-        list.concat(taicpu.op_none(A_ICALL));
-        a_reg_dealloc(list,NR_ZLO);
-        a_reg_dealloc(list,NR_ZHI);
-
-        include(current_procinfo.flags,pi_do_call);
-      end;
-
-
      procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
        begin
          if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
@@ -414,7 +497,15 @@ unit cgcpu;
            OP_NEG:
              begin
                if src<>dst then
-                 a_load_reg_reg(list,size,size,src,dst);
+                 begin
+                   if size in [OS_S64,OS_64] then
+                     begin
+                       a_load_reg_reg(list,OS_32,OS_32,src,dst);
+                       a_load_reg_reg(list,OS_32,OS_32,srchi,dsthi);
+                     end
+                   else
+                     a_load_reg_reg(list,size,size,src,dst);
+                 end;
 
                if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
                  begin
@@ -428,7 +519,7 @@ unit cgcpu;
                    tmpreg:=GetNextReg(dst);
                    for i:=2 to tcgsize2size[size] do
                      begin
-                       list.concat(taicpu.op_reg_const(A_SBCI,dst,-1));
+                       list.concat(taicpu.op_reg_const(A_SBCI,tmpreg,-1));
                        NextTmp;
                    end;
                  end;
@@ -488,7 +579,7 @@ unit cgcpu;
                current_asmdata.getjumplabel(l2);
                countreg:=getintregister(list,OS_8);
                a_load_reg_reg(list,size,OS_8,src,countreg);
-               list.concat(taicpu.op_reg_const(A_CP,countreg,0));
+               list.concat(taicpu.op_reg_const(A_CPI,countreg,0));
                a_jmp_flags(list,F_EQ,l2);
                cg.a_label(list,l1);
                case op of
@@ -606,7 +697,7 @@ unit cgcpu;
              end;
            OP_SUB:
              begin
-               list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
+               list.concat(taicpu.op_reg_const(A_SUBI,reg,a and mask));
                if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
                  begin
                    for i:=2 to tcgsize2size[size] do
@@ -618,6 +709,20 @@ unit cgcpu;
                      end;
                  end;
              end;
+           {OP_ADD:
+             begin
+               list.concat(taicpu.op_reg_const(A_SUBI,reg,(-a) and mask));
+               if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+                 begin
+                   for i:=2 to tcgsize2size[size] do
+                     begin
+                       NextReg;
+                       mask:=mask shl 8;
+                       inc(shift,8);
+                       list.concat(taicpu.op_reg_const(A_ADC,reg,(a and mask) shr shift));
+                     end;
+                 end;
+             end; }
          else
            begin
              if size in [OS_64,OS_S64] then
@@ -716,11 +821,11 @@ unit cgcpu;
         else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
           begin
             maybegetcpuregister(list,tmpreg);
-            emit_mov(list,tmpreg,ref.index);
+            emit_mov(list,tmpreg,ref.base);
             maybegetcpuregister(list,GetNextReg(tmpreg));
-            emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
-            list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
-            list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
+            emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
+            list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
+            list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
             ref.base:=tmpreg;
             ref.index:=NR_NO;
           end
@@ -1175,6 +1280,7 @@ unit cgcpu;
       begin
         if a=0 then
           begin
+            swapped:=false;
             { swap parameters? }
             case cmp_op of
               OC_GT:
@@ -1195,7 +1301,7 @@ unit cgcpu;
               OC_A:
                 begin
                   swapped:=true;
-                  cmp_op:=OC_A;
+                  cmp_op:=OC_B;
                 end;
             end;
 
@@ -1227,6 +1333,7 @@ unit cgcpu;
         tmpreg : tregister;
         i : byte;
       begin
+        swapped:=false;
         { swap parameters? }
         case cmp_op of
           OC_GT:
@@ -1247,7 +1354,7 @@ unit cgcpu;
           OC_A:
             begin
               swapped:=true;
-              cmp_op:=OC_A;
+              cmp_op:=OC_B;
             end;
         end;
         if swapped then
@@ -1256,25 +1363,19 @@ unit cgcpu;
             reg1:=reg2;
             reg2:=tmpreg;
           end;
-        list.concat(taicpu.op_reg_reg(A_CP,reg1,reg2));
+        list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
 
         for i:=2 to tcgsize2size[size] do
           begin
             reg1:=GetNextReg(reg1);
             reg2:=GetNextReg(reg2);
-            list.concat(taicpu.op_reg_reg(A_CPC,reg1,reg2));
+            list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
           end;
 
         a_jmp_cond(list,cmp_op,l);
       end;
 
 
-    procedure tcgavr.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
-      begin
-        Comment(V_Error,'tcgarm.a_bit_scan_reg_reg method not implemented');
-      end;
-
-
     procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
       var
         ai : taicpu;
@@ -1338,7 +1439,7 @@ unit cgcpu;
         case value of
           0:
             ;
-          -14..-1:
+          {-14..-1:
             begin
               if ((-value) mod 2)<>0 then
                 list.concat(taicpu.op_reg(A_PUSH,NR_R0));
@@ -1349,7 +1450,7 @@ unit cgcpu;
             begin
               for i:=1 to value do
                 list.concat(taicpu.op_reg(A_POP,NR_R0));
-            end;
+            end;}
           else
             begin
               list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
@@ -1440,6 +1541,8 @@ unit cgcpu;
                 LocalSize:=current_procinfo.calc_stackframe_size;
                 a_adjust_sp(list,LocalSize);
                 regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+                if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+                  regs:=regs+[RS_R28,RS_R29];
 
                 for reg:=RS_R0 to RS_R31 do
                   if reg in regs then
@@ -1772,15 +1875,9 @@ unit cgcpu;
       end;
 
 
-    procedure tcgavr.g_stackpointer_alloc(list: TAsmList; size: longint);
-      begin
-        internalerror(201201071);
-      end;
-
-
     procedure tcgavr.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
       begin
-        internalerror(2011021324);
+        //internalerror(2011021324);
       end;
 
 

+ 13 - 4
compiler/avr/cpubase.pas

@@ -235,11 +235,11 @@ unit cpubase;
       }
       NR_PIC_OFFSET_REG = NR_R9;
       { Results are returned in this register (32-bit values) }
-      NR_FUNCTION_RETURN_REG = NR_R0;
-      RS_FUNCTION_RETURN_REG = RS_R0;
+      NR_FUNCTION_RETURN_REG = NR_R24;
+      RS_FUNCTION_RETURN_REG = RS_R24;
       { Low part of 64bit return value }
-      NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
-      RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
+      NR_FUNCTION_RETURN64_LOW_REG = NR_R22;
+      RS_FUNCTION_RETURN64_LOW_REG = RS_R22;
       { High part of 64bit return value }
       NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
       RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
@@ -290,6 +290,7 @@ unit cpubase;
       }
       std_param_align = 4;
 
+      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
       saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
 
 {*****************************************************************************
@@ -322,6 +323,8 @@ unit cpubase;
     { returns the register with the offset of ofs of a continuous set of register starting with r and being continued with rhi }
     function GetOffsetReg64(const r,rhi: TRegister;ofs : shortint): TRegister;
 
+    function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
+
   implementation
 
     uses
@@ -475,4 +478,10 @@ unit cpubase;
       end;
 
 
+    function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
+      begin
+        is_calljmp:= o in jmp_instructions;
+      end;
+
+
 end.

+ 13 - 10
compiler/avr/cpuinfo.pas

@@ -100,6 +100,9 @@ Const
      'LIBGCC'
    );
 
+    { We know that there are fields after sramsize
+      but we don't care about this warning }
+   {$WARN 3177 OFF}
    embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
    ((
    	controllertypestr:'';
@@ -194,16 +197,16 @@ Const
  const
    cpu_capabilities : array[tcputype] of set of tcpuflags =
      ( { cpu_none } [],
-       { cpu_avr1 } [],
-       { cpu_avr2 } [],
-       { cpu_avr25 } [],
-       { cpu_avr3 } [],
-       { cpu_avr31 } [],
-       { cpu_avr35 } [],
-       { cpu_avr4 } [],
-       { cpu_avr5 } [],
-       { cpu_avr51 } [],
-       { cpu_avr6 } []
+       { cpu_avr1 } [CPUAVR_2_BYTE_PC],
+       { cpu_avr2 } [CPUAVR_2_BYTE_PC],
+       { cpu_avr25 } [CPUAVR_HAS_MOVW,CPUAVR_HAS_LPMX,CPUAVR_2_BYTE_PC],
+       { cpu_avr3 } [CPUAVR_HAS_JMP_CALL,CPUAVR_2_BYTE_PC],
+       { cpu_avr31 } [CPUAVR_HAS_JMP_CALL,CPUAVR_HAS_RAMPZ,CPUAVR_HAS_ELPM,CPUAVR_2_BYTE_PC],
+       { cpu_avr35 } [CPUAVR_HAS_JMP_CALL,CPUAVR_HAS_MOVW,CPUAVR_HAS_LPMX,CPUAVR_2_BYTE_PC],
+       { cpu_avr4 } [CPUAVR_HAS_MOVW,CPUAVR_HAS_LPMX,CPUAVR_HAS_MUL,CPUAVR_2_BYTE_PC],
+       { cpu_avr5 } [CPUAVR_HAS_JMP_CALL,CPUAVR_HAS_MOVW,CPUAVR_HAS_LPMX,CPUAVR_HAS_MUL,CPUAVR_2_BYTE_PC],
+       { cpu_avr51 } [CPUAVR_HAS_JMP_CALL,CPUAVR_HAS_MOVW,CPUAVR_HAS_LPMX,CPUAVR_HAS_MUL,CPUAVR_HAS_RAMPZ,CPUAVR_HAS_ELPM,CPUAVR_HAS_ELPMX,CPUAVR_2_BYTE_PC],
+       { cpu_avr6 } [CPUAVR_HAS_JMP_CALL,CPUAVR_HAS_MOVW,CPUAVR_HAS_LPMX,CPUAVR_HAS_MUL,CPUAVR_HAS_RAMPZ,CPUAVR_HAS_ELPM,CPUAVR_HAS_ELPMX,CPUAVR_3_BYTE_PC]
      );
 
 Implementation

+ 3 - 1
compiler/avr/cpunode.pas

@@ -36,7 +36,9 @@ unit cpunode;
        }
        ,navradd
        ,navrmat
-       ,navrcnv
+       ,navrcnv,
+       { symtable }
+       symcpu
        ;
 
 

+ 60 - 45
compiler/avr/cpupara.pas

@@ -38,7 +38,6 @@ unit cpupara;
           function get_volatile_registers_fpu(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;
@@ -68,45 +67,6 @@ unit cpupara;
       end;
 
 
-    procedure tavrparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
-      var
-        paraloc : pcgparalocation;
-        psym: tparavarsym;
-        pdef: tdef;
-      begin
-        if nr<1 then
-          internalerror(2002070801);
-        psym:=tparavarsym(pd.paras[nr-1]);
-        pdef:=psym.vardef;
-        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
-          pdef:=getpointerdef(pdef);
-        cgpara.reset;
-        cgpara.size:=def_cgsize(pdef);
-        cgpara.intsize:=tcgsize2size[cgpara.size];
-        cgpara.alignment:=std_param_align;
-        cgpara.def:=pdef;
-        paraloc:=cgpara.add_location;
-        with paraloc^ do
-          begin
-            size:=def_cgsize(pdef);
-            def:=pdef;
-            { the four first parameters are passed into registers }
-            if nr<=9 then
-              begin
-                loc:=LOC_REGISTER;
-                register:=newreg(R_INTREGISTER,RS_R25-(nr-1)*2,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-10)*2;
-              end;
-          end;
-      end;
-
-
     function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc;
       begin
          { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
@@ -181,6 +141,8 @@ unit cpupara;
             result:=not is_smallset(def);
           stringdef :
             result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+        else
+          result:=def.size>4;
         end;
       end;
 
@@ -202,7 +164,10 @@ unit cpupara;
             result:=not(def.size in [1,2,4]);
           }
           else
-            result:=inherited ret_in_param(def,pd);
+            if (def.size > 4) then
+              result:=true
+            else
+              result:=inherited ret_in_param(def,pd);
         end;
       end;
 
@@ -481,7 +446,57 @@ unit cpupara;
           { Return in register }
         else
           begin
-            if retcgsize in [OS_64,OS_S64] then
+            case retcgsize of
+              OS_32,OS_S32:
+                begin
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R22;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+
+                  paraloc:=result.add_location;
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R23;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+
+                  paraloc:=result.add_location;
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R24;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+
+                  paraloc:=result.add_location;
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R25;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+                end;
+              OS_16,OS_S16:
+                begin
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R24;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+
+                  paraloc:=result.add_location;
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R25;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+                end;
+              OS_8,OS_S8:
+                begin
+                  paraloc^.loc:=LOC_REGISTER;
+                  paraloc^.register:=NR_R24;
+                  paraloc^.size:=OS_8;
+                  paraloc^.def:=u8inttype;
+                end;
+              else
+                internalerror(2014030101);
+            end;
+
+            {if retcgsize in [OS_64,OS_S64] then
               begin
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
@@ -497,9 +512,9 @@ unit cpupara;
               begin
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RETURN_REG;
-                paraloc^.size:=OS_32;
-                paraloc^.def:=u32inttype;
-              end;
+                paraloc^.size:=OS_INT;
+                paraloc^.def:=u16inttype;
+              end;}
           end;
       end;
 

+ 11 - 2
compiler/avr/cpupi.pas

@@ -37,6 +37,7 @@ unit cpupi;
           // procedure after_pass1;override;
           procedure set_first_temp_offset;override;
           function calc_stackframe_size:longint;override;
+          procedure postprocess_code;override;
        end;
 
 
@@ -49,7 +50,8 @@ unit cpupi;
        tgobj,
        symconst,symsym,paramgr,
        cgbase,
-       cgobj;
+       cgobj,
+       aasmcpu;
 
     procedure tavrprocinfo.set_first_temp_offset;
       begin
@@ -63,10 +65,17 @@ unit cpupi;
     function tavrprocinfo.calc_stackframe_size:longint;
       begin
         maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
-        result:=0;
+        result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize;
       end;
 
 
+    procedure tavrprocinfo.postprocess_code;
+      begin
+        { because of the limited branch distance of cond. branches, they must be replaced
+          sometimes by normal jmps and an inverse branch }
+        finalizeavrcode(aktproccode);
+      end;
+
 begin
    cprocinfo:=tavrprocinfo;
 end.

+ 24 - 10
compiler/avr/raavrgas.pas

@@ -69,14 +69,20 @@ Unit raavrgas;
           name : string[2];
           reg : tregister;
         end;
-{
+
       const
-        extraregs : array[0..19] of treg2str = (
-          (name: 'X'; reg : NR_Z),
-          (name: 'Y'; reg : NR_R1),
-          (name: 'Z'; reg : NR_R2),
+        extraregs : array[0..8] of treg2str = (
+          (name: 'X'; reg : NR_R26),
+          (name: 'XL'; reg : NR_R26),
+          (name: 'XH'; reg : NR_R27),
+          (name: 'Y'; reg : NR_R28),
+          (name: 'YL'; reg : NR_R28),
+          (name: 'YH'; reg : NR_R29),
+          (name: 'Z'; reg : NR_R30),
+          (name: 'ZL'; reg : NR_R30),
+          (name: 'ZH'; reg : NR_R31)
         );
-}
+
       var
         i : longint;
 
@@ -85,9 +91,9 @@ Unit raavrgas;
         { reg found?
           possible aliases are always 2 char
         }
-        if result or (length(s)<>2) then
+        if result or (not (length(s) in [1,2])) then
           exit;
-{
+
         for i:=low(extraregs) to high(extraregs) do
           begin
             if s=extraregs[i].name then
@@ -98,7 +104,6 @@ Unit raavrgas;
                 exit;
               end;
           end;
-}
       end;
 
 
@@ -480,7 +485,16 @@ Unit raavrgas;
               { save the type of register used. }
               tempreg:=actasmregister;
               Consume(AS_REGISTER);
-              if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+              if (actasmtoken=AS_PLUS) then
+                begin
+                  oper.opr.typ:=OPR_REFERENCE;
+
+                  reference_reset_base(oper.opr.ref,tempreg,0,1);
+                  oper.opr.ref.addressmode:=AM_POSTINCREMENT;
+
+                  consume(AS_PLUS);
+                end
+              else 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);

+ 211 - 0
compiler/avr/symcpu.pas

@@ -0,0 +1,211 @@
+{
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Symbol table overrides for AVR
+
+    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.
+

+ 2 - 0
compiler/browcol.pas

@@ -1673,6 +1673,8 @@ end;
                       Symbol^.Flags:=(Symbol^.Flags or sfObject);
                       if tobjectdef(typedef).objecttype=odt_class then
                         Symbol^.Flags:=(Symbol^.Flags or sfClass);
+                      if tobjectdef(typedef).objecttype=odt_class then
+                      if not(df_generic in typedef.defoptions) then
                       ProcessSymTable(Symbol,Symbol^.Items,tobjectdef(typedef).symtable);
                     end;
                   recorddef :

+ 69 - 7
compiler/cclasses.pas

@@ -76,7 +76,7 @@ type
   TListSortCompare = function (Item1, Item2: Pointer): Integer;
   TListCallback = procedure(data,arg:pointer) of object;
   TListStaticCallback = procedure(data,arg:pointer);
-
+  TDynStringArray = Array Of String;
   TFPList = class(TObject)
   private
     FList: PPointerList;
@@ -87,13 +87,13 @@ type
     procedure Put(Index: Integer; Item: Pointer);
     procedure SetCapacity(NewCapacity: Integer);
     procedure SetCount(NewCount: Integer);
-    Procedure RaiseIndexError(Index : Integer);
+    Procedure RaiseIndexError(Index : Integer);{$ifndef VER2_6}noreturn;{$endif VER2_6}
   public
     destructor Destroy; override;
     function Add(Item: Pointer): Integer;
     procedure Clear;
     procedure Delete(Index: Integer);
-    class procedure Error(const Msg: string; Data: PtrInt);
+    class procedure Error(const Msg: string; Data: PtrInt);{$ifndef VER2_6}noreturn;{$endif VER2_6}
     procedure Exchange(Index1, Index2: Integer);
     function Expand: TFPList;
     function Extract(item: Pointer): Pointer;
@@ -224,7 +224,7 @@ type
     function HashOfIndex(Index: Integer): LongWord;
     function GetNextCollision(Index: Integer): Integer;
     procedure Delete(Index: Integer);
-    class procedure Error(const Msg: string; Data: PtrInt);
+    class procedure Error(const Msg: string; Data: PtrInt);{$ifndef VER2_6}noreturn;{$endif VER2_6}
     function Expand: TFPHashList;
     function Extract(item: Pointer): Pointer;
     function IndexOf(Item: Pointer): Integer;
@@ -589,12 +589,74 @@ type
     function FPHash(const s:shortstring):LongWord; inline;
     function FPHash(const a:ansistring):LongWord; inline;
 
+    function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; var Strings: TDynStringArray; AddEmptyStrings : Boolean = False): Integer;
 
 implementation
 
 {*****************************************************************************
                                     Memory debug
 *****************************************************************************}
+    function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; var Strings: TDynStringArray; AddEmptyStrings : Boolean = False): Integer;
+    var
+      b, c : pchar;
+
+      procedure SkipWhitespace;
+        begin
+          while (c^ in Whitespace) do
+            inc (c);
+        end;
+
+      procedure AddString;
+        var
+          l : integer;
+          s : string;
+        begin
+          l := c-b;
+          if (l > 0) or AddEmptyStrings then
+            begin
+              setlength(s, l);
+              if l>0 then
+                move (b^, s[1],l*SizeOf(char));
+              l:=length(Strings);
+              setlength(Strings,l+1);
+              Strings[l]:=S;  
+              inc (result);
+            end;
+        end;
+
+    var
+      quoted : char;
+    begin
+      result := 0;
+      c := Content;
+      Quoted := #0;
+      Separators := Separators + [#13, #10] - ['''','"'];
+      SkipWhitespace;
+      b := c;
+      while (c^ <> #0) do
+        begin
+          if (c^ = Quoted) then
+            begin
+              if ((c+1)^ = Quoted) then
+                inc (c)
+              else
+                Quoted := #0
+            end
+          else if (Quoted = #0) and (c^ in ['''','"']) then
+            Quoted := c^;
+          if (Quoted = #0) and (c^ in Separators) then
+            begin
+              AddString;
+              inc (c);
+              SkipWhitespace;
+              b := c;
+            end
+          else
+            inc (c);
+        end;
+      if (c <> b) then
+        AddString;
+    end;
 
     constructor tmemdebug.create(const s:string);
       begin
@@ -649,7 +711,7 @@ implementation
                TFPObjectList (Copied from rtl/objpas/classes/lists.inc)
 *****************************************************************************}
 
-procedure TFPList.RaiseIndexError(Index : Integer);
+procedure TFPList.RaiseIndexError(Index : Integer);{$ifndef VER2_6}noreturn;{$endif VER2_6}
 begin
   Error(SListIndexError, Index);
 end;
@@ -745,7 +807,7 @@ begin
   end;
 end;
 
-class procedure TFPList.Error(const Msg: string; Data: PtrInt);
+class procedure TFPList.Error(const Msg: string; Data: PtrInt);{$ifndef VER2_6}noreturn;{$endif VER2_6}
 begin
   Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
 end;
@@ -1443,7 +1505,7 @@ begin
     Self.Delete(Result);
 end;
 
-class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);
+class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);{$ifndef VER2_6}noreturn;{$endif VER2_6}
 begin
   Raise EListError.CreateFmt(Msg,[Data])  at get_caller_addr(get_frame), get_caller_frame(get_frame);
 end;

+ 30 - 3
compiler/cfileutl.pas

@@ -764,6 +764,7 @@ end;
   begin
     oldpos := 1;
     slashPos := Pos('/', path);
+    TranslatePathToMac:='';
     if (slashPos <> 0) then   {its a unix path}
       begin
         if slashPos = 1 then
@@ -1479,6 +1480,7 @@ end;
         inquotes:=false;
         result:='';
         i:=1;
+        temp:='';
         while i<=length(QuotedStr) do
           begin
             case QuotedStr[i] of
@@ -1521,6 +1523,10 @@ end;
       var
         quote_script: tscripttype;
       begin
+
+        if do_checkverbosity(V_Executable) then
+          do_comment(V_Executable,'Executing "'+Path+'" with command line "'+
+            ComLine+'"');
         if (cs_link_on_target in current_settings.globalswitches) then
           quote_script:=target_info.script
         else
@@ -1533,7 +1539,21 @@ end;
 
 
     function RequotedExecuteProcess(const Path: AnsiString; const ComLine: array of AnsiString; Flags: TExecuteFlags): Longint;
+      var
+        i : longint;
+        st : string;
       begin
+        if do_checkverbosity(V_Executable) then
+          begin
+            if high(ComLine)=0 then
+              st:=''
+            else
+              st:=ComLine[1];
+            for i:=2 to high(ComLine) do
+              st:=st+' '+ComLine[i];
+            do_comment(V_Executable,'Executing "'+Path+'" with command line "'+
+              st+'"');
+          end;
         result:=sysutils.ExecuteProcess(Path,ComLine,Flags);
       end;
 
@@ -1543,21 +1563,28 @@ end;
         expansion under linux }
 {$ifdef hasunix}
       begin
+        if do_checkverbosity(V_Used) then
+          do_comment(V_Executable,'Executing "'+Command+'" with fpSystem call');
         result := Unix.fpsystem(command);
       end;
 {$else hasunix}
-  {$ifdef amigashell}
+  {$ifdef hasamiga}
       begin
+        if do_checkverbosity(V_Used) then
+          do_comment(V_Executable,'Executing "'+Command+'" using RequotedExecuteProcess');
         result := RequotedExecuteProcess('',command);
       end;
-  {$else amigashell}
+  {$else hasamiga}
       var
         comspec : string;
       begin
         comspec:=GetEnvironmentVariable('COMSPEC');
+        if do_checkverbosity(V_Used) then
+          do_comment(V_Executable,'Executing "'+Command+'" using comspec "'
+            +ComSpec+'"');
         result := RequotedExecuteProcess(comspec,' /C '+command);
       end;
-   {$endif amigashell}
+   {$endif hasamiga}
 {$endif hasunix}
 
 

+ 8 - 13
compiler/cg64f32.pas

@@ -92,8 +92,6 @@ unit cg64f32;
         procedure g_rangecheck64(list: TAsmList; const l:tlocation;fromdef,todef: tdef); override;
       end;
 
-    {# Creates a tregister64 record from 2 32 Bit registers. }
-    function joinreg64(reglo,reghi : tregister) : tregister64;
 
   implementation
 
@@ -107,13 +105,6 @@ unit cg64f32;
                                      Helpers
 ****************************************************************************}
 
-    function joinreg64(reglo,reghi : tregister) : tregister64;
-      begin
-         result.reglo:=reglo;
-         result.reghi:=reghi;
-      end;
-
-
     procedure swap64(var q : int64);
       begin
          q:=(int64(lo(q)) shl 32) or hi(q);
@@ -522,7 +513,7 @@ unit cg64f32;
           LOC_MMREGISTER, LOC_CMMREGISTER:
             a_loadmm_intreg64_reg(list,l.size,reg,l.register);
           else
-            internalerror(200112293);
+            internalerror(200112294);
         end;
       end;
 
@@ -861,14 +852,18 @@ unit cg64f32;
                begin
                  current_asmdata.getjumplabel(neglabel);
                  cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
-               end;
+               end
+             else
+               { we do not have dynamic dfa, so avoid a warning below about the unused
+                 neglabel }
+               neglabel:=nil;
              { For all other values we have a range check error }
              cg.a_call_name(list,'fpc_rangeerror',false);
 
              { if the high dword = 0, the low dword can be considered a }
              { simple cardinal                                          }
              cg.a_label(list,poslabel);
-             hdef:=torddef.create(u32bit,0,$ffffffff);
+             hdef:=corddef.create(u32bit,0,$ffffffff);
 
              location_copy(temploc,l);
              temploc.size:=OS_32;
@@ -908,7 +903,7 @@ unit cg64f32;
                  { if we get here, the 64bit value lies between }
                  { longint($80000000) and -1 (JM)               }
                  cg.a_label(list,neglabel);
-                 hdef:=torddef.create(s32bit,int64(longint($80000000)),int64(-1));
+                 hdef:=corddef.create(s32bit,int64(longint($80000000)),int64(-1));
                  location_copy(temploc,l);
                  temploc.size:=OS_32;
                  hlcg.g_rangecheck(list,temploc,hdef,todef);

+ 9 - 2
compiler/cgbase.pas

@@ -99,8 +99,6 @@ interface
          {$ENDIF}
          {$IFDEF i8086}
          ,addr_dgroup      // the data segment group
-         ,addr_far         // used for emitting 'call/jmp far label' instructions
-         ,addr_far_ref     // used for emitting 'call far [reference]' instructions
          ,addr_seg         // used for getting the segment of an object, e.g. 'mov ax, SEG symbol'
          {$ENDIF}
          );
@@ -282,6 +280,7 @@ interface
 
        { Invalid register number }
        RS_INVALID    = high(tsuperregister);
+       NR_INVALID    = tregister($fffffffff);
 
        tcgsize2size : Array[tcgsize] of integer =
          { integer values }
@@ -375,6 +374,8 @@ interface
     function int_cgsize(const a: tcgint): tcgsize;{$ifdef USEINLINE}inline;{$endif}
     function int_float_cgsize(const a: tcgint): tcgsize;
 
+    function tcgsize2str(cgsize: tcgsize):string;
+
     { return the inverse condition of opcmp }
     function inverse_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
 
@@ -669,6 +670,12 @@ implementation
       end;
 
 
+    function tcgsize2str(cgsize: tcgsize):string;
+      begin
+        Str(cgsize, Result);
+      end;
+
+
     function inverse_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
       const
         list: array[TOpCmp] of TOpCmp =

+ 12 - 1
compiler/cghlcpu.pas

@@ -25,7 +25,7 @@
 
 unit cghlcpu;
 
-{$mode objfpc}
+{$i fpcdefs.inc}
 
 interface
 
@@ -38,6 +38,8 @@ uses
   type
     thlbasecgcpu = class(tcg)
      public
+      procedure g_save_registers(list:TAsmList);override;
+      procedure g_restore_registers(list:TAsmList);override;
       procedure g_stackpointer_alloc(list: TAsmList; size: longint); override;
       procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean); override;
       procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean); override;
@@ -206,6 +208,15 @@ implementation
         internalerror(2012042822);
       end;
 
+    procedure thlbasecgcpu.g_save_registers(list: TAsmList);
+      begin
+        { do nothing }
+      end;
+
+    procedure thlbasecgcpu.g_restore_registers(list: TAsmList);
+      begin
+        { do nothing }
+      end;
 
     procedure thlbasecgcpu.g_stackpointer_alloc(list: TAsmList; size: longint);
       begin

+ 174 - 28
compiler/cgobj.pas

@@ -227,7 +227,6 @@ unit cgobj;
           }
           procedure a_call_name(list : TAsmList;const s : string; weak: boolean);virtual; abstract;
           procedure a_call_reg(list : TAsmList;reg : tregister);virtual; abstract;
-          procedure a_call_ref(list : TAsmList;ref : treference);virtual;
           { same as a_call_name, might be overridden on certain architectures to emit
             static calls without usage of a got trampoline }
           procedure a_call_name_static(list : TAsmList;const s : string);virtual;
@@ -248,7 +247,11 @@ unit cgobj;
           procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);virtual; abstract;
 
           { bit scan instructions }
-          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister); virtual; abstract;
+          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister); virtual;
+
+          { Multiplication with doubling result size.
+            dstlo or dsthi may be NR_NO, in which case corresponding half of result is discarded. }
+          procedure a_mul_reg_reg_pair(list: TAsmList; size: tcgsize; src1,src2,dstlo,dsthi: TRegister);virtual;
 
           { fpu move instructions }
           procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize:tcgsize; reg1, reg2: tregister); virtual; abstract;
@@ -336,11 +339,12 @@ unit cgobj;
              to emit, and the constant value to emit. This function can opcode OP_NONE to
              remove the opcode and OP_MOVE to replace it with a simple load
 
+             @param(size Size of the operand in constant)
              @param(op The opcode to emit, returns the opcode which must be emitted)
              @param(a  The constant which should be emitted, returns the constant which must
                     be emitted)
           }
-          procedure optimize_op_const(var op: topcg; var a : tcgint);virtual;
+          procedure optimize_op_const(size: TCGSize; var op: topcg; var a : tcgint);virtual;
 
          {#
              This routine is used in exception management nodes. It should
@@ -408,7 +412,7 @@ unit cgobj;
 
              @param(size Number of bytes to allocate)
           }
-          procedure g_stackpointer_alloc(list : TAsmList;size : longint);virtual; abstract;
+          procedure g_stackpointer_alloc(list : TAsmList;size : longint);virtual;
           {# Emits instruction for allocating the locals in entry
              code of a routine. This is one of the first
              routine called in @var(genentrycode).
@@ -458,6 +462,9 @@ unit cgobj;
           { Generate code to exit an unwind-protected region. The default implementation
             produces a simple jump to destination label. }
           procedure g_local_unwind(list: TAsmList; l: TAsmLabel);virtual;
+          { Generate code for integer division by constant,
+            generic version is suitable for 3-address CPUs }
+          procedure g_div_const_reg_reg(list:tasmlist; size: TCgSize; a: tcgint; src,dst: tregister); virtual;
 
          protected
           function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual;
@@ -558,6 +565,9 @@ unit cgobj;
         { override to catch 64bit rangechecks }
         procedure g_rangecheck64(list: TAsmList; const l:tlocation; fromdef,todef: tdef);virtual;abstract;
     end;
+
+    { Creates a tregister64 record from 2 32 Bit registers. }
+    function joinreg64(reglo,reghi : tregister) : tregister64;
 {$endif cpu64bitalu}
 
     var
@@ -702,6 +712,8 @@ implementation
     procedure tcg.allocallcpuregisters(list:TAsmList);
       begin
         alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        if uses_registers(R_ADDRESSREGISTER) then
+          alloccpuregisters(list,R_ADDRESSREGISTER,paramanager.get_volatile_registers_address(pocall_default));
 {$if not(defined(i386)) and not(defined(i8086)) and not(defined(avr))}
         if uses_registers(R_FPUREGISTER) then
           alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
@@ -725,6 +737,8 @@ implementation
     procedure tcg.deallocallcpuregisters(list:TAsmList);
       begin
         dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        if uses_registers(R_ADDRESSREGISTER) then
+          dealloccpuregisters(list,R_ADDRESSREGISTER,paramanager.get_volatile_registers_address(pocall_default));
 {$if not(defined(i386)) and not(defined(i8086)) and not(defined(avr))}
         if uses_registers(R_FPUREGISTER) then
           dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
@@ -754,7 +768,7 @@ implementation
           No IE can be generated, because the VMT is written
           without a valid rg[] }
         if assigned(rg[rt]) then
-          rg[rt].add_reg_instruction(instr,r,cg.executionweight);
+          rg[rt].add_reg_instruction(instr,r,executionweight);
       end;
 
 
@@ -940,7 +954,7 @@ implementation
                    { we're at the end of the data, and it can be loaded into
                      the current location's register with a single regular
                      load }
-                   else if (sizeleft in [1,2{$ifndef cpu16bitalu},4{$endif}{$ifdef cpu64bitalu},8{$endif}]) then
+                   else if sizeleft in [1,2,4,8] then
                      begin
                        a_load_ref_reg(list,int_cgsize(sizeleft),location^.size,tmpref,location^.register);
                        if location^.shiftval<0 then
@@ -1126,7 +1140,7 @@ implementation
                end;
              end;
            LOC_FPUREGISTER :
-             cg.a_loadfpu_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
+             a_loadfpu_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
            LOC_REFERENCE :
              begin
                reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset,align);
@@ -1282,6 +1296,7 @@ implementation
         tmpreg,
         tmpreg2 : tregister;
         i : longint;
+        hisize : tcgsize;
       begin
         if ref.alignment in [1,2] then
           begin
@@ -1294,14 +1309,18 @@ implementation
                   a_load_ref_reg(list,fromsize,tosize,tmpref,register)
                 else
                   begin
+                    if FromSize=OS_16 then
+                      hisize:=OS_8
+                    else
+                      hisize:=OS_S8;
                     { first load in tmpreg, because the target register }
                     { may be used in ref as well                        }
                     if target_info.endian=endian_little then
                       inc(tmpref.offset);
                     tmpreg:=getintregister(list,OS_8);
-                    a_load_ref_reg(list,OS_8,OS_8,tmpref,tmpreg);
-                    tmpreg:=makeregsize(list,tmpreg,OS_16);
-                    a_op_const_reg(list,OP_SHL,OS_16,8,tmpreg);
+                    a_load_ref_reg(list,hisize,hisize,tmpref,tmpreg);
+                    tmpreg:=makeregsize(list,tmpreg,FromSize);
+                    a_op_const_reg(list,OP_SHL,FromSize,8,tmpreg);
                     if target_info.endian=endian_little then
                       dec(tmpref.offset)
                     else
@@ -1433,10 +1452,39 @@ implementation
       end;
 
 
-    procedure tcg.optimize_op_const(var op: topcg; var a : tcgint);
+    procedure tcg.optimize_op_const(size: TCGSize; var op: topcg; var a : tcgint);
       var
         powerval : longint;
+        signext_a, zeroext_a: tcgint;
       begin
+        case size of
+          OS_64,OS_S64:
+            begin
+              signext_a:=int64(a);
+              zeroext_a:=int64(a);
+            end;
+          OS_32,OS_S32:
+            begin
+              signext_a:=longint(a);
+              zeroext_a:=dword(a);
+            end;
+          OS_16,OS_S16:
+            begin
+              signext_a:=smallint(a);
+              zeroext_a:=word(a);
+            end;
+          OS_8,OS_S8:
+            begin
+              signext_a:=shortint(a);
+              zeroext_a:=byte(a);
+            end
+          else
+            begin
+              { Should we internalerror() here instead? }
+              signext_a:=a;
+              zeroext_a:=a;
+            end;
+        end;
         case op of
           OP_OR :
             begin
@@ -1445,13 +1493,13 @@ implementation
                 op:=OP_NONE
               else
               { or with max returns max }
-                if a = -1 then
+                if signext_a = -1 then
                   op:=OP_MOVE;
             end;
           OP_AND :
             begin
               { and with max returns same result }
-              if (a = -1) then
+              if (signext_a = -1) then
                 op:=OP_NONE
               else
               { and with 0 returns 0 }
@@ -1463,7 +1511,7 @@ implementation
               { division by 1 returns result }
               if a = 1 then
                 op:=OP_NONE
-              else if ispowerof2(int64(a), powerval) and not(cs_check_overflow in current_settings.localswitches) then
+              else if ispowerof2(int64(zeroext_a), powerval) and not(cs_check_overflow in current_settings.localswitches) then
                 begin
                   a := powerval;
                   op:= OP_SHR;
@@ -1481,7 +1529,7 @@ implementation
                else
                  if a=0 then
                    op:=OP_MOVE
-               else if ispowerof2(int64(a), powerval) and not(cs_check_overflow in current_settings.localswitches)  then
+               else if ispowerof2(int64(zeroext_a), powerval) and not(cs_check_overflow in current_settings.localswitches)  then
                  begin
                    a := powerval;
                    op:= OP_SHL;
@@ -2047,7 +2095,7 @@ implementation
            (tcgsize2size[tosize]<>4) then
           internalerror(2009112504);
         tg.gettemp(list,8,8,tt_normal,tmpref);
-        cg.a_loadmm_reg_ref(list,fromsize,fromsize,mmreg,tmpref,shuffle);
+        a_loadmm_reg_ref(list,fromsize,fromsize,mmreg,tmpref,shuffle);
         a_load_ref_reg(list,tosize,tosize,tmpref,intreg);
         tg.ungettemp(list,tmpref);
       end;
@@ -2131,7 +2179,7 @@ implementation
            pd:=search_system_proc('fpc_check_object_ext');
            paramanager.getintparaloc(pd,1,cgpara1);
            paramanager.getintparaloc(pd,2,cgpara2);
-           reference_reset_symbol(hrefvmt,current_asmdata.RefAsmSymbol(objdef.vmt_mangledname),0,sizeof(pint));
+           reference_reset_symbol(hrefvmt,current_asmdata.RefAsmSymbol(objdef.vmt_mangledname,AT_DATA),0,sizeof(pint));
            if pd.is_pushleftright then
              begin
                a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1);
@@ -2180,6 +2228,10 @@ implementation
         for r:=low(saved_standard_registers) to high(saved_standard_registers) do
           if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
             inc(size,sizeof(aint));
+        if uses_registers(R_ADDRESSREGISTER) then
+          for r:=low(saved_address_registers) to high(saved_address_registers) do
+            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+              inc(size,sizeof(aint));
 
         { mm registers }
         if uses_registers(R_MMREGISTER) then
@@ -2211,6 +2263,17 @@ implementation
                 include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
               end;
 
+            if uses_registers(R_ADDRESSREGISTER) then
+              for r:=low(saved_address_registers) to high(saved_address_registers) do
+                begin
+                  if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+                    begin
+                      a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE),href);
+                      inc(href.offset,sizeof(aint));
+                    end;
+                  include(rg[R_ADDRESSREGISTER].preserved_by_proc,saved_address_registers[r]);
+                end;
+
             if uses_registers(R_MMREGISTER) then
               begin
                 if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
@@ -2257,6 +2320,17 @@ implementation
               inc(href.offset,sizeof(aint));
             end;
 
+        if uses_registers(R_ADDRESSREGISTER) then
+          for r:=low(saved_address_registers) to high(saved_address_registers) do
+            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+              begin
+                hreg:=newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE);
+                { Allocate register so the optimizer does not remove the load }
+                a_reg_alloc(list,hreg);
+                a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
+                inc(href.offset,sizeof(aint));
+              end;
+
         if uses_registers(R_MMREGISTER) then
           begin
             if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
@@ -2297,7 +2371,7 @@ implementation
 
     procedure tcg.g_exception_reason_load(list : TAsmList; const href : treference);
       begin
-        cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
+        a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
         a_load_ref_reg(list, OS_INT, OS_INT, href, NR_FUNCTION_RESULT_REG);
       end;
 
@@ -2348,16 +2422,6 @@ implementation
       end;
 
 
-    procedure tcg.a_call_ref(list : TAsmList;ref: treference);
-      var
-        tempreg : TRegister;
-      begin
-        tempreg := getintregister(list, OS_ADDR);
-        a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,tempreg);
-        a_call_reg(list,tempreg);
-      end;
-
-
    function tcg.g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;
       var
         l: tasmsymbol;
@@ -2444,11 +2508,93 @@ implementation
         internalerror(200807238);
       end;
 
+
+    procedure tcg.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister);
+      begin
+        internalerror(2014070601);
+      end;
+
+
+    procedure tcg.g_stackpointer_alloc(list: TAsmList; size: longint);
+      begin
+        internalerror(2014070602);
+      end;
+
+
+    procedure tcg.a_mul_reg_reg_pair(list: TAsmList; size: TCgSize; src1,src2,dstlo,dsthi: TRegister);
+      begin
+        internalerror(2014060801);
+      end;
+
+
+    procedure tcg.g_div_const_reg_reg(list:tasmlist; size: TCgSize; a: tcgint; src,dst: tregister);
+      var
+        divreg: tregister;
+        magic: aInt;
+        u_magic: aWord;
+        u_shift: byte;
+        u_add: boolean;
+      begin
+        divreg:=getintregister(list,OS_INT);
+        if (size in [OS_S32,OS_S64]) then
+          begin
+            calc_divconst_magic_signed(tcgsize2size[size]*8,a,magic,u_shift);
+            { load magic value }
+            a_load_const_reg(list,OS_INT,magic,divreg);
+            { multiply, discarding low bits }
+            a_mul_reg_reg_pair(list,size,src,divreg,NR_NO,dst);
+            { add/subtract numerator }
+            if (a>0) and (magic<0) then
+              a_op_reg_reg_reg(list,OP_ADD,OS_INT,src,dst,dst)
+            else if (a<0) and (magic>0) then
+              a_op_reg_reg_reg(list,OP_SUB,OS_INT,src,dst,dst);
+            { shift shift places to the right (arithmetic) }
+            a_op_const_reg_reg(list,OP_SAR,OS_INT,u_shift,dst,dst);
+            { extract and add sign bit }
+            if (a>=0) then
+              a_op_const_reg_reg(list,OP_SHR,OS_INT,tcgsize2size[size]*8-1,src,divreg)
+            else
+              a_op_const_reg_reg(list,OP_SHR,OS_INT,tcgsize2size[size]*8-1,dst,divreg);
+            a_op_reg_reg_reg(list,OP_ADD,OS_INT,dst,divreg,dst);
+          end
+        else if (size in [OS_32,OS_64]) then
+          begin
+            calc_divconst_magic_unsigned(tcgsize2size[size]*8,a,u_magic,u_add,u_shift);
+            { load magic in divreg }
+            a_load_const_reg(list,OS_INT,tcgint(u_magic),divreg);
+            { multiply, discarding low bits }
+            a_mul_reg_reg_pair(list,size,src,divreg,NR_NO,dst);
+            if (u_add) then
+              begin
+                { Calculate "(numerator+result) shr u_shift", avoiding possible overflow }
+                a_op_reg_reg_reg(list,OP_SUB,OS_INT,dst,src,divreg);
+                { divreg=(numerator-result) }
+                a_op_const_reg_reg(list,OP_SHR,OS_INT,1,divreg,divreg);
+                { divreg=(numerator-result)/2 }
+                a_op_reg_reg_reg(list,OP_ADD,OS_INT,divreg,dst,divreg);
+                { divreg=(numerator+result)/2, already shifted by 1, so decrease u_shift. }
+                a_op_const_reg_reg(list,OP_SHR,OS_INT,u_shift-1,divreg,dst);
+              end
+            else
+              a_op_const_reg_reg(list,OP_SHR,OS_INT,u_shift,dst,dst);
+          end
+        else
+          InternalError(2014060601);
+      end;
+
+
 {*****************************************************************************
                                     TCG64
 *****************************************************************************}
 
 {$ifndef cpu64bitalu}
+    function joinreg64(reglo,reghi : tregister) : tregister64;
+      begin
+         result.reglo:=reglo;
+         result.reghi:=reghi;
+      end;
+
+
     procedure tcg64.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
       begin
         a_load64_reg_reg(list,regsrc,regdst);

+ 163 - 5
compiler/cgutils.pas

@@ -43,18 +43,15 @@ unit cgutils;
       { Set type definition for cpuregisters }
       tcpuregisterset = set of 0..maxcpuregister;
 
-{$ifdef jvm}
-      tarrayreftype = (art_none,art_indexreg,art_indexref,art_indexconst);
-{$endif jvm}
       { reference record, reordered for best alignment }
       preference = ^treference;
       treference = record
          offset      : asizeint;
          symbol,
          relsymbol   : tasmsymbol;
-{$if defined(x86) or defined(m68k)}
+{$if defined(x86)}
          segment,
-{$endif defined(x86) or defined(m68k)}
+{$endif defined(x86)}
          base,
          index       : tregister;
          refaddr     : trefaddr;
@@ -174,10 +171,17 @@ unit cgutils;
     procedure location_reset_ref(var l : tlocation;lt:TCGRefLoc;lsize:TCGSize; alignment: longint);
     procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
     procedure location_swap(var destloc,sourceloc : tlocation);
+    function location_reg2string(const locreg: tlocation): string;
 
     { returns r with the given alignment }
     function setalignment(const r : treference;b : byte) : treference;
 
+    { Helper function which calculate "magic" values for replacement of division
+      by constant operation by multiplication. See the "PowerPC compiler developer
+      manual" for more information.
+      N is number of bits to handle, functionality tested for values 32 and 64. }
+    procedure calc_divconst_magic_signed(N: byte; d: aInt; out magic_m: aInt; out magic_s: byte);
+    procedure calc_divconst_magic_unsigned(N: byte; d: aWord; out magic_m: aWord; out magic_add: boolean; out magic_shift: byte);
 
 implementation
 
@@ -271,5 +275,159 @@ uses
       end;
 
 
+    function location_reg2string(const locreg: tlocation): string;
+      begin
+        if not (locreg.loc in [LOC_REGISTER,LOC_CREGISTER,
+            LOC_MMXREGISTER,LOC_CMMXREGISTER,
+            LOC_MMREGISTER,LOC_CMMREGISTER,
+            LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
+          internalerror(2013122301);
+
+        if locreg.loc in [LOC_REGISTER,LOC_CREGISTER] then
+          begin
+            case locreg.size of
+{$if defined(cpu64bitalu)}
+              OS_128,OS_S128:
+                result:=std_regname(locreg.registerhi)+':'+std_regname(locreg.register);
+{$elseif defined(cpu32bitalu)}
+              OS_64,OS_S64:
+                result:=std_regname(locreg.registerhi)+':'+std_regname(locreg.register);
+{$elseif defined(cpu16bitalu)}
+              OS_64,OS_S64:
+                if getsupreg(locreg.register)<first_int_imreg then
+                  result:='??:'+std_regname(locreg.registerhi)+':??:'+std_regname(locreg.register)
+                else
+                  result:=std_regname(GetNextReg(locreg.registerhi))+':'+std_regname(locreg.registerhi)+':'+std_regname(GetNextReg(locreg.register))+':'+std_regname(locreg.register);
+              OS_32,OS_S32:
+                if getsupreg(locreg.register)<first_int_imreg then
+                  result:='??:'+std_regname(locreg.register)
+                else
+                  result:=std_regname(GetNextReg(locreg.register))+':'+std_regname(locreg.register);
+{$elseif defined(cpu8bitalu)}
+              OS_64,OS_S64:
+                if getsupreg(locreg.register)<first_int_imreg then
+                  result:='??:??:??:'+std_regname(locreg.registerhi)+':??:??:??:'+std_regname(locreg.register)
+                else
+                  result:=std_regname(GetNextReg(GetNextReg(GetNextReg(locreg.registerhi))))+':'+std_regname(GetNextReg(GetNextReg(locreg.registerhi)))+':'+std_regname(GetNextReg(locreg.registerhi))+':'+std_regname(locreg.registerhi)+':'+std_regname(GetNextReg(GetNextReg(GetNextReg(locreg.register))))+':'+std_regname(GetNextReg(GetNextReg(locreg.register)))+':'+std_regname(GetNextReg(locreg.register))+':'+std_regname(locreg.register);
+              OS_32,OS_S32:
+                if getsupreg(locreg.register)<first_int_imreg then
+                  result:='??:??:??:'+std_regname(locreg.register)
+                else
+                  result:=std_regname(GetNextReg(GetNextReg(GetNextReg(locreg.register))))+':'+std_regname(GetNextReg(GetNextReg(locreg.register)))+':'+std_regname(GetNextReg(locreg.register))+':'+std_regname(locreg.register);
+              OS_16,OS_S16:
+                if getsupreg(locreg.register)<first_int_imreg then
+                  result:='??:'+std_regname(locreg.register)
+                else
+                  result:=std_regname(GetNextReg(locreg.register))+':'+std_regname(locreg.register);
+{$endif}
+              else
+                result:=std_regname(locreg.register);
+            end;
+          end
+        else
+          begin
+            if locreg.registerhi<>NR_NO then
+              result:=std_regname(locreg.registerhi)+':'+std_regname(locreg.register)
+            else
+              result:=std_regname(locreg.register);
+          end;
+      end;
+
+
+{$push}
+{$r-,q-}
+    procedure calc_divconst_magic_signed(N: byte; d: aInt; out magic_m: aInt; out magic_s: byte);
+      var
+        p: aInt;
+        ad,anc,delta,q1,r1,q2,r2,t: aWord;
+        two_N_minus_1: aWord;
+      begin
+        assert((d<-1) or (d>1));
+        two_N_minus_1:=aWord(1) shl (N-1);
+
+        ad:=abs(d);
+        t:=two_N_minus_1+(aWord(d) shr (N-1));
+        anc:=t-1-t mod ad;               { absolute value of nc }
+        p:=(N-1);                        { initialize p }
+        q1:=two_N_minus_1 div anc;       { initialize q1 = 2**p/abs(nc) }
+        r1:=two_N_minus_1-q1*anc;        { initialize r1 = rem(2**p,abs(nc)) }
+        q2:=two_N_minus_1 div ad;        { initialize q2 = 2**p/abs(d) }
+        r2:=two_N_minus_1-q2*ad;         { initialize r2 = rem(2**p,abs(d)) }
+        repeat
+          inc(p);
+          q1:=2*q1;           { update q1 = 2**p/abs(nc) }
+          r1:=2*r1;           { update r1 = rem(2**p/abs(nc)) }
+          if (r1>=anc) then   { must be unsigned comparison }
+            begin
+              inc(q1);
+              dec(r1,anc);
+            end;
+          q2:=2*q2;           { update q2 = 2p/abs(d) }
+          r2:=2*r2;           { update r2 = rem(2p/abs(d)) }
+          if (r2>=ad) then    { must be unsigned comparison }
+            begin
+              inc(q2);
+              dec(r2,ad);
+            end;
+          delta:=ad-r2;
+        until not ((q1<delta) or ((q1=delta) and (r1=0)));
+        magic_m:=q2+1;
+        if (d<0) then
+          magic_m:=-magic_m;  { resulting magic number }
+        magic_s:=p-N;         { resulting shift }
+      end;
+
+
+    procedure calc_divconst_magic_unsigned(N: byte; d: aWord; out magic_m: aWord; out magic_add: boolean; out magic_shift: byte);
+      var
+        p: aInt;
+        nc,delta,q1,r1,q2,r2,two_N_minus_1 : aWord;
+        mask: aWord;
+      begin
+        two_N_minus_1:=aWord(1) shl (N-1);
+        magic_add:=false;
+{$push}
+{$warnings off }
+        mask:=aWord(not 0) shr ((64-N) and (sizeof(aWord)*8-1));
+        nc:=(mask-(-d) mod aInt(d));
+{$pop}
+        p:=N-1;                       { initialize p }
+        q1:=two_N_minus_1 div nc;     { initialize q1 = 2**p/nc }
+        r1:=two_N_minus_1-q1*nc;      { initialize r1 = rem(2**p,nc) }
+        q2:=(two_N_minus_1-1) div d;  { initialize q2 = (2**p-1)/d }
+        r2:=(two_N_minus_1-1)-q2*d;   { initialize r2 = rem((2**p-1),d) }
+        repeat
+          inc(p);
+          if (r1>=(nc-r1)) then
+            begin
+              q1:=2*q1+1;    { update q1 }
+              r1:=2*r1-nc;   { update r1 }
+            end
+          else
+            begin
+              q1:=2*q1;      { update q1 }
+              r1:=2*r1;      { update r1 }
+            end;
+          if ((r2+1)>=(d-r2)) then
+            begin
+              if (q2>=(two_N_minus_1-1)) then
+                magic_add:=true;
+              q2:=2*q2+1;    { update q2 }
+              r2:=2*r2+1-d;  { update r2 }
+            end
+          else
+            begin
+              if (q2>=two_N_minus_1) then
+                magic_add:=true;
+              q2:=2*q2;      { update q2 }
+              r2:=2*r2+1;    { update r2 }
+            end;
+          delta:=d-1-r2;
+        until not ((p<(2*N)) and ((q1<delta) or ((q1=delta) and (r1=0))));
+        magic_m:=(q2+1) and mask;        { resulting magic number }
+        magic_shift:=p-N;     { resulting shift }
+      end;
+{$pop}
+
 end.
 

+ 4 - 0
compiler/compinnr.inc

@@ -115,6 +115,10 @@ const
    in_arctan_real      = 130;
    in_ln_real          = 131;
    in_sin_real         = 132;
+   in_fma_single       = 133;
+   in_fma_double       = 134;
+   in_fma_extended     = 135;
+   in_fma_float128     = 136;
 
 { MMX functions }
   { these contants are used by the mmx unit }

+ 8 - 1
compiler/constexp.pas

@@ -41,7 +41,7 @@ type  Tconstexprint=record
  build trouble when compiling the directory utils, since the cpu directory
  isn't searched there. Therefore we use a procvar and make verbose install
  the errorhandler. A dependency from verbose on this unit is no problem.}
-var   internalerror:errorproc;
+var   internalerrorproc:errorproc;
 
 {Same issue, avoid dependency on cpuinfo because the cpu directory isn't
  searched during utils building.}
@@ -87,7 +87,14 @@ function tostr(const i:Tconstexprint):shortstring;overload;
 implementation
 {****************************************************************************}
 
+{ use a separate procedure here instead of calling internalerrorproc directly because
+  - procedure variables cannot have a noreturn directive
+  - having a procedure and a procedure variable with the same name in the interfaces of different units is confusing }
+procedure internalerror(i:longint);{$ifndef VER2_6}noreturn;{$endif VER2_6}
 
+begin
+  internalerrorproc(i);
+end;
 
 operator := (const u:qword):Tconstexprint;
 

+ 1 - 4
compiler/crefs.pas

@@ -50,11 +50,8 @@ begin
 end;
 
 Function TRefItem.GetCopy : TLinkedListItem;
-var
-  NR : TRefItem;
 begin
-  NR.Create(RefInfo);
-  GetCopy:=NR;
+  Result:=TRefItem.Create(RefInfo);
 end;
 
 procedure TRefLinkedList.WriteToPPU;

+ 45 - 61
compiler/cresstr.pas

@@ -32,7 +32,7 @@ implementation
 
 uses
    SysUtils,
-   cclasses,
+   cclasses,widestr,
    cutils,globtype,globals,systems,
    symconst,symtype,symdef,symsym,
    verbose,fmodule,ppu,
@@ -64,7 +64,7 @@ uses
         constructor Create;
         destructor  Destroy;override;
         procedure CreateResourceStringData;
-        Procedure WriteResourceFile;
+        procedure WriteRSJFile;
         procedure RegisterResourceStrings;
       end;
 
@@ -214,89 +214,73 @@ uses
           current_asmdata.asmlists[al_resourcestrings].concat(Tai_const.create_sym(endsymlab));
       end;
 
-
-    Procedure Tresourcestrings.WriteResourceFile;
-      Type
-        TMode = (quoted,unquoted);
+    procedure Tresourcestrings.WriteRSJFile;
       Var
-        F : Text;
-        Mode : TMode;
-        R : TResourceStringItem;
-        C : char;
-        Col,i : longint;
-        ResFileName : string;
-
-        Procedure Add(Const S : String);
-        begin
-          Write(F,S);
-          inc(Col,length(s));
-        end;
-
+        F: Text;
+        R: TResourceStringItem;
+        ResFileName: string;
+        I: Integer;
+        C: tcompilerwidechar;
+        W: pcompilerwidestring;
       begin
-        ResFileName:=ChangeFileExt(current_module.ppufilename,'.rst');
+        ResFileName:=ChangeFileExt(current_module.ppufilename,'.rsj');
         message1 (general_i_writingresourcefile,ExtractFileName(ResFileName));
         Assign(F,ResFileName);
         {$push}{$i-}
         Rewrite(f);
         {$pop}
-        If IOresult<>0 then
+        if IOresult<>0 then
           begin
             message1(general_e_errorwritingresourcefile,ResFileName);
             exit;
           end;
+        writeln(f,'{"version":1,"strings":[');
         R:=TResourceStringItem(List.First);
         while assigned(R) do
           begin
-            writeln(f);
-            Writeln(f,'# hash value = ',R.Hash);
-            col:=0;
-            Add(R.Name+'=');
-            Mode:=unquoted;
-            For I:=0 to R.Len-1 do
-             begin
-               C:=R.Value[i];
-               If (ord(C)>31) and (Ord(c)<=128) and (c<>'''') then
-                begin
-                  If mode=Quoted then
-                   Add(c)
+            write(f, '{"hash":',R.Hash,',"name":"',R.Name,'","value":"');
+            initwidestring(W);
+            ascii2unicode(R.Value,R.Len,current_settings.sourcecodepage,W);
+            for I := 0 to W^.len - 1 do
+              begin
+                C := W^.Data[I];
+                case C of
+                  Ord('"'), Ord('\'), Ord('/'):
+                    write(f, '\', Chr(C));
+                  8:
+                    write(f, '\b');
+                  9:
+                    write(f, '\t');
+                  10:
+                    write(f, '\n');
+                  13:
+                    write(f, '\r');
+                  12:
+                    write(f, '\f');
                   else
-                   begin
-                     Add(''''+c);
-                     mode:=quoted
-                   end;
-                end
-               else
-                begin
-                  If Mode=quoted then
-                   begin
-                     Add('''');
-                     mode:=unquoted;
-                   end;
-                  Add('#'+tostr(ord(c)));
-                end;
-               If Col>72 then
-                begin
-                  if mode=quoted then
-                   Write (F,'''');
-                  Writeln(F,'+');
-                  Col:=0;
-                  Mode:=unQuoted;
+                  if (C < 32) or (C > 127) then
+                    write(f,'\u',hexStr(Longint(C), 4))
+                  else
+                    write(f,Chr(C));
                 end;
-             end;
-            if mode=quoted then
-             writeln (f,'''');
-            Writeln(f);
+              end;
+            donewidestring(W);
+            write(f,'"}');
             R:=TResourceStringItem(R.Next);
+            if assigned(R) then
+              writeln(f,',')
+            else
+              writeln(f);
           end;
+        writeln(f,']}');
         close(f);
       end;
 
-
     procedure Tresourcestrings.ConstSym_Register(p:TObject;arg:pointer);
       begin
         if (tsym(p).typ=constsym) and
            (tconstsym(p).consttyp=constresourcestring) then
-          List.Concat(tResourceStringItem.Create(TConstsym(p)));
+          List.Concat(TResourceStringItem.Create(TConstsym(p)));
       end;
 
 
@@ -318,7 +302,7 @@ uses
           begin
             current_module.flags:=current_module.flags or uf_has_resourcestrings;
             resstrs.CreateResourceStringData;
-            resstrs.WriteResourceFile;
+            resstrs.WriteRSJFile;
           end;
         resstrs.Free;
       end;

+ 9 - 1
compiler/cstreams.pas

@@ -450,6 +450,11 @@ begin
           l:=0;
          System.Seek(FHandle,l);
        end;
+     else
+       begin
+         CStreamError:=103;
+         l:=Offset;
+       end;
    end;
   {$pop}
   CStreamError:=IOResult;
@@ -549,7 +554,10 @@ begin
     Result:=FMemory
   else
     If NewCapacity=0 then
-      FreeMem (FMemory,Fcapacity)
+      begin
+        FreeMem (FMemory,Fcapacity);
+        Result:=nil;
+      end
     else
       begin
       GetMem (Result,NewCapacity);

+ 8 - 2
compiler/dbgbase.pas

@@ -418,7 +418,9 @@ implementation
         beforeappendsym(list,sym);
         case sym.typ of
           staticvarsym :
-            appendsym_staticvar(list,tstaticvarsym(sym));
+            if not assigned(tstaticvarsym(sym).fieldvarsym) or
+               not(df_generic in tdef(tstaticvarsym(sym).fieldvarsym.owner.defowner).defoptions) then
+              appendsym_staticvar(list,tstaticvarsym(sym));
           unitsym:
             appendsym_unit(list,tunitsym(sym));
           labelsym :
@@ -527,7 +529,11 @@ implementation
           begin
             sym:=tsym(st.SymList[i]);
             if (sym.visibility<>vis_hidden) and
-               (not sym.isdbgwritten) then
+               (not sym.isdbgwritten) and
+               { avoid all generic symbols }
+               not (sp_generic_dummy in sym.symoptions) and
+               not ((sym.typ=typesym) and assigned(ttypesym(sym).typedef) and
+                    (df_generic in ttypesym(sym).typedef.defoptions)) then
               appendsym(list,sym);
           end;
         case st.symtabletype of

+ 15 - 1
compiler/dbgdwarf.pas

@@ -239,6 +239,16 @@ interface
         DW_FORM_ref_sig8 := $20      { reference }
         );
 
+      { values of DW_AT_address_class }
+      Tdwarf_addr = (
+        DW_ADDR_none := 0,
+        DW_ADDR_near16 := 1,
+        DW_ADDR_far16 := 2,
+        DW_ADDR_huge16 := 3,
+        DW_ADDR_near32 := 4,
+        DW_ADDR_far32 := 5
+      );
+
       TDwarfFile = record
         Index: integer;
         Name: PChar;
@@ -1796,7 +1806,7 @@ implementation
           append_labelentry_ref(DW_AT_type,def_dwarf_lab(cansichartype));
           finish_entry;
           append_entry(DW_TAG_subrange_type,false,[
-            DW_AT_lower_bound,DW_FORM_udata,0,
+            DW_AT_lower_bound,DW_FORM_udata,1,
             DW_AT_upper_bound,DW_FORM_udata,qword(slen)
             ]);
           append_labelentry_ref(DW_AT_type,def_dwarf_lab(lendef));
@@ -2320,6 +2330,8 @@ implementation
         has_high_reg : boolean;
         dreg,dreghigh : byte;
       begin
+        blocksize:=0;
+        dreghigh:=0;
         { external symbols can't be resolved at link time, so we
           can't generate stabs for them
 
@@ -2876,6 +2888,8 @@ implementation
               templist.free;
               exit;
             end;
+          else
+            internalerror(2013120111);
         end;
 
         append_entry(DW_TAG_variable,false,[

+ 16 - 2
compiler/dbgstabs.pas

@@ -76,6 +76,7 @@ interface
         global_stab_number : word;
         vardatadef: trecorddef;
         tagtypeprefix: ansistring;
+        function use_tag_prefix(def : tdef) : boolean;
         { tsym writing }
         function  sym_var_value(const s:string;arg:pointer):string;
         function  sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):ansistring;
@@ -187,6 +188,8 @@ implementation
         result := Sym.Name
       else
         result := Sym.RealName;
+      if (Sym.typ=typesym) and (ttypesym(Sym).Fprettyname<>'') then
+        result:=ttypesym(Sym).FPrettyName;
       if target_asm.dollarsign<>'$' then
         result:=ReplaceForbiddenAsmSymbolChars(result);
     end;
@@ -241,6 +244,7 @@ implementation
       len:=0;
       varcounter:=0;
       varptr:=@varvaluedata[0];
+      varvalues[0]:=nil;
       while i<=length(s) do
         begin
           if (s[i]='$') and (i<length(s)) then
@@ -548,6 +552,16 @@ implementation
           appenddef(TAsmList(arg),tfieldvarsym(p).vardef);
       end;
 
+    function TDebugInfoStabs.use_tag_prefix(def : tdef) : boolean;
+      begin
+        { stringdefs are not all considered as 'taggable',
+          because ansi, unicode and wide strings are
+          just associated to pointer types }
+        use_tag_prefix:=(def.typ in tagtypes) and
+                      ((def.typ<>stringdef) or
+                       (tstringdef(tdef).stringtype in [st_shortstring,st_longstring]));
+      end;
+
 
     procedure TDebugInfoStabs.write_def_stabstr(list:TAsmList;def:tdef;const ss:ansistring);
       var
@@ -556,7 +570,7 @@ implementation
         st    : ansistring;
       begin
         { type prefix }
-        if def.typ in tagtypes then
+        if use_tag_prefix(def) then
           stabchar := tagtypeprefix
         else
           stabchar := 't';
@@ -1582,7 +1596,7 @@ implementation
                 if target_dbg.id=dbg_stabs then
                   st:='s'''+backspace_quote(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']),['"','\',#10,#13])+''''
                 else
-                  st:='s'''+stabx_quote_const(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']))
+                  st:='s'''+stabx_quote_const(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']))+''''
               else
                 st:='<constant string too long>';
             end;

+ 17 - 3
compiler/dbgstabx.pas

@@ -132,7 +132,7 @@ implementation
       st    : ansistring;
     begin
       { type prefix }
-      if def.typ in tagtypes then
+      if use_tag_prefix(def) then
         stabchar := tagtypeprefix
       else
         stabchar := 't';
@@ -274,6 +274,7 @@ implementation
       if vo_is_external in sym.varoptions then
         exit;
       ismem:=not(sym.localloc.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_MMREGISTER,LOC_CMMREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER]);
+      isglobal:=false;
       if ismem then
         isglobal:=current_asmdata.RefAsmSymbol(sym.mangledname).bind=AB_GLOBAL;
 
@@ -299,7 +300,7 @@ implementation
       hp, inclinsertpos, last : tai;
       infile : tinputfile;
       i,
-      linenr,
+      linenr, stabx_func_level,
       nolineinfolevel: longint;
       nextlineisfunstart: boolean;
     begin
@@ -311,6 +312,7 @@ implementation
       hp:=Tai(list.first);
       nextlineisfunstart:=false;
       nolineinfolevel:=0;
+      stabx_func_level:=0;
       last:=nil;
       while assigned(hp) do
         begin
@@ -326,7 +328,11 @@ implementation
               if tai_symbol_end(hp).sym.typ = AT_FUNCTION then
                 begin
                   { end of function }
-                  list.insertbefore(Tai_stab.Create_str(stabx_ef,tostr(currfileinfo.line)),hp);
+                  if stabx_func_level > 0 then
+                    begin
+                      list.insertbefore(Tai_stab.Create_str(stabx_ef,tostr(currfileinfo.line)),hp);
+                      dec(stabx_func_level);
+                    end;
                 end;
             ait_marker :
               begin
@@ -380,6 +386,7 @@ implementation
                         may have been created in another file in case the body
                         is completely declared in an include file }
                       list.insertbefore(Tai_stab.Create_str(stabx_bf,tostr(currfileinfo.line)),hp);
+                      inc(stabx_func_level);
                       { -1 to avoid outputting a relative line 0 in the
                         function, because that means something different }
                       dec(curfunstartfileinfo.line);
@@ -388,6 +395,13 @@ implementation
 
                 end;
 
+              { implicit functions have no file information }
+              if nextlineisfunstart then
+                begin
+                  list.insertbefore(Tai_stab.Create_str(stabx_bf,tostr(currfileinfo.line)),hp);
+                  inc(stabx_func_level);
+                  nextlineisfunstart:=false;
+                end;
               if nolineinfolevel=0 then
                 begin
                   { line changed ? }

+ 214 - 7
compiler/defcmp.pas

@@ -152,12 +152,24 @@ interface
     { parentdef's resultdef                                                          }
     function compatible_childmethod_resultdef(parentretdef, childretdef: tdef): boolean;
 
+    { Checks whether the class impldef or one of its parent classes implements }
+    { the interface intfdef and returns the corresponding "implementation link }
+    function find_implemented_interface(impldef,intfdef:tobjectdef):timplementedinterface;
+
+    { Checks whether to defs are related to each other. Thereby the following  }
+    { cases of curdef are implemented:                                         }
+    { - stringdef: on JVM JLObject, JLString and AnsiString are compatible     }
+    { - recorddef: on JVM records are compatible to java_fpcbaserecordtype     }
+    {              and JLObject                                                }
+    { - objectdef: if it inherits from otherdef or they are equal              }
+    function def_is_related(curdef,otherdef:tdef):boolean;
+
 
 implementation
 
     uses
       verbose,systems,constexp,
-      symtable,symsym,
+      symtable,symsym,symcpu,
       defutil,symutil;
 
 
@@ -201,6 +213,7 @@ implementation
       var
          subeq,eq : tequaltype;
          hd1,hd2 : tdef;
+         def_generic : tstoreddef;
          hct : tconverttype;
          hobjdef : tobjectdef;
          hpd : tprocdef;
@@ -312,6 +325,42 @@ implementation
                  exit;
                end;
            end;
+         { handling of partial specializations }
+         if (
+               (df_generic in def_to.defoptions) and
+               (df_specialization in def_from.defoptions) and
+               (tstoreddef(def_from).genericdef=def_to)
+             ) or (
+               (df_generic in def_from.defoptions) and
+               (df_specialization in def_to.defoptions) and
+               (tstoreddef(def_to).genericdef=def_from)
+             ) then
+           begin
+             if tstoreddef(def_from).genericdef=def_to then
+               def_generic:=tstoreddef(def_to)
+             else
+               def_generic:=tstoreddef(def_from);
+             if not assigned(def_generic.genericparas) then
+               internalerror(2014052306);
+             diff:=false;
+             for i:=0 to def_generic.genericparas.count-1 do
+               begin
+                 symfrom:=tsym(def_generic.genericparas[i]);
+                 if symfrom.typ<>typesym then
+                   internalerror(2014052307);
+                 if ttypesym(symfrom).typedef.typ<>undefineddef then
+                   diff:=true;
+                 if diff then
+                   break;
+               end;
+             if not diff then
+               begin
+                 doconv:=tc_equal;
+                 { the definitions are not exactly the same, but only equal }
+                 compare_defs_ext:=te_equal;
+                 exit;
+               end;
+           end;
 
          { we walk the wanted (def_to) types and check then the def_from
            types if there is a conversion possible }
@@ -1290,7 +1339,7 @@ implementation
                    begin
 {$ifdef x86}
                      { check for far pointers }
-                     if (tpointerdef(def_from).x86pointertyp<>tpointerdef(def_to).x86pointertyp) then
+                     if (tcpupointerdef(def_from).x86pointertyp<>tcpupointerdef(def_to).x86pointertyp) then
                        begin
                          if fromtreetype=niln then
                            eq:=te_equal
@@ -1319,7 +1368,7 @@ implementation
                       if (
                           (tpointerdef(def_from).pointeddef.typ=objectdef) and
                           (tpointerdef(def_to).pointeddef.typ=objectdef) and
-                          tobjectdef(tpointerdef(def_from).pointeddef).is_related(
+                          def_is_related(tobjectdef(tpointerdef(def_from).pointeddef),
                             tobjectdef(tpointerdef(def_to).pointeddef))
                          ) then
                        begin
@@ -1516,7 +1565,7 @@ implementation
              begin
                { object pascal objects }
                if (def_from.typ=objectdef) and
-                  (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
+                  (def_is_related(tobjectdef(def_from),tobjectdef(def_to))) then
                 begin
                   doconv:=tc_equal;
                   { also update in htypechk.pas/var_para_allowed if changed
@@ -1588,7 +1637,7 @@ implementation
                         hobjdef:=tobjectdef(def_from);
                         while assigned(hobjdef) do
                           begin
-                             if hobjdef.find_implemented_interface(tobjectdef(def_to))<>nil then
+                             if find_implemented_interface(hobjdef,tobjectdef(def_to))<>nil then
                                begin
                                   if is_interface(def_to) then
                                     doconv:=tc_class_2_intf
@@ -1663,7 +1712,7 @@ implementation
                     begin
                       doconv:=tc_equal;
                       if (cdo_explicit in cdoptions) or
-                         tobjectdef(tclassrefdef(def_from).pointeddef).is_related(
+                         def_is_related(tobjectdef(tclassrefdef(def_from).pointeddef),
                            tobjectdef(tclassrefdef(def_to).pointeddef)) then
                         eq:=te_convert_l1;
                     end;
@@ -2189,8 +2238,166 @@ implementation
            (childretdef.typ=objectdef) and
            is_class_or_interface_or_objc_or_java(parentretdef) and
            is_class_or_interface_or_objc_or_java(childretdef) and
-           (tobjectdef(childretdef).is_related(tobjectdef(parentretdef))))
+           (def_is_related(tobjectdef(childretdef),tobjectdef(parentretdef))))
       end;
 
 
+    function find_implemented_interface(impldef,intfdef:tobjectdef):timplementedinterface;
+      var
+        implintf : timplementedinterface;
+        i : longint;
+      begin
+        if not assigned(impldef) then
+          internalerror(2013102301);
+        if not assigned(intfdef) then
+          internalerror(2013102302);
+        result:=nil;
+        if not assigned(impldef.implementedinterfaces) then
+          exit;
+        for i:=0 to impldef.implementedinterfaces.count-1 do
+          begin
+            implintf:=timplementedinterface(impldef.implementedinterfaces[i]);
+            if equal_defs(implintf.intfdef,intfdef) then
+              begin
+                result:=implintf;
+                exit;
+              end;
+          end;
+      end;
+
+
+    function stringdef_is_related(curdef:tstringdef;otherdef:tdef):boolean;
+      begin
+        result:=
+          (target_info.system in systems_jvm) and
+          (((curdef.stringtype in [st_unicodestring,st_widestring]) and
+            ((otherdef=java_jlobject) or
+             (otherdef=java_jlstring))) or
+           ((curdef.stringtype=st_ansistring) and
+            ((otherdef=java_jlobject) or
+             (otherdef=java_ansistring))));
+      end;
+
+
+    function recorddef_is_related(curdef:trecorddef;otherdef:tdef):boolean;
+      begin
+        { records are implemented via classes in the JVM target, and are
+          all descendents of the java_fpcbaserecordtype class }
+        result:=false;
+        if (target_info.system in systems_jvm) then
+          begin
+            if otherdef.typ=objectdef then
+              begin
+                otherdef:=find_real_class_definition(tobjectdef(otherdef),false);
+                if (otherdef=java_jlobject) or
+                   (otherdef=java_fpcbaserecordtype) then
+                  result:=true
+              end;
+          end;
+      end;
+
+
+    { true if prot implements d (or if they are equal) }
+    function is_related_interface_multiple(prot:tobjectdef;d:tdef):boolean;
+      var
+        i : longint;
+      begin
+        { objcprotocols have multiple inheritance, all protocols from which
+          the current protocol inherits are stored in implementedinterfaces }
+        result:=prot=d;
+        if result then
+          exit;
+
+        for i:=0 to prot.implementedinterfaces.count-1 do
+          begin
+            result:=is_related_interface_multiple(timplementedinterface(prot.implementedinterfaces[i]).intfdef,d);
+            if result then
+              exit;
+          end;
+      end;
+
+
+    function objectdef_is_related(curdef:tobjectdef;otherdef:tdef):boolean;
+      var
+         realself,
+         hp : tobjectdef;
+      begin
+        if (otherdef.typ=objectdef) then
+          otherdef:=find_real_class_definition(tobjectdef(otherdef),false);
+        realself:=find_real_class_definition(curdef,false);
+        if realself=otherdef then
+          begin
+            result:=true;
+            exit;
+          end;
+
+        if (otherdef.typ<>objectdef) then
+          begin
+            result:=false;
+            exit;
+          end;
+
+        { Objective-C protocols and Java interfaces can use multiple
+           inheritance }
+        if (realself.objecttype in [odt_objcprotocol,odt_interfacejava]) then
+          begin
+            result:=is_related_interface_multiple(realself,otherdef);
+            exit;
+          end;
+
+        { formally declared Objective-C and Java classes match Objective-C/Java
+          classes with the same name. In case of Java, the package must also
+          match (still required even though we looked up the real definitions
+          above, because these may be two different formal declarations that
+          cannot be resolved yet) }
+        if (realself.objecttype in [odt_objcclass,odt_javaclass]) and
+           (tobjectdef(otherdef).objecttype=curdef.objecttype) and
+           ((oo_is_formal in curdef.objectoptions) or
+            (oo_is_formal in tobjectdef(otherdef).objectoptions)) and
+           (curdef.objrealname^=tobjectdef(otherdef).objrealname^) then
+          begin
+            { check package name for Java }
+            if curdef.objecttype=odt_objcclass then
+              result:=true
+            else
+              begin
+                result:=
+                  assigned(curdef.import_lib)=assigned(tobjectdef(otherdef).import_lib);
+                if result and
+                   assigned(curdef.import_lib) then
+                  result:=curdef.import_lib^=tobjectdef(otherdef).import_lib^;
+              end;
+            exit;
+          end;
+
+        hp:=realself.childof;
+        while assigned(hp) do
+          begin
+             if equal_defs(hp,otherdef) then
+               begin
+                  result:=true;
+                  exit;
+               end;
+             hp:=hp.childof;
+          end;
+        result:=false;
+      end;
+
+
+    function def_is_related(curdef,otherdef:tdef):boolean;
+      begin
+        if not assigned(curdef) then
+          internalerror(2013102303);
+        case curdef.typ of
+          stringdef:
+            result:=stringdef_is_related(tstringdef(curdef),otherdef);
+          recorddef:
+            result:=recorddef_is_related(trecorddef(curdef),otherdef);
+          objectdef:
+            result:=objectdef_is_related(tobjectdef(curdef),otherdef);
+          else
+            result:=false;
+        end;
+      end;
+
 end.

+ 24 - 28
compiler/defutil.pas

@@ -228,6 +228,9 @@ interface
     {# Returns true, if definition is a "real" real (i.e. single/double/extended) }
     function is_real(def : tdef) : boolean;
 
+    {# Returns true for single,double,extended and cextended }
+    function is_real_or_cextended(def : tdef) : boolean;
+
     { true, if def is a 8 bit int type }
     function is_8bitint(def : tdef) : boolean;
 
@@ -339,7 +342,7 @@ interface
 implementation
 
     uses
-       verbose,cutils;
+       verbose,cutils,symcpu;
 
     { returns true, if def uses FPU }
     function is_fpu(def : tdef) : boolean;
@@ -395,6 +398,13 @@ implementation
       end;
 
 
+    function is_real_or_cextended(def: tdef): boolean;
+      begin
+        result:=(def.typ=floatdef) and
+          (tfloatdef(def).floattype in [s32real,s64real,s80real,sc80real]);
+      end;
+
+
     function range_to_basetype(l,h:TConstExprInt):tordtype;
       begin
         { prefer signed over unsigned }
@@ -675,10 +685,10 @@ implementation
     { true, if p points to an open array def }
     function is_open_array(p : tdef) : boolean;
       begin
-         { check for s32inttype is needed, because for u32bit the high
+         { check for ptrsinttype is needed, because for unsigned the high
            range is also -1 ! (PFV) }
          result:=(p.typ=arraydef) and
-                 (tarraydef(p).rangedef=s32inttype) and
+                 (tarraydef(p).rangedef=ptrsinttype) and
                  (tarraydef(p).lowrange=0) and
                  (tarraydef(p).highrange=-1) and
                  ((tarraydef(p).arrayoptions * [ado_IsVariant,ado_IsArrayOfConst,ado_IsConstructor,ado_IsDynamicArray])=[]);
@@ -1201,12 +1211,11 @@ implementation
                 result:=tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
             end;
           classrefdef,
-          pointerdef,
-          formaldef:
+          pointerdef:
             begin
 {$ifdef x86}
               if (def.typ=pointerdef) and
-                 (tpointerdef(def).x86pointertyp in [x86pt_far,x86pt_huge]) then
+                 (tcpupointerdef(def).x86pointertyp in [x86pt_far,x86pt_huge]) then
                 begin
                   {$if defined(i8086)}
                     result := OS_32;
@@ -1218,24 +1227,16 @@ implementation
                 end
               else
 {$endif x86}
-                result := OS_ADDR;
+                result := int_cgsize(def.size);
             end;
+          formaldef:
+            result := int_cgsize(voidpointertype.size);
           procvardef:
             result:=int_cgsize(def.size);
           stringdef :
-            begin
-              if is_ansistring(def) or is_wide_or_unicode_string(def) then
-                result := OS_ADDR
-              else
-                result:=int_cgsize(def.size);
-            end;
+            result:=int_cgsize(def.size);
           objectdef :
-            begin
-              if is_implicit_pointer_object_type(def) then
-                result := OS_ADDR
-              else
-                result:=int_cgsize(def.size);
-            end;
+            result:=int_cgsize(def.size);
           floatdef:
             if cs_fp_emulation in current_settings.moduleswitches then
               result:=int_cgsize(def.size)
@@ -1245,15 +1246,10 @@ implementation
             result:=int_cgsize(def.size);
           arraydef :
             begin
-              if not is_special_array(def) then
+              if is_dynamic_array(def) or not is_special_array(def) then
                 result := int_cgsize(def.size)
               else
-                begin
-                  if is_dynamic_array(def) then
-                    result := OS_ADDR
-                  else
-                    result := OS_NO;
-                end;
+                result := OS_NO;
             end;
           else
             begin
@@ -1441,13 +1437,13 @@ implementation
     { true if p is a far pointer def }
     function is_farpointer(p : tdef) : boolean;
       begin
-        result:=(p.typ=pointerdef) and (tpointerdef(p).x86pointertyp=x86pt_far);
+        result:=(p.typ=pointerdef) and (tcpupointerdef(p).x86pointertyp=x86pt_far);
       end;
 
     { true if p is a huge pointer def }
     function is_hugepointer(p : tdef) : boolean;
       begin
-        result:=(p.typ=pointerdef) and (tpointerdef(p).x86pointertyp=x86pt_huge);
+        result:=(p.typ=pointerdef) and (tcpupointerdef(p).x86pointertyp=x86pt_huge);
       end;
 {$endif i8086}
 

+ 335 - 0
compiler/dirparse.pas

@@ -0,0 +1,335 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    This unit implements some support functions for the parsing of directives
+    and option strings
+
+    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 dirparse;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      globtype,
+      systems;
+
+    function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
+    function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
+    function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
+    function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
+    function UpdateTargetSwitchStr(s: string; var a: ttargetswitches; global: boolean): boolean;
+
+implementation
+
+    uses
+      globals,
+      cutils,
+      symtable;
+
+    function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
+      var
+        tok  : string;
+        vstr : string;
+        l    : longint;
+        code : integer;
+        b    : talignmentinfo;
+      begin
+        UpdateAlignmentStr:=true;
+        uppervar(s);
+        fillchar(b,sizeof(b),0);
+        repeat
+          tok:=GetToken(s,'=');
+          if tok='' then
+           break;
+          vstr:=GetToken(s,',');
+          val(vstr,l,code);
+          if tok='PROC' then
+           b.procalign:=l
+          else if tok='JUMP' then
+           b.jumpalign:=l
+          else if tok='LOOP' then
+           b.loopalign:=l
+          else if tok='CONSTMIN' then
+           begin
+             b.constalignmin:=l;
+             if l>b.constalignmax then
+               b.constalignmax:=l;
+           end
+          else if tok='CONSTMAX' then
+           b.constalignmax:=l
+          else if tok='VARMIN' then
+           begin
+             b.varalignmin:=l;
+             if l>b.varalignmax then
+               b.varalignmax:=l;
+           end
+          else if tok='VARMAX' then
+           b.varalignmax:=l
+          else if tok='LOCALMIN' then
+           begin
+             b.localalignmin:=l;
+             if l>b.localalignmax then
+               b.localalignmax:=l;
+           end
+          else if tok='LOCALMAX' then
+           b.localalignmax:=l
+          else if tok='RECORDMIN' then
+           begin
+             b.recordalignmin:=l;
+             if l>b.recordalignmax then
+               b.recordalignmax:=l;
+           end
+          else if tok='RECORDMAX' then
+           b.recordalignmax:=l
+          else { Error }
+           UpdateAlignmentStr:=false;
+        until false;
+        Result:=Result and UpdateAlignment(a,b);
+      end;
+
+
+    function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
+      var
+        tok   : string;
+        doset,
+        found : boolean;
+        opt   : toptimizerswitch;
+      begin
+        result:=true;
+        uppervar(s);
+        repeat
+          tok:=GetToken(s,',');
+          if tok='' then
+           break;
+          if Copy(tok,1,2)='NO' then
+            begin
+              delete(tok,1,2);
+              doset:=false;
+            end
+          else
+            doset:=true;
+          found:=false;
+          for opt:=low(toptimizerswitch) to high(toptimizerswitch) do
+            begin
+              if OptimizerSwitchStr[opt]=tok then
+                begin
+                  found:=true;
+                  break;
+                end;
+            end;
+          if found then
+            begin
+              if doset then
+                include(a,opt)
+              else
+                exclude(a,opt);
+            end
+          else
+            result:=false;
+        until false;
+      end;
+
+
+    function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
+      var
+        tok   : string;
+        doset,
+        found : boolean;
+        opt   : twpoptimizerswitch;
+      begin
+        result:=true;
+        uppervar(s);
+        repeat
+          tok:=GetToken(s,',');
+          if tok='' then
+           break;
+          if Copy(tok,1,2)='NO' then
+            begin
+              delete(tok,1,2);
+              doset:=false;
+            end
+          else
+            doset:=true;
+          found:=false;
+          if (tok = 'ALL') then
+            begin
+              for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
+                if doset then
+                  include(a,opt)
+                else
+                  exclude(a,opt);
+            end
+          else
+            begin
+              for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
+                begin
+                  if WPOptimizerSwitchStr[opt]=tok then
+                    begin
+                      found:=true;
+                      break;
+                    end;
+                end;
+              if found then
+                begin
+                  if doset then
+                    include(a,opt)
+                  else
+                    exclude(a,opt);
+                end
+              else
+                result:=false;
+            end;
+        until false;
+      end;
+
+
+    function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
+      var
+        tok   : string;
+        doset,
+        found : boolean;
+        opt   : tdebugswitch;
+      begin
+        result:=true;
+        uppervar(s);
+        repeat
+          tok:=GetToken(s,',');
+          if tok='' then
+           break;
+          if Copy(tok,1,2)='NO' then
+            begin
+              delete(tok,1,2);
+              doset:=false;
+            end
+          else
+            doset:=true;
+          found:=false;
+          for opt:=low(tdebugswitch) to high(tdebugswitch) do
+            begin
+              if DebugSwitchStr[opt]=tok then
+                begin
+                  found:=true;
+                  break;
+                end;
+            end;
+          if found then
+            begin
+              if doset then
+                include(a,opt)
+              else
+                exclude(a,opt);
+            end
+          else
+            result:=false;
+        until false;
+      end;
+
+
+    function UpdateTargetSwitchStr(s: string; var a: ttargetswitches; global: boolean): boolean;
+      var
+        tok,
+        value : string;
+        setstr: string[2];
+        equalspos: longint;
+        doset,
+        gotvalue,
+        found : boolean;
+        opt   : ttargetswitch;
+      begin
+        result:=true;
+        value:='';
+        repeat
+          tok:=GetToken(s,',');
+          if tok='' then
+           break;
+          setstr:=upper(copy(tok,length(tok),1));
+          if setstr='-' then
+            begin
+              setlength(tok,length(tok)-1);
+              doset:=false;
+            end
+          else
+            doset:=true;
+          { value specified? }
+          gotvalue:=false;
+          equalspos:=pos('=',tok);
+          if equalspos<>0 then
+            begin
+              value:=copy(tok,equalspos+1,length(tok));
+              delete(tok,equalspos,length(tok));
+              gotvalue:=true;
+            end;
+          found:=false;
+          uppervar(tok);
+          for opt:=low(ttargetswitch) to high(ttargetswitch) do
+            begin
+              if TargetSwitchStr[opt].name=tok then
+                begin
+                  found:=true;
+                  break;
+                end;
+            end;
+          if found then
+            begin
+              if not global and
+                 TargetSwitchStr[opt].isglobal then
+                result:=false
+              else if not TargetSwitchStr[opt].hasvalue then
+                begin
+                  if gotvalue then
+                    result:=false;
+                  if (TargetSwitchStr[opt].define<>'') and (doset xor (opt in a)) then
+                    if doset then
+                      def_system_macro(TargetSwitchStr[opt].define)
+                    else
+                      undef_system_macro(TargetSwitchStr[opt].define);
+                  if doset then
+                    include(a,opt)
+                  else
+                    exclude(a,opt)
+                end
+              else
+                begin
+                  if not gotvalue or
+                     not doset then
+                    result:=false
+                  else
+                    begin
+                      case opt of
+                        ts_auto_getter_prefix:
+                          prop_auto_getter_prefix:=value;
+                        ts_auto_setter_predix:
+                          prop_auto_setter_prefix:=value;
+                        else
+                          begin
+                            writeln('Internalerror 2012053001');
+                            halt(1);
+                          end;
+                      end;
+                    end;
+                end;
+            end
+          else
+            result:=false;
+        until false;
+      end;
+
+end.

+ 7 - 15
compiler/finput.pas

@@ -226,7 +226,7 @@ uses
          close;
       { free memory }
         if assigned(linebuf) then
-         freemem(linebuf,maxlinebuf shl 2);
+         freemem(linebuf,maxlinebuf*sizeof(linebuf^[0]));
       end;
 
 
@@ -368,24 +368,16 @@ uses
 
 
     procedure tinputfile.setline(line,linepos:longint);
-      var
-        oldlinebuf  : plongintarr;
       begin
         if line<1 then
          exit;
         while (line>=maxlinebuf) do
-         begin
-           oldlinebuf:=linebuf;
-         { create new linebuf and move old info }
-           getmem(linebuf,(maxlinebuf+linebufincrease) shl 2);
-           if assigned(oldlinebuf) then
-            begin
-              move(oldlinebuf^,linebuf^,maxlinebuf shl 2);
-              freemem(oldlinebuf,maxlinebuf shl 2);
-            end;
-           fillchar(linebuf^[maxlinebuf],linebufincrease shl 2,0);
-           inc(maxlinebuf,linebufincrease);
-         end;
+          begin
+            { create new linebuf and move old info }
+            linebuf:=reallocmem(linebuf,(maxlinebuf+linebufincrease)*sizeof(linebuf^[0]));
+            fillchar(linebuf^[maxlinebuf],linebufincrease*sizeof(linebuf^[0]),0);
+            inc(maxlinebuf,linebufincrease);
+          end;
         linebuf^[line]:=linepos;
       end;
 

+ 22 - 17
compiler/fmodule.pas

@@ -221,7 +221,6 @@ interface
         procedure flagdependent(callermodule:tmodule);
         function  addusedunit(hp:tmodule;inuses:boolean;usym:tunitsym):tused_unit;
         procedure updatemaps;
-        procedure check_hints;
         function  derefidx_unit(id:longint):longint;
         function  resolve_unit(id:longint):tmodule;
         procedure allunitsused;
@@ -240,6 +239,7 @@ interface
           u               : tmodule;
           unitsym         : tunitsym;
           constructor create(_u : tmodule;intface,inuses:boolean;usym:tunitsym);
+          procedure check_hints;
        end;
 
        tdependent_unit = class(tlinkedlistitem)
@@ -475,6 +475,27 @@ implementation
       end;
 
 
+    procedure tused_unit.check_hints;
+      var
+        uname: pshortstring;
+      begin
+        uname:=u.realmodulename;
+        if mo_hint_deprecated in u.moduleoptions then
+          if (mo_has_deprecated_msg in u.moduleoptions) and (u.deprecatedmsg <> nil) then
+            MessagePos2(unitsym.fileinfo,sym_w_deprecated_unit_with_msg,uname^,u.deprecatedmsg^)
+          else
+            MessagePos1(unitsym.fileinfo,sym_w_deprecated_unit,uname^);
+        if mo_hint_experimental in u.moduleoptions then
+          MessagePos1(unitsym.fileinfo,sym_w_experimental_unit,uname^);
+        if mo_hint_platform in u.moduleoptions then
+          MessagePos1(unitsym.fileinfo,sym_w_non_portable_unit,uname^);
+        if mo_hint_library in u.moduleoptions then
+          MessagePos1(unitsym.fileinfo,sym_w_library_unit,uname^);
+        if mo_hint_unimplemented in u.moduleoptions then
+          MessagePos1(unitsym.fileinfo,sym_w_non_implemented_unit,uname^);
+      end;
+
+
 {****************************************************************************
                             TDENPENDENT_UNIT
  ****************************************************************************}
@@ -899,22 +920,6 @@ implementation
           end;
       end;
 
-    procedure tmodule.check_hints;
-      begin
-        if mo_hint_deprecated in moduleoptions then
-          if (mo_has_deprecated_msg in moduleoptions) and (deprecatedmsg <> nil) then
-            Message2(sym_w_deprecated_unit_with_msg,realmodulename^,deprecatedmsg^)
-          else
-            Message1(sym_w_deprecated_unit,realmodulename^);
-        if mo_hint_experimental in moduleoptions then
-          Message1(sym_w_experimental_unit,realmodulename^);
-        if mo_hint_platform in moduleoptions then
-          Message1(sym_w_non_portable_unit,realmodulename^);
-        if mo_hint_library in moduleoptions then
-          Message1(sym_w_library_unit,realmodulename^);
-        if mo_hint_unimplemented in moduleoptions then
-          Message1(sym_w_non_implemented_unit,realmodulename^);
-      end;
 
 
     function tmodule.derefidx_unit(id:longint):longint;

+ 5 - 3
compiler/fpcdefs.inc

@@ -74,6 +74,7 @@
   {$define cpurox}
   {$define SUPPORT_SAFECALL}
   {$define SUPPORT_GET_FRAME}
+  {$define cpucapabilities}
 {$endif i386}
 
 {$ifdef x86_64}
@@ -89,6 +90,7 @@
   {$define cpurefshaveindexreg}
   {$define SUPPORT_SAFECALL}
   {$define SUPPORT_GET_FRAME}
+  {$define cpucapabilities}
 {$endif x86_64}
 
 {$ifdef ia64}
@@ -124,7 +126,6 @@
   {$define cpumm}
   {$define cpurox}
   {$define cpurefshaveindexreg}
-  {$define fpc_compiler_has_fixup_jmps}
 {$endif powerpc}
 
 {$ifdef powerpc64}
@@ -135,7 +136,7 @@
   {$define cpumm}
   {$define cpurox}
   {$define cpurefshaveindexreg}
-  {$define fpc_compiler_has_fixup_jmps}
+  {$define cpuno32bitops}
 {$endif powerpc64}
 
 {$ifdef arm}
@@ -177,6 +178,7 @@
   {$define cpufpemu}
   {$define cpurefshaveindexreg}
   {$define cpucapabilities}
+  {$define cpuneedsdiv32helper}
 {$endif m68k}
 
 {$ifdef avr}
@@ -219,8 +221,8 @@
   {$define cpurequiresproperalignment}
   { define cpumm}
   {$define cpurefshaveindexreg}
-  {$define fpc_compiler_has_fixup_jmps}
   {$define SUPPORT_GET_FRAME}
+  {$define SUPPORT_SAFECALL}
 {$endif mips}
 
 {$ifdef jvm}

+ 11 - 1
compiler/fppu.pas

@@ -108,7 +108,7 @@ interface
 implementation
 
 uses
-  SysUtils,strutils,
+  SysUtils,
   cfileutl,
   systems,version,
   symtable, symsym,
@@ -256,6 +256,14 @@ var
            Message(unit_u_ppu_invalid_memory_model,@queuecomment);
            exit;
          end;
+        if ((ppufile.header.flags and uf_i8086_cs_equals_ds)<>0) xor
+            (current_settings.x86memorymodel=mm_tiny) then
+         begin
+           ppufile.free;
+           ppufile:=nil;
+           Message(unit_u_ppu_invalid_memory_model,@queuecomment);
+           exit;
+         end;
 {$endif i8086}
 {$ifdef cpufpemu}
        { check if floating point emulation is on?
@@ -1095,6 +1103,8 @@ var
            flags:=flags or uf_i8086_far_data;
          if current_settings.x86memorymodel=mm_huge then
            flags:=flags or uf_i8086_huge_data;
+         if current_settings.x86memorymodel=mm_tiny then
+           flags:=flags or uf_i8086_cs_equals_ds;
 {$endif i8086}
 {$ifdef cpufpemu}
          if (cs_fp_emulation in current_settings.moduleswitches) then

+ 211 - 0
compiler/generic/symcpu.pas

@@ -0,0 +1,211 @@
+{
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Symbol table overrides for <generic>
+
+    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 = @<somestandardfloattype>;
+
+
+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.
+

+ 29 - 221
compiler/globals.pas

@@ -163,9 +163,9 @@ interface
 {$endif defined(ARM)}
 
         { CPU targets with microcontroller support can add a controller specific unit }
-{$if defined(ARM) or defined(AVR)}
+{$if defined(ARM) or defined(AVR) or defined(MIPSEL)}
          controllertype   : tcontrollertype;
-{$endif defined(ARM) or defined(AVR)}
+{$endif defined(ARM) or defined(AVR) or defined(MIPSEL)}
          { WARNING: this pointer cannot be written as such in record token }
          pmessage : pmessagestaterecord;
        end;
@@ -228,6 +228,9 @@ interface
        wpofeedbackinput,
        wpofeedbackoutput : TPathStr;
 
+       { external assembler extra option }
+       asmextraopt       : string;
+
        { things specified with parameters }
        paratarget        : tsystem;
        paratargetdbg     : tdbg;
@@ -253,8 +256,11 @@ interface
        do_build,
        do_release,
        do_make       : boolean;
+       { Path to ppc }
+       exepath       : TPathStr;
+       { Path to unicode charmap/collation binaries }
+       unicodepath   : TPathStr;
        { path for searching units, different paths can be seperated by ; }
-       exepath            : TPathStr;  { Path to ppc }
        librarysearchpath,
        unitsearchpath,
        objectsearchpath,
@@ -316,6 +322,7 @@ interface
        pendingstate       : tpendingstate;
      { Memory sizes }
        heapsize,
+       maxheapsize,
        stacksize,
        jmp_buf_size,
        jmp_buf_align : longint;
@@ -324,7 +331,7 @@ interface
      { parameter switches }
        debugstop : boolean;
 {$EndIf EXTDEBUG}
-       { Application type (platform specific) 
+       { Application type (platform specific)
          see globtype.pas for description }
        apptype : tapptype;
 
@@ -387,7 +394,7 @@ interface
         globalswitches : [cs_check_unit_name,cs_link_static];
         targetswitches : [];
         moduleswitches : [cs_extsyntax,cs_implicit_exceptions];
-        localswitches : [cs_check_io,cs_typed_const_writable,cs_pointermath];
+        localswitches : [cs_check_io,cs_typed_const_writable,cs_pointermath{$ifdef i8086},cs_force_far_calls{$endif}];
         modeswitches : fpcmodeswitches;
         optimizerswitches : [];
         genwpoptimizerswitches : [];
@@ -397,7 +404,11 @@ interface
         setalloc : 0;
         packenum : 4;
 
+{$ifdef i8086}
+        packrecords     : 1;
+{$else i8086}
         packrecords     : 0;
+{$endif i8086}
         maxfpuregisters : 0;
 
 { Note: GENERIC_CPU is sued together with generic subdirectory to
@@ -491,9 +502,9 @@ interface
 {$if defined(ARM)}
         instructionset : is_arm;
 {$endif defined(ARM)}
-{$if defined(ARM) or defined(AVR)}
+{$if defined(ARM) or defined(AVR) or defined(MIPSEL)}
         controllertype : ct_none;
-{$endif defined(ARM) or defined(AVR)}
+{$endif defined(ARM) or defined(AVR) or defined(MIPSEL)}
         pmessage : nil;
       );
 
@@ -525,13 +536,9 @@ interface
     function Setoptimizecputype(const s:string;var a:tcputype):boolean;
     function Setcputype(const s:string;var a:tsettings):boolean;
     function SetFpuType(const s:string;var a:tfputype):boolean;
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(mipsel)}
     function SetControllerType(const s:string;var a:tcontrollertype):boolean;
-{$endif defined(arm) or defined(avr)}
-    function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
-    function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
-    function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
-    function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
+{$endif defined(arm) or defined(avr) or defined(mipsel)}
     function IncludeFeature(const s : string) : boolean;
     function SetMinFPConstPrec(const s: string; var a: tfloattype) : boolean;
 
@@ -560,11 +567,7 @@ implementation
       macutils,
 {$endif}
 {$ifdef mswindows}
-{$ifdef VER2_4}
-      cwindirs,
-{$else VER2_4}
       windirs,
-{$endif VER2_4}
 {$endif}
       comphook;
 
@@ -916,7 +919,7 @@ implementation
         {$undef GETENVOK}
       {$else}
         GetEnvPchar:=StrPNew(GetEnvironmentVariable(envname));
-        if (length(GetEnvPChar)=0) then 
+        if (length(GetEnvPChar)=0) then
           begin
             FreeEnvPChar(GetEnvPChar);
             GetEnvPChar:=nil;
@@ -1107,7 +1110,9 @@ implementation
              (abiinfo[t].name=hs) then
             begin
               a:=t;
-              result:=true;
+              { abi_old_win32_gnu is a win32 i386 specific "feature" }
+              if (t<>abi_old_win32_gnu) or (target_info.system=system_i386_win32) then
+                result:=true;
               break;
             end;
       end;
@@ -1148,7 +1153,7 @@ implementation
         { set default instruction set for arm }
         if result then
           begin
-            if a.cputype in [cpu_armv6m,cpu_armv6t2,cpu_armv7m] then
+            if a.cputype in [cpu_armv6m,cpu_armv6t2,cpu_armv7m,cpu_armv7em] then
               a.instructionset:=is_thumb
             else
               a.instructionset:=is_arm;
@@ -1172,7 +1177,7 @@ implementation
       end;
 
 
-{$if defined(arm) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(mipsel)}
     function SetControllerType(const s:string;var a:tcontrollertype):boolean;
       var
         t  : tcontrollertype;
@@ -1188,206 +1193,7 @@ implementation
               break;
             end;
       end;
-{$endif defined(arm) or defined(avr)}
-
-
-    function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
-      var
-        tok  : string;
-        vstr : string;
-        l    : longint;
-        code : integer;
-        b    : talignmentinfo;
-      begin
-        UpdateAlignmentStr:=true;
-        uppervar(s);
-        fillchar(b,sizeof(b),0);
-        repeat
-          tok:=GetToken(s,'=');
-          if tok='' then
-           break;
-          vstr:=GetToken(s,',');
-          val(vstr,l,code);
-          if tok='PROC' then
-           b.procalign:=l
-          else if tok='JUMP' then
-           b.jumpalign:=l
-          else if tok='LOOP' then
-           b.loopalign:=l
-          else if tok='CONSTMIN' then
-           begin
-             b.constalignmin:=l;
-             if l>b.constalignmax then
-               b.constalignmax:=l;
-           end
-          else if tok='CONSTMAX' then
-           b.constalignmax:=l
-          else if tok='VARMIN' then
-           begin
-             b.varalignmin:=l;
-             if l>b.varalignmax then
-               b.varalignmax:=l;
-           end
-          else if tok='VARMAX' then
-           b.varalignmax:=l
-          else if tok='LOCALMIN' then
-           begin
-             b.localalignmin:=l;
-             if l>b.localalignmax then
-               b.localalignmax:=l;
-           end
-          else if tok='LOCALMAX' then
-           b.localalignmax:=l
-          else if tok='RECORDMIN' then
-           begin
-             b.recordalignmin:=l;
-             if l>b.recordalignmax then
-               b.recordalignmax:=l;
-           end
-          else if tok='RECORDMAX' then
-           b.recordalignmax:=l
-          else { Error }
-           UpdateAlignmentStr:=false;
-        until false;
-        Result:=Result and UpdateAlignment(a,b);
-      end;
-
-
-    function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
-      var
-        tok   : string;
-        doset,
-        found : boolean;
-        opt   : toptimizerswitch;
-      begin
-        result:=true;
-        uppervar(s);
-        repeat
-          tok:=GetToken(s,',');
-          if tok='' then
-           break;
-          if Copy(tok,1,2)='NO' then
-            begin
-              delete(tok,1,2);
-              doset:=false;
-            end
-          else
-            doset:=true;
-          found:=false;
-          for opt:=low(toptimizerswitch) to high(toptimizerswitch) do
-            begin
-              if OptimizerSwitchStr[opt]=tok then
-                begin
-                  found:=true;
-                  break;
-                end;
-            end;
-          if found then
-            begin
-              if doset then
-                include(a,opt)
-              else
-                exclude(a,opt);
-            end
-          else
-            result:=false;
-        until false;
-      end;
-
-
-    function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
-      var
-        tok   : string;
-        doset,
-        found : boolean;
-        opt   : twpoptimizerswitch;
-      begin
-        result:=true;
-        uppervar(s);
-        repeat
-          tok:=GetToken(s,',');
-          if tok='' then
-           break;
-          if Copy(tok,1,2)='NO' then
-            begin
-              delete(tok,1,2);
-              doset:=false;
-            end
-          else
-            doset:=true;
-          found:=false;
-          if (tok = 'ALL') then
-            begin
-              for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
-                if doset then
-                  include(a,opt)
-                else
-                  exclude(a,opt);
-            end
-          else
-            begin
-              for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
-                begin
-                  if WPOptimizerSwitchStr[opt]=tok then
-                    begin
-                      found:=true;
-                      break;
-                    end;
-                end;
-              if found then
-                begin
-                  if doset then
-                    include(a,opt)
-                  else
-                    exclude(a,opt);
-                end
-              else
-                result:=false;
-            end;
-        until false;
-      end;
-
-
-    function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
-      var
-        tok   : string;
-        doset,
-        found : boolean;
-        opt   : tdebugswitch;
-      begin
-        result:=true;
-        uppervar(s);
-        repeat
-          tok:=GetToken(s,',');
-          if tok='' then
-           break;
-          if Copy(tok,1,2)='NO' then
-            begin
-              delete(tok,1,2);
-              doset:=false;
-            end
-          else
-            doset:=true;
-          found:=false;
-          for opt:=low(tdebugswitch) to high(tdebugswitch) do
-            begin
-              if DebugSwitchStr[opt]=tok then
-                begin
-                  found:=true;
-                  break;
-                end;
-            end;
-          if found then
-            begin
-              if doset then
-                include(a,opt)
-              else
-                exclude(a,opt);
-            end
-          else
-            result:=false;
-        until false;
-      end;
+{$endif defined(arm) or defined(avr) or defined(mipsel)}
 
 
     function IncludeFeature(const s : string) : boolean;
@@ -1498,6 +1304,7 @@ implementation
 {$endif need_path_search}
      begin
        localexepath:=GetEnvironmentVariable('PPC_EXEC_PATH');
+       exeName := '';
        if localexepath='' then
          begin
            exeName := FixFileName(system.paramstr(0));
@@ -1563,6 +1370,7 @@ implementation
         sysrootpath:='';
 
         { Search Paths }
+        unicodepath:='';
         librarysearchpath:=TSearchPathList.Create;
         unitsearchpath:=TSearchPathList.Create;
         includesearchpath:=TSearchPathList.Create;

+ 36 - 18
compiler/globtype.pas

@@ -143,7 +143,11 @@ interface
          cs_external_var, cs_externally_visible,
          { jvm specific }
          cs_check_var_copyout,
-         cs_zerobasedstrings
+         cs_zerobasedstrings,
+         { i8086 specific }
+         cs_force_far_calls,
+         cs_hugeptr_arithmetic_normalization,
+         cs_hugeptr_comparison_normalization
        );
        tlocalswitches = set of tlocalswitch;
 
@@ -162,7 +166,9 @@ interface
          { browser switches are back }
          cs_browser,cs_local_browser,
          { target specific }
-         cs_executable_stack
+         cs_executable_stack,
+         { i8086 specific }
+         cs_huge_code
        );
        tmoduleswitches = set of tmoduleswitch;
 
@@ -253,7 +259,8 @@ interface
          f_heap,f_init_final,f_rtti,f_classes,f_exceptions,f_exitcode,
          f_ansistrings,f_widestrings,f_textio,f_consoleio,f_fileio,
          f_random,f_variants,f_objects,f_dynarrays,f_threading,f_commandargs,
-         f_processes,f_stackcheck,f_dynlibs,f_softfpu,f_objectivec1,f_resources
+         f_processes,f_stackcheck,f_dynlibs,f_softfpu,f_objectivec1,f_resources,
+         f_unicodestring
        );
        tfeatures = set of tfeature;
 
@@ -263,7 +270,7 @@ interface
          cs_opt_level1,cs_opt_level2,cs_opt_level3,
          cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
          cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse,
-         cs_opt_nodedfa,cs_opt_loopstrength,cs_opt_scheduler,cs_opt_autoinline,cs_useebp,
+         cs_opt_nodedfa,cs_opt_loopstrength,cs_opt_scheduler,cs_opt_autoinline,cs_useebp,cs_userbp,
          cs_opt_reorder_fields,cs_opt_fastmath,
          { Allow removing expressions whose result is not used, even when this
            can change program behaviour (range check errors disappear,
@@ -274,7 +281,10 @@ interface
          }
          cs_opt_dead_values,
          { compiler checks for empty procedures/methods and removes calls to them if possible }
-         cs_opt_remove_emtpy_proc
+         cs_opt_remove_emtpy_proc,
+         cs_opt_constant_propagate,
+         cs_opt_dead_store_eliminate,
+         cs_opt_forcenostackframe
        );
        toptimizerswitches = set of toptimizerswitch;
 
@@ -286,10 +296,10 @@ interface
        twpoptimizerswitches = set of twpoptimizerswitch;
 
     type
-       { Used by ARM / AVR to differentiate between specific microcontrollers }
+       { Used by ARM / AVR / MIPSEL to differentiate between specific microcontrollers }
        tcontrollerdatatype = record
           controllertypestr, controllerunitstr: string[20];
-          flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize: dword;
+          flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize, bootbase, bootsize: dword;
        end;
 
        ttargetswitchinfo = record
@@ -302,12 +312,14 @@ interface
        end;
 
     const
-       OptimizerSwitchStr : array[toptimizerswitch] of string[16] = ('',
+       OptimizerSwitchStr : array[toptimizerswitch] of string[17] = ('',
          'LEVEL1','LEVEL2','LEVEL3',
          'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
          'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE',
-         'DFA','STRENGTH','SCHEDULE','AUTOINLINE','USEEBP',
-         'ORDERFIELDS','FASTMATH','DEADVALUES','REMOVEEMPTYPROCS'
+         'DFA','STRENGTH','SCHEDULE','AUTOINLINE','USEEBP','USERBP',
+         'ORDERFIELDS','FASTMATH','DEADVALUES','REMOVEEMPTYPROCS',
+         'CONSTPROP',
+         'DEADSTORE','FORCENOSTACKFRAME'
        );
        WPOptimizerSwitchStr : array [twpoptimizerswitch] of string[14] = (
          'DEVIRTCALLS','OPTVMTS','SYMBOLLIVENESS'
@@ -330,9 +342,9 @@ interface
        );
 
        { switches being applied to all CPUs at the given level }
-       genericlevel1optimizerswitches = [cs_opt_level1];
+       genericlevel1optimizerswitches = [cs_opt_level1,cs_opt_peephole];
        genericlevel2optimizerswitches = [cs_opt_level2,cs_opt_remove_emtpy_proc];
-       genericlevel3optimizerswitches = [cs_opt_level3];
+       genericlevel3optimizerswitches = [cs_opt_level3,cs_opt_constant_propagate,cs_opt_nodedfa];
        genericlevel4optimizerswitches = [cs_opt_reorder_fields,cs_opt_dead_values,cs_opt_fastmath];
 
        { whole program optimizations whose information generation requires
@@ -340,11 +352,12 @@ interface
        }
        WPOptimizationsNeedingAllUnitInfo = [cs_wpo_devirtualize_calls,cs_wpo_optimize_vmts];
 
-       featurestr : array[tfeature] of string[12] = (
+       featurestr : array[tfeature] of string[14] = (
          'HEAP','INITFINAL','RTTI','CLASSES','EXCEPTIONS','EXITCODE',
          'ANSISTRINGS','WIDESTRINGS','TEXTIO','CONSOLEIO','FILEIO',
          'RANDOM','VARIANTS','OBJECTS','DYNARRAYS','THREADING','COMMANDARGS',
-         'PROCESSES','STACKCHECK','DYNLIBS','SOFTFPU','OBJECTIVEC1','RESOURCES'
+         'PROCESSES','STACKCHECK','DYNLIBS','SOFTFPU','OBJECTIVEC1','RESOURCES',
+         'UNICODESTRINGS'
        );
 
     type
@@ -385,8 +398,10 @@ interface
          m_final_fields,        { allows declaring fields as "final", which means they must be initialised
                                   in the (class) constructor and are constant from then on (same as final
                                   fields in Java) }
-         m_default_unicodestring { makes the default string type in $h+ mode unicodestring rather than
-                                   ansistring; similarly, char becomes unicodechar rather than ansichar }
+         m_default_unicodestring, { makes the default string type in $h+ mode unicodestring rather than
+                                    ansistring; similarly, char becomes unicodechar rather than ansichar }
+         m_type_helpers         { allows the declaration of "type helper" (non-Delphi) or "record helper"
+                                  (Delphi) for primitive types }
        );
        tmodeswitches = set of tmodeswitch;
 
@@ -550,7 +565,8 @@ interface
          'ISOUNARYMINUS',
          'SYSTEMCODEPAGE',
          'FINALFIELDS',
-         'UNICODESTRINGS');
+         'UNICODESTRINGS',
+         'TYPEHELPERS');
 
 
      type
@@ -597,7 +613,9 @@ interface
          { subroutine has nested exit }
          pi_has_nested_exit,
          { allocates memory on stack, so stack is unbalanced on exit }
-         pi_has_stack_allocs
+         pi_has_stack_allocs,
+         { set if the stack frame of the procedure is estimated }
+         pi_estimatestacksize
        );
        tprocinfoflags=set of tprocinfoflag;
 

+ 30 - 29
compiler/hlcg2ll.pas

@@ -78,9 +78,6 @@ unit hlcg2ll;
           procedure do_register_allocation(list:TAsmList;headertai:tai); inline;
           procedure translate_register(var reg : tregister); inline;
 
-          {# Emit a label to the instruction stream. }
-          procedure a_label(list : TAsmList;l : tasmlabel); inline;
-
           {# Allocates register r by inserting a pai_realloc record }
           procedure a_reg_alloc(list : TAsmList;r : tregister); inline;
           {# Deallocates register r by inserting a pa_regdealloc record}
@@ -154,7 +151,6 @@ unit hlcg2ll;
 
           function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; weak: boolean): tcgpara;override;
           procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override;
-          procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override;
           { same as a_call_name, might be overridden on certain architectures to emit
             static calls without usage of a got trampoline }
           function a_call_name_static(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef): tcgpara;override;
@@ -314,7 +310,6 @@ unit hlcg2ll;
           procedure g_local_unwind(list: TAsmList; l: TAsmLabel);override;
 
           procedure location_force_reg(list:TAsmList;var l:tlocation;src_size,dst_size:tdef;maybeconst:boolean);override;
-          procedure location_force_fpureg(list:TAsmList;var l: tlocation;size: tdef;maybeconst:boolean);override;
           procedure location_force_mem(list:TAsmList;var l:tlocation;size:tdef);override;
           procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);override;
 //          procedure location_force_mmreg(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);override;
@@ -414,11 +409,6 @@ implementation
       cg.translate_register(reg);
     end;
 
-  procedure thlcg2ll.a_label(list: TAsmList; l: tasmlabel); inline;
-    begin
-      cg.a_label(list,l);
-    end;
-
   procedure thlcg2ll.a_reg_alloc(list: TAsmList; r: tregister);
     begin
       cg.a_reg_alloc(list,r);
@@ -470,11 +460,6 @@ implementation
       cg.a_call_reg(list,reg);
     end;
 
-  procedure thlcg2ll.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference);
-    begin
-      cg.a_call_ref(list,ref);
-    end;
-
   function thlcg2ll.a_call_name_static(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef): tcgpara;
     begin
       cg.a_call_name_static(list,s);
@@ -1029,7 +1014,7 @@ implementation
       hl: tasmlabel;
       oldloc : tlocation;
       const_location: boolean;
-      dst_cgsize: tcgsize;
+      dst_cgsize,tmpsize: tcgsize;
     begin
       oldloc:=l;
       dst_cgsize:=def_cgsize(dst_size);
@@ -1059,7 +1044,7 @@ implementation
 {$ifdef cpuflags}
               LOC_FLAGS :
                 begin
-                  cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
+                  cg.g_flags2reg(list,OS_32,l.resflags,hregister);
                   cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
                 end;
 {$endif cpuflags}
@@ -1072,6 +1057,9 @@ implementation
                   cg.a_label(list,current_procinfo.CurrFalseLabel);
                   cg.a_load_const_reg(list,OS_INT,0,hregister);
                   cg.a_label(list,hl);
+{$if defined(cpu8bitalu) or defined(cpu16bitalu)}
+                  cg.a_load_reg_reg(list,OS_INT,OS_32,hregister,hregister);
+{$endif}
                 end;
               else
                 a_load_loc_reg(list,src_size,u32inttype,l,hregister);
@@ -1083,7 +1071,7 @@ implementation
                if l.loc=LOC_CONSTANT then
                 begin
                   if (longint(l.value)<0) then
-                   cg.a_load_const_reg(list,OS_32,aint($ffffffff),hregisterhi)
+                   cg.a_load_const_reg(list,OS_32,longint($ffffffff),hregisterhi)
                   else
                    cg.a_load_const_reg(list,OS_32,0,hregisterhi);
                 end
@@ -1157,13 +1145,21 @@ implementation
 {$endif cpuflags}
             LOC_JUMP :
               begin
+                tmpsize:=dst_cgsize;
+{$if defined(cpu8bitalu) or defined(cpu16bitalu)}
+                if TCGSize2Size[dst_cgsize]>TCGSize2Size[OS_INT] then
+                  tmpsize:=OS_INT;
+{$endif}
                 cg.a_label(list,current_procinfo.CurrTrueLabel);
-                cg.a_load_const_reg(list,dst_cgsize,1,hregister);
+                cg.a_load_const_reg(list,tmpsize,1,hregister);
                 current_asmdata.getjumplabel(hl);
                 cg.a_jmp_always(list,hl);
                 cg.a_label(list,current_procinfo.CurrFalseLabel);
-                cg.a_load_const_reg(list,dst_cgsize,0,hregister);
+                cg.a_load_const_reg(list,tmpsize,0,hregister);
                 cg.a_label(list,hl);
+{$if defined(cpu8bitalu) or defined(cpu16bitalu)}
+                cg.a_load_reg_reg(list,tmpsize,dst_cgsize,hregister,hregister);
+{$endif}
               end;
             else
               begin
@@ -1217,11 +1213,6 @@ implementation
           location_freetemp(list,oldloc);
     end;
 
-  procedure thlcg2ll.location_force_fpureg(list: TAsmList; var l: tlocation; size: tdef; maybeconst: boolean);
-    begin
-      ncgutil.location_force_fpureg(list,l,maybeconst);
-    end;
-
   procedure thlcg2ll.location_force_mem(list: TAsmList; var l: tlocation; size: tdef);
     var
       r: treference;
@@ -1419,10 +1410,16 @@ implementation
                by typecasting an int64 constant to a record of 8 bytes }
              if locsize = OS_F64 then
                begin
-                 tmploc:=l;
-                 location_force_mem(list,tmploc,size);
-                 cg.a_load_loc_cgpara(list,tmploc,cgpara);
-                 location_freetemp(list,tmploc);
+                 if (cgpara.Location^.Next=nil) and (l.size in [OS_64,OS_S64]) and
+                   (cgpara.size in [OS_64,OS_S64]) then
+                   cg64.a_load64_reg_cgpara(list,l.register64,cgpara)
+                 else
+                   begin
+                     tmploc:=l;
+                     location_force_mem(list,tmploc,size);
+                     cg.a_load_loc_cgpara(list,tmploc,cgpara);
+                     location_freetemp(list,tmploc);
+                   end;
                end
              else
 {$endif not cpu64bitalu}
@@ -1437,6 +1434,10 @@ implementation
     var
       tmploc: tlocation;
     begin
+      { skip e.g. empty records }
+      if (cgpara.location^.loc = LOC_VOID) then
+        exit;
+
       { Handle Floating point types differently
 
         This doesn't depend on emulator settings, emulator settings should

+ 315 - 62
compiler/hlcgobj.pas

@@ -37,12 +37,22 @@ unit hlcgobj;
        cclasses,globtype,constexp,
        cpubase,cgbase,cgutils,parabase,
        aasmbase,aasmtai,aasmdata,aasmcpu,
-       symconst,symtype,symdef,
-       node
+       symconst,symtype,symsym,symdef,
+       node,nutils
        ;
 
     type
        tsubsetloadopt = (SL_REG,SL_REGNOSRCMASK,SL_SETZERO,SL_SETMAX);
+
+       preplaceregrec = ^treplaceregrec;
+       treplaceregrec = record
+         old, new: tregister;
+         oldhi, newhi: tregister;
+         ressym: tsym;
+         { moved sym }
+         sym : tabstractnormalvarsym;
+       end;
+
        {# @abstract(Abstract high level code generator)
           This class implements an abstract instruction generator. All
           methods of this class are generic and are mapped to low level code
@@ -97,6 +107,21 @@ unit hlcgobj;
              result loading, this is the register type used }
           function def2regtyp(def: tdef): tregistertype; virtual;
 
+          {# Returns a reference with its base address set from a pointer that
+             has been loaded in a register.
+
+             A generic version is provided. This routine should be overridden
+             on platforms which support pointers with different sizes (for
+             example i8086 near and far pointers) or require some other sort of
+             special consideration when converting a pointer in a register to a
+             reference.
+
+             @param(ref where the result is returned)
+             @param(regsize the type of the pointer, contained in the reg parameter)
+             @param(reg register containing the value of a pointer)
+          }
+          procedure reference_reset_base(var ref: treference; regsize: tdef; reg: tregister; offset, alignment: longint); virtual;
+
           {# Emit a label to the instruction stream. }
           procedure a_label(list : TAsmList;l : tasmlabel); inline;
 
@@ -194,7 +219,6 @@ unit hlcgobj;
           }
           function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; weak: boolean): tcgpara;virtual;abstract;
           procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);virtual;abstract;
-          procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);virtual;
           { same as a_call_name, might be overridden on certain architectures to emit
             static calls without usage of a got trampoline }
           function a_call_name_static(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef): tcgpara;virtual;
@@ -478,6 +502,13 @@ unit hlcgobj;
           procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);virtual;
 
           procedure maketojumpbool(list:TAsmList; p : tnode);virtual;
+          { if the result of n is a LOC_C(..)REGISTER, try to find the corresponding
+            loadn and change its location to a new register (= SSA). In case reload
+            is true, transfer the old to the new register                            }
+          procedure maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean); virtual;
+         private
+          function do_replace_node_regs(var n: tnode; para: pointer): foreachnoderesult; virtual;
+         public
 
           procedure gen_proc_symbol(list:TAsmList);virtual;
           procedure gen_proc_symbol_end(list:TAsmList);virtual;
@@ -556,9 +587,12 @@ implementation
        globals,systems,
        fmodule,export,
        verbose,defutil,paramgr,
-       symbase,symsym,symtable,
-       ncon,nld,ncgrtti,pass_1,pass_2,
+       symbase,symtable,
+       nbas,ncon,nld,ncgrtti,pass_1,pass_2,
        cpuinfo,cgobj,tgobj,cutils,procinfo,
+{$ifdef x86}
+       cgx86,
+{$endif x86}
        ncgutil,ngenutil;
 
 
@@ -610,12 +644,6 @@ implementation
       result:=cg.getmmregister(list,def_cgsize(size));
     end;
 
-(*
-  function thlcgobj.getmmregister(list: TAsmList; size: tdef): Tregister;
-    begin
-      result:=cg.getmmregister(list,def_cgsize(size));
-    end;
-*)
   function thlcgobj.getflagregister(list: TAsmList; size: tdef): Tregister;
     begin
       result:=cg.getflagregister(list,def_cgsize(size));
@@ -714,6 +742,14 @@ implementation
         end;
     end;
 
+  procedure thlcgobj.reference_reset_base(var ref: treference; regsize: tdef;
+    reg: tregister; offset, alignment: longint);
+    begin
+      reference_reset(ref,alignment);
+      ref.base:=reg;
+      ref.offset:=offset;
+    end;
+
   procedure thlcgobj.a_label(list: TAsmList; l: tasmlabel); inline;
     begin
       cg.a_label(list,l);
@@ -752,7 +788,7 @@ implementation
            a_load_reg_reg(list,size,cgpara.location^.def,r,cgpara.location^.register);
          LOC_REFERENCE,LOC_CREFERENCE:
            begin
-              reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+              reference_reset_base(ref,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
               a_load_reg_ref(list,size,cgpara.location^.def,r,ref);
            end;
          LOC_MMREGISTER,LOC_CMMREGISTER:
@@ -782,7 +818,7 @@ implementation
             a_load_const_reg(list,cgpara.location^.def,a,cgpara.location^.register);
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
-               reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+               reference_reset_base(ref,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
                a_load_const_ref(list,cgpara.location^.def,a,ref);
             end
           else
@@ -834,7 +870,7 @@ implementation
                  { we're at the end of the data, and it can be loaded into
                    the current location's register with a single regular
                    load }
-                 else if (sizeleft in [1,2{$ifndef cpu16bitalu},4{$endif}{$ifdef cpu64bitalu},8{$endif}]) then
+                 else if sizeleft in [1,2,4,8] then
                    begin
                      { don't use cgsize_orddef(int_cgsize(sizeleft)) as fromdef,
                        because that may be larger than location^.register in
@@ -913,7 +949,7 @@ implementation
               begin
                  if assigned(location^.next) then
                    internalerror(2010052906);
-                 reference_reset_base(ref,location^.reference.index,location^.reference.offset,newalignment(cgpara.alignment,cgpara.intsize-sizeleft));
+                 reference_reset_base(ref,voidstackpointertype,location^.reference.index,location^.reference.offset,newalignment(cgpara.alignment,cgpara.intsize-sizeleft));
                  if (def_cgsize(size)<>OS_NO) and
                     (size.size=sizeleft) and
                     (sizeleft<=sizeof(aint)) then
@@ -938,7 +974,7 @@ implementation
                  end;
               end
             else
-              internalerror(2010053111);
+              internalerror(2014032101);
           end;
           inc(tmpref.offset,tcgsize2size[location^.size]);
           dec(sizeleft,tcgsize2size[location^.size]);
@@ -981,22 +1017,6 @@ implementation
          end;
     end;
 
-  procedure thlcgobj.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference);
-    var
-      reg: tregister;
-      size: tdef;
-    begin
-      { the loaded data is always a pointer to a procdef. A procvardef is
-        implicitly a pointer already, but a procdef isn't -> create one }
-      if pd.typ=procvardef then
-        size:=pd
-      else
-        size:=getpointerdef(pd);
-      reg:=getaddressregister(list,size);
-      a_load_ref_reg(list,size,size,ref,reg);
-      a_call_reg(list,pd,reg);
-    end;
-
   function thlcgobj.a_call_name_static(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef): tcgpara;
     begin
       result:=a_call_name(list,pd,s,forceresdef,false);
@@ -1556,6 +1576,8 @@ implementation
                   tmpreg:=getintregister(list,locsize);
                   a_load_const_reg(list,locsize,loc.value,tmpreg);
                 end;
+              else
+                internalerror(2013112909);
             end;
             a_bit_test_reg_reg_reg(list,bitnumbersize,locsize,destsize,bitnumber,tmpreg,destreg);
           end;
@@ -2223,7 +2245,9 @@ implementation
       tmpreg: tregister;
       subsetregdef: torddef;
       stopbit: byte;
+
     begin
+      tmpreg:=NR_NO;
       subsetregdef:=cgsize_orddef(sreg.subsetregsize);
       stopbit:=sreg.startbit+sreg.bitlen;
       // on x86(64), 1 shl 32(64) = 1 instead of 0
@@ -2239,7 +2263,10 @@ implementation
            if (slopt<>SL_REGNOSRCMASK) then
             a_op_const_reg(list,OP_AND,subsetregdef,tcgint(not(bitmask)),tmpreg);
         end;
-      if (slopt<>SL_SETMAX) then
+      if (slopt<>SL_SETMAX) and
+      { the "and" is not needed if the whole register is modified (except for SL_SETZERO),
+        because later on we do a move in this case instead of an or }
+        ((sreg.bitlen<>AIntBits) or (slopt=SL_SETZERO)) then
         a_op_const_reg(list,OP_AND,subsetregdef,tcgint(bitmask),sreg.subsetreg);
 
       case slopt of
@@ -2251,8 +2278,11 @@ implementation
               sreg.subsetreg)
           else
             a_load_const_reg(list,subsetregdef,-1,sreg.subsetreg);
+        { if the whole register is modified, no "or" is needed }
+        else if sreg.bitlen=AIntBits then
+          a_load_reg_reg(list,subsetregdef,subsetregdef,tmpreg,sreg.subsetreg)
         else
-          a_op_reg_reg(list,OP_OR,subsetregdef,tmpreg,sreg.subsetreg);
+          a_op_reg_reg(list,OP_OR,subsetregdef,tmpreg,sreg.subsetreg)
        end;
     end;
 
@@ -2358,7 +2388,7 @@ implementation
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
               cgpara.check_simple_location;
-              reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+              reference_reset_base(ref,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
               a_loadfpu_reg_ref(list,fromsize,cgpara.def,r,ref);
             end;
           LOC_REGISTER,LOC_CREGISTER:
@@ -2389,7 +2419,7 @@ implementation
         LOC_REFERENCE,LOC_CREFERENCE:
           begin
             cgpara.check_simple_location;
-            reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+            reference_reset_base(href,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
             { concatcopy should choose the best way to copy the data }
             g_concatcopy(list,fromsize,ref,href);
           end;
@@ -2469,7 +2499,7 @@ implementation
           a_loadmm_reg_reg(list,fromsize,cgpara.def,reg,cgpara.location^.register,shuffle);
         LOC_REFERENCE,LOC_CREFERENCE:
           begin
-            reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+            reference_reset_base(href,voidstackpointertype,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
             a_loadmm_reg_ref(list,fromsize,cgpara.def,reg,href,shuffle);
           end;
         LOC_REGISTER,LOC_CREGISTER:
@@ -2963,7 +2993,7 @@ implementation
       cgpara1,cgpara2,cgpara3 : TCGPara;
       pd : tprocdef;
     begin
-      pd:=search_system_proc('fpc_shortstr_assign');
+      pd:=search_system_proc('fpc_shortstr_to_shortstr');
       cgpara1.init;
       cgpara2.init;
       cgpara3.init;
@@ -2972,15 +3002,15 @@ implementation
       paramanager.getintparaloc(pd,3,cgpara3);
       if pd.is_pushleftright then
         begin
-          a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1);
-          a_loadaddr_ref_cgpara(list,strdef,source,cgpara2);
-          a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3);
+          a_loadaddr_ref_cgpara(list,strdef,dest,cgpara1);
+          a_load_const_cgpara(list,s32inttype,strdef.len,cgpara2);
+          a_loadaddr_ref_cgpara(list,strdef,source,cgpara3);
         end
       else
         begin
-          a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3);
-          a_loadaddr_ref_cgpara(list,strdef,source,cgpara2);
-          a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1);
+          a_loadaddr_ref_cgpara(list,strdef,source,cgpara3);
+          a_load_const_cgpara(list,s32inttype,strdef.len,cgpara2);
+          a_loadaddr_ref_cgpara(list,strdef,dest,cgpara1);
         end;
       paramanager.freecgpara(list,cgpara3);
       paramanager.freecgpara(list,cgpara2);
@@ -3559,6 +3589,8 @@ implementation
           toreg:=getaddressregister(list,regsize);
         R_FPUREGISTER:
           toreg:=getfpuregister(list,regsize);
+        else
+          internalerror(2013112910);
       end;
       a_load_reg_reg(list,regsize,regsize,fromreg,toreg);
     end;
@@ -3574,6 +3606,8 @@ implementation
             toreg:=getaddressregister(list,regsize);
           R_FPUREGISTER:
             toreg:=getfpuregister(list,regsize);
+        else
+          internalerror(2013112915);
         end;
         a_load_reg_reg(list,regsize,regsize,fromreg,toreg);
       end;
@@ -3678,7 +3712,7 @@ implementation
         begin
           { if it's in an mm register, store to memory first }
           if (l.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
-            internalerror(2011012903);
+            location_force_mem(list,l,size);
           reg:=getfpuregister(list,size);
           a_loadfpu_loc_reg(list,size,size,l,reg);
           location_freetemp(list,l);
@@ -3794,14 +3828,14 @@ implementation
             begin
               if not loadref then
                 internalerror(200410231);
-              reference_reset_base(ref,l.register,0,alignment);
+              reference_reset_base(ref,voidpointertype,l.register,0,alignment);
             end;
           LOC_REFERENCE,
           LOC_CREFERENCE :
             begin
               if loadref then
                 begin
-                  reference_reset_base(ref,getaddressregister(list,voidpointertype),0,alignment);
+                  reference_reset_base(ref,voidpointertype,getaddressregister(list,voidpointertype),0,alignment);
                   { it's a pointer to def }
                   a_load_ref_reg(list,voidpointertype,voidpointertype,l.reference,ref.base);
                 end
@@ -3872,12 +3906,225 @@ implementation
     end;
 
 
-  function use_ent : boolean;
+  procedure thlcgobj.maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean);
+    var
+      rr: treplaceregrec;
+      varloc : tai_varloc;
     begin
-	  use_ent := (target_info.system in [system_mipsel_linux,system_mipseb_linux])
-	             or (target_info.cpu=cpu_alpha);
+      if not (n.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) or
+        ([fc_inflowcontrol,fc_gotolabel,fc_lefthandled] * flowcontrol <> []) then
+        exit;
+      rr.old := n.location.register;
+      rr.ressym := nil;
+      rr.sym := nil;
+      rr.oldhi := NR_NO;
+      case n.location.loc of
+        LOC_CREGISTER:
+          begin
+{$ifdef cpu64bitalu}
+            if (n.location.size in [OS_128,OS_S128]) then
+              begin
+                rr.oldhi := n.location.register128.reghi;
+                rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+              end
+            else
+{$else cpu64bitalu}
+            if (n.location.size in [OS_64,OS_S64]) then
+              begin
+                rr.oldhi := n.location.register64.reghi;
+                rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+                rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+              end
+            else
+{$endif cpu64bitalu}
+              rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
+          end;
+        LOC_CFPUREGISTER:
+          rr.new := cg.getfpuregister(current_asmdata.CurrAsmList,n.location.size);
+{$ifdef SUPPORT_MMX}
+        LOC_CMMXREGISTER:
+          rr.new := tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+{$endif SUPPORT_MMX}
+        LOC_CMMREGISTER:
+          rr.new := cg.getmmregister(current_asmdata.CurrAsmList,n.location.size);
+        else
+          exit;
+      end;
+
+      { self is implicitly returned from constructors, even if there are no
+        references to it; additionally, funcretsym is not set for constructor
+        procdefs }
+      if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+        rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
+      else if not is_void(current_procinfo.procdef.returndef) and
+         assigned(current_procinfo.procdef.funcretsym) and
+         (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
+        rr.ressym:=current_procinfo.procdef.funcretsym;
+
+      if not foreachnode(n,@do_replace_node_regs,@rr) then
+        exit;
+
+      if reload then
+        case n.location.loc of
+          LOC_CREGISTER:
+            begin
+{$ifdef cpu64bitalu}
+              if (n.location.size in [OS_128,OS_S128]) then
+                cg128.a_load128_reg_reg(list,n.location.register128,joinreg128(rr.new,rr.newhi))
+              else
+{$else cpu64bitalu}
+              if (n.location.size in [OS_64,OS_S64]) then
+                cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
+              else
+{$endif cpu64bitalu}
+                cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
+            end;
+          LOC_CFPUREGISTER:
+            cg.a_loadfpu_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
+{$ifdef SUPPORT_MMX}
+          LOC_CMMXREGISTER:
+            cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);
+{$endif SUPPORT_MMX}
+          LOC_CMMREGISTER:
+            cg.a_loadmm_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new,nil);
+          else
+            internalerror(2006090920);
+        end;
+
+      { now that we've change the loadn/temp, also change the node result location }
+{$ifdef cpu64bitalu}
+      if (n.location.size in [OS_128,OS_S128]) then
+        begin
+          n.location.register128.reglo := rr.new;
+          n.location.register128.reghi := rr.newhi;
+          if assigned(rr.sym) and
+             ((rr.sym.currentregloc.register<>rr.new) or
+              (rr.sym.currentregloc.registerhi<>rr.newhi)) then
+            begin
+              varloc:=tai_varloc.create128(rr.sym,rr.new,rr.newhi);
+              varloc.oldlocation:=rr.sym.currentregloc.register;
+              varloc.oldlocationhi:=rr.sym.currentregloc.registerhi;
+              rr.sym.currentregloc.register:=rr.new;
+              rr.sym.currentregloc.registerHI:=rr.newhi;
+              list.concat(varloc);
+            end;
+        end
+      else
+{$else cpu64bitalu}
+      if (n.location.size in [OS_64,OS_S64]) then
+        begin
+          n.location.register64.reglo := rr.new;
+          n.location.register64.reghi := rr.newhi;
+          if assigned(rr.sym) and
+             ((rr.sym.currentregloc.register<>rr.new) or
+              (rr.sym.currentregloc.registerhi<>rr.newhi)) then
+            begin
+              varloc:=tai_varloc.create64(rr.sym,rr.new,rr.newhi);
+              varloc.oldlocation:=rr.sym.currentregloc.register;
+              varloc.oldlocationhi:=rr.sym.currentregloc.registerhi;
+              rr.sym.currentregloc.register:=rr.new;
+              rr.sym.currentregloc.registerHI:=rr.newhi;
+              list.concat(varloc);
+            end;
+        end
+      else
+{$endif cpu64bitalu}
+        begin
+          n.location.register := rr.new;
+          if assigned(rr.sym) and (rr.sym.currentregloc.register<>rr.new) then
+            begin
+              varloc:=tai_varloc.create(rr.sym,rr.new);
+              varloc.oldlocation:=rr.sym.currentregloc.register;
+              rr.sym.currentregloc.register:=rr.new;
+              list.concat(varloc);
+            end;
+        end;
     end;
 
+
+  function thlcgobj.do_replace_node_regs(var n: tnode; para: pointer): foreachnoderesult;
+    var
+      rr: preplaceregrec absolute para;
+    begin
+      result := fen_false;
+      if (nf_is_funcret in n.flags) and (fc_exit in flowcontrol) then
+        exit;
+      case n.nodetype of
+        loadn:
+          begin
+            if (tloadnode(n).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) and
+               (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
+               not assigned(tloadnode(n).left) and
+               ((tloadnode(n).symtableentry <> rr^.ressym) or
+                not(fc_exit in flowcontrol)
+               ) and
+               (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
+               (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
+              begin
+{$ifdef cpu64bitalu}
+                { it's possible a 128 bit location was shifted and/xor typecasted }
+                { in a 64 bit value, so only 1 register was left in the location }
+                if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_128,OS_S128]) then
+                  if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi = rr^.oldhi) then
+                    tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi := rr^.newhi
+                  else
+                    exit;
+{$else cpu64bitalu}
+                { it's possible a 64 bit location was shifted and/xor typecasted }
+                { in a 32 bit value, so only 1 register was left in the location }
+                if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
+                  if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi = rr^.oldhi) then
+                    tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
+                  else
+                    exit;
+{$endif cpu64bitalu}
+                tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
+                rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
+                result := fen_norecurse_true;
+              end;
+          end;
+        temprefn:
+          begin
+            if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
+               (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
+               (ttemprefnode(n).tempinfo^.location.register = rr^.old) then
+              begin
+{$ifdef cpu64bitalu}
+                { it's possible a 128 bit location was shifted and/xor typecasted }
+                { in a 64 bit value, so only 1 register was left in the location }
+                if (ttemprefnode(n).tempinfo^.location.size in [OS_128,OS_S128]) then
+                  if (ttemprefnode(n).tempinfo^.location.register128.reghi = rr^.oldhi) then
+                    ttemprefnode(n).tempinfo^.location.register128.reghi := rr^.newhi
+                  else
+                    exit;
+{$else cpu64bitalu}
+                { it's possible a 64 bit location was shifted and/xor typecasted }
+                { in a 32 bit value, so only 1 register was left in the location }
+                if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
+                  if (ttemprefnode(n).tempinfo^.location.register64.reghi = rr^.oldhi) then
+                    ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
+                  else
+                    exit;
+{$endif cpu64bitalu}
+                ttemprefnode(n).tempinfo^.location.register := rr^.new;
+                result := fen_norecurse_true;
+              end;
+          end;
+        { optimize the searching a bit }
+        derefn,addrn,
+        calln,inlinen,casen,
+        addn,subn,muln,
+        andn,orn,xorn,
+        ltn,lten,gtn,gten,equaln,unequaln,
+        slashn,divn,shrn,shln,notn,
+        inn,
+        asn,isn:
+          result := fen_norecurse_false;
+      end;
+    end;
+
+
   procedure thlcgobj.gen_proc_symbol(list: TAsmList);
     var
       item,
@@ -3911,15 +4158,11 @@ implementation
           previtem:=item;
           item := TCmdStrListItem(item.next);
         end;
-      if (use_ent) then
-        list.concat(Tai_directive.create(asd_ent,current_procinfo.procdef.mangledname));
       current_procinfo.procdef.procstarttai:=tai(list.last);
     end;
 
   procedure thlcgobj.gen_proc_symbol_end(list: TAsmList);
     begin
-      if (use_ent) then
-        list.concat(Tai_directive.create(asd_ent_end,current_procinfo.procdef.mangledname));
       list.concat(Tai_symbol_end.Createname(current_procinfo.procdef.mangledname));
 
       current_procinfo.procdef.procendtai:=tai(list.last);
@@ -4085,7 +4328,7 @@ implementation
          if assigned(hp^.def) and
             is_managed_type(hp^.def) then
           begin
-            reference_reset_base(href,current_procinfo.framepointer,hp^.pos,sizeof(pint));
+            reference_reset_base(href,voidstackpointertype,current_procinfo.framepointer,hp^.pos,voidstackpointertype.size);
             g_initialize(list,hp^.def,href);
           end;
          hp:=hp^.next;
@@ -4133,7 +4376,7 @@ implementation
             is_managed_type(hp^.def) then
           begin
             include(current_procinfo.flags,pi_needs_implicit_finally);
-            reference_reset_base(href,current_procinfo.framepointer,hp^.pos,sizeof(pint));
+            reference_reset_base(href,voidstackpointertype,current_procinfo.framepointer,hp^.pos,voidstackpointertype.size);
             g_finalize(list,hp^.def,href);
           end;
          hp:=hp^.next;
@@ -4237,7 +4480,13 @@ implementation
                 ) and
                not(vo_is_funcret in tstaticvarsym(p).varoptions) and
                not(vo_is_external in tstaticvarsym(p).varoptions) and
-               is_managed_type(tstaticvarsym(p).vardef) then
+               is_managed_type(tstaticvarsym(p).vardef) and
+               not (
+                   assigned(tstaticvarsym(p).fieldvarsym) and
+                   assigned(tstaticvarsym(p).fieldvarsym.owner.defowner) and
+                   (df_generic in tdef(tstaticvarsym(p).fieldvarsym.owner.defowner).defoptions)
+                 )
+               then
               finalize_sym(TAsmList(arg),tsym(p));
           end;
         procsym :
@@ -4302,9 +4551,6 @@ implementation
     end;
 
 
-
-
-
 { generates the code for incrementing the reference count of parameters and
   initialize out parameters }
   { generates the code for incrementing the reference count of parameters and
@@ -4633,8 +4879,15 @@ implementation
               anything }
             if not reusepara then
               begin
-                reference_reset_base(href,para.location^.reference.index,para.location^.reference.offset,para.alignment);
-                a_load_ref_ref(list,para.def,para.def,href,destloc.reference);
+                case para.location^.loc of
+                  LOC_REFERENCE,LOC_CREFERENCE:
+                    begin
+                      reference_reset_base(href,voidstackpointertype,para.location^.reference.index,para.location^.reference.offset,para.alignment);
+                      a_load_ref_ref(list,para.def,para.def,href,destloc.reference);
+                    end;
+                  else
+                    internalerror(2013102301);
+                end;
               end;
           end;
         { TODO other possible locations }

+ 22 - 10
compiler/htypechk.pas

@@ -870,6 +870,8 @@ implementation
       begin
         isbinaryoverloaded:=false;
         operpd:=nil;
+        ppn:=nil;
+
         { load easier access variables }
         ld:=tbinarynode(t).left.resultdef;
         rd:=tbinarynode(t).right.resultdef;
@@ -972,6 +974,8 @@ implementation
     { marks an lvalue as "unregable" }
     procedure make_not_regable_intern(p : tnode; how: tregableinfoflags; records_only: boolean);
       begin
+        if ra_addr_taken in how then
+          include(p.flags,nf_address_taken);
         repeat
           case p.nodetype of
             subscriptn:
@@ -1135,8 +1139,13 @@ implementation
                      exclude(varstateflags,vsf_must_be_valid);
                    tc_pchar_2_string,
                    tc_pointer_2_array :
-                     include(varstateflags,vsf_must_be_valid);
-                 end;
+                     begin
+                       include(varstateflags,vsf_must_be_valid);
+                       { when a pointer is used for array access, the
+                         pointer itself is read and never written }
+                       newstate := vs_read;
+                     end;
+               end;
                  p:=tunarynode(p).left;
                end;
              subscriptn :
@@ -1148,6 +1157,9 @@ implementation
              vecn:
                begin
                  set_varstate(tbinarynode(p).right,vs_read,[vsf_must_be_valid]);
+                 { dyn. arrays and dyn. strings are read }
+                 if is_implicit_array_pointer(tunarynode(p).left.resultdef) then
+                   newstate:=vs_read;
                  if (newstate in [vs_read,vs_readwritten]) or
                     not(tunarynode(p).left.resultdef.typ in [stringdef,arraydef]) then
                    include(varstateflags,vsf_must_be_valid)
@@ -1472,7 +1484,7 @@ implementation
                         is_open_array(fromdef) or
                         is_open_array(todef) or
                         ((fromdef.typ=pointerdef) and (todef.typ=arraydef)) or
-                        (fromdef.is_related(todef))) and
+                        (def_is_related(fromdef,todef))) and
                     (fromdef.size<>todef.size) then
                   begin
                     { in TP it is allowed to typecast to smaller types. But the variable can't
@@ -1505,8 +1517,8 @@ implementation
                      begin
                        { pointer -> array conversion is done then we need to see it
                          as a deref, because a ^ is then not required anymore }
-                       if (ttypeconvnode(hp).left.resultdef.typ=pointerdef) then
-                        gotderef:=true;
+                       if ttypeconvnode(hp).convtype=tc_pointer_2_array then
+                         gotderef:=true;
                      end;
                  end;
                  hp:=ttypeconvnode(hp).left;
@@ -1964,7 +1976,7 @@ implementation
                   (tobjectdef(def_from).objecttype=odt_object) and
                   (tobjectdef(def_to).objecttype=odt_object)
                  ) and
-                 (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
+                 (def_is_related(tobjectdef(def_from),tobjectdef(def_to))) then
                 eq:=te_convert_l1;
             end;
           filedef :
@@ -2696,8 +2708,8 @@ implementation
               { for value and const parameters check precision of real, give
                 penalty for loosing of precision. var and out parameters must match exactly }
                if not(currpara.varspez in [vs_var,vs_out]) and
-                  is_real(def_from) and
-                  is_real(def_to) then
+                  is_real_or_cextended(def_from) and
+                  is_real_or_cextended(def_to) then
                  begin
                    eq:=te_equal;
                    if is_extended(def_to) then
@@ -2728,7 +2740,7 @@ implementation
                   (def_from.typ=objectdef) and
                   (def_to.typ=objectdef) and
                   (tobjectdef(def_from).objecttype=tobjectdef(def_to).objecttype) and
-                  tobjectdef(def_from).is_related(tobjectdef(def_to)) then
+                  def_is_related(tobjectdef(def_from),tobjectdef(def_to)) then
                  begin
                    eq:=te_convert_l1;
                    objdef:=tobjectdef(def_from);
@@ -3226,7 +3238,7 @@ implementation
                   the struct in which the current best method was found }
                 if assigned(pd.struct) and
                    (pd.struct<>tprocdef(bestpd).struct) and
-                   tprocdef(bestpd).struct.is_related(pd.struct) then
+                   def_is_related(tprocdef(bestpd).struct,pd.struct) then
                   break;
                 if (pd.proctypeoption=bestpd.proctypeoption) and
                    ((pd.procoptions*[po_classmethod,po_methodpointer])=(bestpd.procoptions*[po_classmethod,po_methodpointer])) and

+ 71 - 16
compiler/i386/i386att.inc

@@ -161,10 +161,8 @@
 'iret',
 'iret',
 'iretw',
-'iretq',
 'jcxz',
 'jecxz',
-'jrcxz',
 'jmp',
 'lahf',
 'lar',
@@ -200,7 +198,6 @@
 'movq',
 'movsb',
 'movsl',
-'movsq',
 'movsw',
 'movs',
 'movz',
@@ -272,7 +269,6 @@
 'popf',
 'popfl',
 'popfw',
-'popfq',
 'por',
 'prefetch',
 'prefetchw',
@@ -306,7 +302,6 @@
 'pushf',
 'pushfl',
 'pushfw',
-'pushfq',
 'pxor',
 'rcl',
 'rcr',
@@ -334,7 +329,6 @@
 'sbb',
 'scasb',
 'scasl',
-'scasq',
 'scasw',
 'cs',
 'ds',
@@ -596,10 +590,6 @@
 'xsha256',
 'dmint',
 'rdm',
-'movabs',
-'movslq',
-'cqto',
-'cmpxchg16b',
 'movntss',
 'movntsd',
 'insertq',
@@ -637,11 +627,9 @@
 'pcmpeqq',
 'pextrb',
 'pextrd',
-'pextrq',
 'phminposuw',
 'pinsrb',
 'pinsrd',
-'pinsrq',
 'pmaxsb',
 'pmaxsd',
 'pmaxud',
@@ -682,9 +670,6 @@
 'aesdeclast',
 'aesimc',
 'aeskeygenassist',
-'stosq',
-'lodsq',
-'cmpsq',
 'vaddpd',
 'vaddps',
 'vaddsd',
@@ -946,6 +931,7 @@
 'vzeroupper',
 'andn',
 'bextr',
+'tzcnt',
 'rorx',
 'sarx',
 'shlx',
@@ -969,5 +955,74 @@
 'vpsllvq',
 'vpsravd',
 'vpsrlvd',
-'vpsrlvq'
+'vpsrlvq',
+'vgatherdpd',
+'vgatherdps',
+'vgatherqpd',
+'vgatherqps',
+'vpgatherdd',
+'vpgatherdq',
+'vpgatherqd',
+'vpgatherqq',
+'vfmadd132pd',
+'vfmadd213pd',
+'vfmadd231pd',
+'vfmaddpd',
+'vfmadd132ps',
+'vfmadd213ps',
+'vfmadd231ps',
+'vfmadd132sd',
+'vfmadd213sd',
+'vfmadd231sd',
+'vfmadd132ss',
+'vfmadd213ss',
+'vfmadd231ss',
+'vfmaddsub132pd',
+'vfmaddsub213pd',
+'vfmaddsub231pd',
+'vfmaddsub132ps',
+'vfmaddsub213ps',
+'vfmaddsub231ps',
+'vfmsubadd132pd',
+'vfmsubadd213pd',
+'vfmsubadd231pd',
+'vfmsubadd132ps',
+'vfmsubadd213ps',
+'vfmsubadd231ps',
+'vfmsub132pd',
+'vfmsub213pd',
+'vfmsub231pd',
+'vfmsub132ps',
+'vfmsub213ps',
+'vfmsub231ps',
+'vfmsub132sd',
+'vfmsub213sd',
+'vfmsub231sd',
+'vfmsub132ss',
+'vfmsub213ss',
+'vfmsub231ss',
+'vfnmadd132pd',
+'vfnmadd213pd',
+'vfnmadd231pd',
+'vfnmadd132ps',
+'vfnmadd213ps',
+'vfnmadd231ps',
+'vfnmadd132sd',
+'vfnmadd213sd',
+'vfnmadd231sd',
+'vfnmadd132ss',
+'vfnmadd213ss',
+'vfnmadd231ss',
+'vfnmsub132pd',
+'vfnmsub213pd',
+'vfnmsub231pd',
+'vfnmsub132ps',
+'vfnmsub213ps',
+'vfnmsub231ps',
+'vfnmsub132sd',
+'vfnmsub213sd',
+'vfnmsub231sd',
+'vfnmsub132ss',
+'vfnmsub213ss',
+'vfnmsub231ss'
 );

+ 68 - 13
compiler/i386/i386atts.inc

@@ -163,8 +163,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
-attsufNONE,
 attsufINT,
 attsufNONE,
 attsufINT,
@@ -201,7 +199,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINTdual,
 attsufINTdual,
 attsufINT,
@@ -273,7 +270,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINT,
 attsufINT,
 attsufNONE,
@@ -307,7 +303,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINT,
 attsufINT,
 attsufNONE,
@@ -342,7 +337,6 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufNONE,
 attsufINT,
 attsufINT,
 attsufINT,
@@ -599,17 +593,80 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufNONE,
 attsufINT,
 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,
 attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -644,12 +701,17 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufMM,
+attsufMM,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufMM,
+attsufMM,
 attsufNONE,
 attsufNONE,
+attsufMM,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -669,13 +731,11 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -716,17 +776,12 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufMM,
-attsufMM,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
-attsufMM,
-attsufMM,
 attsufNONE,
 attsufNONE,
-attsufMM,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 71 - 16
compiler/i386/i386int.inc

@@ -161,10 +161,8 @@
 'iret',
 'iretd',
 'iretw',
-'iretq',
 'jcxz',
 'jecxz',
-'jrcxz',
 'jmp',
 'lahf',
 'lar',
@@ -200,7 +198,6 @@
 'movq',
 'movsb',
 'movsd',
-'movsq',
 'movsw',
 'movsx',
 'movzx',
@@ -272,7 +269,6 @@
 'popf',
 'popfd',
 'popfw',
-'popfq',
 'por',
 'prefetch',
 'prefetchw',
@@ -306,7 +302,6 @@
 'pushf',
 'pushfd',
 'pushfw',
-'pushfq',
 'pxor',
 'rcl',
 'rcr',
@@ -334,7 +329,6 @@
 'sbb',
 'scasb',
 'scasd',
-'scasq',
 'scasw',
 'segcs',
 'segds',
@@ -596,10 +590,6 @@
 'xsha256',
 'dmint',
 'rdm',
-'movabs',
-'movsxd',
-'cqo',
-'cmpxchg16b',
 'movntss',
 'movntsd',
 'insertq',
@@ -637,11 +627,9 @@
 'pcmpeqq',
 'pextrb',
 'pextrd',
-'pextrq',
 'phminposuw',
 'pinsrb',
 'pinsrd',
-'pinsrq',
 'pmaxsb',
 'pmaxsd',
 'pmaxud',
@@ -682,9 +670,6 @@
 'aesdeclast',
 'aesimc',
 'aeskeygenassist',
-'stosq',
-'lodsq',
-'cmpsq',
 'vaddpd',
 'vaddps',
 'vaddsd',
@@ -946,6 +931,7 @@
 'vzeroupper',
 'andn',
 'bextr',
+'tzcnt',
 'rorx',
 'sarx',
 'shlx',
@@ -969,5 +955,74 @@
 'vpsllvq',
 'vpsravd',
 'vpsrlvd',
-'vpsrlvq'
+'vpsrlvq',
+'vgatherdpd',
+'vgatherdps',
+'vgatherqpd',
+'vgatherqps',
+'vpgatherdd',
+'vpgatherdq',
+'vpgatherqd',
+'vpgatherqq',
+'vfmadd132pd',
+'vfmadd213pd',
+'vfmadd231pd',
+'vfmaddpd',
+'vfmadd132ps',
+'vfmadd213ps',
+'vfmadd231ps',
+'vfmadd132sd',
+'vfmadd213sd',
+'vfmadd231sd',
+'vfmadd132ss',
+'vfmadd213ss',
+'vfmadd231ss',
+'vfmaddsub132pd',
+'vfmaddsub213pd',
+'vfmaddsub231pd',
+'vfmaddsub132ps',
+'vfmaddsub213ps',
+'vfmaddsub231ps',
+'vfmsubadd132pd',
+'vfmsubadd213pd',
+'vfmsubadd231pd',
+'vfmsubadd132ps',
+'vfmsubadd213ps',
+'vfmsubadd231ps',
+'vfmsub132pd',
+'vfmsub213pd',
+'vfmsub231pd',
+'vfmsub132ps',
+'vfmsub213ps',
+'vfmsub231ps',
+'vfmsub132sd',
+'vfmsub213sd',
+'vfmsub231sd',
+'vfmsub132ss',
+'vfmsub213ss',
+'vfmsub231ss',
+'vfnmadd132pd',
+'vfnmadd213pd',
+'vfnmadd231pd',
+'vfnmadd132ps',
+'vfnmadd213ps',
+'vfnmadd231ps',
+'vfnmadd132sd',
+'vfnmadd213sd',
+'vfnmadd231sd',
+'vfnmadd132ss',
+'vfnmadd213ss',
+'vfnmadd231ss',
+'vfnmsub132pd',
+'vfnmsub213pd',
+'vfnmsub231pd',
+'vfnmsub132ps',
+'vfnmsub213ps',
+'vfnmsub231ps',
+'vfnmsub132sd',
+'vfnmsub213sd',
+'vfnmsub231sd',
+'vfnmsub132ss',
+'vfnmsub213ss',
+'vfnmsub231ss'
 );

+ 1 - 1
compiler/i386/i386nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
-1828;
+1942;

+ 71 - 16
compiler/i386/i386op.inc

@@ -161,10 +161,8 @@ A_INVLPG,
 A_IRET,
 A_IRETD,
 A_IRETW,
-A_IRETQ,
 A_JCXZ,
 A_JECXZ,
-A_JRCXZ,
 A_JMP,
 A_LAHF,
 A_LAR,
@@ -200,7 +198,6 @@ A_MOVD,
 A_MOVQ,
 A_MOVSB,
 A_MOVSD,
-A_MOVSQ,
 A_MOVSW,
 A_MOVSX,
 A_MOVZX,
@@ -272,7 +269,6 @@ A_POPAW,
 A_POPF,
 A_POPFD,
 A_POPFW,
-A_POPFQ,
 A_POR,
 A_PREFETCH,
 A_PREFETCHW,
@@ -306,7 +302,6 @@ A_PUSHAW,
 A_PUSHF,
 A_PUSHFD,
 A_PUSHFW,
-A_PUSHFQ,
 A_PXOR,
 A_RCL,
 A_RCR,
@@ -334,7 +329,6 @@ A_SAR,
 A_SBB,
 A_SCASB,
 A_SCASD,
-A_SCASQ,
 A_SCASW,
 A_SEGCS,
 A_SEGDS,
@@ -596,10 +590,6 @@ A_XSHA1,
 A_XSHA256,
 A_DMINT,
 A_RDM,
-A_MOVABS,
-A_MOVSXD,
-A_CQO,
-A_CMPXCHG16B,
 A_MOVNTSS,
 A_MOVNTSD,
 A_INSERTQ,
@@ -637,11 +627,9 @@ A_PBLENDW,
 A_PCMPEQQ,
 A_PEXTRB,
 A_PEXTRD,
-A_PEXTRQ,
 A_PHMINPOSUW,
 A_PINSRB,
 A_PINSRD,
-A_PINSRQ,
 A_PMAXSB,
 A_PMAXSD,
 A_PMAXUD,
@@ -682,9 +670,6 @@ A_AESDEC,
 A_AESDECLAST,
 A_AESIMC,
 A_AESKEYGENASSIST,
-A_STOSQ,
-A_LODSQ,
-A_CMPSQ,
 A_VADDPD,
 A_VADDPS,
 A_VADDSD,
@@ -946,6 +931,7 @@ A_VZEROALL,
 A_VZEROUPPER,
 A_ANDN,
 A_BEXTR,
+A_TZCNT,
 A_RORX,
 A_SARX,
 A_SHLX,
@@ -969,5 +955,74 @@ A_VPSLLVD,
 A_VPSLLVQ,
 A_VPSRAVD,
 A_VPSRLVD,
-A_VPSRLVQ
+A_VPSRLVQ,
+A_VGATHERDPD,
+A_VGATHERDPS,
+A_VGATHERQPD,
+A_VGATHERQPS,
+A_VPGATHERDD,
+A_VPGATHERDQ,
+A_VPGATHERQD,
+A_VPGATHERQQ,
+A_VFMADD132PD,
+A_VFMADD213PD,
+A_VFMADD231PD,
+A_VFMADDPD,
+A_VFMADD132PS,
+A_VFMADD213PS,
+A_VFMADD231PS,
+A_VFMADD132SD,
+A_VFMADD213SD,
+A_VFMADD231SD,
+A_VFMADD132SS,
+A_VFMADD213SS,
+A_VFMADD231SS,
+A_VFMADDSUB132PD,
+A_VFMADDSUB213PD,
+A_VFMADDSUB231PD,
+A_VFMADDSUB132PS,
+A_VFMADDSUB213PS,
+A_VFMADDSUB231PS,
+A_VFMSUBADD132PD,
+A_VFMSUBADD213PD,
+A_VFMSUBADD231PD,
+A_VFMSUBADD132PS,
+A_VFMSUBADD213PS,
+A_VFMSUBADD231PS,
+A_VFMSUB132PD,
+A_VFMSUB213PD,
+A_VFMSUB231PD,
+A_VFMSUB132PS,
+A_VFMSUB213PS,
+A_VFMSUB231PS,
+A_VFMSUB132SD,
+A_VFMSUB213SD,
+A_VFMSUB231SD,
+A_VFMSUB132SS,
+A_VFMSUB213SS,
+A_VFMSUB231SS,
+A_VFNMADD132PD,
+A_VFNMADD213PD,
+A_VFNMADD231PD,
+A_VFNMADD132PS,
+A_VFNMADD213PS,
+A_VFNMADD231PS,
+A_VFNMADD132SD,
+A_VFNMADD213SD,
+A_VFNMADD231SD,
+A_VFNMADD132SS,
+A_VFNMADD213SS,
+A_VFNMADD231SS,
+A_VFNMSUB132PD,
+A_VFNMSUB213PD,
+A_VFNMSUB231PD,
+A_VFNMSUB132PS,
+A_VFNMSUB213PS,
+A_VFNMSUB231PS,
+A_VFNMSUB132SD,
+A_VFNMSUB213SD,
+A_VFNMSUB231SD,
+A_VFNMSUB132SS,
+A_VFNMSUB213SS,
+A_VFNMSUB231SS
 );

+ 140 - 85
compiler/i386/i386prop.inc

@@ -161,8 +161,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_RECX, Ch_None, Ch_None)),
 (Ch: (Ch_RECX, Ch_None, Ch_None)),
 (Ch: (Ch_RECX, Ch_None, Ch_None)),
 (Ch: (Ch_ROp1, Ch_None, Ch_None)),
@@ -201,7 +199,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
@@ -224,8 +221,8 @@
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -272,7 +269,6 @@
 (Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_WFLAGS, Ch_None)),
-(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -306,7 +302,6 @@
 (Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
 (Ch: (Ch_RWESP, Ch_RFLAGS, Ch_None)),
-(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
@@ -335,7 +330,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_None, Ch_None, Ch_None)),
 (Ch: (Ch_None, Ch_None, Ch_None)),
 (Ch: (Ch_None, Ch_None, Ch_None)),
@@ -389,7 +383,7 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_ROp1, Ch_WOp2, Ch_RFLAGS)),
+(Ch: (Ch_ROp1, Ch_RWOp2, Ch_RFLAGS)),
 (Ch: (Ch_RFLAGS, Ch_None, Ch_None)),
 (Ch: (Ch_RFLAGS, Ch_WOp1, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
@@ -489,8 +483,8 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -570,6 +564,7 @@
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -596,13 +591,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
-(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
-(Ch: (Ch_MRAX, Ch_WRDX, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -682,9 +670,6 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_RRAX, Ch_WMemEDI, Ch_RWRDI)),
-(Ch: (Ch_WRAX, Ch_RWRSI, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
@@ -730,6 +715,10 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -753,6 +742,12 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -761,28 +756,20 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
@@ -796,7 +783,15 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -859,6 +854,14 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -867,6 +870,24 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -876,15 +897,26 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -893,8 +925,17 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Wop3, Ch_Rop2, Ch_Rop1)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_Wop3)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
@@ -923,51 +964,65 @@
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
 (Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_None)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_Wop1, Ch_Rop2, Ch_Rop3)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None)),
-(Ch: (Ch_All, Ch_None, Ch_None))
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_Rop1))
 );

+ 807 - 9
compiler/i386/i386tab.inc

@@ -2649,17 +2649,10 @@
   (
     opcode  : A_LEA;
     ops     : 2;
-    optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
-    code    : #208#1#141#72;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+    code    : #193#208#1#141#72;
     flags   : if_8086
   ),
-  (
-    opcode  : A_LEA;
-    ops     : 2;
-    optypes : (ot_reg32 or ot_bits64,ot_immediate,ot_none,ot_none);
-    code    : #208#1#141#72;
-    flags   : if_8086 or if_sd
-  ),
   (
     opcode  : A_LEAVE;
     ops     : 0;
@@ -12460,6 +12453,13 @@
     code    : #242#249#1#247#62#72;
     flags   : if_bmi1
   ),
+  (
+    opcode  : A_TZCNT;
+    ops     : 2;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+    code    : #208#219#2#15#188#72;
+    flags   : if_bmi1 or if_sm
+  ),
   (
     opcode  : A_RORX;
     ops     : 3;
@@ -12795,5 +12795,803 @@
     optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
     code    : #241#242#243#249#1#69#61#80;
     flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_xmem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERDPS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem32,ot_ymmreg,ot_none);
+    code    : #241#242#244#249#1#146#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VGATHERQPS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_ymem32,ot_xmmreg,ot_none);
+    code    : #241#242#244#249#1#147#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem32,ot_ymmreg,ot_none);
+    code    : #241#242#244#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERDQ;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_xmem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#144#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem32,ot_xmmreg,ot_none);
+    code    : #241#242#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_ymem32,ot_xmmreg,ot_none);
+    code    : #241#242#244#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmem64,ot_xmmreg,ot_none);
+    code    : #241#242#243#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VPGATHERQQ;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymem64,ot_ymmreg,ot_none);
+    code    : #241#242#243#244#249#1#145#62#72;
+    flags   : if_avx2
+  ),
+  (
+    opcode  : A_VFMADD132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDPD;
+    ops     : 4;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_xmmreg);
+    code    : #241#242#250#1#105#61#80#247;
+    flags   : if_fma4
+  ),
+  (
+    opcode  : A_VFMADDPD;
+    ops     : 4;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmreg,ot_xmmrm);
+    code    : #241#242#250#243#1#105#61#88#246;
+    flags   : if_fma4
+  ),
+  (
+    opcode  : A_VFMADD132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#152#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#168#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#184#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#153#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#169#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#185#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#153#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#169#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADD231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#185#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#150#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#166#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMADDSUB231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#182#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#151#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#167#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUBADD231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#183#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#154#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#170#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#186#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#155#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#171#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#187#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#155#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#171#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFMSUB231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#187#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#156#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#172#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#188#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#157#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#173#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#189#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#157#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#173#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMADD231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#189#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PD;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#243#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#158#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#174#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231PS;
+    ops     : 3;
+    optypes : (ot_ymmreg,ot_ymmreg,ot_ymmrm,ot_none);
+    code    : #241#242#244#249#1#190#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#159#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#175#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231SD;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#243#1#191#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB132SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#159#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB213SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#175#61#80;
+    flags   : if_fma
+  ),
+  (
+    opcode  : A_VFNMSUB231SS;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmreg,ot_xmmrm,ot_none);
+    code    : #241#242#249#1#191#61#80;
+    flags   : if_fma
   )
 );

+ 211 - 0
compiler/ia64/symcpu.pas

@@ -0,0 +1,211 @@
+{
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Symbol table overrides for IA64
+
+    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.
+

+ 13 - 3
compiler/jvm/cpubase.pas

@@ -142,13 +142,13 @@ uses
       maxfpuvarregs = 1;
 
       { Integer Super registers first and last }
-      first_int_imreg = 10;
+      first_int_imreg = 2;
 
       { Float Super register first and last }
-      first_fpu_imreg     = 10;
+      first_fpu_imreg     = 2;
 
       { MM Super register first and last }
-      first_mm_imreg     = 10;
+      first_mm_imreg     = 2;
 
       regnumber_table : array[tregisterindex] of tregister = (
         {$i rjvmnum.inc}
@@ -157,6 +157,15 @@ uses
      EVALSTACKLOCS = [LOC_REGISTER,LOC_CREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER,
        LOC_MMREGISTER,LOC_CMMREGISTER,LOC_SUBSETREG,LOC_CSUBSETREG];
 
+
+{*****************************************************************************
+                               References
+*****************************************************************************}
+
+   type
+     { array reference types }
+     tarrayreftype = (art_none,art_indexreg,art_indexref,art_indexconst);
+
 {*****************************************************************************
                                 Conditions
 *****************************************************************************}
@@ -254,6 +263,7 @@ uses
       );
 
       { this is only for the generic code which is not used for this architecture }
+      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
       saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
 
       {# Required parameter alignment when calling a routine

+ 4 - 2
compiler/jvm/cpunode.pas

@@ -33,8 +33,10 @@ implementation
     ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
     ncgadd, ncgcal,ncgmat,ncginl,
     njvmadd,njvmcal,njvmmat,njvmcnv,njvmcon,njvminl,njvmmem,njvmflw,njvmld,
-    njvmset
+    njvmset,njvmvmt
     { these are not really nodes }
-    ,rgcpu,tgcpu,njvmutil,njvmtcon;
+    ,rgcpu,tgcpu,njvmutil,njvmtcon,
+    { symtable }
+    symcpu;
 
 end.

+ 4 - 4
compiler/jvm/dbgjasm.pas

@@ -58,7 +58,7 @@ implementation
       version,globals,verbose,systems,
       cpubase,cpuinfo,cgbase,paramgr,
       fmodule,
-      defutil,symtable,jvmdef,ppu
+      defutil,symtable,symcpu,jvmdef,ppu
       ;
 
 {****************************************************************************
@@ -76,7 +76,7 @@ implementation
         exit;
       proc:=tprocdef(sym.owner.defowner);
       jvar:=tai_jvar.create(sym.localloc.reference.offset,jvmmangledbasename(sym,true),fcurrprocstart,fcurrprocend);
-      proc.exprasmlist.InsertAfter(jvar,proc.procstarttai);
+      tcpuprocdef(proc).exprasmlist.InsertAfter(jvar,proc.procstarttai);
     end;
 
 
@@ -109,8 +109,8 @@ implementation
 
       current_asmdata.getlabel(procstartlabel,alt_dbgtype);
       current_asmdata.getlabel(procendlabel,alt_dbgtype);
-      def.exprasmlist.insertafter(tai_label.create(procstartlabel),def.procstarttai);
-      def.exprasmlist.insertbefore(tai_label.create(procendlabel),def.procendtai);
+      tcpuprocdef(def).exprasmlist.insertafter(tai_label.create(procstartlabel),def.procstarttai);
+      tcpuprocdef(def).exprasmlist.insertbefore(tai_label.create(procendlabel),def.procendtai);
 
       fcurrprocstart:=procstartlabel;
       fcurrprocend:=procendlabel;

+ 23 - 14
compiler/jvm/hlcgcpu.pas

@@ -30,6 +30,7 @@ uses
   globtype,
   aasmbase,aasmdata,
   symbase,symconst,symtype,symdef,symsym,
+  node,
   cpubase, hlcgobj, cgbase, cgutils, parabase;
 
   type
@@ -103,6 +104,7 @@ uses
       procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation); override;
 
       procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);override;
+      procedure maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean); override;
       procedure g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister); override;
       procedure g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation); override;
 
@@ -246,7 +248,7 @@ implementation
     verbose,cutils,globals,fmodule,constexp,
     defutil,
     aasmtai,aasmcpu,
-    symtable,jvmdef,
+    symtable,symcpu,jvmdef,
     procinfo,cpuinfo,cgcpu,tgobj;
 
   const
@@ -271,7 +273,7 @@ implementation
       if (fevalstackheight>fmaxevalstackheight) then
         fmaxevalstackheight:=fevalstackheight;
       if cs_asm_regalloc in current_settings.globalswitches then
-        list.concat(tai_comment.Create(strpnew('allocated '+tostr(slots)+', stack height = '+tostr(fevalstackheight))));
+        list.concat(tai_comment.Create(strpnew('    allocated '+tostr(slots)+', stack height = '+tostr(fevalstackheight))));
     end;
 
   procedure thlcgjvm.decstack(list: TAsmList;slots: longint);
@@ -1029,7 +1031,7 @@ implementation
               end;
             art_indexref:
               begin
-                reference_reset_base(href,ref.indexbase,ref.indexoffset,4);
+                cgutils.reference_reset_base(href,ref.indexbase,ref.indexoffset,4);
                 href.symbol:=ref.indexsymbol;
                 a_load_ref_stack(list,s32inttype,href,prepare_stack_for_ref(list,href,false));
               end;
@@ -1512,7 +1514,7 @@ implementation
           begin
             if not tprocvardef(size).is_addressonly then
               begin
-                concatcopy_record(list,tprocvardef(size).classdef,source,dest);
+                concatcopy_record(list,tcpuprocvardef(size).classdef,source,dest);
                 handled:=true;
               end;
           end;
@@ -1625,8 +1627,8 @@ implementation
       if not code.empty and
          current_asmdata.asmlists[al_procedures].empty then
         current_asmdata.asmlists[al_procedures].concat(tai_align.Create(4));
-      pd.exprasmlist:=TAsmList.create;
-      pd.exprasmlist.concatlist(code);
+      tcpuprocdef(pd).exprasmlist:=TAsmList.create;
+      tcpuprocdef(pd).exprasmlist.concatlist(code);
       if assigned(data) and
          not data.empty then
         internalerror(2010122801);
@@ -1711,7 +1713,9 @@ implementation
               if tprocsym(sym).procdeflist.Count<>1 then
                 internalerror(2011071713);
               pd:=tprocdef(tprocsym(sym).procdeflist[0]);
-            end;
+            end
+          else
+            internalerror(2013113008);
           a_load_ref_stack(list,java_jlobject,ref,prepare_stack_for_ref(list,ref,false));
           a_call_name(list,pd,pd.mangledname,nil,false);
           { parameter removed, no result }
@@ -1785,7 +1789,7 @@ implementation
               { passed by reference in array of single element; l contains the
                 base address of the array }
               location_reset_ref(tmploc,LOC_REFERENCE,OS_ADDR,4);
-              reference_reset_base(tmploc.reference,getaddressregister(list,java_jlobject),0,4);
+              cgutils.reference_reset_base(tmploc.reference,getaddressregister(list,java_jlobject),0,4);
               tmploc.reference.arrayreftype:=art_indexconst;
               tmploc.reference.indexoffset:=0;
               a_load_loc_reg(list,java_jlobject,java_jlobject,l,tmploc.reference.base);
@@ -1812,6 +1816,11 @@ implementation
       end;
     end;
 
+  procedure thlcgjvm.maybe_change_load_node_reg(list: TAsmList; var n: tnode; reload: boolean);
+    begin
+      { don't do anything, all registers become stack locations anyway }
+    end;
+
   procedure thlcgjvm.g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister);
     var
       localref: treference;
@@ -1847,7 +1856,7 @@ implementation
       case current_procinfo.procdef.proctypeoption of
         potype_unitinit:
           begin
-            reference_reset_base(ref,NR_NO,0,1);
+            cgutils.reference_reset_base(ref,NR_NO,0,1);
             if assigned(current_module.globalsymtable) then
               allocate_implicit_structs_for_st_with_base_ref(list,current_module.globalsymtable,ref,staticvarsym);
             allocate_implicit_structs_for_st_with_base_ref(list,current_module.localsymtable,ref,staticvarsym);
@@ -1857,7 +1866,7 @@ implementation
             { also initialise local variables, if any }
             inherited;
             { initialise class fields }
-            reference_reset_base(ref,NR_NO,0,1);
+            cgutils.reference_reset_base(ref,NR_NO,0,1);
             allocate_implicit_structs_for_st_with_base_ref(list,tabstractrecorddef(current_procinfo.procdef.owner.defowner).symtable,ref,staticvarsym);
           end
         else
@@ -2306,7 +2315,7 @@ implementation
       sym: tstaticvarsym;
     begin
       result:=false;
-      sym:=tstaticvarsym(tenumdef(def).getbasedef.classdef.symtable.Find('__FPC_ZERO_INITIALIZER'));
+      sym:=tstaticvarsym(tcpuenumdef(tenumdef(def).getbasedef).classdef.symtable.Find('__FPC_ZERO_INITIALIZER'));
       { no enum with ordinal value 0 -> exit }
       if not assigned(sym) then
         exit;
@@ -2406,7 +2415,7 @@ implementation
         internalerror(2011033001);
       selfreg:=getaddressregister(list,selfpara.vardef);
       a_load_loc_reg(list,obj,obj,selfpara.localloc,selfreg);
-      reference_reset_base(ref,selfreg,0,1);
+      cgutils.reference_reset_base(ref,selfreg,0,1);
       allocate_implicit_structs_for_st_with_base_ref(list,obj.symtable,ref,fieldvarsym);
     end;
 
@@ -2420,7 +2429,7 @@ implementation
          (checkdef.typ=formaldef) then
         checkdef:=java_jlobject
       else if checkdef.typ=enumdef then
-        checkdef:=tenumdef(checkdef).classdef
+        checkdef:=tcpuenumdef(checkdef).classdef
       else if checkdef.typ=setdef then
         begin
           if tsetdef(checkdef).elementdef.typ=enumdef then
@@ -2429,7 +2438,7 @@ implementation
             checkdef:=java_jubitset;
         end
       else if checkdef.typ=procvardef then
-        checkdef:=tprocvardef(checkdef).classdef
+        checkdef:=tcpuprocvardef(checkdef).classdef
       else if is_wide_or_unicode_string(checkdef) then
         checkdef:=java_jlstring
       else if is_ansistring(checkdef) then

+ 9 - 6
compiler/jvm/jvmdef.pas

@@ -97,7 +97,7 @@ implementation
     cutils,cclasses,constexp,
     verbose,systems,
     fmodule,
-    symtable,symconst,symsym,symdef,symcreat,
+    symtable,symconst,symsym,symdef,symcpu,symcreat,
     defutil,paramgr;
 
 {******************************************************************
@@ -230,7 +230,7 @@ implementation
             end;
           enumdef:
             begin
-              result:=jvmaddencodedtype(tenumdef(def).getbasedef.classdef,false,encodedstr,forcesignature,founderror);
+              result:=jvmaddencodedtype(tcpuenumdef(tenumdef(def).getbasedef).classdef,false,encodedstr,forcesignature,founderror);
             end;
           orddef :
             begin
@@ -282,7 +282,10 @@ implementation
                 s64real:
                   c:='D';
                 else
-                  result:=false;
+                  begin
+                    result:=false;
+                    c:=' ';
+                  end;
               end;
               encodedstr:=encodedstr+c;
             end;
@@ -349,7 +352,7 @@ implementation
             end;
           procvardef :
             begin
-              result:=jvmaddencodedtype(tprocvardef(def).classdef,false,encodedstr,forcesignature,founderror);
+              result:=jvmaddencodedtype(tcpuprocvardef(def).classdef,false,encodedstr,forcesignature,founderror);
             end;
           objectdef :
             case tobjectdef(def).objecttype of
@@ -680,7 +683,7 @@ implementation
                 end;
               enumdef:
                 begin
-                  result:=tenumdef(def).getbasedef.classdef;
+                  result:=tcpuenumdef(tenumdef(def).getbasedef).classdef;
                 end;
               pointerdef :
                 begin
@@ -721,7 +724,7 @@ implementation
                 end;
               procvardef :
                 begin
-                  result:=tprocvardef(def).classdef;
+                  result:=tcpuprocvardef(def).classdef;
                 end;
               objectdef :
                 case tobjectdef(def).objecttype of

+ 7 - 34
compiler/jvm/njvmadd.pas

@@ -38,8 +38,6 @@ interface
        protected
           function jvm_first_addset: tnode;
 
-          function cmpnode2topcmp(unsigned: boolean): TOpCmp;
-
           procedure second_generic_compare(unsigned: boolean);
 
           procedure pass_left_right;override;
@@ -56,7 +54,7 @@ interface
     uses
       systems,
       cutils,verbose,constexp,globtype,
-      symconst,symtable,symdef,
+      symconst,symtable,symdef,symcpu,
       paramgr,procinfo,pass_1,
       aasmtai,aasmdata,aasmcpu,defutil,
       hlcgobj,hlcgcpu,cgutils,
@@ -215,6 +213,8 @@ interface
                       end;
                       procname:='CONTAINSALL'
                     end;
+                  else
+                    internalerror(2013120114);
                 end;
               result:=ccallnode.createinternmethod(left,procname,ccallparanode.create(right,nil));
               { for an unequaln, we have to negate the result of equals }
@@ -231,7 +231,7 @@ interface
                   procname:='OF';
                   if isenum then
                     begin
-                      inserttypeconv_explicit(tsetelementnode(right).left,tenumdef(tsetelementnode(right).left.resultdef).getbasedef.classdef);
+                      inserttypeconv_explicit(tsetelementnode(right).left,tcpuenumdef(tenumdef(tsetelementnode(right).left.resultdef).getbasedef).classdef);
                       result:=cloadvmtaddrnode.create(ctypenode.create(java_juenumset));
                     end
                   else
@@ -247,7 +247,7 @@ interface
                       procname:='RANGE';
                       if isenum then
                         begin
-                          inserttypeconv_explicit(tsetelementnode(right).right,tenumdef(tsetelementnode(right).right.resultdef).getbasedef.classdef);
+                          inserttypeconv_explicit(tsetelementnode(right).right,tcpuenumdef(tenumdef(tsetelementnode(right).right.resultdef).getbasedef).classdef);
                         end
                       else
                         begin
@@ -268,7 +268,7 @@ interface
                       procname:='ADD';
                       if isenum then
                         begin
-                          inserttypeconv_explicit(tsetelementnode(right).left,tenumdef(tsetelementnode(right).left.resultdef).getbasedef.classdef);
+                          inserttypeconv_explicit(tsetelementnode(right).left,tcpuenumdef(tenumdef(tsetelementnode(right).left.resultdef).getbasedef).classdef);
                         end
                       else
                         begin
@@ -284,7 +284,7 @@ interface
                             factory method, then add all of its elements }
                           if isenum then
                             begin
-                              inserttypeconv_explicit(tsetelementnode(right).right,tenumdef(tsetelementnode(right).right.resultdef).getbasedef.classdef);
+                              inserttypeconv_explicit(tsetelementnode(right).right,tcpuenumdef(tenumdef(tsetelementnode(right).right.resultdef).getbasedef).classdef);
                               tmpn:=cloadvmtaddrnode.create(ctypenode.create(java_juenumset));
                             end
                           else
@@ -333,33 +333,6 @@ interface
       end;
 
 
-    function tjvmaddnode.cmpnode2topcmp(unsigned: boolean): TOpCmp;
-      begin
-        if not unsigned then
-          case nodetype of
-            gtn: result:=OC_GT;
-            gten: result:=OC_GTE;
-            ltn: result:=OC_LT;
-            lten: result:=OC_LTE;
-            equaln: result:=OC_EQ;
-            unequaln: result:=OC_NE;
-            else
-              internalerror(2011010412);
-          end
-        else
-        case nodetype of
-          gtn: result:=OC_A;
-          gten: result:=OC_AE;
-          ltn: result:=OC_B;
-          lten: result:=OC_BE;
-          equaln: result:=OC_EQ;
-          unequaln: result:=OC_NE;
-          else
-            internalerror(2011010412);
-        end;
-      end;
-
-
     procedure tjvmaddnode.second_generic_compare(unsigned: boolean);
       var
         cmpop: TOpCmp;

+ 6 - 2
compiler/jvm/njvmcal.pas

@@ -60,7 +60,7 @@ implementation
 
     uses
       verbose,globals,globtype,constexp,cutils,
-      symconst,symtable,symsym,defutil,
+      symconst,symtable,symsym,symcpu,defutil,
       cgutils,tgobj,procinfo,htypechk,
       cpubase,aasmdata,aasmcpu,
       hlcgobj,hlcgcpu,
@@ -527,7 +527,7 @@ implementation
     var
       pdclass: tobjectdef;
     begin
-      pdclass:=tprocvardef(right.resultdef).classdef;
+      pdclass:=tcpuprocvardef(right.resultdef).classdef;
       { convert procvar type into corresponding class }
       if not tprocvardef(right.resultdef).is_addressonly then
         begin
@@ -590,6 +590,10 @@ implementation
           result:=inherited pass_1;
           if assigned(result) then
             exit;
+          { set fforcedprocname so that even virtual method calls will be
+            name-based (instead of based on VMT entry numbers) }
+          if procdefinition.typ=procdef then
+            fforcedprocname:=tprocdef(procdefinition).mangledname
         end;
     end;
 

+ 44 - 26
compiler/jvm/njvmcnv.pas

@@ -55,6 +55,7 @@ interface
          { procedure second_real_to_real;override; }
          { procedure second_cord_to_pointer;override; }
           procedure second_proc_to_procvar;override;
+          procedure second_nil_to_methodprocvar;override;
           procedure second_bool_to_int;override;
           procedure second_int_to_bool;override;
          { procedure second_load_smallset;override;  }
@@ -95,7 +96,7 @@ implementation
 
    uses
       verbose,globals,globtype,constexp,cutils,
-      symbase,symconst,symdef,symsym,symtable,aasmbase,aasmdata,
+      symbase,symconst,symdef,symsym,symcpu,symtable,aasmbase,aasmdata,
       defutil,defcmp,jvmdef,
       cgbase,cgutils,pass_1,pass_2,
       nbas,ncon,ncal,ninl,nld,nmem,procinfo,
@@ -221,7 +222,7 @@ implementation
       if not assigned(totypedef) or
          (totypedef.typ<>procvardef) then
         begin
-          if assigned(tprocvardef(resultdef).classdef) then
+          if assigned(tcpuprocvardef(resultdef).classdef) then
             internalerror(2011072405);
           { associate generic classdef; this is the result of an @proc
             expression, and such expressions can never result in a direct call
@@ -231,7 +232,7 @@ implementation
             { todo }
             internalerror(2011072406)
           else
-            tprocvardef(resultdef).classdef:=java_procvarbase;
+            tcpuprocvardef(resultdef).classdef:=java_procvarbase;
         end;
     end;
 
@@ -257,7 +258,13 @@ implementation
 
     function tjvmtypeconvnode.pass_1: tnode;
       begin
-        if (nf_explicit in flags) then
+        if (nf_explicit in flags) or
+           { some implicit type conversions from voidpointer to other types
+             (such as dynamic array) are allowed too, even though the types are
+             incompatible -> make sure we check those too and insert checkcast
+             instructions as necessary }
+           (is_voidpointer(left.resultdef) and
+            not is_voidpointer(resultdef)) then
           begin
             do_target_specific_explicit_typeconv(false,result);
             if assigned(result) then
@@ -375,10 +382,10 @@ implementation
         result:=inherited first_nil_to_methodprocvar;
         if assigned(result) then
           exit;
-        if not assigned(tprocvardef(resultdef).classdef) then
-          tprocvardef(resultdef).classdef:=java_procvarbase;
+        if not assigned(tcpuprocvardef(resultdef).classdef) then
+          tcpuprocvardef(resultdef).classdef:=java_procvarbase;
         result:=ccallnode.createinternmethod(
-          cloadvmtaddrnode.create(ctypenode.create(tprocvardef(resultdef).classdef)),'CREATE',nil);
+          cloadvmtaddrnode.create(ctypenode.create(tcpuprocvardef(resultdef).classdef)),'CREATE',nil);
         { method pointer is an implicit pointer type }
         result:=ctypeconvnode.create_explicit(result,getpointerdef(resultdef));
         result:=cderefnode.create(result);
@@ -481,7 +488,7 @@ implementation
         if not assigned(procdefparas) then
           procdefparas:=carrayconstructornode.create(nil,nil);
         constrparas:=ccallparanode.create(procdefparas,constrparas);
-        result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tprocvardef(resultdef).classdef)),'CREATE',constrparas);
+        result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tcpuprocvardef(resultdef).classdef)),'CREATE',constrparas);
         { typecast to the procvar type }
         if tprocvardef(resultdef).is_addressonly then
           result:=ctypeconvnode.create_explicit(result,resultdef)
@@ -683,6 +690,17 @@ implementation
       end;
 
 
+    procedure tjvmtypeconvnode.second_nil_to_methodprocvar;
+      var
+        r: Treference;
+      begin
+        tg.gethltemp(current_asmdata.currasmlist,java_jlobject,java_jlobject.size,tt_normal,r);
+        hlcg.a_load_const_ref(current_asmdata.CurrAsmList,java_jlobject,0,r);
+        location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),1);
+        location.reference:=r;
+      end;
+
+
     procedure tjvmtypeconvnode.second_bool_to_int;
       var
          newsize: tcgsize;
@@ -868,12 +886,12 @@ implementation
           left:=nil;
         end;
 
-      function ord_enum_explicit_typecast(fdef: torddef; todef: tenumdef): tnode;
+      function ord_enum_explicit_typecast(fdef: torddef; todef: tcpuenumdef): tnode;
         var
           psym: tsym;
         begin
           { we only create a class for the basedefs }
-          todef:=todef.getbasedef;
+          todef:=tcpuenumdef(todef.getbasedef);
           psym:=search_struct_member(todef.classdef,'FPCVALUEOF');
           if not assigned(psym) or
              (psym.typ<>procsym) then
@@ -887,12 +905,12 @@ implementation
           left:=nil;
         end;
 
-      function enum_ord_explicit_typecast(fdef: tenumdef; todef: torddef): tnode;
+      function enum_ord_explicit_typecast(fdef: tcpuenumdef; todef: torddef): tnode;
         var
           psym: tsym;
         begin
           { we only create a class for the basedef }
-          fdef:=fdef.getbasedef;
+          fdef:=tcpuenumdef(fdef.getbasedef);
           psym:=search_struct_member(fdef.classdef,'FPCORDINAL');
           if not assigned(psym) or
              (psym.typ<>procsym) then
@@ -938,7 +956,7 @@ implementation
           if tsetdef(resultdef).elementdef.typ=enumdef then
             begin
               inserttypeconv_explicit(left,s64inttype);
-              enumclassdef:=tenumdef(tsetdef(resultdef).elementdef).getbasedef.classdef;
+              enumclassdef:=tcpuenumdef(tenumdef(tsetdef(resultdef).elementdef).getbasedef).classdef;
               mp:=cloadvmtaddrnode.create(ctypenode.create(enumclassdef));
               helpername:='fpcLongToEnumSet';
               { enumclass.fpcLongToEnumSet(left,setbase,setsize) }
@@ -973,21 +991,21 @@ implementation
           result:=nil;
           if fromdef=todef then
             exit;
-          fsym:=tfieldvarsym(search_struct_member(tprocvardef(fromdef).classdef,'METHOD'));
+          fsym:=tfieldvarsym(search_struct_member(tcpuprocvardef(fromdef).classdef,'METHOD'));
           if not assigned(fsym) or
              (fsym.typ<>fieldvarsym) then
             internalerror(2011072414);
           { can either be a procvar or a procvarclass }
           if fromdef.typ=procvardef then
             begin
-              left:=ctypeconvnode.create_explicit(left,tprocvardef(fromdef).classdef);
+              left:=ctypeconvnode.create_explicit(left,tcpuprocvardef(fromdef).classdef);
               include(left.flags,nf_load_procvar);
               typecheckpass(left);
             end;
           result:=csubscriptnode.create(fsym,left);
           { create destination procvartype with info from source }
           result:=ccallnode.createinternmethod(
-            cloadvmtaddrnode.create(ctypenode.create(tprocvardef(todef).classdef)),
+            cloadvmtaddrnode.create(ctypenode.create(tcpuprocvardef(todef).classdef)),
             'CREATE',ccallparanode.create(result,nil));
           left:=nil;
         end;
@@ -999,8 +1017,8 @@ implementation
           { must be procedure-of-object -> implicit pointer type -> get address
             before typecasting to corresponding classdef }
           left:=caddrnode.create_internal(left);
-          inserttypeconv_explicit(left,tprocvardef(fromdef).classdef);
-          fsym:=tfieldvarsym(search_struct_member(tprocvardef(fromdef).classdef,'METHOD'));
+          inserttypeconv_explicit(left,tcpuprocvardef(fromdef).classdef);
+          fsym:=tfieldvarsym(search_struct_member(tcpuprocvardef(fromdef).classdef,'METHOD'));
           if not assigned(fsym) or
              (fsym.typ<>fieldvarsym) then
             internalerror(2011072414);
@@ -1012,11 +1030,11 @@ implementation
         var
           fsym: tsym;
         begin
-          fsym:=tfieldvarsym(search_struct_member(tprocvardef(todef).classdef,'METHOD'));
+          fsym:=tfieldvarsym(search_struct_member(tcpuprocvardef(todef).classdef,'METHOD'));
           if not assigned(fsym) or
              (fsym.typ<>fieldvarsym) then
             internalerror(2011072415);
-          result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tprocvardef(todef).classdef)),
+          result:=ccallnode.createinternmethod(cloadvmtaddrnode.create(ctypenode.create(tcpuprocvardef(todef).classdef)),
             'CREATE',ccallparanode.create(left,nil));
           left:=nil;
         end;
@@ -1071,9 +1089,9 @@ implementation
           result:=true;
           { check procvar conversion compatibility via their classes }
           if fromdef.typ=procvardef then
-            fromdef:=tprocvardef(fromdef).classdef;
+            fromdef:=tcpuprocvardef(fromdef).classdef;
           if todef.typ=procvardef then
-            todef:=tprocvardef(todef).classdef;
+            todef:=tcpuprocvardef(todef).classdef;
           if (todef=java_jlobject) or
              (todef=voidpointertype) then
             exit;
@@ -1083,7 +1101,7 @@ implementation
             but do not allow records to be directly typecasted into class/
             pointer types (you have to use FpcBaseRecordType(@rec) instead) }
           if not is_record(fromdef) and
-             fromdef.is_related(todef) then
+             def_is_related(fromdef,todef) then
             exit;
           if check_type_equality(fromdef,todef) then
             exit;
@@ -1100,7 +1118,7 @@ implementation
             exit;
           if (fromdef.typ=classrefdef) and
              (todef.typ=classrefdef) and
-             tclassrefdef(fromdef).pointeddef.is_related(tclassrefdef(todef).pointeddef) then
+             def_is_related(tclassrefdef(fromdef).pointeddef,tclassrefdef(todef).pointeddef) then
             exit;
           { special case: "array of shortstring" to "array of ShortstringClass"
             and "array of <record>" to "array of FpcRecordBaseType" (normally
@@ -1331,14 +1349,14 @@ implementation
            if left.resultdef.typ=orddef then
              begin
                if not check_only then
-                 resnode:=ord_enum_explicit_typecast(torddef(left.resultdef),tenumdef(resultdef));
+                 resnode:=ord_enum_explicit_typecast(torddef(left.resultdef),tcpuenumdef(resultdef));
                result:=true;
                exit;
              end
            else if resultdef.typ=orddef then
              begin
                if not check_only then
-                 resnode:=enum_ord_explicit_typecast(tenumdef(left.resultdef),torddef(resultdef));
+                 resnode:=enum_ord_explicit_typecast(tcpuenumdef(left.resultdef),torddef(resultdef));
                result:=true;
                exit;
              end

+ 5 - 5
compiler/jvm/njvmcon.pas

@@ -85,7 +85,7 @@ implementation
 
     uses
       globals,cutils,widestr,verbose,constexp,fmodule,
-      symdef,symsym,symtable,symconst,
+      symdef,symsym,symcpu,symtable,symconst,
       aasmdata,aasmcpu,defutil,
       nutils,ncnv,nld,nmem,pjvm,pass_1,
       cgbase,hlcgobj,hlcgcpu,cgutils,cpubase
@@ -98,7 +98,7 @@ implementation
 
     function tjvmordconstnode.pass_1: tnode;
       var
-        basedef: tenumdef;
+        basedef: tcpuenumdef;
         sym: tenumsym;
         classfield: tsym;
       begin
@@ -120,7 +120,7 @@ implementation
             exit;
           end;
         { b) find the corresponding class field }
-        basedef:=tenumdef(resultdef).getbasedef;
+        basedef:=tcpuenumdef(tenumdef(resultdef).getbasedef);
         classfield:=search_struct_member(basedef.classdef,sym.name);
 
         { c) create loadnode of the field }
@@ -313,7 +313,7 @@ implementation
             mp:=cloadvmtaddrnode.create(ctypenode.create(java_juenumset));
             if len=0 then
               begin
-                enumele:=cloadvmtaddrnode.create(ctypenode.create(tenumdef(eledef).getbasedef.classdef));
+                enumele:=cloadvmtaddrnode.create(ctypenode.create(tcpuenumdef(tenumdef(eledef).getbasedef).classdef));
                 inserttypeconv_explicit(enumele,search_system_type('JLCLASS').typedef);
                 paras:=ccallparanode.create(enumele,nil);
                 result:=ccallnode.createinternmethod(mp,'NONEOF',paras)
@@ -445,7 +445,7 @@ implementation
         { add a read-only typed constant }
         new(ps);
         ps^:=value_set^;
-        csym:=tconstsym.create_ptr('_$setconst'+tostr(current_module.symlist.count),constset,ps,resultdef);
+        csym:=cconstsym.create_ptr('_$setconst'+tostr(current_module.symlist.count),constset,ps,resultdef);
         csym.visibility:=vis_private;
         include(csym.symoptions,sp_internal);
         current_module.localsymtable.insert(csym);

+ 2 - 2
compiler/jvm/njvmflw.pas

@@ -55,7 +55,7 @@ implementation
 
     uses
       verbose,globals,systems,globtype,constexp,
-      symconst,symdef,symsym,aasmtai,aasmdata,aasmcpu,defutil,jvmdef,
+      symconst,symdef,symsym,aasmtai,aasmdata,aasmcpu,defutil,jvmdef,defcmp,
       procinfo,cgbase,pass_1,pass_2,parabase,
       cpubase,cpuinfo,
       nbas,nld,ncon,ncnv,
@@ -127,7 +127,7 @@ implementation
            exit;
          { Java exceptions must descend from java.lang.Throwable }
          if assigned(left) and
-            not(left.resultdef).is_related(java_jlthrowable) then
+            not def_is_related(left.resultdef,java_jlthrowable) then
            MessagePos2(left.fileinfo,type_e_incompatible_types,left.resultdef.typename,'class(JLThrowable)');
          { Java exceptions cannot be raised "at" a specific location }
          if assigned(right) then

+ 2 - 2
compiler/jvm/njvminl.pas

@@ -73,7 +73,7 @@ implementation
     uses
       cutils,globals,verbose,globtype,constexp,fmodule,
       aasmbase,aasmtai,aasmdata,aasmcpu,
-      symtype,symconst,symdef,symsym,symtable,jvmdef,
+      symtype,symconst,symdef,symsym,symcpu,symtable,jvmdef,
       defutil,
       nadd,nbas,ncon,ncnv,nmat,nmem,ncal,nld,nflw,nutils,
       cgbase,pass_1,pass_2,
@@ -362,7 +362,7 @@ implementation
         if seteledef.typ=enumdef then
           begin
             inserttypeconv_explicit(setpara,java_juenumset);
-            inserttypeconv_explicit(valuepara.left,tenumdef(seteledef).getbasedef.classdef);
+            inserttypeconv_explicit(valuepara.left,tcpuenumdef(tenumdef(seteledef).getbasedef).classdef);
           end
         else
           begin

+ 1 - 1
compiler/jvm/njvmld.pas

@@ -66,7 +66,7 @@ uses
   symconst,symsym,symdef,symtable,defutil,jvmdef,
   paramgr,
   pass_1,
-  cgbase,hlcgobj,cpuinfo;
+  cpubase,cgbase,hlcgobj,cpuinfo;
 
 { tjvmassignmentnode }
 

+ 15 - 10
compiler/jvm/njvmmem.pas

@@ -61,7 +61,7 @@ implementation
       systems,globals,procinfo,
       cutils,verbose,constexp,
       aasmbase,
-      symconst,symtype,symtable,symsym,symdef,defutil,jvmdef,
+      symconst,symtype,symtable,symsym,symdef,symcpu,defutil,jvmdef,
       htypechk,paramgr,
       nadd,ncal,ncnv,ncon,nld,nutils,
       pass_1,njvmcon,
@@ -199,7 +199,7 @@ implementation
                     { an internal address node will observe "normal" address
                       operator semantics (= take the actual address!) }
                     result:=caddrnode.create_internal(taddrnode(left).left);
-                    result:=ctypeconvnode.create_explicit(result,tprocvardef(taddrnode(left).left.resultdef).classdef);
+                    result:=ctypeconvnode.create_explicit(result,tcpuprocvardef(taddrnode(left).left.resultdef).classdef);
                     taddrnode(left).left:=nil;
                  end;
               end
@@ -209,9 +209,9 @@ implementation
                   begin
                     { the "code" field from the procvar }
                     result:=caddrnode.create_internal(left);
-                    result:=ctypeconvnode.create_explicit(result,tprocvardef(left.resultdef).classdef);
+                    result:=ctypeconvnode.create_explicit(result,tcpuprocvardef(left.resultdef).classdef);
                     { procvarclass.method }
-                    fsym:=search_struct_member(tprocvardef(left.resultdef).classdef,'METHOD');
+                    fsym:=search_struct_member(tcpuprocvardef(left.resultdef).classdef,'METHOD');
                     if not assigned(fsym) or
                        (fsym.typ<>fieldvarsym) then
                       internalerror(2011072501);
@@ -410,7 +410,7 @@ implementation
           begin
            if (right.location.loc<>LOC_CONSTANT) then
              begin
-               psym:=search_struct_member(tenumdef(right.resultdef).getbasedef.classdef,'FPCORDINAL');
+               psym:=search_struct_member(tcpuenumdef(tenumdef(right.resultdef).getbasedef).classdef,'FPCORDINAL');
                if not assigned(psym) or
                   (psym.typ<>procsym) or
                   (tprocsym(psym).ProcdefList.count<>1) then
@@ -427,6 +427,14 @@ implementation
              object instances (since that's what they are in Java) }
            right.resultdef:=s32inttype;
            right.location.size:=OS_S32;
+          end
+        else if (right.location.loc<>LOC_CONSTANT) and
+                ((right.resultdef.typ<>orddef) or
+                 (torddef(right.resultdef).ordtype<>s32bit)) then
+          begin
+            { Java array indices are always 32 bit signed integers }
+            hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,s32inttype,true);
+            right.resultdef:=s32inttype;
           end;
 
         { adjust index if necessary }
@@ -436,11 +444,8 @@ implementation
           begin
             thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
             thlcgjvm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_SUB,right.resultdef,tarraydef(left.resultdef).lowrange);
-            if right.location.loc<>LOC_REGISTER then
-              begin
-                location_reset(right.location,LOC_REGISTER,def_cgsize(right.resultdef));
-                right.location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,right.resultdef);
-              end;
+            location_reset(right.location,LOC_REGISTER,def_cgsize(right.resultdef));
+            right.location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,right.resultdef);
             thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,right.resultdef,right.location.register);
           end;
 

部分文件因为文件数量过多而无法显示