add-arm64-support
authorPascal Packaging Team <pkg-pascal-devel@lists.alioth.debian.org>
Mon, 22 Jan 2018 09:28:53 +0000 (09:28 +0000)
committerAbou Al Montacir <abou.almontacir@sfr.fr>
Mon, 22 Jan 2018 09:28:53 +0000 (09:28 +0000)
Gbp-Pq: Name add-arm64-support.patch

196 files changed:
fpcsrc/Makefile.fpc
fpcsrc/compiler/Makefile.fpc
fpcsrc/compiler/aarch64/a64att.inc
fpcsrc/compiler/aarch64/a64atts.inc
fpcsrc/compiler/aarch64/a64ins.dat
fpcsrc/compiler/aarch64/a64op.inc
fpcsrc/compiler/aarch64/a64reg.dat
fpcsrc/compiler/aarch64/a64tab.inc
fpcsrc/compiler/aarch64/aasmcpu.pas
fpcsrc/compiler/aarch64/agcpugas.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/aoptcpub.pas
fpcsrc/compiler/aarch64/cgcpu.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/cpubase.pas
fpcsrc/compiler/aarch64/cpuinfo.pas
fpcsrc/compiler/aarch64/cpunode.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/cpupara.pas
fpcsrc/compiler/aarch64/cpupi.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/cputarg.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/hlcgcpu.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ncpuadd.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ncpucnv.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ncpuinl.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ncpumat.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ncpumem.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ncpuset.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/ra64con.inc
fpcsrc/compiler/aarch64/ra64dwa.inc
fpcsrc/compiler/aarch64/ra64nor.inc
fpcsrc/compiler/aarch64/ra64num.inc
fpcsrc/compiler/aarch64/ra64rni.inc
fpcsrc/compiler/aarch64/ra64sri.inc
fpcsrc/compiler/aarch64/ra64sta.inc
fpcsrc/compiler/aarch64/ra64std.inc
fpcsrc/compiler/aarch64/ra64sup.inc
fpcsrc/compiler/aarch64/racpu.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/racpugas.pas [new file with mode: 0644]
fpcsrc/compiler/aarch64/rgcpu.pas [new file with mode: 0644]
fpcsrc/compiler/aasmtai.pas
fpcsrc/compiler/aggas.pas
fpcsrc/compiler/aoptobj.pas
fpcsrc/compiler/arm/aasmcpu.pas
fpcsrc/compiler/arm/agarmgas.pas
fpcsrc/compiler/arm/aoptcpu.pas
fpcsrc/compiler/arm/armatt.inc
fpcsrc/compiler/arm/armatts.inc
fpcsrc/compiler/arm/armins.dat
fpcsrc/compiler/arm/armnop.inc
fpcsrc/compiler/arm/armop.inc
fpcsrc/compiler/arm/armreg.dat
fpcsrc/compiler/arm/armtab.inc
fpcsrc/compiler/arm/cgcpu.pas
fpcsrc/compiler/arm/cpubase.pas
fpcsrc/compiler/arm/cpuelf.pas
fpcsrc/compiler/arm/cpuinfo.pas
fpcsrc/compiler/arm/narmadd.pas
fpcsrc/compiler/arm/narmcnv.pas
fpcsrc/compiler/arm/narminl.pas
fpcsrc/compiler/arm/narmmat.pas
fpcsrc/compiler/arm/narmmem.pas
fpcsrc/compiler/arm/raarmgas.pas
fpcsrc/compiler/arm/rarmcon.inc
fpcsrc/compiler/arm/rarmdwa.inc
fpcsrc/compiler/arm/rarmnor.inc
fpcsrc/compiler/arm/rarmnum.inc
fpcsrc/compiler/arm/rarmrni.inc
fpcsrc/compiler/arm/rarmsri.inc
fpcsrc/compiler/arm/rarmsta.inc
fpcsrc/compiler/arm/rarmstd.inc
fpcsrc/compiler/arm/rarmsup.inc
fpcsrc/compiler/assemble.pas
fpcsrc/compiler/cgbase.pas
fpcsrc/compiler/cghlcpu.pas
fpcsrc/compiler/cgobj.pas
fpcsrc/compiler/cgutils.pas
fpcsrc/compiler/fpcdefs.inc
fpcsrc/compiler/hlcg2ll.pas
fpcsrc/compiler/hlcgobj.pas
fpcsrc/compiler/i386/cpuelf.pas
fpcsrc/compiler/i8086/n8086mem.pas
fpcsrc/compiler/jvm/hlcgcpu.pas
fpcsrc/compiler/m68k/n68kmem.pas
fpcsrc/compiler/mips/cpuelf.pas
fpcsrc/compiler/msg/errore.msg
fpcsrc/compiler/msgidx.inc
fpcsrc/compiler/ncal.pas
fpcsrc/compiler/ncgcnv.pas
fpcsrc/compiler/ncginl.pas
fpcsrc/compiler/ncgld.pas
fpcsrc/compiler/ncgmat.pas
fpcsrc/compiler/ncgmem.pas
fpcsrc/compiler/ncgutil.pas
fpcsrc/compiler/ncnv.pas
fpcsrc/compiler/ninl.pas
fpcsrc/compiler/nld.pas
fpcsrc/compiler/nmem.pas
fpcsrc/compiler/objcgutl.pas
fpcsrc/compiler/objcutil.pas
fpcsrc/compiler/ogbase.pas
fpcsrc/compiler/ogcoff.pas
fpcsrc/compiler/ogelf.pas
fpcsrc/compiler/options.pas
fpcsrc/compiler/pparautl.pas
fpcsrc/compiler/ppu.pas
fpcsrc/compiler/psub.pas
fpcsrc/compiler/psystem.pas
fpcsrc/compiler/raatt.pas
fpcsrc/compiler/rautils.pas
fpcsrc/compiler/sparc/cpuelf.pas
fpcsrc/compiler/symdef.pas
fpcsrc/compiler/systems.inc
fpcsrc/compiler/systems.pas
fpcsrc/compiler/systems/i_bsd.pas
fpcsrc/compiler/systems/i_linux.pas
fpcsrc/compiler/systems/i_win.pas
fpcsrc/compiler/systems/t_bsd.pas
fpcsrc/compiler/systems/t_linux.pas
fpcsrc/compiler/tgobj.pas
fpcsrc/compiler/utils/Makefile.fpc
fpcsrc/compiler/utils/fpc.pp
fpcsrc/compiler/utils/mka64ins.pp
fpcsrc/compiler/utils/mkarmins.pp
fpcsrc/compiler/utils/ppuutils/ppudump.pp
fpcsrc/compiler/version.pas
fpcsrc/compiler/x86/agx86att.pas
fpcsrc/compiler/x86/cgx86.pas
fpcsrc/compiler/x86/nx86mem.pas
fpcsrc/compiler/x86_64/cgcpu.pas
fpcsrc/compiler/x86_64/cpuelf.pas
fpcsrc/packages/fcl-res/Makefile.fpc.fpcmake
fpcsrc/packages/fcl-res/src/elfconsts.pp
fpcsrc/packages/fcl-res/src/elfdefaulttarget.inc
fpcsrc/packages/fcl-res/src/elfreader.pp
fpcsrc/packages/fcl-res/src/elfsubwriter.inc
fpcsrc/packages/fcl-res/src/elfwriter.pp
fpcsrc/packages/fcl-res/src/machoconsts.pp
fpcsrc/packages/fcl-res/src/machodefaulttarget.inc
fpcsrc/packages/fcl-res/src/machoreader.pp
fpcsrc/packages/fcl-res/src/machosubwriter.inc
fpcsrc/packages/fcl-res/src/machotypes.pp
fpcsrc/packages/fcl-res/src/machowriter.pp
fpcsrc/packages/fpmkunit/src/fpmkunit.pp
fpcsrc/packages/iosxlocale/Makefile.fpc.fpcmake
fpcsrc/packages/iosxlocale/fpmake.pp
fpcsrc/packages/iosxlocale/src/iosxwstr.pp [new file with mode: 0644]
fpcsrc/packages/rtl-extra/src/linux/unixsock.inc
fpcsrc/packages/rtl-extra/src/unix/ipc.pp
fpcsrc/rtl/aarch64/aarch64.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/int64p.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/makefile.cpu [new file with mode: 0644]
fpcsrc/rtl/aarch64/math.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/mathu.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/set.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/setjump.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/setjumph.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/strings.inc [new file with mode: 0644]
fpcsrc/rtl/aarch64/stringss.inc [new file with mode: 0644]
fpcsrc/rtl/arm/arm.inc
fpcsrc/rtl/arm/thumb2.inc
fpcsrc/rtl/bsd/ostypes.inc
fpcsrc/rtl/darwin/aarch64/sig_cpu.inc [new file with mode: 0644]
fpcsrc/rtl/darwin/aarch64/sighnd.inc [new file with mode: 0644]
fpcsrc/rtl/darwin/extres_multiarch.inc
fpcsrc/rtl/darwin/ptypes.inc
fpcsrc/rtl/darwin/signal.inc
fpcsrc/rtl/inc/ctypes.pp
fpcsrc/rtl/inc/objc.pp
fpcsrc/rtl/inc/objcnf.inc
fpcsrc/rtl/inc/system.inc
fpcsrc/rtl/inc/systemh.inc
fpcsrc/rtl/linux/aarch64/bsyscall.inc [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/cprt0.as [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/dllprt0.as [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/gprt0.as [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/prt0.as [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/sighnd.inc [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/sighndh.inc [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/stat.inc [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/syscall.inc [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/syscallh.inc [new file with mode: 0644]
fpcsrc/rtl/linux/aarch64/sysnr.inc [new file with mode: 0644]
fpcsrc/rtl/linux/bunxsysc.inc
fpcsrc/rtl/linux/linux.pp
fpcsrc/rtl/linux/oldlinux.pp
fpcsrc/rtl/linux/osdefs.inc
fpcsrc/rtl/linux/ossysc.inc
fpcsrc/rtl/linux/ostypes.inc
fpcsrc/rtl/linux/pmutext.inc [new file with mode: 0644]
fpcsrc/rtl/linux/ptypes.inc
fpcsrc/rtl/linux/sysnr-gen.inc [new file with mode: 0644]
fpcsrc/rtl/linux/sysosh.inc
fpcsrc/rtl/linux/termios.inc
fpcsrc/rtl/unix/cthreads.pp
fpcsrc/rtl/unix/cwstring.pp
fpcsrc/utils/fpcm/fpcmmain.pp
fpcsrc/utils/fpcres/fpcres.pas
fpcsrc/utils/fpcres/target.pas

index 1435e4daa5bb7e8bb73a7e99f889970e82a2fd81..6d464b216b6178de042f9ead3c5f47ad34d1e556 100644 (file)
@@ -78,6 +78,9 @@ endif
 ifeq ($(CPU_TARGET),avr)
 PPSUF=avr
 endif
+ifeq ($(CPU_TARGET),aarch64)
+PPSUF=a64
+endif
 
 # cross compilers uses full cpu_target, not just ppc-suffix
 # (except if the target cannot run a native compiler)
index d617dceeba93f2d7211e9c740afcd9130341018f..df2c5d7c7e67468e1809ac20b32db458adfb648c 100644 (file)
@@ -32,7 +32,7 @@ fpcdir=..
 unexport FPC_VERSION FPC_COMPILERINFO
 
 # Which platforms are ready for inclusion in the cycle
-CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086 aarch64
 
 # All supported targets used for clean
 ALLTARGETS=$(CYCLETARGETS)
@@ -80,6 +80,9 @@ endif
 ifdef I8086
 PPC_TARGET=i8086
 endif
+ifdef AARCH64
+PPC_TARGET=aarch64
+endif
 
 # Default is to generate a compiler for the same
 # platform as CPU_TARGET (a native compiler)
@@ -205,6 +208,9 @@ endif
 ifeq ($(CPC_TARGET),i8086)
 CPUSUF=8086
 endif
+ifeq ($(CPC_TARGET),aarch64)
+CPUSUF=a64
+endif
 
 # Do not define the default -d$(CPU_TARGET) because that
 # will conflict with our -d$(CPC_TARGET)
@@ -400,7 +406,7 @@ endif
 # CPU targets
 #####################################################################
 
-PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 alpha vis ia64 mips mipsel avr jvm i8086
+PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 alpha vis ia64 mips mipsel avr jvm i8086 aarch64
 INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS)))
 
 .PHONY: $(PPC_TARGETS) $(INSTALL_TARGETS)
@@ -455,12 +461,12 @@ tempclean:
         -$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC) pp1.wpo pp2.wpo
 
 execlean :
-        -$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
+        -$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppca64$(EXEEXT) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
 
 $(addsuffix _clean,$(ALLTARGETS)):
         -$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
         -$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
-        -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) $(EXENAME))
+        -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) ppcjvm$(EXEEXT) ppc8086$(EXEEXT) ppca64$(EXEEXT) $(EXENAME))
 
 cycleclean: cleanall $(addsuffix _clean,$(CPC_TARGET))
         -$(DEL) $(EXENAME)
index ad0b8050dfdf0f3b20b3bea851cb277ffaa1f269..359719060a915cb03f08014ede3c97becba7b3c0 100644 (file)
@@ -1,15 +1,37 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
-'nop',
+'none',
 'b',
-'cb',
-'tb',
+'cbz',
+'cbnz',
+'tbz',
+'tbnz',
 'bl',
 'blr',
 'br',
 'ret',
+'brk',
+'hlt',
+'hvc',
+'smc',
+'svc',
+'eret',
+'dcps1',
+'dcps2',
+'dcps3',
+'drps',
+'dc',
+'at',
+'tlbi',
+'hint',
+'clrex',
+'dsb',
+'dmb',
+'isb',
 'ldr',
 'str',
+'ldur',
+'stur',
 'ldp',
 'stp',
 'ldnp',
 'ldtr',
 'sttr',
 'ldxr',
+'ldxp',
 'stxr',
+'stxp',
 'ldar',
 'stlr',
 'ldaxr',
 'stlxr',
+'stlxp',
+'ld1',
+'ld2',
+'ld3',
+'ld4',
+'st1',
+'st2',
+'st3',
+'st4',
+'ld1r',
+'ld2r',
+'ld3r',
+'ld4r',
 'prfm',
+'prfum',
 'add',
-'adc',
 'sub',
-'sbc',
 'cmp',
 'cmn',
-'mov',
 'and',
-'bic',
 'eor',
-'eon',
 'orr',
 'orn',
 'tst',
-'mvn',
+'movz',
+'movn',
 'movk',
+'mrs',
+'msr',
 'adrp',
 'adr',
 'bfm',
 'sbfm',
 'ubfm',
 'extr',
-'sxt',
-'uxt',
+'adc',
+'sbc',
+'bic',
+'eon',
 'asrv',
-'llslv',
+'lslv',
 'lsrv',
 'rorv',
+'madd',
+'msub',
+'smaddl',
+'smsubl',
+'smulh',
+'umaddl',
+'umsubl',
+'umulh',
+'sdiv',
+'udiv',
 'cls',
 'clz',
 'rbit',
 'csneg',
 'ccmn',
 'ccmp',
-'madd',
-'msub',
-'smaddl',
-'smsubl',
-'smulh',
-'umaddl',
-'umsubl',
-'umulh',
-'sdiv',
-'udiv',
-'neg',
+'nop',
+'yield',
+'wfe',
+'wfi',
+'sev',
+'sevl',
+'mov',
+'bfi',
+'bfxil',
+'sbfiz',
+'sbfx',
+'ubfiz',
+'ubfx',
 'asr',
 'lsl',
 'lsr',
 'ror',
-'cset',
-'csetm',
-'cinc',
-'cinv',
-'cneg',
+'sxt',
+'uxt',
+'neg',
 'ngc',
+'mvn',
 'mneg',
 'mul',
 'smnegl',
 'smull',
 'umnegl',
 'umull',
+'cset',
+'csetm',
+'cinc',
+'cinv',
+'cneg',
 'fmov',
 'fcvt',
 'fcvtas',
 'fcvtzu',
 'scvtf',
 'ucvtf',
-'fprinta',
-'fprinti',
-'fprintm',
-'fprintn',
-'fprintp',
-'fprintx',
-'fprintz',
+'frinta',
+'frinti',
+'frintm',
+'frintn',
+'frintp',
+'frintx',
+'frintz',
 'fabs',
 'fneg',
 'fsqrt',
 'fcmpe',
 'fccmp',
 'fcmmpe',
-'fcsel'
+'fcsel',
+'umov',
+'ins',
+'movi'
 );
index 6b59b55a9d104239f58f64c0a9f5e21359aa8556..560b3cbb3a9a8e09b90399b6a385ffb0d74af86f 100644 (file)
@@ -1,4 +1,4 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
 attsufNONE,
 attsufNONE,
@@ -130,5 +130,62 @@ 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
 );
index 34fae63c028aa4f27840a34fb2dcdf8c0eb05984..8032befca8a5ffa3be7fb3f1776fc02f3dcda431 100644 (file)
@@ -1,10 +1,15 @@
-[NOP]
+; invalid
+[NONE]
 
 [B]
 
-[CB]
+[CBZ]
+
+[CBNZ]
 
-[TB]
+[TBZ]
+
+[TBNZ]
 
 [BL]
 
 
 [RET]
 
+[BRK]
+
+[HLT]
+
+[HVC]
+
+[SMC]
+
+[SVC]
+
+[ERET]
+
+[DCPS1]
+
+[DCPS2]
+
+[DCPS3]
+
+[DRPS]
+
+[DC]
+
+[AT]
+
+[TLBI]
+
+[HINT]
+
+[CLREX]
+
+[DSB]
+
+[DMB]
+
+[ISB]
+
 [LDR]
 
 [STR]
 
+[LDUR]
+
+[STUR]
+
 [LDP]
 
 [STP]
 
 [LDXR]
 
+[LDXP]
+
 [STXR]
 
+[STXP]
+
 [LDAR]
 
 [STLR]
 
 [STLXR]
 
+[STLXP]
+
+[LD1]
+
+[LD2]
+
+[LD3]
+
+[LD4]
+
+[ST1]
+
+[ST2]
+
+[ST3]
+
+[ST4]
+
+[LD1R]
+
+[LD2R]
+
+[LD3R]
+
+[LD4R]
+
 [PRFM]
 
-[ADD]
+[PRFUM]
 
-[ADC]
+[ADD]
 
 [SUB]
 
-[SBC]
-
 [CMP]
 
 [CMN]
 
-[MOV]
-
 [AND]
 
-[BIC]
-
 [EOR]
 
-[EON]
-
 [ORR]
 
 [ORN]
 
 [TST]
 
-[MVN]
+[MOVZ]
+
+[MOVN]
 
 [MOVK]
 
+[MRS]
+
+[MSR]
+
 [ADRP]
 
 [ADR]
 
 [EXTR]
 
-[SXT]
+[ADC]
 
-[UXT]
+[SBC]
+
+[BIC]
+
+[EON]
 
 [ASRV]
 
-[LLSLV]
+[LSLV]
 
 [LSRV]
 
 [RORV]
 
+[MADD]
+
+[MSUB]
+
+[SMADDL]
+
+[SMSUBL]
+
+[SMULH]
+
+[UMADDL]
+
+[UMSUBL]
+
+[UMULH]
+
+[SDIV]
+
+[UDIV]
+
 [CLS]
 
 [CLZ]
 
 [CCMP]
 
-[MADD]
+; Aliases
+; they are not generated by the compiler, they are only used for inline assembler
+[NOP]
 
-[MSUB]
+[YIELD]
 
-[SMADDL]
+[WFE]
 
-[SMSUBL]
+[WFI]
 
-[SMULH]
+[SEV]
 
-[UMADDL]
+[SEVL]
 
-[UMSUBL]
+[MOV]
 
-[UMULH]
+[BFI]
 
-[SDIV]
+[BFXIL]
 
-[UDIV]
+[SBFIZ]
 
-; Aliases
-; they are not generated by the compiler, they are only used for inline assembler
-[NEG]
+[SBFX]
+
+[UBFIZ]
+
+[UBFX]
 
 [ASR]
 
 
 [ROR]
 
-[CSET]
-
-[CSETM]
-
-[CINC]
+[SXT]
 
-[CINV]
+[UXT]
 
-[CNEG]
+[NEG]
 
 [NGC]
 
+[MVN]
+
 [MNEG]
 
 [MUL]
 
 [UMULL]
 
+[CSET]
+
+[CSETM]
+
+[CINC]
+
+[CINV]
+
+[CNEG]
+
 [FMOV]
 
 [FCVT]
 
 [UCVTF]
 
-[FPRINTA]
+[FRINTA]
 
-[FPRINTI]
+[FRINTI]
 
-[FPRINTM]
+[FRINTM]
 
-[FPRINTN]
+[FRINTN]
 
-[FPRINTP]
+[FRINTP]
 
-[FPRINTX]
+[FRINTX]
 
-[FPRINTZ]
+[FRINTZ]
 
 [FABS]
 
 
 [FCSEL]
 
+[UMOV]
+
+[INS]
+
+[MOVI]
index 05faf81ab97e1b5b9c2129fe4e0137fa943dcb8c..244c232d35092b0197790f316fdce5daf5896e1b 100644 (file)
@@ -1,15 +1,37 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
-A_NOP,
+A_NONE,
 A_B,
-A_CB,
-A_TB,
+A_CBZ,
+A_CBNZ,
+A_TBZ,
+A_TBNZ,
 A_BL,
 A_BLR,
 A_BR,
 A_RET,
+A_BRK,
+A_HLT,
+A_HVC,
+A_SMC,
+A_SVC,
+A_ERET,
+A_DCPS1,
+A_DCPS2,
+A_DCPS3,
+A_DRPS,
+A_DC,
+A_AT,
+A_TLBI,
+A_HINT,
+A_CLREX,
+A_DSB,
+A_DMB,
+A_ISB,
 A_LDR,
 A_STR,
+A_LDUR,
+A_STUR,
 A_LDP,
 A_STP,
 A_LDNP,
@@ -17,40 +39,66 @@ A_STNP,
 A_LDTR,
 A_STTR,
 A_LDXR,
+A_LDXP,
 A_STXR,
+A_STXP,
 A_LDAR,
 A_STLR,
 A_LDAXR,
 A_STLXR,
+A_STLXP,
+A_LD1,
+A_LD2,
+A_LD3,
+A_LD4,
+A_ST1,
+A_ST2,
+A_ST3,
+A_ST4,
+A_LD1R,
+A_LD2R,
+A_LD3R,
+A_LD4R,
 A_PRFM,
+A_PRFUM,
 A_ADD,
-A_ADC,
 A_SUB,
-A_SBC,
 A_CMP,
 A_CMN,
-A_MOV,
 A_AND,
-A_BIC,
 A_EOR,
-A_EON,
 A_ORR,
 A_ORN,
 A_TST,
-A_MVN,
+A_MOVZ,
+A_MOVN,
 A_MOVK,
+A_MRS,
+A_MSR,
 A_ADRP,
 A_ADR,
 A_BFM,
 A_SBFM,
 A_UBFM,
 A_EXTR,
-A_SXT,
-A_UXT,
+A_ADC,
+A_SBC,
+A_BIC,
+A_EON,
 A_ASRV,
-A_LLSLV,
+A_LSLV,
 A_LSRV,
 A_RORV,
+A_MADD,
+A_MSUB,
+A_SMADDL,
+A_SMSUBL,
+A_SMULH,
+A_UMADDL,
+A_UMSUBL,
+A_UMULH,
+A_SDIV,
+A_UDIV,
 A_CLS,
 A_CLZ,
 A_RBIT,
@@ -63,33 +111,39 @@ A_CSINV,
 A_CSNEG,
 A_CCMN,
 A_CCMP,
-A_MADD,
-A_MSUB,
-A_SMADDL,
-A_SMSUBL,
-A_SMULH,
-A_UMADDL,
-A_UMSUBL,
-A_UMULH,
-A_SDIV,
-A_UDIV,
-A_NEG,
+A_NOP,
+A_YIELD,
+A_WFE,
+A_WFI,
+A_SEV,
+A_SEVL,
+A_MOV,
+A_BFI,
+A_BFXIL,
+A_SBFIZ,
+A_SBFX,
+A_UBFIZ,
+A_UBFX,
 A_ASR,
 A_LSL,
 A_LSR,
 A_ROR,
-A_CSET,
-A_CSETM,
-A_CINC,
-A_CINV,
-A_CNEG,
+A_SXT,
+A_UXT,
+A_NEG,
 A_NGC,
+A_MVN,
 A_MNEG,
 A_MUL,
 A_SMNEGL,
 A_SMULL,
 A_UMNEGL,
 A_UMULL,
+A_CSET,
+A_CSETM,
+A_CINC,
+A_CINV,
+A_CNEG,
 A_FMOV,
 A_FCVT,
 A_FCVTAS,
@@ -104,13 +158,13 @@ A_FCVTZS,
 A_FCVTZU,
 A_SCVTF,
 A_UCVTF,
-A_FPRINTA,
-A_FPRINTI,
-A_FPRINTM,
-A_FPRINTN,
-A_FPRINTP,
-A_FPRINTX,
-A_FPRINTZ,
+A_FRINTA,
+A_FRINTI,
+A_FRINTM,
+A_FRINTN,
+A_FRINTP,
+A_FRINTX,
+A_FRINTZ,
 A_FABS,
 A_FNEG,
 A_FSQRT,
@@ -130,5 +184,8 @@ A_FCMP,
 A_FCMPE,
 A_FCCMP,
 A_FCMMPE,
-A_FCSEL
+A_FCSEL,
+A_UMOV,
+A_INS,
+A_MOVI
 );
index f1da4aed49512f9b55fc49b9d8a9c124938d73ce..0ede14cbc243e7eeb456f3d989b2b9051e7a364c 100644 (file)
@@ -70,169 +70,176 @@ W30,$01,$04,$1E,w30,30,30
 X30,$01,$05,$1E,x30,30,30
 WZR,$01,$04,$1F,wzr,31,31
 XZR,$01,$05,$1F,xzr,31,31
+; sp and zr share the same register number, but we still have to be able to
+; differentiate them because some instructions can be encoded with both ->
+; use a different superregister after all
+WSP,$01,$04,$20,wsp,31,31
+SP,$01,$05,$20,sp,31,31
 
 
 ; vfp registers
-B0,$04,$01,$00,b0,0,0
-H0,$04,$03,$00,h0,0,0
-S0,$04,$09,$00,s0,0,0
-D0,$04,$0a,$00,d0,0,0
-Q0,$04,$05,$00,q0,0,0
-B1,$04,$01,$01,b1,1,1
-H1,$04,$03,$01,h1,1,1
-S1,$04,$09,$01,s1,1,1
-D1,$04,$0a,$01,d1,1,1
-Q1,$04,$05,$01,q1,1,1
-B2,$04,$01,$02,b2,2,2
-H2,$04,$03,$02,h2,2,2
-S2,$04,$09,$02,s2,2,2
-D2,$04,$0a,$02,d2,2,2
-Q2,$04,$05,$02,q2,2,2
-B3,$04,$01,$03,b3,3,3
-H3,$04,$03,$03,h3,3,3
-S3,$04,$09,$03,s3,3,3
-D3,$04,$0a,$03,d3,3,3
-Q3,$04,$05,$03,q3,3,3
-B4,$04,$01,$04,b4,4,4
-H4,$04,$03,$04,h4,4,4
-S4,$04,$09,$04,s4,4,4
-D4,$04,$0a,$04,d4,4,4
-Q4,$04,$05,$04,q4,4,4
-B5,$04,$01,$05,b5,5,5
-H5,$04,$03,$05,h5,5,5
-S5,$04,$09,$05,s5,5,5
-D5,$04,$0a,$05,d5,5,5
-Q5,$04,$05,$05,q5,5,5
-B6,$04,$01,$06,b6,6,6
-H6,$04,$03,$06,h6,6,6
-S6,$04,$09,$06,s6,6,6
-D6,$04,$0a,$06,d6,6,6
-Q6,$04,$05,$06,q6,6,6
-B7,$04,$01,$07,b7,7,7
-H7,$04,$03,$07,h7,7,7
-S7,$04,$09,$07,s7,7,7
-D7,$04,$0a,$07,d7,7,7
-Q7,$04,$05,$07,q7,7,7
-B8,$04,$01,$08,b8,8,8
-H8,$04,$03,$08,h8,8,8
-S8,$04,$09,$08,s8,8,8
-D8,$04,$0a,$08,d8,8,8
-Q8,$04,$05,$08,q8,8,8
-B9,$04,$01,$09,b9,9,9
-H9,$04,$03,$09,h9,9,9
-S9,$04,$09,$09,s9,9,9
-D9,$04,$0a,$09,d9,9,9
-Q9,$04,$05,$09,q9,9,9
-B10,$04,$01,$0A,b10,10,10
-H10,$04,$03,$0A,h10,10,10
-S10,$04,$09,$0A,s10,10,10
-D10,$04,$0a,$0A,d10,10,10
-Q10,$04,$05,$0A,q10,10,10
-B11,$04,$01,$0B,b11,11,11
-H11,$04,$03,$0B,h11,11,11
-S11,$04,$09,$0B,s11,11,11
-D11,$04,$0a,$0B,d11,11,11
-Q11,$04,$05,$0B,q11,11,11
-B12,$04,$01,$0C,b12,12,12
-H12,$04,$03,$0C,h12,12,12
-S12,$04,$09,$0C,s12,12,12
-D12,$04,$0a,$0C,d12,12,12
-Q12,$04,$05,$0C,q12,12,12
-B13,$04,$01,$0D,b13,13,13
-H13,$04,$03,$0D,h13,13,13
-S13,$04,$09,$0D,s13,13,13
-D13,$04,$0a,$0D,d13,13,13
-Q13,$04,$05,$0D,q13,13,13
-B14,$04,$01,$0E,b14,14,14
-H14,$04,$03,$0E,h14,14,14
-S14,$04,$09,$0E,s14,14,14
-D14,$04,$0a,$0E,d14,14,14
-Q14,$04,$05,$0E,q14,14,14
-B15,$04,$01,$0F,b15,15,15
-H15,$04,$03,$0F,h15,15,15
-S15,$04,$09,$0F,s15,15,15
-D15,$04,$0a,$0F,d15,15,15
-Q15,$04,$05,$0F,q15,15,15
-B16,$04,$01,$10,b16,16,16
-H16,$04,$03,$10,h16,16,16
-S16,$04,$09,$10,s16,16,16
-D16,$04,$0a,$10,d16,16,16
-Q16,$04,$05,$10,q16,16,16
-B17,$04,$01,$11,b17,17,17
-H17,$04,$03,$11,h17,17,17
-S17,$04,$09,$11,s17,17,17
-D17,$04,$0a,$11,d17,17,17
-Q17,$04,$05,$11,q17,17,17
-B18,$04,$01,$12,b18,18,18
-H18,$04,$03,$12,h18,18,18
-S18,$04,$09,$12,s18,18,18
-D18,$04,$0a,$12,d18,18,18
-Q18,$04,$05,$12,q18,18,18
-B19,$04,$01,$13,b19,19,19
-H19,$04,$03,$13,h19,19,19
-S19,$04,$09,$13,s19,19,19
-D19,$04,$0a,$13,d19,19,19
-Q19,$04,$05,$13,q19,19,19
-B20,$04,$01,$14,b20,20,20
-H20,$04,$03,$14,h20,20,20
-S20,$04,$09,$14,s20,20,20
-D20,$04,$0a,$14,d20,20,20
-Q20,$04,$05,$14,q20,20,20
-B21,$04,$01,$15,b21,21,21
-H21,$04,$03,$15,h21,21,21
-S21,$04,$09,$15,s21,21,21
-D21,$04,$0a,$15,d21,21,21
-Q21,$04,$05,$15,q21,21,21
-B22,$04,$01,$16,b22,22,22
-H22,$04,$03,$16,h22,22,22
-S22,$04,$09,$16,s22,22,22
-D22,$04,$0a,$16,d22,22,22
-Q22,$04,$05,$16,q22,22,22
-B23,$04,$01,$17,b23,23,23
-H23,$04,$03,$17,h23,23,23
-S23,$04,$09,$17,s23,23,23
-D23,$04,$0a,$17,d23,23,23
-Q23,$04,$05,$17,q23,23,23
-B24,$04,$01,$18,b24,24,24
-H24,$04,$03,$18,h24,24,24
-S24,$04,$09,$18,s24,24,24
-D24,$04,$0a,$18,d24,24,24
-Q24,$04,$05,$18,q24,24,24
-B25,$04,$01,$19,b25,25,25
-H25,$04,$03,$19,h25,25,25
-S25,$04,$09,$19,s25,25,25
-D25,$04,$0a,$19,d25,25,25
-Q25,$04,$05,$19,q25,25,25
-B26,$04,$01,$1A,b26,26,26
-H26,$04,$03,$1A,h26,26,26
-S26,$04,$09,$1A,s26,26,26
-D26,$04,$0a,$1A,d26,26,26
-Q26,$04,$05,$1A,q26,26,26
-B27,$04,$01,$1B,b27,27,27
-H27,$04,$03,$1B,h27,27,27
-S27,$04,$09,$1B,s27,27,27
-D27,$04,$0a,$1B,d27,27,27
-Q27,$04,$05,$1B,q27,27,27
-B28,$04,$01,$1C,b28,28,28
-H28,$04,$03,$1C,h28,28,28
-S28,$04,$09,$1C,s28,28,28
-D28,$04,$0a,$1C,d28,28,28
-Q28,$04,$05,$1C,q28,28,28
-B29,$04,$01,$1D,b29,29,29
-H29,$04,$03,$1D,h29,29,29
-S29,$04,$09,$1D,s29,29,29
-D29,$04,$0a,$1D,d29,29,29
-Q29,$04,$05,$1D,q29,29,29
-B30,$04,$01,$1E,b30,30,30
-H30,$04,$03,$1E,h30,30,30
-S30,$04,$09,$1E,s30,30,30
-D30,$04,$0a,$1E,d30,30,30
-Q30,$04,$05,$1E,q30,30,30
-B31,$04,$01,$1F,b31,31,31
-H31,$04,$03,$1F,h31,31,31
-S31,$04,$09,$1F,s31,31,31
-D31,$04,$0a,$1F,d31,31,31
-Q31,$04,$05,$1F,q31,31,31
+B0,$04,$01,$00,b0,64,64
+H0,$04,$03,$00,h0,64,64
+S0,$04,$09,$00,s0,64,64
+D0,$04,$0a,$00,d0,64,64
+Q0,$04,$05,$00,q0,64,64
+B1,$04,$01,$01,b1,65,65
+H1,$04,$03,$01,h1,65,65
+S1,$04,$09,$01,s1,65,65
+D1,$04,$0a,$01,d1,65,65
+Q1,$04,$05,$01,q1,65,65
+B2,$04,$01,$02,b2,66,66
+H2,$04,$03,$02,h2,66,66
+S2,$04,$09,$02,s2,66,66
+D2,$04,$0a,$02,d2,66,66
+Q2,$04,$05,$02,q2,66,66
+B3,$04,$01,$03,b3,67,67
+H3,$04,$03,$03,h3,67,67
+S3,$04,$09,$03,s3,67,67
+D3,$04,$0a,$03,d3,67,67
+Q3,$04,$05,$03,q3,67,67
+B4,$04,$01,$04,b4,68,68
+H4,$04,$03,$04,h4,68,68
+S4,$04,$09,$04,s4,68,68
+D4,$04,$0a,$04,d4,68,68
+Q4,$04,$05,$04,q4,68,68
+B5,$04,$01,$05,b5,69,69
+H5,$04,$03,$05,h5,69,69
+S5,$04,$09,$05,s5,69,69
+D5,$04,$0a,$05,d5,69,69
+Q5,$04,$05,$05,q5,69,69
+B6,$04,$01,$06,b6,70,70
+H6,$04,$03,$06,h6,70,70
+S6,$04,$09,$06,s6,70,70
+D6,$04,$0a,$06,d6,70,70
+Q6,$04,$05,$06,q6,70,70
+B7,$04,$01,$07,b7,71,71
+H7,$04,$03,$07,h7,71,71
+S7,$04,$09,$07,s7,71,71
+D7,$04,$0a,$07,d7,71,71
+Q7,$04,$05,$07,q7,71,71
+B8,$04,$01,$08,b8,72,72
+H8,$04,$03,$08,h8,72,72
+S8,$04,$09,$08,s8,72,72
+D8,$04,$0a,$08,d8,72,72
+Q8,$04,$05,$08,q8,72,72
+B9,$04,$01,$09,b9,73,73
+H9,$04,$03,$09,h9,73,73
+S9,$04,$09,$09,s9,73,73
+D9,$04,$0a,$09,d9,73,73
+Q9,$04,$05,$09,q9,73,73
+B10,$04,$01,$0A,b10,74,74
+H10,$04,$03,$0A,h10,74,74
+S10,$04,$09,$0A,s10,74,74
+D10,$04,$0a,$0A,d10,74,74
+Q10,$04,$05,$0A,q10,74,74
+B11,$04,$01,$0B,b11,75,75
+H11,$04,$03,$0B,h11,75,75
+S11,$04,$09,$0B,s11,75,75
+D11,$04,$0a,$0B,d11,75,75
+Q11,$04,$05,$0B,q11,75,75
+B12,$04,$01,$0C,b12,76,76
+H12,$04,$03,$0C,h12,76,76
+S12,$04,$09,$0C,s12,76,76
+D12,$04,$0a,$0C,d12,76,76
+Q12,$04,$05,$0C,q12,76,76
+B13,$04,$01,$0D,b13,77,77
+H13,$04,$03,$0D,h13,77,77
+S13,$04,$09,$0D,s13,77,77
+D13,$04,$0a,$0D,d13,77,77
+Q13,$04,$05,$0D,q13,77,77
+B14,$04,$01,$0E,b14,78,78
+H14,$04,$03,$0E,h14,78,78
+S14,$04,$09,$0E,s14,78,78
+D14,$04,$0a,$0E,d14,78,78
+Q14,$04,$05,$0E,q14,78,78
+B15,$04,$01,$0F,b15,79,79
+H15,$04,$03,$0F,h15,79,79
+S15,$04,$09,$0F,s15,79,79
+D15,$04,$0a,$0F,d15,79,79
+Q15,$04,$05,$0F,q15,79,79
+B16,$04,$01,$10,b16,80,80
+H16,$04,$03,$10,h16,80,80
+S16,$04,$09,$10,s16,80,80
+D16,$04,$0a,$10,d16,80,80
+Q16,$04,$05,$10,q16,80,80
+B17,$04,$01,$11,b17,81,81
+H17,$04,$03,$11,h17,81,81
+S17,$04,$09,$11,s17,81,81
+D17,$04,$0a,$11,d17,81,81
+Q17,$04,$05,$11,q17,81,81
+B18,$04,$01,$12,b18,82,82
+H18,$04,$03,$12,h18,82,82
+S18,$04,$09,$12,s18,82,82
+D18,$04,$0a,$12,d18,82,82
+Q18,$04,$05,$12,q18,82,82
+B19,$04,$01,$13,b19,83,83
+H19,$04,$03,$13,h19,83,83
+S19,$04,$09,$13,s19,83,83
+D19,$04,$0a,$13,d19,83,83
+Q19,$04,$05,$13,q19,83,83
+B20,$04,$01,$14,b20,84,84
+H20,$04,$03,$14,h20,84,84
+S20,$04,$09,$14,s20,84,84
+D20,$04,$0a,$14,d20,84,84
+Q20,$04,$05,$14,q20,84,84
+B21,$04,$01,$15,b21,85,85
+H21,$04,$03,$15,h21,85,85
+S21,$04,$09,$15,s21,85,85
+D21,$04,$0a,$15,d21,85,85
+Q21,$04,$05,$15,q21,85,85
+B22,$04,$01,$16,b22,86,86
+H22,$04,$03,$16,h22,86,86
+S22,$04,$09,$16,s22,86,86
+D22,$04,$0a,$16,d22,86,86
+Q22,$04,$05,$16,q22,86,86
+B23,$04,$01,$17,b23,87,87
+H23,$04,$03,$17,h23,87,87
+S23,$04,$09,$17,s23,87,87
+D23,$04,$0a,$17,d23,87,87
+Q23,$04,$05,$17,q23,87,87
+B24,$04,$01,$18,b24,88,88
+H24,$04,$03,$18,h24,88,88
+S24,$04,$09,$18,s24,88,88
+D24,$04,$0a,$18,d24,88,88
+Q24,$04,$05,$18,q24,88,88
+B25,$04,$01,$19,b25,89,89
+H25,$04,$03,$19,h25,89,89
+S25,$04,$09,$19,s25,89,89
+D25,$04,$0a,$19,d25,89,89
+Q25,$04,$05,$19,q25,89,89
+B26,$04,$01,$1A,b26,90,90
+H26,$04,$03,$1A,h26,90,90
+S26,$04,$09,$1A,s26,90,90
+D26,$04,$0a,$1A,d26,90,90
+Q26,$04,$05,$1A,q26,90,90
+B27,$04,$01,$1B,b27,91,91
+H27,$04,$03,$1B,h27,91,91
+S27,$04,$09,$1B,s27,91,91
+D27,$04,$0a,$1B,d27,91,91
+Q27,$04,$05,$1B,q27,91,91
+B28,$04,$01,$1C,b28,92,92
+H28,$04,$03,$1C,h28,92,92
+S28,$04,$09,$1C,s28,92,92
+D28,$04,$0a,$1C,d28,92,92
+Q28,$04,$05,$1C,q28,92,92
+B29,$04,$01,$1D,b29,93,93
+H29,$04,$03,$1D,h29,93,93
+S29,$04,$09,$1D,s29,93,93
+D29,$04,$0a,$1D,d29,93,93
+Q29,$04,$05,$1D,q29,93,93
+B30,$04,$01,$1E,b30,94,94
+H30,$04,$03,$1E,h30,94,94
+S30,$04,$09,$1E,s30,94,94
+D30,$04,$0a,$1E,d30,94,94
+Q30,$04,$05,$1E,q30,94,94
+B31,$04,$01,$1F,b31,95,95
+H31,$04,$03,$1F,h31,95,95
+S31,$04,$09,$1F,s31,95,95
+D31,$04,$0a,$1F,d31,95,95
+Q31,$04,$05,$1F,q31,95,95
 
 NZCV,$05,$00,$00,nzcv,0,0
-
+FPCR,$05,$00,$01,fpcr,0,0
+FPSR,$05,$00,$02,fpsr,0,0
+TPIDR_EL0,$05,$00,$03,tpidr_el0,0,0
index 437c9126ba02cb8317c1693c12e868703cd505eb..bcf4b0ddf4c2a32d76537f60c23d95170b5ca401 100644 (file)
@@ -1,4 +1,4 @@
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
 (
 
 );
index 8624744df88b4030bd81441c65b51ceadc142526..f9888517189f5fb0299b662d5902867fd2e3a531 100644 (file)
@@ -1,7 +1,7 @@
 {
     Copyright (c) 2003-2012 by Florian Klaempfl and others
 
-    Contains the assembler object for ARM64
+    Contains the assembler object for Aarch64
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -149,9 +149,6 @@ uses
 
       pinsentry=^tinsentry;
 
-{    const
-      InsTab : array[0..instabentries-1] of TInsEntry={$i a64tab.inc} }
-
     var
       InsTabCache : PInsTabCache;
 
@@ -159,6 +156,7 @@ uses
       taicpu = class(tai_cpu_abstract_sym)
          oppostfix : TOpPostfix;
          procedure loadshifterop(opidx:longint;const so:tshifterop);
+         procedure loadconditioncode(opidx: longint; const c: tasmcond);
          constructor op_none(op : tasmop);
 
          constructor op_reg(op : tasmop;_op1 : tregister);
@@ -167,15 +165,21 @@ uses
 
          constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
          constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+         constructor op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
          constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+         constructor op_reg_const_shifterop(op : tasmop;_op1: tregister; _op2: aint;_op3 : tshifterop);
 
          constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
          constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
          constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+         constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3, _op4: aint);
+         constructor op_reg_reg_const_shifterop(op : tasmop;_op1,_op2 : tregister; _op3: aint; const _op4 : tshifterop);
          constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
          constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
          constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
-         constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+         constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
+         constructor op_reg_reg_reg_cond(op : tasmop;_op1,_op2,_op3 : tregister; const _op4: tasmcond);
+
 
          { this is for Jmp instructions }
          constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
@@ -188,6 +192,7 @@ uses
          function is_same_reg_move(regtype: Tregistertype):boolean; override;
 
          function spilling_get_operation_type(opnr: longint): topertype;override;
+         function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
 
          { assembler }
       public
@@ -203,28 +208,29 @@ uses
          procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
          procedure ppubuildderefimploper(var o:toper);override;
          procedure ppuderefoper(var o:toper);override;
-      private
-         { next fields are filled in pass1, so pass2 is faster }
-         inssize   : shortint;
-         insoffset : longint;
-         LastInsOffset : longint; { need to be public to be reset }
-         insentry  : PInsEntry;
-         function  InsEnd:longint;
-         procedure create_ot(objdata:TObjData);
-         function  Matches(p:PInsEntry):longint;
-         function  calcsize(p:PInsEntry):shortint;
-         procedure gencode(objdata:TObjData);
-         function  NeedAddrPrefix(opidx:byte):boolean;
-         procedure Swapoperands;
-         function  FindInsentry(objdata:TObjData):boolean;
       end;
 
       tai_align = class(tai_align_abstract)
         { nothing to add }
       end;
 
-    function spilling_create_load(const ref:treference;r:tregister):Taicpu;
-    function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+    type
+      tsimplereftype =
+         { valid reference }
+        (sr_simple,
+         { invalid reference, should not be generated by the code generator (but
+           can be encountered via inline assembly, where it must be rejected) }
+         sr_internal_illegal,
+         { invalid reference, may be generated by the code generator and then
+           must be simplified (also rejected in inline assembly) }
+         sr_complex);
+
+    function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
+    function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
+    function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
+
+    function spilling_create_load(const ref: treference; r: tregister): taicpu;
+    function spilling_create_store(r: tregister; const ref: treference): taicpu;
 
     function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
     function setcondition(i : taicpu;c : tasmcond) : taicpu;
@@ -261,6 +267,21 @@ implementation
       end;
 
 
+    procedure taicpu.loadconditioncode(opidx: longint; const c: tasmcond);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+          begin
+            if typ<>top_conditioncode then
+              begin
+                clearop(opidx);
+              end;
+            cc:=c;
+            typ:=top_conditioncode;
+          end;
+      end;
+
+
 {*****************************************************************************
                                  taicpu Constructors
 *****************************************************************************}
@@ -314,6 +335,16 @@ implementation
       end;
 
 
+    constructor taicpu.op_reg_const_shifterop(op: tasmop; _op1: tregister; _op2: aint; _op3: tshifterop);
+      begin
+        inherited create(op);
+        ops:=3;
+        loadreg(0,_op1);
+        loadconst(1,_op2);
+        loadshifterop(2,_op3);
+      end;
+
+
     constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
       begin
          inherited create(op);
@@ -323,6 +354,15 @@ implementation
       end;
 
 
+    constructor taicpu.op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
+      begin
+        inherited create(op);
+        ops:=2;
+        loadreg(0,_op1);
+        loadconditioncode(1,_op2);
+      end;
+
+
     constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
       begin
          inherited create(op);
@@ -354,6 +394,28 @@ implementation
       end;
 
 
+     constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+       begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadconst(2,aint(_op3));
+         loadconst(3,aint(_op4));
+       end;
+
+
+     constructor taicpu.op_reg_reg_const_shifterop(op: tasmop; _op1, _op2: tregister; _op3: aint; const _op4: tshifterop);
+       begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadconst(2,aint(_op3));
+         loadshifterop(3,_op4);
+       end;
+
+
      constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
        begin
          inherited create(op);
@@ -384,7 +446,7 @@ implementation
       end;
 
 
-     constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+     constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
       begin
          inherited create(op);
          ops:=4;
@@ -394,6 +456,16 @@ implementation
          loadshifterop(3,_op4);
       end;
 
+     constructor taicpu.op_reg_reg_reg_cond(op: tasmop; _op1, _op2, _op3: tregister; const _op4: tasmcond);
+       begin
+         inherited create(op);
+         ops:=4;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+         loadconditioncode(3,_op4);
+       end;
+
 
     constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
       begin
@@ -454,85 +526,403 @@ implementation
       end;
 
 
-    function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+    function spilling_create_op(op: tasmop; const ref: treference; r: tregister): taicpu;
+      const
+        { invalid sizes for aarch64 are 0 }
+        subreg2bytesize: array[TSubRegister] of byte =
+          (0,0,0,0,4,8,0,0,0,4,8,0,0,0);
       var
-        op: tasmop;
+        scalefactor: byte;
       begin
+        scalefactor:=subreg2bytesize[getsubreg(r)];
+        if scalefactor=0 then
+          internalerror(2014120301);
+        if (ref.offset>4095*scalefactor) or
+           ((ref.offset>255) and
+            ((ref.offset mod scalefactor)<>0)) or
+           (ref.offset<-256) then
+          internalerror(2014120302);
         case getregtype(r) of
-          R_INTREGISTER :
-            result:=taicpu.op_reg_ref(A_LDR,r,ref);
-          R_MMREGISTER :
-            begin
-              case getsubreg(r) of
-                R_SUBFD:
-                  op:=A_LDR;
-                R_SUBFS:
-                  op:=A_LDR;
-                else
-                  internalerror(2009112905);
-              end;
-              result:=taicpu.op_reg_ref(op,r,ref);
-            end;
+          R_INTREGISTER,
+          R_MMREGISTER:
+            result:=taicpu.op_reg_ref(op,r,ref);
           else
             internalerror(200401041);
         end;
       end;
 
 
-    function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+    function is_valid_load_symbol(op: tasmop; oppostfix: toppostfix; const ref: treference): tsimplereftype;
+      begin
+        result:=sr_complex;
+        if not assigned(ref.symboldata) and
+           not(ref.refaddr in [addr_gotpageoffset,addr_gotpage,addr_pageoffset,addr_page]) then
+          exit;
+        { can't use pre-/post-indexed mode here (makes no sense either) }
+        if ref.addressmode<>AM_OFFSET then
+          exit;
+        { "ldr literal" must be a 32/64 bit LDR and have a symbol }
+        if assigned(ref.symboldata) and
+           ((op<>A_LDR) or
+            not(oppostfix in [PF_NONE,PF_W,PF_SW]) or
+            not assigned(ref.symbol)) then
+          exit;
+        { if this is a (got) page offset load, we must have a base register and a
+          symbol }
+        if (ref.refaddr in [addr_gotpageoffset,addr_pageoffset]) and
+           (not assigned(ref.symbol) or
+            (ref.base=NR_NO) or
+            (ref.index<>NR_NO) or
+            (ref.offset<>0)) then
+          begin
+            result:=sr_internal_illegal;
+            exit;
+          end;
+        { cannot have base or index register (we generate these kind of
+          references internally, they should never end up here with an
+          extra base or offset) }
+        if (ref.refaddr in [addr_gotpage,addr_page]) and
+           (ref.base<>NR_NO) or
+           (ref.index<>NR_NO) then
+          begin
+            result:=sr_internal_illegal;
+            exit;
+          end;
+        result:=sr_simple;
+      end;
+
+
+    function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
       var
-        op: tasmop;
+        maxoffs: asizeint;
+        accesssize: longint;
       begin
-        case getregtype(r) of
-          R_INTREGISTER :
-            result:=taicpu.op_reg_ref(A_STR,r,ref);
-          R_MMREGISTER :
-            begin
-              case getsubreg(r) of
-                R_SUBFD:
-                  op:=A_STR;
-                R_SUBFS:
-                  op:=A_STR;
+        result:=sr_internal_illegal;
+        { post-indexed is only allowed for vector and immediate loads/stores }
+        if (ref.addressmode=AM_POSTINDEXED) and
+           not(op in [A_LD1,A_LD2,A_LD3,A_LD4,A_ST1,A_ST2,A_ST3,A_ST4]) and
+           (not(op in [A_LDR,A_STR,A_LDP,A_STP]) or
+            (ref.base=NR_NO) or
+            (ref.index<>NR_NO)) then
+          exit;
+
+        { can only have a shift mode if we have an index }
+        if (ref.index=NR_NO) and
+           (ref.shiftmode<>SM_None) then
+          exit;
+
+        { the index can never be the stack pointer }
+        if ref.index=NR_SP then
+          exit;
+
+        { no instruction supports an index without a base }
+        if (ref.base=NR_NO) and
+           (ref.index<>NR_NO) then
+          begin
+            result:=sr_complex;
+            exit;
+          end;
+
+        { LDR literal or GOT entry: 32 or 64 bit, label }
+        if assigned(ref.symboldata) or
+           assigned(ref.symbol) then
+          begin
+            { we generate these kind of references internally; at least for now,
+              they should never end up here with an extra base or offset or so }
+            result:=is_valid_load_symbol(op,oppostfix,ref);
+            exit;
+          end;
+
+        { any other reference cannot be gotpage/gotpageoffset/pic }
+        if ref.refaddr in [addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset,addr_pic] then
+          exit;
+
+        { base & index:
+            * index cannot be the stack pointer
+            * offset must be 0
+            * can scale with the size of the access
+            * can zero/sign extend 32 bit index register, and/or multiple by
+              access size
+            * no pre/post-indexing
+        }
+        if (ref.base<>NR_NO) and
+           (ref.index<>NR_NO) then
+          begin
+            if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
+              exit;
+            case op of
+              { this holds for both integer and fpu/vector loads }
+              A_LDR,A_STR:
+                if (ref.offset=0) and
+                   (((ref.shiftmode=SM_None) and
+                     (ref.shiftimm=0)) or
+                    ((ref.shiftmode in [SM_LSL,SM_UXTW,SM_SXTW]) and
+                     (ref.shiftimm=tcgsizep2size[size]))) then
+                  result:=sr_simple
                 else
-                  internalerror(2009112904);
-              end;
-              result:=taicpu.op_reg_ref(op,r,ref);
+                  result:=sr_complex;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110704);
+              { these don't support base+index }
+              A_LDUR,A_STUR,
+              A_LDP,A_STP:
+                result:=sr_complex;
+              else
+                { nothing: result is already sr_internal_illegal };
             end;
+            exit;
+          end;
+
+        { base + immediate offset. Variants:
+            * LDR*/STR*:
+              - pre- or post-indexed with signed 9 bit immediate
+              - regular with unsiged scaled immediate (multiple of access
+                size), in the range 0 to (12 bit * access_size)-1
+            * LDP/STP
+              - pre- or post-indexed with signed 9 bit immediate
+              - regular with signed 9 bit immediate
+            * LDUR*/STUR*:
+              - regular with signed 9 bit immediate
+        }
+        if ref.base<>NR_NO then
+          begin
+            accesssize:=1 shl tcgsizep2size[size];
+            case op of
+              A_LDR,A_STR:
+                begin
+                  if (ref.addressmode=AM_OFFSET) and
+                     (ref.offset>=0) and
+                     (ref.offset<(((1 shl 12)-1)*accesssize)) and
+                     ((ref.offset mod accesssize)=0) then
+                    result:=sr_simple
+                  else if (ref.offset>=-256) and
+                     (ref.offset<=255) then
+                    begin
+                      { non pre-/post-indexed regular loads/stores can only be
+                        performed using LDUR/STUR }
+                      if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
+                        result:=sr_simple
+                      else
+                        result:=sr_complex
+                    end
+                  else
+                    result:=sr_complex;
+                end;
+              A_LDP,A_LDNP,
+              A_STP,A_STNP:
+                begin
+                  { only supported for 32/64 bit }
+                  if not(oppostfix in [PF_W,PF_SW,PF_None]) then
+                    exit;
+                  { offset must be a multple of the access size }
+                  if (ref.offset mod accesssize)<>0 then
+                    exit;
+                  { offset must fit in a signed 7 bit offset }
+                  if (ref.offset>=-(1 shl (6+tcgsizep2size[size]))) and
+                     (ref.offset<=(1 shl (6+tcgsizep2size[size]))-1) then
+                    result:=sr_simple
+                  else
+                    result:=sr_complex;
+                end;
+              A_LDUR,A_STUR:
+                begin
+                  if (ref.addressmode=AM_OFFSET) and
+                     (ref.offset>=-256) and
+                     (ref.offset<=255) then
+                    result:=sr_simple
+                  else
+                    result:=sr_complex;
+                end;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110907);
+              A_LDAR,
+              A_LDAXR,
+              A_LDXR,
+              A_LDXP,
+              A_STLR,
+              A_STLXR,
+              A_STLXP,
+              A_STXP,
+              A_STXR:
+                begin
+                  if (ref.addressmode=AM_OFFSET) and
+                     (ref.offset=0) then
+                    result:=sr_simple;
+                end
+              else
+                { nothing: result is already sr_internal_illegal };
+            end;
+            exit;
+          end;
+        { absolute addresses are not supported, have to load them first into
+          a register }
+        result:=sr_complex;
+      end;
+
+
+    function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
+      begin
+        case opc of
+          A_ADD,
+          A_AND,
+          A_EON,
+          A_EOR,
+          A_ORN,
+          A_ORR,
+          A_SUB:
+            result:=opnr=3;
+          A_BIC,
+          A_CMN,
+          A_CMP,
+          A_MOVK,
+          A_MOVZ,
+          A_MOVN,
+          A_MVN,
+          A_NEG,
+          A_TST:
+            result:=opnr=2;
           else
-            internalerror(200401041);
+            result:=false;
         end;
       end;
 
 
+    function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
+      begin
+        case opc of
+          A_ADD,
+          A_SUB,
+          A_NEG,
+          A_AND,
+          A_TST,
+          A_CMN,
+          A_CMP:
+            begin
+              result:=false;
+              if not useszr then
+                result:=
+                  (sm in shiftedregmodes) and
+                  ((shiftimm in [0..31]) or
+                   (is64bit and
+                    (shiftimm in [32..63])));
+              if not usessp then
+                result:=
+                  result or
+                  ((sm in extendedregmodes) and
+                   (shiftimm in [0..4]));
+            end;
+          A_BIC,
+          A_EON,
+          A_EOR,
+          A_MVN,
+          A_ORN,
+          A_ORR:
+            result:=
+              (sm in shiftedregmodes) and
+              (shiftimm in [0..31*(ord(is64bit)+1)+ord(is64bit)]);
+          A_MOVK,
+          A_MOVZ,
+          A_MOVN:
+            result:=
+              (sm=SM_LSL) and
+              ((shiftimm in [0,16]) or
+               (is64bit and
+                (shiftimm in [32,48])));
+          else
+            result:=false;
+        end;
+      end;
+
+
+    function spilling_create_load(const ref: treference; r: tregister): taicpu;
+      var
+        op: tasmop;
+      begin
+        if (ref.index<>NR_NO) or
+           (ref.offset<-256) or
+           (ref.offset>255) then
+          op:=A_LDR
+        else
+          op:=A_LDUR;
+        result:=spilling_create_op(op,ref,r);
+      end;
+
+
+    function spilling_create_store(r: tregister; const ref: treference): taicpu;
+      var
+        op: tasmop;
+      begin
+        if (ref.index<>NR_NO) or
+           (ref.offset<-256) or
+           (ref.offset>255) then
+          op:=A_STR
+        else
+          op:=A_STUR;
+        result:=spilling_create_op(op,ref,r);
+      end;
+
+
     function taicpu.spilling_get_operation_type(opnr: longint): topertype;
       begin
         case opcode of
-          A_ADC,A_ADD,A_AND,A_BIC,
-          A_EOR,A_CLZ,A_RBIT,
-          A_LDR,
-          A_MOV,A_MVN,A_MUL,
-          A_ORR,A_SBC,A_SUB,
-          A_UXT,A_SXT:
+          A_B,A_BL,
+          A_CMN,A_CMP,
+          A_CCMN,A_CCMP,
+          A_TST:
+            result:=operand_read;
+          A_STR,A_STUR:
             if opnr=0 then
-              result:=operand_write
+              result:=operand_read
             else
+              { check for pre/post indexed in spilling_get_operation_type_ref }
               result:=operand_read;
-          A_B,A_BL,
-          A_CMN,A_CMP,A_TST:
-            result:=operand_read;
-          A_STR:
-            { important is what happens with the involved registers }
+          A_STLXP,
+          A_STLXR,
+          A_STXP,
+          A_STXR:
             if opnr=0 then
-              result := operand_read
+              result:=operand_write
             else
-              { check for pre/post indexed }
-              result := operand_read;
-          else
-            internalerror(200403151);
+              result:=operand_read;
+          A_STP:
+            begin
+              if opnr in [0,1] then
+                result:=operand_read
+              else
+                { check for pre/post indexed in spilling_get_operation_type_ref }
+                result:=operand_read;
+            end;
+           A_LDP,
+           A_LDXP:
+             begin
+               if opnr in [0,1] then
+                 result:=operand_write
+               else
+                 { check for pre/post indexed in spilling_get_operation_type_ref }
+                 result:=operand_read;
+             end;
+           else
+             if opnr=0 then
+               result:=operand_write
+             else
+               result:=operand_read;
         end;
       end;
 
 
+    function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+      begin
+        result:=operand_read;
+        if (oper[opnr]^.ref^.base = reg) and
+          (oper[opnr]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
+           result:=operand_readwrite;
+      end;
+
+
     procedure BuildInsTabCache;
       var
         i : longint;
@@ -1069,22 +1459,12 @@ implementation
         { we need to reset everything here, because the choosen insentry
           can be invalid for a new situation where the previously optimized
           insentry is not correct }
-        InsEntry:=nil;
-        InsSize:=0;
-        LastInsOffset:=-1;
       end;
 
 
     procedure taicpu.ResetPass2;
       begin
         { we are here in a second pass, check if the instruction can be optimized }
-        if assigned(InsEntry) and
-           ((InsEntry^.flags and IF_PASS2)<>0) then
-         begin
-           InsEntry:=nil;
-           InsSize:=0;
-         end;
-        LastInsOffset:=-1;
       end;
 
 
@@ -1097,18 +1477,15 @@ implementation
     function taicpu.Pass1(objdata:TObjData):longint;
       begin
         Pass1:=0;
-        LastInsOffset:=-1;
       end;
 
 
     procedure taicpu.Pass2(objdata:TObjData);
       begin
         { error in pass1 ? }
-        if insentry=nil then
-         exit;
         current_filepos:=fileinfo;
         { Generate the instruction }
-        GenCode(objdata);
+        { GenCode(objdata); }
       end;
 
 
@@ -1132,1046 +1509,6 @@ implementation
       end;
 
 
-    function  taicpu.InsEnd:longint;
-      begin
-        Result:=0; { unimplemented }
-      end;
-
-
-    procedure taicpu.create_ot(objdata:TObjData);
-      begin
-      end;
-
-
-    function taicpu.Matches(p:PInsEntry):longint;
-      begin
-      end;
-
-
-    function  taicpu.calcsize(p:PInsEntry):shortint;
-      begin
-        result:=4;
-      end;
-
-
-    function  taicpu.NeedAddrPrefix(opidx:byte):boolean;
-      begin
-        Result:=False; { unimplemented }
-      end;
-
-
-    procedure taicpu.Swapoperands;
-      begin
-      end;
-
-
-    function taicpu.FindInsentry(objdata:TObjData):boolean;
-      begin
-      end;
-
-
-    procedure taicpu.gencode(objdata:TObjData);
-      var
-        bytes : dword;
-        i_field : byte;
-
-      procedure setshifterop(op : byte);
-        begin
-          case oper[op]^.typ of
-            top_const:
-              begin
-                i_field:=1;
-                bytes:=bytes or dword(oper[op]^.val and $fff);
-              end;
-            top_reg:
-              begin
-                i_field:=0;
-                bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
-
-                { does a real shifter op follow? }
-                if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
-                  begin
-                  end;
-              end;
-          else
-            internalerror(2005091103);
-          end;
-        end;
-
-      begin
-        bytes:=$0;
-        { evaluate and set condition code }
-
-        { condition code allowed? }
-
-        { setup rest of the instruction }
-        case insentry^.code[0] of
-          #$08:
-            begin
-              { set instruction code }
-              bytes:=bytes or (ord(insentry^.code[1]) shl 26);
-              bytes:=bytes or (ord(insentry^.code[2]) shl 21);
-
-              { set destination }
-              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
-
-              { create shifter op }
-              setshifterop(1);
-
-              { set i field }
-              bytes:=bytes or (i_field shl 25);
-
-              { set s if necessary }
-              if oppostfix=PF_S then
-                bytes:=bytes or (1 shl 20);
-            end;
-          #$ff:
-            internalerror(2005091101);
-          else
-            internalerror(2005091102);
-        end;
-        { we're finished, write code }
-        objdata.writebytes(bytes,sizeof(bytes));
-      end;
-
-
-{$ifdef dummy}
-(*
-static void gencode (long segment, long offset, int bits,
-                     insn *ins, char *codes, long insn_end)
-{
-    int has_S_code;             /* S - setflag */
-    int has_B_code;             /* B - setflag */
-    int has_T_code;             /* T - setflag */
-    int has_W_code;             /* ! => W flag */
-    int has_F_code;             /* ^ => S flag */
-    int keep;
-    unsigned char c;
-    unsigned char bytes[4];
-    long          data, size;
-    static int cc_code[] =      /* bit pattern of cc */
-  {                             /* order as enum in  */
-    0x0E, 0x03, 0x02, 0x00,     /* nasm.h            */
-    0x0A, 0x0C, 0x08, 0x0D,
-    0x09, 0x0B, 0x04, 0x01,
-    0x05, 0x07, 0x06,
-  };
-
-
-#ifdef DEBUG
-static char *CC[] =
-  {                                    /* condition code names */
-    "AL", "CC", "CS", "EQ",
-    "GE", "GT", "HI", "LE",
-    "LS", "LT", "MI", "NE",
-    "PL", "VC", "VS", "",
-    "S"
-};
-
-
-    has_S_code = (ins->condition & C_SSETFLAG);
-    has_B_code = (ins->condition & C_BSETFLAG);
-    has_T_code = (ins->condition & C_TSETFLAG);
-    has_W_code = (ins->condition & C_EXSETFLAG);
-    has_F_code = (ins->condition & C_FSETFLAG);
-    ins->condition = (ins->condition & 0x0F);
-
-
-    if (rt_debug)
-      {
-    printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
-            CC[ins->condition & 0x0F]);
-    if (has_S_code)
-      printf ("S");
-    if (has_B_code)
-      printf ("B");
-    if (has_T_code)
-      printf ("T");
-    if (has_W_code)
-      printf ("!");
-    if (has_F_code)
-      printf ("^");
-
-    printf ("\n");
-
-    c = *codes;
-
-    printf ("   (%d)  decode - '0x%02X'\n", ins->operands, c);
-
-
-    bytes[0] = 0xB;
-    bytes[1] = 0xE;
-    bytes[2] = 0xE;
-    bytes[3] = 0xF;
-      }
-
-    // First condition code in upper nibble
-    if (ins->condition < C_NONE)
-      {
-        c = cc_code[ins->condition] << 4;
-      }
-    else
-      {
-        c = cc_code[C_AL] << 4; // is often ALWAYS but not always
-      }
-
-
-    switch (keep = *codes)
-      {
-        case 1:
-          // B, BL
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-
-          if (ins->oprs[0].segment != segment)
-            {
-              // fais une relocation
-              c = 1;
-              data = 0; // Let the linker locate ??
-            }
-          else
-            {
-              c = 0;
-              data = ins->oprs[0].offset - (offset + 8);
-
-              if (data % 4)
-                {
-                  errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
-                }
-            }
-
-          if (data >= 0x1000)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-
-          data = data >> 2;
-          bytes[1] = (data >> 16) & 0xFF;
-          bytes[2] = (data >> 8)  & 0xFF;
-          bytes[3] = (data )      & 0xFF;
-
-          if (c == 1)
-            {
-//            out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
-              out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
-            }
-          else
-            {
-              out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
-            }
-          return;
-
-        case 2:
-          // SWI
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-          data = ins->oprs[0].offset;
-          bytes[1] = (data >> 16) & 0xFF;
-          bytes[2] = (data >> 8) & 0xFF;
-          bytes[3] = (data) & 0xFF;
-          out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-        case 3:
-          // BX
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-          bytes[1] = *codes++;
-          bytes[2] = *codes++;
-          bytes[3] = *codes++;
-          c = regval (&ins->oprs[0],1);
-          if (c == 15)  // PC
-            {
-              errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
-            }
-          else if (c > 15)
-            {
-              errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
-            }
-
-          bytes[3] |= (c & 0x0F);
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 4:         // AND Rd,Rn,Rm
-        case 5:         // AND Rd,Rn,Rm,<shift>Rs
-        case 6:         // AND Rd,Rn,Rm,<shift>imm
-        case 7:         // AND Rd,Rn,<shift>imm
-          ++codes;
-#ifdef DEBUG
-          if (rt_debug)
-            {
-              printf ("         decode - '0x%02X'\n", keep);
-              printf ("           code - '0x%02X'\n", (unsigned char) ( *codes));
-            }
-#endif
-          bytes[0] = c | *codes;
-          ++codes;
-
-          bytes[1] = *codes;
-          if (has_S_code)
-            bytes[1] |= 0x10;
-          c = regval (&ins->oprs[1],1);
-          // Rn in low nibble
-          bytes[1] |= c;
-
-          // Rd in high nibble
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          if (keep != 7)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[2],1);
-            }
-
-          // Shifts if any
-          if (keep == 5 || keep == 6)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 5)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[3],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 6)
-                {
-                  c = (ins->oprs[3].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[3]) << 5;
-
-              bytes[3] |= c;
-            }
-
-          // reg,reg,imm
-          if (keep == 7)
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[2].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 8:         // MOV Rd,Rm
-        case 9:         // MOV Rd,Rm,<shift>Rs
-        case 0xA:       // MOV Rd,Rm,<shift>imm
-        case 0xB:       // MOV Rd,<shift>imm
-          ++codes;
-#ifdef DEBUG
-          if (rt_debug)
-            {
-              printf ("         decode - '0x%02X'\n", keep);
-              printf ("           code - '0x%02X'\n", (unsigned char) ( *codes));
-            }
-#endif
-          bytes[0] = c | *codes;
-          ++codes;
-
-          bytes[1] = *codes;
-          if (has_S_code)
-            bytes[1] |= 0x10;
-
-          // Rd in high nibble
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          if (keep != 0x0B)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[1],1);
-            }
-
-          // Shifts if any
-          if (keep == 0x09 || keep == 0x0A)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 0x09)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[2],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 0x0A)
-                {
-                  c = (ins->oprs[2].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[2]) << 5;
-
-              bytes[3] |= c;
-            }
-
-          // reg,imm
-          if (keep == 0x0B)
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[1].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-
-        case 0xC:       // CMP Rn,Rm
-        case 0xD:       // CMP Rn,Rm,<shift>Rs
-        case 0xE:       // CMP Rn,Rm,<shift>imm
-        case 0xF:       // CMP Rn,<shift>imm
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes;
-
-          // Implicit S code
-          bytes[1] |= 0x10;
-
-          c = regval (&ins->oprs[0],1);
-          // Rn in low nibble
-          bytes[1] |= c;
-
-          // No destination
-          bytes[2] = 0;
-
-          if (keep != 0x0B)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[1],1);
-            }
-
-          // Shifts if any
-          if (keep == 0x0D || keep == 0x0E)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 0x0D)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[2],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 0x0E)
-                {
-                  c = (ins->oprs[2].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[2]) << 5;
-
-              bytes[3] |= c;
-            }
-
-          // reg,imm
-          if (keep == 0x0F)
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[1].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 0x10:      // MRS Rd,<psr>
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          c = regval (&ins->oprs[0],1);
-
-          bytes[2] = c << 4;
-
-          bytes[3] = 0;
-
-          c = ins->oprs[1].basereg;
-
-          if (c == R_CPSR || c == R_SPSR)
-            {
-              if (c == R_SPSR)
-                {
-                  bytes[1] |= 0x40;
-                }
-            }
-          else
-            {
-              errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
-            }
-
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-
-          return;
-
-        case 0x11:      // MSR <psr>,Rm
-        case 0x12:      // MSR <psrf>,Rm
-        case 0x13:      // MSR <psrf>,#expression
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          bytes[2] = *codes;
-
-
-          if (keep == 0x11 || keep == 0x12)
-            {
-              // Rm
-              c = regval (&ins->oprs[1],1);
-
-              bytes[3] = c;
-            }
-          else
-            {
-              int shimm;
-
-              shimm = imm_shift (ins->oprs[1].offset);
-
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
-
-          c = ins->oprs[0].basereg;
-
-          if ( keep == 0x11)
-            {
-              if ( c == R_CPSR || c == R_SPSR)
-                {
-                if ( c== R_SPSR)
-                  {
-                    bytes[1] |= 0x40;
-                  }
-                }
-            else
-              {
-                errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
-              }
-            }
-          else
-            {
-              if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
-                {
-                  if ( c== R_SPSR_FLG)
-                    {
-                      bytes[1] |= 0x40;
-                    }
-                }
-              else
-                {
-                  errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
-                }
-            }
-          break;
-
-        case 0x14:      // MUL  Rd,Rm,Rs
-        case 0x15:      // MULA Rd,Rm,Rs,Rn
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          bytes[3] = *codes;
-
-          // Rd
-          bytes[1] |= regval (&ins->oprs[0],1);
-          if (has_S_code)
-            bytes[1] |= 0x10;
-
-          // Rm
-          bytes[3] |= regval (&ins->oprs[1],1);
-
-          // Rs
-          bytes[2] = regval (&ins->oprs[2],1);
-
-          if (keep == 0x15)
-            {
-              bytes[2] |= regval (&ins->oprs[3],1) << 4;
-            }
-          break;
-
-        case 0x16:      // SMLAL RdHi,RdLo,Rm,Rs
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          bytes[3] = *codes;
-
-          // RdHi
-          bytes[1] |= regval (&ins->oprs[1],1);
-          if (has_S_code)
-            bytes[1] |= 0x10;
-
-          // RdLo
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          // Rm
-          bytes[3] |= regval (&ins->oprs[2],1);
-
-          // Rs
-          bytes[2] |= regval (&ins->oprs[3],1);
-
-          break;
-
-        case 0x17:      // LDR Rd, expression
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-          if (has_T_code)
-            {
-              errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
-            }
-          if (has_W_code)
-            {
-              errfunc (ERR_NONFATAL, "'!' not allowed");
-            }
-
-          // Rn - implicit R15
-          bytes[1] |= 0xF;
-
-          if (ins->oprs[1].segment != segment)
-            {
-              errfunc (ERR_NONFATAL, "label not in same segment");
-            }
-
-          data = ins->oprs[1].offset - (offset + 8);
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          if (data >= 0x1000)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-
-          bytes[2] |= ((data & 0xF00) >> 8);
-          bytes[3] = data & 0xFF;
-          break;
-
-        case 0x18:      // LDR Rd, [Rn]
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-          if (has_T_code)
-            {
-              bytes[1] |= 0x20;         // write-back
-            }
-          else
-            {
-              bytes[0] |= 0x01;         // implicit pre-index mode
-            }
-
-          if (has_W_code)
-            {
-              bytes[1] |= 0x20;         // write-back
-            }
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (c == 0x15)                // R15
-            data = -8;
-          else
-            data = 0;
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          bytes[2] |= ((data & 0xF00) >> 8);
-          bytes[3] = data & 0xFF;
-          break;
-
-        case 0x19:      // LDR Rd, [Rn,#expression]
-        case 0x20:      // LDR Rd, [Rn,Rm]
-        case 0x21:      // LDR Rd, [Rn,Rm,shift]
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (ins->oprs[ins->operands-1].bracket)       // FIXME: Bracket on last operand -> pre-index  <--
-            {
-              bytes[0] |= 0x01;         // pre-index mode
-              if (has_W_code)
-                {
-                  bytes[1] |= 0x20;
-                }
-              if (has_T_code)
-                {
-                  errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
-                }
-            }
-          else
-            {
-              if (has_T_code)           // Forced write-back in post-index mode
-                {
-                  bytes[1] |= 0x20;
-                }
-              if (has_W_code)
-                {
-                  errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
-                }
-            }
-
-          if (keep == 0x19)
-            {
-              data = ins->oprs[2].offset;
-
-              if (data < 0)
-                {
-                  data = -data;
-                }
-              else
-                {
-                  bytes[1] |= 0x80;
-                }
-
-              if (data >= 0x1000)
-                {
-                  errfunc (ERR_NONFATAL, "too long offset");
-                }
-
-              bytes[2] |= ((data & 0xF00) >> 8);
-              bytes[3] = data & 0xFF;
-            }
-          else
-            {
-              if (ins->oprs[2].minus == 0)
-                {
-                  bytes[1] |= 0x80;
-                }
-              c = regval (&ins->oprs[2],1);
-              bytes[3] = c;
-
-              if (keep == 0x21)
-                {
-                  c = ins->oprs[3].offset;
-                  if (c > 0x1F)
-                    {
-                      errfunc (ERR_NONFATAL, "too large shiftvalue");
-                      c = c & 0x1F;
-                    }
-
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  bytes[3] |= shiftval (&ins->oprs[3]) << 5;
-                }
-            }
-
-          break;
-
-        case 0x22:      // LDRH Rd, expression
-          ++codes;
-
-          bytes[0] = c | 0x01;          // Implicit pre-index
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          // Rn - implicit R15
-          bytes[1] |= 0xF;
-
-          if (ins->oprs[1].segment != segment)
-            {
-              errfunc (ERR_NONFATAL, "label not in same segment");
-            }
-
-          data = ins->oprs[1].offset - (offset + 8);
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          if (data >= 0x100)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-          bytes[3] = *codes++;
-
-          bytes[2] |= ((data & 0xF0) >> 4);
-          bytes[3] |= data & 0xF;
-          break;
-
-        case 0x23:      // LDRH Rd, Rn
-          ++codes;
-
-          bytes[0] = c | 0x01;          // Implicit pre-index
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (c == 0x15)                // R15
-            data = -8;
-          else
-            data = 0;
-
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
-
-          if (data >= 0x100)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-          bytes[3] = *codes++;
-
-          bytes[2] |= ((data & 0xF0) >> 4);
-          bytes[3] |= data & 0xF;
-          break;
-
-        case 0x24:      // LDRH Rd, Rn, expression
-        case 0x25:      // LDRH Rd, Rn, Rm
-          ++codes;
-
-          bytes[0] = c;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (ins->oprs[ins->operands-1].bracket)       // FIXME: Bracket on last operand -> pre-index  <--
-            {
-              bytes[0] |= 0x01;         // pre-index mode
-              if (has_W_code)
-                {
-                  bytes[1] |= 0x20;
-                }
-            }
-          else
-            {
-              if (has_W_code)
-                {
-                  errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
-                }
-            }
-
-          bytes[3] = *codes++;
-
-          if (keep == 0x24)
-            {
-              data = ins->oprs[2].offset;
-
-              if (data < 0)
-                {
-                  data = -data;
-                }
-              else
-                {
-                  bytes[1] |= 0x80;
-                }
-
-              if (data >= 0x100)
-                {
-                  errfunc (ERR_NONFATAL, "too long offset");
-                }
-
-              bytes[2] |= ((data & 0xF0) >> 4);
-              bytes[3] |= data & 0xF;
-            }
-          else
-            {
-              if (ins->oprs[2].minus == 0)
-                {
-                  bytes[1] |= 0x80;
-                }
-              c = regval (&ins->oprs[2],1);
-              bytes[3] |= c;
-
-            }
-          break;
-
-        case 0x26:      // LDM/STM Rn, {reg-list}
-          ++codes;
-
-          bytes[0] = c;
-
-          bytes[0] |= ( *codes >> 4) & 0xF;
-          bytes[1] = ( *codes << 4) & 0xF0;
-          ++codes;
-
-          if (has_W_code)
-            {
-              bytes[1] |= 0x20;
-            }
-          if (has_F_code)
-            {
-              bytes[1] |= 0x40;
-            }
-
-          // Rn
-          bytes[1] |= regval (&ins->oprs[0],1);
-
-          data = ins->oprs[1].basereg;
-
-          bytes[2] = ((data >> 8) & 0xFF);
-          bytes[3] = (data & 0xFF);
-
-          break;
-
-        case 0x27:      // SWP Rd, Rm, [Rn]
-          ++codes;
-
-          bytes[0] = c;
-
-          bytes[0] |= *codes++;
-
-          bytes[1] = regval (&ins->oprs[2],1);
-          if (has_B_code)
-            {
-              bytes[1] |= 0x40;
-            }
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          bytes[3] = *codes++;
-          bytes[3] |= regval (&ins->oprs[1],1);
-          break;
-
-        default:
-          errfunc (ERR_FATAL, "unknown decoding of instruction");
-
-          bytes[0] = c;
-          // And a fix nibble
-          ++codes;
-          bytes[0] |= *codes++;
-
-         if ( *codes == 0x01)           // An I bit
-           {
-
-           }
-         if ( *codes == 0x02)           // An I bit
-           {
-
-           }
-         ++codes;
-      }
-    out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-}
-
-*)
-{$endif dummy}
-
 begin
   cai_align:=tai_align;
 end.
diff --git a/fpcsrc/compiler/aarch64/agcpugas.pas b/fpcsrc/compiler/aarch64/agcpugas.pas
new file mode 100644 (file)
index 0000000..1782f64
--- /dev/null
@@ -0,0 +1,303 @@
+{
+    Copyright (c) 2003,2014 by Florian Klaempfl and Jonas Maebe
+
+    This unit implements an asm for AArch64
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit implements the GNU Assembler writer for AArch64
+}
+
+unit agcpugas;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+       globtype,
+       aasmtai,
+       aggas,
+       cpubase,cpuinfo;
+
+    type
+      TAArch64InstrWriter=class(TCPUInstrWriter)
+        procedure WriteInstruction(hp : tai);override;
+      end;
+
+      TAArch64Assembler=class(TGNUassembler)
+        constructor create(smart: boolean); override;
+      end;
+
+      TAArch64AppleAssembler=class(TAppleGNUassembler)
+        constructor create(smart: boolean); override;
+      end;
+
+
+    const
+      gas_shiftmode2str : array[tshiftmode] of string[4] = (
+        '','lsl','lsr','asr',
+        'uxtb','uxth','uxtw','uxtx',
+        'sxtb','sxth','sxtw','sxtx');
+
+    const 
+      cputype_to_gas_march : array[tcputype] of string = (
+        '', // cpu_none
+        'armv8'
+      );
+
+  implementation
+
+    uses
+       cutils,globals,verbose,
+       systems,
+       assemble,
+       aasmcpu,
+       itcpugas,
+       cgbase,cgutils;
+
+
+{****************************************************************************}
+{                      AArch64 Assembler writer                              }
+{****************************************************************************}
+
+    constructor TAArch64Assembler.create(smart: boolean);
+      begin
+        inherited create(smart);
+        InstrWriter := TAArch64InstrWriter.create(self);
+      end;
+
+{****************************************************************************}
+{                      Apple AArch64 Assembler writer                        }
+{****************************************************************************}
+
+    constructor TAArch64AppleAssembler.create(smart: boolean);
+      begin
+        inherited create(smart);
+        InstrWriter := TAArch64InstrWriter.create(self);
+      end;
+
+
+{****************************************************************************}
+{                  Helper routines for Instruction Writer                    }
+{****************************************************************************}
+
+    function getreferencestring(var ref : treference) : string;
+      const
+        darwin_addrpage2str: array[addr_page..addr_gotpageoffset] of string[11] =
+           ('@PAGE','@PAGEOFF','@GOTPAGE','@GOTPAGEOFF');
+        linux_addrpage2str: array[addr_page..addr_gotpageoffset] of string[10] =
+           ('',':lo12:',':got:',':got_lo12:');
+      begin
+        if ref.base=NR_NO then
+          begin
+            case ref.refaddr of
+              addr_gotpage,
+              addr_page,
+              addr_gotpageoffset,
+              addr_pageoffset:
+                begin
+                  if not assigned(ref.symbol) or
+                     (ref.base<>NR_NO) or
+                     (ref.index<>NR_NO) or
+                     (ref.shiftmode<>SM_None) or
+                     (ref.offset<>0) then
+                    internalerror(2014121501);
+                  if target_info.system in systems_darwin then
+                    result:=ref.symbol.name+darwin_addrpage2str[ref.refaddr]
+                  else
+                    result:=linux_addrpage2str[ref.refaddr]+ref.symbol.name
+                end
+              else
+                internalerror(2015022301);
+            end
+          end
+        else
+          begin
+            result:='['+gas_regname(ref.base);
+            if ref.addressmode=AM_POSTINDEXED then
+              result:=result+']';
+            if ref.index<>NR_NO then
+              begin
+                if (ref.offset<>0) or
+                   assigned(ref.symbol) then
+                  internalerror(2014121504);
+                result:=result+', '+gas_regname(ref.index);
+                case ref.shiftmode of
+                  SM_None: ;
+                  SM_LSL,
+                  SM_UXTW, SM_UXTX, SM_SXTW, SM_SXTX:
+                    begin
+                      result:=result+', '+gas_shiftmode2str[ref.shiftmode];
+                      if (ref.shiftmode=SM_LSL) or
+                         (ref.shiftimm<>0) then
+                        result:=result+' #'+tostr(ref.shiftimm);
+                    end
+                  else
+                    internalerror(2014121505);
+                end;
+              end
+            else
+              begin
+                if assigned(ref.symbol) then
+                  begin
+                    case ref.refaddr of
+                      addr_gotpageoffset,
+                      addr_pageoffset:
+                        begin
+                          if target_info.system in systems_darwin then
+                            result:=result+', '+ref.symbol.name+darwin_addrpage2str[ref.refaddr]
+                          else
+                            result:=result+', '+linux_addrpage2str[ref.refaddr]+ref.symbol.name
+                        end
+                      else
+                        { todo: not yet generated/don't know syntax }
+                        internalerror(2014121506);
+                    end;
+                  end
+                else
+                  begin
+                    if ref.refaddr<>addr_no then
+                      internalerror(2014121506);
+                    if (ref.offset<>0) then
+                      result:=result+', #'+tostr(ref.offset);
+                  end;
+              end;
+            case ref.addressmode of
+              AM_OFFSET:
+                result:=result+']';
+              AM_PREINDEXED:
+                result:=result+']!';
+            end;
+          end;
+      end;
+
+
+    function getopstr(hp: taicpu; opnr: longint; const o: toper): string;
+      begin
+        case o.typ of
+          top_reg:
+            { we cannot yet represent "umov w0, v4.s[0]" or "ins v4.d[0], x1",
+              so for now we use "s4" or "d4" instead -> translate here }
+            if ((hp.opcode=A_INS) or
+                (hp.opcode=A_UMOV)) and
+               (getregtype(hp.oper[opnr]^.reg)=R_MMREGISTER) then
+              begin
+                case getsubreg(hp.oper[opnr]^.reg) of
+                  R_SUBMMS:
+                    getopstr:='v'+tostr(getsupreg(hp.oper[opnr]^.reg))+'.S[0]';
+                  R_SUBMMD:
+                    getopstr:='v'+tostr(getsupreg(hp.oper[opnr]^.reg))+'.D[0]';
+                  else
+                    internalerror(2014122907);
+                end;
+              end
+            else
+              getopstr:=gas_regname(o.reg);
+          top_shifterop:
+            begin
+              getopstr:=gas_shiftmode2str[o.shifterop^.shiftmode];
+              if o.shifterop^.shiftimm<>0 then
+                getopstr:=getopstr+' #'+tostr(o.shifterop^.shiftimm)
+            end;
+          top_const:
+            if o.val>=0 then
+              getopstr:='#'+tostr(o.val)
+            else
+              getopstr:='#0x'+hexStr(o.val,16);
+          top_conditioncode:
+            getopstr:=cond2str[o.cc];
+          top_ref:
+            if is_calljmp(hp.opcode) then
+              begin
+                if o.ref^.refaddr<>addr_full then
+                  internalerror(2014122220);
+                if not assigned(o.ref^.symbol) or
+                   assigned(o.ref^.relsymbol) or
+                   (o.ref^.base<>NR_NO) or
+                   (o.ref^.index<>NR_NO) or
+                   (o.ref^.offset<>0) then
+                  internalerror(2014122221);
+                getopstr:=o.ref^.symbol.name;
+              end
+            else
+              getopstr:=getreferencestring(o.ref^);
+          else
+            internalerror(2014121507);
+        end;
+      end;
+
+
+    procedure TAArch64InstrWriter.WriteInstruction(hp : tai);
+      var
+        op: TAsmOp;
+        s: string;
+        i: byte;
+        sep: string[3];
+      begin
+        op:=taicpu(hp).opcode;
+        s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix];
+        if taicpu(hp).condition<>C_NONE then
+          s:=s+'.'+cond2str[taicpu(hp).condition];
+        if taicpu(hp).ops<>0 then
+          begin
+            sep:=#9;
+            for i:=0 to taicpu(hp).ops-1 do
+              begin
+                 // debug code
+                 // writeln(s);
+                 // writeln(taicpu(hp).fileinfo.line);
+                 s:=s+sep+getopstr(taicpu(hp),i,taicpu(hp).oper[i]^);
+                 sep:=',';
+              end;
+          end;
+        owner.AsmWriteLn(s);
+      end;
+
+
+    const
+       as_aarch64_gas_info : tasminfo =
+          (
+            id     : as_gas;
+            idtxt  : 'AS';
+            asmbin : 'as';
+            asmcmd : '-o $OBJ $EXTRAOPT $ASM';
+            supported_targets : [system_aarch64_linux];
+            flags : [af_needar,af_smartlink_sections];
+            labelprefix : '.L';
+            comment : '// ';
+            dollarsign: '$';
+          );
+
+       as_aarch64_clang_darwin_info : tasminfo =
+          (
+            id     : as_clang;
+            idtxt  : 'CLANG';
+            asmbin : 'clang';
+            asmcmd : '-c -o $OBJ $EXTRAOPT -arch arm64 $DARWINVERSION -x assembler $ASM';
+            supported_targets : [system_aarch64_darwin];
+            flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
+            labelprefix : 'L';
+            comment : '# ';
+            dollarsign: '$';
+          );
+
+
+begin
+  RegisterAssembler(as_aarch64_gas_info,TAArch64Assembler);
+  RegisterAssembler(as_aarch64_clang_darwin_info,TAArch64AppleAssembler);
+end.
index d3964a02a35f92860894d3503a94f077be983998..d4fbac69c99b1d0d6f6d6c2d4ea2e66b95f764d9 100644 (file)
@@ -118,17 +118,35 @@ Implementation
     End;
 
 
-  function TAoptBaseCpu.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
+  function TAoptBaseCpu.RegModifiedByInstruction(reg: tregister; p1: tai): boolean;
     var
-      i : Longint;
+      i: longint;
+      preg: tregister;
     begin
       result:=false;
       for i:=0 to taicpu(p1).ops-1 do
-        if (taicpu(p1).oper[i]^.typ=top_reg) and (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
-          begin
-            result:=true;
-            exit;
-          end;
+        case taicpu(p1).oper[i]^.typ of
+          top_reg:
+            begin
+              preg:=taicpu(p1).oper[i]^.reg;
+              if (getregtype(preg)=getregtype(reg)) and
+                 (getsupreg(preg)=getsupreg(reg)) and
+                 (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
+                begin
+                  result:=true;
+                  exit;
+                end;
+            end;
+          top_ref:
+            begin
+              if (taicpu(p1).oper[i]^.ref^.addressmode<>am_offset) and
+                 (reg=taicpu(p1).oper[i]^.ref^.base) then
+                begin
+                  result:=true;
+                  exit
+                end;
+            end;
+        end;
     end;
 
 End.
diff --git a/fpcsrc/compiler/aarch64/cgcpu.pas b/fpcsrc/compiler/aarch64/cgcpu.pas
new file mode 100644 (file)
index 0000000..7faf780
--- /dev/null
@@ -0,0 +1,2275 @@
+{
+    Copyright (c) 2014 by Jonas Maebe
+
+    This unit implements the code generator for AArch64
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       globtype,parabase,
+       cgbase,cgutils,cgobj,
+       aasmbase,aasmtai,aasmdata,aasmcpu,
+       cpubase,cpuinfo,
+       node,symconst,SymType,symdef,
+       rgcpu;
+
+    type
+      tcgaarch64=class(tcg)
+       protected
+        { simplifies "ref" so it can be used with "op". If "ref" can be used
+          with a different load/Store operation that has the same meaning as the
+          original one, "op" will be replaced with the alternative }
+        procedure make_simple_ref(list:TAsmList; var op: tasmop; size: tcgsize; oppostfix: toppostfix; var ref: treference; preferred_newbasereg: tregister);
+        { changes register size without adding register allocation info }
+        function makeregsize(reg: tregister; size: tcgsize): tregister; overload;
+       public
+        function getfpuregister(list: TAsmList; size: Tcgsize): Tregister; override;
+        procedure handle_reg_imm12_reg(list: TAsmList; op: Tasmop; size: tcgsize; src: tregister; a: tcgint; dst: tregister; tmpreg: tregister; setflags, usedest: boolean);
+        procedure init_register_allocators;override;
+        procedure done_register_allocators;override;
+        function  getmmregister(list:TAsmList;size:tcgsize):tregister;override;
+        function handle_load_store(list:TAsmList; op: tasmop; size: tcgsize; oppostfix: toppostfix; reg: tregister; ref: treference):treference;
+        procedure a_call_name(list:TAsmList;const s:string; weak: boolean);override;
+        procedure a_call_reg(list:TAsmList;Reg:tregister);override;
+        { General purpose instructions }
+        procedure maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
+        procedure a_op_const_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; reg: tregister);override;
+        procedure a_op_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src, dst: tregister);override;
+        procedure a_op_const_reg_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister);override;
+        procedure a_op_reg_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister);override;
+        procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister; setflags : boolean; var ovloc : tlocation);override;
+        procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister; setflags : boolean; var ovloc : tlocation);override;
+        { move instructions }
+        procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg: tregister);override;
+        procedure a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference); override;
+        procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister;const ref: TReference);override;
+        procedure a_load_reg_ref_unaligned(list: TAsmList; fromsize, tosize: tcgsize; register: tregister; const ref: treference); override;
+        procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);override;
+        procedure a_load_ref_reg_unaligned(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; register: tregister); override;
+        procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);override;
+        procedure a_loadaddr_ref_reg(list: TAsmList; const ref: TReference; r: tregister);override;
+        { fpu move instructions (not used, all floating point is vector unit-based) }
+        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+        procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);override;
+        procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister; shuffle: pmmshuffle);override;
+        procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference; shuffle: pmmshuffle);override;
+
+        procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle); override;
+        procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle); override;
+
+        procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle); override;
+
+        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
+        { comparison operations }
+        procedure a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);override;
+        procedure a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);override;
+        procedure a_jmp_always(list: TAsmList; l: TAsmLabel);override;
+        procedure a_jmp_name(list: TAsmList; const s: string);override;
+        procedure a_jmp_cond(list: TAsmList; cond: TOpCmp; l: tasmlabel);{ override;}
+        procedure a_jmp_flags(list: TAsmList; const f: tresflags; l: tasmlabel);override;
+        procedure g_flags2reg(list: TAsmList; size: tcgsize; const f:tresflags; reg: tregister);override;
+        procedure g_overflowcheck(list: TAsmList; const loc: tlocation; def: tdef);override;
+        procedure g_overflowcheck_loc(list: TAsmList; const loc: tlocation; def: tdef; ovloc: tlocation);override;
+        procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);override;
+        procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);override;
+        procedure g_maybe_got_init(list: TAsmList); override;
+        procedure g_restore_registers(list: TAsmList);override;
+        procedure g_save_registers(list: TAsmList);override;
+        procedure g_concatcopy_move(list: TAsmList; const source, dest: treference; len: tcgint);
+        procedure g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);override;
+        procedure g_adjust_self_value(list: TAsmList; procdef: tprocdef; ioffset: tcgint);override;
+        procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+       private
+        function save_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister): longint;
+        procedure load_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister);
+      end;
+
+    procedure create_codegen;
+
+    const
+      TOpCG2AsmOpReg: array[topcg] of TAsmOp = (
+        A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NEG,A_MVN,A_ORR,A_ASRV,A_LSLV,A_LSRV,A_SUB,A_EOR,A_NONE,A_RORV
+      );
+      TOpCG2AsmOpImm: array[topcg] of TAsmOp = (
+        A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NEG,A_MVN,A_ORR,A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_NONE,A_ROR
+      );
+      TOpCmp2AsmCond: array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
+        C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI
+      );
+
+
+implementation
+
+  uses
+    globals,verbose,systems,cutils,
+    paramgr,fmodule,
+    symtable,symsym,
+    tgobj,
+    procinfo,cpupi;
+
+
+    procedure tcgaarch64.make_simple_ref(list:TAsmList; var op: tasmop; size: tcgsize; oppostfix: toppostfix; var ref: treference; preferred_newbasereg: tregister);
+      var
+        href: treference;
+        so: tshifterop;
+        accesssize: longint;
+      begin
+        if (ref.base=NR_NO) then
+          begin
+            if ref.shiftmode<>SM_None then
+              internalerror(2014110701);
+            ref.base:=ref.index;
+            ref.index:=NR_NO;
+          end;
+        { no abitrary scale factor support (the generic code doesn't set it,
+          AArch-specific code shouldn't either) }
+        if not(ref.scalefactor in [0,1]) then
+          internalerror(2014111002);
+
+        case simple_ref_type(op,size,oppostfix,ref) of
+          sr_simple:
+            exit;
+          sr_internal_illegal:
+            internalerror(2014121702);
+          sr_complex:
+            { continue } ;
+        end;
+
+        if assigned(ref.symbol) then
+          begin
+            { internal "load symbol" instructions should already be valid }
+            if assigned(ref.symboldata) or
+               (ref.refaddr in [addr_pic,addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset]) then
+              internalerror(2014110802);
+            { no relative symbol support (needed) yet }
+            if assigned(ref.relsymbol) then
+              internalerror(2014111001);
+            { loading a symbol address (whether it's in the GOT or not) consists
+              of two parts: first load the page on which it is located, then
+              either the offset in the page or load the value at that offset in
+              the page. This final GOT-load can be relaxed by the linker in case
+              the variable itself can be stored directly in the GOT }
+            if (preferred_newbasereg=NR_NO) or
+               (ref.base=preferred_newbasereg) or
+               (ref.index=preferred_newbasereg) then
+              preferred_newbasereg:=getaddressregister(list);
+            { load the (GOT) page }
+            reference_reset_symbol(href,ref.symbol,0,8);
+            if ((ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) and
+                (ref.symbol.bind in [AB_LOCAL,AB_GLOBAL])) or
+               ((ref.symbol.typ=AT_DATA) and
+                (ref.symbol.bind=AB_LOCAL)) then
+              href.refaddr:=addr_page
+            else
+              href.refaddr:=addr_gotpage;
+            list.concat(taicpu.op_reg_ref(A_ADRP,preferred_newbasereg,href));
+            { load the GOT entry (= address of the variable) }
+            reference_reset_base(href,preferred_newbasereg,0,sizeof(pint));
+            href.symbol:=ref.symbol;
+            { code symbols defined in the current compilation unit do not
+              have to be accessed via the GOT }
+            if ((ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) and
+                (ref.symbol.bind in [AB_LOCAL,AB_GLOBAL])) or
+               ((ref.symbol.typ=AT_DATA) and
+                (ref.symbol.bind=AB_LOCAL)) then
+              begin
+                href.base:=NR_NO;
+                href.refaddr:=addr_pageoffset;
+                list.concat(taicpu.op_reg_reg_ref(A_ADD,preferred_newbasereg,preferred_newbasereg,href));
+              end
+            else
+              begin
+                href.refaddr:=addr_gotpageoffset;
+                { use a_load_ref_reg() rather than directly encoding the LDR,
+                  so that we'll check the validity of the reference }
+                a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,preferred_newbasereg);
+              end;
+            { set as new base register }
+            if ref.base=NR_NO then
+              ref.base:=preferred_newbasereg
+            else if ref.index=NR_NO then
+              ref.index:=preferred_newbasereg
+            else
+              begin
+                { make sure it's valid in case ref.base is SP -> make it
+                  the second operand}
+                a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,preferred_newbasereg,ref.base,preferred_newbasereg);
+                ref.base:=preferred_newbasereg
+              end;
+            ref.symbol:=nil;
+          end;
+
+        { base & index }
+        if (ref.base<>NR_NO) and
+           (ref.index<>NR_NO) then
+          begin
+            case op of
+              A_LDR, A_STR:
+                begin
+                  if (ref.shiftmode=SM_None) and
+                     (ref.shiftimm<>0) then
+                    internalerror(2014110805);
+                  { wrong shift? (possible in case of something like
+                     array_of_2byte_rec[x].bytefield -> shift will be set 1, but
+                     the final load is a 1 byte -> can't use shift after all }
+                  if (ref.shiftmode in [SM_LSL,SM_UXTW,SM_SXTW]) and
+                     ((ref.shiftimm<>BsfDWord(tcgsizep2size[size])) or
+                      (ref.offset<>0)) then
+                    begin
+                      if preferred_newbasereg=NR_NO then
+                        preferred_newbasereg:=getaddressregister(list);
+                      { "add" supports a superset of the shift modes supported by
+                        load/store instructions }
+                      shifterop_reset(so);
+                      so.shiftmode:=ref.shiftmode;
+                      so.shiftimm:=ref.shiftimm;
+                      list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,preferred_newbasereg,ref.base,ref.index,so));
+                      reference_reset_base(ref,preferred_newbasereg,ref.offset,ref.alignment);
+                      { possibly still an invalid offset -> fall through }
+                    end
+                  else if ref.offset<>0 then
+                    begin
+                      if (preferred_newbasereg=NR_NO) or
+                         { we keep ref.index, so it must not be overwritten }
+                         (ref.index=preferred_newbasereg) then
+                        preferred_newbasereg:=getaddressregister(list);
+                      { add to the base and not to the index, because the index
+                        may be scaled; this works even if the base is SP }
+                      a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,preferred_newbasereg);
+                      ref.offset:=0;
+                      ref.base:=preferred_newbasereg;
+                      { finished }
+                      exit;
+                    end
+                  else
+                    { valid -> exit }
+                    exit;
+                end;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110704);
+              { these don't support base+index }
+              A_LDUR,A_STUR,
+              A_LDP,A_STP:
+                begin
+                  { these either don't support pre-/post-indexing, or don't
+                    support it with base+index }
+                  if ref.addressmode<>AM_OFFSET then
+                    internalerror(2014110911);
+                  if preferred_newbasereg=NR_NO then
+                    preferred_newbasereg:=getaddressregister(list);
+                  if ref.shiftmode<>SM_None then
+                    begin
+                      { "add" supports a superset of the shift modes supported by
+                        load/store instructions }
+                      shifterop_reset(so);
+                      so.shiftmode:=ref.shiftmode;
+                      so.shiftimm:=ref.shiftimm;
+                      list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,preferred_newbasereg,ref.base,ref.index,so));
+                    end
+                  else
+                    a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,ref.index,ref.base,preferred_newbasereg);
+                  reference_reset_base(ref,preferred_newbasereg,ref.offset,ref.alignment);
+                  { fall through to the handling of base + offset, since the
+                    offset may still be too big }
+                end;
+              else
+                internalerror(2014110901);
+            end;
+          end;
+
+        { base + offset }
+        if ref.base<>NR_NO then
+          begin
+            { valid offset for LDUR/STUR -> use that }
+            if (ref.addressmode=AM_OFFSET) and
+               (op in [A_LDR,A_STR]) and
+               (ref.offset>=-256) and
+               (ref.offset<=255) then
+              begin
+                if op=A_LDR then
+                  op:=A_LDUR
+                else
+                  op:=A_STUR
+              end
+            { if it's not a valid LDUR/STUR, use LDR/STR }
+            else if (op in [A_LDUR,A_STUR]) and
+               ((ref.offset<-256) or
+                (ref.offset>255) or
+                (ref.addressmode<>AM_OFFSET)) then
+              begin
+                if op=A_LDUR then
+                  op:=A_LDR
+                else
+                  op:=A_STR
+              end;
+            case op of
+              A_LDR,A_STR:
+                begin
+                  case ref.addressmode of
+                    AM_PREINDEXED:
+                      begin
+                        { since the loaded/stored register cannot be the same
+                          as the base register, we can safely add the
+                          offset to the base if it doesn't fit}
+                        if (ref.offset<-256) or
+                            (ref.offset>255) then
+                          begin
+                            a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base);
+                            ref.offset:=0;
+                          end;
+                      end;
+                    AM_POSTINDEXED:
+                      begin
+                        { cannot emulate post-indexing if we have to fold the
+                          offset into the base register }
+                        if (ref.offset<-256) or
+                            (ref.offset>255) then
+                          internalerror(2014110909);
+                        { ok }
+                      end;
+                    AM_OFFSET:
+                      begin
+                        { unsupported offset -> fold into base register }
+                        accesssize:=1 shl tcgsizep2size[size];
+                        if (ref.offset<0) or
+                           (ref.offset>(((1 shl 12)-1)*accesssize)) or
+                           ((ref.offset mod accesssize)<>0) then
+                          begin
+                            if preferred_newbasereg=NR_NO then
+                              preferred_newbasereg:=getaddressregister(list);
+                            { can we split the offset beween an
+                              "add/sub (imm12 shl 12)" and the load (also an
+                              imm12)?
+                              -- the offset from the load will always be added,
+                                that's why the lower bound has a smaller range
+                                than the upper bound; it must also be a multiple
+                                of the access size }
+                            if (ref.offset>=-(((1 shl 12)-1) shl 12)) and
+                               (ref.offset<=((1 shl 12)-1) shl 12 + ((1 shl 12)-1)) and
+                               ((ref.offset mod accesssize)=0) then
+                              begin
+                                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,(ref.offset shr 12) shl 12,ref.base,preferred_newbasereg);
+                                ref.offset:=ref.offset-(ref.offset shr 12) shl 12;
+                              end
+                            else
+                              begin
+                                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,preferred_newbasereg);
+                                ref.offset:=0;
+                              end;
+                            reference_reset_base(ref,preferred_newbasereg,ref.offset,ref.alignment);
+                          end;
+                      end
+                    else
+                      internalerror(2014110904);
+                  end;
+                end;
+              A_LDP,A_STP:
+                begin
+                  { unsupported offset -> fold into base register (these
+                    instructions support all addressmodes) }
+                  if (ref.offset<-(1 shl (6+tcgsizep2size[size]))) or
+                     (ref.offset>(1 shl (6+tcgsizep2size[size]))-1) then
+                    begin
+                      case ref.addressmode of
+                        AM_POSTINDEXED:
+                          { don't emulate post-indexing if we have to fold the
+                            offset into the base register }
+                          internalerror(2014110910);
+                        AM_PREINDEXED:
+                          { this means the offset must be added to the current
+                            base register }
+                          preferred_newbasereg:=ref.base;
+                        AM_OFFSET:
+                          if preferred_newbasereg=NR_NO then
+                            preferred_newbasereg:=getaddressregister(list);
+                      end;
+                      a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,preferred_newbasereg);
+                      reference_reset_base(ref,preferred_newbasereg,0,ref.alignment);
+                    end
+                end;
+              A_LDUR,A_STUR:
+                begin
+                  { valid, checked above }
+                end;
+              { todo }
+              A_LD1,A_LD2,A_LD3,A_LD4,
+              A_ST1,A_ST2,A_ST3,A_ST4:
+                internalerror(2014110908);
+              else
+                internalerror(2014110708);
+            end;
+            { done }
+            exit;
+          end;
+
+        { only an offset -> change to base (+ offset 0) }
+        if preferred_newbasereg=NR_NO then
+          preferred_newbasereg:=getaddressregister(list);
+        a_load_const_reg(list,OS_ADDR,ref.offset,preferred_newbasereg);
+        reference_reset_base(ref,preferred_newbasereg,0,newalignment(8,ref.offset));
+      end;
+
+
+    function tcgaarch64.makeregsize(reg: tregister; size: tcgsize): tregister;
+      var
+        subreg:Tsubregister;
+      begin
+        subreg:=cgsize2subreg(getregtype(reg),size);
+        result:=reg;
+        setsubreg(result,subreg);
+      end;
+
+
+    function tcgaarch64.getfpuregister(list: TAsmList; size: Tcgsize): Tregister;
+      begin
+        internalerror(2014122110);
+        { squash warning }
+        result:=NR_NO;
+      end;
+
+
+    function tcgaarch64.handle_load_store(list: TAsmList; op: tasmop; size: tcgsize; oppostfix: toppostfix; reg: tregister; ref: treference):treference;
+      begin
+        make_simple_ref(list,op,size,oppostfix,ref,NR_NO);
+        list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
+        result:=ref;
+      end;
+
+
+    procedure tcgaarch64.handle_reg_imm12_reg(list: TAsmList; op: Tasmop; size: tcgsize; src: tregister; a: tcgint; dst: tregister; tmpreg: tregister; setflags, usedest: boolean);
+      var
+        instr: taicpu;
+        so: tshifterop;
+        hadtmpreg: boolean;
+      begin
+        { imm12 }
+        if (a>=0) and
+           (a<=((1 shl 12)-1)) then
+          if usedest then
+            instr:=taicpu.op_reg_reg_const(op,dst,src,a)
+          else
+            instr:=taicpu.op_reg_const(op,src,a)
+        { imm12 lsl 12 }
+        else if (a and not(((tcgint(1) shl 12)-1) shl 12))=0 then
+          begin
+            so.shiftmode:=SM_LSL;
+            so.shiftimm:=12;
+            if usedest then
+              instr:=taicpu.op_reg_reg_const_shifterop(op,dst,src,a shr 12,so)
+            else
+              instr:=taicpu.op_reg_const_shifterop(op,src,a shr 12,so)
+          end
+        else
+          begin
+            { todo: other possible optimizations (e.g. load 16 bit constant in
+                register and then add/sub/cmp/cmn shifted the rest) }
+            if tmpreg=NR_NO then
+              begin
+                hadtmpreg:=false;
+                tmpreg:=getintregister(list,size);
+              end
+            else
+              begin
+                hadtmpreg:=true;
+                getcpuregister(list,tmpreg);
+              end;
+            a_load_const_reg(list,size,a,tmpreg);
+            if usedest then
+              instr:=taicpu.op_reg_reg_reg(op,dst,src,tmpreg)
+            else
+              instr:=taicpu.op_reg_reg(op,src,tmpreg);
+            if hadtmpreg then
+              ungetcpuregister(list,tmpreg);
+          end;
+        if setflags then
+          setoppostfix(instr,PF_S);
+        list.concat(instr);
+      end;
+
+
+{****************************************************************************
+                              Assembler code
+****************************************************************************}
+
+    procedure tcgaarch64.init_register_allocators;
+      begin
+        inherited init_register_allocators;
+
+        rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+            [RS_X0,RS_X1,RS_X2,RS_X3,RS_X4,RS_X5,RS_X6,RS_X7,RS_X8,
+             RS_X9,RS_X10,RS_X11,RS_X12,RS_X13,RS_X14,RS_X15,RS_X16,RS_X17,
+             RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28
+             { maybe we can enable this in the future for leaf functions (it's
+               the frame pointer)
+             ,RS_X29 }],
+            first_int_imreg,[]);
+
+        rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBMMD,
+            [RS_Q0,RS_Q1,RS_Q2,RS_Q3,RS_Q4,RS_Q5,RS_Q6,RS_Q7,
+             RS_Q8,RS_Q9,RS_Q10,RS_Q11,RS_Q12,RS_Q13,RS_Q14,RS_Q15,
+             RS_Q16,RS_Q17,RS_Q18,RS_Q19,RS_Q20,RS_Q21,RS_Q22,RS_Q23,
+             RS_Q24,RS_Q25,RS_Q26,RS_Q27,RS_Q28,RS_Q29,RS_Q30,RS_Q31],
+            first_mm_imreg,[]);
+      end;
+
+
+    procedure tcgaarch64.done_register_allocators;
+      begin
+        rg[R_INTREGISTER].free;
+        rg[R_FPUREGISTER].free;
+        rg[R_MMREGISTER].free;
+        inherited done_register_allocators;
+      end;
+
+
+    function tcgaarch64.getmmregister(list: TAsmList; size: tcgsize):tregister;
+      begin
+        case size of
+          OS_F32:
+            result:=rg[R_MMREGISTER].getregister(list,R_SUBMMS);
+          OS_F64:
+            result:=rg[R_MMREGISTER].getregister(list,R_SUBMMD)
+          else
+            internalerror(2014102701);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_call_name(list: TAsmList; const s: string; weak: boolean);
+      begin
+        if not weak then
+          list.concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(s)))
+        else
+          list.concat(taicpu.op_sym(A_BL,current_asmdata.WeakRefAsmSymbol(s)));
+      end;
+
+
+    procedure tcgaarch64.a_call_reg(list:TAsmList;Reg:tregister);
+      begin
+        list.concat(taicpu.op_reg(A_BLR,reg));
+      end;
+
+
+    {********************** load instructions ********************}
+
+    procedure tcgaarch64.a_load_const_reg(list: TAsmList; size: tcgsize; a: tcgint; reg : tregister);
+      var
+        preva: tcgint;
+        opc: tasmop;
+        shift,maxshift: byte;
+        so: tshifterop;
+        reginited: boolean;
+        mask: tcgint;
+      begin
+        { if we load a value into a 32 bit register, it is automatically
+          zero-extended to 64 bit }
+        if (high(a)=0) and
+           (size in [OS_64,OS_S64]) then
+          begin
+            size:=OS_32;
+            reg:=makeregsize(reg,size);
+          end;
+        { values <= 32 bit are stored in a 32 bit register }
+        if not(size in [OS_64,OS_S64]) then
+          a:=cardinal(a);
+
+        if size in [OS_64,OS_S64] then
+          begin
+            mask:=-1;
+            maxshift:=64;
+          end
+        else
+          begin
+            mask:=$ffffffff;
+            maxshift:=32;
+          end;
+        { single movn enough? (to be extended) }
+        shift:=16;
+        preva:=a;
+        repeat
+          if (a shr shift)=(mask shr shift) then
+            begin
+              if shift=16 then
+                list.concat(taicpu.op_reg_const(A_MOVN,reg,not(word(preva))))
+              else
+                begin
+                  shifterop_reset(so);
+                  so.shiftmode:=SM_LSL;
+                  so.shiftimm:=shift-16;
+                  list.concat(taicpu.op_reg_const_shifterop(A_MOVN,reg,not(word(preva)),so));
+                end;
+              exit;
+            end;
+          { only try the next 16 bits if the current one is all 1 bits, since
+            the movn will set all lower bits to 1 }
+          if word(a shr (shift-16))<>$ffff then
+            break;
+          inc(shift,16);
+        until shift=maxshift;
+        reginited:=false;
+        shift:=0;
+        { can be optimized later to use more movn }
+        repeat
+          { leftover is shifterconst? (don't check if we can represent it just
+            as effectively with movz/movk, as this check is expensive) }
+          if ((shift<tcgsize2size[size]*(8 div 2)) and
+              (word(a)<>0) and
+              ((a shr 16)<>0)) and
+             is_shifter_const(a shl shift,size) then
+            begin
+              if reginited then
+                list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,a shl shift))
+              else
+                list.concat(taicpu.op_reg_reg_const(A_ORR,reg,makeregsize(NR_XZR,size),a shl shift));
+              exit;
+            end;
+          { set all 16 bit parts <> 0 }
+          if (word(a)<>0) or
+             ((shift=0) and
+              (a=0)) then
+            if shift=0 then
+              begin
+                list.concat(taicpu.op_reg_const(A_MOVZ,reg,word(a)));
+                reginited:=true;
+              end
+            else
+              begin
+                shifterop_reset(so);
+                so.shiftmode:=SM_LSL;
+                so.shiftimm:=shift;
+                if not reginited then
+                  begin
+                    opc:=A_MOVZ;
+                    reginited:=true;
+                  end
+                else
+                  opc:=A_MOVK;
+                list.concat(taicpu.op_reg_const_shifterop(opc,reg,word(a),so));
+              end;
+            preva:=a;
+            a:=a shr 16;
+           inc(shift,16);
+        until word(preva)=preva;
+        if not reginited then
+          internalerror(2014102702);
+      end;
+
+
+    procedure tcgaarch64.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
+      var
+        reg: tregister;
+      begin
+        { use the zero register if possible }
+        if a=0 then
+          begin
+            if size in [OS_64,OS_S64] then
+              reg:=NR_XZR
+            else
+              reg:=NR_WZR;
+            a_load_reg_ref(list,size,size,reg,ref);
+          end
+        else
+          inherited;
+      end;
+
+
+    procedure tcgaarch64.a_load_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+      var
+        oppostfix:toppostfix;
+        hreg: tregister;
+      begin
+        if tcgsize2Size[fromsize]>=tcgsize2Size[tosize] then
+          fromsize:=tosize
+        { have a 32 bit register but need a 64 bit one? }
+        else if tosize in [OS_64,OS_S64] then
+          begin
+            { sign extend if necessary }
+            if fromsize in [OS_S8,OS_S16,OS_S32] then
+              begin
+                { can't overwrite reg, may be a constant reg }
+                hreg:=getintregister(list,tosize);
+                a_load_reg_reg(list,fromsize,tosize,reg,hreg);
+                reg:=hreg;
+              end
+            else
+              { top 32 bit are zero by default }
+              reg:=makeregsize(reg,OS_64);
+            fromsize:=tosize;
+          end;
+        if (ref.alignment<>0) and
+           (ref.alignment<tcgsize2size[tosize]) then
+          begin
+            a_load_reg_ref_unaligned(list,fromsize,tosize,reg,ref);
+          end
+        else
+          begin
+            case tosize of
+              { signed integer registers }
+              OS_8,
+              OS_S8:
+                oppostfix:=PF_B;
+              OS_16,
+              OS_S16:
+                oppostfix:=PF_H;
+              OS_32,
+              OS_S32,
+              OS_64,
+              OS_S64:
+                oppostfix:=PF_None;
+              else
+                InternalError(200308299);
+            end;
+            handle_load_store(list,A_STR,tosize,oppostfix,reg,ref);
+          end;
+      end;
+
+
+    procedure tcgaarch64.a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+      var
+        oppostfix:toppostfix;
+      begin
+        if tcgsize2Size[fromsize]>=tcgsize2Size[tosize] then
+          fromsize:=tosize;
+        { ensure that all bits of the 32/64 register are always correctly set:
+           * default behaviour is always to zero-extend to the entire (64 bit)
+             register -> unsigned 8/16/32 bit loads only exist with a 32 bit
+             target register, as the upper 32 bit will be zeroed implicitly
+             -> always make target register 32 bit
+           * signed loads exist both with 32 and 64 bit target registers,
+             depending on whether the value should be sign extended to 32 or
+             to 64 bit (if sign extended to 32 bit, the upper 32 bits of the
+             corresponding 64 bit register are again zeroed) -> no need to
+             change anything (we only have 32 and 64 bit registers), except that
+             when loading an OS_S32 to a 32 bit register, we don't need/can't
+             use sign extension
+        }
+        if fromsize in [OS_8,OS_16,OS_32] then
+          reg:=makeregsize(reg,OS_32);
+        if (ref.alignment<>0) and
+           (ref.alignment<tcgsize2size[fromsize]) then
+          begin
+            a_load_ref_reg_unaligned(list,fromsize,tosize,ref,reg);
+            exit;
+          end;
+        case fromsize of
+          { signed integer registers }
+          OS_8:
+            oppostfix:=PF_B;
+          OS_S8:
+            oppostfix:=PF_SB;
+          OS_16:
+            oppostfix:=PF_H;
+          OS_S16:
+            oppostfix:=PF_SH;
+          OS_S32:
+            if getsubreg(reg)=R_SUBD then
+              oppostfix:=PF_NONE
+            else
+              oppostfix:=PF_SW;
+          OS_32,
+          OS_64,
+          OS_S64:
+            oppostfix:=PF_None;
+          else
+            InternalError(200308297);
+        end;
+        handle_load_store(list,A_LDR,fromsize,oppostfix,reg,ref);
+
+        { clear upper 16 bits if the value was negative }
+        if (fromsize=OS_S8) and (tosize=OS_16) then
+          a_load_reg_reg(list,fromsize,tosize,reg,reg);
+      end;
+
+
+    procedure tcgaarch64.a_load_ref_reg_unaligned(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; register: tregister);
+      var
+        href: treference;
+        hreg1, hreg2, tmpreg: tregister;
+      begin
+        if fromsize in [OS_64,OS_S64] then
+          begin
+            { split into two 32 bit loads }
+            hreg1:=makeregsize(register,OS_32);
+            hreg2:=getintregister(list,OS_32);
+            if target_info.endian=endian_big then
+              begin
+                tmpreg:=hreg1;
+                hreg1:=hreg2;
+                hreg2:=tmpreg;
+              end;
+            { can we use LDP? }
+            if (ref.alignment=4) and
+               (simple_ref_type(A_LDP,OS_32,PF_None,ref)=sr_simple) then
+              list.concat(taicpu.op_reg_reg_ref(A_LDP,hreg1,hreg2,ref))
+            else
+              begin
+                a_load_ref_reg(list,OS_32,OS_32,ref,hreg1);
+                href:=ref;
+                inc(href.offset,4);
+                a_load_ref_reg(list,OS_32,OS_32,href,hreg2);
+              end;
+            list.concat(taicpu.op_reg_reg_const_const(A_BFI,register,makeregsize(hreg2,OS_64),32,32));
+          end
+       else
+         inherited;
+      end;
+
+
+    procedure tcgaarch64.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
+      var
+        instr: taicpu;
+      begin
+        { we use both 32 and 64 bit registers -> insert conversion when when
+          we have to truncate/sign extend inside the (32 or 64 bit) register
+          holding the value, and when we sign extend from a 32 to a 64 bit
+          register }
+        if (tcgsize2size[fromsize]>tcgsize2size[tosize]) or
+           ((tcgsize2size[fromsize]=tcgsize2size[tosize]) and
+            (fromsize<>tosize) and
+            not(fromsize in [OS_32,OS_S32,OS_64,OS_S64])) or
+           ((fromsize in [OS_S8,OS_S16,OS_S32]) and
+            (tosize in [OS_64,OS_S64])) or
+           { needs to mask out the sign in the top 16 bits }
+           ((fromsize=OS_S8) and
+            (tosize=OS_16)) then
+          begin
+            case tosize of
+              OS_8:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_UXT,reg2,makeregsize(reg1,OS_32)),PF_B));
+              OS_16:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_UXT,reg2,makeregsize(reg1,OS_32)),PF_H));
+              OS_S8:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_B));
+              OS_S16:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_H));
+              { while "mov wN, wM" automatically inserts a zero-extension and
+                hence we could encode a 64->32 bit move like that, the problem
+                is that we then can't distinguish 64->32 from 32->32 moves, and
+                the 64->32 truncation could be removed altogether... So use a
+                different instruction }
+              OS_32,
+              OS_S32:
+                { in theory, reg1 should be 64 bit here (since fromsize>tosize),
+                  but because of the way location_force_register() tries to
+                  avoid superfluous zero/sign extensions, it's not always the
+                  case -> also force reg1 to to 64 bit }
+                list.concat(taicpu.op_reg_reg_const_const(A_UBFIZ,makeregsize(reg2,OS_64),makeregsize(reg1,OS_64),0,32));
+              OS_64,
+              OS_S64:
+                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_W));
+              else
+                internalerror(2002090901);
+            end;
+          end
+        else
+          begin
+            { 32 -> 32 bit move implies zero extension (sign extensions have
+              been handled above) -> also use for 32 <-> 64 bit moves }
+            if not(fromsize in [OS_64,OS_S64]) or
+               not(tosize in [OS_64,OS_S64]) then
+              instr:=taicpu.op_reg_reg(A_MOV,makeregsize(reg2,OS_32),makeregsize(reg1,OS_32))
+            else
+              instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+            list.Concat(instr);
+            { Notify the register allocator that we have written a move instruction so
+             it can try to eliminate it. }
+            add_move_instruction(instr);
+          end;
+      end;
+
+
+    procedure tcgaarch64.a_loadaddr_ref_reg(list: TAsmList; const ref: treference; r: tregister);
+      var
+         href: treference;
+         so: tshifterop;
+         op: tasmop;
+      begin
+        op:=A_LDR;
+        href:=ref;
+        { simplify as if we're going to perform a regular 64 bit load, using
+          "r" as the new base register if possible/necessary }
+        make_simple_ref(list,op,OS_ADDR,PF_None,href,r);
+        { load literal? }
+        if assigned(href.symbol) then
+          begin
+            if (href.base<>NR_NO) or
+               (href.index<>NR_NO) or
+               not assigned(href.symboldata) then
+              internalerror(2014110912);
+            list.concat(taicpu.op_reg_sym_ofs(A_ADR,r,href.symbol,href.offset));
+          end
+        else
+          begin
+            if href.index<>NR_NO then
+              begin
+                if href.shiftmode<>SM_None then
+                  begin
+                    { "add" supports a supperset of the shift modes supported by
+                      load/store instructions }
+                    shifterop_reset(so);
+                    so.shiftmode:=href.shiftmode;
+                    so.shiftimm:=href.shiftimm;
+                    list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,r,href.base,href.index,so));
+                  end
+                else
+                  a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,href.index,href.base,r);
+              end
+            else if href.offset<>0 then
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,href.offset,href.base,r)
+            else
+              a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r);
+          end;
+      end;
+
+
+    procedure tcgaarch64.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+      begin
+        internalerror(2014122107)
+      end;
+
+
+    procedure tcgaarch64.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+      begin
+        internalerror(2014122108)
+      end;
+
+
+    procedure tcgaarch64.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+      begin
+        internalerror(2014122109)
+      end;
+
+
+    procedure tcgaarch64.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister; shuffle: pmmshuffle);
+      var
+        instr: taicpu;
+      begin
+        if assigned(shuffle) and
+           not shufflescalar(shuffle) then
+          internalerror(2014122104);
+        if fromsize=tosize then
+          begin
+            instr:=taicpu.op_reg_reg(A_FMOV,reg2,reg1);
+            { Notify the register allocator that we have written a move
+              instruction so it can try to eliminate it. }
+            add_move_instruction(instr);
+          end
+        else
+          begin
+            if (reg_cgsize(reg1)<>fromsize) or
+               (reg_cgsize(reg2)<>tosize) then
+              internalerror(2014110913);
+            instr:=taicpu.op_reg_reg(A_FCVT,reg2,reg1);
+          end;
+        list.Concat(instr);
+      end;
+
+
+    procedure tcgaarch64.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
+       var
+         tmpreg: tregister;
+       begin
+         if assigned(shuffle) and
+            not shufflescalar(shuffle) then
+           internalerror(2014122105);
+         tmpreg:=NR_NO;
+         if (fromsize<>tosize) then
+           begin
+             tmpreg:=reg;
+             reg:=getmmregister(list,fromsize);
+           end;
+         handle_load_store(list,A_LDR,fromsize,PF_None,reg,ref);
+         if (fromsize<>tosize) then
+           a_loadmm_reg_reg(list,fromsize,tosize,reg,tmpreg,nil);
+       end;
+
+
+     procedure tcgaarch64.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
+       var
+         tmpreg: tregister;
+       begin
+         if assigned(shuffle) and
+            not shufflescalar(shuffle) then
+           internalerror(2014122106);
+         if (fromsize<>tosize) then
+           begin
+             tmpreg:=getmmregister(list,tosize);
+             a_loadmm_reg_reg(list,fromsize,tosize,reg,tmpreg,nil);
+             reg:=tmpreg;
+           end;
+         handle_load_store(list,A_STR,tosize,PF_NONE,reg,ref);
+       end;
+
+
+     procedure tcgaarch64.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle);
+       begin
+         if not shufflescalar(shuffle) then
+           internalerror(2014122801);
+         if not(tcgsize2size[fromsize] in [4,8]) or
+            (tcgsize2size[fromsize]<>tcgsize2size[tosize]) then
+           internalerror(2014122803);
+         list.concat(taicpu.op_reg_reg(A_INS,mmreg,intreg));
+       end;
+
+
+     procedure tcgaarch64.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tcgsize; mmreg, intreg: tregister; shuffle: pmmshuffle);
+       begin
+         if not shufflescalar(shuffle) then
+           internalerror(2014122802);
+         if not(tcgsize2size[fromsize] in [4,8]) or
+            (tcgsize2size[fromsize]<>tcgsize2size[tosize]) then
+           internalerror(2014122804);
+         list.concat(taicpu.op_reg_reg(A_UMOV,intreg,mmreg));
+       end;
+
+
+    procedure tcgaarch64.a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle);
+      begin
+        case op of
+          { "xor Vx,Vx" is used to initialize global regvars to 0 }
+          OP_XOR:
+            begin
+              if (src<>dst) or
+                 (reg_cgsize(src)<>size) or
+                 assigned(shuffle) then
+                internalerror(2015011401);
+              case size of
+                OS_F32,
+                OS_F64:
+                  list.concat(taicpu.op_reg_const(A_MOVI,makeregsize(dst,OS_F64),0));
+                else
+                  internalerror(2015011402);
+              end;
+            end
+          else
+            internalerror(2015011403);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
+      var
+        bitsize,
+        signbit: longint;
+      begin
+        if srcsize in [OS_64,OS_S64] then
+          begin
+            bitsize:=64;
+            signbit:=6;
+          end
+        else
+          begin
+            bitsize:=32;
+            signbit:=5;
+          end;
+        { source is 0 -> dst will have to become 255 }
+        list.concat(taicpu.op_reg_const(A_CMP,src,0));
+        if reverse then
+          begin
+            list.Concat(taicpu.op_reg_reg(A_CLZ,makeregsize(dst,srcsize),src));
+            { xor 31/63 is the same as setting the lower 5/6 bits to
+              "31/63-(lower 5/6 bits of dst)" }
+            list.Concat(taicpu.op_reg_reg_const(A_EOR,dst,dst,bitsize-1));
+          end
+        else
+          begin
+            list.Concat(taicpu.op_reg_reg(A_RBIT,makeregsize(dst,srcsize),src));
+            list.Concat(taicpu.op_reg_reg(A_CLZ,dst,dst));
+          end;
+        { set dst to -1 if src was 0 }
+        list.Concat(taicpu.op_reg_reg_reg_cond(A_CSINV,dst,dst,makeregsize(NR_XZR,dstsize),C_NE));
+        { mask the -1 to 255 if src was 0 (anyone find a two-instruction
+          branch-free version? All of mine are 3...) }
+        list.Concat(setoppostfix(taicpu.op_reg_reg(A_UXT,makeregsize(dst,OS_32),makeregsize(dst,OS_32)),PF_B));
+      end;
+
+
+    procedure tcgaarch64.a_load_reg_ref_unaligned(list: TAsmList; fromsize, tosize: tcgsize; register: tregister; const ref: treference);
+      var
+        href: treference;
+        hreg1, hreg2, tmpreg: tregister;
+      begin
+        if fromsize in [OS_64,OS_S64] then
+          begin
+            { split into two 32 bit stores }
+            hreg1:=makeregsize(register,OS_32);
+            hreg2:=getintregister(list,OS_32);
+            a_op_const_reg_reg(list,OP_SHR,OS_64,32,register,makeregsize(hreg2,OS_64));
+            if target_info.endian=endian_big then
+              begin
+                tmpreg:=hreg1;
+                hreg1:=hreg2;
+                hreg2:=tmpreg;
+              end;
+            { can we use STP? }
+            if (ref.alignment=4) and
+               (simple_ref_type(A_STP,OS_32,PF_None,ref)=sr_simple) then
+              list.concat(taicpu.op_reg_reg_ref(A_STP,hreg1,hreg2,ref))
+            else
+              begin
+                a_load_reg_ref(list,OS_32,OS_32,hreg1,ref);
+                href:=ref;
+                inc(href.offset,4);
+                a_load_reg_ref(list,OS_32,OS_32,hreg2,href);
+              end;
+          end
+       else
+         inherited;
+      end;
+
+
+    procedure tcgaarch64.maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
+      const
+        overflowops = [OP_MUL,OP_IMUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+      begin
+        if (op in overflowops) and
+           (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+          a_load_reg_reg(list,OS_32,size,makeregsize(dst,OS_32),makeregsize(dst,OS_32))
+      end;
+
+
+    procedure tcgaarch64.a_op_const_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; reg: tregister);
+      begin
+        optimize_op_const(size,op,a);
+        case op of
+          OP_NONE:
+            exit;
+          OP_MOVE:
+            a_load_const_reg(list,size,a,reg);
+          OP_NEG,OP_NOT:
+            internalerror(200306011);
+          else
+            a_op_const_reg_reg(list,op,size,a,reg,reg);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_op_reg_reg(list:TAsmList;op:topcg;size:tcgsize;src,dst:tregister);
+      begin
+        Case op of
+          OP_NEG,
+          OP_NOT:
+            begin
+              list.concat(taicpu.op_reg_reg(TOpCG2AsmOpReg[op],dst,src));
+              maybeadjustresult(list,op,size,dst);
+            end
+          else
+            a_op_reg_reg_reg(list,op,size,src,dst,dst);
+        end;
+      end;
+
+
+    procedure tcgaarch64.a_op_const_reg_reg(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister);
+      var
+        l: tlocation;
+      begin
+        a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,l);
+      end;
+
+
+    procedure tcgaarch64.a_op_reg_reg_reg(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister);
+      var
+        hreg: tregister;
+      begin
+        { no ROLV opcode... }
+        if op=OP_ROL then
+          begin
+            case size of
+              OS_32,OS_S32,
+              OS_64,OS_S64:
+                begin
+                  hreg:=getintregister(list,size);
+                  a_load_const_reg(list,size,tcgsize2size[size]*8,hreg);
+                  a_op_reg_reg(list,OP_SUB,size,src1,hreg);
+                  a_op_reg_reg_reg(list,OP_ROR,size,hreg,src2,dst);
+                  exit;
+                end;
+              else
+                internalerror(2014111005);
+            end;
+          end
+        else if (op=OP_ROR) and
+           not(size in [OS_32,OS_S32,OS_64,OS_S64]) then
+          internalerror(2014111006);
+        if TOpCG2AsmOpReg[op]=A_NONE then
+          internalerror(2014111007);
+        list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOpReg[op],dst,src2,src1));
+        maybeadjustresult(list,op,size,dst);
+      end;
+
+
+    procedure tcgaarch64.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; a: tcgint; src, dst: tregister; setflags : boolean; var ovloc : tlocation);
+      var
+        shiftcountmask: longint;
+        constreg: tregister;
+      begin
+        { add/sub instructions have only positive immediate operands }
+        if (op in [OP_ADD,OP_SUB]) and
+           (a<0) then
+          begin
+            if op=OP_ADD then
+              op:=op_SUB
+            else
+              op:=OP_ADD;
+            { avoid range/overflow error in case a = low(tcgint) }
+{$push}{$r-}{$q-}
+            a:=-a;
+{$pop}
+          end;
+        ovloc.loc:=LOC_VOID;
+        optimize_op_const(size,op,a);
+        case op of
+          OP_NONE:
+            begin
+              a_load_reg_reg(list,size,size,src,dst);
+              exit;
+            end;
+          OP_MOVE:
+            begin
+              a_load_const_reg(list,size,a,dst);
+              exit;
+            end;
+        end;
+        case op of
+          OP_ADD,
+          OP_SUB:
+            begin
+              handle_reg_imm12_reg(list,TOpCG2AsmOpImm[op],size,src,a,dst,NR_NO,setflags,true);
+              { on a 64 bit target, overflows with smaller data types
+                are handled via range errors }
+              if setflags and
+                 (size in [OS_64,OS_S64]) then
+                begin
+                  location_reset(ovloc,LOC_FLAGS,OS_8);
+                  if size=OS_64 then
+                    if op=OP_ADD then
+                      ovloc.resflags:=F_CS
+                    else
+                      ovloc.resflags:=F_CC
+                  else
+                    ovloc.resflags:=F_VS;
+                end;
+            end;
+          OP_OR,
+          OP_AND,
+          OP_XOR:
+            begin
+              if not(size in [OS_64,OS_S64]) then
+                a:=cardinal(a);
+              if is_shifter_const(a,size) then
+                list.concat(taicpu.op_reg_reg_const(TOpCG2AsmOpReg[op],dst,src,a))
+              else
+                begin
+                  constreg:=getintregister(list,size);
+                  a_load_const_reg(list,size,a,constreg);
+                  a_op_reg_reg_reg(list,op,size,constreg,src,dst);
+                end;
+            end;
+          OP_SHL,
+          OP_SHR,
+          OP_SAR:
+            begin
+              if size in [OS_64,OS_S64] then
+                shiftcountmask:=63
+              else
+                shiftcountmask:=31;
+              if (a and shiftcountmask)<>0 Then
+                list.concat(taicpu.op_reg_reg_const(
+                  TOpCG2AsmOpImm[Op],dst,src,a and shiftcountmask))
+              else
+                a_load_reg_reg(list,size,size,src,dst);
+              if (a and not(tcgint(shiftcountmask)))<>0 then
+                internalError(2014112101);
+            end;
+          OP_ROL,
+          OP_ROR:
+            begin
+              case size of
+                OS_32,OS_S32:
+                  if (a and not(tcgint(31)))<>0 then
+                    internalError(2014112102);
+                OS_64,OS_S64:
+                  if (a and not(tcgint(63)))<>0 then
+                    internalError(2014112103);
+                else
+                  internalError(2014112104);
+              end;
+              { there's only a ror opcode }
+              if op=OP_ROL then
+                a:=(tcgsize2size[size]*8)-a;
+              list.concat(taicpu.op_reg_reg_const(A_ROR,dst,src,a));
+            end;
+          OP_MUL,
+          OP_IMUL,
+          OP_DIV,
+          OP_IDIV:
+            begin
+              constreg:=getintregister(list,size);
+              a_load_const_reg(list,size,a,constreg);
+              a_op_reg_reg_reg_checkoverflow(list,op,size,constreg,src,dst,setflags,ovloc);
+            end;
+          else
+            internalerror(2014111403);
+        end;
+        maybeadjustresult(list,op,size,dst);
+      end;
+
+
+    procedure tcgaarch64.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister; setflags : boolean; var ovloc : tlocation);
+      var
+        tmpreg1: tregister;
+      begin
+        ovloc.loc:=LOC_VOID;
+        { overflow can only occur with 64 bit calculations on 64 bit cpus }
+        if setflags and
+           (size in [OS_64,OS_S64]) then
+          begin
+            case op of
+              OP_ADD,
+              OP_SUB:
+                begin
+                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(TOpCG2AsmOpReg[op],dst,src2,src1),PF_S));
+                  ovloc.loc:=LOC_FLAGS;
+                  if size=OS_64 then
+                    if op=OP_ADD then
+                      ovloc.resflags:=F_CS
+                    else
+                      ovloc.resflags:=F_CC
+                  else
+                    ovloc.resflags:=F_VS;
+                  { finished; since we won't call through to a_op_reg_reg_reg,
+                    adjust the result here if necessary }
+                  maybeadjustresult(list,op,size,dst);
+                  exit;
+                end;
+              OP_MUL:
+                begin
+                  { check whether the upper 64 bit of the 128 bit product is 0 }
+                  tmpreg1:=getintregister(list,OS_64);
+                  list.concat(taicpu.op_reg_reg_reg(A_UMULH,tmpreg1,src2,src1));
+                  list.concat(taicpu.op_reg_const(A_CMP,tmpreg1,0));
+                  ovloc.loc:=LOC_FLAGS;
+                  ovloc.resflags:=F_NE;
+                  { still have to perform the actual multiplication  }
+                end;
+              OP_IMUL:
+                begin
+                  { check whether the sign bit of the (128 bit) result is the
+                    same as "sign bit of src1" xor "signbit of src2" (if so, no
+                    overflow and the xor-product of all sign bits is 0) }
+                  tmpreg1:=getintregister(list,OS_64);
+                  list.concat(taicpu.op_reg_reg_reg(A_SMULH,tmpreg1,src2,src1));
+                  list.concat(taicpu.op_reg_reg_reg(A_EOR,tmpreg1,tmpreg1,src1));
+                  list.concat(taicpu.op_reg_reg_reg(A_EOR,tmpreg1,tmpreg1,src2));
+                  list.concat(taicpu.op_reg_const(A_TST,tmpreg1,$80000000));
+                  ovloc.loc:=LOC_FLAGS;
+                  ovloc.resflags:=F_NE;
+                  { still have to perform the actual multiplication }
+                end;
+              OP_IDIV,
+              OP_DIV:
+                begin
+                  { not handled here, needs div-by-zero check (dividing by zero
+                    just gives a 0 result on aarch64), and low(int64) div -1
+                    check for overflow) }
+                  internalerror(2014122101);
+                end;
+            end;
+          end;
+        a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+      end;
+
+
+
+  {*************** compare instructructions ****************}
+
+    procedure tcgaarch64.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
+      var
+        op: tasmop;
+      begin
+        if a>=0 then
+          op:=A_CMP
+        else
+          op:=A_CMN;
+        { avoid range/overflow error in case a=low(tcgint) }
+{$push}{$r-}{$q-}
+        handle_reg_imm12_reg(list,op,size,reg,abs(a),NR_XZR,NR_NO,false,false);
+{$pop}
+        a_jmp_cond(list,cmp_op,l);
+      end;
+
+
+    procedure tcgaarch64.a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1,reg2: tregister; l: tasmlabel);
+      begin
+        list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
+        a_jmp_cond(list,cmp_op,l);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_always(list: TAsmList; l: TAsmLabel);
+      var
+        ai: taicpu;
+      begin
+        ai:=TAiCpu.op_sym(A_B,current_asmdata.RefAsmSymbol(l.name));
+        ai.is_jmp:=true;
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_name(list: TAsmList; const s: string);
+      var
+        ai: taicpu;
+      begin
+        ai:=TAiCpu.op_sym(A_B,current_asmdata.RefAsmSymbol(s));
+        ai.is_jmp:=true;
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_cond(list: TAsmList; cond: TOpCmp; l: TAsmLabel);
+      var
+        ai: taicpu;
+      begin
+        ai:=TAiCpu.op_sym(A_B,l);
+        ai.is_jmp:=true;
+        ai.SetCondition(TOpCmp2AsmCond[cond]);
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.a_jmp_flags(list: TAsmList; const f: tresflags; l: tasmlabel);
+      var
+        ai : taicpu;
+      begin
+        ai:=Taicpu.op_sym(A_B,l);
+        ai.is_jmp:=true;
+        ai.SetCondition(flags_to_cond(f));
+        list.Concat(ai);
+      end;
+
+
+    procedure tcgaarch64.g_flags2reg(list: TAsmList; size: tcgsize; const f: tresflags; reg: tregister);
+      begin
+        list.concat(taicpu.op_reg_cond(A_CSET,reg,flags_to_cond(f)));
+      end;
+
+
+    procedure tcgaarch64.g_overflowcheck(list: TAsmList; const loc: tlocation; def: tdef);
+      begin
+        { we need an explicit overflow location, because there are many
+          possibilities (not just the overflow flag, which is only used for
+          signed add/sub) }
+        internalerror(2014112303);
+      end;
+
+
+    procedure tcgaarch64.g_overflowcheck_loc(list: TAsmList; const loc: tlocation; def: tdef; ovloc : tlocation);
+      var
+        hl : tasmlabel;
+        hflags : tresflags;
+      begin
+        if not(cs_check_overflow in current_settings.localswitches) then
+          exit;
+        current_asmdata.getjumplabel(hl);
+        case ovloc.loc of
+          LOC_FLAGS:
+            begin
+              hflags:=ovloc.resflags;
+              inverse_flags(hflags);
+              cg.a_jmp_flags(list,hflags,hl);
+            end;
+          else
+            internalerror(2014112304);
+        end;
+        a_call_name(list,'FPC_OVERFLOW',false);
+        a_label(list,hl);
+      end;
+
+  { *********** entry/exit code and address loading ************ }
+
+    function tcgaarch64.save_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister): longint;
+      var
+        ref: treference;
+        sr: tsuperregister;
+        pairreg: tregister;
+      begin
+        result:=0;
+        reference_reset_base(ref,NR_SP,-16,16);
+        ref.addressmode:=AM_PREINDEXED;
+        pairreg:=NR_NO;
+        { store all used registers pairwise }
+        for sr:=lowsr to highsr do
+          if sr in rg[rt].used_in_proc then
+            if pairreg=NR_NO then
+              pairreg:=newreg(rt,sr,sub)
+            else
+              begin
+                inc(result,16);
+                list.concat(taicpu.op_reg_reg_ref(A_STP,pairreg,newreg(rt,sr,sub),ref));
+                pairreg:=NR_NO
+              end;
+        { one left -> store twice (stack must be 16 bytes aligned) }
+        if pairreg<>NR_NO then
+          begin
+            list.concat(taicpu.op_reg_reg_ref(A_STP,pairreg,pairreg,ref));
+            inc(result,16);
+          end;
+      end;
+
+
+    procedure FixupOffsets(p:TObject;arg:pointer);
+      var
+        sym: tabstractnormalvarsym absolute p;
+      begin
+        if (tsym(p).typ in [paravarsym,localvarsym]) and
+          (sym.localloc.loc=LOC_REFERENCE) and
+          (sym.localloc.reference.base=NR_STACK_POINTER_REG) then
+          begin
+            sym.localloc.reference.base:=NR_FRAME_POINTER_REG;
+            dec(sym.localloc.reference.offset,PLongint(arg)^);
+          end;
+      end;
+
+
+    procedure tcgaarch64.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
+      var
+        ref: treference;
+        totalstackframesize: longint;
+      begin
+        if nostackframe then
+          exit;
+        { stack pointer has to be aligned to 16 bytes at all times }
+        localsize:=align(localsize,16);
+
+        { save stack pointer and return address }
+        reference_reset_base(ref,NR_SP,-16,16);
+        ref.addressmode:=AM_PREINDEXED;
+        list.concat(taicpu.op_reg_reg_ref(A_STP,NR_FP,NR_LR,ref));
+        { initialise frame pointer }
+        a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_SP,NR_FP);
+
+        totalstackframesize:=localsize;
+        { save modified integer registers }
+        inc(totalstackframesize,
+          save_regs(list,R_INTREGISTER,RS_X19,RS_X28,R_SUBWHOLE));
+        { only the lower 64 bits of the modified vector registers need to be
+          saved; if the caller needs the upper 64 bits, it has to save them
+          itself }
+        inc(totalstackframesize,
+          save_regs(list,R_MMREGISTER,RS_D8,RS_D15,R_SUBMMD));
+
+        { allocate stack space }
+        if localsize<>0 then
+          begin
+            localsize:=align(localsize,16);
+            current_procinfo.final_localsize:=localsize;
+            handle_reg_imm12_reg(list,A_SUB,OS_ADDR,NR_SP,localsize,NR_SP,NR_IP0,false,true);
+          end;
+        { By default, we use the frame pointer to access parameters passed via
+          the stack and the stack pointer to address local variables and temps
+          because
+           a) we can use bigger positive than negative offsets (so accessing
+              locals via negative offsets from the frame pointer would be less
+              efficient)
+           b) we don't know the local size while generating the code, so
+              accessing the parameters via the stack pointer is not possible
+              without copying them
+          The problem with this is the get_frame() intrinsic:
+           a) it must return the same value as what we pass as parentfp
+              parameter, since that's how it's used in the TP-style objects unit
+           b) its return value must usable to access all local data from a
+              routine (locals and parameters), since it's all the nested
+              routines have access to
+           c) its return value must be usable to construct a backtrace, as it's
+              also used by the exception handling routines
+
+          The solution we use here, based on something similar that's done in
+          the MIPS port, is to generate all accesses to locals in the routine
+          itself SP-relative, and then after the code is generated and the local
+          size is known (namely, here), we change all SP-relative variables/
+          parameters into FP-relative ones. This means that they'll be accessed
+          less efficiently from nested routines, but those accesses are indirect
+          anyway and at least this way they can be accessed at all
+        }
+        if current_procinfo.has_nestedprocs then
+          begin
+            current_procinfo.procdef.localst.SymList.ForEachCall(@FixupOffsets,@totalstackframesize);
+            current_procinfo.procdef.parast.SymList.ForEachCall(@FixupOffsets,@totalstackframesize);
+          end;
+      end;
+
+
+    procedure tcgaarch64.g_maybe_got_init(list : TAsmList);
+      begin
+        { nothing to do on Darwin or Linux }
+      end;
+
+
+    procedure tcgaarch64.g_restore_registers(list:TAsmList);
+      begin
+        { done in g_proc_exit }
+      end;
+
+
+    procedure tcgaarch64.load_regs(list: TAsmList; rt: tregistertype; lowsr, highsr: tsuperregister; sub: tsubregister);
+      var
+        ref: treference;
+        sr, highestsetsr: tsuperregister;
+        pairreg: tregister;
+        regcount: longint;
+      begin
+        reference_reset_base(ref,NR_SP,16,16);
+        ref.addressmode:=AM_POSTINDEXED;
+        { highest reg stored twice? }
+        regcount:=0;
+        highestsetsr:=RS_NO;
+        for sr:=lowsr to highsr do
+          if sr in rg[rt].used_in_proc then
+            begin
+              inc(regcount);
+              highestsetsr:=sr;
+            end;
+        if odd(regcount) then
+          begin
+            list.concat(taicpu.op_reg_ref(A_LDR,newreg(rt,highestsetsr,sub),ref));
+            highestsetsr:=pred(highestsetsr);
+          end;
+        { load all (other) used registers pairwise }
+        pairreg:=NR_NO;
+        for sr:=highestsetsr downto lowsr do
+          if sr in rg[rt].used_in_proc then
+            if pairreg=NR_NO then
+              pairreg:=newreg(rt,sr,sub)
+            else
+              begin
+                list.concat(taicpu.op_reg_reg_ref(A_LDP,newreg(rt,sr,sub),pairreg,ref));
+                pairreg:=NR_NO
+              end;
+        { There can't be any register left }
+        if pairreg<>NR_NO then
+          internalerror(2014112602);
+      end;
+
+
+
+    procedure tcgaarch64.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
+      var
+        ref: treference;
+        regsstored: boolean;
+        sr: tsuperregister;
+      begin
+        if not nostackframe then
+          begin
+            { if no registers have been stored, we don't have to subtract the
+              allocated temp space from the stack pointer }
+            regsstored:=false;
+            for sr:=RS_X19 to RS_X28 do
+              if sr in rg[R_INTREGISTER].used_in_proc then
+                begin
+                  regsstored:=true;
+                  break;
+                end;
+            if not regsstored then
+              for sr:=RS_D8 to RS_D15 do
+                if sr in rg[R_MMREGISTER].used_in_proc then
+                  begin
+                    regsstored:=true;
+                    break;
+                  end;
+            { restore registers (and stack pointer) }
+            if regsstored then
+              begin
+                if current_procinfo.final_localsize<>0 then
+                  handle_reg_imm12_reg(list,A_ADD,OS_ADDR,NR_SP,current_procinfo.final_localsize,NR_SP,NR_IP0,false,true);
+                load_regs(list,R_MMREGISTER,RS_D8,RS_D15,R_SUBMMD);
+                load_regs(list,R_INTREGISTER,RS_X19,RS_X28,R_SUBWHOLE);
+              end
+            else if current_procinfo.final_localsize<>0 then
+              { restore stack pointer }
+              a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_FP,NR_SP);
+
+            { restore framepointer and return address }
+            reference_reset_base(ref,NR_SP,16,16);
+            ref.addressmode:=AM_POSTINDEXED;
+            list.concat(taicpu.op_reg_reg_ref(A_LDP,NR_FP,NR_LR,ref));
+          end;
+
+        { return }
+        list.concat(taicpu.op_none(A_RET));
+      end;
+
+
+    procedure tcgaarch64.g_save_registers(list : TAsmList);
+      begin
+        { done in g_proc_entry }
+      end;
+
+
+    { ************* concatcopy ************ }
+
+    procedure tcgaarch64.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+      var
+        paraloc1,paraloc2,paraloc3 : TCGPara;
+        pd : tprocdef;
+      begin
+        pd:=search_system_proc('MOVE');
+        paraloc1.init;
+        paraloc2.init;
+        paraloc3.init;
+        paramanager.getintparaloc(pd,1,paraloc1);
+        paramanager.getintparaloc(pd,2,paraloc2);
+        paramanager.getintparaloc(pd,3,paraloc3);
+        a_load_const_cgpara(list,OS_SINT,len,paraloc3);
+        a_loadaddr_ref_cgpara(list,dest,paraloc2);
+        a_loadaddr_ref_cgpara(list,source,paraloc1);
+        paramanager.freecgpara(list,paraloc3);
+        paramanager.freecgpara(list,paraloc2);
+        paramanager.freecgpara(list,paraloc1);
+        alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        alloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+        a_call_name(list,'FPC_MOVE',false);
+        dealloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+        dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+        paraloc3.done;
+        paraloc2.done;
+        paraloc1.done;
+      end;
+
+
+    procedure tcgaarch64.g_concatcopy(list: TAsmList; const source, dest: treference; len: tcgint);
+
+      var
+        sourcebasereplaced, destbasereplaced: boolean;
+
+      { get optimal memory operation to use for loading/storing data
+        in an unrolled loop }
+      procedure getmemop(scaledop, unscaledop: tasmop; const startref, endref: treference; opsize: tcgsize; postfix: toppostfix; out memop: tasmop; out needsimplify: boolean);
+        begin
+          if (simple_ref_type(scaledop,opsize,postfix,startref)=sr_simple) and
+             (simple_ref_type(scaledop,opsize,postfix,endref)=sr_simple) then
+            begin
+              memop:=unscaledop;
+              needsimplify:=true;
+            end
+          else if (unscaledop<>A_NONE) and
+             (simple_ref_type(unscaledop,opsize,postfix,startref)=sr_simple) and
+             (simple_ref_type(unscaledop,opsize,postfix,endref)=sr_simple) then
+            begin
+              memop:=unscaledop;
+              needsimplify:=false;
+            end
+          else
+            begin
+              memop:=scaledop;
+              needsimplify:=true;
+            end;
+        end;
+
+      { adjust the offset and/or addressing mode after a load/store so it's
+        correct for the next one of the same size }
+      procedure updaterefafterloadstore(var ref: treference; oplen: longint);
+        begin
+          case ref.addressmode of
+            AM_OFFSET:
+              inc(ref.offset,oplen);
+            AM_POSTINDEXED:
+              { base register updated by instruction, next offset can remain
+                the same }
+              ;
+            AM_PREINDEXED:
+              begin
+                { base register updated by instruction -> next instruction can
+                  use post-indexing with offset = sizeof(operation) }
+                ref.offset:=0;
+                ref.addressmode:=AM_OFFSET;
+              end;
+          end;
+        end;
+
+      { generate a load/store and adjust the reference offset to the next
+        memory location if necessary }
+      procedure genloadstore(list: TAsmList; op: tasmop; reg: tregister; var ref: treference; postfix: toppostfix; opsize: tcgsize);
+        begin
+          list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),postfix));
+          updaterefafterloadstore(ref,tcgsize2size[opsize]);
+        end;
+
+      { generate a dual load/store (ldp/stp) and adjust the reference offset to
+        the next memory location if necessary }
+      procedure gendualloadstore(list: TAsmList; op: tasmop; reg1, reg2: tregister; var ref: treference; postfix: toppostfix; opsize: tcgsize);
+        begin
+          list.concat(setoppostfix(taicpu.op_reg_reg_ref(op,reg1,reg2,ref),postfix));
+          updaterefafterloadstore(ref,tcgsize2size[opsize]*2);
+        end;
+
+      { turn a reference into a pre- or post-indexed reference for use in a
+        load/store of a particular size }
+      procedure makesimpleforcopy(list: TAsmList; var scaledop: tasmop; opsize: tcgsize; postfix: toppostfix; forcepostindexing: boolean; var ref: treference; var basereplaced: boolean);
+        var
+          tmpreg: tregister;
+          scaledoffset: longint;
+          orgaddressmode: taddressmode;
+        begin
+          scaledoffset:=tcgsize2size[opsize];
+          if scaledop in [A_LDP,A_STP] then
+            scaledoffset:=scaledoffset*2;
+          { can we use the reference as post-indexed without changes? }
+          if forcepostindexing then
+            begin
+              orgaddressmode:=ref.addressmode;
+              ref.addressmode:=AM_POSTINDEXED;
+              if (orgaddressmode=AM_POSTINDEXED) or
+                 ((ref.offset=0) and
+                  (simple_ref_type(scaledop,opsize,postfix,ref)=sr_simple)) then
+                begin
+                  { just change the post-indexed offset to the access size }
+                  ref.offset:=scaledoffset;
+                  { and replace the base register if that didn't happen yet
+                    (could be sp or a regvar) }
+                  if not basereplaced then
+                    begin
+                      tmpreg:=getaddressregister(list);
+                      a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg);
+                      ref.base:=tmpreg;
+                      basereplaced:=true;
+                    end;
+                  exit;
+                end;
+              ref.addressmode:=orgaddressmode;
+            end;
+{$ifdef dummy}
+          This could in theory be useful in case you have a concatcopy from
+          e.g. x1+255 to x1+267 *and* the reference is aligned, but this seems
+          very unlikely. Disabled because it still needs fixes, as it
+          also generates pre-indexed loads right now at the very end for the
+          left-over gencopies
+
+          { can we turn it into a pre-indexed reference for free? (after the
+            first operation, it will be turned into an offset one) }
+          if not forcepostindexing and
+             (ref.offset<>0) then
+            begin
+              orgaddressmode:=ref.addressmode;
+              ref.addressmode:=AM_PREINDEXED;
+              tmpreg:=ref.base;
+              if not basereplaced and
+                 (ref.base=tmpreg) then
+                begin
+                  tmpreg:=getaddressregister(list);
+                  a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref.base,tmpreg);
+                  ref.base:=tmpreg;
+                  basereplaced:=true;
+                end;
+              if simple_ref_type(scaledop,opsize,postfix,ref)<>sr_simple then
+                make_simple_ref(list,scaledop,opsize,postfix,ref,NR_NO);
+              exit;
+            end;
+{$endif dummy}
+          if not forcepostindexing then
+            begin
+              ref.addressmode:=AM_OFFSET;
+              make_simple_ref(list,scaledop,opsize,postfix,ref,NR_NO);
+              { this may still cause problems if the final offset is no longer
+                a simple ref; it's a bit complicated to pass all information
+                through at all places and check that here, so play safe: we
+                currently never generate unrolled copies for more than 64
+                bytes (32 with non-double-register copies) }
+              if ref.index=NR_NO then
+                begin
+                  if ((scaledop in [A_LDP,A_STP]) and
+                      (ref.offset<((64-8)*tcgsize2size[opsize]))) or
+                     ((scaledop in [A_LDUR,A_STUR]) and
+                      (ref.offset<(255-8*tcgsize2size[opsize]))) or
+                     ((scaledop in [A_LDR,A_STR]) and
+                      (ref.offset<((4096-8)*tcgsize2size[opsize]))) then
+                    exit;
+                end;
+            end;
+          tmpreg:=getaddressregister(list);
+          a_loadaddr_ref_reg(list,ref,tmpreg);
+          basereplaced:=true;
+          if forcepostindexing then
+            begin
+              reference_reset_base(ref,tmpreg,scaledoffset,ref.alignment);
+              ref.addressmode:=AM_POSTINDEXED;
+            end
+          else
+            begin
+              reference_reset_base(ref,tmpreg,0,ref.alignment);
+              ref.addressmode:=AM_OFFSET;
+            end
+        end;
+
+      { prepare a reference for use by gencopy. This is done both after the
+        unrolled and regular copy loop -> get rid of post-indexing mode, make
+        sure ref is valid }
+      procedure preparecopy(list: tasmlist; scaledop, unscaledop: tasmop; var ref: treference; opsize: tcgsize; postfix: toppostfix; out op: tasmop; var basereplaced: boolean);
+        var
+          simplify: boolean;
+        begin
+          if ref.addressmode=AM_POSTINDEXED then
+            ref.offset:=tcgsize2size[opsize];
+          getmemop(scaledop,scaledop,ref,ref,opsize,postfix,op,simplify);
+          if simplify then
+            begin
+              makesimpleforcopy(list,scaledop,opsize,postfix,false,ref,basereplaced);
+              op:=scaledop;
+            end;
+        end;
+
+      { generate a copy from source to dest of size opsize/postfix }
+      procedure gencopy(list: TAsmList; var source, dest: treference; postfix: toppostfix; opsize: tcgsize);
+        var
+          reg: tregister;
+          loadop, storeop: tasmop;
+        begin
+          preparecopy(list,A_LDR,A_LDUR,source,opsize,postfix,loadop,sourcebasereplaced);
+          preparecopy(list,A_STR,A_STUR,dest,opsize,postfix,storeop,destbasereplaced);
+          reg:=getintregister(list,opsize);
+          genloadstore(list,loadop,reg,source,postfix,opsize);
+          genloadstore(list,storeop,reg,dest,postfix,opsize);
+        end;
+
+
+      { copy the leftovers after an unrolled or regular copy loop }
+      procedure gencopyleftovers(list: TAsmList; var source, dest: treference; len: longint);
+        begin
+          { stop post-indexing if we did so in the loop, since in that case all
+            offsets definitely can be represented now }
+          if source.addressmode=AM_POSTINDEXED then
+            begin
+              source.addressmode:=AM_OFFSET;
+              source.offset:=0;
+            end;
+          if dest.addressmode=AM_POSTINDEXED then
+            begin
+              dest.addressmode:=AM_OFFSET;
+              dest.offset:=0;
+            end;
+          { transfer the leftovers }
+          if len>=8 then
+            begin
+              dec(len,8);
+              gencopy(list,source,dest,PF_NONE,OS_64);
+            end;
+          if len>=4 then
+            begin
+              dec(len,4);
+              gencopy(list,source,dest,PF_NONE,OS_32);
+            end;
+          if len>=2 then
+            begin
+              dec(len,2);
+              gencopy(list,source,dest,PF_H,OS_16);
+            end;
+          if len>=1 then
+            begin
+              dec(len);
+              gencopy(list,source,dest,PF_B,OS_8);
+            end;
+        end;
+
+
+      const
+        { load_length + loop dec + cbnz }
+        loopoverhead=12;
+        { loop overhead + load + store }
+        totallooplen=loopoverhead + 8;
+      var
+        totalalign: longint;
+        maxlenunrolled: tcgint;
+        loadop, storeop: tasmop;
+        opsize: tcgsize;
+        postfix: toppostfix;
+        tmpsource, tmpdest: treference;
+        scaledstoreop, unscaledstoreop,
+        scaledloadop, unscaledloadop: tasmop;
+        regs: array[1..8] of tregister;
+        countreg: tregister;
+        i, regcount: longint;
+        hl: tasmlabel;
+        simplifysource, simplifydest: boolean;
+      begin
+        if len=0 then
+          exit;
+        sourcebasereplaced:=false;
+        destbasereplaced:=false;
+        { maximum common alignment }
+        totalalign:=max(1,newalignment(source.alignment,dest.alignment));
+        { use a simple load/store? }
+        if (len in [1,2,4,8]) and
+           ((totalalign>=(len div 2)) or
+            (source.alignment=len) or
+            (dest.alignment=len)) then
+          begin
+            opsize:=int_cgsize(len);
+            a_load_ref_ref(list,opsize,opsize,source,dest);
+            exit;
+          end;
+
+        { alignment > length is not useful, and would break some checks below }
+        while totalalign>len do
+          totalalign:=totalalign div 2;
+
+        { operation sizes to use based on common alignment }
+        case totalalign of
+          1:
+            begin
+              postfix:=PF_B;
+              opsize:=OS_8;
+            end;
+          2:
+            begin
+              postfix:=PF_H;
+              opsize:=OS_16;
+            end;
+          4:
+            begin
+              postfix:=PF_None;
+              opsize:=OS_32;
+            end
+          else
+            begin
+              totalalign:=8;
+              postfix:=PF_None;
+              opsize:=OS_64;
+            end;
+        end;
+        { maximum length to handled with an unrolled loop (4 loads + 4 stores) }
+        maxlenunrolled:=min(totalalign,8)*4;
+        { ldp/stp -> 2 registers per instruction }
+        if (totalalign>=4) and
+           (len>=totalalign*2) then
+          begin
+            maxlenunrolled:=maxlenunrolled*2;
+            scaledstoreop:=A_STP;
+            scaledloadop:=A_LDP;
+            unscaledstoreop:=A_NONE;
+            unscaledloadop:=A_NONE;
+          end
+        else
+          begin
+            scaledstoreop:=A_STR;
+            scaledloadop:=A_LDR;
+            unscaledstoreop:=A_STUR;
+            unscaledloadop:=A_LDUR;
+          end;
+        { we only need 4 instructions extra to call FPC_MOVE }
+        if cs_opt_size in current_settings.optimizerswitches then
+          maxlenunrolled:=maxlenunrolled div 2;
+        if (len>maxlenunrolled) and
+           (len>totalalign*8) then
+          begin
+            g_concatcopy_move(list,source,dest,len);
+            exit;
+          end;
+
+        simplifysource:=true;
+        simplifydest:=true;
+        tmpsource:=source;
+        tmpdest:=dest;
+        { can we directly encode all offsets in an unrolled loop? }
+        if len<=maxlenunrolled then
+          begin
+{$ifdef extdebug}
+            list.concat(tai_comment.Create(strpnew('concatcopy unrolled loop; len/opsize/align: '+tostr(len)+'/'+tostr(tcgsize2size[opsize])+'/'+tostr(totalalign))));
+{$endif extdebug}
+            { the leftovers will be handled separately -> -(len mod opsize) }
+            inc(tmpsource.offset,len-(len mod tcgsize2size[opsize]));
+            { additionally, the last regular load/store will be at
+              offset+len-opsize (if len-(len mod opsize)>len) }
+            if tmpsource.offset>source.offset then
+              dec(tmpsource.offset,tcgsize2size[opsize]);
+            getmemop(scaledloadop,unscaledloadop,source,tmpsource,opsize,postfix,loadop,simplifysource);
+            inc(tmpdest.offset,len-(len mod tcgsize2size[opsize]));
+            if tmpdest.offset>dest.offset then
+              dec(tmpdest.offset,tcgsize2size[opsize]);
+            getmemop(scaledstoreop,unscaledstoreop,dest,tmpdest,opsize,postfix,storeop,simplifydest);
+            tmpsource:=source;
+            tmpdest:=dest;
+            { if we can't directly encode all offsets, simplify }
+            if simplifysource then
+              begin
+                loadop:=scaledloadop;
+                makesimpleforcopy(list,loadop,opsize,postfix,false,tmpsource,sourcebasereplaced);
+              end;
+            if simplifydest then
+              begin
+                storeop:=scaledstoreop;
+                makesimpleforcopy(list,storeop,opsize,postfix,false,tmpdest,destbasereplaced);
+              end;
+            regcount:=len div tcgsize2size[opsize];
+            { in case we transfer two registers at a time, we copy an even
+              number of registers }
+            if loadop=A_LDP then
+              regcount:=regcount and not(1);
+            { initialise for dfa }
+            regs[low(regs)]:=NR_NO;
+            { max 4 loads/stores -> max 8 registers (in case of ldp/stdp) }
+            for i:=1 to regcount do
+              regs[i]:=getintregister(list,opsize);
+            if loadop=A_LDP then
+              begin
+                { load registers }
+                for i:=1 to (regcount div 2) do
+                  gendualloadstore(list,loadop,regs[i*2-1],regs[i*2],tmpsource,postfix,opsize);
+                { store registers }
+                for i:=1 to (regcount div 2) do
+                  gendualloadstore(list,storeop,regs[i*2-1],regs[i*2],tmpdest,postfix,opsize);
+              end
+            else
+              begin
+                for i:=1 to regcount do
+                  genloadstore(list,loadop,regs[i],tmpsource,postfix,opsize);
+                for i:=1 to regcount do
+                  genloadstore(list,storeop,regs[i],tmpdest,postfix,opsize);
+              end;
+            { leftover }
+            len:=len-regcount*tcgsize2size[opsize];
+{$ifdef extdebug}
+            list.concat(tai_comment.Create(strpnew('concatcopy unrolled loop leftover: '+tostr(len))));
+{$endif extdebug}
+          end
+        else
+          begin
+{$ifdef extdebug}
+            list.concat(tai_comment.Create(strpnew('concatcopy regular loop; len/align: '+tostr(len)+'/'+tostr(totalalign))));
+{$endif extdebug}
+            { regular loop -> definitely use post-indexing }
+            loadop:=scaledloadop;
+            makesimpleforcopy(list,loadop,opsize,postfix,true,tmpsource,sourcebasereplaced);
+            storeop:=scaledstoreop;
+            makesimpleforcopy(list,storeop,opsize,postfix,true,tmpdest,destbasereplaced);
+            current_asmdata.getjumplabel(hl);
+            countreg:=getintregister(list,OS_32);
+            if loadop=A_LDP then
+              a_load_const_reg(list,OS_32,len div tcgsize2size[opsize]*2,countreg)
+            else
+              a_load_const_reg(list,OS_32,len div tcgsize2size[opsize],countreg);
+            a_label(list,hl);
+            a_op_const_reg(list,OP_SUB,OS_32,1,countreg);
+            if loadop=A_LDP then
+              begin
+                regs[1]:=getintregister(list,opsize);
+                regs[2]:=getintregister(list,opsize);
+                gendualloadstore(list,loadop,regs[1],regs[2],tmpsource,postfix,opsize);
+                gendualloadstore(list,storeop,regs[1],regs[2],tmpdest,postfix,opsize);
+              end
+            else
+              begin
+                regs[1]:=getintregister(list,opsize);
+                genloadstore(list,loadop,regs[1],tmpsource,postfix,opsize);
+                genloadstore(list,storeop,regs[1],tmpdest,postfix,opsize);
+              end;
+            list.concat(taicpu.op_reg_sym_ofs(A_CBNZ,countreg,hl,0));
+            len:=len mod tcgsize2size[opsize];
+          end;
+        gencopyleftovers(list,tmpsource,tmpdest,len);
+      end;
+
+
+    procedure tcgaarch64.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
+      begin
+        { This method is integrated into g_intf_wrapper and shouldn't be called separately }
+        InternalError(2013020102);
+      end;
+
+
+    procedure tcgaarch64.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+      var
+        make_global: boolean;
+        href: treference;
+        hsym: tsym;
+        paraloc: pcgparalocation;
+        op: tasmop;
+      begin
+        if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+          Internalerror(200006137);
+        if not assigned(procdef.struct) or
+           (procdef.procoptions*[po_classmethod, po_staticmethod,
+             po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+          Internalerror(200006138);
+        if procdef.owner.symtabletype<>ObjectSymtable then
+          Internalerror(200109191);
+
+        make_global:=false;
+        if (not current_module.is_unit) or create_smartlink_library or
+           (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+          make_global:=true;
+
+        if make_global then
+          list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+        else
+          list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+        { set param1 interface to self  }
+        procdef.init_paraloc_info(callerside);
+        hsym:=tsym(procdef.parast.Find('self'));
+        if not(assigned(hsym) and
+          (hsym.typ=paravarsym)) then
+          internalerror(2010103101);
+        paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+        if assigned(paraloc^.next) then
+          InternalError(2013020101);
+
+        case paraloc^.loc of
+          LOC_REGISTER:
+            handle_reg_imm12_reg(list,A_SUB,paraloc^.size,paraloc^.register,ioffset,paraloc^.register,NR_IP0,false,true);
+          else
+            internalerror(2010103102);
+        end;
+
+        if (po_virtualmethod in procdef.procoptions) and
+            not is_objectpascal_helper(procdef.struct) then
+          begin
+            if (procdef.extnumber=$ffff) then
+              Internalerror(200006139);
+            { mov  0(%rdi),%rax ; load vmt}
+            reference_reset_base(href,paraloc^.register,0,sizeof(pint));
+            getcpuregister(list,NR_IP0);
+            a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_IP0);
+            { jmp *vmtoffs(%eax) ; method offs }
+            reference_reset_base(href,NR_IP0,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+            op:=A_LDR;
+            make_simple_ref(list,op,OS_ADDR,PF_None,href,NR_IP0);
+            list.concat(taicpu.op_reg_ref(op,NR_IP0,href));
+            ungetcpuregister(list,NR_IP0);
+            list.concat(taicpu.op_reg(A_BR,NR_IP0));
+          end
+        else
+          a_jmp_name(list,procdef.mangledname);
+        list.concat(Tai_symbol_end.Createname(labelname));
+      end;
+
+
+    procedure create_codegen;
+      begin
+        cg:=tcgaarch64.Create;
+        cg128:=tcg128.Create;
+      end;
+
+end.
index 5d28471c70f7f26b2845cc325e6ca4569dcf8523..7b3afd309feebdc724d611b4c72395d1a66729c2 100644 (file)
@@ -1,7 +1,8 @@
 {
     Copyright (c) 1998-2012 by Florian Klaempfl and Peter Vreman
+    Copyright (c) 2014 by Jonas Maebe and Florian Klaempfl
 
-    Contains the base types for ARM64
+    Contains the base types for Aarch64
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -68,14 +69,22 @@ unit cpubase;
       { Available Superregisters }
       {$i ra64sup.inc}
 
+      RS_IP0 = RS_X16;
+      RS_IP1 = RS_X17;
+
       R_SUBWHOLE = R_SUBQ;
 
       { Available Registers }
       {$i ra64con.inc}
 
+      NR_IP0 = NR_X16;
+      NR_IP1 = NR_X17;
+
       { Integer Super registers first and last }
       first_int_supreg = RS_X0;
-      first_int_imreg = $20;
+      { xzr and sp take up a separate super register because some instructions
+        are ambiguous otherwise }
+      first_int_imreg = $21;
 
       { Integer Super registers first and last }
       first_fpu_supreg = RS_S0;
@@ -92,7 +101,7 @@ unit cpubase;
         The value of this constant is equal to the constant
         PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
       }
-      std_param_align = 4;
+      std_param_align = 8;
 
       { TODO: Calculate bsstart}
       regnumber_count_bsstart = 128;
@@ -109,7 +118,7 @@ unit cpubase;
         {$i ra64dwa.inc}
       );
       { registers which may be destroyed by calls }
-      VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X29..RS_X30];
+      VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X30];
       VOLATILE_MMREGISTERS =  [RS_D0..RS_D7,RS_D16..RS_D31];
 
     type
@@ -126,16 +135,23 @@ unit cpubase;
       TOpPostfix = (PF_None,
         { update condition flags }
         PF_S,
-        { load/store }
-        PF_B,PF_SB,PF_H,PF_SH
+        { load/store sizes }
+        PF_B,PF_SB,PF_H,PF_SH,PF_W,PF_SW
       );
 
       TOpPostfixes = set of TOpPostfix;
 
     const
-      oppostfix2str : array[TOpPostfix] of string[2] = ('',
+      tcgsizep2size: array[OS_NO..OS_F128] of byte =
+        {OS_NO }
+        (0,
+        {OS_8,OS_16,OS_32,OS_64,OS_128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128}
+            0,    1,    2,    3,     4,    0,     1,     2,     3,      4,
+        {OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,}
+             2,      3,     0,     3,      4);
+      oppostfix2str: array[TOpPostfix] of string[2] = ('',
         's',
-        'b','sb','h','sh');
+        'b','sb','h','sh','w','sw');
 
 {*****************************************************************************
                                 Conditions
@@ -150,13 +166,15 @@ unit cpubase;
       TAsmConds = set of TAsmCond;
 
     const
+      C_CS = C_HS;
+      C_CC = C_LO;
       cond2str : array[TAsmCond] of string[2]=('',
         'eq','ne','hs','lo','mi','pl','vs','vc','hi','ls',
         'ge','lt','gt','le','al','nv'
       );
 
       uppercond2str : array[TAsmCond] of string[2]=('',
-        'EQ','NE','hs','LO','MI','PL','VS','VC','HI','LS',
+        'EQ','NE','HS','LO','MI','PL','VS','VC','HI','LS',
         'GE','LT','GT','LE','AL','NV'
       );
 
@@ -168,12 +186,28 @@ unit cpubase;
       TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
         F_GE,F_LT,F_GT,F_LE);
 
+    const
+      F_HS = F_CS;
+      F_LO = F_CC;
+
 {*****************************************************************************
                                 Operands
 *****************************************************************************}
 
+    type
       taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
-      tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR);
+
+      tshiftmode = (SM_None,
+                    { shifted register instructions. LSL can also be used for
+                      the index register of certain loads/stores }
+                    SM_LSL,SM_LSR,SM_ASR,
+                    { extended register instructions: zero/sign extension +
+                        optional shift (interpreted as LSL after extension)
+                       -- the index register of certain loads/stores can be
+                          extended via (s|u)xtw with a shiftval of either 0 or
+                          log2(transfer size of the load/store)
+                    }
+                    SM_UXTB,SM_UXTH,SM_UXTW,SM_UXTX,SM_SXTB,SM_SXTH,SM_SXTW,SM_SXTX);
 
       tupdatereg = (UR_None,UR_Update);
 
@@ -184,12 +218,6 @@ unit cpubase;
         shiftimm : byte;
       end;
 
-      tcpumodeflag = (mfA, mfI, mfF);
-      tcpumodeflags = set of tcpumodeflag;
-
-      tspecialregflag = (srC, srX, srS, srF);
-      tspecialregflags = set of tspecialregflag;
-
 {*****************************************************************************
                                  Constants
 *****************************************************************************}
@@ -201,6 +229,10 @@ unit cpubase;
       maxfpuregs = 32;
       maxaddrregs = 0;
 
+      shiftedregmodes = [SM_LSL,SM_UXTB,SM_UXTH,SM_UXTW,SM_UXTX,SM_SXTB,SM_SXTH,SM_SXTW,SM_SXTX];
+      extendedregmodes = [SM_LSL,SM_LSR,SM_ASR];
+
+
 {*****************************************************************************
                                 Operand Sizes
 *****************************************************************************}
@@ -232,17 +264,23 @@ unit cpubase;
                           Generic Register names
 *****************************************************************************}
 
-      NR_SP = NR_XZR;
-      RS_SP = RS_XZR;
-      NR_WSP = NR_WZR;
-      RS_WSP = RS_WZR;
+
+      NR_FP = NR_X29;
+      RS_FP = RS_X29;
+      NR_WFP = NR_W29;
+      RS_WFP = RS_W29;
+
+      NR_LR = NR_X30;
+      RS_LR = RS_X30;
+      NR_WLR = NR_W30;
+      RS_WLR = RS_W30;
 
       { Stack pointer register }
       NR_STACK_POINTER_REG = NR_SP;
       RS_STACK_POINTER_REG = RS_SP;
-      { Frame pointer register (initialized in tarmprocinfo.init_framepointer) }
-      RS_FRAME_POINTER_REG: tsuperregister = RS_X29;
-      NR_FRAME_POINTER_REG: tregister = NR_X29;
+      { Frame pointer register }
+      NR_FRAME_POINTER_REG = NR_X29;
+      RS_FRAME_POINTER_REG = RS_X29;
       { Register for addressing absolute data in a position independant way,
         such as in PIC code. The exact meaning is ABI specific. For
         further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
@@ -307,6 +345,9 @@ unit cpubase;
 
     function dwarf_reg(r:tregister):shortint;
 
+    function is_shifter_const(d: aint; size: tcgsize): boolean;
+
+
   implementation
 
     uses
@@ -329,13 +370,24 @@ unit cpubase;
     function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
       begin
         case regtype of
+          R_INTREGISTER:
+            begin
+              case s of
+                { there's only Wn and Xn }
+                OS_64,
+                OS_S64:
+                  cgsize2subreg:=R_SUBWHOLE;
+                else
+                  cgsize2subreg:=R_SUBD;
+                end;
+            end;
           R_MMREGISTER:
             begin
               case s of
                 OS_F32:
-                  cgsize2subreg:=R_SUBFS;
+                  cgsize2subreg:=R_SUBMMS;
                 OS_F64:
-                  cgsize2subreg:=R_SUBFD;
+                  cgsize2subreg:=R_SUBMMD;
                 else
                   internalerror(2009112701);
               end;
@@ -349,18 +401,22 @@ unit cpubase;
     function reg_cgsize(const reg: tregister): tcgsize;
       begin
         case getregtype(reg) of
-          R_INTREGISTER :
-            reg_cgsize:=OS_32;
-          R_FPUREGISTER :
-            reg_cgsize:=OS_F80;
+          R_INTREGISTER:
+            case getsubreg(reg) of
+              R_SUBD:
+                result:=OS_32
+              else
+                result:=OS_64;
+            end;
           R_MMREGISTER :
             begin
               case getsubreg(reg) of
-                R_SUBFD,
-                R_SUBWHOLE:
+                R_SUBMMD:
                   result:=OS_F64;
-                R_SUBFS:
+                R_SUBMMS:
                   result:=OS_F32;
+                R_SUBMMWHOLE:
+                  result:=OS_M128;
                 else
                   internalerror(2009112903);
               end;
@@ -373,9 +429,7 @@ unit cpubase;
 
     function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
       begin
-        { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
-          To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
-        is_calljmp:= o in [A_B,A_BLR,A_RET];
+        is_calljmp:=o in [A_B,A_BL,A_BLR,A_RET,A_CBNZ,A_CBZ,A_TBNZ,A_TBZ];
       end;
 
 
@@ -391,8 +445,8 @@ unit cpubase;
 
     function flags_to_cond(const f: TResFlags) : TAsmCond;
       const
-        flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
-          (C_EQ,C_NE,C_HI,C_LO,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+        flag_2_cond: array[TResFlags] of TAsmCond =
+          (C_EQ,C_NE,C_HS,C_LO,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
            C_GE,C_LT,C_GT,C_LE);
       begin
         if f>high(flag_2_cond) then
@@ -434,7 +488,7 @@ unit cpubase;
     function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
       const
         inverse: array[TAsmCond] of TAsmCond=(C_None,
-          C_NE,C_EQ,C_LO,C_HI,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+          C_NE,C_EQ,C_LO,C_HS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
           C_LT,C_GE,C_LE,C_GT,C_None,C_None
         );
       begin
@@ -456,4 +510,112 @@ unit cpubase;
       end;
 
 
+    function is_shifter_const(d: aint; size: tcgsize): boolean;
+      var
+         pattern, checkpattern: qword;
+         patternlen, maxbits, replicatedlen: longint;
+         rightmostone, rightmostzero, checkbit, secondrightmostbit: longint;
+      begin
+        result:=false;
+        { patterns with all bits 0 or 1 cannot be represented this way }
+        if (d=0) then
+          exit;
+        case size of
+          OS_64,
+          OS_S64:
+            begin
+              if d=-1 then
+                exit;
+              maxbits:=64;
+            end
+          else
+            begin
+              if longint(d)=-1 then
+                exit;
+              { we'll generate a 32 bit pattern -> ignore upper sign bits in
+                case of negative longint value }
+              d:=cardinal(d);
+              maxbits:=32;
+            end;
+        end;
+        { "The Logical (immediate) instructions accept a bitmask immediate value
+          that is a 32-bit pattern or a 64-bit pattern viewed as a vector of
+          identical elements of size e = 2, 4, 8, 16, 32 or, 64 bits. Each
+          element contains the same sub-pattern, that is a single run of
+          1 to (e - 1) nonzero bits from bit 0 followed by zero bits, then
+          rotated by 0 to (e - 1) bits." (ARMv8 ARM)
+
+          Rather than generating all possible patterns and checking whether they
+          match our constant, we check whether the lowest 2/4/8/... bits are
+          a valid pattern, and if so whether the constant consists of a
+          replication of this pattern. Such a valid pattern has the form of
+          either (regexp notation)
+            * 1+0+1*
+            * 0+1+0* }
+        patternlen:=2;
+        while patternlen<=maxbits do
+          begin
+            { try lowest <patternlen> bits of d as pattern }
+            if patternlen<>64 then
+              pattern:=qword(d) and ((qword(1) shl patternlen)-1)
+            else
+              pattern:=qword(d);
+            { valid pattern? If it contains too many 1<->0 transitions, larger
+              parts of d cannot be a valid pattern either }
+            rightmostone:=BsfQWord(pattern);
+            rightmostzero:=BsfQWord(not(pattern));
+            { pattern all ones or zeroes -> not a valid pattern (but larger ones
+              can still be valid, since we have too few transitions) }
+            if (rightmostone<patternlen) and
+               (rightmostzero<patternlen) then
+              begin
+                if rightmostone>rightmostzero then
+                  begin
+                    { we have .*1*0* -> check next zero position by shifting
+                      out the existing zeroes (shr rightmostone), inverting and
+                      then again looking for the rightmost one position }
+                    checkpattern:=not(pattern);
+                    checkbit:=rightmostone;
+                  end
+                else
+                  begin
+                    { same as above, but for .*0*1* }
+                    checkpattern:=pattern;
+                    checkbit:=rightmostzero;
+                  end;
+                secondrightmostbit:=BsfQWord(checkpattern shr checkbit)+checkbit;
+                { if this position is >= patternlen -> ok (1 transition),
+                  otherwise we now have 2 transitions and have to check for a
+                  third (if there is one, abort)
+
+                  bsf returns 255 if no 1 bit is found, so in that case it's
+                  also ok
+                  }
+                if secondrightmostbit<patternlen then
+                  begin
+                    secondrightmostbit:=BsfQWord(not(checkpattern) shr secondrightmostbit)+secondrightmostbit;
+                    if secondrightmostbit<patternlen then
+                      exit;
+                  end;
+                { ok, this is a valid pattern, now does d consist of a
+                  repetition of this pattern? }
+                replicatedlen:=patternlen;
+                checkpattern:=pattern;
+                while replicatedlen<maxbits do
+                  begin
+                    { douplicate current pattern }
+                    checkpattern:=checkpattern or (checkpattern shl replicatedlen);
+                    replicatedlen:=replicatedlen*2;
+                  end;
+                if qword(d)=checkpattern then
+                  begin
+                    { yes! }
+                    result:=true;
+                    exit;
+                  end;
+              end;
+            patternlen:=patternlen*2;
+          end;
+      end;
+
 end.
index d253ed77f4b9c03e407f5b6faafacc630f9e529d..a84ece58aaeba11ce455ad8719f6c89ff4f10eda 100644 (file)
@@ -103,12 +103,12 @@ Const
                                  { no need to write info about those }
                                  [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
                                  [cs_opt_regvar,cs_opt_loopunroll,cs_opt_tailrecursion,
-                                 cs_opt_stackframe,cs_opt_nodecse,cs_opt_reorder_fields,cs_opt_fastmath];
+                                 cs_opt_nodecse,cs_opt_reorder_fields,cs_opt_fastmath];
 
    level1optimizerswitches = genericlevel1optimizerswitches;
    level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
      [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
-   level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [cs_opt_scheduler{,cs_opt_loopunroll}];
+   level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
    level4optimizerswitches = genericlevel4optimizerswitches + level3optimizerswitches + [];
 
 Implementation
diff --git a/fpcsrc/compiler/aarch64/cpunode.pas b/fpcsrc/compiler/aarch64/cpunode.pas
new file mode 100644 (file)
index 0000000..2e917fb
--- /dev/null
@@ -0,0 +1,40 @@
+{******************************************************************************
+    Copyright (c) 2014 by Florian Klaempfl
+
+    Includes the aarch64 code generator
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *****************************************************************************}
+unit cpunode;
+
+{$I fpcdefs.inc}
+
+interface
+{ This unit is used to define the specific CPU implementations. All needed
+actions are included in the INITALIZATION part of these units. This explains
+the behaviour of such a unit having just a USES clause! }
+
+implementation
+
+  uses
+    ncgbas,ncgflw,ncgcal,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,ncgobjc,
+    ncpuadd,ncpumat,ncpumem,ncpuinl,ncpucnv,ncpuset,
+    { this not really a node }
+    rgcpu,
+    { symtable }
+    symcpu;
+
+end.
index e8f6d753d7474978b028e000b85d6edd58ffd0cc..ee5659f49b983e9276ad7350081bbf09ac56e31e 100644 (file)
@@ -1,5 +1,5 @@
 {
-    Copyright (c) 2003-2012 by Florian Klaempfl and others
+    Copyright (c) 2013-2014 by Jonas Maebe, Florian Klaempfl and others
 
     AArch64 specific calling conventions
 
@@ -34,19 +34,24 @@ unit cpupara;
 
     type
        taarch64paramanager = class(tparamanager)
-          function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
-          function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
-          function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
-          function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
-          function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
-          procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
-          function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
-          function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
-          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
+          function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
+          function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
+          function get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset; override;
+          function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
+          function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override;
+          function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override;
+          function create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;override;
+          function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
+          function param_use_paraloc(const cgpara: tcgpara): boolean; override;
          private
-          procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
-          function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-            var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
+          curintreg,
+          curmmreg: tsuperregister;
+          curstackoffset: aword;
+
+          procedure init_para_alloc_values;
+          procedure alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
+
+          procedure create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
        end;
 
   implementation
@@ -56,6 +61,13 @@ unit cpupara;
        rgobj,
        defutil,symsym,symtable;
 
+    const
+      RS_FIRST_INT_PARAM_SUPREG = RS_X0;
+      RS_LAST_INT_PARAM_SUPREG = RS_X7;
+      { Q0/D0/S0/H0/B0 all have the same superregister number }
+      RS_FIRST_MM_PARAM_SUPREG = RS_D0;
+      RS_LAST_MM_PARAM_SUPREG = RS_D7;
+
 
     function taarch64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
       begin
@@ -75,47 +87,91 @@ unit cpupara;
       end;
 
 
-    procedure taarch64paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
+    function is_hfa_internal(p: tdef; var basedef: tdef; var elecount: longint): boolean;
       var
-        paraloc : pcgparalocation;
-        def : tdef;
+        i: longint;
+        sym: tsym;
+        tmpelecount: longint;
       begin
-        if nr<1 then
-          internalerror(2002070801);
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
-        cgpara.reset;
-        cgpara.size:=def_cgsize(def);
-        cgpara.intsize:=tcgsize2size[cgpara.size];
-        cgpara.alignment:=std_param_align;
-        cgpara.def:=def;
-        paraloc:=cgpara.add_location;
-        with paraloc^ do
-          begin
-            size:=OS_INT;
-            { the four first parameters are passed into registers }
-            if nr<=8 then
-              begin
-                loc:=LOC_REGISTER;
-                register:=newreg(R_INTREGISTER,RS_X0+nr-1,R_SUBWHOLE);
-              end
-            else
-              begin
-                { the other parameters are passed on the stack }
-                loc:=LOC_REFERENCE;
-                reference.index:=NR_STACK_POINTER_REG;
-                reference.offset:=(nr-9)*8;
-              end;
-          end;
+        result:=false;
+        case p.typ of
+          arraydef:
+            begin
+              if is_special_array(p) then
+                exit;
+              case tarraydef(p).elementdef.typ of
+                floatdef:
+                  begin
+                    { an array of empty records has no influence }
+                    if tarraydef(p).elementdef.size=0 then
+                      begin
+                        result:=true;
+                        exit
+                      end;
+                    tmpelecount:=0;
+                    if not is_hfa_internal(tarraydef(p).elementdef,basedef,tmpelecount) then
+                      exit;
+                    { tmpelecount now contains the number of hfa elements in a
+                      single array element (e.g. 2 if it's an array of a record
+                      containing two singles) -> multiply by number of elements
+                      in the array }
+                    inc(elecount,tarraydef(p).elecount*tmpelecount);
+                    if elecount>4 then
+                      exit;
+                  end;
+                else
+                  result:=is_hfa_internal(tarraydef(p).elementdef,basedef,elecount);
+                end;
+            end;
+          floatdef:
+            begin
+              if not assigned(basedef) then
+                basedef:=p
+              else if basedef<>p then
+                exit;
+              inc(elecount);
+              result:=true;
+            end;
+          recorddef:
+            begin
+              for i:=0 to tabstractrecorddef(p).symtable.symlist.count-1 do
+                begin
+                  sym:=tsym(tabstractrecorddef(p).symtable.symlist[i]);
+                  if sym.typ<>fieldvarsym then
+                    continue;
+                  if not is_hfa_internal(tfieldvarsym(sym).vardef,basedef,elecount) then
+                    exit
+                end;
+              result:=true;
+            end;
+          else
+            exit
+        end;
       end;
 
 
-    function Is_HFA(p : tdef) : boolean;
+    { Returns whether a def is a "homogeneous float array" at the machine level.
+      This means that in the memory layout, the def only consists of maximally
+      4 floating point values that appear consecutively in memory }
+    function is_hfa(p: tdef; out basedef: tdef) : boolean;
+      var
+        elecount: longint;
       begin
         result:=false;
+        basedef:=nil;
+        elecount:=0;
+        result:=is_hfa_internal(p,basedef,elecount);
+        result:=
+          result and
+          (elecount>0) and
+          (elecount<=4) and
+          (p.size=basedef.size*elecount)
       end;
 
 
-    function getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
+    function getparaloc(calloption: tproccalloption; p: tdef): tcgloc;
+      var
+        hfabasedef: tdef;
       begin
          { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
            if push_addr_param for the def is true
@@ -134,7 +190,10 @@ unit cpupara;
             classrefdef:
               getparaloc:=LOC_REGISTER;
             recorddef:
-              getparaloc:=LOC_REGISTER;
+              if not is_hfa(p,hfabasedef) then
+                getparaloc:=LOC_REGISTER
+              else
+                getparaloc:=LOC_MMREGISTER;
             objectdef:
               getparaloc:=LOC_REGISTER;
             stringdef:
@@ -147,12 +206,12 @@ unit cpupara;
             filedef:
               getparaloc:=LOC_REGISTER;
             arraydef:
-              getparaloc:=LOC_REFERENCE;
-            setdef:
-              if is_smallset(p) then
+              if not is_hfa(p,hfabasedef) then
                 getparaloc:=LOC_REGISTER
               else
-                getparaloc:=LOC_REFERENCE;
+                getparaloc:=LOC_MMREGISTER;
+            setdef:
+              getparaloc:=LOC_REGISTER;
             variantdef:
               getparaloc:=LOC_REGISTER;
             { avoid problems with errornous definitions }
@@ -164,7 +223,9 @@ unit cpupara;
       end;
 
 
-    function taarch64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+    function taarch64paramanager.push_addr_param(varspez: tvarspez; def :tdef; calloption: tproccalloption): boolean;
+      var
+        hfabasedef: tdef;
       begin
         result:=false;
         if varspez in [vs_var,vs_out,vs_constref] then
@@ -174,19 +235,36 @@ unit cpupara;
           end;
         case def.typ of
           objectdef:
-            result:=not(Is_HFA(def) and (is_object(def) and ((varspez=vs_const) or (def.size=0));
+            result:=is_object(def);
           recorddef:
-            { note: should this ever be changed, make sure that const records
-                are always passed by reference for calloption=pocall_mwpascal }
-            result:=(varspez=vs_const) or (def.size=0);
+            { ABI: any composite > 16 bytes that not a hfa/hva
+              Special case: MWPascal, which passes all const parameters by
+                reference for compatibility reasons
+            }
+            result:=
+              ((varspez=vs_const) and
+               (calloption=pocall_mwpascal)) or
+              (not is_hfa(def,hfabasedef) and
+               (def.size>16));
           variantdef,
           formaldef:
             result:=true;
+          { arrays are composites and hence treated the same as records by the
+            ABI (watch out for C, where an array is a pointer)
+            Also: all other platforms pass const arrays by reference. Do the
+              same here, because there is too much hacky code out there that
+              relies on this ("array[0..0] of x" passed as const parameter and
+              then indexed beyond its bounds) }
           arraydef:
-            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
-                             is_open_array(def) or
-                             is_array_of_const(def) or
-                             is_array_constructor(def);
+            result:=
+              (calloption in cdecl_pocalls) or
+              is_open_array(def) or
+              is_array_of_const(def) or
+              is_array_constructor(def) or
+              ((tarraydef(def).highrange>=tarraydef(def).lowrange) and
+               ((varspez=vs_const) or
+                (not is_hfa(def,hfabasedef) and
+                 (def.size>16))));
           setdef :
             result:=def.size>16;
           stringdef :
@@ -195,511 +273,370 @@ unit cpupara;
       end;
 
 
-    function taarch64paramanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
-      var
-        i: longint;
-        sym: tsym;
-        fpufield: boolean;
+    function taarch64paramanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
       begin
         if handle_common_ret_in_param(def,pd,result) then
           exit;
-        case def.typ of
-          recorddef:
-            begin
-              result:=def.size>4;
-              if not result and
-                 (target_info.abi in [abi_default,abi_armeb]) then
-                begin
-                  { in case of the old ARM abi (APCS), a struct is returned in
-                    a register only if it is simple. And what is a (non-)simple
-                    struct:
-
-                    "A non-simple type is any non-floating-point type of size
-                     greater than one word (including structures containing only
-                     floating-point fields), and certain single-word structured
-                     types."
-                       (-- ARM APCS documentation)
-
-                    So only floating point types or more than one word ->
-                    definitely non-simple (more than one word is already
-                    checked above). This includes unions/variant records with
-                    overlaid floating point and integer fields.
-
-                    Smaller than one word struct types are simple if they are
-                    "integer-like", and:
-
-                    "A structure is termed integer-like if its size is less than
-                    or equal to one word, and the offset of each of its
-                    addressable subfields is zero."
-                      (-- ARM APCS documentation)
-
-                    An "addressable subfield" is a field of which you can take
-                    the address, which in practive means any non-bitfield.
-                    In Pascal, there is no way to express the difference that
-                    you can have in C between "char" and "int :8". In this
-                    context, we use the fake distinction that a type defined
-                    inside the record itself (such as "a: 0..255;") indicates
-                    a bitpacked field while a field using a different type
-                    (such as "a: byte;") is not.
-                  }
-                  for i:=0 to trecorddef(def).symtable.SymList.count-1 do
-                    begin
-                      sym:=tsym(trecorddef(def).symtable.SymList[i]);
-                      if sym.typ<>fieldvarsym then
-                        continue;
-                      { bitfield -> ignore }
-                      if (trecordsymtable(trecorddef(def).symtable).usefieldalignment=bit_alignment) and
-                         (tfieldvarsym(sym).vardef.typ in [orddef,enumdef]) and
-                         (tfieldvarsym(sym).vardef.owner.defowner=def) then
-                        continue;
-                      { all other fields must be at offset zero }
-                      if tfieldvarsym(sym).fieldoffset<>0 then
-                        begin
-                          result:=true;
-                          exit;
-                        end;
-                      { floating point field -> also by reference }
-                      if tfieldvarsym(sym).vardef.typ=floatdef then
-                        begin
-                          result:=true;
-                          exit;
-                        end;
-                    end;
-                end;
-            end;
-          procvardef:
-            if not tprocvardef(def).is_addressonly then
-              result:=true
-            else
-              result:=false
-          else
-            result:=inherited ret_in_param(def,pd);
-        end;
-      end;
-
-
-    procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
-      begin
-        curintreg:=RS_R0;
-        curfloatreg:=RS_F0;
-        curmmreg:=RS_D0;
-        cur_stack_offset:=0;
-        sparesinglereg := NR_NO;
+        { ABI: if the parameter would be passed in registers, it is returned
+            in those registers; otherwise, it's returned by reference }
+        result:=push_addr_param(vs_value,def,pd.proccalloption);
       end;
 
 
-    function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-        var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
-
+    procedure taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
       var
-        nextintreg,nextfloatreg,nextmmreg : tsuperregister;
-        paradef : tdef;
-        paraloc : pcgparalocation;
-        stack_offset : aword;
-        hp : tparavarsym;
-        loc : tcgloc;
-        paracgsize   : tcgsize;
-        paralen : longint;
-        i : integer;
-        firstparaloc: boolean;
-
-      procedure assignintreg;
-        begin
-          { In case of po_delphi_nested_cc, the parent frame pointer
-            is always passed on the stack. }
-           if (nextintreg<=RS_R3) and
-              (not(vo_is_parentfp in hp.varoptions) or
-               not(po_delphi_nested_cc in p.procoptions)) then
-             begin
-               paraloc^.loc:=LOC_REGISTER;
-               paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
-               inc(nextintreg);
-             end
-           else
-             begin
-               paraloc^.loc:=LOC_REFERENCE;
-               paraloc^.reference.index:=NR_STACK_POINTER_REG;
-               paraloc^.reference.offset:=stack_offset;
-               inc(stack_offset,4);
-            end;
-        end;
-
-
+        hp: tparavarsym;
+        i: longint;
       begin
-        result:=0;
-        nextintreg:=curintreg;
-        nextfloatreg:=curfloatreg;
-        nextmmreg:=curmmreg;
-        stack_offset:=cur_stack_offset;
-
         for i:=0 to paras.count-1 do
           begin
             hp:=tparavarsym(paras[i]);
-            paradef:=hp.vardef;
-
-            hp.paraloc[side].reset;
-
-            { currently only support C-style array of const,
-              there should be no location assigned to the vararg array itself }
-            if (p.proccalloption in cstylearrayofconst) and
-               is_array_of_const(paradef) then
-              begin
-                paraloc:=hp.paraloc[side].add_location;
-                { hack: the paraloc must be valid, but is not actually used }
-                paraloc^.loc:=LOC_REGISTER;
-                paraloc^.register:=NR_R0;
-                paraloc^.size:=OS_ADDR;
-                break;
-              end;
-
-            if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+            { hidden function result parameter is passed in X8 (doesn't have to
+              be valid on return) according to the ABI
+
+              -- don't follow the ABI for managed types, because
+               a) they are passed in registers as parameters, so we should also
+                  return them in a register to be ABI-compliant (which we can't
+                  because the entire compiler is built around the idea that
+                  they are returned by reference, for ref-counting performance
+                  and Delphi-compatibility reasons)
+               b) there are hacks in the system unit that expect that you can
+                  call
+                    function f: com_interface;
+                  as
+                    procedure p(out o: obj);
+                  That can only work in case we do not use x8 to return them
+                  from the function, but the regular first parameter register.
+
+              As the ABI says this behaviour is ok for C++ classes with a
+              non-trivial copy constructor or destructor, it seems reasonable
+              for us to do this for managed types as well.}
+            if (vo_is_funcret in hp.varoptions) and
+               not is_managed_type(hp.vardef) then
               begin
-                paradef:=getpointerdef(paradef);
-                loc:=LOC_REGISTER;
-                paracgsize := OS_ADDR;
-                paralen := tcgsize2size[OS_ADDR];
-              end
-            else
-              begin
-                if not is_special_array(paradef) then
-                  paralen := paradef.size
-                else
-                  paralen := tcgsize2size[def_cgsize(paradef)];
-                loc := getparaloc(p.proccalloption,paradef,isvariadic);
-                if (paradef.typ in [objectdef,arraydef,recorddef]) and
-                  not is_special_array(paradef) and
-                  (hp.varspez in [vs_value,vs_const]) then
-                  paracgsize := int_cgsize(paralen)
-                else
+                hp.paraloc[side].reset;
+                hp.paraloc[side].size:=OS_ADDR;
+                hp.paraloc[side].alignment:=voidpointertype.alignment;
+                hp.paraloc[side].intsize:=voidpointertype.size;
+                hp.paraloc[side].def:=getpointerdef(hp.vardef);
+                with hp.paraloc[side].add_location^ do
                   begin
-                    paracgsize:=def_cgsize(paradef);
-                    { for things like formaldef }
-                    if (paracgsize=OS_NO) then
-                      begin
-                        paracgsize:=OS_ADDR;
-                        paralen:=tcgsize2size[OS_ADDR];
-                        paradef:=voidpointertype;
-                      end;
+                    size:=OS_ADDR;
+                    def:=hp.paraloc[side].def;
+                    loc:=LOC_REGISTER;
+                    register:=NR_X8;
                   end
-              end;
-
-             hp.paraloc[side].size:=paracgsize;
-             hp.paraloc[side].Alignment:=std_param_align;
-             hp.paraloc[side].intsize:=paralen;
-             hp.paraloc[side].def:=paradef;
-             firstparaloc:=true;
-
-{$ifdef EXTDEBUG}
-             if paralen=0 then
-               internalerror(200410311);
-{$endif EXTDEBUG}
-             while paralen>0 do
-               begin
-                 paraloc:=hp.paraloc[side].add_location;
-
-                 if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
-                   case paracgsize of
-                     OS_F32:
-                       paraloc^.size:=OS_32;
-                     OS_F64:
-                       paraloc^.size:=OS_32;
-                     else
-                       internalerror(2005082901);
-                   end
-                 else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
-                   paraloc^.size := OS_32
-                 else
-                   paraloc^.size:=paracgsize;
-                 case loc of
-                    LOC_REGISTER:
-                      begin
-                        { align registers for eabi }
-                        if (target_info.abi in [abi_eabi,abi_eabihf]) and
-                           firstparaloc and
-                           (paradef.alignment=8) then
-                          begin
-                            if (nextintreg in [RS_R1,RS_R3]) then
-                              inc(nextintreg)
-                            else if nextintreg>RS_R3 then
-                              stack_offset:=align(stack_offset,8);
-                          end;
-                        { this is not abi compliant
-                          why? (FK) }
-                        if nextintreg<=RS_R3 then
-                          begin
-                            paraloc^.loc:=LOC_REGISTER;
-                            paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
-                            inc(nextintreg);
-                          end
-                        else
-                          begin
-                            { LOC_REFERENCE always contains everything that's left }
-                            paraloc^.loc:=LOC_REFERENCE;
-                            paraloc^.size:=int_cgsize(paralen);
-                            if (side=callerside) then
-                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
-                            paraloc^.reference.offset:=stack_offset;
-                            inc(stack_offset,align(paralen,4));
-                            paralen:=0;
-                         end;
-                      end;
-                    LOC_FPUREGISTER:
-                      begin
-                        if nextfloatreg<=RS_F3 then
-                          begin
-                            paraloc^.loc:=LOC_FPUREGISTER;
-                            paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
-                            inc(nextfloatreg);
-                          end
-                        else
-                          begin
-                            paraloc^.loc:=LOC_REFERENCE;
-                            paraloc^.reference.index:=NR_STACK_POINTER_REG;
-                            paraloc^.reference.offset:=stack_offset;
-                            case paraloc^.size of
-                              OS_F32:
-                                inc(stack_offset,4);
-                              OS_F64:
-                                inc(stack_offset,8);
-                              OS_F80:
-                                inc(stack_offset,10);
-                              OS_F128:
-                                inc(stack_offset,16);
-                              else
-                                internalerror(200403201);
-                            end;
-                          end;
-                      end;
-                    LOC_MMREGISTER:
-                      begin
-                        if (nextmmreg<=RS_D7) or
-                           ((paraloc^.size = OS_F32) and
-                            (sparesinglereg<>NR_NO)) then
-                          begin
-                            paraloc^.loc:=LOC_MMREGISTER;
-                            case paraloc^.size of
-                              OS_F32:
-                                if sparesinglereg = NR_NO then 
-                                  begin     
-                                    paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
-                                    sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
-                                    inc(nextmmreg);
-                                  end
-                                else
-                                  begin
-                                    paraloc^.register:=sparesinglereg;
-                                    sparesinglereg := NR_NO;
-                                  end;
-                              OS_F64:
-                                begin
-                                  paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
-                                  inc(nextmmreg);
-                                end;
-                              else
-                                internalerror(2012031601);
-                            end;
-                          end
-                        else
-                          begin
-                            { once a floating point parameters has been placed
-                            on the stack we must not pass any more in vfp regs
-                            even if there is a single precision register still
-                            free}
-                            sparesinglereg := NR_NO;
-                            { LOC_REFERENCE always contains everything that's left }
-                            paraloc^.loc:=LOC_REFERENCE;
-                            paraloc^.size:=int_cgsize(paralen);
-                            if (side=callerside) then
-                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
-                            paraloc^.reference.offset:=stack_offset;
-                            inc(stack_offset,align(paralen,4));
-                            paralen:=0;
-                         end;
-                      end;
-                    LOC_REFERENCE:
-                      begin
-                        if push_addr_param(hp.varspez,paradef,p.proccalloption) then
-                          begin
-                            paraloc^.size:=OS_ADDR;
-                            assignintreg
-                          end
-                        else
-                          begin
-                            { align stack for eabi }
-                            if (target_info.abi in [abi_eabi,abi_eabihf]) and
-                               firstparaloc and
-                               (paradef.alignment=8) then
-                              stack_offset:=align(stack_offset,8);
-
-                             paraloc^.size:=paracgsize;
-                             paraloc^.loc:=LOC_REFERENCE;
-                             paraloc^.reference.index:=NR_STACK_POINTER_REG;
-                             paraloc^.reference.offset:=stack_offset;
-                             inc(stack_offset,align(paralen,4));
-                             paralen:=0
-                          end;
-                      end;
-                    else
-                      internalerror(2002071002);
-                 end;
-                 if side=calleeside then
-                   begin
-                     if paraloc^.loc=LOC_REFERENCE then
-                       begin
-                         paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-                         { on non-Darwin, the framepointer contains the value
-                           of the stack pointer on entry. On Darwin, the
-                           framepointer points to the previously saved
-                           framepointer (which is followed only by the saved
-                           return address -> framepointer + 4 = stack pointer
-                           on entry }
-                         if not(target_info.system in systems_darwin) then
-                           inc(paraloc^.reference.offset,4)
-                         else
-                           inc(paraloc^.reference.offset,8);
-                       end;
-                   end;
-                 dec(paralen,tcgsize2size[paraloc^.size]);
-                 firstparaloc:=false
-               end;
+              end
+            else
+              alloc_para(hp.paraloc[side],p,hp.varspez,side,hp.vardef,isvariadic,
+                (vo_is_parentfp in hp.varoptions) and
+                (po_delphi_nested_cc in p.procoptions));
           end;
-        curintreg:=nextintreg;
-        curfloatreg:=nextfloatreg;
-        curmmreg:=nextmmreg;
-        cur_stack_offset:=stack_offset;
-        result:=cur_stack_offset;
       end;
 
 
     function  taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
       var
-        paraloc : pcgparalocation;
-        retcgsize  : tcgsize;
+        retcgsize: tcgsize;
       begin
          if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
            exit;
 
-        paraloc:=result.add_location;
-        { Return in FPU register? }
-        if result.def.typ=floatdef then
+         { in this case, it must be returned in registers as if it were passed
+           as the first parameter }
+         init_para_alloc_values;
+         alloc_para(result,p,vs_value,side,result.def,false,false);
+         { sanity check (LOC_VOID for empty records) }
+         if not assigned(result.location) or
+            not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
+           internalerror(2014113001);
+      end;
+
+    function taarch64paramanager.param_use_paraloc(const cgpara: tcgpara): boolean;
+      begin
+        { we always set up a stack frame -> we can always access the parameters
+          this way }
+        result:=
+          (cgpara.location^.loc=LOC_REFERENCE) and
+          not assigned(cgpara.location^.next);
+      end;
+
+
+    procedure taarch64paramanager.init_para_alloc_values;
+      begin
+        curintreg:=RS_FIRST_INT_PARAM_SUPREG;
+        curmmreg:=RS_FIRST_MM_PARAM_SUPREG;
+        curstackoffset:=0;
+      end;
+
+
+    procedure taarch64paramanager.alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
+      var
+        hfabasedef, locdef: tdef;
+        paraloc: pcgparalocation;
+        paralen, stackslotlen: asizeint;
+        loc: tcgloc;
+        paracgsize, locsize: tcgsize;
+        firstparaloc: boolean;
+      begin
+        result.reset;
+
+        { currently only support C-style array of const,
+          there should be no location assigned to the vararg array itself }
+        if (p.proccalloption in cstylearrayofconst) and
+           is_array_of_const(paradef) then
           begin
-            if target_info.abi = abi_eabihf then 
-              begin
-                paraloc^.loc:=LOC_MMREGISTER;
-                case retcgsize of
-                  OS_64,
-                  OS_F64:
-                    begin
-                      paraloc^.register:=NR_MM_RESULT_REG;
-                    end;
-                  OS_32,
-                  OS_F32:
-                    begin
-                      paraloc^.register:=NR_S0;
-                    end;
-                  else
-                    internalerror(2012032501);
-                end;
-                paraloc^.size:=retcgsize;
-              end
-            else if (p.proccalloption in [pocall_softfloat]) or
-               (cs_fp_emulation in current_settings.moduleswitches) or
-               (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
-              begin
-                case retcgsize of
-                  OS_64,
-                  OS_F64:
-                    begin
-                      paraloc^.loc:=LOC_REGISTER;
-                      if target_info.endian = endian_big then
-                        paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
-                      else
-                        paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
-                      paraloc^.size:=OS_32;
-                      paraloc:=result.add_location;
-                      paraloc^.loc:=LOC_REGISTER;
-                      if target_info.endian = endian_big then
-                        paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
-                      else
-                        paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
-                      paraloc^.size:=OS_32;
-                    end;
-                  OS_32,
-                  OS_F32:
-                    begin
-                      paraloc^.loc:=LOC_REGISTER;
-                      paraloc^.register:=NR_FUNCTION_RETURN_REG;
-                      paraloc^.size:=OS_32;
-                    end;
-                  else
-                    internalerror(2005082603);
-                end;
-              end
-            else
-              begin
-                paraloc^.loc:=LOC_FPUREGISTER;
-                paraloc^.register:=NR_FPU_RESULT_REG;
-                paraloc^.size:=retcgsize;
-              end;
+            paraloc:=result.add_location;
+            { hack: the paraloc must be valid, but is not actually used }
+            paraloc^.loc:=LOC_REGISTER;
+            paraloc^.register:=NR_X0;
+            paraloc^.size:=OS_ADDR;
+            exit;
+          end;
+
+        if push_addr_param(varspez,paradef,p.proccalloption) then
+          begin
+            paradef:=getpointerdef(paradef);
+            loc:=LOC_REGISTER;
+            paracgsize:=OS_ADDR;
+            paralen:=tcgsize2size[OS_ADDR];
           end
-          { Return in register }
         else
           begin
-            if retcgsize in [OS_64,OS_S64] then
-              begin
-                paraloc^.loc:=LOC_REGISTER;
-                if target_info.endian = endian_big then
-                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
-                else
-                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
-                paraloc^.size:=OS_32;
-                paraloc:=result.add_location;
-                paraloc^.loc:=LOC_REGISTER;
-                if target_info.endian = endian_big then
-                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
-                else
-                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
-                paraloc^.size:=OS_32;
-              end
+            if not is_special_array(paradef) then
+              paralen:=paradef.size
+            else
+              paralen:=tcgsize2size[def_cgsize(paradef)];
+            loc:=getparaloc(p.proccalloption,paradef);
+            if (paradef.typ in [objectdef,arraydef,recorddef]) and
+               not is_special_array(paradef) and
+               (varspez in [vs_value,vs_const]) then
+              paracgsize:=int_cgsize(paralen)
             else
               begin
-                paraloc^.loc:=LOC_REGISTER;
-                paraloc^.register:=NR_FUNCTION_RETURN_REG;
-                if (result.intsize<>3) then
-                  paraloc^.size:=retcgsize
-                else
-                  paraloc^.size:=OS_32;
-              end;
+                paracgsize:=def_cgsize(paradef);
+                { for things like formaldef }
+                if paracgsize=OS_NO then
+                  begin
+                    paracgsize:=OS_ADDR;
+                    paralen:=tcgsize2size[OS_ADDR];
+                    paradef:=voidpointertype;
+                  end;
+              end
           end;
+
+          { get hfa basedef if applicable }
+          if not is_hfa(paradef,hfabasedef) then
+            hfabasedef:=nil;
+
+         result.size:=paracgsize;
+         result.alignment:=std_param_align;
+         result.intsize:=paralen;
+         result.def:=paradef;
+
+         { empty record: skipped (explicitly defined by Apple ABI, undefined
+           by general ABI; libffi also skips them in all cases) }
+         if not is_special_array(paradef) and
+            (paradef.size=0) then
+           begin
+             paraloc:=result.add_location;
+             paraloc^.loc:=LOC_VOID;
+             paraloc^.def:=paradef;
+             paraloc^.size:=OS_NO;
+             exit;
+           end;
+
+         { sufficient registers left? }
+         case loc of
+           LOC_REGISTER:
+             begin
+               { In case of po_delphi_nested_cc, the parent frame pointer
+                 is always passed on the stack. }
+               if isdelphinestedcc then
+                 loc:=LOC_REFERENCE
+               else if curintreg+((paralen-1) shr 3)>RS_LAST_INT_PARAM_SUPREG then
+                 begin
+                   { not enough integer registers left -> no more register
+                     parameters, copy all to stack
+                   }
+                   curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
+                   loc:=LOC_REFERENCE;
+                 end;
+             end;
+           LOC_MMREGISTER:
+             begin;
+               { every hfa element must be passed in a separate register }
+               if (assigned(hfabasedef) and
+                   (curmmreg+(paralen div hfabasedef.size)>RS_LAST_MM_PARAM_SUPREG)) or
+                  (curmmreg+((paralen-1) shr 3)>RS_LAST_MM_PARAM_SUPREG) then
+                 begin
+                   { not enough mm registers left -> no more register
+                     parameters, copy all to stack
+                   }
+                   curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
+                   loc:=LOC_REFERENCE;
+                 end;
+             end;
+         end;
+
+         { allocate registers/stack locations }
+         firstparaloc:=true;
+         repeat
+           paraloc:=result.add_location;
+
+           { set paraloc size/def }
+           if assigned(hfabasedef) then
+             begin
+               locsize:=def_cgsize(hfabasedef);
+               locdef:=hfabasedef;
+             end
+           { make sure we don't lose whether or not the type is signed }
+           else if (loc=LOC_REGISTER) and
+                   (paradef.typ<>orddef) then
+             begin
+               locsize:=int_cgsize(paralen);
+               locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
+             end
+           else
+             begin
+               locsize:=paracgsize;
+               locdef:=paradef;
+             end;
+           if locsize in [OS_NO,OS_128,OS_S128] then
+             begin
+               if paralen>4 then
+                 begin
+                   paraloc^.size:=OS_INT;
+                   paraloc^.def:=u64inttype;
+                 end
+               else
+                 begin
+                   { for 3-byte records }
+                   paraloc^.size:=OS_32;
+                   paraloc^.def:=u32inttype;
+                 end;
+             end
+           else
+             begin
+               paraloc^.size:=locsize;
+               paraloc^.def:=locdef;
+             end;
+
+           { paraloc loc }
+           paraloc^.loc:=loc;
+
+           { assign register/stack address }
+           case loc of
+             LOC_REGISTER:
+               begin
+                 paraloc^.register:=newreg(R_INTREGISTER,curintreg,cgsize2subreg(R_INTREGISTER,paraloc^.size));
+                 inc(curintreg);
+                 dec(paralen,tcgsize2size[paraloc^.size]);
+
+                 { "The general ABI specifies that it is the callee's
+                    responsibility to sign or zero-extend arguments having fewer
+                    than 32 bits, and that unused bits in a register are
+                    unspecified. In iOS, however, the caller must perform such
+                    extensions, up to 32 bits." }
+                 if (target_info.abi=abi_aarch64_darwin) and
+                    (side=callerside) and
+                    is_ordinal(paradef) and
+                    (paradef.size<4) then
+                   paraloc^.size:=OS_32;
+
+                 { in case it's a composite, "The argument is passed as though
+                   it had been loaded into the registers from a double-word-
+                   aligned address with an appropriate sequence of LDR
+                   instructions loading consecutive registers from memory" ->
+                   in case of big endian, values in not completely filled
+                   registers must be shifted to the top bits }
+                 if (target_info.endian=endian_big) and
+                    not(paraloc^.size in [OS_64,OS_S64]) and
+                    (paradef.typ in [setdef,recorddef,arraydef,objectdef]) then
+                   paraloc^.shiftval:=-(8-tcgsize2size[paraloc^.size]);
+               end;
+             LOC_MMREGISTER:
+               begin
+                 paraloc^.register:=newreg(R_MMREGISTER,curmmreg,cgsize2subreg(R_MMREGISTER,paraloc^.size));
+                 inc(curmmreg);
+                 dec(paralen,tcgsize2size[paraloc^.size]);
+               end;
+             LOC_REFERENCE:
+               begin
+                  paraloc^.size:=paracgsize;
+                  paraloc^.loc:=LOC_REFERENCE;
+
+                  { the current stack offset may not be properly aligned in
+                    case we're on Darwin have allocated a non-variadic argument
+                    < 8 bytes previously }
+                  if target_info.abi=abi_aarch64_darwin then
+                    curstackoffset:=align(curstackoffset,paraloc^.def.alignment);
+
+                  { on Darwin, non-variadic arguments take up their actual size
+                    on the stack; on other platforms, they take up a multiple of
+                    8 bytes }
+                  if (target_info.abi=abi_aarch64_darwin) and
+                     not isvariadic then
+                    stackslotlen:=paralen
+                  else
+                    stackslotlen:=align(paralen,8);
+
+                  { from the ABI: if arguments occupy partial stack space, they
+                    have to occupy the lowest significant bits of a register
+                    containing that value which is then stored to memory ->
+                    in case of big endian, skip the alignment bytes (if any) }
+                  if target_info.endian=endian_little then
+                    paraloc^.reference.offset:=curstackoffset
+                  else
+                    paraloc^.reference.offset:=curstackoffset+stackslotlen-paralen;
+                  if side=callerside then
+                    paraloc^.reference.index:=NR_STACK_POINTER_REG
+                  else
+                    begin
+                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                      inc(paraloc^.reference.offset,16);
+                    end;
+                  inc(curstackoffset,stackslotlen);
+                  paralen:=0
+               end;
+             else
+               internalerror(2002071002);
+           end;
+         firstparaloc:=false;
+         { <=0 for sign/zero-extended locations }
+         until paralen<=0;
       end;
 
 
-    function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
-      var
-        cur_stack_offset: aword;
-        curintreg, curfloatreg, curmmreg: tsuperregister;
-        sparesinglereg:tregister;
+    function taarch64paramanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;
       begin
-        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+        init_para_alloc_values;
 
-        result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
+        create_paraloc_info_intern(p,side,p.paras,false);
+        result:=curstackoffset;
 
         create_funcretloc_info(p,side);
      end;
 
 
-    function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
-      var
-        cur_stack_offset: aword;
-        curintreg, curfloatreg, curmmreg: tsuperregister;
-        sparesinglereg:tregister;
+    function taarch64paramanager.create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;
       begin
-        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+        init_para_alloc_values;
 
-        result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
-        if (p.proccalloption in cstylearrayofconst) then
-          { just continue loading the parameters in the registers }
-          result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
+        { non-variadic parameters }
+        create_paraloc_info_intern(p,callerside,p.paras,false);
+        if p.proccalloption in cstylearrayofconst then
+          begin
+            { on Darwin, we cannot use any registers for variadic parameters }
+            if target_info.abi=abi_aarch64_darwin then
+              begin
+                curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
+                curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
+              end;
+            { continue loading the parameters  }
+            create_paraloc_info_intern(p,callerside,varargspara,true);
+            result:=curstackoffset;
+          end
         else
           internalerror(200410231);
       end;
diff --git a/fpcsrc/compiler/aarch64/cpupi.pas b/fpcsrc/compiler/aarch64/cpupi.pas
new file mode 100644 (file)
index 0000000..ff6505c
--- /dev/null
@@ -0,0 +1,68 @@
+{
+    Copyright (c) 2002 by Florian Klaempfl
+
+    This unit contains the CPU specific part of tprocinfo
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    procinfo,
+    psub;
+
+  type
+    taarch64procinfo=class(tcgprocinfo)
+      constructor create(aparent: tprocinfo); override;
+      procedure set_first_temp_offset; override;
+    end;
+
+implementation
+
+  uses
+    tgobj,
+    cpubase;
+
+  constructor taarch64procinfo.create(aparent: tprocinfo);
+    begin
+      inherited;
+      { use the stack pointer as framepointer, because
+         1) we exactly know the offsets of the temps from the stack pointer
+            after pass 1 (based on the require parameter stack size for called
+            routines), while we don't know it for the frame pointer (it depends
+            on the number of saved registers)
+         2) temp offsets from the stack pointer are positive while those from
+            the frame pointer are negative, and we can directly encode much
+            bigger positive offsets in the instructions
+      }
+      framepointer:=NR_STACK_POINTER_REG;
+    end;
+
+  procedure taarch64procinfo.set_first_temp_offset;
+    begin
+     { leave room for allocated parameters }
+     tg.setfirsttemp(align(maxpushedparasize,16));
+    end;
+
+
+begin
+  cprocinfo:=taarch64procinfo;
+end.
diff --git a/fpcsrc/compiler/aarch64/cputarg.pas b/fpcsrc/compiler/aarch64/cputarg.pas
new file mode 100644 (file)
index 0000000..584a295
--- /dev/null
@@ -0,0 +1,70 @@
+{
+    Copyright (c) 2001-2002 by Peter Vreman
+
+    Includes the AArch64 dependent target units
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+    uses
+      systems { prevent a syntax error when nothing is included }
+
+{**************************************
+             Targets
+**************************************}
+
+    {$ifndef NOTARGETLINUX}
+      ,t_linux
+    {$endif}
+    {$ifndef NOTARGETBSD}
+      ,t_bsd
+    {$endif}
+
+{**************************************
+             Assemblers
+**************************************}
+
+    {$ifndef NOAGCPUGAS}
+      ,agcpugas
+    {$endif}
+
+{**************************************
+        Assembler Readers
+**************************************}
+
+  {$ifndef NoRaarmgas}
+       ,racpugas
+  {$endif NoRaarmgas}
+
+{**************************************
+             Debuginfo
+**************************************}
+
+  {$ifndef NoDbgDwarf}
+      ,dbgdwarf
+  {$endif NoDbgDwarf}
+      ;
+
+end.
diff --git a/fpcsrc/compiler/aarch64/hlcgcpu.pas b/fpcsrc/compiler/aarch64/hlcgcpu.pas
new file mode 100644 (file)
index 0000000..bdcecce
--- /dev/null
@@ -0,0 +1,156 @@
+{
+    Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
+    Member of the Free Pascal development team
+
+    This unit contains routines to create a pass-through high-level code
+    generator. This is used by most regular code generators.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit hlcgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    symtype,
+    aasmdata,
+    cgbase,cgutils,
+    hlcgobj, hlcg2ll;
+
+  type
+    thlcgaarch64 = class(thlcg2ll)
+      procedure a_load_subsetreg_reg(list: TAsmList; subsetsize, tosize: tdef; const sreg: tsubsetregister; destreg: tregister); override;
+      procedure a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tdef; const fromsreg, tosreg: tsubsetregister); override;
+     protected
+      procedure a_load_regconst_subsetreg_intern(list: TAsmList; fromsize, subsetsize: tdef; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
+    end;
+
+  procedure create_hlcodegen;
+
+implementation
+
+  uses
+    defutil,
+    cpubase,aasmcpu,
+    cgobj,cgcpu;
+
+  procedure thlcgaarch64.a_load_subsetreg_reg(list: TAsmList; subsetsize, tosize: tdef; const sreg: tsubsetregister; destreg: tregister);
+    var
+      op: tasmop;
+      tocgsize: tcgsize;
+      tmpdestreg: tregister;
+    begin
+      tocgsize:=def_cgsize(tosize);
+      if (sreg.startbit<>0) or
+         not(sreg.bitlen in [32,64]) then
+        begin
+          if is_signed(subsetsize) then
+            op:=A_SBFX
+          else
+            op:=A_UBFX;
+          { source and destination register of SBFX/UBFX have to be the same size }
+          if (sreg.subsetregsize in [OS_64,OS_S64]) and
+             not(tocgsize in [OS_64,OS_S64]) then
+            tmpdestreg:=cg.getintregister(list,OS_64)
+          else if not(sreg.subsetregsize in [OS_64,OS_S64]) and
+             (tocgsize in [OS_64,OS_S64]) then
+            tmpdestreg:=cg.getintregister(list,OS_32)
+          else
+            tmpdestreg:=destreg;
+          list.concat(taicpu.op_reg_reg_const_const(op,tmpdestreg,sreg.subsetreg,sreg.startbit,sreg.bitlen));
+          { need to sign extend further or truncate? }
+          if (sreg.subsetregsize=OS_S64) and
+             not(tocgsize in [OS_64,OS_S64]) then
+            cg.a_load_reg_reg(list,OS_S64,tocgsize,tmpdestreg,destreg)
+          else if is_signed(subsetsize) and
+             (tocgsize in [OS_8,OS_16]) then
+            cg.a_load_reg_reg(list,OS_32,tocgsize,tmpdestreg,destreg)
+          else if tmpdestreg<>destreg then
+            cg.a_load_reg_reg(list,def_cgsize(subsetsize),tocgsize,tmpdestreg,destreg)
+        end
+      else
+        cg.a_load_reg_reg(list,def_cgsize(subsetsize),tocgsize,sreg.subsetreg,destreg);
+    end;
+
+
+  procedure makeregssamesize(list: tasmlist; fromsize, tosize: tcgsize; orgfromreg, orgtoreg: tregister; out newfromreg, newtoreg: tregister);
+    begin
+      if (fromsize in [OS_S64,OS_64])<>
+         (tosize in [OS_S64,OS_64]) then
+        begin
+          newfromreg:=cg.makeregsize(list,orgfromreg,OS_64);
+          newtoreg:=cg.makeregsize(list,orgtoreg,OS_64);
+        end
+      else
+        begin
+          newfromreg:=orgfromreg;
+          newtoreg:=orgtoreg;
+        end;
+    end;
+
+
+  procedure thlcgaarch64.a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tdef; const fromsreg, tosreg: tsubsetregister);
+    var
+      fromreg, toreg: tregister;
+
+    begin
+      { BFM can only insert a bitfield that starts at position 0 in the source
+        source or destination register }
+      if (tosreg.startbit=0) and
+         (fromsreg.bitlen>=tosreg.bitlen) then
+        begin
+          makeregssamesize(list,fromsreg.subsetregsize,tosreg.subsetregsize,fromsreg.subsetreg,tosreg.subsetreg,fromreg,toreg);
+          list.concat(taicpu.op_reg_reg_const_const(A_BFXIL,toreg,fromreg,fromsreg.startbit,tosreg.bitlen))
+        end
+      else if (fromsreg.startbit=0) and
+         (fromsreg.bitlen>=tosreg.bitlen) then
+        begin
+          makeregssamesize(list,fromsreg.subsetregsize,tosreg.subsetregsize,fromsreg.subsetreg,tosreg.subsetreg,fromreg,toreg);
+          list.concat(taicpu.op_reg_reg_const_const(A_BFI,toreg,fromreg,tosreg.startbit,tosreg.bitlen))
+        end
+      else
+        inherited;
+    end;
+
+
+  procedure thlcgaarch64.a_load_regconst_subsetreg_intern(list: TAsmList; fromsize, subsetsize: tdef; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt);
+    var
+      toreg: tregister;
+    begin
+      if slopt in [SL_SETZERO,SL_SETMAX] then
+        inherited
+      else if not(sreg.bitlen in [32,64]) then
+        begin
+          makeregssamesize(list,def_cgsize(fromsize),sreg.subsetregsize,fromreg,sreg.subsetreg,fromreg,toreg);
+          list.concat(taicpu.op_reg_reg_const_const(A_BFI,toreg,fromreg,sreg.startbit,sreg.bitlen))
+        end
+      else
+        a_load_reg_reg(list,fromsize,subsetsize,fromreg,sreg.subsetreg);
+    end;
+
+
+  procedure create_hlcodegen;
+    begin
+      hlcg:=thlcgaarch64.create;
+      create_codegen;
+    end;
+
+
+end.
diff --git a/fpcsrc/compiler/aarch64/ncpuadd.pas b/fpcsrc/compiler/aarch64/ncpuadd.pas
new file mode 100644 (file)
index 0000000..16c9abc
--- /dev/null
@@ -0,0 +1,402 @@
+{
+    Copyright (c) 2014 Jonas Maebe
+
+    Code generation for add nodes on AArch64
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       node,ncgadd,cpubase;
+
+    type
+       taarch64addnode = class(tcgaddnode)
+       private
+          function  GetResFlags(unsigned:Boolean):TResFlags;
+          function  GetFPUResFlags:TResFlags;
+       protected
+          procedure second_addfloat;override;
+          procedure second_cmpfloat;override;
+          procedure second_cmpboolean;override;
+          procedure second_cmpsmallset;override;
+          procedure second_cmpordinal;override;
+          procedure second_addordinal;override;
+          procedure second_add64bit; override;
+          procedure second_cmp64bit; override;
+       public
+          function use_generic_mul32to64: boolean; override;
+       end;
+
+  implementation
+
+    uses
+      systems,
+      cutils,verbose,
+      paramgr,procinfo,
+      aasmtai,aasmdata,aasmcpu,defutil,
+      cgbase,cgcpu,cgutils,
+      cpupara,
+      ncon,nset,nadd,
+      hlcgobj, ncgutil,cgobj;
+
+{*****************************************************************************
+                               taarch64addnode
+*****************************************************************************}
+
+    function taarch64addnode.GetResFlags(unsigned:Boolean):TResFlags;
+      begin
+        case NodeType of
+          equaln:
+            GetResFlags:=F_EQ;
+          unequaln:
+            GetResFlags:=F_NE;
+          else
+            if not(unsigned) then
+              begin
+                if nf_swapped in flags then
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_GT;
+                    lten:
+                      GetResFlags:=F_GE;
+                    gtn:
+                      GetResFlags:=F_LT;
+                    gten:
+                      GetResFlags:=F_LE;
+                    else
+                      internalerror(2014082010);
+                  end
+                else
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_LT;
+                    lten:
+                      GetResFlags:=F_LE;
+                    gtn:
+                      GetResFlags:=F_GT;
+                    gten:
+                      GetResFlags:=F_GE;
+                    else
+                      internalerror(2014082011);
+                  end;
+              end
+            else
+              begin
+                if nf_swapped in Flags then
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_HI;
+                    lten:
+                      GetResFlags:=F_HS;
+                    gtn:
+                      GetResFlags:=F_LO;
+                    gten:
+                      GetResFlags:=F_LS;
+                    else
+                      internalerror(2014082012);
+                  end
+                else
+                  case NodeType of
+                    ltn:
+                      GetResFlags:=F_LO;
+                    lten:
+                      GetResFlags:=F_LS;
+                    gtn:
+                      GetResFlags:=F_HI;
+                    gten:
+                      GetResFlags:=F_HS;
+                    else
+                      internalerror(2014082013);
+                  end;
+              end;
+        end;
+      end;
+
+
+    function taarch64addnode.GetFPUResFlags:TResFlags;
+      begin
+        case NodeType of
+          equaln:
+            result:=F_EQ;
+          unequaln:
+            result:=F_NE;
+          else
+            begin
+              if nf_swapped in Flags then
+                case NodeType of
+                  ltn:
+                    result:=F_GT;
+                  lten:
+                    result:=F_GE;
+                  gtn:
+                    result:=F_LO;
+                  gten:
+                    result:=F_LS;
+                  else
+                    internalerror(2014082014);
+                end
+              else
+                case NodeType of
+                  ltn:
+                    result:=F_LO;
+                  lten:
+                    result:=F_LS;
+                  gtn:
+                    result:=F_GT;
+                  gten:
+                    result:=F_GE;
+                  else
+                    internalerror(2014082015);
+                end;
+            end;
+        end;
+      end;
+
+
+    procedure taarch64addnode.second_addfloat;
+      var
+        op : TAsmOp;
+      begin
+        pass_left_right;
+        if nf_swapped in flags then
+          swapleftright;
+
+        { force fpureg as location, left right doesn't matter
+          as both will be in a fpureg }
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+
+        location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+        location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+
+        case nodetype of
+          addn :
+            begin
+              op:=A_FADD;
+            end;
+          muln :
+            begin
+              op:=A_FMUL;
+            end;
+          subn :
+            begin
+              op:=A_FSUB;
+            end;
+          slashn :
+            begin
+              op:=A_FDIV;
+            end;
+          else
+            internalerror(200306014);
+        end;
+
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+           location.register,left.location.register,right.location.register));
+      end;
+
+
+    procedure taarch64addnode.second_cmpfloat;
+      begin
+        pass_left_right;
+        if nf_swapped in flags then
+          swapleftright;
+
+        { force fpureg as location, left right doesn't matter
+          as both will be in a fpureg }
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getfpuresflags;
+
+        { signalling compare so we can get exceptions }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCMPE,
+             left.location.register,right.location.register));
+      end;
+
+
+    procedure taarch64addnode.second_cmpboolean;
+      begin
+        pass_left_right;
+        force_reg_left_right(true,true);
+
+        if right.location.loc=LOC_CONSTANT then
+          begin
+            if right.location.value>=0 then
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMP,left.location.size,left.location.register,right.location.value,NR_XZR,NR_NO,false,false)
+            else
+              { avoid overflow if value=low(int64) }
+{$push}{$r-}{$q-}
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMN,left.location.size,left.location.register,-right.location.value,NR_XZR,NR_NO,false,false)
+{$pop}
+          end
+        else
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(true);
+      end;
+
+
+    procedure taarch64addnode.second_cmpsmallset;
+      var
+        tmpreg : tregister;
+        op: tasmop;
+      begin
+        pass_left_right;
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+
+        force_reg_left_right(true,true);
+
+        if right.location.loc=LOC_CONSTANT then
+          begin
+            { when doing a cmp/cmn on 32 bit, we care whether the *lower 32 bit*
+              is a positive/negative value -> sign extend }
+            if not(right.location.size in [OS_64,OS_S64]) then
+              right.location.value:=longint(right.location.value);
+            if right.location.value>=0 then
+              op:=A_CMP
+            else
+              op:=A_CMN;
+          end
+        else
+          { for DFA }
+          op:=A_NONE;
+
+        case nodetype of
+          equaln,
+          unequaln:
+            begin
+              if right.location.loc=LOC_CONSTANT then
+                tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),left.location.register,abs(right.location.value),NR_XZR,NR_NO,false,false)
+              else
+                current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+              location.resflags:=getresflags(true);
+            end;
+          lten,
+          gten:
+            begin
+              if (not(nf_swapped in flags) and
+                  (nodetype=lten)) or
+                 ((nf_swapped in flags) and
+                  (nodetype=gten)) then
+                swapleftright;
+              { we can't handle left as a constant yet }
+              if left.location.loc=LOC_CONSTANT then
+                hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+              tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
+              if right.location.loc=LOC_CONSTANT then
+                begin
+                  hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,right.location.value,left.location.register,tmpreg);
+                  tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),tmpreg,abs(right.location.value),NR_XZR,NR_NO,false,false)
+                end
+              else
+                begin
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
+                end;
+              location.resflags:=F_EQ;
+            end;
+          else
+            internalerror(2012042701);
+        end;
+      end;
+
+
+    procedure taarch64addnode.second_cmpordinal;
+      var
+        unsigned : boolean;
+      begin
+        pass_left_right;
+        force_reg_left_right(true,true);
+
+        unsigned:=not(is_signed(left.resultdef)) or
+                  not(is_signed(right.resultdef));
+
+        if right.location.loc = LOC_CONSTANT then
+          begin
+            if right.location.value>=0 then
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMP,left.location.size,left.location.register,right.location.value,NR_XZR,NR_NO,false,false)
+            else
+{$push}{$r-}{$q-}
+              Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMN,left.location.size,left.location.register,-right.location.value,NR_XZR,NR_NO,false,false)
+{$pop}
+          end
+        else
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+
+        location_reset(location,LOC_FLAGS,OS_NO);
+        location.resflags:=getresflags(unsigned);
+      end;
+
+
+    procedure taarch64addnode.second_addordinal;
+      const
+        multops: array[boolean] of TAsmOp = (A_SMULL,A_UMULL);
+      var
+        unsigned: boolean;
+      begin
+        { 32x32->64 multiplication }
+        if (nodetype=muln) and
+           is_32bit(left.resultdef) and
+           is_32bit(right.resultdef) and
+           is_64bit(resultdef) then
+          begin
+            unsigned:=not(is_signed(left.resultdef)) or
+                      not(is_signed(right.resultdef));
+            pass_left_right;
+            force_reg_left_right(true,true);
+            { force_reg_left_right can leave right as a LOC_CONSTANT (we can't
+              say "a constant register is okay, but an ordinal constant isn't) }
+            if right.location.loc=LOC_CONSTANT then
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+            location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+            location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(multops[unsigned],location.register,left.location.register,right.location.register));
+          end
+        else
+          inherited second_addordinal;
+      end;
+
+
+    procedure taarch64addnode.second_add64bit;
+      begin
+        second_addordinal;
+      end;
+
+
+    procedure taarch64addnode.second_cmp64bit;
+      begin
+        second_cmpordinal;
+      end;
+
+
+    function taarch64addnode.use_generic_mul32to64: boolean;
+      begin
+        result:=false;
+      end;
+
+
+begin
+  caddnode:=taarch64addnode;
+end.
diff --git a/fpcsrc/compiler/aarch64/ncpucnv.pas b/fpcsrc/compiler/aarch64/ncpucnv.pas
new file mode 100644 (file)
index 0000000..459d47a
--- /dev/null
@@ -0,0 +1,201 @@
+{
+    Copyright (c) 2014 by Jonas Maebe
+
+    Generate AArch64 assembler for type converting nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit ncpucnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ncnv,ncgcnv;
+
+    type
+      taarch64typeconvnode = class(TCgTypeConvNode)
+        protected
+         function typecheck_int_to_real: tnode; override;
+         function first_int_to_real: tnode; override;
+
+        { procedure second_int_to_int;override; }
+        { procedure second_string_to_string;override; }
+        { procedure second_cstring_to_pchar;override; }
+        { procedure second_string_to_chararray;override; }
+        { procedure second_array_to_pointer;override; }
+        { procedure second_pointer_to_array;override; }
+        { procedure second_chararray_to_string;override; }
+        { procedure second_char_to_string;override; }
+         procedure second_int_to_real;override;
+        { procedure second_real_to_real;override; }
+        { procedure second_cord_to_pointer;override; }
+        { procedure second_proc_to_procvar;override; }
+        { procedure second_bool_to_int;override; }
+         procedure second_int_to_bool;override;
+        { procedure second_load_smallset;override;  }
+        { procedure second_ansistring_to_pchar;override; }
+        { procedure second_pchar_to_string;override; }
+        { procedure second_class_to_intf;override; }
+        { procedure second_char_to_char;override; }
+      end;
+
+implementation
+
+  uses
+    verbose,globals,
+    symdef,aasmdata,aasmbase,
+    defutil,
+    cgbase,cgutils,procinfo,
+    cpubase,aasmcpu,
+    pass_2,cgobj,
+    hlcgobj;
+
+
+{*****************************************************************************
+                             FirstTypeConv
+*****************************************************************************}
+
+  function taarch64typeconvnode.typecheck_int_to_real: tnode;
+    begin
+      { aarch64 supports converting everything to floating point, even fixed
+        point! Unfortunately, it only supports fixed point with a power-of-2
+        fraction, which is not the case for currency.
+
+        Generate the division by 10000 via nodes so the 10000.0 constant can
+        be reused. }
+      if is_currency(resultdef) and
+         not(nf_is_currency in flags) then
+        begin
+          { convert the equivalent int64 value to double without conversion
+            (internal typecast -> will set nf_is_currency flag) }
+          result:=ctypeconvnode.create_internal(left,s64floattype);
+          { turn into currency with conversion, which will divide by 10000
+            (regular typecast) }
+          result:=ctypeconvnode.create(result,s64currencytype);
+          exit;
+        end;
+      { The only other thing we have to take care of: convert values < 32 bit
+        to 32 bit }
+      if left.resultdef.size<4 then
+        begin
+          if is_signed(left.resultdef) then
+            inserttypeconv(left,s32inttype)
+          else
+            inserttypeconv(left,u32inttype)
+        end;
+      result:=inherited;
+    end;
+
+
+  function taarch64typeconvnode.first_int_to_real: tnode;
+    begin
+      result:=nil;
+      expectloc:=LOC_MMREGISTER;
+    end;
+
+
+{*****************************************************************************
+                             SecondTypeConv
+*****************************************************************************}
+
+  procedure taarch64typeconvnode.second_int_to_real;
+    var
+      op: tasmop;
+    begin
+      location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+      location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+      hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+      if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+        internalerror(2014120401);
+      case left.location.size of
+        OS_32,
+        OS_64:
+          op:=A_UCVTF;
+        OS_S32,
+        OS_S64,
+        { for currency and comp }
+        OS_F64:
+          op:=A_SCVTF;
+        else
+          internalerror(2014120402);
+      end;
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+      { no scaling for currency, that's handled in pass_typecheck }
+    end;
+
+
+  procedure taarch64typeconvnode.second_int_to_bool;
+    var
+      resflags: tresflags;
+      hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+    begin
+      if (nf_explicit in flags) and
+         not(left.expectloc in [LOC_FLAGS,LOC_JUMP]) then
+        begin
+          inherited;
+          exit;
+        end;
+
+      { can't use the generic code, as it assumes that OP_OR automatically sets
+        the flags. We can also do things more efficiently directly }
+
+      oldTrueLabel:=current_procinfo.CurrTrueLabel;
+      oldFalseLabel:=current_procinfo.CurrFalseLabel;
+      current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+      current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+      secondpass(left);
+      if codegenerror then
+       exit;
+
+      case left.location.loc of
+        LOC_CREFERENCE,
+        LOC_REFERENCE,
+        LOC_REGISTER,
+        LOC_CREGISTER,
+        LOC_JUMP:
+          begin
+             hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+             current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,0));
+             resflags:=F_NE;
+          end;
+        LOC_FLAGS :
+          resflags:=left.location.resflags;
+        else
+          internalerror(2014122902);
+      end;
+      { load flags to register }
+      location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+      location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+      if is_cbool(resultdef) then
+        begin
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_cond(A_CSETM,location.register,flags_to_cond(resflags)));
+            { truncate? (in case cbools are ever made unsigned) }
+            if resultdef.size<4 then
+              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,location.size,location.register,location.register);
+        end
+      else
+        cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register);
+      cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
+      current_procinfo.CurrTrueLabel:=oldTrueLabel;
+      current_procinfo.CurrFalseLabel:=oldFalseLabel;
+    end;
+
+
+begin
+   ctypeconvnode:=taarch64typeconvnode;
+end.
diff --git a/fpcsrc/compiler/aarch64/ncpuinl.pas b/fpcsrc/compiler/aarch64/ncpuinl.pas
new file mode 100644 (file)
index 0000000..93f3456
--- /dev/null
@@ -0,0 +1,184 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generates ARM inline nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuinl;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ninl,ncginl;
+
+    type
+      taarch64inlinenode = class(tcgInlineNode)
+        function first_abs_real: tnode; override;
+        function first_sqr_real: tnode; override;
+        function first_sqrt_real: tnode; override;
+        function first_round_real: tnode; override;
+        function first_trunc_real: tnode; override;
+        procedure second_abs_real; override;
+        procedure second_sqr_real; override;
+        procedure second_sqrt_real; override;
+        procedure second_abs_long; override;
+        procedure second_round_real; override;
+        procedure second_trunc_real; override;
+        procedure second_get_frame; override;
+      private
+        procedure load_fpu_location;
+      end;
+
+
+implementation
+
+    uses
+      globtype,verbose,globals,
+      cpuinfo, defutil,symdef,aasmdata,aasmcpu,
+      cgbase,cgutils,pass_1,pass_2,
+      cpubase,ncgutil,cgobj,cgcpu, hlcgobj;
+
+{*****************************************************************************
+                              taarch64inlinenode
+*****************************************************************************}
+
+    procedure taarch64inlinenode.load_fpu_location;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_copy(location,left.location);
+        location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+        location.loc:=LOC_MMREGISTER;
+      end;
+
+
+    function taarch64inlinenode.first_abs_real : tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_sqr_real : tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_sqrt_real : tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_round_real: tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    function taarch64inlinenode.first_trunc_real: tnode;
+      begin
+        expectloc:=LOC_MMREGISTER;
+        result:=nil;
+      end;
+
+
+    procedure taarch64inlinenode.second_abs_real;
+      begin
+        load_fpu_location;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABS,location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_sqr_real;
+      begin
+        load_fpu_location;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FMUL,location.register,left.location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_sqrt_real;
+      begin
+        load_fpu_location;
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT,location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_abs_long;
+      var
+        opsize : tcgsize;
+        hp : taicpu;
+      begin
+        secondpass(left);
+        opsize:=def_cgsize(left.resultdef);
+        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+        location:=left.location;
+        location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+
+        current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_NEG,location.register,left.location.register),PF_S));
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_cond(A_CSEL,location.register,location.register,left.location.register,C_GE));
+      end;
+
+
+    procedure taarch64inlinenode.second_round_real;
+      var
+        hreg: tregister;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+        hreg:=cg.getmmregister(current_asmdata.CurrAsmList,left.location.size);
+        { round as floating point using current rounding mode }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRINTX,hreg,left.location.register));
+        { convert to signed integer rounding towards zero (there's no "round to
+          integer using current rounding mode") }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCVTZS,location.register,hreg));
+      end;
+
+
+    procedure taarch64inlinenode.second_trunc_real;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+        { convert to signed integer rounding towards zero }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCVTZS,location.register,left.location.register));
+      end;
+
+
+    procedure taarch64inlinenode.second_get_frame;
+      begin
+        location_reset(location,LOC_CREGISTER,OS_ADDR);
+        { this routine is used to get the frame pointer for backtracing
+          purposes. current_procinfo.framepointer is set to SP because that one
+          is used to access temps. On most platforms these two frame pointers
+          are the same, but not on AArch64. }
+        location.register:=NR_FRAME_POINTER_REG;
+      end;
+
+begin
+  cinlinenode:=taarch64inlinenode;
+end.
diff --git a/fpcsrc/compiler/aarch64/ncpumat.pas b/fpcsrc/compiler/aarch64/ncpumat.pas
new file mode 100644 (file)
index 0000000..8837490
--- /dev/null
@@ -0,0 +1,196 @@
+{
+    Copyright (c) 1998-2002, 2014 by Florian Klaempfl and Jonas Maebe
+
+    Generate AArch64 assembler for math nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpumat;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,nmat,ncgmat;
+
+    type
+      taarch64moddivnode = class(tmoddivnode)
+         function pass_1: tnode; override;
+         procedure pass_generate_code;override;
+      end;
+
+      taarch64notnode = class(tcgnotnode)
+         procedure second_boolean;override;
+      end;
+
+      taarch64unaryminusnode = class(tcgunaryminusnode)
+         procedure second_float; override;
+      end;
+
+implementation
+
+    uses
+      globtype,systems,constexp,
+      cutils,verbose,globals,
+      symconst,symdef,
+      aasmbase,aasmcpu,aasmtai,aasmdata,
+      defutil,
+      cgbase,cgobj,hlcgobj,pass_2,procinfo,
+      ncon,
+      cpubase,
+      ncgutil,cgcpu,cgutils;
+
+{*****************************************************************************
+                             taarch64moddivnode
+*****************************************************************************}
+
+    function taarch64moddivnode.pass_1: tnode;
+      begin
+        result:=inherited pass_1;
+        if not assigned(result) then
+          include(current_procinfo.flags,pi_do_call);
+      end;
+
+
+    procedure taarch64moddivnode.pass_generate_code;
+      var
+         op         : tasmop;
+         tmpreg,
+         numerator,
+         divider,
+         resultreg  : tregister;
+         hl : tasmlabel;
+         overflowloc: tlocation;
+      begin
+       secondpass(left);
+       secondpass(right);
+
+       { set result location }
+       location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+       location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+       resultreg:=location.register;
+
+       { put numerator in register }
+       hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+       numerator:=left.location.register;
+
+       { load divider in a register }
+       hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+       divider:=right.location.register;
+
+       { start division }
+       if is_signed(left.resultdef) then
+         op:=A_SDIV
+       else
+         op:=A_UDIV;
+       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,numerator,divider));
+
+       { no divide-by-zero detection available in hardware, emulate (if it's a
+         constant, this will have been detected earlier already) }
+       if (right.nodetype<>ordconstn) then
+         begin
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,
+             right.location.register,0));
+
+           current_asmdata.getjumplabel(hl);
+           current_asmdata.CurrAsmList.concat(taicpu.op_cond_sym(A_B,C_NE,hl));
+           cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIVBYZERO',false);
+           cg.a_label(current_asmdata.CurrAsmList,hl);
+         end;
+
+       { in case of overflow checking, also check for low(int64) div (-1)
+         (no hardware support for this either) }
+       if (cs_check_overflow in current_settings.localswitches) and
+          is_signed(left.resultdef) and
+          ((right.nodetype<>ordconstn) or
+           (tordconstnode(right).value=-1)) then
+         begin
+           { num=ffff... and div=8000... <=>
+             num xor not(div xor 8000...) = 0
+             (and we have the "eon" operation, which performs "xor not(...)" }
+           tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
+           hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,left.resultdef,low(int64),left.location.register,tmpreg);
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_EON,
+             tmpreg,left.location.register,tmpreg));
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,tmpreg,0));
+           { now the zero/equal flag is set in case we divided low(int64) by
+             (-1) }
+           location_reset(overflowloc,LOC_FLAGS,OS_NO);
+           overflowloc.resflags:=F_EQ;
+           cg.g_overflowcheck_loc(current_asmdata.CurrAsmList,location,resultdef,overflowloc);
+         end;
+
+       { in case of modulo, multiply result again by the divider and subtract
+         from the numerator }
+       if nodetype=modn then
+         current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MSUB,resultreg,
+           resultreg,divider,numerator));
+    end;
+
+
+{*****************************************************************************
+                               taarch64notnode
+*****************************************************************************}
+
+    procedure taarch64notnode.second_boolean;
+      begin
+        if not handle_locjump then
+          begin
+            secondpass(left);
+            case left.location.loc of
+              LOC_FLAGS :
+                begin
+                  location_copy(location,left.location);
+                  inverse_flags(location.resflags);
+                end;
+              LOC_REGISTER, LOC_CREGISTER,
+              LOC_REFERENCE, LOC_CREFERENCE,
+              LOC_SUBSETREG, LOC_CSUBSETREG,
+              LOC_SUBSETREF, LOC_CSUBSETREF:
+                begin
+                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,
+                    left.location.register,0));
+                  location_reset(location,LOC_FLAGS,OS_NO);
+                  location.resflags:=F_EQ;
+               end;
+              else
+                internalerror(2003042401);
+            end;
+          end;
+      end;
+
+
+{*****************************************************************************
+                                   taarch64unaryminusnode
+*****************************************************************************}
+
+    procedure taarch64unaryminusnode.second_float;
+      begin
+        secondpass(left);
+        hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+        location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+        location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FNEG,location.register,left.location.register));
+      end;
+
+begin
+   cmoddivnode:=taarch64moddivnode;
+   cnotnode:=taarch64notnode;
+   cunaryminusnode:=taarch64unaryminusnode;
+end.
diff --git a/fpcsrc/compiler/aarch64/ncpumem.pas b/fpcsrc/compiler/aarch64/ncpumem.pas
new file mode 100644 (file)
index 0000000..99e6f4c
--- /dev/null
@@ -0,0 +1,142 @@
+{
+    Copyright (c) 2014 by Jonas Maebe
+
+    Generate AArch64 code for in memory related nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpumem;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    globtype,
+    cgbase,
+    symtype,
+    node,nmem,ncgmem;
+
+  type
+    taarch64loadparentfpnode = class(tcgloadparentfpnode)
+      procedure pass_generate_code; override;
+    end;
+
+    taarch64vecnode = class(tcgvecnode)
+     protected
+      function valid_index_size(size: tcgsize): boolean; override;
+     public
+       procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint); override;
+    end;
+
+implementation
+
+  uses
+    cutils,verbose,
+    defutil,
+    aasmdata,cpubase,
+    cgutils,
+    cgobj;
+
+  { taarch64loadparentfpnode }
+
+  procedure taarch64loadparentfpnode.pass_generate_code;
+    begin
+      inherited pass_generate_code;
+      { see the comments in tcgaarch64.g_proc_entry }
+      if (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
+         (location.register=NR_STACK_POINTER_REG) then
+        if (kind=lpf_forpara) then
+          location.register:=NR_FRAME_POINTER_REG
+        else
+          begin
+            { load stack pointer in a different register, as many instructions
+              cannot directly work with the stack pointer. The register
+              allocator can merge them if possible }
+            location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+            cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_STACK_POINTER_REG,location.register);
+            location.loc:=LOC_REGISTER;
+          end;
+    end;
+
+
+  { taarch64vecnode }
+
+  function taarch64vecnode.valid_index_size(size: tcgsize): boolean;
+    begin
+      { all sizes are ok if we handle the "reference reg mul", because
+         a) we use a 64 bit register for 64 bit values, and a 32 bit one (that
+            we can sign/zero-extend inside the reference) for smaller values
+         b) for values < 32 bit, the entire 32 bit register always contains the
+            sign/zero-extended version of the value }
+      result:=
+        not is_packed_array(left.resultdef) and
+        (get_mul_size in [1,2,4,8,16]);
+    end;
+
+
+  procedure taarch64vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
+    var
+      base: tregister;
+      oldoffset: asizeint;
+      shift: byte;
+    begin
+      { we can only scale the index by shl 0..4 }
+      if not(l in [1,2,4,8,16]) then
+        begin
+          inherited;
+          exit;
+        end;
+      { we need a base set and an index available }
+      if (location.reference.base=NR_NO) or
+         (location.reference.index<>NR_NO) then
+        begin
+          { don't integrate the offset yet, make_simple_ref() may be able to
+            handle it more efficiently later (unless an offset is all we have
+            -> optimization for someone that wants to add support for AArch64
+            embedded targets) }
+          oldoffset:=location.reference.offset;
+          location.reference.offset:=0;
+          base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+          cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,base);
+          reference_reset_base(location.reference,base,oldoffset,location.reference.alignment);
+        end;
+      shift:=BsfDWord(l);
+      location.reference.index:=maybe_const_reg;
+      { sign/zero-extend? }
+      if regsize.size=8 then
+        if shift<>0 then
+          location.reference.shiftmode:=SM_LSL
+        else
+          location.reference.shiftmode:=SM_NONE
+      else if is_signed(regsize) then
+        location.reference.shiftmode:=SM_SXTW
+      else if shift<>0 then
+        location.reference.shiftmode:=SM_UXTW
+      else
+        { the upper 32 bits are always already zero-extended -> just use 64 bit
+          register }
+        location.reference.index:=cg.makeregsize(current_asmdata.CurrAsmList,location.reference.index,OS_64);
+      location.reference.shiftimm:=shift;
+      location.reference.alignment:=newalignment(location.reference.alignment,l);
+    end;
+
+
+begin
+  cloadparentfpnode:=taarch64loadparentfpnode;
+  cvecnode:=taarch64vecnode;
+end.
diff --git a/fpcsrc/compiler/aarch64/ncpuset.pas b/fpcsrc/compiler/aarch64/ncpuset.pas
new file mode 100644 (file)
index 0000000..a253afb
--- /dev/null
@@ -0,0 +1,175 @@
+{
+    Copyright (c) 2015 by Jonas Maebe
+
+    Generate AArch64 assembler for in set/case nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuset;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,aasmdata,globtype;
+
+    type
+       taarch64casenode = class(tcgcasenode)
+         protected
+           procedure optimizevalues(var max_linear_list: aint; var max_dist: aword);override;
+           function  has_jumptable: boolean;override;
+           procedure genjumptable(hp: pcaselabel ;min_, max_: aint);override;
+       end;
+
+
+implementation
+
+    uses
+      systems,
+      verbose,globals,constexp,
+      symconst,symdef,defutil,
+      paramgr,
+      cpuinfo,
+      pass_2,cgcpu,
+      ncon,
+      tgobj,ncgutil,regvars,rgobj,aasmcpu,
+      procinfo,
+      cgutils;
+
+{*****************************************************************************
+                            TCGCASENODE
+*****************************************************************************}
+
+
+    procedure taarch64casenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
+      begin
+        max_linear_list:=10;
+      end;
+    
+
+    function taarch64casenode.has_jumptable: boolean;
+      begin
+        has_jumptable:=true;
+      end;
+
+
+    procedure taarch64casenode.genjumptable(hp: pcaselabel; min_, max_: aint);
+      var
+        last: TConstExprInt;
+        tablelabel: TAsmLabel;
+        basereg,indexreg,jumpreg: TRegister;
+        href: TReference;
+        opcgsize: tcgsize;
+        sectype: TAsmSectiontype;
+        jtitemconsttype: taiconst_type;
+
+      procedure genitem(list:TAsmList;t : pcaselabel);
+        var
+          i : aint;
+        begin
+          if assigned(t^.less) then
+            genitem(list,t^.less);
+          { fill possible hole }
+          i:=last.svalue+1;
+          while i<=t^._low.svalue-1 do
+            begin
+              list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,elselabel));
+              inc(i);
+            end;
+          i:=t^._low.svalue;
+          while i<=t^._high.svalue do
+            begin
+              list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,blocklabel(t^.blockid)));
+              inc(i);
+            end;
+          last:=t^._high;
+          if assigned(t^.greater) then
+            genitem(list,t^.greater);
+        end;
+
+      begin
+        if not(target_info.system in systems_darwin) then
+          jtitemconsttype:=aitconst_32bit
+        else
+          { see https://gmplib.org/list-archives/gmp-bugs/2012-December/002836.html }
+          jtitemconsttype:=aitconst_darwin_dwarf_delta32;
+
+        last:=min_;
+        opcgsize:=def_cgsize(opsize);
+        { a <= x <= b <-> unsigned(x-a) <= (b-a) }
+        cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opcgsize,aint(min_),hregister);
+        if not(jumptable_no_range) then
+          begin
+             { case expr greater than max_ => goto elselabel }
+             cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opcgsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
+             min_:=0;
+          end;
+        { local label in order to avoid using GOT }
+        current_asmdata.getlabel(tablelabel,alt_data);
+        indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_ADDR);
+        cg.a_load_reg_reg(current_asmdata.CurrAsmList,opcgsize,OS_ADDR,hregister,indexreg);
+        { load table address }
+        reference_reset_symbol(href,tablelabel,0,4);
+        basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+        cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
+        { load table slot, 32-bit sign extended }
+        reference_reset_base(href,basereg,0,4);
+        href.index:=indexreg;
+        href.shiftmode:=SM_LSL;
+        href.shiftimm:=2;
+        jumpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+        cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,jumpreg);
+        { add table address }
+        cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,basereg,jumpreg);
+        { and finally jump }
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_BR,jumpreg));
+        { generate jump table }
+        if not(target_info.system in systems_darwin) then
+          sectype:=sec_rodata
+        else
+          begin
+            { on Mac OS X, dead code stripping ("smart linking") happens based on
+              global symbols: every global/static symbol (symbols that do not
+              start with "L") marks the start of a new "subsection" that is
+              discarded by the linker if there are no references to this symbol.
+              This means that if you put the jump table in the rodata section, it
+              will become part of the block of data associated with the previous
+              non-L-label in the rodata section and stay or be thrown away
+              depending on whether that block of data is referenced. Therefore,
+              jump tables must be added in the code section and since aktlocaldata
+              is inserted right after the routine, it will become part of the
+              same subsection that contains the routine's code }
+            sectype:=sec_code;
+          end;
+        new_section(current_procinfo.aktlocaldata,sectype,current_procinfo.procdef.mangledname,4);
+        if target_info.system in systems_darwin then
+          begin
+            { additionally, these tables are now marked via ".data_region jt32"
+              and ".end_data_region" }
+            current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_data_region,'jt32'));
+          end;
+        current_procinfo.aktlocaldata.concat(Tai_label.Create(tablelabel));
+        genitem(current_procinfo.aktlocaldata,hp);
+        if target_info.system in systems_darwin then
+          current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_end_data_region,''));
+      end;
+
+
+begin
+   ccasenode:=taarch64casenode;
+end.
index 141d7a1cc464c47c636d0330cd6ec91ce95feda0..0092d15af0101a5389723603acca956c1f5c2dc1 100644 (file)
@@ -64,6 +64,8 @@ NR_W30 = tregister($0104001E);
 NR_X30 = tregister($0105001E);
 NR_WZR = tregister($0104001F);
 NR_XZR = tregister($0105001F);
+NR_WSP = tregister($01040020);
+NR_SP = tregister($01050020);
 NR_B0 = tregister($04010000);
 NR_H0 = tregister($04030000);
 NR_S0 = tregister($04090000);
@@ -225,3 +227,6 @@ NR_S31 = tregister($0409001F);
 NR_D31 = tregister($040a001F);
 NR_Q31 = tregister($0405001F);
 NR_NZCV = tregister($05000000);
+NR_FPCR = tregister($05000001);
+NR_FPSR = tregister($05000002);
+NR_TPIDR_EL0 = tregister($05000003);
index 1198db78e8d1271e65e36ad84369fbf3104cc8bd..eaaf04faed56f2eb915c54c071431a91f3621cd1 100644 (file)
 30,
 31,
 31,
+31,
+31,
+64,
+64,
+64,
+64,
+64,
+65,
+65,
+65,
+65,
+65,
+66,
+66,
+66,
+66,
+66,
+67,
+67,
+67,
+67,
+67,
+68,
+68,
+68,
+68,
+68,
+69,
+69,
+69,
+69,
+69,
+70,
+70,
+70,
+70,
+70,
+71,
+71,
+71,
+71,
+71,
+72,
+72,
+72,
+72,
+72,
+73,
+73,
+73,
+73,
+73,
+74,
+74,
+74,
+74,
+74,
+75,
+75,
+75,
+75,
+75,
+76,
+76,
+76,
+76,
+76,
+77,
+77,
+77,
+77,
+77,
+78,
+78,
+78,
+78,
+78,
+79,
+79,
+79,
+79,
+79,
+80,
+80,
+80,
+80,
+80,
+81,
+81,
+81,
+81,
+81,
+82,
+82,
+82,
+82,
+82,
+83,
+83,
+83,
+83,
+83,
+84,
+84,
+84,
+84,
+84,
+85,
+85,
+85,
+85,
+85,
+86,
+86,
+86,
+86,
+86,
+87,
+87,
+87,
+87,
+87,
+88,
+88,
+88,
+88,
+88,
+89,
+89,
+89,
+89,
+89,
+90,
+90,
+90,
+90,
+90,
+91,
+91,
+91,
+91,
+91,
+92,
+92,
+92,
+92,
+92,
+93,
+93,
+93,
+93,
+93,
+94,
+94,
+94,
+94,
+94,
+95,
+95,
+95,
+95,
+95,
 0,
 0,
 0,
-0,
-0,
-1,
-1,
-1,
-1,
-1,
-2,
-2,
-2,
-2,
-2,
-3,
-3,
-3,
-3,
-3,
-4,
-4,
-4,
-4,
-4,
-5,
-5,
-5,
-5,
-5,
-6,
-6,
-6,
-6,
-6,
-7,
-7,
-7,
-7,
-7,
-8,
-8,
-8,
-8,
-8,
-9,
-9,
-9,
-9,
-9,
-10,
-10,
-10,
-10,
-10,
-11,
-11,
-11,
-11,
-11,
-12,
-12,
-12,
-12,
-12,
-13,
-13,
-13,
-13,
-13,
-14,
-14,
-14,
-14,
-14,
-15,
-15,
-15,
-15,
-15,
-16,
-16,
-16,
-16,
-16,
-17,
-17,
-17,
-17,
-17,
-18,
-18,
-18,
-18,
-18,
-19,
-19,
-19,
-19,
-19,
-20,
-20,
-20,
-20,
-20,
-21,
-21,
-21,
-21,
-21,
-22,
-22,
-22,
-22,
-22,
-23,
-23,
-23,
-23,
-23,
-24,
-24,
-24,
-24,
-24,
-25,
-25,
-25,
-25,
-25,
-26,
-26,
-26,
-26,
-26,
-27,
-27,
-27,
-27,
-27,
-28,
-28,
-28,
-28,
-28,
-29,
-29,
-29,
-29,
-29,
-30,
-30,
-30,
-30,
-30,
-31,
-31,
-31,
-31,
-31,
 0
index cce0278c44918fafc4308613f94cc13c4c824989..a7bff1f7e804058eb153520e017c7e0c8a6b7ac2 100644 (file)
@@ -1,2 +1,2 @@
 { don't edit, this file is generated from a64reg.dat }
-226
+231
index 6cdb6b8b5b00bb9dc691b729963712b588aaf674..4173686ca4edf102d385b6d56b103734d54906b6 100644 (file)
@@ -64,6 +64,8 @@ tregister($0104001E),
 tregister($0105001E),
 tregister($0104001F),
 tregister($0105001F),
+tregister($01040020),
+tregister($01050020),
 tregister($04010000),
 tregister($04030000),
 tregister($04090000),
@@ -224,4 +226,7 @@ tregister($0403001F),
 tregister($0409001F),
 tregister($040a001F),
 tregister($0405001F),
-tregister($05000000)
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003)
index 29b24dae31267e33a8c82f31121c301acf1ad9c4..d818e4d5f5f95924d39c2af04a02c94cf183bd73 100644 (file)
@@ -32,6 +32,7 @@
 59,
 61,
 63,
+65,
 2,
 4,
 6,
 60,
 62,
 64,
-65,
-70,
-75,
-80,
-85,
-90,
-95,
-100,
-105,
-110,
-115,
-120,
-125,
-130,
-135,
-140,
-145,
-150,
-155,
-160,
-165,
-170,
-175,
-180,
-185,
-190,
-195,
-200,
-205,
-210,
-215,
-220,
 66,
-71,
-76,
-81,
-86,
-91,
-96,
-101,
-106,
-111,
-116,
-121,
-126,
-131,
-136,
-141,
-146,
-151,
-156,
-161,
-166,
-171,
-176,
-181,
-186,
-191,
-196,
-201,
-206,
-211,
-216,
-221,
-69,
-74,
-79,
-84,
-89,
-94,
-99,
-104,
-109,
-114,
-119,
-124,
-129,
-134,
-139,
-144,
-149,
-154,
-159,
-164,
-169,
-174,
-179,
-184,
-189,
-194,
-199,
-204,
-209,
-214,
-219,
-224,
 67,
 72,
 77,
 213,
 218,
 223,
-225
+71,
+76,
+81,
+86,
+91,
+96,
+101,
+106,
+111,
+116,
+121,
+126,
+131,
+136,
+141,
+146,
+151,
+156,
+161,
+166,
+171,
+176,
+181,
+186,
+191,
+196,
+201,
+206,
+211,
+216,
+221,
+226,
+69,
+74,
+79,
+84,
+89,
+94,
+99,
+104,
+109,
+114,
+119,
+124,
+129,
+134,
+139,
+144,
+149,
+154,
+159,
+164,
+169,
+174,
+179,
+184,
+189,
+194,
+199,
+204,
+209,
+214,
+219,
+224,
+70,
+75,
+80,
+85,
+90,
+95,
+100,
+105,
+110,
+115,
+120,
+125,
+130,
+135,
+140,
+145,
+150,
+155,
+160,
+165,
+170,
+175,
+180,
+185,
+190,
+195,
+200,
+205,
+210,
+215,
+220,
+225,
+227,
+228,
+229,
+230
index a3e6620ea6be964f5e031bdc541fad5881c80561..570563bbbc5544a3f6ee1172580c68df258edd14 100644 (file)
@@ -1,8 +1,39 @@
 { don't edit, this file is generated from a64reg.dat }
 0,
-65,
+67,
+72,
+117,
+122,
+127,
+132,
+137,
+142,
+147,
+152,
+157,
+162,
+77,
+167,
+172,
+177,
+182,
+187,
+192,
+197,
+202,
+207,
+212,
+82,
+217,
+222,
+87,
+92,
+97,
+102,
+107,
+112,
 70,
-115,
+75,
 120,
 125,
 130,
@@ -12,8 +43,8 @@
 150,
 155,
 160,
-75,
 165,
+80,
 170,
 175,
 180,
 200,
 205,
 210,
-80,
 215,
-220,
 85,
+220,
+225,
 90,
 95,
 100,
 105,
 110,
+115,
+228,
+229,
 68,
 73,
 118,
@@ -64,9 +98,9 @@
 103,
 108,
 113,
-66,
+227,
 71,
-116,
+76,
 121,
 126,
 131,
 151,
 156,
 161,
-76,
 166,
+81,
 171,
 176,
 181,
 201,
 206,
 211,
-81,
 216,
-221,
 86,
+221,
+226,
 91,
 96,
 101,
 106,
 111,
-225,
+116,
 69,
 74,
 119,
 104,
 109,
 114,
-67,
-72,
-117,
-122,
-127,
-132,
-137,
-142,
-147,
-152,
-157,
-162,
-77,
-167,
-172,
-177,
-182,
-187,
-192,
-197,
-202,
-207,
-212,
-82,
-217,
-222,
-87,
-92,
-97,
-102,
-107,
-112,
+66,
+230,
 1,
 3,
 21,
 15,
 17,
 19,
+65,
 63,
 2,
 4,
index 1198db78e8d1271e65e36ad84369fbf3104cc8bd..eaaf04faed56f2eb915c54c071431a91f3621cd1 100644 (file)
 30,
 31,
 31,
+31,
+31,
+64,
+64,
+64,
+64,
+64,
+65,
+65,
+65,
+65,
+65,
+66,
+66,
+66,
+66,
+66,
+67,
+67,
+67,
+67,
+67,
+68,
+68,
+68,
+68,
+68,
+69,
+69,
+69,
+69,
+69,
+70,
+70,
+70,
+70,
+70,
+71,
+71,
+71,
+71,
+71,
+72,
+72,
+72,
+72,
+72,
+73,
+73,
+73,
+73,
+73,
+74,
+74,
+74,
+74,
+74,
+75,
+75,
+75,
+75,
+75,
+76,
+76,
+76,
+76,
+76,
+77,
+77,
+77,
+77,
+77,
+78,
+78,
+78,
+78,
+78,
+79,
+79,
+79,
+79,
+79,
+80,
+80,
+80,
+80,
+80,
+81,
+81,
+81,
+81,
+81,
+82,
+82,
+82,
+82,
+82,
+83,
+83,
+83,
+83,
+83,
+84,
+84,
+84,
+84,
+84,
+85,
+85,
+85,
+85,
+85,
+86,
+86,
+86,
+86,
+86,
+87,
+87,
+87,
+87,
+87,
+88,
+88,
+88,
+88,
+88,
+89,
+89,
+89,
+89,
+89,
+90,
+90,
+90,
+90,
+90,
+91,
+91,
+91,
+91,
+91,
+92,
+92,
+92,
+92,
+92,
+93,
+93,
+93,
+93,
+93,
+94,
+94,
+94,
+94,
+94,
+95,
+95,
+95,
+95,
+95,
 0,
 0,
 0,
-0,
-0,
-1,
-1,
-1,
-1,
-1,
-2,
-2,
-2,
-2,
-2,
-3,
-3,
-3,
-3,
-3,
-4,
-4,
-4,
-4,
-4,
-5,
-5,
-5,
-5,
-5,
-6,
-6,
-6,
-6,
-6,
-7,
-7,
-7,
-7,
-7,
-8,
-8,
-8,
-8,
-8,
-9,
-9,
-9,
-9,
-9,
-10,
-10,
-10,
-10,
-10,
-11,
-11,
-11,
-11,
-11,
-12,
-12,
-12,
-12,
-12,
-13,
-13,
-13,
-13,
-13,
-14,
-14,
-14,
-14,
-14,
-15,
-15,
-15,
-15,
-15,
-16,
-16,
-16,
-16,
-16,
-17,
-17,
-17,
-17,
-17,
-18,
-18,
-18,
-18,
-18,
-19,
-19,
-19,
-19,
-19,
-20,
-20,
-20,
-20,
-20,
-21,
-21,
-21,
-21,
-21,
-22,
-22,
-22,
-22,
-22,
-23,
-23,
-23,
-23,
-23,
-24,
-24,
-24,
-24,
-24,
-25,
-25,
-25,
-25,
-25,
-26,
-26,
-26,
-26,
-26,
-27,
-27,
-27,
-27,
-27,
-28,
-28,
-28,
-28,
-28,
-29,
-29,
-29,
-29,
-29,
-30,
-30,
-30,
-30,
-30,
-31,
-31,
-31,
-31,
-31,
 0
index 039d5fff20175a48ef8d9dd0b86625ae6b5a8724..1eaedf8a348d1a6758257a5f822bf49186f2e802 100644 (file)
@@ -64,6 +64,8 @@
 'x30',
 'wzr',
 'xzr',
+'wsp',
+'sp',
 'b0',
 'h0',
 's0',
 's31',
 'd31',
 'q31',
-'nzcv'
+'nzcv',
+'fpcr',
+'fpsr',
+'tpidr_el0'
index 730f708a138f5244862c60d9427fcb3b10be2aeb..0e59c014ebb6ec9845c974c8ddac86c850a0e7ea 100644 (file)
@@ -64,6 +64,8 @@ RS_W30 = $1E;
 RS_X30 = $1E;
 RS_WZR = $1F;
 RS_XZR = $1F;
+RS_WSP = $20;
+RS_SP = $20;
 RS_B0 = $00;
 RS_H0 = $00;
 RS_S0 = $00;
@@ -225,3 +227,6 @@ RS_S31 = $1F;
 RS_D31 = $1F;
 RS_Q31 = $1F;
 RS_NZCV = $00;
+RS_FPCR = $01;
+RS_FPSR = $02;
+RS_TPIDR_EL0 = $03;
diff --git a/fpcsrc/compiler/aarch64/racpu.pas b/fpcsrc/compiler/aarch64/racpu.pas
new file mode 100644 (file)
index 0000000..b043e14
--- /dev/null
@@ -0,0 +1,88 @@
+{
+    Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+    Copyright (c) 2014 by Jonas Maebe
+
+    Handles the common AArch64 assembler reader routines
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit racpu;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      cgbase,
+      cpubase,
+      aasmtai,aasmdata,
+      rautils;
+
+    type
+      TAArch64Operand=class(TOperand)
+      end;
+
+      TAArch64Instruction=class(TInstruction)
+        oppostfix : toppostfix;
+        function ConcatInstruction(p:TAsmList) : tai;override;
+        function Is64bit: boolean;
+        function cgsize: tcgsize;
+      end;
+
+  implementation
+
+    uses
+      verbose,
+      aasmcpu;
+
+    function TAArch64Instruction.ConcatInstruction(p:TAsmList) : tai;
+      begin
+        result:=inherited ConcatInstruction(p);
+        taicpu(result).oppostfix:=oppostfix;
+      end;
+
+
+    function TAArch64Instruction.Is64bit: boolean;
+      begin
+        result:=
+          (operands[1].opr.typ=OPR_REGISTER) and
+          (getsubreg(operands[1].opr.reg)=R_SUBQ);
+      end;
+
+    function TAArch64Instruction.cgsize: tcgsize;
+      begin
+        if ops<1 then
+          internalerror(2014122001);
+        if operands[1].opr.typ<>OPR_REGISTER then
+          internalerror(2014122002);
+        result:=reg_cgsize(operands[1].opr.reg);
+        { a 32 bit integer register could actually be 16 or 8 bit }
+        if result=OS_32 then
+          case oppostfix of
+            PF_B:
+              result:=OS_8;
+            PF_SB:
+              result:=OS_S8;
+            PF_H:
+              result:=OS_16;
+            PF_SH:
+              result:=OS_S16;
+          end;
+      end;
+
+
+end.
diff --git a/fpcsrc/compiler/aarch64/racpugas.pas b/fpcsrc/compiler/aarch64/racpugas.pas
new file mode 100644 (file)
index 0000000..b0d6b88
--- /dev/null
@@ -0,0 +1,1053 @@
+{
+    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+    Copyright (c) 2014 by Jonas Maebe
+
+    Does the parsing for the AArch64 GNU AS styled inline assembler.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit racpugas;
+
+{$i fpcdefs.inc}
+
+  Interface
+
+    uses
+      raatt,racpu,
+      cpubase;
+
+    type
+      taarch64attreader = class(tattreader)
+        actoppostfix : TOpPostfix;
+        function is_asmopcode(const s: string):boolean;override;
+        function is_register(const s:string):boolean;override;
+        procedure handleopcode;override;
+        procedure BuildReference(oper: taarch64operand; is64bit: boolean);
+        procedure BuildOperand(oper: taarch64operand; is64bit: boolean);
+        function TryBuildShifterOp(instr: taarch64instruction; opnr: longint) : boolean;
+        procedure BuildOpCode(instr: taarch64instruction);
+        procedure ReadSym(oper: taarch64operand; is64bit: boolean);
+        procedure ConvertCalljmp(instr: taarch64instruction);
+        function ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
+      end;
+
+
+  Implementation
+
+    uses
+      { helpers }
+      cutils,
+      { global }
+      globtype,verbose,
+      systems,aasmbase,aasmtai,aasmdata,aasmcpu,
+      { symtable }
+      symconst,symsym,
+      procinfo,
+      rabase,rautils,
+      cgbase,cgutils;
+
+
+    function taarch64attreader.is_register(const s:string):boolean;
+      type
+        treg2str = record
+          name : string[3];
+          reg : tregister;
+        end;
+
+      const
+        extraregs : array[0..3] of treg2str = (
+          (name: 'FP' ; reg: NR_FP),
+          (name: 'LR' ; reg: NR_LR),
+          (name: 'IP0'; reg: NR_IP0),
+          (name: 'IP1'; reg: NR_IP1));
+
+      var
+        i : longint;
+
+      begin
+        result:=inherited is_register(s);
+        { reg found?
+          possible aliases are always 2 or 3 chars
+        }
+        if result or not(length(s) in [2,3]) then
+          exit;
+        for i:=low(extraregs) to high(extraregs) do
+          begin
+            if s=extraregs[i].name then
+              begin
+                actasmregister:=extraregs[i].reg;
+                result:=true;
+                actasmtoken:=AS_REGISTER;
+                exit;
+              end;
+          end;
+      end;
+
+
+    procedure taarch64attreader.ReadSym(oper: taarch64operand; is64bit: boolean);
+      var
+         tempstr, mangledname : string;
+         typesize,l,k: aint;
+      begin
+        tempstr:=actasmpattern;
+        Consume(AS_ID);
+        { typecasting? }
+        if (actasmtoken=AS_LPAREN) and
+           SearchType(tempstr,typesize) then
+          begin
+            oper.hastype:=true;
+            Consume(AS_LPAREN);
+            BuildOperand(oper,is64bit);
+            Consume(AS_RPAREN);
+            if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+              oper.SetSize(typesize,true);
+          end
+        else
+          if not oper.SetupVar(tempstr,false) then
+            Message1(sym_e_unknown_id,tempstr);
+        { record.field ? }
+        if actasmtoken=AS_DOT then
+          begin
+            BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+            if (mangledname<>'') then
+              Message(asmr_e_invalid_reference_syntax);
+            inc(oper.opr.ref.offset,l);
+          end;
+      end;
+
+
+    Procedure taarch64attreader.BuildReference(oper: taarch64operand; is64bit: boolean);
+
+      procedure do_error;
+        begin
+          Message(asmr_e_invalid_reference_syntax);
+          RecoverConsume(false);
+        end;
+
+
+      procedure test_end(require_rbracket : boolean);
+        begin
+          if require_rbracket then begin
+            if not(actasmtoken=AS_RBRACKET) then
+              begin
+                do_error;
+                exit;
+              end
+            else
+              Consume(AS_RBRACKET);
+            if (actasmtoken=AS_NOT) then
+              begin
+                oper.opr.ref.addressmode:=AM_PREINDEXED;
+                Consume(AS_NOT);
+              end;
+          end;
+          if not(actasmtoken in [AS_SEPARATOR,AS_end]) then
+            do_error
+          else
+            begin
+{$IFDEF debugasmreader}
+              writeln('TEST_end_FINAL_OK. Created the following ref:');
+              writeln('oper.opr.ref.shiftimm=',oper.opr.ref.shiftimm);
+              writeln('oper.opr.ref.shiftmode=',ord(oper.opr.ref.shiftmode));
+              writeln('oper.opr.ref.index=',ord(oper.opr.ref.index));
+              writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
+              writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
+              writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
+              writeln;
+{$endIF debugasmreader}
+            end;
+        end;
+
+
+      function is_shifter_ref_operation(var a : tshiftmode) : boolean;
+        begin
+          a:=SM_NONE;
+          if (actasmpattern='LSL') then
+            a:=SM_LSL
+          else if (actasmpattern='UXTW') then
+            a:=SM_UXTW
+          else if (actasmpattern='SXTW') then
+            a:=SM_SXTW
+          else if (actasmpattern='SXTX') then
+            a:=SM_SXTX;
+          is_shifter_ref_operation:=not(a=SM_NONE);
+        end;
+
+
+      procedure read_index_shift(require_rbracket : boolean);
+        var
+          shift: aint;
+        begin
+          case actasmtoken of
+            AS_COMMA :
+              begin
+                Consume(AS_COMMA);
+                if not(actasmtoken=AS_ID) then
+                  do_error;
+                if is_shifter_ref_operation(oper.opr.ref.shiftmode) then
+                  begin
+                    Consume(actasmtoken);
+                    if actasmtoken=AS_HASH then
+                      begin
+                        Consume(AS_HASH);
+                        shift:=BuildConstExpression(false,true);
+                        if not(shift in [0,2+ord(is64bit)]) then
+                          do_error;
+                        oper.opr.ref.shiftimm:=shift;
+                        test_end(require_rbracket);
+                      end;
+                   end
+                 else
+                   begin
+                     do_error;
+                     exit;
+                   end;
+              end;
+            AS_RBRACKET :
+              if require_rbracket then
+                test_end(require_rbracket)
+              else
+                begin
+                  do_error;
+                  exit;
+                end;
+            AS_SEPARATOR,AS_END :
+              if not require_rbracket then
+                test_end(false)
+               else
+                 do_error;
+            else
+              begin
+                do_error;
+                exit;
+              end;
+          end;
+        end;
+
+
+      procedure read_index(require_rbracket : boolean);
+        var
+          recname : string;
+          o_int,s_int : aint;
+        begin
+          case actasmtoken of
+            AS_REGISTER :
+              begin
+                if getsupreg(actasmregister)=RS_XZR then
+                  Message1(asmr_e_invalid_ref_register,actasmpattern);
+                oper.opr.ref.index:=actasmregister;
+                Consume(AS_REGISTER);
+                read_index_shift(require_rbracket);
+                exit;
+              end;
+            AS_HASH : // constant
+              begin
+                Consume(AS_HASH);
+(*
+                if actasmtoken=AS_COLON then
+                  begin
+                    consume(AS_COLON);
+                    { GNU-style lower 12 bits of address of non-GOT-based
+                      access }
+                    if (actasmpattern='LO12') then
+                      begin
+                        consume(actasmtoken);
+                        consume(AS_COLON);
+                        if not oper.SetupVar(actasmpattern,false) then
+                          begin
+                            do_error;
+                            exit
+                          end;
+                        consume(AS_ID);
+                        oper.opr.ref.refaddr:=addr_??? (not gotpageoffset);
+                      end
+                    else
+                      begin
+                        do_error;
+                        exit
+                      end;
+                  end
+                else
+*)
+                  begin
+                    o_int:=BuildConstExpression(false,true);
+                    inc(oper.opr.ref.offset,o_int);
+                  end;
+                test_end(require_rbracket);
+                exit;
+              end;
+            AS_ID :
+              begin
+                recname:=actasmpattern;
+                Consume(AS_ID);
+                { Apple-style got page offset }
+                if actasmtoken=AS_AT then
+                  begin
+                    if not oper.SetupVar(recname,false) then
+                      begin
+                        do_error;
+                        exit
+                      end;
+                    consume(AS_AT);
+                    if actasmpattern='GOTPAGEOFF' then
+                      begin
+                        consume(actasmtoken);
+                        oper.opr.ref.refaddr:=addr_gotpageoffset;
+                      end
+                    else if actasmpattern='PAGEOFF' then
+                      begin
+                        consume(actasmtoken);
+                        oper.opr.ref.refaddr:=addr_pageoffset;
+                      end
+                    else
+                      begin
+                        do_error;
+                        exit
+                      end;
+                  end
+                else
+                  begin
+                    BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
+                    inc(oper.opr.ref.offset,o_int);
+                  end;
+                test_end(require_rbracket);
+                exit;
+              end;
+            AS_AT:
+              begin
+                do_error;
+                exit;
+              end;
+            AS_RBRACKET :
+              begin
+                if require_rbracket then
+                  begin
+                    test_end(require_rbracket);
+                    exit;
+                  end
+                else
+                  begin
+                    do_error; // unexpected rbracket
+                    exit;
+                  end;
+              end;
+            AS_SEPARATOR,AS_end :
+              begin
+                if not require_rbracket then
+                  begin
+                    test_end(false);
+                    exit;
+                  end
+                else
+                  begin
+                    do_error;
+                    exit;
+                  end;
+              end;
+            else
+              begin
+                // unexpected token
+                do_error;
+                exit;
+              end;
+          end; // case
+        end;
+
+
+      procedure try_prepostindexed;
+        begin
+          Consume(AS_RBRACKET);
+          case actasmtoken of
+            AS_COMMA :
+              begin // post-indexed
+                Consume(AS_COMMA);
+                oper.opr.ref.addressmode:=AM_POSTINDEXED;
+                read_index(false);
+                exit;
+              end;
+            AS_NOT :
+              begin   // pre-indexed
+                Consume(AS_NOT);
+                oper.opr.ref.addressmode:=AM_PREINDEXED;
+                test_end(false);
+                exit;
+              end;
+            else
+              begin
+                test_end(false);
+                exit;
+              end;
+          end; // case
+        end;
+
+      begin
+        Consume(AS_LBRACKET);
+        oper.opr.ref.addressmode:=AM_OFFSET; // assume "neither PRE nor POST inc"
+        if actasmtoken=AS_REGISTER then
+          begin
+            if getsupreg(actasmregister)=RS_XZR then
+              Message1(asmr_e_invalid_ref_register,actasmpattern);
+            oper.opr.ref.base:=actasmregister;
+            Consume(AS_REGISTER);
+            case actasmtoken of
+              AS_RBRACKET :
+                begin
+                  try_prepostindexed;
+                  exit;
+                end;
+              AS_COMMA :
+                begin
+                  Consume(AS_COMMA);
+                  read_index(true);
+                  exit;
+                end;
+              else
+                begin
+                  Message(asmr_e_invalid_reference_syntax);
+                  RecoverConsume(false);
+                end;
+            end;
+          end
+        else
+          Begin
+            case actasmtoken of
+              AS_ID :
+                begin
+                  { TODO: local variables and parameters }
+                  Message(asmr_e_invalid_reference_syntax);
+                  RecoverConsume(false);
+                  exit;
+                end;
+              else
+                begin // elsecase
+                  Message(asmr_e_invalid_reference_syntax);
+                  RecoverConsume(false);
+                  exit;
+                end;
+            end;
+          end;
+      end;
+
+
+    function taarch64attreader.TryBuildShifterOp(instr: taarch64instruction; opnr: longint): boolean;
+
+      procedure handlepara(sm : tshiftmode);
+        begin
+          consume(AS_ID);
+          fillchar(instr.operands[opnr].opr,sizeof(instr.operands[opnr].opr),0);
+          instr.operands[opnr].opr.typ:=OPR_SHIFTEROP;
+          instr.operands[opnr].opr.shifterop.shiftmode:=sm;
+          if (sm=SM_LSL) or
+             (actasmtoken=AS_HASH) then
+            begin
+              consume(AS_HASH);
+              instr.operands[opnr].opr.shifterop.shiftimm:=BuildConstExpression(false,false);
+            end;
+        end;
+
+      const
+        shiftmode2str: array[SM_LSL..SM_SXTX] of string[4] =
+          ('LSL','LSR','ASR',
+           'UXTB','UXTH','UXTW','UXTX',
+           'SXTB','SXTH','SXTW','SXTX');
+      var
+        sm: tshiftmode;
+        i: longint;
+        usessp,
+        useszr: boolean;
+      begin
+        result:=false;
+        if (actasmtoken=AS_ID) then
+          begin
+            for sm:=low(shiftmode2str) to high(shiftmode2str) do
+              if actasmpattern=shiftmode2str[sm] then
+                begin
+                  handlepara(sm);
+                  if instr.operands[1].opr.typ=OPR_REGISTER then
+                    begin
+                      { the possible shifter ops depend on whether this
+                        instruction uses sp and/or zr }
+                      usessp:=false;
+                      useszr:=false;
+                      for i:=low(instr.operands) to pred(opnr) do
+                        begin
+                          if (instr.operands[1].opr.typ=OPR_REGISTER) then
+                            case getsupreg(instr.operands[1].opr.reg) of
+                              RS_XZR:
+                                useszr:=true;
+                              RS_SP:
+                                usessp:=true;
+                            end;
+                        end;
+                      result:=valid_shifter_operand(instr.opcode,useszr,usessp,instr.Is64bit,sm,instr.operands[opnr].opr.shifterop.shiftimm);
+                    end
+                end;
+          end;
+      end;
+
+
+    function taarch64attreader.ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
+      begin
+        case actopcode of
+          A_CSEL,A_CSINC,A_CSINV,A_CSNEG,A_CSET,A_CSETM,
+          A_CINC,A_CINV,A_CNEG,A_CCMN,A_CCMP,
+          A_B:
+            begin
+              { search for condition, conditions are always 2 chars }
+              if (is_operand<>(actopcode=A_B)) and
+                 (length(hs)>1) then
+                begin
+                  { workaround for DFA bug }
+                  result:=low(tasmcond);
+                  for result:=low(tasmcond) to high(tasmcond) do
+                    begin
+                      if hs=uppercond2str[result] then
+                        exit;
+                    end;
+                end;
+            end;
+        end;
+        result:=C_None;;
+      end;
+
+
+    Procedure taarch64attreader.BuildOperand(oper: taarch64operand; is64bit: boolean);
+      var
+        expr: string;
+        typesize, l: aint;
+
+        procedure MaybeAddGotAddrMode;
+          begin
+            if actasmtoken=AS_AT then
+              begin
+                consume(AS_AT);
+                if actasmpattern='GOTPAGE' then
+                  oper.opr.ref.refaddr:=addr_gotpage
+                else if actasmpattern='GOTPAGEOFF' then
+                  oper.opr.ref.refaddr:=addr_gotpageoffset
+                else if actasmpattern='PAGE' then
+                  oper.opr.ref.refaddr:=addr_page
+                else if actasmpattern='PAGEOFF' then
+                  oper.opr.ref.refaddr:=addr_pageoffset
+                else
+                  Message(asmr_e_expr_illegal);
+                consume(actasmtoken);
+              end
+            else
+              oper.opr.ref.refaddr:=addr_pic;
+          end;
+
+        procedure AddLabelOperand(hl:tasmlabel);
+          begin
+            if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+               is_calljmp(actopcode) then
+             begin
+               oper.opr.typ:=OPR_SYMBOL;
+               oper.opr.symbol:=hl;
+             end
+            else if (actopcode=A_ADR) or
+               (actopcode=A_ADRP) then
+              begin
+                oper.InitRef;
+                MaybeAddGotAddrMode;
+                oper.opr.ref.symbol:=hl;
+                if (actasmtoken in [AS_PLUS, AS_MINUS]) then
+                  begin
+                    l:=BuildConstExpression(true,false);
+                    oper.opr.ref.offset:=l;
+                  end;
+              end;
+          end;
+
+
+        procedure MaybeRecordOffset;
+          var
+            mangledname: string;
+            hasdot  : boolean;
+            l,
+            toffset,
+            tsize   : aint;
+          begin
+            if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+              exit;
+            l:=0;
+            hasdot:=(actasmtoken=AS_DOT);
+            if hasdot then
+              begin
+                if expr<>'' then
+                  begin
+                    BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+                    if (oper.opr.typ<>OPR_CONSTANT) and
+                       (mangledname<>'') then
+                      Message(asmr_e_wrong_sym_type);
+                    inc(l,toffset);
+                    oper.SetSize(tsize,true);
+                  end;
+              end;
+            if actasmtoken in [AS_PLUS,AS_MINUS] then
+              inc(l,BuildConstExpression(true,false));
+            case oper.opr.typ of
+              OPR_LOCAL :
+                begin
+                  { don't allow direct access to fields of parameters, because that
+                    will generate buggy code. Allow it only for explicit typecasting }
+                  if hasdot and
+                     (not oper.hastype) and
+                     (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+                     (current_procinfo.procdef.proccalloption<>pocall_register) then
+                    Message(asmr_e_cannot_access_field_directly_for_parameters);
+                  inc(oper.opr.localsymofs,l)
+                end;
+              OPR_CONSTANT :
+                inc(oper.opr.val,l);
+              OPR_REFERENCE :
+                if (mangledname<>'') then
+                  begin
+                    if (oper.opr.val<>0) then
+                      Message(asmr_e_wrong_sym_type);
+                    oper.opr.typ:=OPR_SYMBOL;
+                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+                  end
+                else
+                  inc(oper.opr.val,l);
+              OPR_SYMBOL:
+                Message(asmr_e_invalid_symbol_ref);
+              else
+                internalerror(200309221);
+            end;
+          end;
+
+
+        function MaybeBuildReference(is64bit: boolean):boolean;
+          { Try to create a reference, if not a reference is found then false
+            is returned }
+          begin
+            MaybeBuildReference:=true;
+            case actasmtoken of
+              AS_INTNUM,
+              AS_MINUS,
+              AS_PLUS:
+                Begin
+                  oper.opr.ref.offset:=BuildConstExpression(True,False);
+                  if actasmtoken<>AS_LPAREN then
+                    Message(asmr_e_invalid_reference_syntax)
+                  else
+                    BuildReference(oper,is64bit);
+                end;
+              AS_LPAREN:
+                BuildReference(oper,is64bit);
+              AS_ID: { only a variable is allowed ... }
+                Begin
+                  ReadSym(oper,is64bit);
+                  case actasmtoken of
+                    AS_end,
+                    AS_SEPARATOR,
+                    AS_COMMA: ;
+                    AS_LPAREN:
+                      BuildReference(oper,is64bit);
+                  else
+                    Begin
+                      Message(asmr_e_invalid_reference_syntax);
+                      Consume(actasmtoken);
+                    end;
+                  end; {end case }
+                end;
+              else
+               MaybeBuildReference:=false;
+            end; { end case }
+          end;
+
+
+      var
+        tempreg: tregister;
+        hl: tasmlabel;
+        icond: tasmcond;
+      Begin
+        expr:='';
+        case actasmtoken of
+          AS_LBRACKET: { Memory reference or constant expression }
+            Begin
+              oper.InitRef;
+              BuildReference(oper,is64bit);
+            end;
+
+          AS_HASH: { Constant expression  }
+            Begin
+              Consume(AS_HASH);
+              BuildConstantOperand(oper);
+            end;
+
+          (*
+          AS_INTNUM,
+          AS_MINUS,
+          AS_PLUS:
+            Begin
+              { Constant memory offset }
+              { This must absolutely be followed by (  }
+              oper.InitRef;
+              oper.opr.ref.offset:=BuildConstExpression(True,False);
+              if actasmtoken<>AS_LPAREN then
+                begin
+                  ofs:=oper.opr.ref.offset;
+                  BuildConstantOperand(oper);
+                  inc(oper.opr.val,ofs);
+                end
+              else
+                BuildReference(oper,is64bit);
+            end;
+          *)
+          AS_ID: { A constant expression, or a Variable ref.  }
+            Begin
+              { Condition code? }
+              icond:=ToConditionCode(actasmpattern,true);
+              if icond<>C_None then
+                begin
+                  oper.opr.typ:=OPR_COND;
+                  oper.opr.cc:=icond;
+                  consume(AS_ID);
+                end
+              else
+              { Local Label ? }
+              if is_locallabel(actasmpattern) then
+               begin
+                 CreateLocalLabel(actasmpattern,hl,false);
+                 Consume(AS_ID);
+                 AddLabelOperand(hl);
+               end
+              else
+               { Check for label }
+               if SearchLabel(actasmpattern,hl,false) then
+                 begin
+                   Consume(AS_ID);
+                   AddLabelOperand(hl);
+                 end
+              else
+               { probably a variable or normal expression }
+               { or a procedure (such as in CALL ID)      }
+               begin
+                 { is it a constant ? }
+                 if SearchIConstant(actasmpattern,l) then
+                  begin
+                    if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+                      Message(asmr_e_invalid_operand_type);
+                    BuildConstantOperand(oper);
+                  end
+                 else
+                  begin
+                    expr:=actasmpattern;
+                    Consume(AS_ID);
+                    { typecasting? }
+                    if (actasmtoken=AS_LPAREN) and
+                       SearchType(expr,typesize) then
+                     begin
+                       oper.hastype:=true;
+                       Consume(AS_LPAREN);
+                       BuildOperand(oper,is64bit);
+                       Consume(AS_RPAREN);
+                       if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+                         oper.SetSize(typesize,true);
+                     end
+                    else
+                     begin
+                       if not(oper.SetupVar(expr,false)) then
+                        Begin
+                          { look for special symbols ... }
+                          if expr= '__HIGH' then
+                            begin
+                              consume(AS_LPAREN);
+                              if not oper.setupvar('high'+actasmpattern,false) then
+                                Message1(sym_e_unknown_id,'high'+actasmpattern);
+                              consume(AS_ID);
+                              consume(AS_RPAREN);
+                            end
+                          else
+                           if expr = '__RESULT' then
+                            oper.SetUpResult
+                          else
+                           if expr = '__SELF' then
+                            oper.SetupSelf
+                          else
+                           if expr = '__OLDEBP' then
+                            oper.SetupOldEBP
+                          else
+                            Message1(sym_e_unknown_id,expr);
+                        end
+                       else
+                         MaybeAddGotAddrMode;
+                     end;
+                  end;
+                  if actasmtoken=AS_DOT then
+                    MaybeRecordOffset;
+                  { add a constant expression? }
+                  if (actasmtoken=AS_PLUS) then
+                   begin
+                     l:=BuildConstExpression(true,false);
+                     case oper.opr.typ of
+                       OPR_CONSTANT :
+                         inc(oper.opr.val,l);
+                       OPR_LOCAL :
+                         inc(oper.opr.localsymofs,l);
+                       OPR_REFERENCE :
+                         inc(oper.opr.ref.offset,l);
+                       else
+                         internalerror(200309202);
+                     end;
+                   end
+               end;
+              { Do we have a indexing reference, then parse it also }
+              if actasmtoken=AS_LPAREN then
+                BuildReference(oper,is64bit);
+            end;
+
+          { Register, a variable reference or a constant reference  }
+          AS_REGISTER:
+            Begin
+              { save the type of register used. }
+              tempreg:=actasmregister;
+              Consume(AS_REGISTER);
+              if (actasmtoken in [AS_end,AS_SEPARATOR,AS_COMMA]) then
+                Begin
+                  if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+                    Message(asmr_e_invalid_operand_type);
+                  oper.opr.typ:=OPR_REGISTER;
+                  oper.opr.reg:=tempreg;
+                end
+              else
+                Message(asmr_e_syn_operand);
+            end;
+
+          AS_end,
+          AS_SEPARATOR,
+          AS_COMMA: ;
+        else
+          Begin
+            Message(asmr_e_syn_operand);
+            Consume(actasmtoken);
+          end;
+        end; { end case }
+      end;
+
+{*****************************************************************************
+                                taarch64attreader
+*****************************************************************************}
+
+    procedure taarch64attreader.BuildOpCode(instr: taarch64instruction);
+      var
+        operandnum : longint;
+      Begin
+        { opcode }
+        if (actasmtoken<>AS_OPCODE) then
+         Begin
+           Message(asmr_e_invalid_or_missing_opcode);
+           RecoverConsume(true);
+           exit;
+         end;
+        { Fill the instr object with the current state }
+        with instr do
+          begin
+            Opcode:=ActOpcode;
+            condition:=ActCondition;
+            oppostfix:=actoppostfix;
+          end;
+        Consume(AS_OPCODE);
+
+        { We are reading operands, so opcode will be an AS_ID }
+        operandnum:=1;
+        { Zero operand opcode ?  }
+        if actasmtoken in [AS_SEPARATOR,AS_end] then
+         begin
+           instr.Ops:=0;
+           exit;
+         end;
+        { Read the operands }
+        repeat
+          case actasmtoken of
+            AS_COMMA: { Operand delimiter }
+              Begin
+                { operandnum and not operandnum+1, because tinstruction is
+                  one-based and taicpu is zero-based)
+                }
+                if can_be_shifter_operand(instr.opcode,operandnum) then
+                  begin
+                    Consume(AS_COMMA);
+                    if not TryBuildShifterOp(instr,operandnum+1) then
+                      Message(asmr_e_illegal_shifterop_syntax);
+                    Inc(operandnum);
+                  end
+                else
+                  begin
+                    if operandnum>Max_Operands then
+                      Message(asmr_e_too_many_operands)
+                    else
+                      Inc(operandnum);
+                    Consume(AS_COMMA);
+                  end;
+              end;
+            AS_SEPARATOR,
+            AS_end : { End of asm operands for this opcode  }
+              begin
+                break;
+              end;
+          else
+            begin
+              BuildOperand(taarch64operand(instr.operands[operandnum]),instr.Is64bit);
+              instr.Ops:=operandnum;
+              if instr.operands[operandnum].opr.typ=OPR_REFERENCE then
+                if simple_ref_type(instr.opcode,instr.cgsize,instr.oppostfix,instr.operands[operandnum].opr.ref)<>sr_simple then
+                  Message(asmr_e_invalid_reference_syntax);
+                ;
+            end;
+          end; { end case }
+        until false;
+      end;
+
+
+    function taarch64attreader.is_asmopcode(const s: string):boolean;
+
+      const
+        { sorted by length so longer postfixes will match first }
+        postfix2strsorted : array[1..7] of string[3] = (
+          'SB','SH','SW',
+          'B','H','W',
+          'S');
+
+        postfixsorted : array[1..7] of TOpPostfix = (
+          PF_SB,PF_SH,PF_SW,
+          PF_B,PF_H,PF_W,
+          PF_S);
+
+      var
+        j  : longint;
+        hs : string;
+        maxlen : longint;
+        icond : tasmcond;
+      Begin
+        { making s a value parameter would break other assembler readers }
+        hs:=s;
+        is_asmopcode:=false;
+
+        { clear opcode }
+        actopcode:=A_None;
+        actcondition:=C_None;
+
+        { b.cond ? }
+        if (length(hs)=4) and
+           (hs[1]='B') and
+           (hs[2]='.') then
+          begin
+            actopcode:=A_B;
+            actasmtoken:=AS_OPCODE;
+            actcondition:=ToConditionCode(copy(hs,3,length(actasmpattern)-2),false);
+            if actcondition<>C_None then
+              is_asmopcode:=true;
+            exit;
+          end;
+
+        maxlen:=max(length(hs),7);
+        actopcode:=A_NONE;
+        for j:=maxlen downto 1 do
+          begin
+            actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
+            if actopcode<>A_NONE then
+              begin
+                actasmtoken:=AS_OPCODE;
+                { strip op code }
+                delete(hs,1,j);
+                break;
+              end;
+          end;
+        if actopcode=A_NONE then
+          exit;
+
+        { check for postfix }
+        if length(hs)>0 then
+          begin
+            for j:=low(postfixsorted) to high(postfixsorted) do
+              begin
+                if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                  begin
+                    actoppostfix:=postfixsorted[j];
+                    { strip postfix }
+                    delete(hs,1,length(postfix2strsorted[j]));
+                    break;
+                  end;
+              end;
+          end;
+        { if we stripped all postfixes, it's a valid opcode }
+        is_asmopcode:=length(hs)=0;
+      end;
+
+
+    procedure taarch64attreader.ConvertCalljmp(instr: taarch64instruction);
+      var
+        newopr : toprrec;
+      begin
+        if instr.Operands[1].opr.typ=OPR_REFERENCE then
+          begin
+            newopr.typ:=OPR_SYMBOL;
+            newopr.symbol:=instr.Operands[1].opr.ref.symbol;
+            newopr.symofs:=instr.Operands[1].opr.ref.offset;
+            if (instr.Operands[1].opr.ref.base<>NR_NO) or
+              (instr.Operands[1].opr.ref.index<>NR_NO) or
+              (instr.Operands[1].opr.ref.refaddr<>addr_pic) then
+              Message(asmr_e_syn_operand);
+            instr.Operands[1].opr:=newopr;
+          end;
+      end;
+
+    procedure taarch64attreader.handleopcode;
+      var
+        instr: taarch64instruction;
+      begin
+        instr:=taarch64instruction.Create(taarch64operand);
+        BuildOpcode(instr);
+        if is_calljmp(instr.opcode) then
+          ConvertCalljmp(instr);
+        {
+        instr.AddReferenceSizes;
+        instr.SetInstructionOpsize;
+        instr.CheckOperandSizes;
+        }
+        instr.ConcatInstruction(curlist);
+        instr.Free;
+        actoppostfix:=PF_None;
+      end;
+
+
+{*****************************************************************************
+                                     Initialize
+*****************************************************************************}
+
+const
+  asmmode_arm_att_info : tasmmodeinfo =
+          (
+            id    : asmmode_arm_gas;
+            idtxt : 'GAS';
+            casmreader : taarch64attreader;
+          );
+
+  asmmode_arm_standard_info : tasmmodeinfo =
+          (
+            id    : asmmode_standard;
+            idtxt : 'STANDARD';
+            casmreader : taarch64attreader;
+          );
+
+initialization
+  RegisterAsmMode(asmmode_arm_att_info);
+  RegisterAsmMode(asmmode_arm_standard_info);
+end.
diff --git a/fpcsrc/compiler/aarch64/rgcpu.pas b/fpcsrc/compiler/aarch64/rgcpu.pas
new file mode 100644 (file)
index 0000000..fb9521c
--- /dev/null
@@ -0,0 +1,171 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    This unit implements the SPARC specific class for the register
+    allocator
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      aasmbase,aasmcpu,aasmtai,aasmdata,
+      cgbase,cgutils,
+      cpubase,
+      globtype,
+      rgobj;
+
+    type
+      trgcpu=class(trgobj)
+        procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+        procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+       protected
+        procedure do_spill_op(list: tasmlist; op: tasmop; pos: tai; const spilltemp: treference; tempreg: tregister);
+      end;
+
+      trgintcpu=class(trgcpu)
+        procedure add_cpu_interferences(p: tai); override;
+      end;
+
+
+implementation
+
+    uses
+      verbose,cutils,
+      cgobj;
+
+    procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+      begin
+        do_spill_op(list,A_LDR,pos,spilltemp,tempreg);
+      end;
+
+
+    procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+      begin
+        do_spill_op(list,A_STR,pos,spilltemp,tempreg);
+      end;
+
+
+    procedure trgcpu.do_spill_op(list: tasmlist; op: tasmop; pos: tai; const spilltemp: treference; tempreg: tregister);
+      var
+        helpins  : tai;
+        tmpref   : treference;
+        helplist : TAsmList;
+        hreg     : tregister;
+        isload   : boolean;
+      begin
+        isload:=op=A_LDR;
+        { offset out of range for regular load/store? }
+        if simple_ref_type(op,reg_cgsize(tempreg),PF_None,spilltemp)<>sr_simple then
+          begin
+            helplist:=TAsmList.create;
+
+            if getregtype(tempreg)=R_INTREGISTER then
+              hreg:=tempreg
+            else
+              hreg:=cg.getaddressregister(helplist);
+
+            cg.a_load_const_reg(helplist,OS_ADDR,spilltemp.offset,hreg);
+            reference_reset_base(tmpref,spilltemp.base,0,sizeof(pint));
+            tmpref.index:=hreg;
+            if isload then
+              helpins:=spilling_create_load(tmpref,tempreg)
+            else
+              helpins:=spilling_create_store(tempreg,tmpref);
+            helplist.concat(helpins);
+            add_cpu_interferences(helpins);
+            list.insertlistafter(pos,helplist);
+            helplist.free;
+          end
+        else if isload then
+          inherited do_spill_read(list,pos,spilltemp,tempreg)
+        else
+          inherited do_spill_written(list,pos,spilltemp,tempreg)
+      end;
+
+
+    procedure trgintcpu.add_cpu_interferences(p: tai);
+     var
+       i, j: longint;
+     begin
+       if p.typ=ait_instruction then
+         begin
+           { add interferences for instructions that can have SP as a register
+             operand }
+           case taicpu(p).opcode of
+             A_MOV:
+               { all operands can be SP }
+               exit;
+             A_ADD,
+             A_SUB,
+             A_CMP,
+             A_CMN:
+               { ok as destination or first source in immediate or extended
+                 register form }
+               if (taicpu(p).oper[taicpu(p).ops-1]^.typ<>top_shifterop) or
+                  valid_shifter_operand(taicpu(p).opcode,false,true,
+                    reg_cgsize(taicpu(p).oper[0]^.reg) in [OS_64,OS_S64],
+                    taicpu(p).oper[taicpu(p).ops-1]^.shifterop^.shiftmode,
+                    taicpu(p).oper[taicpu(p).ops-1]^.shifterop^.shiftimm) then
+                 begin
+                   if taicpu(p).oper[taicpu(p).ops-1]^.typ=top_shifterop then
+                     i:=taicpu(p).ops-2
+                   else
+                     i:=taicpu(p).ops-1;
+                   if (taicpu(p).oper[i]^.typ=top_reg) then
+                     add_edge(getsupreg(taicpu(p).oper[i]^.reg),RS_SP);
+                   exit;
+                 end;
+             A_AND,
+             A_EOR,
+             A_ORR,
+             A_TST:
+               { ok in immediate form }
+               if taicpu(p).oper[taicpu(p).ops-1]^.typ=top_const then
+                 exit;
+           end;
+           { add interferences for other registers }
+           for i:=0 to taicpu(p).ops-1 do
+             begin
+               case taicpu(p).oper[i]^.typ of
+                 top_reg:
+                   if getregtype(taicpu(p).oper[i]^.reg)=R_INTREGISTER then
+                     add_edge(getsupreg(taicpu(p).oper[i]^.reg),RS_SP);
+                 top_ref:
+                   begin
+                     { sp can always be base, never be index }
+                     if taicpu(p).oper[i]^.ref^.index<>NR_NO then
+                       add_edge(getsupreg(taicpu(p).oper[i]^.ref^.index),RS_SP);
+                     { in case of write back, the base register must be
+                       different from the loaded/stored register }
+                     if (taicpu(p).oper[i]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
+                        (taicpu(p).oper[i]^.ref^.base<>NR_NO) then
+                       begin
+                         for j:=pred(i) downto 0 do
+                           if taicpu(p).oper[j]^.typ=TOP_REG then
+                             add_edge(getsupreg(taicpu(p).oper[j]^.reg),getsupreg(taicpu(p).oper[i]^.ref^.base));
+                       end;
+                   end;
+               end;
+             end;
+         end;
+     end;
+
+end.
index c3176dc544d0001ff9c0a1c4b5b74049208bbdef..989187df73a05218a912c30a4f1323fbc4c1e568 100644 (file)
@@ -80,7 +80,6 @@ interface
           ait_labeled_instruction,
 {$endif m68k}
 {$ifdef arm}
-          ait_thumb_func,
           ait_thumb_set,
 {$endif arm}
           ait_set,
@@ -198,7 +197,6 @@ interface
           'labeled_instr',
 {$endif m68k}
 {$ifdef arm}
-          'thumb_func',
           'thumb_set',
 {$endif arm}
           'set',
@@ -221,11 +219,11 @@ interface
 {$ifdef arm}
        { ARM only }
        ,top_regset
-       ,top_conditioncode
        ,top_modeflags
        ,top_specialreg
 {$endif arm}
 {$if defined(arm) or defined(aarch64)}
+       ,top_conditioncode
        ,top_shifterop
 {$endif defined(arm) or defined(aarch64)}
 {$ifdef m68k}
@@ -268,12 +266,12 @@ interface
           top_local  : (localoper:plocaloper);
       {$ifdef arm}
           top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister; usermode: boolean);
-          top_conditioncode : (cc : TAsmCond);
           top_modeflags : (modeflags : tcpumodeflags);
           top_specialreg : (specialreg:tregister; specialflags:tspecialregflags);
       {$endif arm}
       {$if defined(arm) or defined(aarch64)}
           top_shifterop : (shifterop : pshifterop);
+          top_conditioncode : (cc : TAsmCond);
       {$endif defined(arm) or defined(aarch64)}
       {$ifdef m68k}
           top_regset : (dataregset,addrregset:^tcpuregisterset);
@@ -310,7 +308,6 @@ interface
                      ait_cutobject,ait_marker,ait_varloc,ait_align,ait_section,ait_comment,
                      ait_const,ait_directive,
 {$ifdef arm}
-                     ait_thumb_func,
                      ait_thumb_set,
 {$endif arm}
                      ait_set,ait_weak,
@@ -356,7 +353,11 @@ interface
         { for Jasmin }
         asd_jclass,asd_jinterface,asd_jsuper,asd_jfield,asd_jlimit,asd_jline,
         { .ent/.end for MIPS and Alpha }
-        asd_ent,asd_ent_end
+        asd_ent,asd_ent_end,
+        { supported by recent clang-based assemblers for data-in-code  }
+        asd_data_region, asd_end_data_region,
+        { .thumb_func for ARM }
+        asd_thumb_func
       );
 
       TAsmSehDirective=(
@@ -385,7 +386,11 @@ interface
         { for Jasmin }
         'class','interface','super','field','limit','line',
         { .ent/.end for MIPS and Alpha }
-        'ent','end'
+        'ent','end',
+        { supported by recent clang-based assemblers for data-in-code }
+        'data_region','end_data_region',
+        { .thumb_func for ARM }
+        'thumb_func'
       );
       sehdirectivestr : array[TAsmSehDirective] of string[16]=(
         '.seh_proc','.seh_endproc',
@@ -2552,6 +2557,9 @@ implementation
 {$ifdef ARM}
               and not(r.base=NR_R15)
 {$endif ARM}
+{$ifdef aarch64}
+              and not(r.refaddr in [addr_full,addr_gotpageoffset,addr_gotpage])
+{$endif aarch64}
               then
               internalerror(200502052);
             typ:=top_ref;
index b764cda351c46f7d42c37ff5dd8098b08620ce88..db63e13d3334f9db1bdf4b72063312cfd6a9f38a 100644 (file)
@@ -532,6 +532,8 @@ implementation
          system_powerpc64_darwin,
          system_x86_64_darwin,
          system_arm_darwin,
+         system_aarch64_darwin,
+         system_x86_64_iphonesim,
          system_powerpc_aix,
          system_powerpc64_aix:
            begin
@@ -567,7 +569,8 @@ implementation
                     AsmWriteln('__TEXT,__picsymbolstub4,symbol_stubs,none,16')
                   else
                     AsmWriteln('__TEXT,__symbol_stub4,symbol_stubs,none,12')
-                { darwin/x86-64 uses RIP-based GOT addressing, no symbol stubs }
+                { darwin/(x86-64/AArch64) uses PC-based GOT addressing, no
+                  explicit symbol stubs }
                 else
                   internalerror(2006031101);
               end;
@@ -1352,10 +1355,6 @@ implementation
                  AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
              end;
 {$ifdef arm}
-           ait_thumb_func:
-             begin
-               AsmWriteLn(#9'.thumb_func');
-             end;
            ait_thumb_set:
              begin
                AsmWriteLn(#9'.thumb_set '+tai_thumb_set(hp).sym^+', '+tai_thumb_set(hp).value^);
index 619e24e0c5170cebb42f460de7bb9cc480586089..c875aa321e8a92b7874b5ac8c0b838e2a881ab89 100644 (file)
@@ -361,7 +361,7 @@ Unit AoptObj;
 
     function JumpTargetOp(ai: taicpu): poper; inline;
       begin
-{$ifdef MIPS}
+{$if defined(MIPS)}
         { MIPS branches can have 1,2 or 3 operands, target label is the last one. }
         result:=ai.oper[ai.ops-1];
 {$else MIPS}
@@ -1179,9 +1179,9 @@ Unit AoptObj;
     function IsJumpToLabel(hp: taicpu): boolean;
       begin
         result:=(hp.opcode=aopt_uncondjmp) and
-{$ifdef arm}
+{$if defined(arm) or defined(aarch64)}
           (hp.condition=c_None) and
-{$endif arm}
+{$endif arm or aarch64}
           (JumpTargetOp(hp)^.typ = top_ref) and
           (JumpTargetOp(hp)^.ref^.symbol is TAsmLabel);
       end;
@@ -1260,6 +1260,14 @@ Unit AoptObj;
                     exit;
                   if not GetFinalDestination(taicpu(p1),succ(level)) then
                     exit;
+{$if defined(aarch64)}
+                  { can't have conditional branches to
+                    global labels on AArch64, because the
+                    offset may become too big }
+                  if not(taicpu(hp).condition in [C_None,C_AL,C_NV]) and
+                     (tasmlabel(JumpTargetOp(taicpu(p1))^.ref^.symbol).bind<>AB_LOCAL) then
+                    exit;
+{$endif aarch64}
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).decrefs;
                   JumpTargetOp(hp)^.ref^.symbol:=JumpTargetOp(taicpu(p1))^.ref^.symbol;
                   tasmlabel(JumpTargetOp(hp)^.ref^.symbol).increfs;
@@ -1398,9 +1406,15 @@ Unit AoptObj;
                                     FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp2) then
                                   begin
                                     if (taicpu(p).opcode=aopt_condjmp)
-  {$ifdef arm}
+  {$if defined(arm) or defined(aarch64)}
                                       and (taicpu(p).condition<>C_None)
-  {$endif arm}
+  {$endif arm or aarch64}
+  {$if defined(aarch64)}
+                                      { can't have conditional branches to
+                                        global labels on AArch64, because the
+                                        offset may become too big }
+                                      and (tasmlabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).bind=AB_LOCAL)
+  {$endif aarch64}
                                     then
                                       begin
                                         taicpu(p).condition:=inverse_cond(taicpu(p).condition);
index 77ee3dc1912fd99ba6c443ae42ad6b1a491a5803..7e5d5566ba7ac0492e031d77ba930bd4752b1360 100644 (file)
@@ -30,7 +30,8 @@ uses
   aasmbase,aasmtai,aasmdata,aasmsym,
   ogbase,
   symtype,
-  cpubase,cpuinfo,cgbase,cgutils;
+  cpubase,cpuinfo,cgbase,cgutils,
+  sysutils;
 
     const
       { "mov reg,reg" source operand number }
@@ -54,7 +55,8 @@ uses
                      $00000200;
 
       OT_SIZE_MASK = $000003FF;  { all the size attributes  }
-      OT_NON_SIZE  = longint(not OT_SIZE_MASK);
+      OT_NON_SIZE  = $0FFFF800;
+      OT_OPT_SIZE  = $F0000000;
 
       OT_SIGNED    = $00000100;  { the operand need to be signed -128-127 }
 
@@ -73,6 +75,7 @@ uses
       OT_IMM80     = $00002010;
       OT_IMMTINY   = $00002100;
       OT_IMMSHIFTER= $00002200;
+      OT_IMMEDIATEZERO = $10002200;
       OT_IMMEDIATE24 = OT_IMM24;
       OT_SHIFTIMM  = OT_SHIFTEROP or OT_IMMSHIFTER;
       OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
@@ -85,9 +88,12 @@ uses
       OT_REG8      = $00201001;
       OT_REG16     = $00201002;
       OT_REG32     = $00201004;
+      OT_REGLO     = $10201004;  { lower reg (r0-r7) }
+      OT_REGSP     = $20201004;
       OT_REG64     = $00201008;
       OT_VREG      = $00201010;  { vector register }
       OT_REGF      = $00201020;  { coproc register }
+      OT_REGS      = $00201040;  { special register with mask }
       OT_MEMORY    = $00204000;  { register number in 'basereg'  }
       OT_MEM8      = $00204001;
       OT_MEM16     = $00204002;
@@ -96,20 +102,24 @@ uses
       OT_MEM80     = $00204010;
       { word/byte load/store }
       OT_AM2       = $00010000;
-      { misc ld/st operations }
+      { misc ld/st operations, thumb reg indexed }
       OT_AM3       = $00020000;
-      { multiple ld/st operations }
+      { multiple ld/st operations or thumb imm indexed }
       OT_AM4       = $00040000;
-      { co proc. ld/st operations }
+      { co proc. ld/st operations or thumb sp+imm indexed }
       OT_AM5       = $00080000;
-      OT_AMMASK    = $000f0000;
+      { exclusive ld/st operations or thumb pc+imm indexed }
+      OT_AM6       = $00100000;
+      OT_AMMASK    = $001f0000;
       { IT instruction }
-      OT_CONDITION = $00100000;
+      OT_CONDITION = $00200000;
+      OT_MODEFLAGS = $00400000;
 
       OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
       OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
       OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
       OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
+      OT_MEMORYAM6 = OT_MEMORY or OT_AM6;
 
       OT_FPUREG    = $01000000;  { floating point stack registers  }
       OT_REG_SMASK = $00070000;  { special register operands: these may be treated differently  }
@@ -128,9 +138,34 @@ uses
       IF_NONE   = $00000000;
 
       IF_ARMMASK    = $000F0000;
-      IF_ARM7       = $00070000;
-      IF_FPMASK     = $00F00000;
-      IF_FPA        = $00100000;
+      IF_ARM32      = $00010000;
+      IF_THUMB      = $00020000;
+      IF_THUMB32    = $00040000;
+      IF_WIDE       = $00080000;
+
+      IF_ARMvMASK   = $0FF00000;
+      IF_ARMv4      = $00100000;
+      IF_ARMv4T     = $00200000;
+      IF_ARMv5      = $00300000;
+      IF_ARMv5T     = $00400000;
+      IF_ARMv5TE    = $00500000;
+      IF_ARMv5TEJ   = $00600000;
+      IF_ARMv6      = $00700000;
+      IF_ARMv6K     = $00800000;
+      IF_ARMv6T2    = $00900000;
+      IF_ARMv6Z     = $00A00000;
+      IF_ARMv6M     = $00B00000;
+      IF_ARMv7      = $00C00000;
+      IF_ARMv7A     = $00D00000;
+      IF_ARMv7R     = $00E00000;
+      IF_ARMv7M     = $00F00000;
+      IF_ARMv7EM    = $01000000;
+
+      IF_FPMASK     = $F0000000;
+      IF_FPA        = $10000000;
+      IF_VFPv2      = $20000000;
+      IF_VFPv3      = $40000000;
+      IF_VFPv4      = $80000000;
 
       { if the instruction can change in a second pass }
       IF_PASS2  = longint($80000000);
@@ -142,9 +177,9 @@ uses
       tinsentry = record
         opcode  : tasmop;
         ops     : byte;
-        optypes : array[0..3] of longint;
+        optypes : array[0..5] of longint;
         code    : array[0..maxinfolen] of char;
-        flags   : longint;
+        flags   : longword;
       end;
 
       pinsentry=^tinsentry;
@@ -228,11 +263,18 @@ uses
          procedure ppubuildderefimploper(var o:toper);override;
          procedure ppuderefoper(var o:toper);override;
       private
+         { pass1 info }
+         inIT,
+         lastinIT: boolean;
+         { arm version info }
+         fArmVMask,
+         fArmMask  : longint;
          { next fields are filled in pass1, so pass2 is faster }
          inssize   : shortint;
          insoffset : longint;
          LastInsOffset : longint; { need to be public to be reset }
          insentry  : PInsEntry;
+         procedure BuildArmMasks;
          function  InsEnd:longint;
          procedure create_ot(objdata:TObjData);
          function  Matches(p:PInsEntry):longint;
@@ -247,10 +289,6 @@ uses
         { nothing to add }
       end;
 
-      tai_thumb_func = class(tai)
-        constructor create;
-      end;
-
     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
 
@@ -614,9 +652,10 @@ implementation
         result:=(
                   ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
                   ((opcode=A_MVF) and (regtype = R_FPUREGISTER)) or
-                  ((opcode in [A_FCPYS, A_FCPYD]) and (regtype = R_MMREGISTER))
+                  ((opcode in [A_FCPYS, A_FCPYD]) and (regtype = R_MMREGISTER)) or
+                  ((opcode in [A_VMOV]) and (regtype = R_MMREGISTER) and (oppostfix in [PF_F32,PF_F64]))
                 ) and
-                (oppostfix in [PF_None,PF_D]) and
+                ((oppostfix in [PF_None,PF_D]) or (opcode = A_VMOV)) and
                 (condition=C_None) and
                 (ops=2) and
                 (oper[0]^.typ=top_reg) and
@@ -626,8 +665,6 @@ implementation
 
 
     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
-      var
-        op: tasmop;
       begin
         case getregtype(r) of
           R_INTREGISTER :
@@ -638,19 +675,7 @@ implementation
             }
             result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
           R_MMREGISTER :
-            begin
-              case getsubreg(r) of
-                R_SUBFD:
-                  op:=A_FLDD;
-                R_SUBFS:
-                  op:=A_FLDS;
-                R_SUBNONE:
-                  op:=A_VLDR;
-                else
-                  internalerror(2009112905);
-              end;
-              result:=taicpu.op_reg_ref(op,r,ref);
-            end;
+            result:=taicpu.op_reg_ref(A_VLDR,r,ref);
           else
             internalerror(200401041);
         end;
@@ -658,8 +683,6 @@ implementation
 
 
     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
-      var
-        op: tasmop;
       begin
         case getregtype(r) of
           R_INTREGISTER :
@@ -670,19 +693,7 @@ implementation
             }
             result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
           R_MMREGISTER :
-            begin
-              case getsubreg(r) of
-                R_SUBFD:
-                  op:=A_FSTD;
-                R_SUBFS:
-                  op:=A_FSTS;
-                R_SUBNONE:
-                  op:=A_VSTR;
-                else
-                  internalerror(2009112904);
-              end;
-              result:=taicpu.op_reg_ref(op,r,ref);
-            end;
+            result:=taicpu.op_reg_ref(A_VSTR,r,ref);
           else
             internalerror(200401041);
         end;
@@ -1302,6 +1313,41 @@ implementation
                 end;
             end;
 
+            curtai:=tai(curtai.Next);
+          end;
+      end;
+
+
+    procedure ensurethumbencodings(list: TAsmList);
+      var
+        curtai: tai;
+        op2reg: TRegister;
+      begin
+        { Do Thumb 16bit transformations to form valid instruction forms }
+        curtai:=tai(list.first);
+        while assigned(curtai) do
+          begin
+            case curtai.typ of
+              ait_instruction:
+                begin
+                  case taicpu(curtai).opcode of
+                    A_ADD,
+                    A_AND,A_EOR,A_ORR,A_BIC,
+                    A_LSL,A_LSR,A_ASR,A_ROR,
+                    A_ADC,A_SBC:
+                      begin
+                        if (taicpu(curtai).ops = 3) and
+                           (taicpu(curtai).oper[2]^.typ=top_reg) and
+                           (taicpu(curtai).oper[0]^.reg=taicpu(curtai).oper[1]^.reg) and
+                           (taicpu(curtai).oper[0]^.reg<>NR_STACK_POINTER_REG) then
+                          begin
+                            taicpu(curtai).oper[1]^.reg:=taicpu(curtai).oper[2]^.reg;
+                            taicpu(curtai).ops:=2;
+                          end;
+                      end;
+                  end;
+                end;
+            end;
 
             curtai:=tai(curtai.Next);
           end;
@@ -1401,14 +1447,175 @@ implementation
           end;
       end;
 
+    procedure fix_invalid_imms(list: TAsmList);
+      var
+        curtai: tai;
+        sh: byte;
+      begin
+        curtai:=tai(list.First);
+        while assigned(curtai) do
+          begin
+            case curtai.typ of
+              ait_instruction:
+                begin
+                  if (taicpu(curtai).opcode in [A_AND,A_BIC]) and
+                     (taicpu(curtai).ops=3) and
+                     (taicpu(curtai).oper[2]^.typ=top_const) and
+                     (not is_shifter_const(taicpu(curtai).oper[2]^.val,sh)) and
+                     is_shifter_const((not taicpu(curtai).oper[2]^.val) and $FFFFFFFF,sh) then
+                    begin
+                      case taicpu(curtai).opcode of
+                        A_AND: taicpu(curtai).opcode:=A_BIC;
+                        A_BIC: taicpu(curtai).opcode:=A_AND;
+                      end;
+                      taicpu(curtai).oper[2]^.val:=(not taicpu(curtai).oper[2]^.val) and $FFFFFFFF;
+                    end
+                  else if (taicpu(curtai).opcode in [A_SUB,A_ADD]) and
+                     (taicpu(curtai).ops=3) and
+                     (taicpu(curtai).oper[2]^.typ=top_const) and
+                     (not is_shifter_const(taicpu(curtai).oper[2]^.val,sh)) and
+                     is_shifter_const(-taicpu(curtai).oper[2]^.val,sh) then
+                    begin
+                      case taicpu(curtai).opcode of
+                        A_ADD: taicpu(curtai).opcode:=A_SUB;
+                        A_SUB: taicpu(curtai).opcode:=A_ADD;
+                      end;
+                      taicpu(curtai).oper[2]^.val:=-taicpu(curtai).oper[2]^.val;
+                    end;
+                end;
+            end;
+
+            curtai:=tai(curtai.Next);
+          end;
+      end;
+
+
+    procedure gather_it_info(list: TAsmList);
+      var
+        curtai: tai;
+        in_it: boolean;
+        it_count: longint;
+      begin
+        in_it:=false;
+        it_count:=0;
+
+        curtai:=tai(list.First);
+        while assigned(curtai) do
+          begin
+            case curtai.typ of
+              ait_instruction:
+                begin
+                  case taicpu(curtai).opcode of
+                    A_IT..A_ITTTT:
+                      begin
+                        if in_it then
+                          Message1(asmw_e_invalid_opcode_and_operands, 'ITxx instruction is inside another ITxx instruction')
+                        else
+                          begin
+                            in_it:=true;
+                            it_count:=GetITLevels(taicpu(curtai).opcode);
+                          end;
+                      end;
+                    else
+                      begin
+                        taicpu(curtai).inIT:=in_it;
+                        taicpu(curtai).lastinIT:=in_it and (it_count=1);
+
+                        if in_it then
+                          begin
+                            dec(it_count);
+                            if it_count <= 0 then
+                              in_it:=false;
+                          end;
+                      end;
+                  end;
+                end;
+            end;
+
+            curtai:=tai(curtai.Next);
+          end;
+      end;
+
+
+    { Expands pseudo instructions ( mov r1,r2,lsl #4 -> lsl r1,r2,#4) }
+    procedure expand_instructions(list: TAsmList);
+      var
+        curtai: tai;
+      begin
+        curtai:=tai(list.First);
+        while assigned(curtai) do
+          begin
+            case curtai.typ of
+              ait_instruction:
+                begin
+                  case taicpu(curtai).opcode of
+                    A_MOV:
+                      begin
+                        if (taicpu(curtai).ops=3) and
+                           (taicpu(curtai).oper[2]^.typ=top_shifterop) then
+                          begin
+                            case taicpu(curtai).oper[2]^.shifterop^.shiftmode of
+                              SM_LSL: taicpu(curtai).opcode:=A_LSL;
+                              SM_LSR: taicpu(curtai).opcode:=A_LSR;
+                              SM_ASR: taicpu(curtai).opcode:=A_ASR;
+                              SM_ROR: taicpu(curtai).opcode:=A_ROR;
+                              SM_RRX: taicpu(curtai).opcode:=A_RRX;
+                            end;
+
+                            if taicpu(curtai).oper[2]^.shifterop^.shiftmode=SM_RRX then
+                              taicpu(curtai).ops:=2;
+
+                            if taicpu(curtai).oper[2]^.shifterop^.rs=NR_NO then
+                              taicpu(curtai).loadconst(2, taicpu(curtai).oper[2]^.shifterop^.shiftimm)
+                            else
+                              taicpu(curtai).loadreg(2, taicpu(curtai).oper[2]^.shifterop^.rs);
+                          end;
+                      end;
+                    A_NEG:
+                      begin
+                        taicpu(curtai).opcode:=A_RSB;
+
+                        if taicpu(curtai).ops=2 then
+                          begin
+                            taicpu(curtai).loadconst(2,0);
+                            taicpu(curtai).ops:=3;
+                          end
+                        else
+                          begin
+                            taicpu(curtai).loadconst(1,0);
+                            taicpu(curtai).ops:=2;
+                          end;
+                      end;
+                    A_SWI:
+                      begin
+                        taicpu(curtai).opcode:=A_SVC;
+                      end;
+                  end;
+                end;
+            end;
+
+            curtai:=tai(curtai.Next);
+          end;
+      end;
+
+
     procedure finalizearmcode(list, listtoinsert: TAsmList);
       begin
+        expand_instructions(list);
+
         { Do Thumb-2 16bit -> 32bit transformations }
         if GenerateThumb2Code then
           begin
+            ensurethumbencodings(list);
             ensurethumb2encodings(list);
             foldITInstructions(list);
-          end;
+          end
+        else if GenerateThumbCode then
+          ensurethumbencodings(list);
+
+        gather_it_info(list);
+
+        fix_invalid_imms(list);
 
         insertpcrelativedata(list, listtoinsert);
       end;
@@ -1604,6 +1811,12 @@ implementation
                else
                  if (ot and OT_FPUREG)=OT_FPUREG then
                   s:=s+'fpureg'
+               else
+                 if (ot and OT_REGS)=OT_REGS then
+                  s:=s+'sreg'
+               else
+                 if (ot and OT_REGF)=OT_REGF then
+                  s:=s+'creg'
                else
                 if (ot and OT_REGISTER)=OT_REGISTER then
                  begin
@@ -1628,9 +1841,17 @@ implementation
                    s:=s+'mem';
                    addsize:=true;
                    if (ot and OT_AM2)<>0 then
+                     s:=s+' am2 '
+                   else if (ot and OT_AM6)<>0 then
                      s:=s+' am2 ';
                  end
                else
+                 if (ot and OT_SHIFTEROP)=OT_SHIFTEROP then
+                  begin
+                    s:=s+'shifterop';
+                    addsize:=false;
+                  end
+                else
                  s:=s+'???';
                { size }
                if addsize then
@@ -1705,7 +1926,12 @@ implementation
         current_filepos:=fileinfo;
 
         { tranlate LDR+postfix to complete opcode }
-        if (opcode=A_LDR) and (oppostfix<>PF_None) then
+        if (opcode=A_LDR) and (oppostfix=PF_D) then
+          begin
+            opcode:=A_LDRD;
+            oppostfix:=PF_None;
+          end
+        else if (opcode=A_LDR) and (oppostfix<>PF_None) then
           begin
             if (oppostfix in [low(ldr2op)..high(ldr2op)]) then
               opcode:=ldr2op[oppostfix]
@@ -1716,6 +1942,11 @@ implementation
             { postfix has been added to opcode }
             oppostfix:=PF_None;
           end
+        else if (opcode=A_STR) and (oppostfix=PF_D) then
+          begin
+            opcode:=A_STRD;
+            oppostfix:=PF_None;
+          end
         else if (opcode=A_STR) and (oppostfix<>PF_None) then
           begin
             if (oppostfix in [low(str2op)..high(str2op)]) then
@@ -1771,6 +2002,58 @@ implementation
       end;
 
 
+    procedure taicpu.BuildArmMasks;
+      const
+        Masks: array[tcputype] of longint =
+          (
+            IF_NONE,
+            IF_ARMv4,
+            IF_ARMv4,
+            IF_ARMv4T or IF_ARMv4,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z,
+            IF_ARMv4T or IF_ARMv5T or IF_ARMv6M,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7 or IF_ARMv7A,
+            IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7 or IF_ARMv7A or IF_ARMv7R,
+            IF_ARMv4T or IF_ARMv5T or IF_ARMv6T2 or IF_ARMv7M,
+            IF_ARMv4T or IF_ARMv5T or IF_ARMv6T2 or IF_ARMv7M or IF_ARMv7EM
+          );
+
+        FPUMasks: array[tfputype] of longword =
+          (
+            IF_NONE,
+            IF_NONE,
+            IF_NONE,
+            IF_FPA,
+            IF_FPA,
+            IF_FPA,
+            IF_VFPv2,
+            IF_VFPv2 or IF_VFPv3,
+            IF_VFPv2 or IF_VFPv3,
+            IF_NONE,
+            IF_VFPv2 or IF_VFPv3 or IF_VFPv4
+          );
+      begin
+        fArmVMask:=Masks[current_settings.cputype] or FPUMasks[current_settings.fputype];
+
+        if current_settings.instructionset=is_thumb then
+          begin
+            fArmMask:=IF_THUMB;
+            if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then
+             fArmMask:=fArmMask or IF_THUMB32;
+          end
+        else
+          fArmMask:=IF_ARM32;
+      end;
+
+
     function  taicpu.InsEnd:longint;
       begin
         Result:=0; { unimplemented }
@@ -1798,9 +2081,19 @@ implementation
                 begin
                   case getregtype(reg) of
                     R_INTREGISTER:
-                      ot:=OT_REG32 or OT_SHIFTEROP;
+                      begin
+                        ot:=OT_REG32 or OT_SHIFTEROP;
+                        if getsupreg(reg)<8 then
+                          ot:=ot or OT_REGLO
+                        else if reg=NR_STACK_POINTER_REG then
+                          ot:=ot or OT_REGSP;
+                      end;
                     R_FPUREGISTER:
                       ot:=OT_FPUREG;
+                    R_MMREGISTER:
+                      ot:=OT_VREG;
+                    R_SPECIALREGISTER:
+                      ot:=OT_REGF;
                     else
                       internalerror(2005090901);
                   end;
@@ -1831,7 +2124,30 @@ implementation
                         ref^.base:=NR_PC;
 
                       { determine possible address modes }
+                      if GenerateThumbCode or
+                         GenerateThumb2Code then
+                        begin
+                          if (ref^.base=NR_PC) then
+                            ot:=ot or OT_AM6
+                          else if (ref^.base=NR_STACK_POINTER_REG) then
+                            ot:=ot or OT_AM5
+                          else if ref^.index=NR_NO then
+                            ot:=ot or OT_AM4
+                          else
+                            ot:=ot or OT_AM3;
+                        end;
+
                       if (ref^.base<>NR_NO) and
+                        (opcode in [A_LDREX,A_LDREXB,A_LDREXH,A_LDREXD,
+                                    A_STREX,A_STREXB,A_STREXH,A_STREXD]) and
+                        (
+                          (ref^.addressmode=AM_OFFSET) and
+                          (ref^.index=NR_NO) and
+                          (ref^.shiftmode=SM_None) and
+                          (ref^.offset=0)
+                        ) then
+                        ot:=ot or OT_AM6
+                      else if (ref^.base<>NR_NO) and
                         (
                           (
                             (ref^.index=NR_NO) and
@@ -1846,14 +2162,17 @@ implementation
                           (
                             (ref^.index<>NR_NO) and
                             (ref^.shiftmode<>SM_None) and
-                            (ref^.shiftimm<=31) and
+                            (ref^.shiftimm<=32) and
                             (ref^.offset=0)
                           )
                         ) then
                         ot:=ot or OT_AM2;
 
                       if (ref^.index<>NR_NO) and
-                        (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
+                        (oppostfix in [PF_None,PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
+                                       PF_IAD,PF_DBD,PF_FDD,PF_EAD,
+                                       PF_IAS,PF_DBS,PF_FDS,PF_EAS,
+                                       PF_IAX,PF_DBX,PF_FDX,PF_EAX]) and
                         (
                           (ref^.base=NR_NO) and
                           (ref^.shiftmode=SM_None) and
@@ -1887,7 +2206,11 @@ implementation
               top_const :
                 begin
                   ot:=OT_IMMEDIATE;
-                  if is_shifter_const(val,dummy) then
+                  if (val=0) then
+                    ot:=ot_immediatezero
+                  else if is_shifter_const(val,dummy) then
+                    ot:=OT_IMMSHIFTER
+                  else if GenerateThumb2Code and is_thumb32_imm(val) then
                     ot:=OT_IMMSHIFTER
                   else
                     ot:=OT_IMM32
@@ -1902,6 +2225,18 @@ implementation
                 begin
                   ot:=OT_SHIFTEROP;
                 end;
+              top_conditioncode:
+                begin
+                  ot:=OT_CONDITION;
+                end;
+              top_specialreg:
+                begin
+                  ot:=OT_REGS;
+                end;
+              top_modeflags:
+                begin
+                  ot:=OT_MODEFLAGS;
+                end;
               else
                 internalerror(2004022623);
             end;
@@ -1935,7 +2270,6 @@ implementation
         {siz : array[0..3] of longint;}
       begin
         Matches:=100;
-        writeln(getstring,'---');
 
         { Check the opcode and operands }
         if (p^.opcode<>opcode) or (p^.ops<>ops) then
@@ -1944,6 +2278,27 @@ implementation
            exit;
          end;
 
+        { check ARM instruction version }
+        if (p^.flags and fArmVMask)=0 then
+          begin
+            Matches:=0;
+            exit;
+          end;
+
+        { check ARM instruction type }
+        if (p^.flags and fArmMask)=0 then
+          begin
+            Matches:=0;
+            exit;
+          end;
+
+        { Check wideformat flag }
+        if wideformat and ((p^.flags and IF_WIDE)=0) then
+          begin
+            matches:=0;
+            exit;
+          end;
+
         { Check that no spurious colons or TOs are present }
         for i:=0 to p^.ops-1 do
          if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
@@ -1965,6 +2320,12 @@ implementation
                  Matches:=0;
                  exit;
                end
+              else if ((p^.optypes[i] and OT_OPT_SIZE)<>0) and
+                       ((p^.optypes[i] and OT_OPT_SIZE)<>(oper[i]^.ot and OT_OPT_SIZE)) then
+               begin
+                 Matches:=0;
+                 exit;
+               end
               else
                Matches:=1;
             end;
@@ -1977,7 +2338,7 @@ implementation
         { update condition flags
           or floating point single }
       if (oppostfix=PF_S) and
-        not(p^.code[0] in [#$04]) then
+        not(p^.code[0] in [#$04..#$0F,#$14..#$16,#$29,#$30,#$60..#$6B,#$80..#$82,#$A0..#$A2,#$44,#$94,#$42,#$92]) then
         begin
           Matches:=0;
           exit;
@@ -1985,7 +2346,13 @@ implementation
 
       { floating point size }
       if (oppostfix in [PF_D,PF_E,PF_P,PF_EP]) and
-        not(p^.code[0] in []) then
+        not(p^.code[0] in [
+          // FPA
+          #$A0..#$A2,
+          // old-school VFP
+          #$42,#$92,
+          // vldm/vstm
+          #$44,#$94]) then
         begin
           Matches:=0;
           exit;
@@ -1997,7 +2364,9 @@ implementation
           // ldr,str,ldrb,strb
           #$17,
           // stm,ldm
-          #$26
+          #$26,#$69,#$8C,
+          // vldm/vstm
+          #$44,#$94
         ]) then
         begin
           Matches:=0;
@@ -2017,6 +2386,57 @@ implementation
           exit;
         end;
 
+      { Check thumb flags }
+      if p^.code[0] in [#$60..#$61] then
+        begin
+          if (p^.code[0]=#$60) and
+             (GenerateThumb2Code and
+              ((not inIT) and (oppostfix<>PF_S)) or
+              (inIT and (condition=C_None))) then
+            begin
+              Matches:=0;
+              exit;
+            end
+          else if (p^.code[0]=#$61) and
+             (oppostfix=PF_S) then
+            begin
+              Matches:=0;
+              exit;
+            end;
+        end
+      else if p^.code[0]=#$62 then
+        begin
+          if (GenerateThumb2Code and
+              (condition<>C_None) and
+              (not inIT) and
+              (not lastinIT)) then
+            begin
+              Matches:=0;
+              exit;
+            end;
+        end
+      else if p^.code[0]=#$63 then
+        begin
+          if inIT then
+            begin
+              Matches:=0;
+              exit;
+            end;
+        end
+      else if p^.code[0]=#$64 then
+        begin
+          if (opcode=A_MUL) then
+            begin
+              if (ops=3) and
+                 ((oper[2]^.typ<>top_reg) or
+                  (oper[0]^.reg<>oper[2]^.reg)) then
+                begin
+                  matches:=0;
+                  exit;
+                end;
+            end;
+        end;
+
       { Check operand sizes }
         { as default an untyped size can get all the sizes, this is different
           from nasm, but else we need to do a lot checking which opcodes want
@@ -2112,6 +2532,8 @@ implementation
          begin
            { create the .ot fields }
            create_ot(objdata);
+
+           BuildArmMasks;
            { set the file postion }
            current_filepos:=fileinfo;
          end
@@ -2148,1013 +2570,2895 @@ implementation
 
 
     procedure taicpu.gencode(objdata:TObjData);
+      const
+        CondVal : array[TAsmCond] of byte=(
+         $E, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $A,
+         $B, $C, $D, $E, 0);
       var
-        bytes : dword;
+        bytes, rd, rm, rn, d, m, n : dword;
+        bytelen : longint;
+        dp_operation : boolean;
         i_field : byte;
+        currsym : TObjSymbol;
+        offset : longint;
+        refoper : poper;
+        msb : longint;
+        r: byte;
 
       procedure setshifterop(op : byte);
+        var
+          r : byte;
+          imm : dword;
+          count : integer;
         begin
           case oper[op]^.typ of
             top_const:
               begin
                 i_field:=1;
-                bytes:=bytes or dword(oper[op]^.val and $fff);
+                if oper[op]^.val and $ff=oper[op]^.val then
+                  bytes:=bytes or dword(oper[op]^.val)
+                else
+                  begin
+                    { calc rotate and adjust imm }
+                    count:=0;
+                    r:=0;
+                    imm:=dword(oper[op]^.val);
+                    repeat
+                      imm:=RolDWord(imm, 2);
+                      inc(r);
+                      inc(count);
+                      if count > 32 then
+                        begin
+                          message1(asmw_e_invalid_opcode_and_operands, 'invalid shifter imm');
+                          exit;
+                        end;
+                    until (imm and $ff)=imm;
+                    bytes:=bytes or (r shl 8) or imm;
+                  end;
               end;
             top_reg:
               begin
                 i_field:=0;
-                bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
+                bytes:=bytes or getsupreg(oper[op]^.reg);
 
                 { does a real shifter op follow? }
-                if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
-                  begin
-                  end;
+                if (op+1<opercnt) and (oper[op+1]^.typ=top_shifterop) then
+                  with oper[op+1]^.shifterop^ do
+                    begin
+                      bytes:=bytes or ((shiftimm and $1F) shl 7);
+                      if shiftmode<>SM_RRX then
+                        bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+                      else
+                        bytes:=bytes or (3 shl 5);
+                      if getregtype(rs) <> R_INVALIDREGISTER then
+                        begin
+                          bytes:=bytes or (1 shl 4);
+                          bytes:=bytes or (getsupreg(rs) shl 8);
+                        end
+                    end;
               end;
           else
             internalerror(2005091103);
           end;
         end;
 
-      begin
-        bytes:=$0;
-        i_field:=0;
-        { evaluate and set condition code }
-
-        { condition code allowed? }
-
-        { setup rest of the instruction }
-        case insentry^.code[0] of
-          #$08:
+      function MakeRegList(reglist: tcpuregisterset): word;
+        var
+          i, w: word;
+        begin
+          result:=0;
+          w:=1;
+          for i:=RS_R0 to RS_R15 do
             begin
-              { set instruction code }
-              bytes:=bytes or (ord(insentry^.code[1]) shl 26);
-              bytes:=bytes or (ord(insentry^.code[2]) shl 21);
-
-              { set destination }
-              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
-
-              { create shifter op }
-              setshifterop(1);
-
-              { set i field }
-              bytes:=bytes or (i_field shl 25);
-
-              { set s if necessary }
-              if oppostfix=PF_S then
-                bytes:=bytes or (1 shl 20);
+              if i in reglist then
+                result:=result or w;
+              w:=w shl 1
             end;
-          #$ff:
-            internalerror(2005091101);
+        end;
+
+      function getcoproc(reg: tregister): byte;
+        begin
+          if reg=NR_p15 then
+            result:=15
           else
-            internalerror(2005091102);
+            begin
+              Message1(asmw_e_invalid_opcode_and_operands,'Invalid coprocessor port');
+              result:=0;
+            end;
         end;
-        { we're finished, write code }
-        objdata.writebytes(bytes,sizeof(bytes));
-      end;
 
+      function getcoprocreg(reg: tregister): byte;
+        begin
+          result:=getsupreg(reg)-getsupreg(NR_CR0);
+        end;
 
-{$ifdef dummy}
-(*
-static void gencode (long segment, long offset, int bits,
-                     insn *ins, char *codes, long insn_end)
-{
-    int has_S_code;             /* S - setflag */
-    int has_B_code;             /* B - setflag */
-    int has_T_code;             /* T - setflag */
-    int has_W_code;             /* ! => W flag */
-    int has_F_code;             /* ^ => S flag */
-    int keep;
-    unsigned char c;
-    unsigned char bytes[4];
-    long          data, size;
-    static int cc_code[] =      /* bit pattern of cc */
-  {                             /* order as enum in  */
-    0x0E, 0x03, 0x02, 0x00,     /* nasm.h            */
-    0x0A, 0x0C, 0x08, 0x0D,
-    0x09, 0x0B, 0x04, 0x01,
-    0x05, 0x07, 0x06,
-  };
-
-
-#ifdef DEBUG
-static char *CC[] =
-  {                                    /* condition code names */
-    "AL", "CC", "CS", "EQ",
-    "GE", "GT", "HI", "LE",
-    "LS", "LT", "MI", "NE",
-    "PL", "VC", "VS", "",
-    "S"
-};
-
-
-    has_S_code = (ins->condition & C_SSETFLAG);
-    has_B_code = (ins->condition & C_BSETFLAG);
-    has_T_code = (ins->condition & C_TSETFLAG);
-    has_W_code = (ins->condition & C_EXSETFLAG);
-    has_F_code = (ins->condition & C_FSETFLAG);
-    ins->condition = (ins->condition & 0x0F);
-
-
-    if (rt_debug)
-      {
-    printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
-            CC[ins->condition & 0x0F]);
-    if (has_S_code)
-      printf ("S");
-    if (has_B_code)
-      printf ("B");
-    if (has_T_code)
-      printf ("T");
-    if (has_W_code)
-      printf ("!");
-    if (has_F_code)
-      printf ("^");
-
-    printf ("\n");
-
-    c = *codes;
-
-    printf ("   (%d)  decode - '0x%02X'\n", ins->operands, c);
-
-
-    bytes[0] = 0xB;
-    bytes[1] = 0xE;
-    bytes[2] = 0xE;
-    bytes[3] = 0xF;
-      }
+      function getmmreg(reg: tregister): byte;
+        begin
+          case reg of
+            NR_D0: result:=0;
+            NR_D1: result:=1;
+            NR_D2: result:=2;
+            NR_D3: result:=3;
+            NR_D4: result:=4;
+            NR_D5: result:=5;
+            NR_D6: result:=6;
+            NR_D7: result:=7;
+            NR_D8: result:=8;
+            NR_D9: result:=9;
+            NR_D10: result:=10;
+            NR_D11: result:=11;
+            NR_D12: result:=12;
+            NR_D13: result:=13;
+            NR_D14: result:=14;
+            NR_D15: result:=15;
+            NR_D16: result:=16;
+            NR_D17: result:=17;
+            NR_D18: result:=18;
+            NR_D19: result:=19;
+            NR_D20: result:=20;
+            NR_D21: result:=21;
+            NR_D22: result:=22;
+            NR_D23: result:=23;
+            NR_D24: result:=24;
+            NR_D25: result:=25;
+            NR_D26: result:=26;
+            NR_D27: result:=27;
+            NR_D28: result:=28;
+            NR_D29: result:=29;
+            NR_D30: result:=30;
+            NR_D31: result:=31;
+
+            NR_S0: result:=0;
+            NR_S1: result:=1;
+            NR_S2: result:=2;
+            NR_S3: result:=3;
+            NR_S4: result:=4;
+            NR_S5: result:=5;
+            NR_S6: result:=6;
+            NR_S7: result:=7;
+            NR_S8: result:=8;
+            NR_S9: result:=9;
+            NR_S10: result:=10;
+            NR_S11: result:=11;
+            NR_S12: result:=12;
+            NR_S13: result:=13;
+            NR_S14: result:=14;
+            NR_S15: result:=15;
+            NR_S16: result:=16;
+            NR_S17: result:=17;
+            NR_S18: result:=18;
+            NR_S19: result:=19;
+            NR_S20: result:=20;
+            NR_S21: result:=21;
+            NR_S22: result:=22;
+            NR_S23: result:=23;
+            NR_S24: result:=24;
+            NR_S25: result:=25;
+            NR_S26: result:=26;
+            NR_S27: result:=27;
+            NR_S28: result:=28;
+            NR_S29: result:=29;
+            NR_S30: result:=30;
+            NR_S31: result:=31;
+          else
+            result:=0;
+          end;
+        end;
 
-    // First condition code in upper nibble
-    if (ins->condition < C_NONE)
-      {
-        c = cc_code[ins->condition] << 4;
-      }
-    else
-      {
-        c = cc_code[C_AL] << 4; // is often ALWAYS but not always
-      }
+      procedure encodethumbimm(imm: longword);
+        var
+          imm12, tmp: tcgint;
+          shift: integer;
+          found: boolean;
+        begin
+          found:=true;
+          if (imm and $FF) = imm then
+            imm12:=imm
+          else if ((imm shr 16)=(imm and $FFFF)) and
+                  ((imm and $FF00FF00) = 0) then
+            imm12:=(imm and $ff) or ($1 shl 8)
+          else if ((imm shr 16)=(imm and $FFFF)) and
+                  ((imm and $00FF00FF) = 0) then
+            imm12:=((imm shr 8) and $ff) or ($2 shl 8)
+          else if ((imm shr 16)=(imm and $FFFF)) and
+                  (((imm shr 8) and $FF)=(imm and $FF)) then
+            imm12:=(imm and $ff) or ($3 shl 8)
+          else
+            begin
+              found:=false;
+              imm12:=0;
+              for shift:=1 to 31 do
+                begin
+                  tmp:=RolDWord(imm,shift);
+                  if ((tmp and $FF)=tmp) and
+                     ((tmp and $80)=$80) then
+                    begin
+                      imm12:=(tmp and $7F) or (shift shl 7);
+                      found:=true;
+                      break;
+                    end;
+                end;
+            end;
 
+          if found then
+            begin
+              bytes:=bytes or (imm12 and $FF);
+              bytes:=bytes or (((imm12 shr 8) and $7) shl 12);
+              bytes:=bytes or (((imm12 shr 11) and $1) shl 26);
+            end
+          else
+            Message1(asmw_e_value_exceeds_bounds, IntToStr(imm));
+        end;
 
-    switch (keep = *codes)
-      {
-        case 1:
-          // B, BL
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
+      procedure setthumbshift(op: byte; is_sat: boolean = false);
+        var
+          shift,typ: byte;
+        begin
+          shift:=0;
+          typ:=0;
+          case oper[op]^.shifterop^.shiftmode of
+            SM_LSL: begin typ:=0; shift:=oper[op]^.shifterop^.shiftimm; end;
+            SM_LSR: begin typ:=1; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
+            SM_ASR: begin typ:=2; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
+            SM_ROR: begin typ:=3; shift:=oper[op]^.shifterop^.shiftimm; if shift=0 then message(asmw_e_invalid_opcode_and_operands); end;
+            SM_RRX: begin typ:=3; shift:=0; end;
+          end;
 
-          if (ins->oprs[0].segment != segment)
-            {
-              // fais une relocation
-              c = 1;
-              data = 0; // Let the linker locate ??
-            }
+          if is_sat then
+            begin
+              bytes:=bytes or ((typ and 1) shl 5);
+              bytes:=bytes or ((typ shr 1) shl 21);
+            end
           else
-            {
-              c = 0;
-              data = ins->oprs[0].offset - (offset + 8);
-
-              if (data % 4)
-                {
-                  errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
-                }
-            }
+            bytes:=bytes or (typ shl 4);
+          bytes:=bytes or (shift and $3) shl 6;
+          bytes:=bytes or ((shift and $1C) shr 2) shl 12;
+        end;
 
-          if (data >= 0x1000)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
+      begin
+        bytes:=$0;
+        bytelen:=4;
+        i_field:=0;
+        { evaluate and set condition code }
+        bytes:=bytes or (CondVal[condition] shl 28);
 
-          data = data >> 2;
-          bytes[1] = (data >> 16) & 0xFF;
-          bytes[2] = (data >> 8)  & 0xFF;
-          bytes[3] = (data )      & 0xFF;
+        { condition code allowed? }
 
-          if (c == 1)
-            {
-//            out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
-              out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
-            }
-          else
-            {
-              out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
-            }
-          return;
-
-        case 2:
-          // SWI
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-          data = ins->oprs[0].offset;
-          bytes[1] = (data >> 16) & 0xFF;
-          bytes[2] = (data >> 8) & 0xFF;
-          bytes[3] = (data) & 0xFF;
-          out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-        case 3:
-          // BX
-          ++codes;
-          c |= *codes++;
-          bytes[0] = c;
-          bytes[1] = *codes++;
-          bytes[2] = *codes++;
-          bytes[3] = *codes++;
-          c = regval (&ins->oprs[0],1);
-          if (c == 15)  // PC
-            {
-              errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
-            }
-          else if (c > 15)
-            {
-              errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
-            }
+        { setup rest of the instruction }
+        case insentry^.code[0] of
+          #$01: // B/BL
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              { set offset }
+              if oper[0]^.typ=top_const then
+                bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
+              else
+                begin
+                  currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+                  if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+                    begin
+                      objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24);
+                      bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
+                    end
+                  else
+                    bytes:=bytes or (((currsym.offset-insoffset-8) shr 2) and $ffffff);
+                end;
+            end;
+          #$02:
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              { set code }
+              bytes:=bytes or (oper[0]^.val and $FFFFFF);
+            end;
+          #$03:
+            begin // BLX/BX
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+
+              bytes:=bytes or getsupreg(oper[0]^.reg);
+            end;
+          #$04..#$07: // SUB
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              { set Rn }
+              bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+              { create shifter op }
+              setshifterop(2);
+              { set I field }
+              bytes:=bytes or (i_field shl 25);
+              { set S if necessary }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$08,#$0A,#$0B: // MOV
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              { create shifter op }
+              setshifterop(1);
+              { set I field }
+              bytes:=bytes or (i_field shl 25);
+              { set S if necessary }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$0C,#$0E,#$0F: // CMP
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+              { create shifter op }
+              setshifterop(1);
+              { set I field }
+              bytes:=bytes or (i_field shl 25);
+              { always set S bit }
+              bytes:=bytes or (1 shl 20);
+            end;
+          #$10: // MRS
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+              case oper[1]^.reg of
+                NR_APSR,NR_CPSR:;
+                NR_SPSR:
+                  begin
+                    bytes:=bytes or (1 shl 22);
+                  end;
+              else
+                Message(asmw_e_invalid_opcode_and_operands);
+              end;
+            end;
+          #$12,#$13: // MSR
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              { set destination }
+
+              if oper[0]^.typ=top_specialreg then
+                begin
+                  if (oper[0]^.specialreg<>NR_CPSR) and
+                     (oper[0]^.specialreg<>NR_SPSR) then
+                    Message1(asmw_e_invalid_opcode_and_operands, '"Invalid special reg"');
+
+                  if srC in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 16);
+                  if srX in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 17);
+                  if srS in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 18);
+                  if srF in oper[0]^.specialflags then
+                    bytes:=bytes or (1 shl 19);
+
+                  { Set R bit }
+                  if oper[0]^.specialreg=NR_SPSR then
+                    bytes:=bytes or (1 shl 22);
+                end
+              else
+                case oper[0]^.reg of
+                  NR_APSR_nzcvq: bytes:=bytes or (2 shl 18);
+                  NR_APSR_g: bytes:=bytes or (1 shl 18);
+                  NR_APSR_nzcvqg: bytes:=bytes or (3 shl 18);
+                else
+                  Message1(asmw_e_invalid_opcode_and_operands, 'Invalid combination APSR bits used');
+                end;
+
+              setshifterop(1);
+            end;
+          #$14: // MUL/MLA r1,r2,r3
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]);
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+
+              if oppostfix in [PF_S] then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$15: // MUL/MLA r1,r2,r3,r4
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]) shl 4;
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+              if ops>3 then
+                bytes:=bytes or getsupreg(oper[3]^.reg) shl 12
+              else
+                bytes:=bytes or ord(insentry^.code[4]) shl 12;
+
+              if oppostfix in [PF_R,PF_X] then
+                bytes:=bytes or (1 shl 5);
+
+              if oppostfix in [PF_S] then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$16: // MULL r1,r2,r3,r4
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]) shl 4;
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+              if (ops=3) and (opcode=A_PKHTB) then
+                begin
+                  bytes:=bytes or getsupreg(oper[1]^.reg);
+                  bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
+                end
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
+                  bytes:=bytes or getsupreg(oper[2]^.reg);
+                end;
+
+              if ops=4 then
+                begin
+                  if oper[3]^.typ=top_shifterop then
+                    begin
+                      if opcode in [A_PKHBT,A_PKHTB] then
+                        begin
+                          if ((opcode=A_PKHTB) and
+                              (oper[3]^.shifterop^.shiftmode <> SM_ASR)) or
+                            ((opcode=A_PKHBT) and
+                             (oper[3]^.shifterop^.shiftmode <> SM_LSL)) or
+                            (oper[3]^.shifterop^.rs<>NR_NO) then
+                            Message1(asmw_e_invalid_opcode_and_operands,GetString);
+
+                          bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
+                        end
+                      else
+                        begin
+                          if (oper[3]^.shifterop^.shiftmode<>sm_ror) or
+                            (oper[3]^.shifterop^.rs<>NR_NO) or
+                            (not (oper[3]^.shifterop^.shiftimm in [0,8,16,24])) then
+                            Message1(asmw_e_invalid_opcode_and_operands,GetString);
+
+                          bytes:=bytes or (((oper[3]^.shifterop^.shiftimm shr 3) and $3) shl 10);
+                        end;
+                    end
+                  else
+                    bytes:=bytes or getsupreg(oper[3]^.reg) shl 8;
+                end;
+
+              if PF_S=oppostfix then
+                bytes:=bytes or (1 shl 20);
+              if PF_X=oppostfix then
+                bytes:=bytes or (1 shl 5);
+            end;
+          #$17: // LDR/STR
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+              if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[1]^.ref^.offset;
+                  if offset>=0 then
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
+                  else
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $FFF);
+                end
+              else
+                begin
+                  { set U flag }
+                  if oper[1]^.ref^.signindex>=0 then
+                    bytes:=bytes or (1 shl 23);
+                  { set I flag }
+                  bytes:=bytes or (1 shl 25);
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+                  { set shift }
+                  with oper[1]^.ref^ do
+                    if shiftmode<>SM_None then
+                      begin
+                        bytes:=bytes or ((shiftimm and $1F) shl 7);
+                        if shiftmode<>SM_RRX then
+                          bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+                        else
+                          bytes:=bytes or (3 shl 5);
+                      end
+                end;
+              { set W bit }
+              if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+                bytes:=bytes or (1 shl 21);
+              { set P bit if necessary }
+              if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+                bytes:=bytes or (1 shl 24);
+            end;
+          #$18: // LDREX/STREX
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              if (ops=3) then
+                begin
+                  if opcode<>A_LDREXD then
+                    bytes:=bytes or getsupreg(oper[1]^.reg);
+
+                  bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
+                end
+              else if (ops=4) then // STREXD
+                begin
+                  if opcode<>A_LDREXD then
+                    bytes:=bytes or getsupreg(oper[1]^.reg);
+
+                  bytes:=bytes or (getsupreg(oper[3]^.ref^.base) shl 16);
+                end
+              else
+                bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 16);
+            end;
+          #$19: // LDRD/STRD
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+              refoper:=oper[1];
+              if ops=3 then
+                refoper:=oper[2];
+
+              bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
+              if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  bytes:=bytes or (1 shl 22);
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(refoper^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+refoper^.ref^.offset;
+                  if offset>=0 then
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
+                  else
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $F);
+                  bytes:=bytes or ((offset and $F0) shl 4);
+                end
+              else
+                begin
+                  { set U flag }
+                  if refoper^.ref^.signindex>=0 then
+                    bytes:=bytes or (1 shl 23);
+                  bytes:=bytes or getsupreg(refoper^.ref^.index);
+                end;
+              { set W bit }
+              if refoper^.ref^.addressmode=AM_PREINDEXED then
+                bytes:=bytes or (1 shl 21);
+              { set P bit if necessary }
+              if refoper^.ref^.addressmode<>AM_POSTINDEXED then
+                bytes:=bytes or (1 shl 24);
+            end;
+          #$1A: // QADD/QSUB
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]) shl 4;
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.reg) shl 0;
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
+            end;
+          #$1B:
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]) shl 4;
+              { set regs }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              if ops=3 then
+                begin
+                  if (oper[2]^.shifterop^.shiftmode<>sm_ror) or
+                    (oper[2]^.shifterop^.rs<>NR_NO) or
+                    (not (oper[2]^.shifterop^.shiftimm in [0,8,16,24])) then
+                    Message1(asmw_e_invalid_opcode_and_operands,GetString);
+
+                  bytes:=bytes or (((oper[2]^.shifterop^.shiftimm shr 3) and $3) shl 10);
+                end;
+            end;
+          #$1C: // MCR/MRC
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]) shl 4;
+              { set regs and operands }
+              bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
+              bytes:=bytes or ((oper[1]^.val and $7) shl 21);
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
+              bytes:=bytes or getcoprocreg(oper[3]^.reg) shl 16;
+              bytes:=bytes or getcoprocreg(oper[4]^.reg);
+              if ops > 5 then
+                bytes:=bytes or ((oper[5]^.val and $7) shl 5);
+            end;
+          #$1D: // MCRR/MRRC
+            begin
+              { set instruction code }
+              bytes:=bytes or ord(insentry^.code[1]) shl 24;
+              bytes:=bytes or ord(insentry^.code[2]) shl 16;
+              bytes:=bytes or ord(insentry^.code[3]) shl 4;
+              { set regs and operands }
+              bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
+              bytes:=bytes or ((oper[1]^.val and $7) shl 4);
+              bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[3]^.reg) shl 16;
+              bytes:=bytes or getcoprocreg(oper[4]^.reg);
+            end;
+          #$1E: // LDRHT/STRHT
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+              refoper:=oper[1];
+
+              bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
+              if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  bytes:=bytes or (1 shl 22);
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(refoper^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+refoper^.ref^.offset;
+
+                  if offset>=0 then
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
+                  else
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $F);
+                  bytes:=bytes or ((offset and $F0) shl 4);
+                end
+              else
+                begin
+                  { set U flag }
+                  if refoper^.ref^.signindex>=0 then
+                    bytes:=bytes or (1 shl 23);
+                  bytes:=bytes or getsupreg(refoper^.ref^.index);
+                end;
+            end;
+          #$22: // LDRH/STRH
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 16);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { src/dest register (Rd) }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              { base register (Rn) }
+              bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+              if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  bytes:=bytes or (1 shl 22); // with immediate offset
+                  offset:=oper[1]^.ref^.offset;
+                  if offset>=0 then
+                    { set U flag }
+                    bytes:=bytes or (1 shl 23)
+                  else
+                    offset:=-offset;
+                  bytes:=bytes or (offset and $F);
+                  bytes:=bytes or ((offset and $F0) shl 4);
+                end
+              else
+                begin
+                  { set U flag }
+                  if oper[1]^.ref^.signindex>=0 then
+                    bytes:=bytes or (1 shl 23);
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+                end;
+              { set W bit }
+              if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+                bytes:=bytes or (1 shl 21);
+              { set P bit if necessary }
+              if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+                bytes:=bytes or (1 shl 24);
+            end;
+          #$25: // PLD/PLI
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
+              if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[0]^.ref^.offset;
+                  if offset>=0 then
+                    begin
+                      { set U flag }
+                      bytes:=bytes or (1 shl 23);
+                      bytes:=bytes or offset
+                    end
+                  else
+                    begin
+                      offset:=-offset;
+                      bytes:=bytes or offset
+                    end;
+                end
+              else
+                begin
+                  bytes:=bytes or (1 shl 25);
+                  { set U flag }
+                  if oper[0]^.ref^.signindex>=0 then
+                    bytes:=bytes or (1 shl 23);
+                  bytes:=bytes or getsupreg(oper[0]^.ref^.index);
+                  { set shift }
+                  with oper[0]^.ref^ do
+                    if shiftmode<>SM_None then
+                      begin
+                        bytes:=bytes or ((shiftimm and $1F) shl 7);
+                        if shiftmode<>SM_RRX then
+                          bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+                        else
+                          bytes:=bytes or (3 shl 5);
+                      end
+                end;
+            end;
+          #$26: // LDM/STM
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 20);
+
+              if ops>1 then
+                begin
+                  if oper[0]^.typ=top_ref then
+                    begin
+                      { set W bit }
+                      if oper[0]^.ref^.addressmode=AM_PREINDEXED then
+                        bytes:=bytes or (1 shl 21);
+                      { set Rn }
+                      bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 16);
+                    end
+                  else { typ=top_reg }
+                    begin
+                      { set Rn }
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+                    end;
+
+                  if oper[1]^.usermode then
+                    begin
+                      if (oper[0]^.typ=top_ref) then
+                        begin
+                          if (opcode=A_LDM) and
+                             (RS_PC in oper[1]^.regset^) then
+                            begin
+                              // Valid exception return
+                            end
+                          else
+                            Message(asmw_e_invalid_opcode_and_operands);
+                        end;
+
+                      bytes:=bytes or (1 shl 22);
+                    end;
+                  { reglist }
+                  bytes:=bytes or MakeRegList(oper[1]^.regset^);
+                end
+              else
+                begin
+                  { push/pop }
+                  { Set W and Rn to SP }
+                  if opcode=A_PUSH then
+                    bytes:=bytes or (1 shl 21);
+                  bytes:=bytes or ($D shl 16);
+                  { reglist }
+                  bytes:=bytes or MakeRegList(oper[0]^.regset^);
+                end;
+              { set P bit }
+              if (opcode=A_LDM) and (oppostfix in [PF_ED,PF_EA,PF_IB,PF_DB])
+              or (opcode=A_STM) and (oppostfix in [PF_FA,PF_FD,PF_IB,PF_DB])
+              or (opcode=A_PUSH) then
+                bytes:=bytes or (1 shl 24);
+              { set U bit }
+              if (opcode=A_LDM) and (oppostfix in [PF_None,PF_ED,PF_FD,PF_IB,PF_IA])
+              or (opcode=A_STM) and (oppostfix in [PF_None,PF_FA,PF_EA,PF_IB,PF_IA])
+              or (opcode=A_POP) then
+                bytes:=bytes or (1 shl 23);
+            end;
+          #$27: // SWP/SWPB
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 20);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 4);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              if ops=3 then
+                bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
+            end;
+          #$28: // BX/BLX
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              { set offset }
+              if oper[0]^.typ=top_const then
+                bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
+              else
+                begin
+                  currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+                  if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+                    begin
+                      bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
+                      objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
+                    end
+                  else
+                    begin
+                      offset:=((currsym.offset-insoffset-8) and $3fffffe);
+
+                      { Turn BLX into BL if the destination isn't odd, could happen with recursion }
+                      if not odd(offset shr 1) then
+                        bytes:=(bytes and $EB000000) or $EB000000;
+
+                      bytes:=bytes or ((offset shr 2) and $ffffff);
+                      bytes:=bytes or ((offset shr 1) and $1) shl 24;
+                    end;
+                end;
+            end;
+          #$29: // SUB
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              { set S if necessary }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$2A:
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set opers }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              if opcode in [A_SSAT, A_SSAT16] then
+                bytes:=bytes or (((oper[1]^.val-1) and $1F) shl 16)
+              else
+                bytes:=bytes or ((oper[1]^.val and $1F) shl 16);
+              bytes:=bytes or getsupreg(oper[2]^.reg);
+
+              if (ops>3) and
+                (oper[3]^.typ=top_shifterop) and
+                (oper[3]^.shifterop^.rs=NR_NO) then
+                begin
+                  bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
+                  if oper[3]^.shifterop^.shiftmode=SM_ASR then
+                    bytes:=bytes or (1 shl 6)
+                  else if oper[3]^.shifterop^.shiftmode<>SM_LSL then
+                    Message1(asmw_e_invalid_opcode_and_operands,GetString);
+                end;
+            end;
+          #$2B: // SETEND
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set endian specifier }
+              bytes:=bytes or ((oper[0]^.val and 1) shl 9);
+            end;
+          #$2C: // MOVW
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              { set imm }
+              bytes:=bytes or (oper[1]^.val and $FFF);
+              bytes:=bytes or ((oper[1]^.val and $F000) shl 4);
+            end;
+          #$2D: // BFX
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+
+              if ops=3 then
+                begin
+                  msb:=(oper[1]^.val+oper[2]^.val-1);
+
+                  { set destination }
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+                  { set immediates }
+                  bytes:=bytes or ((oper[1]^.val and $1F) shl 7);
+                  bytes:=bytes or ((msb and $1F) shl 16);
+                end
+              else
+                begin
+                  if opcode in [A_BFC,A_BFI] then
+                    msb:=(oper[2]^.val+oper[3]^.val-1)
+                  else
+                    msb:=oper[3]^.val-1;
+
+                  { set destination }
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+                  bytes:=bytes or getsupreg(oper[1]^.reg);
+                  { set immediates }
+                  bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
+                  bytes:=bytes or ((msb and $1F) shl 16);
+                end;
+            end;
+          #$2E: // Cache stuff
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set code }
+              bytes:=bytes or (oper[0]^.val and $F);
+            end;
+          #$2F: // Nop
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+            end;
+          #$30: // Shifts
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set destination }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+              if ops>2 then
+                begin
+                  { set shift }
+                  if oper[2]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[2]^.reg) shl 8)
+                  else
+                    bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
+                end;
+              { set S if necessary }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$31: // BKPT
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 0);
+              { set imm }
+              bytes:=bytes or (oper[0]^.val and $FFF0) shl 4;
+              bytes:=bytes or (oper[0]^.val and $F);
+            end;
+          #$32: // CLZ/REV
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+              bytes:=bytes or getsupreg(oper[1]^.reg);
+            end;
+          #$33:
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+              if oper[1]^.typ=top_ref then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[1]^.ref^.offset;
+                  if offset>=0 then
+                    begin
+                      { set U flag }
+                      bytes:=bytes or (1 shl 23);
+                      bytes:=bytes or offset
+                    end
+                  else
+                    begin
+                      bytes:=bytes or (1 shl 22);
+                      offset:=-offset;
+                      bytes:=bytes or offset
+                    end;
+                end
+              else
+                begin
+                  if is_shifter_const(oper[1]^.val,r) then
+                    begin
+                      setshifterop(1);
+                      bytes:=bytes or (1 shl 23);
+                    end
+                  else
+                    begin
+                      bytes:=bytes or (1 shl 22);
+                      oper[1]^.val:=-oper[1]^.val;
+                      setshifterop(1);
+                    end;
+                end;
+            end;
+          #$40,#$90: // VMOV
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+
+              { set regs }
+              Rd:=0;
+              Rn:=0;
+              Rm:=0;
+
+              case oppostfix of
+                PF_None:
+                  begin
+                    if ops=4 then
+                      begin
+                        if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
+                           (getregtype(oper[2]^.reg)=R_INTREGISTER) then
+                          begin
+                            Rd:=getmmreg(oper[0]^.reg);
+                            Rm:=getsupreg(oper[2]^.reg);
+                            Rn:=getsupreg(oper[3]^.reg);
+                          end
+                        else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
+                                (getregtype(oper[2]^.reg)=R_MMREGISTER) then
+                          begin
+                            Rm:=getsupreg(oper[0]^.reg);
+                            Rn:=getsupreg(oper[1]^.reg);
+                            Rd:=getmmreg(oper[2]^.reg);
+                          end
+                        else
+                          message(asmw_e_invalid_opcode_and_operands);
+
+                        bytes:=bytes or (((Rd and $1E) shr 1) shl 0);
+                        bytes:=bytes or ((Rd and $1) shl 5);
+
+                        bytes:=bytes or (Rm shl 12);
+                        bytes:=bytes or (Rn shl 16);
+                      end
+                    else if ops=3 then
+                      begin
+                        if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
+                           (getregtype(oper[1]^.reg)=R_INTREGISTER) then
+                          begin
+                            Rd:=getmmreg(oper[0]^.reg);
+                            Rm:=getsupreg(oper[1]^.reg);
+                            Rn:=getsupreg(oper[2]^.reg);
+                          end
+                        else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
+                                (getregtype(oper[2]^.reg)=R_MMREGISTER) then
+                          begin
+                            Rm:=getsupreg(oper[0]^.reg);
+                            Rn:=getsupreg(oper[1]^.reg);
+                            Rd:=getmmreg(oper[2]^.reg);
+                          end
+                        else
+                          message(asmw_e_invalid_opcode_and_operands);
+
+                        bytes:=bytes or ((Rd and $F) shl 0);
+                        bytes:=bytes or ((Rd and $10) shl 1);
+
+                        bytes:=bytes or (Rm shl 12);
+                        bytes:=bytes or (Rn shl 16);
+                      end
+                    else if ops=2 then
+                      begin
+                        if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
+                           (getregtype(oper[1]^.reg)=R_INTREGISTER) then
+                          begin
+                            Rd:=getmmreg(oper[0]^.reg);
+                            Rm:=getsupreg(oper[1]^.reg);
+                          end
+                        else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
+                                (getregtype(oper[1]^.reg)=R_MMREGISTER) then
+                          begin
+                            Rm:=getsupreg(oper[0]^.reg);
+                            Rd:=getmmreg(oper[1]^.reg);
+                          end
+                        else
+                          message(asmw_e_invalid_opcode_and_operands);
+
+                        bytes:=bytes or (((Rd and $1E) shr 1) shl 16);
+                        bytes:=bytes or ((Rd and $1) shl 7);
+
+                        bytes:=bytes or (Rm shl 12);
+                      end;
+                  end;
+                PF_F32:
+                  begin
+                    if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
+                       (getregtype(oper[1]^.reg)<>R_MMREGISTER) then
+                      Message(asmw_e_invalid_opcode_and_operands);
+
+                    Rd:=getmmreg(oper[0]^.reg);
+                    Rm:=getmmreg(oper[1]^.reg);
+
+                    bytes:=bytes or (((Rd and $1E) shr 1) shl 12);
+                    bytes:=bytes or ((Rd and $1) shl 22);
+
+                    bytes:=bytes or (((Rm and $1E) shr 1) shl 0);
+                    bytes:=bytes or ((Rm and $1) shl 5);
+                  end;
+                PF_F64:
+                  begin
+                    if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
+                       (getregtype(oper[1]^.reg)<>R_MMREGISTER) then
+                      Message(asmw_e_invalid_opcode_and_operands);
 
-          bytes[3] |= (c & 0x0F);
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 4:         // AND Rd,Rn,Rm
-        case 5:         // AND Rd,Rn,Rm,<shift>Rs
-        case 6:         // AND Rd,Rn,Rm,<shift>imm
-        case 7:         // AND Rd,Rn,<shift>imm
-          ++codes;
-#ifdef DEBUG
-          if (rt_debug)
-            {
-              printf ("         decode - '0x%02X'\n", keep);
-              printf ("           code - '0x%02X'\n", (unsigned char) ( *codes));
-            }
-#endif
-          bytes[0] = c | *codes;
-          ++codes;
-
-          bytes[1] = *codes;
-          if (has_S_code)
-            bytes[1] |= 0x10;
-          c = regval (&ins->oprs[1],1);
-          // Rn in low nibble
-          bytes[1] |= c;
-
-          // Rd in high nibble
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-
-          if (keep != 7)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[2],1);
-            }
+                    Rd:=getmmreg(oper[0]^.reg);
+                    Rm:=getmmreg(oper[1]^.reg);
 
-          // Shifts if any
-          if (keep == 5 || keep == 6)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 5)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[3],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 6)
-                {
-                  c = (ins->oprs[3].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[3]) << 5;
-
-              bytes[3] |= c;
-            }
+                    bytes:=bytes or (1 shl 8);
 
-          // reg,reg,imm
-          if (keep == 7)
-            {
-              int shimm;
+                    bytes:=bytes or ((Rd and $F) shl 12);
+                    bytes:=bytes or (((Rd and $10) shr 4) shl 22);
 
-              shimm = imm_shift (ins->oprs[2].offset);
+                    bytes:=bytes or (Rm and $F);
+                    bytes:=bytes or ((Rm and $10) shl 1);
+                  end;
+              end;
+            end;
+          #$41,#$91: // VMRS/VMSR
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set regs }
+              if (opcode=A_VMRS) or
+                 (opcode=A_FMRX) then
+                begin
+                  case oper[1]^.reg of
+                    NR_FPSID: Rn:=$0;
+                    NR_FPSCR: Rn:=$1;
+                    NR_MVFR1: Rn:=$6;
+                    NR_MVFR0: Rn:=$7;
+                    NR_FPEXC: Rn:=$8;
+                  else
+                    Rn:=0;
+                    message(asmw_e_invalid_opcode_and_operands);
+                  end;
 
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
+                  bytes:=bytes or (Rn shl 16);
 
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
-
-        case 8:         // MOV Rd,Rm
-        case 9:         // MOV Rd,Rm,<shift>Rs
-        case 0xA:       // MOV Rd,Rm,<shift>imm
-        case 0xB:       // MOV Rd,<shift>imm
-          ++codes;
-#ifdef DEBUG
-          if (rt_debug)
-            {
-              printf ("         decode - '0x%02X'\n", keep);
-              printf ("           code - '0x%02X'\n", (unsigned char) ( *codes));
-            }
-#endif
-          bytes[0] = c | *codes;
-          ++codes;
+                  if oper[0]^.reg=NR_APSR_nzcv then
+                    bytes:=bytes or ($F shl 12)
+                  else
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+                end
+              else
+                begin
+                  case oper[0]^.reg of
+                    NR_FPSID: Rn:=$0;
+                    NR_FPSCR: Rn:=$1;
+                    NR_FPEXC: Rn:=$8;
+                  else
+                    Rn:=0;
+                    message(asmw_e_invalid_opcode_and_operands);
+                  end;
 
-          bytes[1] = *codes;
-          if (has_S_code)
-            bytes[1] |= 0x10;
+                  bytes:=bytes or (Rn shl 16);
 
-          // Rd in high nibble
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
+                end;
+            end;
+          #$42,#$92: // VMUL
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set regs }
+              if ops=3 then
+                begin
+                  Rd:=getmmreg(oper[0]^.reg);
+                  Rn:=getmmreg(oper[1]^.reg);
+                  Rm:=getmmreg(oper[2]^.reg);
+                end
+              else if ops=1 then
+                begin
+                  Rd:=getmmreg(oper[0]^.reg);
+                  Rn:=0;
+                  Rm:=0;
+                end
+              else if oper[1]^.typ=top_const then
+                begin
+                  Rd:=getmmreg(oper[0]^.reg);
+                  Rn:=0;
+                  Rm:=0;
+                end
+              else
+                begin
+                  Rd:=getmmreg(oper[0]^.reg);
+                  Rn:=0;
+                  Rm:=getmmreg(oper[1]^.reg);
+                end;
 
-          if (keep != 0x0B)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[1],1);
-            }
+              if (oppostfix=PF_F32) or (insentry^.code[5]=#1) then
+                begin
+                  D:=rd and $1; Rd:=Rd shr 1;
+                  N:=rn and $1; Rn:=Rn shr 1;
+                  M:=rm and $1; Rm:=Rm shr 1;
+                end
+              else
+                begin
+                  D:=(rd shr 4) and $1; Rd:=Rd and $F;
+                  N:=(rn shr 4) and $1; Rn:=Rn and $F;
+                  M:=(rm shr 4) and $1; Rm:=Rm and $F;
 
-          // Shifts if any
-          if (keep == 0x09 || keep == 0x0A)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 0x09)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[2],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 0x0A)
-                {
-                  c = (ins->oprs[2].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[2]) << 5;
-
-              bytes[3] |= c;
-            }
+                  bytes:=bytes or (1 shl 8);
+                end;
 
-          // reg,imm
-          if (keep == 0x0B)
-            {
-              int shimm;
+              bytes:=bytes or (Rd shl 12);
+              bytes:=bytes or (Rn shl 16);
+              bytes:=bytes or (Rm shl 0);
 
-              shimm = imm_shift (ins->oprs[1].offset);
+              bytes:=bytes or (D shl 22);
+              bytes:=bytes or (N shl 7);
+              bytes:=bytes or (M shl 5);
+            end;
+          #$43,#$93: // VCVT
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set regs }
+              Rd:=getmmreg(oper[0]^.reg);
+              Rm:=getmmreg(oper[1]^.reg);
+
+              if (ops=2) and
+                 (oppostfix in [PF_F32F64,PF_F64F32]) then
+                begin
+                  if oppostfix=PF_F32F64 then
+                    begin
+                      bytes:=bytes or (1 shl 8);
 
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
+                      D:=rd and $1; Rd:=Rd shr 1;
+                      M:=(rm shr 4) and $1; Rm:=Rm and $F;
+                    end
+                  else
+                    begin
+                      D:=(rd shr 4) and $1; Rd:=Rd and $F;
+                      M:=rm and $1; Rm:=Rm shr 1;
+                    end;
 
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
+                  bytes:=bytes and $FFF0FFFF;
+                  bytes:=bytes or ($7 shl 16);
 
+                  bytes:=bytes or (Rd shl 12);
+                  bytes:=bytes or (Rm shl 0);
 
-        case 0xC:       // CMP Rn,Rm
-        case 0xD:       // CMP Rn,Rm,<shift>Rs
-        case 0xE:       // CMP Rn,Rm,<shift>imm
-        case 0xF:       // CMP Rn,<shift>imm
-          ++codes;
+                  bytes:=bytes or (D shl 22);
+                  bytes:=bytes or (M shl 5);
+                end
+              else if (ops=2) and
+                      (oppostfix=PF_None) then
+                begin
+                  d:=0;
+                  case getsubreg(oper[0]^.reg) of
+                    R_SUBNONE:
+                      rd:=getsupreg(oper[0]^.reg);
+                    R_SUBFS:
+                      begin
+                        rd:=getmmreg(oper[0]^.reg);
 
-          bytes[0] = c | *codes++;
+                        d:=rd and 1;
+                        rd:=rd shr 1;
+                      end;
+                    R_SUBFD:
+                      begin
+                        rd:=getmmreg(oper[0]^.reg);
 
-          bytes[1] = *codes;
+                        d:=(rd shr 4) and 1;
+                        rd:=rd and $F;
+                      end;
+                  end;
 
-          // Implicit S code
-          bytes[1] |= 0x10;
+                  m:=0;
+                  case getsubreg(oper[1]^.reg) of
+                    R_SUBNONE:
+                      rm:=getsupreg(oper[1]^.reg);
+                    R_SUBFS:
+                      begin
+                        rm:=getmmreg(oper[1]^.reg);
 
-          c = regval (&ins->oprs[0],1);
-          // Rn in low nibble
-          bytes[1] |= c;
+                        m:=rm and 1;
+                        rm:=rm shr 1;
+                      end;
+                    R_SUBFD:
+                      begin
+                        rm:=getmmreg(oper[1]^.reg);
 
-          // No destination
-          bytes[2] = 0;
+                        m:=(rm shr 4) and 1;
+                        rm:=rm and $F;
+                      end;
+                  end;
 
-          if (keep != 0x0B)
-            {
-              // Rm in low nibble
-              bytes[3] = regval (&ins->oprs[1],1);
-            }
+                  bytes:=bytes or (Rd shl 12);
+                  bytes:=bytes or (Rm shl 0);
 
-          // Shifts if any
-          if (keep == 0x0D || keep == 0x0E)
-            {
-              // Shift in bytes 2 and 3
-              if (keep == 0x0D)
-                {
-                  // Rs
-                  c = regval (&ins->oprs[2],1);
-                  bytes[2] |= c;
-
-                  c = 0x10;             // Set bit 4 in byte[3]
-                }
-              if (keep == 0x0E)
-                {
-                  c = (ins->oprs[2].offset) & 0x1F;
-
-                  // #imm
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  c = 0;                // Clr bit 4 in byte[3]
-                }
-              // <shift>
-              c |= shiftval (&ins->oprs[2]) << 5;
-
-              bytes[3] |= c;
-            }
+                  bytes:=bytes or (D shl 22);
+                  bytes:=bytes or (M shl 5);
+                end
+              else if ops=2 then
+                begin
+                  case oppostfix of
+                    PF_S32F64,
+                    PF_U32F64,
+                    PF_F64S32,
+                    PF_F64U32:
+                      bytes:=bytes or (1 shl 8);
+                  end;
 
-          // reg,imm
-          if (keep == 0x0F)
-            {
-              int shimm;
+                  if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64] then
+                    begin
+                      case oppostfix of
+                        PF_S32F64,
+                        PF_S32F32:
+                          bytes:=bytes or (1 shl 16);
+                      end;
 
-              shimm = imm_shift (ins->oprs[1].offset);
+                      bytes:=bytes or (1 shl 18);
 
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
+                      D:=rd and $1; Rd:=Rd shr 1;
 
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-          return;
+                      if oppostfix in [PF_S32F64,PF_U32F64] then
+                        begin
+                          M:=(rm shr 4) and $1; Rm:=Rm and $F;
+                        end
+                      else
+                        begin
+                          M:=rm and $1; Rm:=Rm shr 1;
+                        end;
+                    end
+                  else
+                    begin
+                      case oppostfix of
+                        PF_F64S32,
+                        PF_F32S32:
+                          bytes:=bytes or (1 shl 7);
+                        else
+                          bytes:=bytes and $FFFFFF7F;
+                      end;
 
-        case 0x10:      // MRS Rd,<psr>
-          ++codes;
+                      M:=rm and $1; Rm:=Rm shr 1;
 
-          bytes[0] = c | *codes++;
+                      if oppostfix in [PF_F64S32,PF_F64U32] then
+                        begin
+                          D:=(rd shr 4) and $1; Rd:=Rd and $F;
+                        end
+                      else
+                        begin
+                          D:=rd and $1; Rd:=Rd shr 1;
+                        end
+                    end;
 
-          bytes[1] = *codes++;
+                  bytes:=bytes or (Rd shl 12);
+                  bytes:=bytes or (Rm shl 0);
 
-          // Rd
-          c = regval (&ins->oprs[0],1);
+                  bytes:=bytes or (D shl 22);
+                  bytes:=bytes or (M shl 5);
+                end
+              else
+                begin
+                  if rd<>rm then
+                    message(asmw_e_invalid_opcode_and_operands);
+
+                  case oppostfix of
+                    PF_S32F32,PF_U32F32,
+                    PF_F32S32,PF_F32U32,
+                    PF_S32F64,PF_U32F64,
+                    PF_F64S32,PF_F64U32:
+                      begin
+                        if not (oper[2]^.val in [1..32]) then
+                          message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 1-32');
 
-          bytes[2] = c << 4;
+                        bytes:=bytes or (1 shl 7);
+                        rn:=32;
+                      end;
+                    PF_S16F64,PF_U16F64,
+                    PF_F64S16,PF_F64U16,
+                    PF_S16F32,PF_U16F32,
+                    PF_F32S16,PF_F32U16:
+                      begin
+                        if not (oper[2]^.val in [0..16]) then
+                          message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 0-16');
 
-          bytes[3] = 0;
+                        rn:=16;
+                      end;
+                  else
+                    Rn:=0;
+                    message(asmw_e_invalid_opcode_and_operands);
+                  end;
 
-          c = ins->oprs[1].basereg;
+                  case oppostfix of
+                    PF_S16F64,PF_U16F64,
+                    PF_S32F64,PF_U32F64,
+                    PF_F64S16,PF_F64U16,
+                    PF_F64S32,PF_F64U32:
+                      begin
+                        bytes:=bytes or (1 shl 8);
+                        D:=(rd shr 4) and $1; Rd:=Rd and $F;
+                      end;
+                  else
+                    begin
+                      D:=rd and $1; Rd:=Rd shr 1;
+                    end;
+                  end;
 
-          if (c == R_CPSR || c == R_SPSR)
-            {
-              if (c == R_SPSR)
-                {
-                  bytes[1] |= 0x40;
-                }
-            }
-          else
-            {
-              errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
-            }
+                  case oppostfix of
+                    PF_U16F64,PF_U16F32,
+                    PF_U32F32,PF_U32F64,
+                    PF_F64U16,PF_F32U16,
+                    PF_F32U32,PF_F64U32:
+                      bytes:=bytes or (1 shl 16);
+                  end;
 
-          out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+                  if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64,PF_S16F32,PF_S16F64,PF_U16F32,PF_U16F64] then
+                    bytes:=bytes or (1 shl 18);
 
-          return;
+                  bytes:=bytes or (Rd shl 12);
+                  bytes:=bytes or (D shl 22);
 
-        case 0x11:      // MSR <psr>,Rm
-        case 0x12:      // MSR <psrf>,Rm
-        case 0x13:      // MSR <psrf>,#expression
-          ++codes;
+                  rn:=rn-oper[2]^.val;
 
-          bytes[0] = c | *codes++;
+                  bytes:=bytes or ((rn and $1) shl 5);
+                  bytes:=bytes or ((rn and $1E) shr 1);
+                end;
+            end;
+          #$44,#$94: // VLDM/VSTM/VPUSH/VPOP
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              { set regs }
+              if ops=2 then
+                begin
+                  if oper[0]^.typ=top_ref then
+                    begin
+                      Rn:=getsupreg(oper[0]^.ref^.index);
 
-          bytes[1] = *codes++;
+                      if oper[0]^.ref^.addressmode<>AM_OFFSET then
+                        begin
+                          { set W }
+                          bytes:=bytes or (1 shl 21);
+                        end
+                      else if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
+                        message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
+                    end
+                  else
+                    begin
+                      Rn:=getsupreg(oper[0]^.reg);
 
-          bytes[2] = *codes;
+                      if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
+                        message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
+                    end;
 
+                  bytes:=bytes or (Rn shl 16);
 
-          if (keep == 0x11 || keep == 0x12)
-            {
-              // Rm
-              c = regval (&ins->oprs[1],1);
+                  { Set PU bits }
+                  case oppostfix of
+                    PF_None,
+                    PF_IA,PF_IAS,PF_IAD,PF_IAX:
+                      bytes:=bytes or (1 shl 23);
+                    PF_DB,PF_DBS,PF_DBD,PF_DBX:
+                      bytes:=bytes or (2 shl 23);
+                  end;
 
-              bytes[3] = c;
-            }
-          else
-            {
-              int shimm;
+                  case oppostfix of
+                    PF_IAX,PF_DBX,PF_FDX,PF_EAX:
+                      begin
+                        bytes:=bytes or (1 shl 8);
+                        bytes:=bytes or (1 shl 0); // Offset is odd
+                      end;
+                  end;
 
-              shimm = imm_shift (ins->oprs[1].offset);
+                  dp_operation:=(oper[1]^.subreg=R_SUBFD);
+                  if oper[1]^.regset^=[] then
+                    message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
 
-              if (shimm == -1)
-                {
-                  errfunc (ERR_NONFATAL, "cannot create that constant");
-                }
-              bytes[3] = shimm & 0xFF;
-              bytes[2] |= (shimm & 0xF00) >> 8;
-            }
+                  rd:=0;
+                  for r:=0 to 31 do
+                    if r in oper[1]^.regset^ then
+                      begin
+                        rd:=r;
+                        break;
+                      end;
 
-          c = ins->oprs[0].basereg;
-
-          if ( keep == 0x11)
-            {
-              if ( c == R_CPSR || c == R_SPSR)
-                {
-                if ( c== R_SPSR)
-                  {
-                    bytes[1] |= 0x40;
-                  }
-                }
-            else
-              {
-                errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
-              }
-            }
-          else
-            {
-              if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
-                {
-                  if ( c== R_SPSR_FLG)
-                    {
-                      bytes[1] |= 0x40;
-                    }
-                }
-              else
-                {
-                  errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
-                }
-            }
-          break;
+                  rn:=32-rd;
+                  for r:=rd+1 to 31 do
+                    if not(r in oper[1]^.regset^) then
+                      begin
+                        rn:=r-rd;
+                        break;
+                      end;
 
-        case 0x14:      // MUL  Rd,Rm,Rs
-        case 0x15:      // MULA Rd,Rm,Rs,Rn
-          ++codes;
+                  if dp_operation then
+                    begin
+                      bytes:=bytes or (1 shl 8);
 
-          bytes[0] = c | *codes++;
+                      bytes:=bytes or (rn*2);
 
-          bytes[1] = *codes++;
+                      bytes:=bytes or ((rd and $F) shl 12);
+                      bytes:=bytes or (((rd and $10) shr 4) shl 22);
+                    end
+                  else
+                    begin
+                      bytes:=bytes or rn;
 
-          bytes[3] = *codes;
+                      bytes:=bytes or ((rd and $1) shl 22);
+                      bytes:=bytes or (((rd and $1E) shr 1) shl 12);
+                    end;
+                end
+              else { VPUSH/VPOP }
+                begin
+                  dp_operation:=(oper[0]^.subreg=R_SUBFD);
+                  if oper[0]^.regset^=[] then
+                    message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
 
-          // Rd
-          bytes[1] |= regval (&ins->oprs[0],1);
-          if (has_S_code)
-            bytes[1] |= 0x10;
+                  rd:=0;
+                  for r:=0 to 31 do
+                    if r in oper[0]^.regset^ then
+                      begin
+                        rd:=r;
+                        break;
+                      end;
 
-          // Rm
-          bytes[3] |= regval (&ins->oprs[1],1);
+                  rn:=32-rd;
+                  for r:=rd+1 to 31 do
+                    if not(r in oper[0]^.regset^) then
+                      begin
+                        rn:=r-rd;
+                        break;
+                      end;
 
-          // Rs
-          bytes[2] = regval (&ins->oprs[2],1);
+                  if dp_operation then
+                    begin
+                      bytes:=bytes or (1 shl 8);
 
-          if (keep == 0x15)
-            {
-              bytes[2] |= regval (&ins->oprs[3],1) << 4;
-            }
-          break;
+                      bytes:=bytes or (rn*2);
 
-        case 0x16:      // SMLAL RdHi,RdLo,Rm,Rs
-          ++codes;
+                      bytes:=bytes or ((rd and $F) shl 12);
+                      bytes:=bytes or (((rd and $10) shr 4) shl 22);
+                    end
+                  else
+                    begin
+                      bytes:=bytes or rn;
 
-          bytes[0] = c | *codes++;
+                      bytes:=bytes or ((rd and $1) shl 22);
+                      bytes:=bytes or (((rd and $1E) shr 1) shl 12);
+                    end;
+                end;
+            end;
+          #$45,#$95: // VLDR/VSTR
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              { set regs }
+              rd:=getmmreg(oper[0]^.reg);
 
-          bytes[1] = *codes++;
+              if getsubreg(oper[0]^.reg)=R_SUBFD then
+                begin
+                  bytes:=bytes or (1 shl 8);
 
-          bytes[3] = *codes;
+                  bytes:=bytes or ((rd and $F) shl 12);
+                  bytes:=bytes or (((rd and $10) shr 4) shl 22);
+                end
+              else
+                begin
+                  bytes:=bytes or (((rd and $1E) shr 1) shl 12);
+                  bytes:=bytes or ((rd and $1) shl 22);
+                end;
 
-          // RdHi
-          bytes[1] |= regval (&ins->oprs[1],1);
-          if (has_S_code)
-            bytes[1] |= 0x10;
+              { set ref }
+              bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+              if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[1]^.ref^.offset;
 
-          // RdLo
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          // Rm
-          bytes[3] |= regval (&ins->oprs[2],1);
+                  offset:=offset div 4;
 
-          // Rs
-          bytes[2] |= regval (&ins->oprs[3],1);
+                  if offset>=0 then
+                    begin
+                      { set U flag }
+                      bytes:=bytes or (1 shl 23);
+                      bytes:=bytes or offset
+                    end
+                  else
+                    begin
+                      offset:=-offset;
+                      bytes:=bytes or offset
+                    end;
+                end
+              else
+                message(asmw_e_invalid_opcode_and_operands);
+            end;
+          #$46: { System instructions }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              { set regs }
+              if (oper[0]^.typ=top_modeflags) then
+                begin
+                  if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 8);
+                  if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
+                  if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
+                end;
 
-          break;
+              if (ops=2) then
+                bytes:=bytes or (oper[1]^.val and $1F)
+              else if (ops=1) and
+                      (oper[0]^.typ=top_const) then
+                bytes:=bytes or (oper[0]^.val and $1F);
+            end;
+          #$60: { Thumb }
+            begin
+              bytelen:=2;
+              bytes:=0;
+
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { set regs }
+              if ops=2 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
+                  if (oper[1]^.typ=top_reg) then
+                    bytes:=bytes or ((getsupreg(oper[1]^.reg) and $7) shl 6)
+                  else
+                    bytes:=bytes or ((oper[1]^.val and $1F) shl 6);
+                end
+              else if ops=3 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+                  if (oper[2]^.typ=top_reg) then
+                    bytes:=bytes or ((getsupreg(oper[2]^.reg) and $7) shl 6)
+                  else
+                    bytes:=bytes or ((oper[2]^.val and $1F) shl 6);
+                end
+              else if ops=1 then
+                begin
+                  if oper[0]^.typ=top_const then
+                    bytes:=bytes or (oper[0]^.val and $FF);
+                end;
+            end;
+          #$61: { Thumb }
+            begin
+              bytelen:=2;
+              bytes:=0;
+
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { set regs }
+              if ops=2 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                  bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
 
-        case 0x17:      // LDR Rd, expression
-          ++codes;
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+                end
+              else if ops=1 then
+                begin
+                  if oper[0]^.typ=top_const then
+                    bytes:=bytes or (oper[0]^.val and $FF);
+                end;
+            end;
+          #$62..#$63: { Thumb branches }
+            begin
+              bytelen:=2;
+              bytes:=0;
 
-          bytes[0] = c | *codes++;
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
 
-          bytes[1] = *codes++;
+              if insentry^.code[0]=#$63 then
+                bytes:=bytes or (CondVal[condition] shl 8);
 
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-          if (has_T_code)
-            {
-              errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
-            }
-          if (has_W_code)
-            {
-              errfunc (ERR_NONFATAL, "'!' not allowed");
-            }
+              if oper[0]^.typ=top_const then
+                begin
+                  if insentry^.code[0]=#$63 then
+                    bytes:=bytes or (((oper[0]^.val shr 1)-1) and $FF)
+                  else
+                    bytes:=bytes or (((oper[0]^.val shr 1)-1) and $3FF);
+                end
+              else if oper[0]^.typ=top_reg then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
+                end
+              else if oper[0]^.typ=top_ref then
+                begin
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[0]^.ref^.offset;
+
+                  if insentry^.code[0]=#$63 then
+                    bytes:=bytes or (((offset+4) shr 1) and $FF)
+                  else
+                    bytes:=bytes or (((offset+4) shr 1) and $7FF);
+                end
+            end;
+          #$64: { Thumb: Special encodings }
+            begin
+              bytelen:=2;
+              bytes:=0;
 
-          // Rn - implicit R15
-          bytes[1] |= 0xF;
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
 
-          if (ins->oprs[1].segment != segment)
-            {
-              errfunc (ERR_NONFATAL, "label not in same segment");
-            }
 
-          data = ins->oprs[1].offset - (offset + 8);
+              case opcode of
+                A_SUB:
+                  begin
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                    if (ops=3) and
+                       (oper[2]^.typ=top_const) then
+                      bytes:=bytes or ((oper[2]^.val shr 2) and $7F)
+                    else if (ops=2) and
+                            (oper[1]^.typ=top_const) then
+                      bytes:=bytes or ((oper[1]^.val shr 2) and $7F);
+                  end;
+                A_MUL:
+                  if (ops in [2,3]) then
+                    begin
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                      bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+                    end;
+                A_ADD:
+                  begin
+                    if ops=2 then
+                      begin
+                        bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                        bytes:=bytes or (getsupreg(oper[1]^.reg) shl $3);
+                      end
+                    else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
+                       (oper[2]^.typ=top_const) then
+                      begin
+                        bytes:=bytes or (getsupreg(oper[0]^.reg) and $7) shl 8;
+                        bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
+                      end
+                    else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
+                       (oper[2]^.typ=top_reg) then
+                      begin
+                        bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                        bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
+                      end
+                    else
+                      begin
+                        bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                        bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
+                      end;
+                  end;
+              end;
+            end;
+          #$65: { Thumb load/store }
+            begin
+              bytelen:=2;
+              bytes:=0;
+
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+              bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
+              bytes:=bytes or (getsupreg(oper[1]^.ref^.index) shl 6);
+            end;
+          #$66: { Thumb load/store }
+            begin
+              bytelen:=2;
+              bytes:=0;
+
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+              bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
+              bytes:=bytes or (((oper[1]^.ref^.offset shr ord(insentry^.code[3])) and $1F) shl 6);
+            end;
+          #$67: { Thumb load/store }
+            begin
+              bytelen:=2;
+              bytes:=0;
+
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { set regs }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+              if oper[1]^.typ=top_ref then
+                bytes:=bytes or ((oper[1]^.ref^.offset shr ord(insentry^.code[3])) and $FF)
+              else
+                bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF);
+            end;
+          #$68: { Thumb CB[N]Z }
+            begin
+              bytelen:=2;
+              bytes:=0;
 
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              { set opers }
+              bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
 
-          if (data >= 0x1000)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
+              if oper[1]^.typ=top_ref then
+                begin
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[1]^.ref^.offset;
+
+                  offset:=offset div 2;
+                end
+              else
+                offset:=oper[1]^.val div 2;
 
-          bytes[2] |= ((data & 0xF00) >> 8);
-          bytes[3] = data & 0xFF;
-          break;
+              bytes:=bytes or ((offset) and $1F) shl 3;
+              bytes:=bytes or ((offset shr 5) and 1) shl 9;
+            end;
+          #$69: { Thumb: Push/Pop/Stm/Ldm }
+            begin
+              bytelen:=2;
+              bytes:=0;
 
-        case 0x18:      // LDR Rd, [Rn]
-          ++codes;
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
 
-          bytes[0] = c | *codes++;
+              case opcode of
+                A_PUSH:
+                  begin
+                    for r:=0 to 7 do
+                      if r in oper[0]^.regset^ then
+                        bytes:=bytes or (1 shl r);
+                    if RS_R14 in oper[0]^.regset^ then
+                      bytes:=bytes or (1 shl 8);
+                  end;
+                A_POP:
+                  begin
+                    for r:=0 to 7 do
+                      if r in oper[0]^.regset^ then
+                        bytes:=bytes or (1 shl r);
+                    if RS_R15 in oper[0]^.regset^ then
+                      bytes:=bytes or (1 shl 8);
+                  end;
+                A_STM:
+                  begin
+                    for r:=0 to 7 do
+                      if r in oper[1]^.regset^ then
+                        bytes:=bytes or (1 shl r);
 
-          bytes[1] = *codes++;
+                    if oper[0]^.typ=top_ref then
+                      bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 8)
+                    else
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  end;
+                A_LDM:
+                  begin
+                    for r:=0 to 7 do
+                      if r in oper[1]^.regset^ then
+                        bytes:=bytes or (1 shl r);
 
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-          if (has_T_code)
-            {
-              bytes[1] |= 0x20;         // write-back
-            }
-          else
-            {
-              bytes[0] |= 0x01;         // implicit pre-index mode
-            }
+                    if oper[0]^.typ=top_ref then
+                      bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 8)
+                    else
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  end;
+              end;
+            end;
+          #$6A: { Thumb: IT }
+            begin
+              bytelen:=2;
+              bytes:=0;
 
-          if (has_W_code)
-            {
-              bytes[1] |= 0x20;         // write-back
-            }
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 0);
 
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
+              bytes:=bytes or (CondVal[oper[0]^.cc] shl 4);
 
-          if (c == 0x15)                // R15
-            data = -8;
-          else
-            data = 0;
+              i_field:=(bytes shr 4) and 1;
+              i_field:=(i_field shl 1) or i_field;
+              i_field:=(i_field shl 2) or i_field;
 
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
+              bytes:=bytes or ((i_field and ord(insentry^.code[3])) xor (ord(insentry^.code[3]) shr 4));
+            end;
+          #$6B: { Thumb: Data processing (misc) }
+            begin
+              bytelen:=2;
+              bytes:=0;
+
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
+              { set regs }
+              if ops>=2 then
+                begin
+                  if oper[1]^.typ=top_const then
+                    begin
+                      bytes:=bytes or ((getsupreg(oper[0]^.reg) and $7) shl 8);
+                      bytes:=bytes or (oper[1]^.val and $FF);
+                    end
+                  else if oper[1]^.typ=top_reg then
+                    begin
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+                      bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+                    end;
+                end
+              else if ops=1 then
+                begin
+                  if oper[0]^.typ=top_const then
+                    bytes:=bytes or (oper[0]^.val and $FF);
+                end;
+            end;
+          #$6C: { Thumb: CPS }
+            begin
+              bytelen:=2;
+              bytes:=0;
 
-          bytes[2] |= ((data & 0xF00) >> 8);
-          bytes[3] = data & 0xFF;
-          break;
-
-        case 0x19:      // LDR Rd, [Rn,#expression]
-        case 0x20:      // LDR Rd, [Rn,Rm]
-        case 0x21:      // LDR Rd, [Rn,Rm,shift]
-          ++codes;
-
-          bytes[0] = c | *codes++;
-
-          bytes[1] = *codes++;
-
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          if (has_B_code)
-            bytes[1] |= 0x40;
-
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
-
-          if (ins->oprs[ins->operands-1].bracket)       // FIXME: Bracket on last operand -> pre-index  <--
-            {
-              bytes[0] |= 0x01;         // pre-index mode
-              if (has_W_code)
-                {
-                  bytes[1] |= 0x20;
-                }
-              if (has_T_code)
-                {
-                  errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
-                }
-            }
-          else
-            {
-              if (has_T_code)           // Forced write-back in post-index mode
-                {
-                  bytes[1] |= 0x20;
-                }
-              if (has_W_code)
-                {
-                  errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
-                }
-            }
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+              bytes:=bytes or ord(insentry^.code[2]);
 
-          if (keep == 0x19)
-            {
-              data = ins->oprs[2].offset;
+              if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 2);
+              if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 1);
+              if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 0);
+            end;
+          #$80: { Thumb-2: Dataprocessing }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-              if (data < 0)
-                {
-                  data = -data;
-                }
-              else
-                {
-                  bytes[1] |= 0x80;
-                }
+              if ops=1 then
+                begin
+                  if oper[0]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
+                  else if oper[0]^.typ=top_const then
+                    bytes:=bytes or (oper[0]^.val and $F);
+                end
+              else if (ops=2) and
+                 (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+
+                  if oper[1]^.typ=top_const then
+                    encodethumbimm(oper[1]^.val)
+                  else if oper[1]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+                end
+              else if (ops=3) and
+                      (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+
+                  if oper[2]^.typ=top_shifterop then
+                    setthumbshift(2)
+                  else if oper[2]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[2]^.reg) shl 12);
+                end
+              else if (ops=2) and
+                      (opcode in [A_REV,A_RBIT,A_REV16,A_REVSH,A_CLZ]) then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+                end
+              else if ops=2 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+
+                  if oper[1]^.typ=top_const then
+                    encodethumbimm(oper[1]^.val)
+                  else if oper[1]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+                end
+              else if ops=3 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+
+                  if oper[2]^.typ=top_const then
+                    encodethumbimm(oper[2]^.val)
+                  else if oper[2]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+                end
+              else if ops=4 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+                  bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+
+                  if oper[3]^.typ=top_shifterop then
+                    setthumbshift(3)
+                  else if oper[3]^.typ=top_reg then
+                    bytes:=bytes or (getsupreg(oper[3]^.reg) shl 12);
+                end;
 
-              if (data >= 0x1000)
-                {
-                  errfunc (ERR_NONFATAL, "too long offset");
-                }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20)
+              else if oppostfix=PF_X then
+                bytes:=bytes or (1 shl 4)
+              else if oppostfix=PF_R then
+                bytes:=bytes or (1 shl 4);
+            end;
+          #$81: { Thumb-2: Dataprocessing misc }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-              bytes[2] |= ((data & 0xF00) >> 8);
-              bytes[3] = data & 0xFF;
-            }
-          else
-            {
-              if (ins->oprs[2].minus == 0)
-                {
-                  bytes[1] |= 0x80;
-                }
-              c = regval (&ins->oprs[2],1);
-              bytes[3] = c;
-
-              if (keep == 0x21)
-                {
-                  c = ins->oprs[3].offset;
-                  if (c > 0x1F)
-                    {
-                      errfunc (ERR_NONFATAL, "too large shiftvalue");
-                      c = c & 0x1F;
-                    }
-
-                  bytes[2] |= c >> 1;
-                  if (c & 0x01)
-                    {
-                      bytes[3] |= 0x80;
-                    }
-                  bytes[3] |= shiftval (&ins->oprs[3]) << 5;
-                }
-            }
+              if ops=3 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
 
-          break;
+                  if oper[2]^.typ=top_const then
+                    begin
+                      bytes:=bytes or (oper[2]^.val and $FF);
+                      bytes:=bytes or ((oper[2]^.val and $700) shr 8) shl 12;
+                      bytes:=bytes or ((oper[2]^.val and $800) shr 11) shl 26;
+                    end;
+                end
+              else if ops=2 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
 
-        case 0x22:      // LDRH Rd, expression
-          ++codes;
+                  offset:=0;
+                  if oper[1]^.typ=top_const then
+                    begin
+                      offset:=oper[1]^.val;
+                    end
+                  else if oper[1]^.typ=top_ref then
+                    begin
+                      currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                      if assigned(currsym) then
+                        offset:=currsym.offset-insoffset-8;
+                      offset:=offset+oper[1]^.ref^.offset;
 
-          bytes[0] = c | 0x01;          // Implicit pre-index
+                      offset:=offset;
+                    end;
 
-          bytes[1] = *codes++;
+                  bytes:=bytes or  (offset and $FF);
+                  bytes:=bytes or ((offset and $700) shr 8) shl 12;
+                  bytes:=bytes or ((offset and $800) shr 11) shl 26;
+                  bytes:=bytes or ((offset and $F000) shr 12) shl 16;
+                end;
 
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$82: { Thumb-2: Shifts }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          // Rn - implicit R15
-          bytes[1] |= 0xF;
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+              if oper[1]^.typ=top_reg then
+                begin
+                  offset:=2;
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+                end
+              else
+                begin
+                  offset:=1;
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 0);
+                end;
 
-          if (ins->oprs[1].segment != segment)
-            {
-              errfunc (ERR_NONFATAL, "label not in same segment");
-            }
+              if oper[offset]^.typ=top_const then
+                begin
+                  bytes:=bytes or (oper[offset]^.val and $3) shl 6;
+                  bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
+                end
+              else if oper[offset]^.typ=top_reg then
+                bytes:=bytes or (getsupreg(oper[offset]^.reg) shl 16);
 
-          data = ins->oprs[1].offset - (offset + 8);
+              if (ops>=(offset+2)) and
+                 (oper[offset+1]^.typ=top_const) then
+                bytes:=bytes or (oper[offset+1]^.val and $1F);
 
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$84: { Thumb-2: Shifts(width-1) }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          if (data >= 0x100)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-          bytes[3] = *codes++;
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+              if oper[1]^.typ=top_reg then
+                begin
+                  offset:=2;
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+                end
+              else
+                offset:=1;
 
-          bytes[2] |= ((data & 0xF0) >> 4);
-          bytes[3] |= data & 0xF;
-          break;
+              if oper[offset]^.typ=top_const then
+                begin
+                  bytes:=bytes or (oper[offset]^.val and $3) shl 6;
+                  bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
+                end;
 
-        case 0x23:      // LDRH Rd, Rn
-          ++codes;
+              if (ops>=(offset+2)) and
+                 (oper[offset+1]^.typ=top_const) then
+                begin
+                  if opcode in [A_BFI,A_BFC] then
+                    i_field:=oper[offset+1]^.val+oper[offset]^.val-1
+                  else
+                    i_field:=oper[offset+1]^.val-1;
 
-          bytes[0] = c | 0x01;          // Implicit pre-index
+                  bytes:=bytes or (i_field and $1F);
+                end;
 
-          bytes[1] = *codes++;
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20);
+            end;
+          #$83: { Thumb-2: Saturation }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
+              bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+              bytes:=bytes or (oper[1]^.val and $1F);
+              bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
 
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
+              if ops=4 then
+                setthumbshift(3,true);
+            end;
+          #$85: { Thumb-2: Long multiplications }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          if (c == 0x15)                // R15
-            data = -8;
-          else
-            data = 0;
+              if ops=4 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
+                  bytes:=bytes or (getsupreg(oper[3]^.reg) shl 0);
+                end;
 
-          if (data < 0)
-            {
-              data = -data;
-            }
-          else
-            {
-              bytes[1] |= 0x80;
-            }
+              if oppostfix=PF_S then
+                bytes:=bytes or (1 shl 20)
+              else if oppostfix=PF_X then
+                bytes:=bytes or (1 shl 4);
+            end;
+          #$86: { Thumb-2: Extension ops }
+            begin
+              bytes:=0;
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          if (data >= 0x100)
-            {
-              errfunc (ERR_NONFATAL, "too long offset");
-            }
-          bytes[3] = *codes++;
+              if ops=2 then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+                end
+              else if ops=3 then
+                begin
+                  if oper[2]^.typ=top_shifterop then
+                    begin
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                      bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+                      bytes:=bytes or ((oper[2]^.shifterop^.shiftimm shr 3) shl 4);
+                    end
+                  else
+                    begin
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                      bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+                      bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+                    end;
+                end
+              else if ops=4 then
+                begin
+                  if oper[3]^.typ=top_shifterop then
+                    begin
+                      bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+                      bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+                      bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+                      bytes:=bytes or ((oper[3]^.shifterop^.shiftimm shr 3) shl 4);
+                    end;
+                end;
+            end;
+          #$87: { Thumb-2: PLD/PLI }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
+              if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=offset+oper[0]^.ref^.offset;
+                  if offset>=0 then
+                    begin
+                      { set U flag }
+                      bytes:=bytes or (1 shl 23);
+                      bytes:=bytes or (offset and $FFF);
+                    end
+                  else
+                    begin
+                      bytes:=bytes or ($3 shl 10);
 
-          bytes[2] |= ((data & 0xF0) >> 4);
-          bytes[3] |= data & 0xF;
-          break;
+                      offset:=-offset;
+                      bytes:=bytes or (offset and $FF);
+                    end;
+                end
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.ref^.index);
+                  { set shift }
+                  with oper[0]^.ref^ do
+                    if shiftmode=SM_LSL then
+                      bytes:=bytes or ((shiftimm and $1F) shl 4);
+                end;
+            end;
+          #$88: { Thumb-2: LDR/STR }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+              if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=(offset+oper[1]^.ref^.offset) shr ord(insentry^.code[5]);
+                  if offset>=0 then
+                    begin
+                      if not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT]) then
+                        bytes:=bytes or (1 shl 23);
+                      { set U flag }
+                      if (oper[1]^.ref^.addressmode<>AM_OFFSET) then
+                        bytes:=bytes or (1 shl 9);
+                      bytes:=bytes or offset
+                    end
+                  else
+                    begin
+                      bytes:=bytes or (1 shl 11);
 
-        case 0x24:      // LDRH Rd, Rn, expression
-        case 0x25:      // LDRH Rd, Rn, Rm
-          ++codes;
+                      offset:=-offset;
+                      bytes:=bytes or offset
+                    end;
+                end
+              else
+                begin
+                  { set I flag }
+                  bytes:=bytes or (1 shl 25);
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+                  { set shift }
+                  with oper[1]^.ref^ do
+                    if shiftmode<>SM_None then
+                      bytes:=bytes or ((shiftimm and $1F) shl 4);
+                end;
 
-          bytes[0] = c;
+              if not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT]) then
+                begin
+                  { set W bit }
+                  if oper[1]^.ref^.addressmode<>AM_OFFSET then
+                    bytes:=bytes or (1 shl 8);
+                  { set P bit if necessary }
+                  if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+                    bytes:=bytes or (1 shl 10);
+                end;
+            end;
+          #$89: { Thumb-2: LDRD/STRD }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
+              bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+              if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
+                begin
+                  { set offset }
+                  offset:=0;
+                  currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
+                  if assigned(currsym) then
+                    offset:=currsym.offset-insoffset-8;
+                  offset:=(offset+oper[2]^.ref^.offset) div 4;
+                  if offset>=0 then
+                    begin
+                      { set U flag }
+                      bytes:=bytes or (1 shl 23);
+                      bytes:=bytes or offset
+                    end
+                  else
+                    begin
+                      offset:=-offset;
+                      bytes:=bytes or offset
+                    end;
+                end
+              else
+                begin
+                  message(asmw_e_invalid_opcode_and_operands);
+                end;
+              { set W bit }
+              if oper[2]^.ref^.addressmode<>AM_OFFSET then
+                bytes:=bytes or (1 shl 21);
+              { set P bit if necessary }
+              if oper[2]^.ref^.addressmode<>AM_POSTINDEXED then
+                bytes:=bytes or (1 shl 24);
+            end;
+          #$8A: { Thumb-2: LDREX }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+              { set Rn and Rd }
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+              if (ops=2) and (opcode in [A_LDREX]) then
+                begin
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+                  if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+                    begin
+                      { set offset }
+                      offset:=0;
+                      currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+                      if assigned(currsym) then
+                        offset:=currsym.offset-insoffset-8;
+                      offset:=(offset+oper[1]^.ref^.offset) div 4;
+                      if offset>=0 then
+                        begin
+                          bytes:=bytes or offset
+                        end
+                      else
+                        begin
+                          message(asmw_e_invalid_opcode_and_operands);
+                        end;
+                    end
+                  else
+                    begin
+                      message(asmw_e_invalid_opcode_and_operands);
+                    end;
+                end
+              else if (ops=2) then
+                begin
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+                end
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
+                  bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+                end;
+            end;
+          #$8B: { Thumb-2: STREX }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+              { set Rn and Rd }
+              if (ops=3) and (opcode in [A_STREX]) then
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.reg) shl 8;
+                  bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
+                  bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+                  if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
+                    begin
+                      { set offset }
+                      offset:=0;
+                      currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
+                      if assigned(currsym) then
+                        offset:=currsym.offset-insoffset-8;
+                      offset:=(offset+oper[2]^.ref^.offset) div 4;
+                      if offset>=0 then
+                        begin
+                          bytes:=bytes or offset
+                        end
+                      else
+                        begin
+                          message(asmw_e_invalid_opcode_and_operands);
+                        end;
+                    end
+                  else
+                    begin
+                      message(asmw_e_invalid_opcode_and_operands);
+                    end;
+                end
+              else if (ops=3) then
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
+                  bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
+                  bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+                end
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
+                  bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
+                  bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+                  bytes:=bytes or getsupreg(oper[3]^.ref^.base) shl 16;
+                end;
+            end;
+          #$8C: { Thumb-2: LDM/STM }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or (ord(insentry^.code[4]) shl 0);
 
-          bytes[1] = *codes++;
+              if oper[0]^.typ=top_reg then
+                bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
+              else
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 16);
+                  if oper[0]^.ref^.addressmode<>AM_OFFSET then
+                    bytes:=bytes or (1 shl 21);
+                end;
 
-          // Rd
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
+              for r:=0 to 15 do
+                if r in oper[1]^.regset^ then
+                  bytes:=bytes or (1 shl r);
 
-          // Rn
-          c = regval (&ins->oprs[1],1);
-          bytes[1] |= c;
+              case oppostfix of
+                PF_None,PF_IA,PF_FD: bytes:=bytes or ($1 shl 23);
+                PF_DB,PF_EA: bytes:=bytes or ($2 shl 23);
+              end;
+            end;
+          #$8D: { Thumb-2: BL/BLX }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 8);
+              { set offset }
+              if oper[0]^.typ=top_const then
+                offset:=(oper[0]^.val shr 1) and $FFFFFF
+              else
+                begin
+                  currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+                  if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+                    begin
+                      objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
+                      offset:=$FFFFFE
+                    end
+                  else
+                    offset:=((currsym.offset-insoffset-8) shr 1) and $FFFFFF;
+                end;
 
-          if (ins->oprs[ins->operands-1].bracket)       // FIXME: Bracket on last operand -> pre-index  <--
-            {
-              bytes[0] |= 0x01;         // pre-index mode
-              if (has_W_code)
-                {
-                  bytes[1] |= 0x20;
-                }
-            }
-          else
-            {
-              if (has_W_code)
-                {
-                  errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
-                }
-            }
+              bytes:=bytes or ((offset shr 00) and $7FF) shl 0;
+              bytes:=bytes or ((offset shr 11) and $3FF) shl 16;
+              bytes:=bytes or (((offset shr 21) xor (offset shr 23) xor 1) and $1) shl 11;
+              bytes:=bytes or (((offset shr 22) xor (offset shr 23) xor 1) and $1) shl 13;
+              bytes:=bytes or ((offset shr 23) and $1) shl 26;
+            end;
+          #$8E: { Thumb-2: TBB/TBH }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
+              { set Rn and Rm }
+              bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
+
+              if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
+                message(asmw_e_invalid_effective_address)
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.ref^.index);
 
-          bytes[3] = *codes++;
+                  if (opcode=A_TBH) and
+                     (oper[0]^.ref^.shiftmode<>SM_LSL) and
+                     (oper[0]^.ref^.shiftimm<>1) then
+                    message(asmw_e_invalid_effective_address);
+                end;
+            end;
+          #$8F: { Thumb-2: CPSxx }
+            begin
+              { set opcode }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          if (keep == 0x24)
-            {
-              data = ins->oprs[2].offset;
+              if (oper[0]^.typ=top_modeflags) then
+                begin
+                  if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
+                  if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
+                  if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 5);
+                end;
 
-              if (data < 0)
-                {
-                  data = -data;
-                }
-              else
-                {
-                  bytes[1] |= 0x80;
-                }
+              if (ops=2) then
+                bytes:=bytes or (oper[1]^.val and $1F)
+              else if (ops=1) and
+                      (oper[0]^.typ=top_const) then
+                bytes:=bytes or (oper[0]^.val and $1F);
+            end;
+          #$96: { Thumb-2: MSR/MRS }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-              if (data >= 0x100)
-                {
-                  errfunc (ERR_NONFATAL, "too long offset");
-                }
+              if opcode=A_MRS then
+                begin
+                  bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
 
-              bytes[2] |= ((data & 0xF0) >> 4);
-              bytes[3] |= data & 0xF;
-            }
-          else
-            {
-              if (ins->oprs[2].minus == 0)
-                {
-                  bytes[1] |= 0x80;
-                }
-              c = regval (&ins->oprs[2],1);
-              bytes[3] |= c;
+                  case oper[1]^.reg of
+                    NR_MSP: bytes:=bytes or $08;
+                    NR_PSP: bytes:=bytes or $09;
 
-            }
-          break;
+                    NR_IPSR: bytes:=bytes or $05;
+                    NR_EPSR: bytes:=bytes or $06;
+                    NR_APSR: bytes:=bytes or $00;
 
-        case 0x26:      // LDM/STM Rn, {reg-list}
-          ++codes;
+                    NR_PRIMASK: bytes:=bytes or $10;
+                    NR_BASEPRI: bytes:=bytes or $11;
+                    NR_BASEPRI_MAX: bytes:=bytes or $12;
+                    NR_FAULTMASK: bytes:=bytes or $13;
+                    NR_CONTROL: bytes:=bytes or $14;
+                  else
+                    Message(asmw_e_invalid_opcode_and_operands);
+                  end;
+                end
+              else
+                begin
+                  bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
 
-          bytes[0] = c;
+                  case oper[0]^.reg of
+                    NR_APSR,
+                    NR_APSR_nzcvqg: bytes:=bytes or $C00;
+                    NR_APSR_g: bytes:=bytes or $400;
+                    NR_APSR_nzcvq: bytes:=bytes or $800;
 
-          bytes[0] |= ( *codes >> 4) & 0xF;
-          bytes[1] = ( *codes << 4) & 0xF0;
-          ++codes;
+                    NR_MSP: bytes:=bytes or $08;
+                    NR_PSP: bytes:=bytes or $09;
 
-          if (has_W_code)
-            {
-              bytes[1] |= 0x20;
-            }
-          if (has_F_code)
-            {
-              bytes[1] |= 0x40;
-            }
+                    NR_PRIMASK: bytes:=bytes or $10;
+                    NR_BASEPRI: bytes:=bytes or $11;
+                    NR_BASEPRI_MAX: bytes:=bytes or $12;
 
-          // Rn
-          bytes[1] |= regval (&ins->oprs[0],1);
+                    NR_FAULTMASK: bytes:=bytes or $13;
+                    NR_CONTROL: bytes:=bytes or $14;
+                  else
+                    Message(asmw_e_invalid_opcode_and_operands);
+                  end;
+                end;
+            end;
+          #$A0: { FPA: CPDT(LDF/STF) }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+              bytes:=bytes or ord(insentry^.code[4]);
 
-          data = ins->oprs[1].basereg;
+              if ops=2 then
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+                  bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+                  bytes:=bytes or ((oper[1]^.ref^.offset shr 2) and $FF);
+                  if oper[1]^.ref^.offset>=0 then
+                    bytes:=bytes or (1 shl 23);
+
+                  if oper[1]^.ref^.addressmode<>AM_OFFSET then
+                    bytes:=bytes or (1 shl 21);
+                  if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+                    bytes:=bytes or (1 shl 24);
+
+                  case oppostfix of
+                    PF_D: bytes:=bytes or (0 shl 22) or (1 shl 15);
+                    PF_E: bytes:=bytes or (1 shl 22) or (0 shl 15);
+                    PF_P: bytes:=bytes or (1 shl 22) or (1 shl 15);
+                  end;
+                end
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
 
-          bytes[2] = ((data >> 8) & 0xFF);
-          bytes[3] = (data & 0xFF);
+                  case oper[1]^.val of
+                    1: bytes:=bytes or (1 shl 15);
+                    2: bytes:=bytes or (1 shl 22);
+                    3: bytes:=bytes or (1 shl 22) or (1 shl 15);
+                    4: ;
+                  else
+                    message1(asmw_e_invalid_opcode_and_operands, 'Invalid count for LFM/SFM');
+                  end;
 
-          break;
+                  bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+                  bytes:=bytes or ((oper[2]^.ref^.offset shr 2) and $FF);
+                  if oper[2]^.ref^.offset>=0 then
+                    bytes:=bytes or (1 shl 23);
 
-        case 0x27:      // SWP Rd, Rm, [Rn]
-          ++codes;
+                  if oper[2]^.ref^.addressmode<>AM_OFFSET then
+                    bytes:=bytes or (1 shl 21);
+                  if oper[2]^.ref^.addressmode=AM_PREINDEXED then
+                    bytes:=bytes or (1 shl 24);
+                end;
+            end;
+          #$A1: { FPA: CPDO }
+            begin
+              { set instruction code }
+              bytes:=bytes or ($E shl 24);
+              bytes:=bytes or (ord(insentry^.code[1]) shl 15);
+              bytes:=bytes or ((ord(insentry^.code[2]) shr 1) shl 20);
+              bytes:=bytes or (1 shl 8);
 
-          bytes[0] = c;
+              bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+              if ops=2 then
+                begin
+                  if oper[1]^.typ=top_reg then
+                    bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
+                  else
+                    case oper[1]^.val of
+                      0: bytes:=bytes or $8;
+                      1: bytes:=bytes or $9;
+                      2: bytes:=bytes or $A;
+                      3: bytes:=bytes or $B;
+                      4: bytes:=bytes or $C;
+                      5: bytes:=bytes or $D;
+                      //0.5: bytes:=bytes or $E;
+                      10: bytes:=bytes or $F;
+                    else
+                      Message(asmw_e_invalid_opcode_and_operands);
+                    end;
+                end
+              else
+                begin
+                  bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
+                  if oper[2]^.typ=top_reg then
+                    bytes:=bytes or getsupreg(oper[2]^.reg) shl 0
+                  else
+                    case oper[2]^.val of
+                      0: bytes:=bytes or $8;
+                      1: bytes:=bytes or $9;
+                      2: bytes:=bytes or $A;
+                      3: bytes:=bytes or $B;
+                      4: bytes:=bytes or $C;
+                      5: bytes:=bytes or $D;
+                      //0.5: bytes:=bytes or $E;
+                      10: bytes:=bytes or $F;
+                    else
+                      Message(asmw_e_invalid_opcode_and_operands);
+                    end;
+                end;
 
-          bytes[0] |= *codes++;
+              case roundingmode of
+                RM_P: bytes:=bytes or (1 shl 5);
+                RM_M: bytes:=bytes or (2 shl 5);
+                RM_Z: bytes:=bytes or (3 shl 5);
+              end;
 
-          bytes[1] = regval (&ins->oprs[2],1);
-          if (has_B_code)
-            {
-              bytes[1] |= 0x40;
-            }
-          bytes[2] = regval (&ins->oprs[0],1) << 4;
-          bytes[3] = *codes++;
-          bytes[3] |= regval (&ins->oprs[1],1);
-          break;
+              case oppostfix of
+                PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
+                PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
+                PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
+              else
+                message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
+              end;
+            end;
+          #$A2: { FPA: CPDO }
+            begin
+              { set instruction code }
+              bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+              bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+              bytes:=bytes or ($11 shl 4);
 
-        default:
-          errfunc (ERR_FATAL, "unknown decoding of instruction");
+              case opcode of
+                A_FLT:
+                  begin
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+                    bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
 
-          bytes[0] = c;
-          // And a fix nibble
-          ++codes;
-          bytes[0] |= *codes++;
+                    case roundingmode of
+                      RM_P: bytes:=bytes or (1 shl 5);
+                      RM_M: bytes:=bytes or (2 shl 5);
+                      RM_Z: bytes:=bytes or (3 shl 5);
+                    end;
 
-         if ( *codes == 0x01)           // An I bit
-           {
+                    case oppostfix of
+                      PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
+                      PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
+                      PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
+                    else
+                      message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
+                    end;
+                  end;
+                A_FIX:
+                  begin
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+                    bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
 
-           }
-         if ( *codes == 0x02)           // An I bit
-           {
+                    case roundingmode of
+                      RM_P: bytes:=bytes or (1 shl 5);
+                      RM_M: bytes:=bytes or (2 shl 5);
+                      RM_Z: bytes:=bytes or (3 shl 5);
+                    end;
+                  end;
+                A_WFS,A_RFS,A_WFC,A_RFC:
+                  begin
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+                  end;
+                A_CMF,A_CNF,A_CMFE,A_CNFE:
+                  begin
+                    bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
 
-           }
-         ++codes;
-      }
-    out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-}
+                    if oper[1]^.typ=top_reg then
+                      bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
+                    else
+                      case oper[1]^.val of
+                        0: bytes:=bytes or $8;
+                        1: bytes:=bytes or $9;
+                        2: bytes:=bytes or $A;
+                        3: bytes:=bytes or $B;
+                        4: bytes:=bytes or $C;
+                        5: bytes:=bytes or $D;
+                        //0.5: bytes:=bytes or $E;
+                        10: bytes:=bytes or $F;
+                      else
+                        Message(asmw_e_invalid_opcode_and_operands);
+                      end;
+                  end;
+              end;
+            end;
+          #$fe: // No written data
+            begin
+              exit;
+            end;
+          #$ff:
+            internalerror(2005091101);
+          else
+            begin
+              writeln(ord(insentry^.code[0]), ' - ', opcode);
+              internalerror(2005091102);
+            end;
+        end;
 
-*)
-{$endif dummy}
+        { Todo: Decide whether the code above should take care of writing data in an order that makes senes }
+        if (insentry^.code[0] in [#$80..#$96]) and (bytelen=4) then
+          bytes:=((bytes shr 16) and $FFFF) or ((bytes and $FFFF) shl 16);
 
-  constructor tai_thumb_func.create;
-    begin
-      inherited create;
-      typ:=ait_thumb_func;
-    end;
+        { we're finished, write code }
+        objdata.writebytes(bytes,bytelen);
+      end;
 
 begin
   cai_align:=tai_align;
index 68fd5680d59508163419ae363f3a9b50d87ea21e..07e9068e169d71b03b43661146202262114a98f3 100644 (file)
@@ -42,11 +42,14 @@ unit agarmgas;
       end;
 
       TArmInstrWriter=class(TCPUInstrWriter)
+        unified_syntax: boolean;
+
         procedure WriteInstruction(hp : tai);override;
       end;
 
       TArmAppleGNUAssembler=class(TAppleGNUassembler)
         constructor create(smart: boolean); override;
+        procedure WriteExtraHeader; override;
       end;
 
 
@@ -93,6 +96,8 @@ unit agarmgas;
       begin
         inherited create(smart);
         InstrWriter := TArmInstrWriter.create(self);
+        if GenerateThumb2Code then
+          TArmInstrWriter(InstrWriter).unified_syntax:=true;
       end;
 
 
@@ -109,6 +114,8 @@ unit agarmgas;
           result:='-mfpu=vfpv3-d16 '+result;
         if (current_settings.fputype = fpu_fpv4_s16) then
           result:='-mfpu=fpv4-sp-d16 '+result;
+        if (current_settings.fputype = fpu_vfpv4) then
+          result:='-mfpu=vfpv4 '+result;
 
         if GenerateThumb2Code then
           result:='-march='+cputype_to_gas_march[current_settings.cputype]+' -mthumb -mthumb-interwork '+result
@@ -126,7 +133,7 @@ unit agarmgas;
     procedure TArmGNUAssembler.WriteExtraHeader;
       begin
         inherited WriteExtraHeader;
-        if GenerateThumb2Code then
+        if TArmInstrWriter(InstrWriter).unified_syntax then
           AsmWriteLn(#9'.syntax unified');
       end;
 
@@ -138,6 +145,15 @@ unit agarmgas;
       begin
         inherited create(smart);
         InstrWriter := TArmInstrWriter.create(self);
+        TArmInstrWriter(InstrWriter).unified_syntax:=true;
+      end;
+
+
+    procedure TArmAppleGNUAssembler.WriteExtraHeader;
+      begin
+        inherited WriteExtraHeader;
+        if TArmInstrWriter(InstrWriter).unified_syntax then
+          AsmWriteLn(#9'.syntax unified');
       end;
 
 
@@ -208,7 +224,7 @@ unit agarmgas;
       var
         hs : string;
         first : boolean;
-        r : tsuperregister;
+        r, rs : tsuperregister;
       begin
         case o.typ of
           top_reg:
@@ -230,14 +246,44 @@ unit agarmgas;
             begin
               getopstr:='{';
               first:=true;
-              for r:=RS_R0 to RS_R15 do
-                if r in o.regset^ then
-                  begin
-                    if not(first) then
-                      getopstr:=getopstr+',';
-                    getopstr:=getopstr+gas_regname(newreg(o.regtyp,r,o.subreg));
-                    first:=false;
-                  end;
+              if R_SUBFS=o.subreg then
+                begin
+                  for r:=0 to 31 do // S0 to S31
+                    if r in o.regset^ then
+                      begin
+                        if not(first) then
+                          getopstr:=getopstr+',';
+                        if odd(r) then
+                          rs:=(r shr 1)+RS_S1
+                        else
+                          rs:=(r shr 1)+RS_S0;
+                        getopstr:=getopstr+gas_regname(newreg(o.regtyp,rs,o.subreg));
+                        first:=false;
+                      end;
+                end
+              else if R_SUBFD=o.subreg then
+                begin
+                  for r:=0 to 31 do
+                    if r in o.regset^ then
+                      begin
+                        if not(first) then
+                          getopstr:=getopstr+',';
+                        rs:=r+RS_D0;
+                        getopstr:=getopstr+gas_regname(newreg(o.regtyp,rs,o.subreg));
+                        first:=false;
+                      end;
+                end
+              else
+                begin
+                  for r:=RS_R0 to RS_R15 do
+                    if r in o.regset^ then
+                      begin
+                        if not(first) then
+                          getopstr:=getopstr+',';
+                        getopstr:=getopstr+gas_regname(newreg(o.regtyp,r,o.subreg));
+                        first:=false;
+                      end;
+                end;
               getopstr:=getopstr+'}';
               if o.usermode then
                 getopstr:=getopstr+'^';
@@ -289,15 +335,17 @@ unit agarmgas;
         sep: string[3];
     begin
       op:=taicpu(hp).opcode;
+      postfix:='';
       if GenerateThumb2Code then
         begin
-          postfix:='';
           if taicpu(hp).wideformat then
             postfix:='.w';
-
+        end;
+      if unified_syntax then
+        begin
           if taicpu(hp).ops = 0 then
             s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
-          else if (taicpu(hp).opcode>=A_VABS) and (taicpu(hp).opcode<=A_VSUB) then
+          else if taicpu(hp).oppostfix in [PF_8..PF_U32F64] then
             s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
           else
             s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix]+cond2str[taicpu(hp).condition]+postfix; // Conditional infixes are deprecated in unified syntax
@@ -314,7 +362,7 @@ unit agarmgas;
                // writeln(taicpu(hp).fileinfo.line);
 
                { LDM and STM use references as first operand but they are written like a register }
-               if (i=0) and (op in [A_LDM,A_STM,A_FSTM,A_FLDM]) then
+               if (i=0) and (op in [A_LDM,A_STM,A_FSTM,A_FLDM,A_VSTM,A_VLDM]) then
                  begin
                    case taicpu(hp).oper[0]^.typ of
                      top_ref:
index bd7860162958f8c4e76876773a573ff7d610fe13..e015ee9bba5bf03036ff2c7a792c330005a9bff3 100644 (file)
@@ -2353,7 +2353,7 @@ Implementation
     { set of opcode which might or do write to memory }
     { TODO : extend armins.dat to contain r/w info }
     opcode_could_mem_write = [A_B,A_BL,A_BLX,A_BKPT,A_BX,A_STR,A_STRB,A_STRBT,
-                              A_STRH,A_STRT,A_STF,A_SFM,A_STM,A_FSTS,A_FSTD];
+                              A_STRH,A_STRT,A_STF,A_SFM,A_STM,A_FSTS,A_FSTD,A_VSTR,A_VSTM];
 
 
   { adjust the register live information when swapping the two instructions p and hp1,
index 602cb025a89e2b4e3df812368352f00c44fedd60..363944ff45679f2104521cc0b930e0e0ae23a993 100644 (file)
@@ -1,12 +1,9 @@
 { don't edit, this file is generated from armins.dat }
 (
 'none',
-'abs',
-'acs',
-'asn',
-'atn',
 'adc',
 'add',
+'addw',
 'adf',
 'adr',
 'and',
 'bkpt',
 'bx',
 'cdp',
-'cmf',
-'cmfe',
 'cmn',
 'cmp',
+'cmf',
+'cmfe',
+'stf',
+'ldf',
+'lfm',
 'clz',
-'cnf',
-'cos',
 'cps',
 'cpsid',
 'cpsie',
-'dvf',
 'eor',
-'exp',
-'fdv',
-'flt',
-'fix',
-'fml',
-'frd',
 'ldc',
 'ldm',
 'ldrbt',
 'ldrsb',
 'ldrsh',
 'ldrt',
-'ldf',
-'lfm',
-'lgn',
-'log',
 'mcr',
+'mcr2',
+'mrc',
+'mrc2',
+'mcrr',
+'mcrr2',
+'mrrc',
+'mrrc2',
 'mla',
 'mov',
-'mrc',
 'mrs',
 'msr',
-'mnf',
-'muf',
 'mul',
 'mvf',
 'mvn',
+'vmov',
 'nop',
+'orn',
 'orr',
-'rdf',
-'rfs',
-'rfc',
-'rmf',
-'rpw',
 'rsb',
 'rsc',
-'rsf',
-'rnd',
-'pol',
 'sbc',
 'sfm',
 'sin',
 'smlal',
 'smull',
-'sqt',
-'suf',
-'stf',
 'stm',
 'str',
 'strb',
 'swi',
 'swp',
 'swpb',
-'tan',
 'teq',
 'tst',
 'umlal',
 'umull',
 'wfs',
 'ldrd',
-'mcrr',
-'mrrc',
 'pld',
+'pldw',
 'qadd',
 'qdadd',
 'qdsub',
 'smlaltt',
 'smlawb',
 'smlawt',
+'vldm',
+'vstm',
+'vpop',
+'vpush',
+'vldr',
+'vstr',
 'smulbb',
 'smulbt',
 'smultb',
 'smulwb',
 'smulwt',
 'strd',
-'fabsd',
-'fabss',
-'faddd',
-'fadds',
-'fcmpd',
-'fcmped',
-'fcmpes',
-'fcmpezd',
-'fcmpezs',
-'fcmps',
-'fcmpzd',
-'fcmpzs',
-'fcpyd',
-'fcpys',
-'fcvtds',
-'fcvtsd',
-'fdivd',
-'fdivs',
-'fldd',
-'fldm',
-'flds',
-'fmacd',
-'fmacs',
-'fmdhr',
-'fmdlr',
-'fmrdh',
-'fmrdl',
-'fmrs',
-'fmrx',
-'fmscd',
-'fmscs',
-'fmsr',
-'fmstat',
-'fmuld',
-'fmuls',
-'fmxr',
-'fnegd',
-'fnegs',
-'fnmacd',
-'fnmacs',
-'fnmscd',
-'fnmscs',
-'fnmuld',
-'fnmuls',
-'fsitod',
-'fsitos',
-'fsqrtd',
-'fsqrts',
+'ldrht',
+'strht',
+'ldrsbt',
+'ldrsht',
 'fstd',
 'fstm',
 'fsts',
-'fsubd',
-'fsubs',
-'ftosid',
-'ftosis',
-'ftouid',
-'ftouis',
-'fuitod',
-'fuitos',
-'fmdrr',
-'fmrrd',
 'bfc',
 'bfi',
 'clrex',
 'ldrexb',
 'ldrexd',
 'ldrexh',
+'strex',
+'strexb',
+'strexd',
+'strexh',
 'mls',
-'pkh',
+'pkhbt',
+'pkhtb',
 'pli',
 'qadd16',
 'qadd8',
 'lsr',
 'lsl',
 'ror',
+'rrx',
+'umaal',
 'shadd16',
 'shadd8',
 'shasx',
 'ssax',
 'ssub16',
 'ssub8',
-'strex',
-'strexb',
-'strexd',
-'strexh',
 'sxtab',
 'sxtab16',
 'sxtah',
+'ubfx',
+'uxtab',
+'uxtab16',
+'uxtah',
 'sxtb',
 'sxtb16',
+'sxth',
 'uxtb',
+'uxtb16',
 'uxth',
-'sxth',
 'uadd16',
 'uadd8',
 'uasx',
-'ubfx',
 'uhadd16',
 'uhadd8',
 'uhasx',
 'uhsax',
 'uhsub16',
 'uhsub8',
-'umaal',
 'uqadd16',
 'uqadd8',
 'uqasx',
 'uqsax',
 'uqsub16',
 'uqsub8',
-'uqsad8',
-'uqsada8',
+'usad8',
+'usada8',
 'usat',
 'usat16',
 'usax',
 'usub16',
 'usub8',
-'uxtab',
-'uxtab16',
-'uxtah',
-'uxtb16',
 'wfe',
 'wfi',
 'yield',
+'fabsd',
+'fabss',
+'faddd',
+'fadds',
+'fcmpd',
+'fcmps',
+'fcmped',
+'fcmpes',
+'fcmpzd',
+'fcmpzs',
+'fcmpezd',
+'fcmpezs',
+'fcpyd',
+'fcpys',
+'fcvtds',
+'fcvtsd',
+'fdivd',
+'fdivs',
+'fldd',
+'fldm',
+'flds',
+'fmacd',
+'fmacs',
+'fmdhr',
+'fmdlr',
+'fmrdh',
+'fmrdl',
+'fmrs',
+'fmrx',
+'fmscd',
+'fmscs',
+'fmsr',
+'fmstat',
+'fmuld',
+'fmuls',
+'fmxr',
+'fnegd',
+'fnegs',
+'fnmacd',
+'fnmacs',
+'fnmscd',
+'fnmscs',
+'fnmuld',
+'fnmuls',
+'fsitod',
+'fsitos',
+'fsqrtd',
+'fsqrts',
+'fsubd',
+'fsubs',
+'ftosid',
+'ftosis',
+'ftouid',
+'ftouis',
+'fuitod',
+'fuitos',
+'fmdrr',
+'fmrrd',
 'pop',
 'push',
 'sdiv',
 'vcmp',
 'vcmpe',
 'vcvt',
+'vcvtr',
 'vdiv',
-'vldm',
-'vldr',
-'vmov',
 'vmrs',
 'vmsr',
-'vmul',
 'vmla',
 'vmls',
+'vmul',
 'vnmla',
 'vnmls',
+'vnmul',
 'vfma',
 'vfms',
 'vfnma',
 'vfnms',
 'vneg',
-'vnmul',
-'vpop',
-'vpush',
 'vsqrt',
-'vstm',
-'vstr',
 'vsub',
+'dmb',
+'isb',
+'dsb',
+'smc',
 'neg',
-'svc'
+'svc',
+'bxj',
+'udf',
+'tan',
+'sqt',
+'suf',
+'rsf',
+'rnd',
+'pol',
+'rdf',
+'rfs',
+'rfc',
+'wfc',
+'rmf',
+'rpw',
+'mnf',
+'muf',
+'abs',
+'acs',
+'asn',
+'atn',
+'cnf',
+'cnfe',
+'cos',
+'dvf',
+'exp',
+'fdv',
+'flt',
+'fix',
+'fml',
+'frd',
+'lgn',
+'log'
 );
index 2c9aeac21645e67474825018a537913643db432d..fcab30cb1c1303dcf96d9389451a47527c0f77fd 100644 (file)
@@ -330,5 +330,27 @@ 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
 );
index 411983bb93c9d67f089e1af5649e073b82200226..edfa65faab885b729a7cea8ae8198ece14d61ee6 100644 (file)
 [NONE]
 void                  void                            none
 
-[ABScc]
+[ADCcc]
+reglo,reglo                 \x6B\x41\x40                  THUMB,ARMv4T
 
-[ACScc]
+reg32,immshifter            \x80\xF1\x40\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\x40\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x40\x0\x0            THUMB32,WIDE,ARMv6T2
 
-[ASNcc]
+reg32,reg32,reg32           \4\x0\xA0                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xA0                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\xA0                     ARM32,ARMv4
 
-[ATNcc]
+[ADDcc]
+reg32,reg32                 \x61\x44\x0                   THUMB,ARMv4T
+reglo,reglo,reglo           \x60\x18\x0                   THUMB,ARMv4T
 
-[ADCcc]
-reg32,reg32,reg32        \4\x0\xA0                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\xA0                     ARM7
-reg32,reg32,reg32,imm    \6\x0\xA0                     ARM7
-reg32,reg32,imm          \7\x2\xA0                     ARM7
+reglo,immshifter            \x60\x1C\x0                   THUMB,ARMv4T
+reglo,reglo,immshifter      \x60\x1C\x0                   THUMB,ARMv4T
+reglo,immshifter            \x6B\x30\x0                   THUMB,ARMv4T
 
-[ADDcc]
-reg32,reg32,reg32        \4\x0\x80                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x80                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x80                     ARM7
-reg32,reg32,imm          \7\x2\x80                     ARM7
+reglo,regsp,immshifter      \x64\xA8\x00                  THUMB,ARMv4T
+regsp,regsp,immshifter      \x64\xB0\x00                  THUMB,ARMv4T
+reg32,regsp,reg32           \x64\x44\x68                  THUMB,ARMv4T
+regsp,reg32                 \x64\x44\x85                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF1\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32                 \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \4\x0\x80                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x80                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\x80                     ARM32,ARMv4
+
+[ADDWcc]
+reg32,reg32,immshifter      \x81\xF2\x0\x0\x0             THUMB32,ARMv6T2
 
 [ADFcc]
+fpureg,fpureg,fpureg        \xA1\0\x0                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x0                     ARM32,FPA
 
 [ADRcc]
+;reg32,immshifter           \x33\x2\x0F                   ARM32,ARMv4
+;reg32,imm32                \x33\x2\x0F                   ARM32,ARMv4
+reglo,immshifter            \x67\xA0\x0\2                 THUMB,ARMv4T
+reglo,memam6                \x67\xA0\x0\2                 THUMB,ARMv4T
+
+reg32,imm32                 \x81\xF2\xAF\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,immshifter            \x81\xF2\xAF\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x81\xF2\xAF\x0\x0            THUMB32,WIDE,ARMv6T2
+
+reg32,memam2                \x33\x2\x0F                   ARM32,ARMv4
 
 [ANDcc]
-reg32,reg32,reg32        \4\x0\x00                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x00                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x00                     ARM7
-reg32,reg32,imm          \7\x2\x00                     ARM7
+reglo,reglo                 \x6B\x40\x00                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF0\x0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x0\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \x4\x0\x00                    ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x0\x00                    ARM32,ARMv4
+reg32,reg32,immshifter      \x7\x2\x00                    ARM32,ARMv4
 
 [Bcc]
-mem32                    \1\x0A                        ARM7
-imm24                    \1\x0A                        ARM7
+imm24                       \x62\xE0\x0                   THUMB,ARMv4T
+immshifter                  \x62\xE0\x0                   THUMB,ARMv4T
+mem32                       \x62\xE0\x0                   THUMB,ARMv4T
+
+imm24                       \x63\xD0\x0                   THUMB,ARMv4T
+immshifter                  \x63\xD0\x0                   THUMB,ARMv4T
+mem32                       \x63\xD0\x0                   THUMB,ARMv4T
+
+imm24                       \x1\x0A                       ARM32,ARMv4
+mem32                       \x1\x0A                       ARM32,ARMv4
 
 [BICcc]
-reg32,reg32,reg32        \4\x1\xC0                     ARM7
-reg32,reg32,reg32,reg32  \5\x1\xC0                     ARM7
-reg32,reg32,reg32,imm    \6\x1\xC0                     ARM7
-reg32,reg32,imm          \7\x3\xC0                     ARM7
+reglo,reglo                 \x6B\x43\x80                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF0\x20\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x20\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x20\x0\x0            THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \x6\x1\xC0                    ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x1\xC0                    ARM32,ARMv4
+reg32,reg32,immshifter      \x7\x3\xC0                    ARM32,ARMv4
 
 [BLcc]
-mem32                    \1\x0B                        ARM7
-imm24                    \1\x0B                        ARM7
+imm24                    \x8D\xF0\xD0                   THUMB,THUMB32,ARMv4T
+immshifter               \x8D\xF0\xD0                   THUMB,THUMB32,ARMv4T
+mem32                    \x8D\xF0\xD0                   THUMB,THUMB32,ARMv4T
+
+imm24                    \x1\x0B                        ARM32,ARMv4
+mem32                    \x1\x0B                        ARM32,ARMv4
 
 [BLX]
-mem32                    \xff                        ARM7
-imm24                    \xff                        ARM7
+reg32                    \x62\x47\x80                   THUMB,ARMv4T
+
+immshifter               \x8D\xF0\xC0                   THUMB32,ARMv6T2
+imm24                    \x8D\xF0\xC0                   THUMB32,ARMv6T2
+mem32                    \x8D\xF0\xC0                   THUMB32,ARMv6T2
+
+imm24                    \x28\xFA                       ARM32,ARMv5T
+mem32                    \x28\xFA                       ARM32,ARMv5T
+reg32                    \3\x01\x2F\xFF\x30             ARM32,ARMv5T
 
 [BKPTcc]
+immshifter               \x60\xBE\x0                   THUMB,ARMv5T
+imm                      \x31\x1\x20\x70               ARM32,ARMv5T
+immshifter               \x31\x1\x20\x70               ARM32,ARMv5T
 
 [BXcc]
-reg32                    \3\x01\x2F\xFF\x10            ARM7
+reg32                    \x62\x47\x0                   THUMB,ARMv4T
+
+reg32                    \3\x01\x2F\xFF\x10            ARM32,ARMv4T
 
 [CDP]
-reg8,reg8           \300\1\x10\101                ARM7
+reg8,reg8                \300\1\x10\101                ARM32,ARMv4
 
-[CMFcc]
+[CMNcc]
+reglo,reglo             \x6B\x42\xC0                     THUMB,ARMv4T
 
-[CMFEcc]
+reg32,immshifter        \x80\xF1\x10\x0F\x00             THUMB32,ARMv6T2
+reg32,reg32             \x80\xEB\x10\x0F\x00             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop   \x80\xEB\x10\x0F\x00             THUMB32,WIDE,ARMv6T2
 
-[CMNcc]
-reg32,reg32              \xC\x1\x60                     ARM7
-reg32,reg32,reg32        \xD\x1\x60                     ARM7
-reg32,reg32,imm          \xE\x1\x60                     ARM7
-reg32,imm                \xF\x3\x60                     ARM7
+reg32,reg32             \xC\x1\x60                       ARM32,ARMv4
+reg32,reg32,shifterop   \xE\x1\x60                       ARM32,ARMv4
+reg32,immshifter        \xF\x1\x60                       ARM32,ARMv4
 
 [CMPcc]
-reg32,reg32              \xC\x1\x40                     ARM7
-reg32,reg32,reg32        \xD\x1\x40                     ARM7
-reg32,reg32,imm          \xE\x1\x40                     ARM7
-reg32,imm                \xF\x3\x40                     ARM7
+reglo,reglo             \x6B\x42\x80                     THUMB,ARMv4T
+reg32,reg32             \x61\x45\x0                      THUMB,ARMv4T
 
-[CLZcc]
-reg32,reg32              \x27\x01\x01                   ARM7
+reglo,immshifter        \x6B\x28\x0                      THUMB,ARMv4T
 
-[CNFcc]
+reg32,immshifter         \x80\xF1\xB0\x0F\x00           THUMB32,WIDE,ARMv6T2
+reg32,reg32              \x80\xEB\xB0\x0F\x00           THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop    \x80\xEB\xB0\x0F\x00           THUMB32,WIDE,ARMv6T2
 
-[COScc]
+reg32,reg32              \xC\x1\x40                     ARM32,ARMv4
+reg32,reg32,shifterop    \xE\x1\x40                     ARM32,ARMv4
+reg32,immshifter         \xF\x3\x40                     ARM32,ARMv4
 
-[CPS]
-[CPSID]
-[CPSIE]
+[CMFcc]
+fpureg,fpureg            \xA2\xE\x90                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\x90                    ARM32,FPA
 
-[DVFcc]
+[CMFEcc]
+fpureg,fpureg            \xA2\xE\xC0                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\xC0                    ARM32,FPA
 
-[EORcc]
-reg32,reg32,reg32        \4\x0\x20                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x20                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x20                     ARM7
-reg32,reg32,imm          \7\x2\x20                     ARM7
+[STFcc]
+fpureg,memam2            \xA0\xC\x00\x1\x0              ARM32,FPA
 
-[EXPcc]
+[LDFcc]
+fpureg,memam2            \xA0\xC\x10\x1\x0              ARM32,FPA
 
-[FDVcc]
+[LFMcc]
+fpureg,imm32,memam2      \xA0\xC\x10\x2\x0              ARM32,FPA
+fpureg,immshifter,memam2 \xA0\xC\x10\x2\x0              ARM32,FPA
 
-[FLTcc]
+[CLZcc]
+reg32,reg32              \x80\xFA\xB0\xF0\x80           THUMB32,ARMv6T2
+reg32,reg32              \x32\x01\x6F\xF\x10            ARM32,ARMv4
 
-[FIXcc]
+[CPS]
+immshifter               \x8F\xF3\xAF\x81\x00           THUMB32,ARMv6T2
+immshifter               \x46\xF1\x2\x0\x0              ARM32,ARMv6
 
-[FMLcc]
+[CPSID]
+modeflags                \x6C\xB6\x70                   THUMB,ARMv6
+modeflags                \x8F\xF3\xAF\x86\x00           THUMB32,WIDE,ARMv6T2
+modeflags,immshifter     \x8F\xF3\xAF\x87\x00           THUMB32,WIDE,ARMv6T2
+modeflags                \x46\xF1\xC\x0\x0              ARM32,ARMv6
+modeflags,immshifter     \x46\xF1\xE\x0\x0              ARM32,ARMv6
 
-[FRDcc]
+[CPSIE]
+modeflags                \x6C\xB6\x60                   THUMB,ARMv6
+modeflags                \x8F\xF3\xAF\x84\x00           THUMB32,WIDE,ARMv6T2
+modeflags,immshifter     \x8F\xF3\xAF\x85\x00           THUMB32,WIDE,ARMv6T2
+modeflags                \x46\xF1\x8\x0\x0              ARM32,ARMv6
+modeflags,immshifter     \x46\xF1\xA\x0\x0              ARM32,ARMv6
+
+[EORcc]
+reglo,reglo                 \x6B\x40\x40                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF0\x80\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x80\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x80\x0\x0            THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \4\x0\x20                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x20                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\x20                     ARM32,ARMv4
 
 [LDC]
-reg32,reg32         \321\300\1\x11\101            ARM7
+reg32,reg32         \321\300\1\x11\101            ARM32,ARMv4
 
 [LDMcc]
-memam4,reglist            \x26\x81                     ARM7
+memam4,reglist              \x69\xC8            THUMB,ARMv4T
+reglo,reglist               \x69\xC8            THUMB,ARMv4T
+
+memam4,reglist              \x8C\xE8\x10\x0\x0  THUMB32,WIDE,ARMv6T2
+reg32,reglist               \x8C\xE8\x10\x0\x0  THUMB32,WIDE,ARMv6T2
+
+memam4,reglist                   \x26\x81                         ARM32,ARMv4
+reg32,reglist                    \x26\x81                         ARM32,ARMv4
 
 [LDRBTcc]
+reg32,memam2              \x88\xF8\x10\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x17\x04\x70                   ARM32,ARMv4
+reg32,immshifter          \x17\x04\x70                   ARM32,ARMv4
 
 [LDRBcc]
-reg32,memam2              \x17\x07\x10                            ARM7
+reglo,memam3              \x65\x5C\x0\0                  THUMB,ARMv4T
+reglo,memam4              \x66\x78\x0\0                  THUMB,ARMv4T
+reg32,memam2              \x88\xF8\x10\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2              \x17\x04\x50                   ARM32,ARMv4
 
 [LDRcc]
-reg32,memam2              \x17\x05\x10                   ARM7
-; reg32,imm32              \x17\x05\x10                   ARM7
-; reg32,reg32              \x18\x04\x10                   ARM7
-; reg32,reg32,imm32        \x19\x04\x10                   ARM7
-; reg32,reg32,reg32        \x20\x06\x10                   ARM7
-; reg32,reg32,reg32,imm32  \x21\x06\x10                   ARM7
+reglo,memam3              \x65\x58\x0\2                  THUMB,ARMv4T
+reglo,memam4              \x66\x68\x0\2                  THUMB,ARMv4T
+reglo,memam5              \x67\x98\x0\2                  THUMB,ARMv4T
+reglo,memam6              \x67\x48\x0\2                  THUMB,ARMv4T
+reg32,memam2              \x88\xF8\x50\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2              \x17\x04\x10                   ARM32,ARMv4
 
 [LDRHcc]
-reg32,imm32              \x22\x50\xB0               ARM7
-reg32,reg32              \x23\x50\xB0               ARM7
-reg32,reg32,imm32        \x24\x50\xB0                   ARM7
-reg32,reg32,reg32        \x25\x10\xB0                   ARM7
+reglo,memam3              \x65\x5A\x0\1                  THUMB,ARMv4T
+reglo,memam4              \x66\x88\x0\1                  THUMB,ARMv4T
+reg32,memam2              \x88\xF8\x30\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2              \x22\x10\xB0                   ARM32,ARMv4
 
 [LDRSBcc]
-reg32,imm32              \x22\x50\xD0               ARM7
-reg32,reg32              \x23\x50\xD0               ARM7
-reg32,reg32,imm32        \x24\x50\xD0                   ARM7
-reg32,reg32,reg32        \x25\x10\xD0                   ARM7
+reglo,memam3              \x65\x56\x0\0                  THUMB,ARMv4T
+reg32,memam2              \x88\xF9\x10\x0\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x22\x10\xD0                   ARM32,ARMv4
+reg32,reg32               \x23\x50\xD0                   ARM32,ARMv4
+reg32,reg32,imm32         \x24\x50\xD0                   ARM32,ARMv4
+reg32,reg32,reg32         \x25\x10\xD0                   ARM32,ARMv4
 
 [LDRSHcc]
-reg32,imm32              \x22\x50\xF0               ARM7
-reg32,reg32              \x23\x50\xF0               ARM7
-reg32,reg32,imm32        \x24\x50\xF0                   ARM7
-reg32,reg32,reg32        \x25\x10\xF0                   ARM7
+reglo,memam3              \x65\x5E\x0\1                  THUMB,ARMv4T
+reg32,memam2              \x88\xF9\x30\x0\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x22\x10\xF0                   ARM32,ARMv4
 
 [LDRTcc]
+reg32,memam2              \x88\xF8\x50\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2              \x17\x04\x30                   ARM32,ARMv4
 
-[LDFcc]
+[MCRcc]
+regf,immshifter,reg32,regf,regf              \x1C\xE\x0\x1     ARM32,ARMv4
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xE\x0\x1     ARM32,ARMv4
 
-[LFMcc]
-reg32,imm8,fpureg        \xF0\x02\x01                   FPA
+[MCR2cc]
+regf,immshifter,reg32,regf,regf              \x1C\xFE\x0\x1    ARM32,ARMv5T
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xFE\x0\x1    ARM32,ARMv5T
 
-[LGNcc]
+[MRCcc]
+regf,immshifter,reg32,regf,regf              \x1C\xE\x10\x1    ARM32,ARMv4
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xE\x10\x1    ARM32,ARMv4
 
-[LOGcc]
+[MRC2cc]
+regf,immshifter,reg32,regf,regf              \x1C\xFE\x10\x1   ARM32,ARMv5T
+regf,immshifter,reg32,regf,regf,immshifter   \x1C\xFE\x10\x1   ARM32,ARMv5T
+
+[MCRRcc]
+regf,immshifter,reg32,reg32,regf             \x1D\xC\x40\x0    ARM32,ARMv5TE
+
+[MCRR2cc]
+regf,immshifter,reg32,reg32,regf             \x1D\xFC\x40\x0   ARM32,ARMv6
+
+[MRRCcc]
+regf,immshifter,reg32,reg32,regf             \x1D\xC\x50\x0    ARM32,ARMv5TE
 
-[MCR]
-; reg32,mem32         \320\301\1\x13\110            ARM7
+[MRRC2cc]
+regf,immshifter,reg32,reg32,regf             \x1D\xFC\x50\x0   ARM32,ARMv6
 
 [MLAcc]
-reg32,reg32,reg32,reg32  \x15\x00\x20\x90               ARM7
+reg32,reg32,reg32,reg32  \x80\xFB\x0\x0\x0              THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32  \x15\x00\x20\x9                ARM32,ARMv4
 
 [MOVcc]
-; reg32,shifterop              \x8\x0\0xd                   ARM7
-; reg32,immshifter             \x8\x0\0xd                  ARM7
-; reg32,reg32,reg32        \x9\x1\xA0                     ARM7
-; reg32,reg32,imm          \xA\x1\xA0                     ARM7
-; reg32,imm                \xB\x3\xA0                     ARM7
+reglo,reglo             \x6B\x0\x0                       THUMB,ARMv4T
+reg32,reg32             \x61\x46\x00                     THUMB,ARMv4T
+
+reglo,immshifter        \x6B\x20\x0                      THUMB,ARMv4T
+
+reg32,immshifter        \x80\xF0\x4F\x0\x0               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32             \x80\xEA\x4F\x0\x0               THUMB32,WIDE,ARMv6T2
 
-[MRC]
-; reg32,reg32         \321\301\1\x13\110                  ARM7
+reg32,shifterop         \x8\x1\xA0                       ARM32,ARMv4
+reg32,reg32,shifterop   \xA\x1\xA0                       ARM32,ARMv4
+reg32,immshifter        \xB\x1\xA0                       ARM32,ARMv4
 
 [MRScc]
-reg32,reg32         \x10\x01\x0F                        ARM7
+reg32,regf          \x96\xF3\xEF\x80\x0                 THUMB32,ARMv6
+reg32,regf          \x10\x01\x0F                        ARM32,ARMv4
 
 [MSRcc]
-reg32,reg32         \x11\x01\x29\xF0                    ARM7
-regf,reg32          \x12\x01\x28\xF0                    ARM7
-regf,imm            \x13\x03\x28\xF0                    ARM7
+regf,reg32          \x96\xF3\x80\x80\x0                 THUMB32,ARMv6
 
-[MNFcc]
-
-[MUFcc]
+regf,reg32          \x12\x01\x20\xF0                    ARM32,ARMv4
+regf,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
+regs,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 
 [MULcc]
-reg32,reg32,reg32        \x14\x00\x00\x90          ARM7
+reglo,reglo            \x64\x43\x40              THUMB,ARMv4T
+reglo,reglo,reglo      \x64\x43\x40              THUMB,ARMv4T
+reg32,reg32            \x80\xFB\x00\xF0\x00      THUMB32,ARMv6T2
+reg32,reg32,reg32      \x80\xFB\x00\xF0\x00      THUMB32,ARMv6T2
+reg32,reg32,reg32      \x14\x00\x00\x90          ARM32,ARMv4
 
 [MVFcc]
-fpureg,fpureg              \xF2                      FPA
-fpureg,immfpu              \xF2                      FPA
+fpureg,fpureg               \xA1\1\x1                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x1                     ARM32,FPA
 
 [MVNcc]
-; reg32,reg32         \x8\x0\0xf                     ARM7
-; reg32,reg32,reg32   \x9\x1\xE0                     ARM7
-; reg32,reg32,imm     \xA\x1\xE0                     ARM7
-; reg32,imm           \xB\x3\xE0                     ARM7
+reglo,reglo             \x6B\x43\xc0                    THUMB,ARMv4T
 
-[NOP]
+reg32,immshifter        \x80\xF0\x6F\x0\x0               THUMB32,ARMv6T2
+reg32,reg32             \x80\xEA\x6F\x0\x0               THUMB32,WIDE,ARMv6T2
 
-[ORRcc]
-reg32,reg32,reg32        \4\x1\x80                     ARM7
-reg32,reg32,reg32,reg32  \5\x1\x80                     ARM7
-reg32,reg32,reg32,imm    \6\x1\x80                     ARM7
-reg32,reg32,imm          \7\x3\x80                     ARM7
+reg32,reg32            \x8\x1\xE0                       ARM32,ARMv4
+reg32,reg32,shifterop  \xA\x1\xE0                       ARM32,ARMv4
+reg32,immshifter       \xB\x1\xE0                       ARM32,ARMv4
 
-[RDFcc]
+[VMOVcc]
+vreg,vreg         \x90\xEE\xB0\xA\x40            THUMB32,VFPv2
+vreg,vreg         \x40\xE\xB0\xA\x40            ARM32,VFPv2
 
-[RFScc]
+reg32,vreg        \x90\xEE\x10\xA\x10            THUMB32,VFPv2
+vreg,reg32        \x90\xEE\x00\xA\x10            THUMB32,VFPv2
+reg32,vreg        \x40\xE\x10\xA\x10            ARM32,VFPv2
+vreg,reg32        \x40\xE\x00\xA\x10            ARM32,VFPv2
 
-[RFCcc]
+reg32,reg32,vreg,vreg \x90\xEC\x50\xA\x10        THUMB32,VFPv2
+vreg,vreg,reg32,reg32 \x90\xEC\x40\xA\x10        THUMB32,VFPv2
+reg32,reg32,vreg,vreg \x40\xC\x50\xA\x10        ARM32,VFPv2
+vreg,vreg,reg32,reg32 \x40\xC\x40\xA\x10        ARM32,VFPv2
 
-[RMFcc]
+reg32,reg32,vreg      \x90\xEC\x50\xB\x10        THUMB32,VFPv2
+vreg,reg32,reg32      \x90\xEC\x40\xB\x10        THUMB32,VFPv2
+reg32,reg32,vreg      \x40\xC\x50\xB\x10        ARM32,VFPv2
+vreg,reg32,reg32      \x40\xC\x40\xB\x10        ARM32,VFPv2
 
-[RPWcc]
+[NOP]
+void                    \x61\xBF\x0                  THUMB,ARMv6T2
+void                    \x2F\x03\x20\xF0\x0          ARM32,ARMv6K
+; Before ARMv6K use mov r0,r0
+void                    \x2F\xE1\xA0\x0\x0           ARM32,ARMv4
+
+[ORNcc]
+reg32,immshifter            \x80\xF0\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x60\x0\x0            THUMB32,ARMv6T2
 
-[RSBcc]
-reg32,reg32,reg32        \4\x0\x60                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\x60                     ARM7
-reg32,reg32,reg32,imm    \6\x0\x60                     ARM7
-reg32,reg32,imm          \7\x2\x60                     ARM7
+[ORRcc]
+reglo,reglo                  \x6B\x43\x00            THUMB,ARMv4T
 
-[RSCcc]
-reg32,reg32,reg32        \4\x0\xE0                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\xE0                     ARM7
-reg32,reg32,reg32,imm    \6\x0\xE0                     ARM7
-reg32,reg32,imm          \7\x2\xE0                     ARM7
+reg32,immshifter            \x80\xF0\x40\x0\x0       THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF0\x40\x0\x0       THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x40\x0\x0       THUMB32,WIDE,ARMv6T2
 
-[RSFcc]
+reg32,reg32,reg32            \4\x1\x80               ARM32,ARMv4
+reg32,reg32,reg32,reg32      \5\x1\x80               ARM32,ARMv4
+reg32,reg32,reg32,shifterop  \6\x1\x80               ARM32,ARMv4
+reg32,reg32,immshifter       \7\x3\x80               ARM32,ARMv4
 
-[RNDcc]
+[RSBcc]
+reglo,reglo,immzero         \x6B\x42\x40                  THUMB,ARMv4T
 
-[POLcc]
+reg32,immshifter            \x80\xF1\xC0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32                 \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\xC0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\xC0\x0\x0             THUMB32,ARMv6T2
+
+reg32,reg32,reg32            \6\x0\x60                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop  \6\x0\x60                     ARM32,ARMv4
+reg32,reg32,immshifter       \7\x0\x60                     ARM32,ARMv4
+
+[RSCcc]
+reg32,reg32,reg32            \4\x0\xE0                     ARM32,ARMv4
+reg32,reg32,reg32,reg32      \5\x0\xE0                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop  \6\x0\xE0                     ARM32,ARMv4
+reg32,reg32,immshifter       \7\x2\xE0                     ARM32,ARMv4
 
 [SBCcc]
-reg32,reg32,reg32        \4\x0\xC0                     ARM7
-reg32,reg32,reg32,reg32  \5\x0\xC0                     ARM7
-reg32,reg32,reg32,imm    \6\x0\xC0                     ARM7
-reg32,reg32,imm          \7\x2\xC0                     ARM7
+reglo,reglo                 \x6B\x41\x80                  THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF1\x60\x0\x0             THUMB32,ARMv6T2
+reg32,reg32                 \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\x60\x0\x0             THUMB32,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x60\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32           \4\x0\xC0                     ARM32,ARMv4
+reg32,reg32,reg32,reg32     \5\x0\xC0                     ARM32,ARMv4
+reg32,reg32,reg32,imm       \6\x0\xC0                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xC0                     ARM32,ARMv4
+reg32,reg32,immshifter      \7\x2\xC0                     ARM32,ARMv4
 
 [SFMcc]
-reg32,imm8,fpureg        \xF0\x02\x00                   FPA
+fpureg,imm32,memam2      \xA0\xC\x00\x2\x0              ARM32,FPA
+fpureg,immshifter,memam2 \xA0\xC\x00\x2\x0              ARM32,FPA
 
 [SINcc]
+fpureg,fpureg               \xA1\1\x11                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x11                    ARM32,FPA
 
 [SMLALcc]
-reg32,reg32,reg32,reg32  \x16\x00\xE0\x90               ARM7
+reg32,reg32,reg32,reg32     \x85\xFB\xC0\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\xE0\x9               ARM32,ARMv4
 
 [SMULLcc]
-reg32,reg32,reg32,reg32  \x16\x00\xC0\x90               ARM7
-
-[SQTcc]
+reg32,reg32,reg32,reg32     \x85\xFB\x80\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\xC0\x9               ARM32,ARMv4
 
-[SUFcc]
+[STMcc]
+memam4,reglist              \x69\xC0            THUMB,ARMv4T
+reglo,reglist               \x69\xC0            THUMB,ARMv4T
 
-[STFcc]
+memam4,reglist              \x8C\xE8\x00\x0\x0  THUMB32,WIDE,ARMv6T2
+reg32,reglist               \x8C\xE8\x00\x0\x0  THUMB32,WIDE,ARMv6T2
 
-[STMcc]
-memam4,reglist            \x26\x80                     ARM7
+memam4,reglist                   \x26\x80                         ARM32,ARMv4
+reg32,reglist                    \x26\x80                         ARM32,ARMv4
 
 [STRcc]
-reg32,memam2              \x17\x04\x00                   ARM7
-; reg32,imm32              \x17\x05\x00                   ARM7
-; reg32,reg32              \x18\x04\x00                   ARM7
-; reg32,reg32,imm32        \x19\x04\x00                   ARM7
-; reg32,reg32,reg32        \x20\x06\x00                   ARM7
-; reg32,reg32,reg32,imm32  \x21\x06\x00                   ARM7
+reglo,memam3                \x65\x50\x0\2                  THUMB,ARMv4T
+reglo,memam4                \x66\x60\x0\2                  THUMB,ARMv4T
+reglo,memam5                \x67\x90\x0\2                  THUMB,ARMv4T
+reg32,memam2                \x88\xF8\x40\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x17\x04\x00                   ARM32,ARMv4
 
 [STRBcc]
-reg32,memam2              \x17\x06\x00                           ARM7
+reglo,memam3                \x65\x54\x0\0                  THUMB,ARMv4T
+reglo,memam4                \x66\x70\x0\0                  THUMB,ARMv4T
+reg32,memam2                \x88\xF8\x00\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x17\x04\x40                   ARM32,ARMv4
 
 [STRBTcc]
+reg32,memam2                \x88\xF8\x00\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2                \x17\x04\x60                   ARM32,ARMv4
+reg32,immshifter            \x17\x04\x60                   ARM32,ARMv4
 
-; A dummy since it is parsed as STR{cond}H
 [STRHcc]
-reg32,imm32              \x22\x40\xB0              ARM7
-reg32,reg32              \x23\x40\xB0               ARM7
-reg32,reg32,imm32        \x24\x40\xB0                   ARM7
-reg32,reg32,reg32        \x25\x00\xB0                   ARM7
+reglo,memam3                \x65\x52\x0\1                  THUMB,ARMv4T
+reglo,memam4                \x66\x80\x0\1                  THUMB,ARMv4T
+reg32,memam2                \x88\xF8\x20\x0\x0\0           THUMB32,WIDE,ARMv6T2
+reg32,memam2                \x22\x00\xB0                   ARM32,ARMv4
 
 [STRTcc]
+reg32,memam2                \x88\xF8\x40\xE\x0\0           THUMB32,ARMv6T2
+reg32,memam2                \x17\x04\x20                   ARM32,ARMv4
 
 [SUBcc]
-reg32,reg32,shifterop     \4\x0\x40                     ARM7
-reg32,reg32,immshifter    \4\x0\x40                     ARM7
-reg32,reg32,reg32        \4\x0\x40                     ARM7
-; reg32,reg32,reg32,reg32  \5\x0\x40                     ARM7
-; reg32,reg32,reg32,imm    \6\x0\x40                     ARM7
-; reg32,reg32,imm          \7\x2\x40                     ARM7
+regsp,immshifter            \x64\xB0\x80                   THUMB,ARMv4T
+regsp,regsp,immshifter      \x64\xB0\x80                   THUMB,ARMv4T
+reglo,reglo                 \x60\x1A\x0                    THUMB,ARMv4T
+reglo,reglo,reglo           \x60\x1A\x0                    THUMB,ARMv4T
+
+reglo,immshifter            \x60\x1E\x0                    THUMB,ARMv4T
+reglo,reglo,immshifter      \x60\x1E\x0                    THUMB,ARMv4T
+reglo,imm8                  \x6B\x38\x0                    THUMB,ARMv4T
+reglo,immshifter            \x6B\x38\x0                    THUMB,ARMv4T
+
+reg32,immshifter            \x80\xF1\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32                 \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter      \x80\xF1\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32           \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\xA0\x0\x0             THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,shifterop       \x4\x0\x40                     ARM32,ARMv4
+reg32,reg32,immshifter      \x4\x0\x40                     ARM32,ARMv4
+reg32,reg32,reg32           \x4\x0\x40                     ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x0\x40                     ARM32,ARMv4
 
 [SWIcc]
-imm                 \2\x0F                        ARM7
+; Old alias for SVC
 
 [SWPcc]
-reg32,reg32,reg32   \x27\x01\x90                   ARM7
+reg32,reg32,memam2          \x27\x10\x09                   ARM32,ARMv4
 
 [SWPBcc]
-reg32,reg32,reg32   \x27\x01\x90                   ARM7
-
-[TANcc]
+reg32,reg32,memam2          \x27\x14\x09                   ARM32,ARMv4
 
 [TEQcc]
-reg32,reg32         \xC\x1\x20                     ARM7
-reg32,reg32,reg32   \xD\x1\x20                     ARM7
-reg32,reg32,imm     \xE\x1\x20                     ARM7
-reg32,imm           \xF\x3\x20                     ARM7
+reg32,immshifter      \x80\xF0\x90\x0F\x00           THUMB32,ARMv6T2
+reg32,reg32           \x80\xEA\x90\x0F\x00           THUMB32,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x90\x0F\x00           THUMB32,ARMv6T2
+
+reg32,reg32           \xC\x1\x20                     ARM32,ARMv4
+reg32,reg32,reg32     \xD\x1\x20                     ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x20                     ARM32,ARMv4
+reg32,immshifter      \xF\x3\x20                     ARM32,ARMv4
 
 [TSTcc]
-reg32,reg32         \xC\x1\x00                     ARM7
-reg32,reg32,reg32   \xD\x1\x00                     ARM7
-reg32,reg32,imm     \xE\x1\x00                     ARM7
-reg32,imm           \xF\x3\x00                     ARM7
+reglo,reglo           \x6B\x42\x00                   THUMB,ARMv4T
+
+reg32,immshifter      \x80\xF0\x10\x0F\x00           THUMB32,ARMv6T2
+reg32,reg32           \x80\xEA\x10\x0F\x00           THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x10\x0F\x00           THUMB32,WIDE,ARMv6T2
+
+reg32,reg32           \xC\x1\x00                     ARM32,ARMv4
+reg32,reg32,reg32     \xD\x1\x00                     ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x00                     ARM32,ARMv4
+reg32,immshifter      \xF\x3\x00                     ARM32,ARMv4
 
 [UMLALcc]
-reg32,reg32,reg32,reg32  \x16\x00\xA0\x90               ARM7
+reg32,reg32,reg32,reg32     \x85\xFB\xE0\x0\x00     THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\xA0\x9         ARM32,ARMv4
 
 [UMULLcc]
-reg32,reg32,reg32,reg32  \x16\x00\x80\x90               ARM7
+reg32,reg32,reg32,reg32     \x85\xFB\xA0\x0\x0      THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x00\x80\x9         ARM32,ARMv4
 
 [WFScc]
+reg32                      \xA2\xE\x2               ARM32,FPA
 
 ; EDSP instructions
 [LDRDcc]
-
-[MCRRcc]
-
-[MRRCcc]
+reg32,reg32,memam2         \x89\xE8\x50\x0\x0                  THUMB32,ARMv6T2
+reg32,reg32,memam2         \x19\x0\x0\x0\xD0                   ARM32,ARMv4
 
 [PLD]
+memam2                     \x87\xF8\x10\xF0\x0                 THUMB32,ARMv6T2
+memam2                     \x25\xF5\x50\xF0\x0                 ARM32,ARMv5TE
+
+[PLDW]
+memam2                     \x87\xF8\x30\xF0\x0                 THUMB32,ARMv7
+memam2                     \x25\xF5\x10\xF0\x0                 ARM32,ARMv7
 
 [QADDcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\x80                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x00\x05                    ARM32,ARMv5TE
 
 [QDADDcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\x90                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x40\x05                    ARM32,ARMv5TE
 
 [QDSUBcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\xB0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x60\x05                    ARM32,ARMv5TE
 
 [QSUBcc]
+reg32,reg32,reg32          \x82\xFA\x80\xF0\xA0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x1A\x01\x20\x05                    ARM32,ARMv5TE
 
 [SMLABBcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\x8                     ARM32,ARMv5TE
 
 [SMLABTcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\xC                     ARM32,ARMv5TE
 
 [SMLATBcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\xA                     ARM32,ARMv5TE
 
 [SMLATTcc]
+reg32,reg32,reg32,reg32     \x15\x01\x00\xE                     ARM32,ARMv5TE
 
 [SMLALBBcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\x8                     ARM32,ARMv5TE
 
 [SMLALBTcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\xC                     ARM32,ARMv5TE
 
 [SMLALTBcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\xA                     ARM32,ARMv5TE
 
 [SMLALTTcc]
+reg32,reg32,reg32,reg32     \x16\x01\x40\xE                     ARM32,ARMv5TE
 
 [SMLAWBcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x30\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x1\x20\x8                      ARM32,ARMv5TE
 
 [SMLAWTcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x30\x0\x10                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x1\x20\xC                      ARM32,ARMv5TE
+
+[VLDMcc]
+memam4,reglist               \x94\xEC\x10\xA                    THUMB32,VFPv2
+reg32,reglist                \x94\xEC\x10\xA                    THUMB32,VFPv2
+memam4,reglist               \x44\xC\x10\xA                     ARM32,VFPv2
+reg32,reglist                \x44\xC\x10\xA                     ARM32,VFPv2
+
+[VSTMcc]
+memam4,reglist               \x94\xEC\x00\xA                    THUMB32,VFPv2
+reg32,reglist                \x94\xEC\x00\xA                    THUMB32,VFPv2
+memam4,reglist               \x44\xC\x00\xA                     ARM32,VFPv2
+reg32,reglist                \x44\xC\x00\xA                     ARM32,VFPv2
+
+[VPOP]
+reglist                            \x94\xEC\xBD\xA                      THUMB32,VFPv2
+reglist                            \x44\xC\xBD\xA                       ARM32,VFPv2
+
+[VPUSH]
+reglist                            \x94\xED\x2D\xA                      THUMB32,VFPv2
+reglist                            \x44\xD\x2D\xA                       ARM32,VFPv2
+
+[VLDRcc]
+vreg,memam2             \x95\xED\x10\xA             THUMB32,VFPv2
+vreg,memam2             \x45\xD\x10\xA             ARM32,VFPv2
+
+[VSTRcc]
+vreg,memam2             \x95\xED\x0\xA              THUMB32,VFPv2
+vreg,memam2             \x45\xD\x0\xA              ARM32,VFPv2
 
 [SMULBBcc]
+reg32,reg32,reg32           \x15\x01\x60\x8\x0                  ARM32,ARMv5TE
 
 [SMULBTcc]
+reg32,reg32,reg32           \x15\x01\x60\xC\x0                  ARM32,ARMv5TE
 
 [SMULTBcc]
+reg32,reg32,reg32           \x15\x01\x60\xA\x0                  ARM32,ARMv5TE
 
 [SMULTTcc]
+reg32,reg32,reg32           \x15\x01\x60\xE\x0                  ARM32,ARMv5TE
 
 [SMULWBcc]
+reg32,reg32,reg32           \x14\x1\x20\xA0                     ARM32,ARMv5TE
 
 [SMULWTcc]
+reg32,reg32,reg32           \x14\x1\x20\xE0                     ARM32,ARMv5TE
 
 [STRDcc]
+reg32,reg32,memam2         \x89\xE8\x40\x0\x0                  THUMB32,ARMv6T2
+reg32,reg32,memam2         \x19\x0\x0\x0\xF0                   ARM32,ARMv4
 
-;
-; vfp instructions
-;
-[FABSDcc]
+[LDRHTcc]
+reg32,memam2               \x88\xF8\x30\xE\x0\0                THUMB32,ARMv6T2
+reg32,memam2               \x19\x0\x30\x0\xB0                  ARM32,ARMv4
 
-[FABSScc]
+[STRHTcc]
+reg32,memam2               \x88\xF8\x20\xE\x0\0                THUMB32,ARMv6T2
 
-[FADDDcc]
+reg32,memam2               \x88\xF8\x20\xE\x0\0                THUMB32,ARMv6T2
+reg32,memam2               \x1E\x0\x20\x0\xB0                  ARM32,ARMv4
 
-[FADDScc]
+[LDRSBTcc]
+reg32,memam2               \x88\xF9\x10\xE\x0\0                THUMB32,ARMv6T2
+reg32,memam2               \x1E\x0\x30\x0\xD0                  ARM32,ARMv4
 
-[FCMPDcc]
+[LDRSHTcc]
+reg32,memam2              \x88\xF9\x30\xE\x0\0                 THUMB32,ARMv6T2
+reg32,memam2              \x1E\x0\x30\x0\xF0                   ARM32,ARMv4
 
-[FCMPEDcc]
+[FSTDcc]
+vreg,memam2             \x95\xED\x0\xA                         THUMB32,VFPv2
+vreg,memam2             \x45\xD\x0\xA                          ARM32,VFPv2
 
-[FCMPEScc]
+[FSTMcc]
+memam4,reglist               \x94\xEC\x00\xA                             THUMB32,VFPv2
+reg32,reglist                \x94\xEC\x00\xA                             THUMB32,VFPv2
+memam4,reglist               \x44\xC\x00\xA                                 ARM32,VFPv2
+reg32,reglist                \x44\xC\x00\xA                                 ARM32,VFPv2
 
-[FCMPEZDcc]
+[FSTScc]
+vreg,memam2             \x95\xED\x0\xA                         THUMB32,VFPv2
+vreg,memam2             \x45\xD\x0\xA                          ARM32,VFPv2
 
-[FCMPEZScc]
+; ARMv6
 
-[FCMPScc]
+[BFCcc]
+reg32,immshifter,immshifter       \x84\xF3\x6F\x0\x0            THUMB32,ARMv6T2
+reg32,immshifter,imm32            \x84\xF3\x6F\x0\x0            THUMB32,ARMv6T2
 
-[FCMPZDcc]
+reg32,immshifter,immshifter       \x2D\x7\xC0\x0\x1F            ARM32,ARMv4
+reg32,immshifter,imm32            \x2D\x7\xC0\x0\x1F            ARM32,ARMv4
 
-[FCMPZScc]
+[BFIcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\x60\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,immshifter,imm32      \x84\xF3\x60\x0\x0            THUMB32,ARMv6T2
 
-[FCPYDcc]
+reg32,reg32,immshifter,immshifter \x2D\x7\xC0\x0\x10            ARM32,ARMv4
+reg32,reg32,immshifter,imm32      \x2D\x7\xC0\x0\x10            ARM32,ARMv4
 
-[FCPYScc]
+[CLREX]
+void                      \x80\xF3\xBF\x8F\x2F            THUMB32,ARMv7
+void                      \x2F\xF5\x7F\xF0\x1F            ARM32,ARMv6K
 
-[FCVTDScc]
+[LDREXcc]
+reg32,memam6              \x8A\xE8\x50\x0F\x00            THUMB32,ARMv6T2
+reg32,memam6              \x18\x01\x90\x0F\x9F            ARM32,ARMv4
 
-[FCVTSDcc]
+[LDREXBcc]
+reg32,memam6              \x8A\xE8\xD0\x0F\x4F            THUMB32,ARMv7
+reg32,memam6              \x18\x01\xD0\x0F\x9F            ARM32,ARMv4
 
-[FDIVDcc]
+[LDREXDcc]
+reg32,reg32,memam6        \x8A\xE8\xD0\x00\x7F            THUMB32,ARMv7
+reg32,reg32,memam6        \x18\x01\xB0\x0F\x9F            ARM32,ARMv4
 
-[FDIVScc]
+[LDREXHcc]
+reg32,memam6              \x8A\xE8\xD0\x0F\x5F            THUMB32,ARMv7
+reg32,memam6              \x18\x01\xF0\x0F\x9F            ARM32,ARMv4
 
-[FLDDcc]
+[STREXcc]
+reg32,reg32,memam6        \x8B\xE8\x40\x00\x00            THUMB32,ARMv6T2
+reg32,reg32,memam6        \x18\x01\x80\x0F\x90            ARM32,ARMv4
 
-[FLDMcc]
+[STREXBcc]
+reg32,reg32,memam6        \x8B\xE8\xC0\x0F\x40            THUMB32,ARMv7
+reg32,reg32,memam6        \x18\x01\xC0\x0F\x90            ARM32,ARMv4
 
-[FLDScc]
+[STREXDcc]
+reg32,reg32,reg32,memam6  \x8B\xE8\xC0\x00\x70            THUMB32,ARMv7
+reg32,reg32,reg32,memam6  \x18\x01\xA0\x0F\x90            ARM32,ARMv4
 
-[FMACDcc]
+[STREXHcc]
+reg32,reg32,memam6        \x8B\xE8\xC0\x0F\x50            THUMB32,ARMv7
+reg32,reg32,memam6        \x18\x01\xE0\x0F\x90            ARM32,ARMv4
 
-[FMACScc]
+[MLScc]
+reg32,reg32,reg32,reg32   \x80\xFB\x0\x0\x10              THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32   \x15\x00\x60\x9                 ARM32,ARMv6T2
 
-[FMDHRcc]
+[PKHBTcc]
+reg32,reg32,reg32           \x80\xEA\xC0\x0\x0            THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x0            THUMB32,ARMv6T2
 
-[FMDLRcc]
+reg32,reg32,reg32           \x16\x6\x80\x1                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\x80\x1                     ARM32,ARMv6
 
-[FMRDHcc]
+[PKHTBcc]
+reg32,reg32,reg32           \x80\xEA\xC0\x0\x10           THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x10           THUMB32,ARMv6T2
 
-[FMRDLcc]
+reg32,reg32,reg32           \x16\x6\x80\x1                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\x80\x5                     ARM32,ARMv6
 
-[FMRScc]
+[PLI]
+memam2                     \x87\xF9\x10\xF0\x0                 THUMB32,ARMv7
+memam2                     \x25\xF4\x50\xF0\x0                 ARM32,ARMv7
 
-[FMRXcc]
+[QADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF1                    ARM32,ARMv6
+[QADD8cc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF9                    ARM32,ARMv6
+[QASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF3                    ARM32,ARMv6
+[QSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF5                    ARM32,ARMv6
+[QSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xF7                    ARM32,ARMv6
+[QSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x10                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x20\xFF                    ARM32,ARMv6
 
-[FMSCDcc]
+[RBITcc]
+reg32,reg32                \x80\xFA\x90\xF0\xA0                THUMB32,ARMv6T2
+reg32,reg32                \x32\x6\xFF\xF\x30                  ARM32,ARMv6T2
 
-[FMSCScc]
+[REVcc]
+reglo,reglo                \x61\xBA\x00                        THUMB,ARMv6
+reg32,reg32                \x80\xFA\x90\xF0\x80                THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x32\x6\xBF\xF\x30                  ARM32,ARMv6
 
-[FMSRcc]
+[REV16cc]
+reglo,reglo                \x61\xBA\x40                        THUMB,ARMv6
+reg32,reg32                \x80\xFA\x90\xF0\x90                THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x32\x6\xBF\xF\xB0                  ARM32,ARMv6
 
-[FMSTATcc]
+[REVSHcc]
+reglo,reglo                \x61\xBA\xC0                        THUMB,ARMv6
+reg32,reg32                \x80\xFA\x90\xF0\xB0                THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x32\x6\xFF\xF\xB0                  ARM32,ARMv6
 
-[FMULDcc]
+[SADD16cc]
+reg32,reg32,reg32          \x80\xFA\90\xF0\x0                  THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF1                    ARM32,ARMv6
 
-[FMULScc]
+[SADD8cc]
+reg32,reg32,reg32          \x80\xFA\80\xF0\x0                  THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF9                    ARM32,ARMv6
 
-[FMXRcc]
+[SASXcc]
+reg32,reg32,reg32          \x80\xFA\A0\xF0\x0                  THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF3                    ARM32,ARMv6
 
-[FNEGDcc]
+[SBFXcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\x40\x0\x0           THUMB32,ARMv6T2
+reg32,reg32,immshifter,immshifter \x2D\x7\xA0\x0\x50           ARM32,ARMv6T2
 
-[FNEGScc]
+[SELcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x80                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x80\xFB                    ARM32,ARMv6
 
-[FNMACDcc]
+[SETEND]
+immshifter                 \x2B\xF1\x01\x0\x0                  ARM32,ARMv6
 
-[FNMACScc]
+[SEVcc]
+void                       \x64\xBF\x40                        THUMB,ARMv7
+void                       \x2F\x3\x20\xF0\x4                  ARM32,ARMv6K
 
-[FNMSCDcc]
+[ASRcc]
+reglo,immshifter           \x60\x1\x0                          THUMB,ARMv4T
+reglo,reglo,immshifter     \x60\x1\x0                          THUMB,ARMv4T
+reglo,reglo                \x6B\x41\x0                         THUMB,ARMv4T
 
-[FNMSCScc]
+reg32,immshifter           \x82\xEA\x4F\x0\x20                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x20                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x40\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x40\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FNMULDcc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x50                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x40                  ARM32,ARMv4
 
-[FNMULScc]
+[LSRcc]
+reglo,immshifter           \x60\x8\x0                          THUMB,ARMv4T
+reglo,reglo,immshifter     \x60\x8\x0                          THUMB,ARMv4T
+reglo,reglo                \x6B\x40\xC0                        THUMB,ARMv4T
 
-[FSITODcc]
+reg32,immshifter           \x82\xEA\x4F\x0\x10                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x10                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x20\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x20\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FSITOScc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x30                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x20                  ARM32,ARMv4
 
-[FSQRTDcc]
+[LSLcc]
+reglo,immshifter           \x60\x0\x0                          THUMB,ARMv4T
+reglo,reglo,immshifter     \x60\x0\x0                          THUMB,ARMv4T
+reglo,reglo                \x6B\x40\x80                        THUMB,ARMv4T
 
-[FSQRTScc]
+reg32,immshifter           \x82\xEA\x4F\x0\x00                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x00                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FSTDcc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x10                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x00                  ARM32,ARMv4
 
-[FSTMcc]
+[RORcc]
+reglo,reglo                \x6B\x41\xC0                        THUMB,ARMv4T
 
-[FSTScc]
+reg32,immshifter           \x82\xEA\x4F\x0\x30                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter     \x82\xEA\x4F\x0\x30                 THUMB32,WIDE,ARMv6T2
+reg32,reg32                \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32          \x80\xFA\x60\xF0\x0                 THUMB32,WIDE,ARMv6T2
 
-[FSUBDcc]
+reg32,reg32,reg32          \x30\x1\xA0\x0\x70                  ARM32,ARMv4
+reg32,reg32,immshifter     \x30\x1\xA0\x0\x60                  ARM32,ARMv4
 
-[FSUBScc]
+[RRXcc]
+reg32,reg32                \x80\xEA\x4F\x00\x30                THUMB32,ARMv6T2
+reg32,reg32                \x30\x1\xA0\x0\x60                  ARM32,ARMv4
 
-[FTOSIDcc]
+[UMAALcc]
+reg32,reg32,reg32,reg32     \x85\xFB\xE0\x0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32     \x16\x0\x40\x9                     ARM32,ARMv6
 
-[FTOSIScc]
+[SHADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF1                    ARM32,ARMv6
 
-[FTOUIDcc]
+[SHADD8cc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF9                    ARM32,ARMv6
 
-[FTOUIScc]
+[SHASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF3                    ARM32,ARMv6
 
-[FUITODcc]
+[SHSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF5                    ARM32,ARMv6
 
-[FUITOScc]
+[SHSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xF7                    ARM32,ARMv6
 
-[FMDRRcc]
+[SHSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x20                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x30\xFF                    ARM32,ARMv6
 
-[FMRRDcc]
+[SMLADcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x20\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x00\x1                      ARM32,ARMv6
 
-; ARMv6
+[SMLALDcc]
+reg32,reg32,reg32,reg32    \x85\xFB\xC0\x0\xC0                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x16\x7\x40\x1                      ARM32,ARMv4
 
-[BFCcc]
+[SMLSDcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x40\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x00\x5                      ARM32,ARMv6
 
-[BFIcc]
+[SMLSLDcc]
+reg32,reg32,reg32,reg32    \x85\xFB\xD0\x0\xC0                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x16\x7\x40\x5                      ARM32,ARMv6
 
-[CLREX]
+[SMMLAcc]
+reg32,reg32,reg32,reg32    \x80\xFB\x50\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x50\x1                      ARM32,ARMv6
 
-[LDREXcc]
-[LDREXBcc]
-[LDREXDcc]
-[LDREXHcc]
+[SMMLScc]
+reg32,reg32,reg32,reg32    \x80\xFB\x60\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x7\x50\xD                      ARM32,ARMv6
 
-[MLScc]
+[SMMULcc]
+reg32,reg32,reg32          \x80\xFB\x50\xF0\x0                 THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x7\x50\x1\xF                   ARM32,ARMv6
 
-[PKHcc]
+[SMUADcc]
+reg32,reg32,reg32          \x80\xFB\x20\xF0\x0                 THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x7\x00\x1\xF                   ARM32,ARMv6
 
-[PLI]
+[SMUSDcc]
+reg32,reg32,reg32          \x80\xFB\x40\xF0\x0                 THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x7\x00\x5\xF                   ARM32,ARMv6
 
-[QADD16cc]
-[QADD8cc]
-[QASXcc]
-[QSAXcc]
-[QSUB16cc]
-[QSUB8cc]
+[SRScc]
 
-[RBITcc]
+[SSATcc]
+reg32,immshifter,reg32            \x83\xF3\x00\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32,shifterop  \x83\xF3\x00\x0\x0          THUMB32,ARMv6T2
 
-[REVcc]
-[REV16cc]
-[REVSHcc]
+reg32,immshifter,reg32            \x2A\x6\xA0\x0\x10          ARM32,ARMv6
+reg32,immshifter,reg32,shifterop  \x2A\x6\xA0\x0\x10          ARM32,ARMv6
 
-[SADD16cc]
-[SADD8cc]
-[SASXcc]
+[SSAT16cc]
+reg32,immshifter,reg32            \x83\xF3\x20\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32            \x2A\x6\xA0\xF\x30          ARM32,ARMv6
 
-[SBFXcc]
+[SSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF5                   ARM32,ARMv6
 
-[SELcc]
+[SSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xF7                   ARM32,ARMv6
 
-[SETEND]
+[SSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x0                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x10\xFF                   ARM32,ARMv6
 
-[SEVcc]
+[SXTABcc]
+reg32,reg32,reg32           \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
 
-[ASRcc]
+reg32,reg32,reg32           \x16\x06\xA0\x07                  ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\xA0\x07                  ARM32,ARMv6
 
-[LSRcc]
+[SXTAB16cc]
+reg32,reg32,reg32           \x86\xFA\x20\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x20\xF0\x80              THUMB32,ARMv6T2
 
-[LSLcc]
+reg32,reg32,reg32           \x16\x06\x80\x07                  ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\x80\x07                  ARM32,ARMv6
 
-[RORcc]
+[SXTAHcc]
+reg32,reg32,reg32           \x86\xFA\x00\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x00\xF0\x80              THUMB32,ARMv6T2
 
-[SHADD16cc]
-[SHADD8cc]
-[SHASXcc]
-[SHSAXcc]
-[SHSUB16cc]
-[SHSUB8cc]
+reg32,reg32,reg32           \x16\x06\xB0\x07                  ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\xB0\x07                  ARM32,ARMv6
 
-[SMLADcc]
-[SMLALDcc]
-[SMLSDcc]
-[SMLSLDcc]
-[SMMLAcc]
-[SMMLScc]
-[SMMULcc]
-[SMUADcc]
-[SMUSDcc]
+[UBFXcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\xC0\x0\x0          THUMB32,ARMv6T2
+reg32,reg32,immshifter,immshifter \x2D\x7\xE0\x0\x50          ARM32,ARMv4
 
-[SRScc]
+[UXTABcc]
+reg32,reg32,reg32           \x86\xFA\x50\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x50\xF0\x80              THUMB32,ARMv6T2
 
-[SSATcc]
-[SSAT16cc]
-[SSAXcc]
+reg32,reg32,reg32           \x16\x6\xE0\x7                    ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xE0\x7                    ARM32,ARMv6
 
-[SSUB16cc]
-[SSUB8cc]
+[UXTAB16cc]
+reg32,reg32,reg32           \x86\xFA\x30\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x30\xF0\x80              THUMB32,ARMv6T2
 
-[STREXcc]
-[STREXBcc]
-[STREXDcc]
-[STREXHcc]
+reg32,reg32,reg32           \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x40\xF0\x80              THUMB32,ARMv6T2
+
+reg32,reg32,reg32           \x16\x6\xC0\x7                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xC0\x7                     ARM32,ARMv6
+
+[UXTAHcc]
+reg32,reg32,reg32           \x86\xFA\x10\xF0\x80              THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x10\xF0\x80              THUMB32,ARMv6T2
+
+reg32,reg32,reg32           \x16\x6\xF0\x7                     ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xF0\x7                     ARM32,ARMv6
 
-[SXTABcc]
-[SXTAB16cc]
-[SXTAHcc]
 [SXTBcc]
+reglo,reglo                 \x61\xB2\x40                       THUMB,ARMv6
+
+reg32,reg32                 \x86\xFA\x4F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x4F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xAF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xAF\x7                     ARM32,ARMv6
+
 [SXTB16cc]
+reg32,reg32                 \x86\xFA\x2F\xF0\x80               THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x2F\xF0\x80               THUMB32,ARMv6T2
+
+reg32,reg32                 \x1B\x6\x8F\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\x8F\x7                     ARM32,ARMv6
+
+[SXTHcc]
+reglo,reglo                 \x61\xB2\x00                       THUMB,ARMv6
+
+reg32,reg32                 \x86\xFA\x0F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x0F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xBF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xBF\x7                     ARM32,ARMv6
 
 [UXTBcc]
+reglo,reglo                 \x61\xB2\xC0                       THUMB,ARMv6
+
+reg32,reg32                 \x86\xFA\x5F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x5F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xEF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xEF\x7                     ARM32,ARMv6
+
+[UXTB16cc]
+reg32,reg32                 \x86\xFA\x3F\xF0\x80               THUMB32,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x3F\xF0\x80               THUMB32,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xCF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xCF\x7                     ARM32,ARMv6
+
 [UXTHcc]
+reglo,reglo                 \x61\xB2\x80                       THUMB,ARMv6
 
-[SXTHcc]
+reg32,reg32                 \x86\xFA\x1F\xF0\x80               THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop       \x86\xFA\x1F\xF0\x80               THUMB32,WIDE,ARMv6T2
+
+reg32,reg32                 \x1B\x6\xFF\x7                     ARM32,ARMv6
+reg32,reg32,shifterop       \x1B\x6\xFF\x7                     ARM32,ARMv6
 
 [UADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF1                    ARM32,ARMv6
+
 [UADD8cc]
-[UASXcc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF9                    ARM32,ARMv6
 
-[UBFXcc]
+[UASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF3                    ARM32,ARMv6
 
 [UHADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF1                    ARM32,ARMv6
+
 [UHADD8cc]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF9                    ARM32,ARMv6
+
 [UHASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF3                    ARM32,ARMv6
+
 [UHSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF5                    ARM32,ARMv6
+
 [UHSUB16cc]
-[UHSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xF7                    ARM32,ARMv6
 
-[UMAALcc]
+[UHSUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x60                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x70\xFF                    ARM32,ARMv6
 
 [UQADD16cc]
+reg32,reg32,reg32          \x80\xFA\x90\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF1                    ARM32,ARMv6
+
 [UQADD8]
+reg32,reg32,reg32          \x80\xFA\x80\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF9                    ARM32,ARMv6
+
 [UQASXcc]
+reg32,reg32,reg32          \x80\xFA\xA0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF3                    ARM32,ARMv6
+
 [UQSAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF5                    ARM32,ARMv6
 
 [UQSUB16cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xF7                    ARM32,ARMv6
+
 [UQSUB8cc]
-[UQSAD8cc]
-[UQSADA8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x50                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x60\xFF                    ARM32,ARMv6
+
+[USAD8cc]
+reg32,reg32,reg32          \x80\xFB\x70\xF0\x00                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x15\x07\x80\x01\xF                 ARM32,ARMv6
+
+[USADA8cc]
+reg32,reg32,reg32,reg32    \x80\xFB\x70\x0\x00                 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32    \x15\x07\x80\x01                    ARM32,ARMv6
 
 [USATcc]
+reg32,immshifter,reg32            \x83\xF3\x80\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32,shifterop  \x83\xF3\x80\x0\x0          THUMB32,ARMv6T2
+
+reg32,immshifter,reg32            \x2A\x6\xE0\x0\x10          ARM32,ARMv6
+reg32,immshifter,reg32,shifterop  \x2A\x6\xE0\x0\x10          ARM32,ARMv6
+
 [USAT16cc]
+reg32,immshifter,reg32            \x83\xF3\xA0\x0\x0          THUMB32,ARMv6T2
+reg32,immshifter,reg32            \x2A\x6\xE0\xF\x30          ARM32,ARMv6
+
 [USAXcc]
+reg32,reg32,reg32          \x80\xFA\xE0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF5                    ARM32,ARMv6
 
 [USUB16cc]
-[USUB8cc]
+reg32,reg32,reg32          \x80\xFA\xD0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xF7                    ARM32,ARMv6
 
-[UXTABcc]
-[UXTAB16cc]
-[UXTAHcc]
-[UXTB16cc]
+[USUB8cc]
+reg32,reg32,reg32          \x80\xFA\xC0\xF0\x40                THUMB32,ARMv6T2
+reg32,reg32,reg32          \x16\x06\x50\xFF                    ARM32,ARMv6
 
 [WFEcc]
+void                          \x64\xBF\x20                     THUMB,ARMv7
+void                          \x2F\x3\x20\xF0\x2               ARM32,ARMv6K
+
 [WFIcc]
+void                          \x64\xBF\x30                     THUMB,ARMv7
+void                          \x2F\x3\x20\xF0\x3               ARM32,ARMv6K
+
 [YIELDcc]
+void                          \x64\xBF\x10                     THUMB,ARMv7
+void                          \x2F\x3\x20\xF0\x1               ARM32,ARMv6K
+
+;
+; vfp instructions
+;
+[FABSDcc]
+vreg,vreg               \x92\xEE\xB0\xA\xC0\0        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB0\xA\xC0\0         ARM32,VFPv2
+
+[FABSScc]
+vreg,vreg               \x92\xEE\xB0\xA\xC0\1        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB0\xA\xC0\1         ARM32,VFPv2
+
+[FADDDcc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x0\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x0\0          ARM32,VFPv2
+
+[FADDScc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x0\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x0\1          ARM32,VFPv2
+
+[FCMPDcc]
+vreg,vreg               \x92\xEE\xB4\xA\x40\0        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\x40\0         ARM32,VFPv2
+
+[FCMPScc]
+vreg,vreg               \x92\xEE\xB4\xA\x40\1        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\x40\1         ARM32,VFPv2
+
+[FCMPEDcc]
+vreg,vreg               \x92\xEE\xB4\xA\xC0\0        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\xC0\0         ARM32,VFPv2
+
+[FCMPEScc]
+vreg,vreg               \x92\xEE\xB4\xA\xC0\1        THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\xC0\1         ARM32,VFPv2
+
+[FCMPZDcc]
+vreg                    \x92\xEE\xB5\xA\x40\0        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\x40\0         ARM32,VFPv2
+
+[FCMPZScc]
+vreg                    \x92\xEE\xB5\xA\x40\1        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\x40\1         ARM32,VFPv2
+
+[FCMPEZDcc]
+vreg                    \x92\xEE\xB5\xA\xC0\0        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\xC0\0         ARM32,VFPv2
+
+[FCMPEZScc]
+vreg                    \x92\xEE\xB5\xA\xC0\1        THUMB32,VFPv2
+vreg                    \x42\xE\xB5\xA\xC0\1         ARM32,VFPv2
+
+[FCPYDcc]
+vreg,vreg               \x43\xEE\xB0\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB0\xB\x40           ARM32,VFPv2
+
+[FCPYScc]
+vreg,vreg               \x43\xEE\xB0\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB0\xA\x40           ARM32,VFPv2
+
+[FCVTDScc]
+vreg,vreg               \x43\xEE\xB7\xA\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB7\xA\xC0           ARM32,VFPv2
+
+[FCVTSDcc]
+vreg,vreg               \x43\xEE\xB7\xB\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB7\xB\xC0           ARM32,VFPv2
+
+[FDIVDcc]
+vreg,vreg,vreg          \x92\xEE\x80\xA\x0\0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x80\xA\x0\0           ARM32,VFPv2
+
+[FDIVScc]
+vreg,vreg,vreg          \x92\xEE\x80\xA\x0\1          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x80\xA\x0\1           ARM32,VFPv2
+
+[FLDDcc]
+vreg,memam2             \x95\xED\x10\xA               THUMB32,VFPv2
+vreg,memam2             \x45\xD\x10\xA                ARM32,VFPv2
+
+[FLDMcc]
+memam4,reglist               \x94\xEC\x10\xA                    THUMB32,VFPv2
+reg32,reglist                \x94\xEC\x10\xA                    THUMB32,VFPv2
+memam4,reglist               \x44\xC\x10\xA                        ARM32,VFPv2
+reg32,reglist                \x44\xC\x10\xA                        ARM32,VFPv2
+
+[FLDScc]
+vreg,memam2             \x95\xED\x10\xA               THUMB32,VFPv2
+vreg,memam2             \x45\xD\x10\xA                ARM32,VFPv2
+
+[FMACDcc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x00\0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x00\0           ARM32,VFPv2
+
+[FMACScc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x00\1          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x00\1           ARM32,VFPv2
+
+[FMDHRcc]
+
+[FMDLRcc]
+
+[FMRDHcc]
+
+[FMRDLcc]
+
+[FMRScc]
+reg32,vreg              \x90\xEE\x10\xA\x10           THUMB32,VFPv2
+reg32,vreg              \x40\xE\x10\xA\x10            ARM32,VFPv2
+
+[FMRXcc]
+reg32,regf              \x91\xEE\xF0\xA\x10           THUMB32,VFPv2
+regf,regf               \x91\xEE\xF0\xA\x10           THUMB32,VFPv2
+reg32,regf              \x41\xE\xF0\xA\x10            ARM32,VFPv2
+regf,regf               \x41\xE\xF0\xA\x10            ARM32,VFPv2
+
+[FMSCDcc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x00\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x00\0          ARM32,VFPv2
+
+[FMSCScc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x00\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x00\1          ARM32,VFPv2
+
+[FMSRcc]
+vreg,reg32              \x90\xEE\x00\xA\x10           THUMB32,VFPv2
+vreg,reg32              \x40\xE\x00\xA\x10            ARM32,VFPv2
+
+[FMSTATcc]
+void                    \x80\xEE\xF1\xFA\x10          THUMB32,VFPv2
+void                    \x2F\xE\xF1\xFA\x10           ARM32,VFPv2
+
+[FMULDcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x0\0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x0\0           ARM32,VFPv2
+
+[FMULScc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x0\1          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x0\1           ARM32,VFPv2
+
+[FMXRcc]
+regf,reg32              \x91\xEE\xE0\xA\x10           THUMB32,VFPv2
+regf,reg32              \x41\xE\xE0\xA\x10            ARM32,VFPv2
+
+[FNEGDcc]
+vreg,vreg               \x92\xEE\xB1\xA\x40\0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\x40\0          ARM32,VFPv2
+
+[FNEGScc]
+vreg,vreg               \x92\xEE\xB1\xA\x40\1         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\x40\1          ARM32,VFPv2
+
+[FNMACDcc]
+vreg,vreg,vreg          \x92\xEE\x00\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x00\xA\x40\0          ARM32,VFPv2
+
+[FNMACScc]
+vreg,vreg,vreg          \x92\xEE\x00\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x00\xA\x40\1          ARM32,VFPv2
+
+[FNMSCDcc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x40\0          ARM32,VFPv2
+
+[FNMSCScc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x40\1          ARM32,VFPv2
+
+[FNMULDcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x40\0          ARM32,VFPv2
+
+[FNMULScc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x40\1          ARM32,VFPv2
+
+[FSITODcc]
+vreg,vreg               \x43\xEE\xB8\xB\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xB\xC0           ARM32,VFPv2
+
+[FSITOScc]
+vreg,vreg               \x43\xEE\xB8\xA\xC0          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xA\xC0           ARM32,VFPv2
+
+[FSQRTDcc]
+vreg,vreg               \x92\xEE\xB1\xA\xC0\0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\xC0\0          ARM32,VFPv2
+
+[FSQRTScc]
+vreg,vreg               \x92\xEE\xB1\xA\xC0\1         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\xC0\1          ARM32,VFPv2
+
+[FSUBDcc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x40\0         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x40\0          ARM32,VFPv2
+
+[FSUBScc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x40\1         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x40\1          ARM32,VFPv2
+
+[FTOSIDcc]
+vreg,vreg               \x43\xEE\xBD\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBD\xB\x40           ARM32,VFPv2
+
+[FTOSIScc]
+vreg,vreg               \x43\xEE\xBD\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBD\xA\x40           ARM32,VFPv2
+
+[FTOUIDcc]
+vreg,vreg               \x43\xEE\xBC\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBC\xB\x40           ARM32,VFPv2
+
+[FTOUIScc]
+vreg,vreg               \x43\xEE\xBC\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xBC\xA\x40           ARM32,VFPv2
+
+[FUITODcc]
+vreg,vreg               \x43\xEE\xB8\xB\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xB\x40           ARM32,VFPv2
+
+[FUITOScc]
+vreg,vreg               \x43\xEE\xB8\xA\x40          THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xA\x40           ARM32,VFPv2
+
+[FMDRRcc]
+
+[FMRRDcc]
 
 ; Thumb-2
 
 [POP]
+reglist                       \x69\xBC                   THUMB,ARMv4T
+reglist                                  \x26\x8B                             ARM32,ARMv4
 
 [PUSH]
+reglist                       \x69\xB4                   THUMB,ARMv4T
+reglist                                  \x26\x80                             ARM32,ARMv4
 
 [SDIVcc]
+reg32,reg32,reg32             \x80\xFB\x90\xF0\xF0       THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32             \x15\x07\x10\x01\xF        ARM32,ARMv7
 
 [UDIVcc]
+reg32,reg32,reg32             \x80\xFB\xB0\xF0\xF0       THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32             \x15\x07\x30\x01\xF        ARM32,ARMv7
 
 [MOVTcc]
+reg32,imm                     \x81\xF2\xC0\x0\x0         THUMB32,ARMv6T2
+reg32,immshifter              \x81\xF2\xC0\x0\x0         THUMB32,ARMv6T2
+
+reg32,imm                     \x2C\x3\x40                ARM32,ARMv6T2
+reg32,immshifter              \x2C\x3\x40                ARM32,ARMv6T2
 
 [IT]
+condition                     \x6A\xBF\x08\x00           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITE]
+condition                     \x6A\xBF\x04\x88           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITT]
+condition                     \x6A\xBF\x04\x08           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITEE]
+condition                     \x6A\xBF\x02\xCC           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTE]
+condition                     \x6A\xBF\x02\x4C           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITET]
+condition                     \x6A\xBF\x02\x8C           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTT]
+condition                     \x6A\xBF\x02\x0C           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITEEE]
+condition                     \x6A\xBF\x01\xEE           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTEE]
+condition                     \x6A\xBF\x01\x6E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITETE]
+condition                     \x6A\xBF\x01\xAE           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTTE]
+condition                     \x6A\xBF\x01\x2E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITEET]
+condition                     \x6A\xBF\x01\xCE           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTET]
+condition                     \x6A\xBF\x01\x4E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITETT]
+condition                     \x6A\xBF\x01\x8E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
 
 [ITTTT]
+condition                     \x6A\xBF\x01\x0E           THUMB,ARMv6T2
+condition                     \xFE                       ARM32,ARMv4
+
+[TBBcc]
+memam2                  \x8E\xE8\xD0\xF0\x00       THUMB32,ARMv6T2
 
-[TBB]
-[TBH]
+[TBHcc]
+memam2                  \x8E\xE8\xD0\xF0\x10       THUMB32,ARMv6T2
 
 [MOVW]
+reg32,imm32             \x2C\x3\x0                 ARM32,ARMv6T2
+reg32,immshifter        \x2C\x3\x0                 ARM32,ARMv6T2
+
+reg32,imm32             \x81\xF2\x40\x0\x0         THUMB32,ARMv6T2
+reg32,immshifter        \x81\xF2\x40\x0\x0         THUMB32,ARMv6T2
 
 [CBZ]
+reglo,immshifter        \x68\xB1                   THUMB,ARMv6T2
+reglo,memam2            \x68\xB1                   THUMB,ARMv6T2
+
 [CBNZ]
+reglo,immshifter        \x68\xB9                   THUMB,ARMv6T2
+reglo,memam2            \x68\xB9                   THUMB,ARMv6T2
+
+; VFP
+[VABScc]
+vreg,vreg               \x92\xEE\xB0\xA\xC0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB0\xA\xC0         ARM32,VFPv2
+
+[VADDcc]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x0          ARM32,VFPv2
+
+[VCMPcc]
+vreg,vreg               \x92\xEE\xB4\xA\x40         THUMB32,VFPv2
+vreg,immshifter         \x92\xEE\xB5\xA\x40         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\x40         ARM32,VFPv2
+vreg,immshifter         \x42\xE\xB5\xA\x40         ARM32,VFPv2
+
+[VCMPEcc]
+vreg,vreg               \x92\xEE\xB4\xA\xC0         THUMB32,VFPv2
+vreg,immshifter         \x92\xEE\xB5\xA\xC0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB4\xA\xC0         ARM32,VFPv2
+vreg,immshifter         \x42\xE\xB5\xA\xC0         ARM32,VFPv2
+
+[VCVTcc]
+vreg,vreg               \x93\xEE\xB8\xA\xC0         THUMB32,VFPv2
+vreg,vreg,immshifter    \x93\xEE\xBA\xA\x40         THUMB32,VFPv3
+vreg,vreg               \x43\xE\xB8\xA\xC0         ARM32,VFPv2
+vreg,vreg,immshifter    \x43\xE\xBA\xA\x40         ARM32,VFPv3
+
+[VCVTRcc]
+vreg,vreg               \x93\xEE\xB8\xA\x40         THUMB32,VFPv2
+vreg,vreg               \x43\xE\xB8\xA\x40         ARM32,VFPv2
+
+[VDIVcc]
+vreg,vreg,vreg          \x92\xEE\x80\xA\x0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x80\xA\x0          ARM32,VFPv2
+
+[VMRScc]
+reg32,regf              \x91\xEE\xF0\xA\x10         THUMB32,VFPv2
+regf,regf               \x91\xEE\xF0\xA\x10         THUMB32,VFPv2
+reg32,regf              \x41\xE\xF0\xA\x10         ARM32,VFPv2
+regf,regf               \x41\xE\xF0\xA\x10         ARM32,VFPv2
+
+[VMSRcc]
+regf,reg32              \x91\xEE\xE0\xA\x10         THUMB32,VFPv2
+regf,reg32              \x41\xE\xE0\xA\x10         ARM32,VFPv2
+
+[VMLAcc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x00          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x00          ARM32,VFPv2
+
+[VMLScc]
+vreg,vreg,vreg          \x92\xEE\x0\xA\x40          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x0\xA\x40          ARM32,VFPv2
+
+[VMULcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x0          THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x0          ARM32,VFPv2
+
+[VNMLAcc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x40         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x40         ARM32,VFPv2
+
+[VNMLScc]
+vreg,vreg,vreg          \x92\xEE\x10\xA\x00         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x10\xA\x00         ARM32,VFPv2
+
+[VNMULcc]
+vreg,vreg,vreg          \x92\xEE\x20\xA\x40         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x20\xA\x40         ARM32,VFPv2
 
-; FPv4-s16 - ARMv7M floating point
-[VABS]
-[VADD]
-[VCMP]
-[VCMPE]
-[VCVT]
-[VDIV]
-[VLDM]
-[VLDR]
-[VMOV]
-[VMRS]
-[VMSR]
-[VMUL]
-[VMLA]
-[VMLS]
-[VNMLA]
-[VNMLS]
 [VFMA]
+vreg,vreg,vreg          \x92\xEE\xA0\xA\x00          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\xA0\xA\x00          ARM32,VFPv4
+
 [VFMS]
+vreg,vreg,vreg          \x92\xEE\xA0\xA\x40          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\xA0\xA\x40          ARM32,VFPv4
+
 [VFNMA]
+vreg,vreg,vreg          \x92\xEE\x90\xA\x00          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\x90\xA\x00          ARM32,VFPv4
+
 [VFNMS]
-[VNEG]
-[VNMUL]
-[VPOP]
-[VPUSH]
+vreg,vreg,vreg          \x92\xEE\x90\xA\x40          THUMB32,VFPv4
+vreg,vreg,vreg          \x42\xE\x90\xA\x40          ARM32,VFPv4
+
+[VNEGcc]
+vreg,vreg               \x92\xEE\xB1\xA\x40         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\x40         ARM32,VFPv2
+
 [VSQRT]
-[VSTM]
-[VSTR]
+vreg,vreg               \x92\xEE\xB1\xA\xC0         THUMB32,VFPv2
+vreg,vreg               \x42\xE\xB1\xA\xC0         ARM32,VFPv2
+
 [VSUB]
+vreg,vreg,vreg          \x92\xEE\x30\xA\x40         THUMB32,VFPv2
+vreg,vreg,vreg          \x42\xE\x30\xA\x40         ARM32,VFPv2
+
+[DMBcc]
+immshifter        \x80\xF3\xBF\x8F\x50             THUMB32,ARMv7
+immshifter        \x2E\xF5\x7F\xF0\x50             ARM32,ARMv7
+
+[ISBcc]
+immshifter        \x80\xF3\xBF\x8F\x60             THUMB32,ARMv7
+immshifter        \x2E\xF5\x7F\xF0\x60             ARM32,ARMv7
+
+[DSBcc]
+immshifter        \x80\xF3\xBF\x8F\x40             THUMB32,ARMv7
+immshifter        \x2E\xF5\x7F\xF0\x40             ARM32,ARMv7
+
+[SMCcc]
+immshifter        \x2E\x01\x60\x00\x70             ARM32,ARMv7
+imm32             \x2E\x01\x60\x00\x70             ARM32,ARMv7
 
 ; Thumb armv6-m (gcc)
-[NEG]
-[SVC]
+[NEGcc]
+
+[SVCcc]
+immshifter         \x61\xDF\x0                     THUMB,ARMv4T
+imm32              \x61\xDF\x0                     THUMB,ARMv4T
+
+immshifter         \x2\x0F                         ARM32,ARMv4
+imm32              \x2\x0F                         ARM32,ARMv4
+
+[BXJcc]
+reg32              \x80\xF3\xC0\x8F\x0             THUMB32,ARMv6T2
+reg32              \x3\x01\x2F\xFF\x20             ARM32,ARMv5TEJ
+
+; Undefined mnemonic
+[UDF]
+immshifter           \x61\xDE\x0                   THUMB,ARMv4T
+void                 void                          ARM32,ARMv4T
+
+; FPA
+
+
+[TANcc]
+fpureg,fpureg               \xA1\1\x15                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x15                    ARM32,FPA
+
+[SQTcc]
+fpureg,fpureg               \xA1\1\x9                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x9                     ARM32,FPA
+
+[SUFcc]
+fpureg,fpureg,fpureg        \xA1\0\x4                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x4                     ARM32,FPA
+
+[RSFcc]
+fpureg,fpureg,fpureg        \xA1\0\x6                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x6                     ARM32,FPA
+
+[RNDcc]
+fpureg,fpureg               \xA1\1\x7                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x7                     ARM32,FPA
+
+[POLcc]
+fpureg,fpureg,fpureg        \xA1\0\x18                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x18                    ARM32,FPA
+
+[RDFcc]
+fpureg,fpureg,fpureg        \xA1\0\xA                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\xA                     ARM32,FPA
+
+[RFScc]
+reg32                      \xA2\xE\x3               ARM32,FPA
+
+[RFCcc]
+reg32                      \xA2\xE\x5               ARM32,FPA
+
+[WFCcc]
+reg32                      \xA2\xE\x4               ARM32,FPA
+
+[RMFcc]
+fpureg,fpureg,fpureg        \xA1\0\x10                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x10                    ARM32,FPA
 
+[RPWcc]
+fpureg,fpureg,fpureg        \xA1\0\xC                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\xC                     ARM32,FPA
+
+[MNFcc]
+fpureg,fpureg               \xA1\1\x3                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x3                     ARM32,FPA
+
+[MUFcc]
+fpureg,fpureg,fpureg        \xA1\0\x2                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x2                     ARM32,FPA
+
+[ABScc]
+fpureg,fpureg               \xA1\1\x5                     ARM32,FPA
+fpureg,immshifter           \xA1\1\x5                     ARM32,FPA
+
+[ACScc]
+fpureg,fpureg               \xA1\1\x19                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x19                    ARM32,FPA
+
+[ASNcc]
+fpureg,fpureg               \xA1\1\x17                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x17                    ARM32,FPA
+
+[ATNcc]
+fpureg,fpureg               \xA1\1\x1B                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x1B                    ARM32,FPA
+
+[CNFcc]
+fpureg,fpureg            \xA2\xE\xB0                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\xB0                    ARM32,FPA
+
+[CNFEcc]
+fpureg,fpureg            \xA2\xE\xF0                    ARM32,FPA
+fpureg,immshifter        \xA2\xE\xF0                    ARM32,FPA
+
+[COScc]
+fpureg,fpureg               \xA1\1\x13                    ARM32,FPA
+fpureg,immshifter           \xA1\1\x13                    ARM32,FPA
+
+[DVFcc]
+fpureg,fpureg,fpureg        \xA1\0\x8                     ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x8                     ARM32,FPA
+
+[EXPcc]
+fpureg,fpureg               \xA1\1\xF                     ARM32,FPA
+fpureg,immshifter           \xA1\1\xF                     ARM32,FPA
+
+[FDVcc]
+fpureg,fpureg,fpureg        \xA1\0\x14                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x14                    ARM32,FPA
+
+[FLTcc]
+fpureg,reg32                \xA2\xE\x00                   ARM32,FPA
+
+[FIXcc]
+reg32,fpureg                \xA2\xE\x10                   ARM32,FPA
+
+[FMLcc]
+fpureg,fpureg,fpureg        \xA1\0\x12                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x12                    ARM32,FPA
+
+[FRDcc]
+fpureg,fpureg,fpureg        \xA1\0\x16                    ARM32,FPA
+fpureg,fpureg,immshifter    \xA1\0\x16                    ARM32,FPA
+
+[LGNcc]
+fpureg,fpureg               \xA1\1\xD                     ARM32,FPA
+fpureg,immshifter           \xA1\1\xD                     ARM32,FPA
+
+[LOGcc]
+fpureg,fpureg               \xA1\1\xB                     ARM32,FPA
+fpureg,immshifter           \xA1\1\xB                     ARM32,FPA
\ No newline at end of file
index 75c526399990d36866f894d9fb5333d10021dedb..5fc78695316af487f7c4b22f89779e24a9af571a 100644 (file)
@@ -1,2 +1,2 @@
 { don't edit, this file is generated from armins.dat }
-105;
+952;
index c91c9c03346a1234f75d972d851d2bff6d60b0eb..84aa9755f72a6c8d53c96d77c2fdaf0097e97325 100644 (file)
@@ -1,12 +1,9 @@
 { don't edit, this file is generated from armins.dat }
 (
 A_NONE,
-A_ABS,
-A_ACS,
-A_ASN,
-A_ATN,
 A_ADC,
 A_ADD,
+A_ADDW,
 A_ADF,
 A_ADR,
 A_AND,
@@ -17,24 +14,18 @@ A_BLX,
 A_BKPT,
 A_BX,
 A_CDP,
-A_CMF,
-A_CMFE,
 A_CMN,
 A_CMP,
+A_CMF,
+A_CMFE,
+A_STF,
+A_LDF,
+A_LFM,
 A_CLZ,
-A_CNF,
-A_COS,
 A_CPS,
 A_CPSID,
 A_CPSIE,
-A_DVF,
 A_EOR,
-A_EXP,
-A_FDV,
-A_FLT,
-A_FIX,
-A_FML,
-A_FRD,
 A_LDC,
 A_LDM,
 A_LDRBT,
@@ -44,41 +35,32 @@ A_LDRH,
 A_LDRSB,
 A_LDRSH,
 A_LDRT,
-A_LDF,
-A_LFM,
-A_LGN,
-A_LOG,
 A_MCR,
+A_MCR2,
+A_MRC,
+A_MRC2,
+A_MCRR,
+A_MCRR2,
+A_MRRC,
+A_MRRC2,
 A_MLA,
 A_MOV,
-A_MRC,
 A_MRS,
 A_MSR,
-A_MNF,
-A_MUF,
 A_MUL,
 A_MVF,
 A_MVN,
+A_VMOV,
 A_NOP,
+A_ORN,
 A_ORR,
-A_RDF,
-A_RFS,
-A_RFC,
-A_RMF,
-A_RPW,
 A_RSB,
 A_RSC,
-A_RSF,
-A_RND,
-A_POL,
 A_SBC,
 A_SFM,
 A_SIN,
 A_SMLAL,
 A_SMULL,
-A_SQT,
-A_SUF,
-A_STF,
 A_STM,
 A_STR,
 A_STRB,
@@ -89,16 +71,14 @@ A_SUB,
 A_SWI,
 A_SWP,
 A_SWPB,
-A_TAN,
 A_TEQ,
 A_TST,
 A_UMLAL,
 A_UMULL,
 A_WFS,
 A_LDRD,
-A_MCRR,
-A_MRRC,
 A_PLD,
+A_PLDW,
 A_QADD,
 A_QDADD,
 A_QDSUB,
@@ -113,6 +93,12 @@ A_SMLALTB,
 A_SMLALTT,
 A_SMLAWB,
 A_SMLAWT,
+A_VLDM,
+A_VSTM,
+A_VPOP,
+A_VPUSH,
+A_VLDR,
+A_VSTR,
 A_SMULBB,
 A_SMULBT,
 A_SMULTB,
@@ -120,67 +106,13 @@ A_SMULTT,
 A_SMULWB,
 A_SMULWT,
 A_STRD,
-A_FABSD,
-A_FABSS,
-A_FADDD,
-A_FADDS,
-A_FCMPD,
-A_FCMPED,
-A_FCMPES,
-A_FCMPEZD,
-A_FCMPEZS,
-A_FCMPS,
-A_FCMPZD,
-A_FCMPZS,
-A_FCPYD,
-A_FCPYS,
-A_FCVTDS,
-A_FCVTSD,
-A_FDIVD,
-A_FDIVS,
-A_FLDD,
-A_FLDM,
-A_FLDS,
-A_FMACD,
-A_FMACS,
-A_FMDHR,
-A_FMDLR,
-A_FMRDH,
-A_FMRDL,
-A_FMRS,
-A_FMRX,
-A_FMSCD,
-A_FMSCS,
-A_FMSR,
-A_FMSTAT,
-A_FMULD,
-A_FMULS,
-A_FMXR,
-A_FNEGD,
-A_FNEGS,
-A_FNMACD,
-A_FNMACS,
-A_FNMSCD,
-A_FNMSCS,
-A_FNMULD,
-A_FNMULS,
-A_FSITOD,
-A_FSITOS,
-A_FSQRTD,
-A_FSQRTS,
+A_LDRHT,
+A_STRHT,
+A_LDRSBT,
+A_LDRSHT,
 A_FSTD,
 A_FSTM,
 A_FSTS,
-A_FSUBD,
-A_FSUBS,
-A_FTOSID,
-A_FTOSIS,
-A_FTOUID,
-A_FTOUIS,
-A_FUITOD,
-A_FUITOS,
-A_FMDRR,
-A_FMRRD,
 A_BFC,
 A_BFI,
 A_CLREX,
@@ -188,8 +120,13 @@ A_LDREX,
 A_LDREXB,
 A_LDREXD,
 A_LDREXH,
+A_STREX,
+A_STREXB,
+A_STREXD,
+A_STREXH,
 A_MLS,
-A_PKH,
+A_PKHBT,
+A_PKHTB,
 A_PLI,
 A_QADD16,
 A_QADD8,
@@ -212,6 +149,8 @@ A_ASR,
 A_LSR,
 A_LSL,
 A_ROR,
+A_RRX,
+A_UMAAL,
 A_SHADD16,
 A_SHADD8,
 A_SHASX,
@@ -233,49 +172,102 @@ A_SSAT16,
 A_SSAX,
 A_SSUB16,
 A_SSUB8,
-A_STREX,
-A_STREXB,
-A_STREXD,
-A_STREXH,
 A_SXTAB,
 A_SXTAB16,
 A_SXTAH,
+A_UBFX,
+A_UXTAB,
+A_UXTAB16,
+A_UXTAH,
 A_SXTB,
 A_SXTB16,
+A_SXTH,
 A_UXTB,
+A_UXTB16,
 A_UXTH,
-A_SXTH,
 A_UADD16,
 A_UADD8,
 A_UASX,
-A_UBFX,
 A_UHADD16,
 A_UHADD8,
 A_UHASX,
 A_UHSAX,
 A_UHSUB16,
 A_UHSUB8,
-A_UMAAL,
 A_UQADD16,
 A_UQADD8,
 A_UQASX,
 A_UQSAX,
 A_UQSUB16,
 A_UQSUB8,
-A_UQSAD8,
-A_UQSADA8,
+A_USAD8,
+A_USADA8,
 A_USAT,
 A_USAT16,
 A_USAX,
 A_USUB16,
 A_USUB8,
-A_UXTAB,
-A_UXTAB16,
-A_UXTAH,
-A_UXTB16,
 A_WFE,
 A_WFI,
 A_YIELD,
+A_FABSD,
+A_FABSS,
+A_FADDD,
+A_FADDS,
+A_FCMPD,
+A_FCMPS,
+A_FCMPED,
+A_FCMPES,
+A_FCMPZD,
+A_FCMPZS,
+A_FCMPEZD,
+A_FCMPEZS,
+A_FCPYD,
+A_FCPYS,
+A_FCVTDS,
+A_FCVTSD,
+A_FDIVD,
+A_FDIVS,
+A_FLDD,
+A_FLDM,
+A_FLDS,
+A_FMACD,
+A_FMACS,
+A_FMDHR,
+A_FMDLR,
+A_FMRDH,
+A_FMRDL,
+A_FMRS,
+A_FMRX,
+A_FMSCD,
+A_FMSCS,
+A_FMSR,
+A_FMSTAT,
+A_FMULD,
+A_FMULS,
+A_FMXR,
+A_FNEGD,
+A_FNEGS,
+A_FNMACD,
+A_FNMACS,
+A_FNMSCD,
+A_FNMSCS,
+A_FNMULD,
+A_FNMULS,
+A_FSITOD,
+A_FSITOS,
+A_FSQRTD,
+A_FSQRTS,
+A_FSUBD,
+A_FSUBS,
+A_FTOSID,
+A_FTOSIS,
+A_FTOUID,
+A_FTOUIS,
+A_FUITOD,
+A_FUITOS,
+A_FMDRR,
+A_FMRRD,
 A_POP,
 A_PUSH,
 A_SDIV,
@@ -306,29 +298,59 @@ A_VADD,
 A_VCMP,
 A_VCMPE,
 A_VCVT,
+A_VCVTR,
 A_VDIV,
-A_VLDM,
-A_VLDR,
-A_VMOV,
 A_VMRS,
 A_VMSR,
-A_VMUL,
 A_VMLA,
 A_VMLS,
+A_VMUL,
 A_VNMLA,
 A_VNMLS,
+A_VNMUL,
 A_VFMA,
 A_VFMS,
 A_VFNMA,
 A_VFNMS,
 A_VNEG,
-A_VNMUL,
-A_VPOP,
-A_VPUSH,
 A_VSQRT,
-A_VSTM,
-A_VSTR,
 A_VSUB,
+A_DMB,
+A_ISB,
+A_DSB,
+A_SMC,
 A_NEG,
-A_SVC
+A_SVC,
+A_BXJ,
+A_UDF,
+A_TAN,
+A_SQT,
+A_SUF,
+A_RSF,
+A_RND,
+A_POL,
+A_RDF,
+A_RFS,
+A_RFC,
+A_WFC,
+A_RMF,
+A_RPW,
+A_MNF,
+A_MUF,
+A_ABS,
+A_ACS,
+A_ASN,
+A_ATN,
+A_CNF,
+A_CNFE,
+A_COS,
+A_DVF,
+A_EXP,
+A_FDV,
+A_FLT,
+A_FIX,
+A_FML,
+A_FRD,
+A_LGN,
+A_LOG
 );
index b7d264f1edb490219aaeccfa6f693aa56d0a9379..87887d5d016cc457a4864299e143c504ba89a469 100644 (file)
@@ -87,7 +87,7 @@ S28,$04,$06,$0E,s28,0,0
 S29,$04,$06,$2E,s29,0,0
 D14,$04,$07,$0E,d14,0,0
 S30,$04,$06,$0F,s30,0,0
-S31,$04,$06,$2F,s21,0,0
+S31,$04,$06,$2F,s31,0,0
 D15,$04,$07,$0F,d15,0,0
 D16,$04,$07,$10,d16,0,0
 D17,$04,$07,$11,d17,0,0
@@ -145,4 +145,11 @@ BASEPRI,$05,$00,$1F,basepri,0,0
 BASEPRI_MAX,$05,$00,$20,basepri_max,0,0
 FAULTMASK,$05,$00,$21,faultmask,0,0
 CONTROL,$05,$00,$22,control,0,0
-
+; VFP registers
+FPSID,$05,$00,$23,fpsid,0,0
+MVFR1,$05,$00,$24,mvfr1,0,0
+MVFR0,$05,$00,$25,mvfr0,0,0
+FPEXC,$05,$00,$26,fpexc,0,0
+APSR_nzcvq,$05,$00,$27,apsr_nzcvq,0,0
+APSR_g,$05,$00,$28,apsr_g,0,0
+APSR_nzcvqg,$05,$00,$29,apsr_nzcvqg,0,0
index f0e43f6832bbbb032141096e98b51229914449ba..ad1beba15f2b92383c05dabe72535a8b2a3d9d11 100644 (file)
   (
     opcode  : A_NONE;
     ops     : 0;
-    optypes : (ot_none,ot_none,ot_none,ot_none);
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #0;
     flags   : if_none
   ),
+  (
+    opcode  : A_ADC;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
   (
     opcode  : A_ADC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#160;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_ADC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#160;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#160;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#0#160;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#2#160;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#68#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
     opcode  : A_ADD;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#128;
-    flags   : if_arm7
+    optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+    code    : #96#24#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#28#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#28#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#48#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reglo,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #100#168#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #100#176#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_regsp,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #100#68#104;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_regsp,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#68#133;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_ADD;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#128;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#128;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADD;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#0#128;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_ADD;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#2#128;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ADDW;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #129#242#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ADF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_ADF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#160#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#160#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#175#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#175#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#175#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ADR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #51#2#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_AND;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#0;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_AND;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#0;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_AND;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#0;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_AND;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#0#0;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_AND;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#2#0;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#224#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#224#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#224#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #99#208#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #99#208#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_B;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #99#208#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
     opcode  : A_B;
     ops     : 1;
-    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#10;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_B;
     ops     : 1;
-    optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#10;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#67#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
   ),
   (
     opcode  : A_BIC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#1#192;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
   ),
   (
     opcode  : A_BIC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#1#192;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#32#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_BIC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #6#1#192;
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_BIC;
     ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
     code    : #6#1#192;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_BIC;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
     code    : #7#3#192;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BL;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#208;
+    flags   : if_thumb or if_thumb32 or if_armv4t
+  ),
+  (
+    opcode  : A_BL;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#208;
+    flags   : if_thumb or if_thumb32 or if_armv4t
+  ),
+  (
+    opcode  : A_BL;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#208;
+    flags   : if_thumb or if_thumb32 or if_armv4t
   ),
   (
     opcode  : A_BL;
     ops     : 1;
-    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#11;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
   ),
   (
     opcode  : A_BL;
     ops     : 1;
-    optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
     code    : #1#11;
-    flags   : if_arm7
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#71#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #141#240#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #40#250;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #40#250;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BLX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #3#1#47#255#48;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BKPT;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#190#0;
+    flags   : if_thumb or if_armv5t
+  ),
+  (
+    opcode  : A_BKPT;
+    ops     : 1;
+    optypes : (ot_immediate,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #49#1#32#112;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BKPT;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #49#1#32#112;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_BX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #98#71#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_BX;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #3#1#47#255#16;
+    flags   : if_arm32 or if_armv4t
+  ),
+  (
+    opcode  : A_CDP;
+    ops     : 2;
+    optypes : (ot_reg8,ot_reg8,ot_none,ot_none,ot_none,ot_none);
+    code    : #192#1#16#65;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#66#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#16#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#1#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#66#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#69#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#40#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#176#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#176#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#176#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMP;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#3#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CMF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#144;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CMF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#144;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CMFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#192;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CMFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#192;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_STF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #160#12#0#1#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LDF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #160#12#16#1#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediate or ot_bits32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#16#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#16#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_CLZ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#176#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CLZ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#1#111#15#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CPS;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#129#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CPS;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#2#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #108#182#112;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#134#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#135#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#12#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSID;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#14#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #108#182#96;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#132#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #143#243#175#133#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 1;
+    optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#8#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_CPSIE;
+    ops     : 2;
+    optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #70#241#10#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#128#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_EOR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#2#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #209#192#1#17#65;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#200;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#200;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#16#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#16#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#129;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#129;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#16#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#112;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#112;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#92#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#120#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#16#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#80;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#88#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#104#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam5,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#152#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#72#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#80#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#90#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#136#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#48#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#16#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#86#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#16#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#16#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #35#80#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #36#80#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #37#16#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#94#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LDRSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#48#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#16#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#80#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#48;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MCR;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#14#0#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MCR;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#14#0#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MCR2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#254#0#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MCR2;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#254#0#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MRC;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#14#16#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MRC;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#14#16#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MRC2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+    code    : #28#254#16#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MRC2;
+    ops     : 6;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+    code    : #28#254#16#1;
+    flags   : if_arm32 or if_armv5t
+  ),
+  (
+    opcode  : A_MCRR;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#12#64#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_MCRR2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#252#64#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_MRRC;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#12#80#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_MRRC2;
+    ops     : 5;
+    optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+    code    : #29#252#80#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_MLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#0#32#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#70#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#32#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_shifterop,ot_none,ot_none,ot_none,ot_none);
+    code    : #8#1#160;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #10#1#160;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #11#1#160;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #150#243#239#128#0;
+    flags   : if_thumb32 or if_armv6
+  ),
+  (
+    opcode  : A_MRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #16#1#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #150#243#128#128#0;
+    flags   : if_thumb32 or if_armv6
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #18#1#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #19#3#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regs,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #19#3#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#67#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+    code    : #100#67#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#251#0#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#0#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #20#0#0#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MVF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#1;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_MVF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#1;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#67#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#111#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#111#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #8#1#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #10#1#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MVN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #11#1#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#176#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#176#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#16#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#0#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#16#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#0#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_vreg,ot_none,ot_none);
+    code    : #144#236#80#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_vreg,ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #144#236#64#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_vreg,ot_none,ot_none);
+    code    : #64#12#80#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 4;
+    optypes : (ot_vreg,ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #64#12#64#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #144#236#80#11#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #144#236#64#11#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #64#12#80#11#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMOV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #64#12#64#11#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_NOP;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#191#0;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_NOP;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#0;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_NOP;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#225#160#0#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORN;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#67#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#240#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#64#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#1#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #5#1#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#1#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ORR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#3#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediatezero,ot_none,ot_none,ot_none);
+    code    : #107#66#64;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#192#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#192#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #6#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #5#0#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RSC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#2#224;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#96#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #5#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate,ot_none,ot_none);
+    code    : #6#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SBC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #7#2#192;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediate or ot_bits32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#0#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SFM;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #160#12#0#2#0;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SIN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#17;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SIN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#17;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_SMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#224#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#192#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #140#232#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#80#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#96#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam5,ot_none,ot_none,ot_none,ot_none);
+    code    : #103#144#0#2;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#64#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#84#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#112#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#0#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STRB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#0#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+    code    : #101#82#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+    code    : #102#128#0#1;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#32#0#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_STRH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #34#0#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#64#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #23#4#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#176#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #100#176#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#26#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+    code    : #96#26#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#30#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#30#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediate or ot_bits8,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#56#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#56#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#241#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #128#241#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#235#160#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #4#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #4#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #4#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SUB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #6#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SWP;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #39#16#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SWPB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #39#20#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#144#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#144#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#144#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #13#1#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TEQ;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#3#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#66#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#240#16#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #128#234#16#15#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #12#1#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #13#1#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #14#1#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TST;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #15#3#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#224#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UMLAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#160#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#160#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UMULL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#128#9;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_WFS;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#2;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LDRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #137#232#80#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #25#0#0#0#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_PLD;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #135#248#16#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PLD;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #37#245#80#240#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_PLDW;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #135#248#48#240#0;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_PLDW;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #37#245#16#240#0;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_QADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#0#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_QDADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#144;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QDADD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#64#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_QDSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#176;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QDSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#96#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_QSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #130#250#128#240#160;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSUB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #26#1#32#5;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLABB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLABT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#12;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLATB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#10;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLATT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#0#14;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALBB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALBT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#12;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALTB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#10;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLALTT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#1#64#14;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLAWB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#48#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAWB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#32#8;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMLAWT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#48#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAWT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#1#32#12;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPOP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#189#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPOP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#189#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#237#45#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VPUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#13#45#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VLDR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VSTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_SMULBB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#8#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULBT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#12#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#10#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULTT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#1#96#14#0;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULWB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #20#1#32#160;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_SMULWT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #20#1#32#224;
+    flags   : if_arm32 or if_armv5te
+  ),
+  (
+    opcode  : A_STRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #137#232#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+    code    : #25#0#0#0#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#48#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #25#0#48#0#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#32#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#248#32#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STRHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #30#0#32#0#176;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#16#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSBT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #30#0#48#0#208;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDRSHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #136#249#48#14#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDRSHT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #30#0#48#0#240;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_FSTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#0#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#0#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #132#243#111#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #132#243#111#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #45#7#192#0#31;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BFC;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #45#7#192#0#31;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #132#243#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none);
+    code    : #132#243#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #45#7#192#0#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BFI;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none);
+    code    : #45#7#192#0#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_CLREX;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#47;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_CLREX;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#245#127#240#31;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_LDREX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #138#232#80#15#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_LDREX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #24#1#144#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDREXB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #138#232#208#15#79;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_LDREXB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #24#1#208#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDREXD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #138#232#208#0#127;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_LDREXD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#176#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LDREXH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #138#232#208#15#95;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_LDREXH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+    code    : #24#1#240#15#159;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #139#232#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_STREX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#128#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREXB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #139#232#192#15#64;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_STREXB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#192#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREXD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none);
+    code    : #139#232#192#0#112;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_STREXD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none);
+    code    : #24#1#160#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_STREXH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #139#232#192#15#80;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_STREXH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+    code    : #24#1#224#15#144;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_MLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#0#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#0#96#9;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PKHBT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#234#192#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #128#234#192#0#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PKHTB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#128#5;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_PLI;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #135#249#16#240#0;
+    flags   : if_thumb32 or if_armv7
+  ),
+  (
+    opcode  : A_PLI;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #37#244#80#240#0;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_QADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_QSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_QSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#32#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_RBIT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#160;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RBIT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#255#15#48;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_REV;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#186#0;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_REV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_REV;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#191#15#48;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_REV16;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#186#64;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_REV16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#144;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_REV16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#191#15#176;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_REVSH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#186#192;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_REVSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#176;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_REVSH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #50#6#255#15#176;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#72#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#64#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#80#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #132#243#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #45#7#160#0#80;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SEL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SEL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#251;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SETEND;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #43#241#1#0#0;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SEV;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#64;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_SEV;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#4;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#1#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#1#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#32;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#32;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#64#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#64#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#80;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ASR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#64;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#8#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#8#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#16;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#16;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#32#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#32#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#48;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#32;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #96#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #96#0#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#64#128;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#16;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_LSL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#0;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #107#65#192;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#48;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #130#234#79#0#48;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#96#240#0;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#112;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ROR;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_RRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#234#79#0#48;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_RRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #48#1#160#0#96;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UMAAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#224#0#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UMAAL;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#0#64#9;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#32;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#48#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMLAD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLAD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#0#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMLALD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#192#0#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLALD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#7#64#1;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SMLSD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLSD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#0#5;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMLSLD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #133#251#208#0#192;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMLSLD;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #22#7#64#5;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMMLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#80#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMMLA;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#80#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMMLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#96#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMMLS;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#80#13;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMMUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#80#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMMUL;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#80#1#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMUAD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#32#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMUAD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#0#1#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SMUSD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#64#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SMUSD;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#0#5#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #131#243#0#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#160#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #42#6#160#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#32#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#160#15#48;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#16#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#160#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#160#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#32#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#32#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#128#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#128#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#0#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#0#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#176#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#176#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #132#243#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UBFX;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+    code    : #45#7#224#0#80;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#80#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#80#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#224#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAB;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#224#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#48#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#48#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#64#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#192#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAB16;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#192#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #134#250#16#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #134#250#16#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#240#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTAH;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #22#6#240#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#64;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#79#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#79#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#175#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#175#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#47#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#47#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#143#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#143#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#0;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#15#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#15#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#191#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_SXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#191#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#192;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#95#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#95#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#239#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#239#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#63#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#63#240#128;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#207#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#207#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 2;
+    optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#178#128;
+    flags   : if_thumb or if_armv6
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #134#250#31#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #134#250#31#240#128;
+    flags   : if_thumb32 or if_wide or if_armv6t2
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #27#6#255#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UXTH;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+    code    : #27#6#255#7;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#96;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UHSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#112#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#144#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQADD16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#241;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#128#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQADD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#249;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#160#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQASX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#243;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQSAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQSUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_UQSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#80;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_UQSUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#96#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#112#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAD8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#128#1#15;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USADA8;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #128#251#112#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USADA8;
+    ops     : 4;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+    code    : #21#7#128#1;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #131#243#128#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#224#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAT;
+    ops     : 4;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+    code    : #42#6#224#0#16;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #131#243#160#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAT16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #42#6#224#15#48;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#224#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USAX;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#245;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#208#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USUB16;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#247;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_USUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#250#192#240#64;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_USUB8;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #22#6#80#255;
+    flags   : if_arm32 or if_armv6
+  ),
+  (
+    opcode  : A_WFE;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#32;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_WFE;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#2;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_WFI;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#48;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_WFI;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#3;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_YIELD;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #100#191#16;
+    flags   : if_thumb or if_armv7
+  ),
+  (
+    opcode  : A_YIELD;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#3#32#240#1;
+    flags   : if_arm32 or if_armv6k
+  ),
+  (
+    opcode  : A_FABSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#176#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FABSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#176#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FABSS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#176#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FABSS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#176#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FADDS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPED;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPED;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPES;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPES;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZD;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCMPEZS;
+    ops     : 1;
+    optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#176#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#176#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#176#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCPYS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#176#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#183#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#183#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#183#11#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FCVTSD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#183#11#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#128#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#128#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#128#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FDIVS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#128#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #148#236#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDM;
+    ops     : 2;
+    optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+    code    : #68#12#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #149#237#16#10;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FLDS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #69#13#16#10;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#16#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#16#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMRX;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #144#238#0#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #64#14#0#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSTAT;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#238#241#250#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMSTAT;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #47#14#241#250#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#0#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#0#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#0#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#0#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMXR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#224#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FMXR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#224#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNEGS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMACS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMSCS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FNMULS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#11#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#11#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#192#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#192#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#192#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSQRTS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#192#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#64#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#64#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#64#1;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FSUBS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#64#1;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#189#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#189#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#189#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOSIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#189#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#188#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUID;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#188#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#188#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FTOUIS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#188#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#11#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOD;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#11#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#238#184#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_FUITOS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_POP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#188;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_POP;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#139;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_PUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #105#180;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_PUSH;
+    ops     : 1;
+    optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #38#128;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#144#240#240;
+    flags   : if_thumb32 or if_armv7r or if_armv7m
+  ),
+  (
+    opcode  : A_SDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#16#1#15;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_UDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #128#251#176#240#240;
+    flags   : if_thumb32 or if_armv7r or if_armv7m
+  ),
+  (
+    opcode  : A_UDIV;
+    ops     : 3;
+    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+    code    : #21#7#48#1#15;
+    flags   : if_arm32 or if_armv7
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#192#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#64;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVT;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#64;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_IT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#8#0;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_IT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#4#136;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#4#8;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#204;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#76;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#140;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#2#12;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITEEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#238;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITEEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#110;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTEE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITETE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#174;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITETE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#46;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTTE;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITEET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#206;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITEET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#78;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTET;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITETT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#142;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITETT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_ITTTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #106#191#1#14;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_ITTTT;
+    ops     : 1;
+    optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #254;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_TBB;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #142#232#208#240#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_TBH;
+    ops     : 1;
+    optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #142#232#208#240#16;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#0;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #44#3#0;
+    flags   : if_arm32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_MOVW;
+    ops     : 2;
+    optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #129#242#64#0#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_CBZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#177;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_CBZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#177;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_CBNZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#185;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_CBNZ;
+    ops     : 2;
+    optypes : (ot_reglo,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+    code    : #104#185;
+    flags   : if_thumb or if_armv6t2
+  ),
+  (
+    opcode  : A_VABS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#176#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VABS;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#176#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VADD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VADD;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMP;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#180#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#181#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#180#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCMPE;
+    ops     : 2;
+    optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#181#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #147#238#184#10#192;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #147#238#186#10#64;
+    flags   : if_thumb32 or if_vfpv3
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#192;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVT;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #67#14#186#10#64;
+    flags   : if_arm32 or if_vfpv3
+  ),
+  (
+    opcode  : A_VCVTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #147#238#184#10#64;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VCVTR;
+    ops     : 2;
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #67#14#184#10#64;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VDIV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#128#10#0;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VDIV;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#128#10#0;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#240#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMRS;
+    ops     : 2;
+    optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#240#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #145#238#224#10#16;
+    flags   : if_thumb32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMSR;
+    ops     : 2;
+    optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #65#14#224#10#16;
+    flags   : if_arm32 or if_vfpv2
+  ),
+  (
+    opcode  : A_VMLA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#0;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_BLX;
-    ops     : 1;
-    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
-    code    : #15#15;
-    flags   : if_arm7
+    opcode  : A_VMLA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#0;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_BLX;
-    ops     : 1;
-    optypes : (ot_immediate24,ot_none,ot_none,ot_none);
-    code    : #15#15;
-    flags   : if_arm7
+    opcode  : A_VMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#0#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_BX;
-    ops     : 1;
-    optypes : (ot_reg32,ot_none,ot_none,ot_none);
-    code    : #3#1#47#255#16;
-    flags   : if_arm7
+    opcode  : A_VMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#0#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CDP;
-    ops     : 2;
-    optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
-    code    : #192#1#16#65;
-    flags   : if_arm7
+    opcode  : A_VMUL;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#0;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#96;
-    flags   : if_arm7
+    opcode  : A_VMUL;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#0;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
+    opcode  : A_VNMLA;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#96;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
+    opcode  : A_VNMLA;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#96;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMN;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#96;
-    flags   : if_arm7
+    opcode  : A_VNMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#16#10#0;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#64;
-    flags   : if_arm7
+    opcode  : A_VNMLS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#16#10#0;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
+    opcode  : A_VNMUL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#64;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#32#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
+    opcode  : A_VNMUL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#64;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#32#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_CMP;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#64;
-    flags   : if_arm7
+    opcode  : A_VFMA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#160#10#0;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_CLZ;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #39#1#1;
-    flags   : if_arm7
+    opcode  : A_VFMA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#160#10#0;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
+    opcode  : A_VFMS;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#32;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#160#10#64;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#32;
-    flags   : if_arm7
+    opcode  : A_VFMS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#160#10#64;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#32;
-    flags   : if_arm7
+    opcode  : A_VFNMA;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#144#10#0;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_EOR;
+    opcode  : A_VFNMA;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#32;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#144#10#0;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_LDC;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #209#192#1#17#65;
-    flags   : if_arm7
+    opcode  : A_VFNMS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#144#10#64;
+    flags   : if_thumb32 or if_vfpv4
   ),
   (
-    opcode  : A_LDM;
-    ops     : 2;
-    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
-    code    : #38#129;
-    flags   : if_arm7
+    opcode  : A_VFNMS;
+    ops     : 3;
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#144#10#64;
+    flags   : if_arm32 or if_vfpv4
   ),
   (
-    opcode  : A_LDRB;
+    opcode  : A_VNEG;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#7#16;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_LDR;
+    opcode  : A_VNEG;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#5#16;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSQRT;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #146#238#177#10#192;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSQRT;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+    code    : #66#14#177#10#192;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSUB;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #146#238#48#10#64;
+    flags   : if_thumb32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRH;
+    opcode  : A_VSUB;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#176;
-    flags   : if_arm7
+    optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+    code    : #66#14#48#10#64;
+    flags   : if_arm32 or if_vfpv2
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#208;
-    flags   : if_arm7
+    opcode  : A_DMB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#80;
+    flags   : if_thumb32 or if_armv7
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#208;
-    flags   : if_arm7
+    opcode  : A_DMB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#245#127#240#80;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#208;
-    flags   : if_arm7
+    opcode  : A_ISB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#96;
+    flags   : if_thumb32 or if_armv7
   ),
   (
-    opcode  : A_LDRSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#208;
-    flags   : if_arm7
+    opcode  : A_ISB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#245#127#240#96;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#80#240;
-    flags   : if_arm7
+    opcode  : A_DSB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#191#143#64;
+    flags   : if_thumb32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#80#240;
-    flags   : if_arm7
+    opcode  : A_DSB;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#245#127#240#64;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#80#240;
-    flags   : if_arm7
+    opcode  : A_SMC;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#1#96#0#112;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LDRSH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#16#240;
-    flags   : if_arm7
+    opcode  : A_SMC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #46#1#96#0#112;
+    flags   : if_arm32 or if_armv7
   ),
   (
-    opcode  : A_LFM;
-    ops     : 3;
-    optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
-    code    : #240#2#1;
-    flags   : if_fpa
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#223#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
-    opcode  : A_MLA;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #21#0#32#144;
-    flags   : if_arm7
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#223#0;
+    flags   : if_thumb or if_armv4t
   ),
   (
-    opcode  : A_MRS;
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_SVC;
+    ops     : 1;
+    optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #2#15;
+    flags   : if_arm32 or if_armv4
+  ),
+  (
+    opcode  : A_BXJ;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #128#243#192#143#0;
+    flags   : if_thumb32 or if_armv6t2
+  ),
+  (
+    opcode  : A_BXJ;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #3#1#47#255#32;
+    flags   : if_arm32 or if_armv5tej
+  ),
+  (
+    opcode  : A_UDF;
+    ops     : 1;
+    optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #97#222#0;
+    flags   : if_thumb or if_armv4t
+  ),
+  (
+    opcode  : A_UDF;
+    ops     : 0;
+    optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #0;
+    flags   : if_arm32 or if_armv4t
+  ),
+  (
+    opcode  : A_TAN;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #16#1#15;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#21;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MSR;
+    opcode  : A_TAN;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #17#1#41#240;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#21;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MSR;
+    opcode  : A_SQT;
     ops     : 2;
-    optypes : (ot_regf,ot_reg32,ot_none,ot_none);
-    code    : #18#1#40#240;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#9;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MSR;
+    opcode  : A_SQT;
     ops     : 2;
-    optypes : (ot_regf,ot_immediate,ot_none,ot_none);
-    code    : #19#3#40#240;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#9;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MUL;
+    opcode  : A_SUF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #20#0#0#144;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#4;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MVF;
-    ops     : 2;
-    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none);
-    code    : #242;
-    flags   : if_fpa
+    opcode  : A_SUF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#4;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_MVF;
-    ops     : 2;
-    optypes : (ot_fpureg,ot_immediatefpu,ot_none,ot_none);
-    code    : #242;
-    flags   : if_fpa
+    opcode  : A_RSF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#6;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
+    opcode  : A_RSF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#1#128;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#6;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#1#128;
-    flags   : if_arm7
+    opcode  : A_RND;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#7;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#1#128;
-    flags   : if_arm7
+    opcode  : A_RND;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#7;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_ORR;
+    opcode  : A_POL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#3#128;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#24;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
+    opcode  : A_POL;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#96;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#24;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#96;
-    flags   : if_arm7
+    opcode  : A_RDF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#10;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#96;
-    flags   : if_arm7
+    opcode  : A_RDF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#10;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#96;
-    flags   : if_arm7
+    opcode  : A_RFS;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#3;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#224;
-    flags   : if_arm7
+    opcode  : A_RFC;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#5;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#224;
-    flags   : if_arm7
+    opcode  : A_WFC;
+    ops     : 1;
+    optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#4;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#224;
-    flags   : if_arm7
+    opcode  : A_RMF;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#16;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_RSC;
+    opcode  : A_RMF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#224;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#16;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
+    opcode  : A_RPW;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#192;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#12;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #5#0#192;
-    flags   : if_arm7
+    opcode  : A_RPW;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#12;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
-    code    : #6#0#192;
-    flags   : if_arm7
+    opcode  : A_MNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#3;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SBC;
+    opcode  : A_MNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#3;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_MUF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #7#2#192;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#2;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SFM;
+    opcode  : A_MUF;
     ops     : 3;
-    optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
-    code    : #240#2#0;
-    flags   : if_fpa
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#2;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SMLAL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#224#144;
-    flags   : if_arm7
+    opcode  : A_ABS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#5;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SMULL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#192#144;
-    flags   : if_arm7
+    opcode  : A_ABS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#5;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STM;
+    opcode  : A_ACS;
     ops     : 2;
-    optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
-    code    : #38#128;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#25;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STR;
+    opcode  : A_ACS;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#4#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#25;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRB;
+    opcode  : A_ASN;
     ops     : 2;
-    optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
-    code    : #23#6#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#23;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
+    opcode  : A_ASN;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
-    code    : #34#64#176;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#23;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
+    opcode  : A_ATN;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #35#64#176;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#27;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
-    code    : #36#64#176;
-    flags   : if_arm7
+    opcode  : A_ATN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#27;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_STRH;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #37#0#176;
-    flags   : if_arm7
+    opcode  : A_CNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#176;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SUB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
-    code    : #4#0#64;
-    flags   : if_arm7
+    opcode  : A_CNF;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#176;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SUB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
-    code    : #4#0#64;
-    flags   : if_arm7
+    opcode  : A_CNFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#240;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SUB;
-    ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #4#0#64;
-    flags   : if_arm7
+    opcode  : A_CNFE;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#240;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SWI;
-    ops     : 1;
-    optypes : (ot_immediate,ot_none,ot_none,ot_none);
-    code    : #2#15;
-    flags   : if_arm7
+    opcode  : A_COS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#19;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SWP;
+    opcode  : A_COS;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#19;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_DVF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #39#1#144;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#8;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_SWPB;
+    opcode  : A_DVF;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #39#1#144;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#8;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_EXP;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#15;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_EXP;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#15;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_FDV;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#20;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_FDV;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#20;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TEQ;
+    opcode  : A_FLT;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#32;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#0;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FIX;
     ops     : 2;
-    optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
-    code    : #12#1#0;
-    flags   : if_arm7
+    optypes : (ot_reg32,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #162#14#16;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FML;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
-    code    : #13#1#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#18;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FML;
     ops     : 3;
-    optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
-    code    : #14#1#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#18;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_TST;
+    opcode  : A_FRD;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+    code    : #161#0#22;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_FRD;
+    ops     : 3;
+    optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+    code    : #161#0#22;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LGN;
     ops     : 2;
-    optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
-    code    : #15#3#0;
-    flags   : if_arm7
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#13;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_UMLAL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#160#144;
-    flags   : if_arm7
+    opcode  : A_LGN;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#13;
+    flags   : if_arm32 or if_fpa
   ),
   (
-    opcode  : A_UMULL;
-    ops     : 4;
-    optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
-    code    : #22#0#128#144;
-    flags   : if_arm7
+    opcode  : A_LOG;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#11;
+    flags   : if_arm32 or if_fpa
+  ),
+  (
+    opcode  : A_LOG;
+    ops     : 2;
+    optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+    code    : #161#1#11;
+    flags   : if_arm32 or if_fpa
   )
 );
index 5ea2b39a0dec6d33c2bef95feece84bddb571cd5..babaa17f27382b8fd733127292c8025c91633e5e 100644 (file)
@@ -104,7 +104,7 @@ unit cgcpu;
 
         procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle); override;
         { Transform unsupported methods into Internal errors }
-        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister); override;
 
         { try to generate optimized 32 Bit multiplication, returns true if successful generated }
         function try_optimized_mul32_const_reg_reg(list: TAsmList; a: tcgint; src, dst: tregister) : boolean;
@@ -1703,7 +1703,7 @@ unit cgcpu;
       end;
 
 
-    procedure tbasecgarm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+    procedure tbasecgarm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister);
       begin
         if reverse then
           begin
@@ -2032,11 +2032,11 @@ unit cgcpu;
                      ref.index:=ref.base;
                      ref.base:=NR_NO;
                      { FSTMX is deprecated on ARMv6 and later }
-                     if (current_settings.cputype<cpu_armv6) then
+                     {if (current_settings.cputype<cpu_armv6) then
                        postfix:=PF_IAX
                      else
-                       postfix:=PF_IAD;
-                     list.concat(setoppostfix(taicpu.op_ref_regset(A_FSTM,ref,R_MMREGISTER,R_SUBFD,mmregs),postfix));
+                       postfix:=PF_IAD;}
+                     list.concat(taicpu.op_ref_regset(A_VSTM,ref,R_MMREGISTER,R_SUBFD,mmregs));
                    end;
                end;
              end;
@@ -2133,11 +2133,11 @@ unit cgcpu;
                       ref.index:=ref.base;
                       ref.base:=NR_NO;
                       { FLDMX is deprecated on ARMv6 and later }
-                      if (current_settings.cputype<cpu_armv6) then
+                      {if (current_settings.cputype<cpu_armv6) then
                         mmpostfix:=PF_IAX
                       else
-                        mmpostfix:=PF_IAD;
-                      list.concat(setoppostfix(taicpu.op_ref_regset(A_FLDM,ref,R_MMREGISTER,R_SUBFD,mmregs),mmpostfix));
+                        mmpostfix:=PF_IAD;}
+                      list.concat(taicpu.op_ref_regset(A_VLDM,ref,R_MMREGISTER,R_SUBFD,mmregs));
                     end;
                 end;
               end;
@@ -2934,8 +2934,8 @@ unit cgcpu;
     function get_scalar_mm_op(fromsize,tosize : tcgsize) : tasmop;
       const
         convertop : array[OS_F32..OS_F128,OS_F32..OS_F128] of tasmop = (
-          (A_FCPYS,A_FCVTSD,A_NONE,A_NONE,A_NONE),
-          (A_FCVTDS,A_FCPYD,A_NONE,A_NONE,A_NONE),
+          (A_VMOV,A_VCVT,A_NONE,A_NONE,A_NONE),
+          (A_VCVT,A_VMOV,A_NONE,A_NONE,A_NONE),
           (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE),
           (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE),
           (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE));
@@ -2946,33 +2946,30 @@ unit cgcpu;
       end;
 
 
+    function get_scalar_mm_prefix(fromsize,tosize : tcgsize) : TOpPostfix;
+      const
+        convertop : array[OS_F32..OS_F128,OS_F32..OS_F128] of TOpPostfix = (
+          (PF_F32,   PF_F32F64,PF_None,PF_None,PF_None),
+          (PF_F64F32,PF_F64,   PF_None,PF_None,PF_None),
+          (PF_None,  PF_None,  PF_None,PF_None,PF_None),
+          (PF_None,  PF_None,  PF_None,PF_None,PF_None),
+          (PF_None,  PF_None,  PF_None,PF_None,PF_None));
+      begin
+        result:=convertop[fromsize,tosize];
+      end;
+
+
     procedure tbasecgarm.a_loadmm_reg_reg(list: tasmlist; fromsize,tosize: tcgsize; reg1,reg2: tregister; shuffle: pmmshuffle);
       var
         instr: taicpu;
       begin
-        if shuffle=nil then
-          begin
-            if fromsize=tosize then
-              { needs correct size in case of spilling }
-              case fromsize of
-                OS_F32:
-                  instr:=taicpu.op_reg_reg(A_FCPYS,reg2,reg1);
-                OS_F64:
-                  instr:=taicpu.op_reg_reg(A_FCPYD,reg2,reg1);
-                else
-                  internalerror(2009112405);
-              end
-            else
-              internalerror(2009112406);
-          end
-        else if shufflescalar(shuffle) then
-          instr:=taicpu.op_reg_reg(get_scalar_mm_op(tosize,fromsize),reg2,reg1)
+        if (shuffle=nil) or shufflescalar(shuffle) then
+          instr:=setoppostfix(taicpu.op_reg_reg(get_scalar_mm_op(tosize,fromsize),reg2,reg1),get_scalar_mm_prefix(tosize,fromsize))
         else
           internalerror(2009112407);
         list.concat(instr);
         case instr.opcode of
-          A_FCPYS,
-          A_FCPYD:
+          A_VMOV:
             add_move_instruction(instr);
         end;
       end;
@@ -2983,7 +2980,6 @@ unit cgcpu;
         intreg,
         tmpmmreg : tregister;
         reg64    : tregister64;
-        op       : tasmop;
       begin
         if assigned(shuffle) and
            not(shufflescalar(shuffle)) then
@@ -3032,15 +3028,7 @@ unit cgcpu;
           end
         else
           begin
-             case fromsize of
-               OS_F32:
-                 op:=A_FLDS;
-               OS_F64:
-                 op:=A_FLDD;
-               else
-                 internalerror(2009112415);
-             end;
-             handle_load_store(list,op,PF_None,tmpmmreg,ref);
+             handle_load_store(list,A_VLDR,PF_None,tmpmmreg,ref);
           end;
 
         if (tmpmmreg<>reg) then
@@ -3053,7 +3041,6 @@ unit cgcpu;
         intreg,
         tmpmmreg : tregister;
         reg64    : tregister64;
-        op       : tasmop;
       begin
         if assigned(shuffle) and
            not(shufflescalar(shuffle)) then
@@ -3105,15 +3092,7 @@ unit cgcpu;
           end
         else
           begin
-             case fromsize of
-               OS_F32:
-                 op:=A_FSTS;
-               OS_F64:
-                 op:=A_FSTD;
-               else
-                 internalerror(2009112418);
-             end;
-             handle_load_store(list,op,PF_None,tmpmmreg,ref);
+             handle_load_store(list,A_VSTR,PF_None,tmpmmreg,ref);
           end;
       end;
 
@@ -3129,7 +3108,7 @@ unit cgcpu;
         if assigned(shuffle) and
            not shufflescalar(shuffle) then
           internalerror(2009112516);
-        list.concat(taicpu.op_reg_reg(A_FMSR,mmreg,intreg));
+        list.concat(taicpu.op_reg_reg(A_VMOV,mmreg,intreg));
       end;
 
 
@@ -3144,7 +3123,7 @@ unit cgcpu;
         if assigned(shuffle) and
            not shufflescalar(shuffle) then
           internalerror(2009112514);
-        list.concat(taicpu.op_reg_reg(A_FMRS,intreg,mmreg));
+        list.concat(taicpu.op_reg_reg(A_VMOV,intreg,mmreg));
       end;
 
 
@@ -3166,9 +3145,9 @@ unit cgcpu;
                 a_load_const_reg(list,OS_32,0,tmpreg);
                 case size of
                   OS_F32:
-                    list.concat(taicpu.op_reg_reg(A_FMSR,dst,tmpreg));
+                    list.concat(taicpu.op_reg_reg(A_VMOV,dst,tmpreg));
                   OS_F64:
-                    list.concat(taicpu.op_reg_reg_reg(A_FMDRR,dst,tmpreg,tmpreg));
+                    list.concat(taicpu.op_reg_reg_reg(A_VMOV,dst,tmpreg,tmpreg));
                   else
                     internalerror(2009112908);
                 end;
@@ -3290,7 +3269,7 @@ unit cgcpu;
           Internalerror(200109191);
 
           if GenerateThumbCode or GenerateThumb2Code then
-            list.concat(tai_thumb_func.create);
+            list.concat(tai_directive.Create(asd_thumb_func,''));
 
         make_global:=false;
         if (not current_module.is_unit) or
@@ -3433,7 +3412,7 @@ unit cgcpu;
           conversions }
         if (mmsize<>OS_F64) then
           internalerror(2009112405);
-        list.concat(taicpu.op_reg_reg_reg(A_FMDRR,mmreg,intreg.reglo,intreg.reghi));
+        list.concat(taicpu.op_reg_reg_reg(A_VMOV,mmreg,intreg.reglo,intreg.reghi));
       end;
 
 
@@ -3443,7 +3422,7 @@ unit cgcpu;
           conversions }
         if (mmsize<>OS_F64) then
           internalerror(2009112406);
-        list.concat(taicpu.op_reg_reg_reg(A_FMRRD,intreg.reglo,intreg.reghi,mmreg));
+        list.concat(taicpu.op_reg_reg_reg(A_VMOV,intreg.reglo,intreg.reghi,mmreg));
       end;
 
 
@@ -4378,7 +4357,13 @@ 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 in [fpu_fpv4_s16,fpu_vfpv3_d16] then
+        if current_settings.fputype=fpu_vfpv3 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_D16,RS_D17,RS_D18,RS_D19,RS_D20,RS_D21,RS_D22,RS_D23,RS_D24,RS_D25,RS_D26,RS_D27,RS_D28,RS_D29,RS_D30,RS_D31,
+               RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15
+              ],first_mm_imreg,[])
+        else 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
@@ -5301,19 +5286,13 @@ unit cgcpu;
 
     procedure tthumb2cgarm.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
       begin
-        if fromsize=OS_F32 then
-          handle_load_store(list,A_VLDR,PF_F32,reg,ref)
-        else
-          handle_load_store(list,A_VLDR,PF_F64,reg,ref);
+        handle_load_store(list,A_VLDR,PF_None,reg,ref);
       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
-          handle_load_store(list,A_VSTR,PF_F32,reg,ref)
-        else
-          handle_load_store(list,A_VSTR,PF_F64,reg,ref);
+        handle_load_store(list,A_VSTR,PF_None,reg,ref);
       end;
 
 
index 3ebc5c2b46098cf1bc40de1543e41c31f5d01aae..66fd7f1a09cd225f40ade4915e157d766b280aa4 100644 (file)
@@ -93,7 +93,7 @@ unit cpubase;
       first_mm_imreg     = $30;
 
 { TODO: Calculate bsstart}
-      regnumber_count_bsstart = 64;
+      regnumber_count_bsstart = 128;
 
       regnumber_table : array[tregisterindex] of tregister = (
         {$i rarmnum.inc}
@@ -130,6 +130,10 @@ unit cpubase;
         PF_S,
         { floating point size }
         PF_D,PF_E,PF_P,PF_EP,
+        { exchange }
+        PF_X,
+        { rounding }
+        PF_R,
         { load/store }
         PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
         { multiple load/store address modes }
@@ -138,10 +142,18 @@ unit cpubase;
         PF_IAD,PF_DBD,PF_FDD,PF_EAD,
         PF_IAS,PF_DBS,PF_FDS,PF_EAS,
         PF_IAX,PF_DBX,PF_FDX,PF_EAX,
-        { FPv4 postfixes }
-        PF_32,PF_64,PF_F32,PF_F64,
-        PF_F32S32,PF_F32U32,
-        PF_S32F32,PF_U32F32
+        { VFP postfixes }
+        PF_8,PF_16,PF_32,PF_64,
+        PF_I8,PF_I16,PF_I32,PF_I64,
+        PF_S8,PF_S16,PF_S32,PF_S64,
+        PF_U8,PF_U16,PF_U32,PF_U64,
+        PF_P8, // polynomial
+        PF_F32,PF_F64,
+        PF_F32F64,PF_F64F32,
+        PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32,
+        PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64,
+        PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32,
+        PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64
       );
 
       TOpPostfixes = set of TOpPostfix;
@@ -157,14 +169,24 @@ unit cpubase;
       oppostfix2str : array[TOpPostfix] of string[8] = ('',
         's',
         'd','e','p','ep',
+        'x',
+        'r',
         'b','sb','bt','h','sh','t',
         'ia','ib','da','db','fd','fa','ed','ea',
         'iad','dbd','fdd','ead',
         'ias','dbs','fds','eas',
         'iax','dbx','fdx','eax',
-        '.32','.64','.f32','.f64',
-        '.f32.s32','.f32.u32',
-        '.s32.f32','.u32.f32');
+        '.8','.16','.32','.64',
+        '.i8','.i16','.i32','.i64',
+        '.s8','.s16','.s32','.s64',
+        '.u8','.u16','.u32','.u64',
+        '.p8',
+        '.f32','.f64',
+        '.f32.f64','.f64.f32',
+        '.f32.s16','.f32.u16','.s16.f32','.u16.f32',
+        '.f64.s16','.f64.u16','.s16.f64','.u16.f64',
+        '.f32.s32','.f32.u32','.s32.f32','.u32.f32',
+        '.f64.s32','.f64.u32','.s32.f64','.u32.f64');
 
       roundingmode2str : array[TRoundingMode] of string[1] = ('',
         'p','m','z');
@@ -569,7 +591,6 @@ unit cpubase;
       var
         t : aint;
         i : longint;
-        imm : byte;
       begin
         {Loading 0-255 is simple}
         if (d and $FF) = d then
@@ -584,10 +605,20 @@ unit cpubase;
                 ) then
           result:=true
         {Can an 8-bit value be shifted accordingly?}
-        else if is_shifter_const(d,imm) then
-          result:=true
         else
-          result:=false;
+          begin
+            result:=false;
+            for i:=1 to 31 do
+              begin
+                t:=RolDWord(d,i);
+                if ((t and $FF)=t) and
+                   ((t and $80)=$80) then
+                  begin
+                    result:=true;
+                    exit;
+                  end;
+              end;
+          end;
       end;
     
     function is_continuous_mask(d : aint;var lsb, width: byte) : boolean;
index c912955f8962dc9b84e3b6f4a75d8511daf9c6c1..3226885b4cc919094618530df18b004e293eb407 100644 (file)
@@ -325,8 +325,15 @@ implementation
           result:=R_ARM_ABS32;
         RELOC_RELATIVE:
           result:=R_ARM_REL32;
+        RELOC_RELATIVE_24:
+          result:=R_ARM_JUMP24;
+        RELOC_RELATIVE_24_THUMB:
+          result:=R_ARM_CALL;
+        RELOC_RELATIVE_CALL_THUMB:
+          result:=R_ARM_THM_CALL;
       else
         result:=0;
+        writeln(objrel.typ);
         InternalError(2012110602);
       end;
     end;
@@ -666,9 +673,14 @@ implementation
                   begin
                     if (reltyp=R_ARM_CALL) then
                       { change BL to BLX, dest bit 1 goes to instruction bit 24 }
-                      address:=(address and $FE000000) or (((tmp-curloc) and 2) shl 23) or $10000000
+                      address:=(address and $FE000000) or (((tmp-curloc) and 2) shl 23) or $F0000000
                     else
                       InternalError(2014092001);
+                  end
+                else if (address and $FF000000)=$FA000000 then
+                  begin
+                    { Change BLX to BL }
+                    address:=(address and $EA000000) or $01000000;
                   end;
                 tmp:=tmp-curloc;
                 // TODO: check overflow
@@ -902,6 +914,11 @@ implementation
     end;
 
 
+  function elf_arm_encodeflags: longword;
+    begin
+      result:=EF_ARM_EABI_VER5;
+    end;
+
 {*****************************************************************************
                                     Initialize
 *****************************************************************************}
@@ -924,9 +941,26 @@ implementation
         encodereloc:       @elf_arm_encodeReloc;
         loadreloc:         @elf_arm_loadReloc;
         loadsection:       @elf_arm_loadSection;
+        encodeflags:       @elf_arm_encodeflags;
       );
 
+    as_arm_elf32_info : tasminfo =
+       (
+         id     : as_arm_elf32;
+         idtxt  : 'ELF';
+         asmbin : '';
+         asmcmd : '';
+         supported_targets : [system_arm_embedded,system_arm_darwin,
+                              system_arm_linux,system_arm_gba,
+                              system_arm_nds];
+         flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf];
+         labelprefix : '.L';
+         comment : '';
+         dollarsign: '$';
+       );
+
 initialization
+  RegisterAssembler(as_arm_elf32_info,TElfAssembler);
   ElfTarget:=elf_target_arm;
   ElfExeOutputClass:=TElfExeOutputARM;
 
index c0ed34bed89287f5736dfb8ed69ff3c97f957099..043e52602861d4438885bd69228499c34e977fef 100644 (file)
@@ -67,7 +67,8 @@ Type
       fpu_vfpv2,
       fpu_vfpv3,
       fpu_vfpv3_d16,
-      fpu_fpv4_s16
+      fpu_fpv4_s16,
+      fpu_vfpv4
      );
 
    tcontrollertype =
@@ -399,7 +400,8 @@ Const
      'VFPV2',
      'VFPV3',
      'VFPV3_D16',
-     'FPV4_S16'
+     'FPV4_S16',
+     'VFPV4'
    );
 
 
@@ -746,7 +748,7 @@ Const
        { cpu_armv3    } [],
        { cpu_armv4    } [CPUARM_HAS_UMULL],
        { cpu_armv4t   } [CPUARM_HAS_BX,CPUARM_HAS_UMULL],
-       { cpu_armv5    } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_UMULL],
+       { cpu_armv5    } [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],
index 4e26f7173618db1661e7be4de3d1e80429d8518f..0f1ee49cd20776ca52ed0e0d9057d3d4e1801d41 100644 (file)
@@ -162,6 +162,7 @@ interface
       var
         op : TAsmOp;
         singleprec: boolean;
+        pf: TOpPostfix;
       begin
         pass_left_right;
         if (nf_swapped in flags) then
@@ -210,33 +211,25 @@ interface
               location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
 
               singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+              if singleprec then
+                pf:=PF_F32
+              else
+                pf:=PF_F64;
               case nodetype of
                 addn :
-                  if singleprec then
-                    op:=A_FADDS
-                  else
-                    op:=A_FADDD;
+                  op:=A_VADD;
                 muln :
-                  if singleprec then
-                    op:=A_FMULS
-                  else
-                    op:=A_FMULD;
+                  op:=A_VMUL;
                 subn :
-                  if singleprec then
-                    op:=A_FSUBS
-                  else
-                    op:=A_FSUBD;
+                  op:=A_VSUB;
                 slashn :
-                  if singleprec then
-                    op:=A_FDIVS
-                  else
-                    op:=A_FDIVD;
+                  op:=A_VDIV;
                 else
                   internalerror(2009111401);
               end;
 
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
-                 location.register,left.location.register,right.location.register));
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op,
+                 location.register,left.location.register,right.location.register),pf));
             end;
           fpu_fpv4_s16:
             begin
@@ -275,6 +268,7 @@ interface
     procedure tarmaddnode.second_cmpfloat;
       var
         op: TAsmOp;
+        pf: TOpPostfix;
       begin
         pass_left_right;
         if (nf_swapped in flags) then
@@ -310,19 +304,20 @@ interface
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
 
+              if nodetype in [equaln,unequaln] then
+                op:=A_VCMP
+              else
+                op:=A_VCMPE;
+
               if (tfloatdef(left.resultdef).floattype=s32real) then
-                if nodetype in [equaln,unequaln] then
-                  op:=A_FCMPS
-                 else
-                   op:=A_FCMPES
-              else if nodetype in [equaln,unequaln] then
-                op:=A_FCMPD
+                pf:=PF_F32
               else
-                op:=A_FCMPED;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
-                left.location.register,right.location.register));
+                pf:=PF_F64;
+
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op,
+                left.location.register,right.location.register), pf));
               cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
-              current_asmdata.CurrAsmList.concat(taicpu.op_none(A_FMSTAT));
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VMRS,NR_APSR_nzcv,NR_FPSCR));
               location.resflags:=GetFpuResFlags;
             end;
           fpu_fpv4_s16:
index ae7f743b8939ac8bb61bb0bd0d8955cacbd9e57f..62dd2aadb51f055063910c12fb84c3368398d6a0 100644 (file)
@@ -170,9 +170,9 @@ implementation
 
     procedure tarmtypeconvnode.second_int_to_real;
       const
-        signedprec2vfpop: array[boolean,OS_F32..OS_F64] of tasmop =
-          ((A_FUITOS,A_FUITOD),
-           (A_FSITOS,A_FSITOD));
+        signedprec2vfppf: array[boolean,OS_F32..OS_F64] of toppostfix =
+          ((PF_F32U32,PF_F64U32),
+           (PF_F32S32,PF_F64S32));
       var
         instr : taicpu;
         href : treference;
@@ -253,8 +253,9 @@ implementation
                 location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size)
               else
                 location.register:=left.location.register;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(
-                signedprec2vfpop[signed,location.size],location.register,left.location.register));
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VCVT,
+                location.register,left.location.register),
+                signedprec2vfppf[signed,location.size]));
             end;
           fpu_fpv4_s16:
             begin
index 2ba1cf61e1118fa95ff50db3ec2d0f5786961f3a..97979e17b13f9ab8c84b8de4c631417d7e1267c4 100644 (file)
@@ -234,7 +234,7 @@ implementation
     procedure tarminlinenode.second_abs_real;
       var
         singleprec: boolean;
-        op: TAsmOp;
+        pf: TOpPostfix;
       begin
         load_fpu_location(singleprec);
         case current_settings.fputype of
@@ -247,10 +247,10 @@ implementation
           fpu_vfpv3_d16:
             begin
               if singleprec then
-                op:=A_FABSS
+                pf:=PF_F32
               else
-                op:=A_FABSD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+                pf:=PF_F64;
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register),pf));
             end;
           fpu_fpv4_s16:
             current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32));
@@ -270,7 +270,7 @@ implementation
     procedure tarminlinenode.second_sqr_real;
       var
         singleprec: boolean;
-        op: TAsmOp;
+        pf: TOpPostfix;
       begin
         load_fpu_location(singleprec);
         case current_settings.fputype of
@@ -283,10 +283,10 @@ implementation
           fpu_vfpv3_d16:
             begin
               if singleprec then
-                op:=A_FMULS
+                pf:=PF_F32
               else
-                op:=A_FMULD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
+                pf:=PF_F64;
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register),pf));
             end;
           fpu_fpv4_s16:
             current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register), PF_F32));
@@ -299,7 +299,7 @@ implementation
     procedure tarminlinenode.second_sqrt_real;
       var
         singleprec: boolean;
-        op: TAsmOp;
+        pf: TOpPostfix;
       begin
         load_fpu_location(singleprec);
         case current_settings.fputype of
@@ -312,13 +312,13 @@ implementation
           fpu_vfpv3_d16:
             begin
               if singleprec then
-                op:=A_FSQRTS
+                pf:=PF_F32
               else
-                op:=A_FSQRTD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+                pf:=PF_F64;
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register),pf));
             end;
           fpu_fpv4_s16:
-            current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register));
+            current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register), PF_F32));
         else
           internalerror(2009111402);
         end;
index f9a6e922637ed11f7072509752dcc91f84dc7020..3e2d5b9499969e7778d6cec95f65efc8d2a82a21 100644 (file)
@@ -411,6 +411,7 @@ implementation
     procedure tarmunaryminusnode.second_float;
       var
         op: tasmop;
+        pf: TOpPostfix;
       begin
         secondpass(left);
         case current_settings.fputype of
@@ -432,12 +433,14 @@ implementation
               location:=left.location;
               if (left.location.loc=LOC_CMMREGISTER) then
                 location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
-              if (location.size=OS_F32) then
-                op:=A_FNEGS
+
+              if (tfloatdef(left.resultdef).floattype=s32real) then
+                pf:=PF_F32
               else
-                op:=A_FNEGD;
-              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
-                location.register,left.location.register));
+                pf:=PF_F64;
+
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG,
+                location.register,left.location.register), pf));
             end;
           fpu_fpv4_s16:
             begin
index cdda16413b04bd7ee9246e46e4ab80ed72f4dc59..e316074f8fc7a7515e786a4cdc067124bfa64ef3 100644 (file)
@@ -27,6 +27,7 @@ interface
 
     uses
       globtype,
+      symtype,
       cgbase,cpubase,nmem,ncgmem;
 
     type
@@ -36,7 +37,7 @@ interface
 
 
       tarmvecnode = class(tcgvecnode)
-        procedure update_reference_reg_mul(maybe_const_reg: tregister; l: aint);override;
+        procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);override;
       end;
 
 implementation
@@ -70,7 +71,7 @@ implementation
                              TARMVECNODE
 *****************************************************************************}
 
-     procedure tarmvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+     procedure tarmvecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
        var
          hreg: tregister;
          hl : longint;
@@ -79,7 +80,7 @@ implementation
             (GenerateThumbCode) or
             { simple constant? }
             (l=1) or ispowerof2(l,hl) or ispowerof2(l+1,hl) or ispowerof2(l-1,hl) then
-           inherited update_reference_reg_mul(maybe_const_reg,l)
+           inherited update_reference_reg_mul(maybe_const_reg,regsize,l)
          else if (location.reference.base<>NR_NO) then
            begin
              hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
index e7de7b8d716fcb6fbc910d4753730290961b041a..07ffca3ef565df93647c05cdafdcc426bdc0ebf8 100644 (file)
@@ -30,6 +30,7 @@ Unit raarmgas;
       cpubase;
 
     type
+
       tarmattreader = class(tattreader)
         actoppostfix : TOpPostfix;
         actwideformat : boolean;
@@ -45,6 +46,13 @@ Unit raarmgas;
         procedure ReadSym(oper : tarmoperand);
         procedure ConvertCalljmp(instr : tarminstruction);
         procedure HandleTargetDirective; override;
+      protected
+        function is_unified: boolean; virtual;
+      end;
+
+      tarmunifiedattreader = class(tarmattreader)
+      protected
+        function is_unified: boolean; override;
       end;
 
 
@@ -63,15 +71,21 @@ Unit raarmgas;
       cgbase,cgutils;
 
 
+    function tarmunifiedattreader.is_unified: boolean;
+      begin
+        result:=true;
+      end;
+
+
     function tarmattreader.is_register(const s:string):boolean;
       type
         treg2str = record
-          name : string[2];
+          name : string[3];
           reg : tregister;
         end;
 
       const
-        extraregs : array[0..19] of treg2str = (
+        extraregs : array[0..19+16] of treg2str = (
           (name: 'A1'; reg : NR_R0),
           (name: 'A2'; reg : NR_R1),
           (name: 'A3'; reg : NR_R2),
@@ -91,7 +105,25 @@ Unit raarmgas;
           (name: 'IP'; reg : NR_R12),
           (name: 'SP'; reg : NR_R13),
           (name: 'LR'; reg : NR_R14),
-          (name: 'PC'; reg : NR_R15));
+          (name: 'PC'; reg : NR_R15),
+
+          (name: 'C0'; reg : NR_CR0),
+          (name: 'C1'; reg : NR_CR1),
+          (name: 'C2'; reg : NR_CR2),
+          (name: 'C3'; reg : NR_CR3),
+          (name: 'C4'; reg : NR_CR4),
+          (name: 'C5'; reg : NR_CR5),
+          (name: 'C6'; reg : NR_CR6),
+          (name: 'C7'; reg : NR_CR7),
+          (name: 'C8'; reg : NR_CR8),
+          (name: 'C9'; reg : NR_CR9),
+          (name: 'C10'; reg : NR_CR10),
+          (name: 'C11'; reg : NR_CR11),
+          (name: 'C12'; reg : NR_CR12),
+          (name: 'C13'; reg : NR_CR13),
+          (name: 'C14'; reg : NR_CR14),
+          (name: 'C15'; reg : NR_CR15)
+          );
 
       var
         i : longint;
@@ -101,7 +133,7 @@ Unit raarmgas;
         { reg found?
           possible aliases are always 2 char
         }
-        if result or (length(s)<>2) then
+        if result or (not (length(s) in [2,3])) then
           exit;
         for i:=low(extraregs) to high(extraregs) do
           begin
@@ -241,7 +273,9 @@ Unit raarmgas;
                           do_error;
                         oper.opr.ref.shiftimm := shift;
                         test_end(require_rbracket);
-                      end;
+                      end
+                    else
+                      test_end(require_rbracket);
                    end
                  else
                    begin
@@ -528,7 +562,7 @@ Unit raarmgas;
             else if (actasmpattern='ROR') then
               handlepara(SM_ROR)
             else if (actasmpattern='RRX') then
-              handlepara(SM_ROR)
+              handlepara(SM_RRX)
             else
               result:=false;
           end
@@ -785,6 +819,18 @@ Unit raarmgas;
           end;
 
 
+      function getregsetindex(reg: tregister): integer;
+        begin
+          if getsubreg(reg)=R_SUBFS then
+            begin
+              result:=getsupreg(reg)*2;
+              if result>32 then
+                result:=result-63;
+            end
+          else
+            result:=getsupreg(reg);
+        end;
+
       var
         tempreg : tregister;
         ireg : tsuperregister;
@@ -958,7 +1004,7 @@ Unit raarmgas;
                   oper.opr.typ:=OPR_REGISTER;
                   oper.opr.reg:=tempreg;
                 end
-              else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM,A_FLDM,A_FSTM]) then
+              else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM,A_FLDM,A_FSTM,A_VLDM,A_VSTM]) then
                 begin
                   consume(AS_NOT);
                   oper.opr.typ:=OPR_REFERENCE;
@@ -976,11 +1022,11 @@ Unit raarmgas;
               registerset:=[];
               regtype:=R_INVALIDREGISTER;
               subreg:=R_SUBNONE;
-              while true do
+              while actasmtoken<>AS_RSBRACKET do
                 begin
                   if actasmtoken=AS_REGISTER then
                     begin
-                      include(registerset,getsupreg(actasmregister));
+                      include(registerset,getregsetindex(actasmregister));
                       if regtype<>R_INVALIDREGISTER then
                         begin
                           if (getregtype(actasmregister)<>regtype) or
@@ -997,7 +1043,7 @@ Unit raarmgas;
                       if actasmtoken=AS_MINUS then
                         begin
                           consume(AS_MINUS);
-                          for ireg:=getsupreg(tempreg) to getsupreg(actasmregister) do
+                          for ireg:=getregsetindex(tempreg) to getregsetindex(actasmregister) do
                             include(registerset,ireg);
                           consume(AS_REGISTER);
                         end;
@@ -1137,8 +1183,19 @@ Unit raarmgas;
           case actasmtoken of
             AS_COMMA: { Operand delimiter }
               Begin
-                if ((instr.opcode in [A_MOV, A_MVN, A_CMP, A_CMN, A_TST, A_TEQ]) and (operandnum=2)) or
-                  ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA,A_MRC,A_MCR,A_MCRR,A_MRRC])) then
+                if ((instr.opcode in [A_MOV,A_MVN,A_CMP,A_CMN,A_TST,A_TEQ,
+                                      A_UXTB,A_UXTH,A_UXTB16,
+                                      A_SXTB,A_SXTH,A_SXTB16]) and
+                    (operandnum=2)) or
+                  ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA,A_UMAAL,A_MLS,
+                                                           A_SMLABB,A_SMLABT,A_SMLATB,A_SMLATT,A_SMMLA,A_SMMLS,A_SMLAD,A_SMLALD,A_SMLSD,
+                                                           A_SMLALBB,A_SMLALBT,A_SMLALTB,A_SMLALTT,A_SMLSLD,
+                                                           A_SMLAWB,A_SMLAWT,
+                                                           A_MRC,A_MCR,A_MCRR,A_MRRC,A_MRC2,A_MCR2,A_MCRR2,A_MRRC2,
+                                                           A_STREXD,A_STRD,
+                                                           A_USADA8,
+                                                           A_VMOV,
+                                                           A_SBFX,A_UBFX,A_BFI])) then
                   begin
                     Consume(AS_COMMA);
                     if not(TryBuildShifterOp(instr.Operands[operandnum+1] as tarmoperand)) then
@@ -1160,7 +1217,8 @@ Unit raarmgas;
                 break;
               end;
           else
-            if (instr.opcode = A_MSR) and (operandnum = 1) then
+            if ((instr.opcode = A_MRS) and (operandnum = 2)) or
+               ((instr.opcode = A_MSR) and (operandnum = 1)) then
               BuildSpecialreg(instr.Operands[operandnum] as tarmoperand)
             else
               BuildOperand(instr.Operands[operandnum] as tarmoperand);
@@ -1174,25 +1232,34 @@ Unit raarmgas;
 
       const
         { sorted by length so longer postfixes will match first }
-        postfix2strsorted : array[1..31] of string[3] = (
-          'IAD','DBD','FDD','EAD',
-          'IAS','DBS','FDS','EAS',
-          'IAX','DBX','FDX','EAX',
-          'EP','SB','BT','SH',
-          'IA','IB','DA','DB','FD','FA','ED','EA',
-          'B','D','E','P','T','H','S');
-
-        postfixsorted : array[1..31] of TOpPostfix = (
-          PF_IAD,PF_DBD,PF_FDD,PF_EAD,
-          PF_IAS,PF_DBS,PF_FDS,PF_EAS,
-          PF_IAX,PF_DBX,PF_FDX,PF_EAX,
-          PF_EP,PF_SB,PF_BT,PF_SH,
-          PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
-          PF_B,PF_D,PF_E,PF_P,PF_T,PF_H,PF_S);
+        postfix2strsorted : array[1..70] of string[9] = (
+          '.F32.S32','.F32.U32','.S32.F32','.U32.F32','.F64.S32','.F64.U32','.S32.F64','.U32.F64',
+          '.F32.S16','.F32.U16','.S16.F32','.U16.F32','.F64.S16','.F64.U16','.S16.F64','.U16.F64',
+          '.F32.F64','.F64.F32',
+          '.I16','.I32','.I64','.S16','.S32','.S64','.U16','.U32','.U64','.F32','.F64',
+          'IAD','DBD','FDD','EAD','IAS','DBS','FDS','EAS','IAX','DBX','FDX','EAX',
+          '.16','.32','.64','.I8','.S8','.U8','.P8',
+          'EP','SB','BT','SH','IA','IB','DA','DB','FD','FA','ED','EA',
+          '.8','S','D','E','P','X','R','B','H','T');
+
+        postfixsorted : array[1..70] of TOpPostfix = (
+          PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32,PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64,
+          PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32,PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64,
+          PF_F32F64,PF_F64F32,
+          PF_I16,PF_I32,
+          PF_I64,PF_S16,PF_S32,PF_S64,PF_U16,PF_U32,PF_U64,PF_F32,
+          PF_F64,PF_IAD,PF_DBD,PF_FDD,PF_EAD,
+          PF_IAS,PF_DBS,PF_FDS,PF_EAS,PF_IAX,
+          PF_DBX,PF_FDX,PF_EAX,PF_16,PF_32,
+          PF_64,PF_I8,PF_S8,PF_U8,PF_P8,
+          PF_EP,PF_SB,PF_BT,PF_SH,PF_IA,
+          PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,
+          PF_ED,PF_EA,PF_8,PF_S,PF_D,PF_E,
+          PF_P,PF_X,PF_R,PF_B,PF_H,PF_T);
 
       var
-        j  : longint;
-        hs : string;
+        j, j2 : longint;
+        hs,hs2 : string;
         maxlen : longint;
         icond : tasmcond;
       Begin
@@ -1220,61 +1287,126 @@ Unit raarmgas;
                   end;
               end;
           end;
-        maxlen:=max(length(hs),5);
+        maxlen:=min(length(hs),6);
         actopcode:=A_NONE;
-        for j:=maxlen downto 1 do
+        j2:=maxlen;
+        hs2:=hs;
+        while j2>=1 do
           begin
-            actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
-            if actopcode<>A_NONE then
+            hs:=hs2;
+            while j2>=1 do
               begin
-                actasmtoken:=AS_OPCODE;
-                { strip op code }
-                delete(hs,1,j);
-                break;
+                actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
+                if actopcode<>A_NONE then
+                  begin
+                    actasmtoken:=AS_OPCODE;
+                    { strip op code }
+                    delete(hs,1,j2);
+                    dec(j2);
+                    break;
+                  end;
+                dec(j2);
               end;
-          end;
-        if actopcode=A_NONE then
-          exit;
 
-        { search for condition, conditions are always 2 chars }
-        if length(hs)>1 then
-          begin
-            for icond:=low(tasmcond) to high(tasmcond) do
+            if actopcode=A_NONE then
+              exit;
+
+            if is_unified then
               begin
-                if copy(hs,1,2)=uppercond2str[icond] then
+                { check for postfix }
+                if (length(hs)>0) and (actoppostfix=PF_None) then
                   begin
-                    actcondition:=icond;
-                    { strip condition }
-                    delete(hs,1,2);
-                    break;
+                    for j:=low(postfixsorted) to high(postfixsorted) do
+                      begin
+                        if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                          begin
+                            if not ((length(hs)-length(postfix2strsorted[j])) in [0,2,4]) then
+                              continue;
+
+                            actoppostfix:=postfixsorted[j];
+                            { strip postfix }
+                            delete(hs,1,length(postfix2strsorted[j]));
+                            break;
+                          end;
+                      end;
                   end;
-              end;
-          end;
-        { check for postfix }
-        if length(hs)>0 then
-          begin
-            for j:=low(postfixsorted) to high(postfixsorted) do
+                { search for condition, conditions are always 2 chars }
+                if length(hs)>1 then
+                  begin
+                    for icond:=low(tasmcond) to high(tasmcond) do
+                      begin
+                        if copy(hs,1,2)=uppercond2str[icond] then
+                          begin
+                            actcondition:=icond;
+                            { strip condition }
+                            delete(hs,1,2);
+                            break;
+                          end;
+                      end;
+                  end;
+                { check for postfix }
+                if (length(hs)>0) and (actoppostfix=PF_None) then
+                  begin
+                    for j:=low(postfixsorted) to high(postfixsorted) do
+                      begin
+                        if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                          begin
+                            if not ((length(hs)-length(postfix2strsorted[j])) = 0) then
+                              continue;
+
+                            actoppostfix:=postfixsorted[j];
+                            { strip postfix }
+                            delete(hs,1,length(postfix2strsorted[j]));
+                            break;
+                          end;
+                      end;
+                  end;
+              end
+            else
               begin
-                if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                { search for condition, conditions are always 2 chars }
+                if length(hs)>1 then
                   begin
-                    actoppostfix:=postfixsorted[j];
-                    { strip postfix }
-                    delete(hs,1,length(postfix2strsorted[j]));
-                    break;
+                    for icond:=low(tasmcond) to high(tasmcond) do
+                      begin
+                        if copy(hs,1,2)=uppercond2str[icond] then
+                          begin
+                            actcondition:=icond;
+                            { strip condition }
+                            delete(hs,1,2);
+                            break;
+                          end;
+                      end;
+                  end;
+                { check for postfix }
+                if (length(hs)>0) and (actoppostfix=PF_None) then
+                  begin
+                    for j:=low(postfixsorted) to high(postfixsorted) do
+                      begin
+                        if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+                          begin
+                            actoppostfix:=postfixsorted[j];
+                            { strip postfix }
+                            delete(hs,1,length(postfix2strsorted[j]));
+                            break;
+                          end;
+                      end;
                   end;
               end;
-          end;
-        { check for format postfix }
-        if length(hs)>0 then
-          begin
-            if upcase(copy(hs,1,2)) = '.W' then
+            { check for format postfix }
+            if length(hs)>0 then
               begin
-                actwideformat:=true;
-                delete(hs,1,2);
+                if copy(hs,1,2) = '.W' then
+                  begin
+                    actwideformat:=true;
+                    delete(hs,1,2);
+                  end;
               end;
+            { if we stripped all postfixes, it's a valid opcode }
+            is_asmopcode:=length(hs)=0;
+            if is_asmopcode = true then
+              break;
           end;
-        { if we stripped all postfixes, it's a valid opcode }
-        is_asmopcode:=length(hs)=0;
       end;
 
 
@@ -1313,12 +1445,17 @@ Unit raarmgas;
         else if actasmpattern='.thumb_func' then
           begin
             consume(AS_TARGET_DIRECTIVE);
-            curList.concat(tai_thumb_func.create);
+            curList.concat(tai_directive.create(asd_thumb_func,''));
           end
         else
           inherited HandleTargetDirective;
       end;
 
+    function tarmattreader.is_unified: boolean;
+      begin
+        result:=false;
+      end;
+
 
     procedure tarmattreader.handleopcode;
       var
@@ -1348,10 +1485,17 @@ const
   asmmode_arm_att_info : tasmmodeinfo =
           (
             id    : asmmode_arm_gas;
-            idtxt : 'GAS';
+            idtxt : 'DIVIDED';
             casmreader : tarmattreader;
           );
 
+  asmmode_arm_att_unified_info : tasmmodeinfo =
+          (
+            id    : asmmode_arm_gas_unified;
+            idtxt : 'UNIFIED';
+            casmreader : tarmunifiedattreader;
+          );
+
   asmmode_arm_standard_info : tasmmodeinfo =
           (
             id    : asmmode_standard;
@@ -1361,5 +1505,6 @@ const
 
 initialization
   RegisterAsmMode(asmmode_arm_att_info);
+  RegisterAsmMode(asmmode_arm_att_unified_info);
   RegisterAsmMode(asmmode_arm_standard_info);
 end.
index 3d5cb5e7f42726da39c3c05acafccddb5552658b..5eccbc818fe03e7c80077372190997669fe5146d 100644 (file)
@@ -123,3 +123,10 @@ NR_BASEPRI = tregister($0500001F);
 NR_BASEPRI_MAX = tregister($05000020);
 NR_FAULTMASK = tregister($05000021);
 NR_CONTROL = tregister($05000022);
+NR_FPSID = tregister($05000023);
+NR_MVFR1 = tregister($05000024);
+NR_MVFR0 = tregister($05000025);
+NR_FPEXC = tregister($05000026);
+NR_APSR_nzcvq = tregister($05000027);
+NR_APSR_g = tregister($05000028);
+NR_APSR_nzcvqg = tregister($05000029);
index 624996d855e8f1d5853eb17f4e38476592625409..d2e3292cf853160ac8317dbb23fd6e6c878907c7 100644 (file)
 0,
 0,
 0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
 0
index 5b7bb114ef586078f9b8837abd20c184d156e932..c4e9a7062090556c3c948dba87e4d586ce70ca15 100644 (file)
@@ -1,2 +1,2 @@
 { don't edit, this file is generated from armreg.dat }
-124
+131
index 73d011e105ccb526edad09be609055c1593c44ac..16002ed6084ea04eff29323da995e40bd204b7ab 100644 (file)
@@ -122,4 +122,11 @@ tregister($0500001E),
 tregister($0500001F),
 tregister($05000020),
 tregister($05000021),
-tregister($05000022)
+tregister($05000022),
+tregister($05000023),
+tregister($05000024),
+tregister($05000025),
+tregister($05000026),
+tregister($05000027),
+tregister($05000028),
+tregister($05000029)
index be4c8f3524f5437ec708a7603b11e79b9608176e..cd3dc04a9698699c716a0dab2f2947afb5bcf23c 100644 (file)
 120,
 121,
 122,
-123
+123,
+124,
+125,
+126,
+127,
+128,
+129,
+130
index 6eca14213ea4c445545f4918997c237e697f3960..1f5dabb4054a53acb24afa000a580c10b8c66d59 100644 (file)
@@ -1,7 +1,10 @@
 { don't edit, this file is generated from armreg.dat }
 0,
 110,
+129,
 92,
+128,
+130,
 120,
 121,
 123,
 23,
 24,
 122,
+127,
 90,
+124,
 114,
 113,
 111,
 117,
+126,
+125,
 109,
 119,
 118,
 53,
 28,
 55,
-71,
 56,
 58,
 59,
 68,
 29,
 70,
+71,
 31,
 32,
 34,
index bce1177c075948ef123c52cc95a52d91e530ae6d..db130cb127f02349903eb1a0274fbc9e10173a7c 100644 (file)
 0,
 0,
 0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
 0
index 4fed2df7ffcd19ae29e23028d0d4fa0b7c74cc9d..1f9c8211bbae3654a91a9c63db3d2ebea10e2e42 100644 (file)
@@ -70,7 +70,7 @@
 's29',
 'd14',
 's30',
-'s21',
+'s31',
 'd15',
 'd16',
 'd17',
 'basepri',
 'basepri_max',
 'faultmask',
-'control'
+'control',
+'fpsid',
+'mvfr1',
+'mvfr0',
+'fpexc',
+'apsr_nzcvq',
+'apsr_g',
+'apsr_nzcvqg'
index 285c1e09e9206aa0c1cfdb0e8227ddfb88f74dce..7baa8ad7818384102829b2d6bce669868470af3f 100644 (file)
@@ -123,3 +123,10 @@ RS_BASEPRI = $1F;
 RS_BASEPRI_MAX = $20;
 RS_FAULTMASK = $21;
 RS_CONTROL = $22;
+RS_FPSID = $23;
+RS_MVFR1 = $24;
+RS_MVFR0 = $25;
+RS_FPEXC = $26;
+RS_APSR_nzcvq = $27;
+RS_APSR_g = $28;
+RS_APSR_nzcvqg = $29;
index 16c6272e207f6ed45b2eee960a254ae651e0a375..feb007f3680ad68fafb5b041bc739a930fe9205c 100644 (file)
@@ -83,6 +83,7 @@ interface
         lastsectype : TAsmSectionType;
         procedure WriteSourceLine(hp: tailineinfo);
         procedure WriteTempalloc(hp: tai_tempalloc);
+        Function DoPipe:boolean;
       public
         {# Returns the complete path and executable name of the assembler
            program.
@@ -271,7 +272,7 @@ Implementation
                                  TExternalAssembler
 *****************************************************************************}
 
-    Function DoPipe:boolean;
+    Function TExternalAssembler.DoPipe:boolean;
       begin
         DoPipe:=(cs_asm_pipe in current_settings.globalswitches) and
                 (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) and
@@ -1224,6 +1225,10 @@ Implementation
                    asd_reference:
                      { ignore for now, but should be added}
                      ;
+{$ifdef ARM}
+                   asd_thumb_func:
+                     ObjData.ThumbFunc:=true;
+{$endif ARM}
                    else
                      internalerror(2010011101);
                  end;
@@ -1368,6 +1373,9 @@ Implementation
                    asd_reference:
                      { ignore for now, but should be added}
                      ;
+                   asd_thumb_func:
+                     { ignore for now, but should be added}
+                     ;
                    else
                      internalerror(2010011102);
                  end;
@@ -1391,6 +1399,7 @@ Implementation
         objsymend : TObjSymbol;
         zerobuf : array[0..63] of byte;
         relative_reloc: boolean;
+        tmp    : word;
       begin
         fillchar(zerobuf,sizeof(zerobuf),0);
         fillchar(objsym,sizeof(objsym),0);
@@ -1514,6 +1523,11 @@ Implementation
                    aitconst_darwin_dwarf_delta32,
                    aitconst_darwin_dwarf_delta64:
                      ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
+                   aitconst_half16bit:
+                     begin
+                       tmp:=Tai_const(hp).value div 2;
+                       ObjData.writebytes(tmp,2);
+                     end
                    else
                      internalerror(200603254);
                  end;
index 678192e96e2ac4bfa5f5dba0f309dc4260e4edb2..dff6e84ea78f92884a81a3d8876ed4d6b6f8c611 100644 (file)
@@ -101,6 +101,12 @@ interface
          ,addr_dgroup      // the data segment group
          ,addr_seg         // used for getting the segment of an object, e.g. 'mov ax, SEG symbol'
          {$ENDIF}
+         {$IFDEF AARCH64}
+         ,addr_page
+         ,addr_pageoffset
+         ,addr_gotpage
+         ,addr_gotpageoffset
+         {$ENDIF AARCH64}
          );
 
 
@@ -329,6 +335,13 @@ interface
           OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_M256,OS_M8,OS_M16,OS_M32,
           OS_M64,OS_M128,OS_M256);
 
+       tcgsize2signed : array[tcgsize] of tcgsize = (OS_NO,
+          OS_S8,OS_S16,OS_S32,OS_S64,OS_S128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128,
+          OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+          OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_M256,OS_M8,OS_M16,OS_M32,
+          OS_M64,OS_M128,OS_M256);
+
+
        tcgloc2str : array[TCGLoc] of string[12] = (
             'LOC_INVALID',
             'LOC_VOID',
index 7568553f678d2ba1ccc7b2a920e9240ff4bc6a2a..c9620e460ebe0f7e71efe7a4e307852a481983d5 100644 (file)
@@ -65,14 +65,14 @@ uses
       procedure a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); override;
       procedure a_call_reg(list: TAsmList; reg: tregister); override;
       procedure a_call_name(list: TAsmList; const s: string; weak: boolean); override;
-      procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister); override;
+      procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
     end;
 
 implementation
 
    { thlbasecgcpu }
 
-    procedure thlbasecgcpu.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister);
+    procedure thlbasecgcpu.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
       begin
         internalerror(2012042801);
       end;
index ccf26f2d114ce1895bb8720f28c21a7809306454..4245ff4a3859732c445e25639c0678cd0c40956a 100644 (file)
@@ -247,7 +247,7 @@ 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;
+          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: 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. }
@@ -865,7 +865,14 @@ implementation
          ref : treference;
          tmpreg : tregister;
       begin
-         cgpara.check_simple_location;
+         if assigned(cgpara.location^.next) then
+           begin
+             tg.gethltemp(list,cgpara.def,cgpara.def.size,tt_persistent,ref);
+             a_load_reg_ref(list,size,size,r,ref);
+             a_load_ref_cgpara(list,size,ref,cgpara);
+             tg.ungettemp(list,ref);
+             exit;
+           end;
          paramanager.alloccgpara(list,cgpara);
          if cgpara.location^.shiftval<0 then
            begin
@@ -2525,7 +2532,7 @@ implementation
       end;
 
 
-    procedure tcg.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister);
+    procedure tcg.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
       begin
         internalerror(2014070601);
       end;
index fb2fea8c7727ad926d9ec3d7f996af29d202a3f5..738026ff2486050b03bff86dd0ca3f3a616e609b 100644 (file)
@@ -63,6 +63,12 @@ unit cgutils;
          addressmode : taddressmode;
          shiftmode   : tshiftmode;
 {$endif arm}
+{$ifdef aarch64}
+         symboldata  : tlinkedlistitem;
+         shiftimm    : byte;
+         addressmode : taddressmode;
+         shiftmode   : tshiftmode;
+{$endif aarch64}
 {$ifdef avr}
          addressmode : taddressmode;
 {$endif avr}
index cf24905b7b72972e567dfade65ee9e33619bfd48..83e7c7f54ed6a1c23df06dd7c9361a8056dc793a 100644 (file)
   {$define cpurox}
   {$define cputargethasfixedstack}
   {$define cpurefshaveindexreg}
+  {$define SUPPORT_GET_FRAME}
 {$endif aarch64}
 
 {$IFDEF MACOS}
index 6d50fd9d145008bce0518d663670a566c30098a0..bae865c1a559832aaca4a83343d66136541aa43a 100644 (file)
@@ -171,7 +171,7 @@ unit hlcg2ll;
           procedure a_loadaddr_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister);override;
 
           { bit scan instructions }
-          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tdef; src, dst: tregister); override;
+          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister); override;
 
           { fpu move instructions }
           procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
@@ -586,9 +586,9 @@ implementation
       cg.a_loadaddr_ref_reg(list,ref,r);
     end;
 
-  procedure thlcg2ll.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tdef; src, dst: tregister);
+  procedure thlcg2ll.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister);
     begin
-      cg.a_bit_scan_reg_reg(list,reverse,def_cgsize(size),src,dst);
+      cg.a_bit_scan_reg_reg(list,reverse,def_cgsize(srcsize),def_cgsize(dstsize),src,dst);
     end;
 
   procedure thlcg2ll.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
index 5a938882c3c41d4267d8f26c65e1fb2277eb2885..1bc55d54cc2657e04684dc0687c6ef330f63308b 100644 (file)
@@ -301,7 +301,7 @@ unit hlcgobj;
          public
 
           { bit scan instructions (still need transformation to thlcgobj) }
-          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tdef; src, dst: tregister); virtual; abstract;
+          procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister); virtual; abstract;
 
           { fpu move instructions }
           procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); virtual; abstract;
@@ -536,9 +536,9 @@ unit hlcgobj;
          public
 
           procedure gen_load_para_value(list:TAsmList);virtual;
-         protected
           { helpers called by gen_load_para_value }
           procedure g_copyvalueparas(p:TObject;arg:pointer);virtual;
+         protected
           procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
           procedure init_paras(p:TObject;arg:pointer);
          protected
@@ -4140,7 +4140,7 @@ implementation
         begin
 {$ifdef arm}
           if GenerateThumbCode or GenerateThumb2Code then
-            list.concat(tai_thumb_func.create);
+            list.concat(tai_directive.create(asd_thumb_func,''));
 {$endif arm}
           { "double link" all procedure entry symbols via .reference }
           { directives on darwin, because otherwise the linker       }
@@ -4523,7 +4523,11 @@ implementation
          if (tparavarsym(p).varspez=vs_value) then
           begin
             include(current_procinfo.flags,pi_needs_implicit_finally);
-            location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).localloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+            location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).localloc,href,
+              is_open_array(tparavarsym(p).vardef) or
+              ((target_info.system in systems_caller_copy_addr_value_para) and
+               paramanager.push_addr_param(vs_value,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)),
+              sizeof(pint));
             if is_open_array(tparavarsym(p).vardef) then
               begin
                 if paramanager.push_high_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption) then
@@ -4543,7 +4547,8 @@ implementation
           end;
        end;
       { open arrays can contain elements requiring init/final code, so the else has been removed here }
-      if (tparavarsym(p).varspez=vs_value) and
+      if not(target_info.system in systems_caller_copy_addr_value_para) and
+         (tparavarsym(p).varspez=vs_value) and
          (is_open_array(tparavarsym(p).vardef) or
           is_array_of_const(tparavarsym(p).vardef)) then
         begin
@@ -4581,7 +4586,11 @@ implementation
                  if not((tparavarsym(p).vardef.typ=variantdef) and
                    paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
                    begin
-                     location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+                     location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,
+                       is_open_array(tparavarsym(p).vardef) or
+                       ((target_info.system in systems_caller_copy_addr_value_para) and
+                        paramanager.push_addr_param(vs_value,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)),
+                       sizeof(pint));
                      if is_open_array(tparavarsym(p).vardef) then
                        begin
                          if paramanager.push_high_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption) then
@@ -4682,8 +4691,11 @@ implementation
     begin
       list:=TAsmList(arg);
       if (tsym(p).typ=paravarsym) and
-         (tparavarsym(p).varspez=vs_value) and
-        (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
+         ((vo_has_local_copy in tparavarsym(p).varoptions) or
+          (not(target_info.system in systems_caller_copy_addr_value_para) and
+           (is_open_array(tparavarsym(p).vardef) or
+            is_array_of_const(tparavarsym(p).vardef)) and
+           (tparavarsym(p).varspez=vs_value))) then
         begin
           { we have no idea about the alignment at the caller side }
           location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,true,1);
index fd171e3ed0134e2f27ebf0896c139db3c8e1ed47..7c6c36b2f5a2ab3c9d7427d8095be5165d463f28 100644 (file)
@@ -496,6 +496,7 @@ implementation
         encodereloc:       @elf_i386_encodeReloc;
         loadreloc:         @elf_i386_loadReloc;
         loadsection:       nil;
+        encodeflags:       nil;
       );
 
     as_i386_elf32_info : tasminfo =
index 7d12ef92234693ffbb9e513f1111910d4dc0104c..0dc521b8fa22b2dc29f0fd02810c1d5f8d81d204 100644 (file)
@@ -27,6 +27,7 @@ interface
 
     uses
       globtype,
+      symtype,
       cgbase,cpuinfo,cpubase,
       node,nmem,ncgmem,nx86mem,ni86mem;
 
@@ -45,7 +46,7 @@ interface
        ti8086vecnode = class(tcgvecnode)
         protected
          function first_arraydef: tnode;override;
-         procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);override;
+         procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);override;
        end;
 
 implementation
@@ -53,7 +54,7 @@ implementation
     uses
       systems,globals,constexp,
       cutils,verbose,
-      symbase,symconst,symdef,symtable,symtype,symsym,symx86,symcpu,
+      symbase,symconst,symdef,symtable,symsym,symx86,symcpu,
       parabase,paramgr,
       aasmtai,aasmdata,
       nld,ncon,nadd,ncal,ncnv,
@@ -212,13 +213,13 @@ implementation
       end;
 
 
-    procedure ti8086vecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+    procedure ti8086vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
       var
         saveseg: TRegister;
       begin
         saveseg:=location.reference.segment;
         location.reference.segment:=NR_NO;
-        inherited update_reference_reg_mul(maybe_const_reg,l);
+        inherited;
         location.reference.segment:=saveseg;
       end;
 
index 909c18703e0d9db32260c58b978ae9db73852cea..96b9d683c4d71189402455b815f4a9107e9a91f6 100644 (file)
@@ -114,7 +114,7 @@ uses
       procedure gen_exit_code(list: TAsmList); override;
 
       { unimplemented/unnecessary routines }
-      procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tdef; src, dst: tregister); override;
+      procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister); override;
       procedure a_loadmm_loc_reg(list: TAsmList; fromsize, tosize: tdef; const loc: tlocation; const reg: tregister; shuffle: pmmshuffle); override;
       procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister; shuffle: pmmshuffle); override;
       procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister; shuffle: pmmshuffle); override;
@@ -1884,7 +1884,7 @@ implementation
       { nothing }
     end;
 
-  procedure thlcgjvm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tdef; src, dst: tregister);
+  procedure thlcgjvm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister);
     begin
       internalerror(2012090201);
     end;
index d6cb270f0b8832b2fe0b668c319b3a18e9f6a6ec..6c72fab54b0a3c48525100ed6ccc5ae05dc9c9a5 100644 (file)
@@ -27,12 +27,13 @@ interface
 
     uses
       globtype,
+      symtype,
       cgbase,cpuinfo,cpubase,
       node,nmem,ncgmem;
 
     type
        t68kvecnode = class(tcgvecnode)
-          procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);override;
+          procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint); override;
           //procedure pass_generate_code;override;
        end;
 
@@ -59,7 +60,7 @@ implementation
     { the live range of the LOC_CREGISTER will most likely overlap the   }
     { the live range of the target LOC_(C)REGISTER)                      }
     { The passed register may be a LOC_CREGISTER as well.                }
-    procedure t68kvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+    procedure t68kvecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
       var
         hreg: tregister;
         scaled: boolean;
index 1c2de17e0c22c61cb36e65e92a591e5cc9a615ba..9beff74504c42865d10fe912e6850c89527899ef 100644 (file)
@@ -1026,6 +1026,7 @@ implementation
         encodereloc:       @elf_mips_encodeReloc;
         loadreloc:         @elf_mips_loadReloc;
         loadsection:       @elf_mips_loadSection;
+        encodeflags:       nil;
       );
 
 initialization
index 7770f7d38753ccb58216b0ea3d5dc2d816703e17..badfd1ab4ed2e23f250fe1a80d480400202f00a0 100644 (file)
@@ -3443,6 +3443,7 @@ new features, etc.):
 #    4 = x86_64
 #    6 = 680x0 targets
 #    8 = 8086 (16-bit) targets
+#    a = AArch64
 #    A = ARM
 #    e = in extended debug mode only
 #    F = help for the 'fpc' binary (independent of the target compiler)
@@ -3713,6 +3714,7 @@ F*2P<x>_Set target CPU (arm,avr,i386,jvm,m68k,mips,mipsel,powerpc,powerpc64,spar
 3*2Twince_Windows CE
 4*2Tdarwin_Darwin/Mac OS X
 4*2Tfreebsd_FreeBSD
+4*2Tiphonesim_ iPhoneSimulator
 4*2Tlinux_Linux
 4*2Tnetbsd_NetBSD
 4*2Topenbsd_OpenBSD
@@ -3723,6 +3725,7 @@ F*2P<x>_Set target CPU (arm,avr,i386,jvm,m68k,mips,mipsel,powerpc,powerpc64,spar
 6*2Tlinux_Linux
 6*2Tpalmos_PalmOS
 8*2Tmsdos_MS-DOS (and compatible)
+a*2Tdarwin_Darwin/iOS
 A*2Tandroid_Android
 A*2Tdarwin_Darwin/iPhoneOS/iOS
 A*2Tembedded_Embedded
@@ -3777,6 +3780,7 @@ A*2WA_Specify native type application (Windows)
 3*2Wb_Create a bundle instead of a library (Darwin)
 P*2Wb_Create a bundle instead of a library (Darwin)
 p*2Wb_Create a bundle instead of a library (Darwin)
+a*2Wb_Create a bundle instead of a library (Darwin)
 A*2Wb_Create a bundle instead of a library (Darwin)
 4*2Wb_Create a bundle instead of a library (Darwin)
 3*2WB_Create a relocatable image (Windows, Symbian)
@@ -3794,6 +3798,7 @@ P*2WC_Specify console type application (Classic Mac OS)
 A*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)
 3*2We_Use external resources (Darwin)
 4*2We_Use external resources (Darwin)
+a*2We_Use external resources (Darwin)
 A*2We_Use external resources (Darwin)
 P*2We_Use external resources (Darwin)
 p*2We_Use external resources (Darwin)
@@ -3804,6 +3809,7 @@ A*2WG_Specify graphic type application (Windows)
 P*2WG_Specify graphic type application (Classic Mac OS)
 3*2Wi_Use internal resources (Darwin)
 4*2Wi_Use internal resources (Darwin)
+a*2Wi_Use internal resources (Darwin)
 A*2Wi_Use internal resources (Darwin)
 P*2Wi_Use internal resources (Darwin)
 p*2Wi_Use internal resources (Darwin)
@@ -3827,6 +3833,8 @@ A*2Wpxxxx_Specify the controller type; see fpc -i or fpc -iu for possible values
 m*2Wpxxxx_Specify the controller type; see fpc -i or fpc -iu for possible values
 V*2Wpxxxx_Specify the controller type; see fpc -i or fpc -iu for possible values
 3*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (iphonesim)
+4*2WP<x>_Minimum iOS deployment version: 8.0, 8.0.2, ... (iphonesim)
+a*2WP<x>_Minimum iOS deployment version: 7.0, 7.1.2, ... (Darwin)
 A*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (Darwin)
 3*2WR_Generate relocation code (Windows)
 4*2WR_Generate relocation code (Windows)
index f70f6dafecfcf5d78b0994c8faebca972c0fe04d..53f3862fb0e6883543e0f8fda40b1e53afa90c9d 100644 (file)
@@ -1001,7 +1001,7 @@ const
   option_info=11024;
   option_help_pages=11025;
 
-  MsgTxtSize = 74662;
+  MsgTxtSize = 74840;
 
   MsgIdxMax : array[1..20] of longint=(
     26,99,339,123,96,57,126,27,202,64,
index b4a7627e1fca0021bb64279a86b38dc10f4d36a3..7b701558fe98f8e3f4927de617168ac4da5a158a 100644 (file)
@@ -200,6 +200,10 @@ interface
           fparainit,
           fparacopyback: tnode;
           procedure handlemanagedbyrefpara(orgparadef: tdef);virtual;abstract;
+          { on some targets, value parameters that are passed by reference must
+            be copied to a temp location by the caller (and then a reference to
+            this temp location must be passed) }
+          procedure copy_value_by_ref_para;
        public
           callparaflags : tcallparaflags;
           parasym       : tparavarsym;
@@ -591,6 +595,208 @@ implementation
                              TCALLPARANODE
  ****************************************************************************}
 
+    procedure tcallparanode.copy_value_by_ref_para;
+      var
+        initstat,
+        copybackstat,
+        finistat: tstatementnode;
+        finiblock: tblocknode;
+        paratemp: ttempcreatenode;
+        arraysize,
+        arraybegin: tnode;
+        lefttemp: ttempcreatenode;
+        vardatatype,
+        temparraydef: tdef;
+      begin
+        { this routine is for targets where by-reference value parameters need
+          to be copied by the caller. It's basically the node-level equivalent
+          of thlcgobj.g_copyvalueparas }
+
+        { in case of an array constructor, we don't need a copy since the array
+          constructor itself is already constructed on the fly (and hence if
+          it's modified by the caller, that's no problem) }
+        if not is_array_constructor(left.resultdef) then
+          begin
+            fparainit:=internalstatements(initstat);
+            fparacopyback:=internalstatements(copybackstat);
+            finiblock:=internalstatements(finistat);
+            paratemp:=nil;
+
+            { making a copy of an open array, an array of const or a dynamic
+              array requires dynamic memory allocation since we don't know the
+              size at compile time }
+            if is_open_array(left.resultdef) or
+               is_array_of_const(left.resultdef) or
+               (is_dynamic_array(left.resultdef) and
+                is_open_array(parasym.vardef)) then
+              begin
+                 paratemp:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+                 if is_dynamic_array(left.resultdef) then
+                   begin
+                      { note that in insert_typeconv, this dynamic array was
+                        already converted into an open array (-> dereferenced)
+                        and then its resultdef was restored to the original
+                        dynamic array one -> get the address before treating it
+                        as a dynamic array here }
+                     { first restore the actual resultdef of left }
+                     temparraydef:=left.resultdef;
+                     left.resultdef:=parasym.vardef;
+                     { get its address }
+                     lefttemp:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+                     addstatement(initstat,lefttemp);
+                     addstatement(finistat,ctempdeletenode.create(lefttemp));
+                     addstatement(initstat,
+                       cassignmentnode.create(
+                         ctemprefnode.create(lefttemp),
+                         caddrnode.create_internal(left)
+                       )
+                     );
+                     { restore the resultdef }
+                     left.resultdef:=temparraydef;
+                     { now treat that address (correctly) as the original
+                       dynamic array to get its start and length }
+                     arraybegin:=cvecnode.create(
+                       ctypeconvnode.create_explicit(ctemprefnode.create(lefttemp),
+                         left.resultdef),
+                       genintconstnode(0)
+                     );
+                     arraysize:=caddnode.create(muln,
+                       geninlinenode(in_length_x,false,
+                         ctypeconvnode.create_explicit(ctemprefnode.create(lefttemp),
+                           left.resultdef)
+                       ),
+                       genintconstnode(tarraydef(left.resultdef).elementdef.size)
+                     );
+                   end
+                 else
+                   begin
+                     { no problem here that left is used multiple times, as
+                       sizeof() will simply evaluate to the high parameter }
+                     arraybegin:=left.getcopy;
+                     arraysize:=geninlinenode(in_sizeof_x,false,left);
+                   end;
+                 addstatement(initstat,paratemp);
+                 { paratemp:=getmem(sizeof(para)) }
+                 addstatement(initstat,
+                   cassignmentnode.create(
+                     ctemprefnode.create(paratemp),
+                     ccallnode.createintern('fpc_getmem',
+                       ccallparanode.create(
+                         arraysize.getcopy,nil
+                       )
+                     )
+                   )
+                 );
+                 { move(para,temp,sizeof(arr)) (no "left.getcopy" below because
+                   we replace left afterwards) }
+                 addstatement(initstat,
+                   ccallnode.createintern('MOVE',
+                     ccallparanode.create(
+                       arraysize,
+                       ccallparanode.create(
+                         cderefnode.create(ctemprefnode.create(paratemp)),
+                         ccallparanode.create(
+                           arraybegin,nil
+                         )
+                       )
+                     )
+                   )
+                 );
+                 { no reference count increases, that's still done on the callee
+                   side because for compatibility with targets that perform this
+                   copy on the callee side, that should only be done for non-
+                   assember functions (and we can't know that 100% certain here,
+                   e.g. in case of external declarations) (*) }
+
+                 { free the memory again after the call: freemem(paratemp) }
+                 addstatement(finistat,
+                   ccallnode.createintern('fpc_freemem',
+                     ccallparanode.create(
+                       ctemprefnode.create(paratemp),nil
+                     )
+                   )
+                 );
+                 { replace the original parameter with a dereference of the
+                   temp typecasted to the same type as the original parameter
+                   (don't free left, it has been reused above) }
+                 left:=ctypeconvnode.create_internal(
+                   cderefnode.create(ctemprefnode.create(paratemp)),
+                   left.resultdef);
+              end
+            else if is_shortstring(parasym.vardef) then
+              begin
+                { the shortstring parameter may have a different size than the
+                  parameter type -> assign and truncate/extend }
+                paratemp:=ctempcreatenode.create(parasym.vardef,parasym.vardef.size,tt_persistent,false);
+                addstatement(initstat,paratemp);
+                { assign shortstring }
+                addstatement(initstat,
+                  cassignmentnode.create(
+                    ctemprefnode.create(paratemp),left
+                  )
+                );
+                { replace parameter with temp (don't free left, it has been
+                  reused above) }
+                left:=ctemprefnode.create(paratemp);
+              end
+            else if parasym.vardef.typ=variantdef then
+              begin
+                vardatatype:=search_system_type('TVARDATA').typedef;
+                paratemp:=ctempcreatenode.create(vardatatype,vardatatype.size,tt_persistent,false);
+                addstatement(initstat,paratemp);
+                addstatement(initstat,
+                  ccallnode.createintern('fpc_variant_copy_overwrite',
+                    ccallparanode.create(
+                      ctypeconvnode.create_explicit(ctemprefnode.create(paratemp),
+                          vardatatype
+                        ),
+                      ccallparanode.create(ctypeconvnode.create_explicit(left,
+                        vardatatype),
+                        nil
+                      )
+                    )
+                  )
+                );
+                { replace parameter with temp (don't free left, it has been
+                  reused above) }
+                left:=ctypeconvnode.create_explicit(ctemprefnode.create(paratemp),parasym.vardef);
+              end
+            else if is_managed_type(left.resultdef) then
+              begin
+                { don't increase/decrease the reference count here, will be done by
+                  the callee (see (*) above) -> typecast to array of byte
+                  for the assignment to the temp }
+                temparraydef:=getarraydef(u8inttype,left.resultdef.size);
+                paratemp:=ctempcreatenode.create(temparraydef,temparraydef.size,tt_persistent,false);
+                addstatement(initstat,paratemp);
+                addstatement(initstat,
+                  cassignmentnode.create(
+                    ctemprefnode.create(paratemp),
+                    ctypeconvnode.create_internal(left,temparraydef)
+                  )
+                );
+                left:=ctypeconvnode.create_explicit(ctemprefnode.create(paratemp),left.resultdef);
+              end
+            else
+              begin
+                paratemp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,false);
+                addstatement(initstat,paratemp);
+                addstatement(initstat,
+                  cassignmentnode.create(ctemprefnode.create(paratemp),left)
+                );
+                { replace parameter with temp (don't free left, it has been
+                  reused above) }
+                left:=ctemprefnode.create(paratemp);
+              end;
+            addstatement(finistat,ctempdeletenode.create(paratemp));
+            addstatement(copybackstat,finiblock);
+            firstpass(fparainit);
+            firstpass(left);
+            firstpass(fparacopyback);
+          end;
+      end;
+
+
     constructor tcallparanode.create(expr,next : tnode);
 
       begin
@@ -720,6 +926,7 @@ implementation
           tcallparanode(right).firstcallparan;
         if not assigned(left.resultdef) then
           get_paratype;
+
         if assigned(parasym) and
            (target_info.system in systems_managed_vm) and
            (parasym.varspez in [vs_var,vs_out,vs_constref]) and
@@ -728,6 +935,27 @@ implementation
            (left.nodetype<>nothingn) then
           handlemanagedbyrefpara(left.resultdef);
 
+        { for targets that have to copy "value parameters by reference" on the
+          caller side
+
+          aktcallnode may not be assigned in case firstcallparan is called for
+          fake parameters to inline nodes (in that case, we don't have a real
+          call and hence no "caller side" either)
+          }
+        if assigned(aktcallnode) and
+           (target_info.system in systems_caller_copy_addr_value_para) and
+           ((assigned(parasym) and
+             (parasym.varspez=vs_value)) or
+            (cpf_varargs_para in callparaflags)) and
+           (left.nodetype<>nothingn) and
+           not(vo_has_local_copy in parasym.varoptions) and
+           ((not is_open_array(parasym.vardef) and
+             not is_array_of_const(parasym.vardef)) or
+            not(aktcallnode.procdefinition.proccalloption in cdecl_pocalls)) and
+           paramanager.push_addr_param(vs_value,parasym.vardef,
+                      aktcallnode.procdefinition.proccalloption) then
+          copy_value_by_ref_para;
+
         { does it need to load RTTI? }
         if assigned(parasym) and (parasym.varspez=vs_out) and
            (cs_create_pic in current_settings.moduleswitches) and
@@ -2090,6 +2318,8 @@ implementation
 
         { A) set the appropriate objc_msgSend* variant to call }
 
+        { The AArch64 abi does not require special handling for struct returns }
+{$ifndef aarch64}
         { record returned via implicit pointer }
         if paramanager.ret_in_param(resultdef,procdefinition) then
           begin
@@ -2108,11 +2338,13 @@ implementation
         else if (resultdef.typ=floatdef) and
                 not(cnf_inherited in callnodeflags) then
           msgsendname:='OBJC_MSGSEND_FPRET'
-{$endif}
+{$endif i386}
         { default }
-        else if not(cnf_inherited in callnodeflags) then
+        else
+{$endif aarch64}
+             if not(cnf_inherited in callnodeflags) then
           msgsendname:='OBJC_MSGSEND'
-{$if defined(onlymacosx10_6) or defined(arm) }
+{$if defined(onlymacosx10_6) or defined(arm) or defined(aarch64)}
         else if (target_info.system in systems_objc_nfabi) then
           msgsendname:='OBJC_MSGSENDSUPER2'
 {$endif onlymacosx10_6 or arm}
@@ -2573,10 +2805,10 @@ implementation
                      if not assigned(right) then
                        begin
                          if assigned(procdefinition.owner.defowner) then
-                           para.left:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner))
+                           para.left:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner),lpf_forpara)
                          { exceptfilters called from main level are not owned }
                          else if procdefinition.proctypeoption=potype_exceptfilter then
-                           para.left:=cloadparentfpnode.create(current_procinfo.procdef)
+                           para.left:=cloadparentfpnode.create(current_procinfo.procdef,lpf_forpara)
                          else
                            internalerror(200309287);
                        end
@@ -2870,8 +3102,6 @@ implementation
         statements : tstatementnode;
         converted_result_data : ttempcreatenode;
         calltype: tdispcalltype;
-      label
-        errorexit;
       begin
          result:=nil;
          candidates:=nil;
@@ -2879,460 +3109,462 @@ implementation
          oldcallnode:=aktcallnode;
          aktcallnode:=self;
 
-         { determine length of parameter list }
-         pt:=tcallparanode(left);
-         paralength:=0;
-         while assigned(pt) do
-          begin
-            inc(paralength);
-            pt:=tcallparanode(pt.right);
-          end;
+         try
+           { determine length of parameter list }
+           pt:=tcallparanode(left);
+           paralength:=0;
+           while assigned(pt) do
+            begin
+              inc(paralength);
+              pt:=tcallparanode(pt.right);
+            end;
 
-         { determine the type of the parameters }
-         if assigned(left) then
-          begin
-            tcallparanode(left).get_paratype;
-            if codegenerror then
-              goto errorexit;
-          end;
+           { determine the type of the parameters }
+           if assigned(left) then
+            begin
+              tcallparanode(left).get_paratype;
+              if codegenerror then
+                exit;
+            end;
 
-         if assigned(methodpointer) then
-           typecheckpass(methodpointer);
+           if assigned(methodpointer) then
+             typecheckpass(methodpointer);
 
-         { procedure variable ? }
-         if assigned(right) then
-           begin
-              set_varstate(right,vs_read,[vsf_must_be_valid]);
-              typecheckpass(right);
-              if codegenerror then
-               exit;
+           { procedure variable ? }
+           if assigned(right) then
+             begin
+                set_varstate(right,vs_read,[vsf_must_be_valid]);
+                typecheckpass(right);
+                if codegenerror then
+                  exit;
 
-              procdefinition:=tabstractprocdef(right.resultdef);
+                procdefinition:=tabstractprocdef(right.resultdef);
 
-              { Compare parameters from right to left }
-              paraidx:=procdefinition.Paras.count-1;
-              { Skip default parameters }
-              if not(po_varargs in procdefinition.procoptions) then
-                begin
-                  { ignore hidden parameters }
-                  while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
-                    dec(paraidx);
-                  for i:=1 to procdefinition.maxparacount-paralength do
-                    begin
-                      if paraidx<0 then
-                        internalerror(200402265);
-                      if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
-                        begin
-                          CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
-                          goto errorexit;
-                        end;
+                { Compare parameters from right to left }
+                paraidx:=procdefinition.Paras.count-1;
+                { Skip default parameters }
+                if not(po_varargs in procdefinition.procoptions) then
+                  begin
+                    { ignore hidden parameters }
+                    while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
                       dec(paraidx);
-                    end;
-                end;
-              while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
-                dec(paraidx);
-              pt:=tcallparanode(left);
-              lastpara:=paralength;
-              while (paraidx>=0) and assigned(pt) do
-                begin
-                  { only goto next para if we're out of the varargs }
-                  if not(po_varargs in procdefinition.procoptions) or
-                     (lastpara<=procdefinition.maxparacount) then
-                   begin
-                     repeat
-                       dec(paraidx);
-                     until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
-                   end;
-                  pt:=tcallparanode(pt.right);
-                  dec(lastpara);
-                end;
-              if assigned(pt) or
-                 ((paraidx>=0) and
-                  not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
-                begin
-                   if assigned(pt) then
-                     current_filepos:=pt.fileinfo;
-                   CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
-                   goto errorexit;
-                end;
-           end
-         else
-         { not a procedure variable }
-           begin
-              { do we know the procedure to call ? }
-              if not(assigned(procdefinition)) then
-                begin
-                  { ignore possible private for properties or in delphi mode for anon. inherited (FK) }
-                  ignorevisibility:=(nf_isproperty in flags) or
-                                    ((m_delphi in current_settings.modeswitches) and (cnf_anon_inherited in callnodeflags));
-                  candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,ignorevisibility,
-                    not(nf_isproperty in flags),cnf_objc_id_call in callnodeflags,cnf_unit_specified in callnodeflags,
-                    callnodeflags*[cnf_anon_inherited,cnf_inherited]=[],cnf_anon_inherited in callnodeflags);
-
-                   { no procedures found? then there is something wrong
-                     with the parameter size or the procedures are
-                     not accessible }
-                   if candidates.count=0 then
-                    begin
-                      { when it's an auto inherited call and there
-                        is no procedure found, but the procedures
-                        were defined with overload directive and at
-                        least two procedures are defined then we ignore
-                        this inherited by inserting a nothingn. Only
-                        do this ugly hack in Delphi mode as it looks more
-                        like a bug. It's also not documented }
-                      if (m_delphi in current_settings.modeswitches) and
-                         (cnf_anon_inherited in callnodeflags) and
-                         (symtableprocentry.owner.symtabletype=ObjectSymtable) and
-                         (po_overload in tprocdef(symtableprocentry.ProcdefList[0]).procoptions) and
-                         (symtableprocentry.ProcdefList.Count>=2) then
-                        result:=cnothingnode.create
-                      else
-                        begin
-                          { in tp mode we can try to convert to procvar if
-                            there are no parameters specified }
-                          if not(assigned(left)) and
-                             not(cnf_inherited in callnodeflags) and
-                             ((m_tp_procvar in current_settings.modeswitches) or
-                              (m_mac_procvar in current_settings.modeswitches)) and
-                             (not assigned(methodpointer) or
-                              (methodpointer.nodetype <> typen)) then
-                            begin
-                              hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
-                              if assigned(methodpointer) then
-                                tloadnode(hpt).set_mp(methodpointer.getcopy);
-                              typecheckpass(hpt);
-                              result:=hpt;
-                            end
-                          else
-                            begin
-                              CGMessagePos1(fileinfo,parser_e_wrong_parameter_size,symtableprocentry.realname);
-                              symtableprocentry.write_parameter_lists(nil);
-                            end;
-                        end;
-                      candidates.free;
-                      goto errorexit;
-                    end;
+                    for i:=1 to procdefinition.maxparacount-paralength do
+                      begin
+                        if paraidx<0 then
+                          internalerror(200402265);
+                        if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+                          begin
+                            CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
+                            exit;
+                          end;
+                        dec(paraidx);
+                      end;
+                  end;
+                while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+                  dec(paraidx);
+                pt:=tcallparanode(left);
+                lastpara:=paralength;
+                while (paraidx>=0) and assigned(pt) do
+                  begin
+                    { only goto next para if we're out of the varargs }
+                    if not(po_varargs in procdefinition.procoptions) or
+                       (lastpara<=procdefinition.maxparacount) then
+                     begin
+                       repeat
+                         dec(paraidx);
+                       until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+                     end;
+                    pt:=tcallparanode(pt.right);
+                    dec(lastpara);
+                  end;
+                if assigned(pt) or
+                   ((paraidx>=0) and
+                    not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
+                  begin
+                     if assigned(pt) then
+                       current_filepos:=pt.fileinfo;
+                     CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
+                     exit;
+                  end;
+             end
+           else
+           { not a procedure variable }
+             begin
+                { do we know the procedure to call ? }
+                if not(assigned(procdefinition)) then
+                  begin
+                    { ignore possible private for properties or in delphi mode for anon. inherited (FK) }
+                    ignorevisibility:=(nf_isproperty in flags) or
+                                      ((m_delphi in current_settings.modeswitches) and (cnf_anon_inherited in callnodeflags));
+                    candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,ignorevisibility,
+                      not(nf_isproperty in flags),cnf_objc_id_call in callnodeflags,cnf_unit_specified in callnodeflags,
+                      callnodeflags*[cnf_anon_inherited,cnf_inherited]=[],cnf_anon_inherited in callnodeflags);
+
+                     { no procedures found? then there is something wrong
+                       with the parameter size or the procedures are
+                       not accessible }
+                     if candidates.count=0 then
+                      begin
+                        { when it's an auto inherited call and there
+                          is no procedure found, but the procedures
+                          were defined with overload directive and at
+                          least two procedures are defined then we ignore
+                          this inherited by inserting a nothingn. Only
+                          do this ugly hack in Delphi mode as it looks more
+                          like a bug. It's also not documented }
+                        if (m_delphi in current_settings.modeswitches) and
+                           (cnf_anon_inherited in callnodeflags) and
+                           (symtableprocentry.owner.symtabletype=ObjectSymtable) and
+                           (po_overload in tprocdef(symtableprocentry.ProcdefList[0]).procoptions) and
+                           (symtableprocentry.ProcdefList.Count>=2) then
+                          result:=cnothingnode.create
+                        else
+                          begin
+                            { in tp mode we can try to convert to procvar if
+                              there are no parameters specified }
+                            if not(assigned(left)) and
+                               not(cnf_inherited in callnodeflags) and
+                               ((m_tp_procvar in current_settings.modeswitches) or
+                                (m_mac_procvar in current_settings.modeswitches)) and
+                               (not assigned(methodpointer) or
+                                (methodpointer.nodetype <> typen)) then
+                              begin
+                                hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
+                                if assigned(methodpointer) then
+                                  tloadnode(hpt).set_mp(methodpointer.getcopy);
+                                typecheckpass(hpt);
+                                result:=hpt;
+                              end
+                            else
+                              begin
+                                CGMessagePos1(fileinfo,parser_e_wrong_parameter_size,symtableprocentry.realname);
+                                symtableprocentry.write_parameter_lists(nil);
+                              end;
+                          end;
+                        candidates.free;
+                        exit;
+                      end;
 
-                   { Retrieve information about the candidates }
-                   candidates.get_information;
+                     { Retrieve information about the candidates }
+                     candidates.get_information;
 {$ifdef EXTDEBUG}
-                   { Display info when multiple candidates are found }
-                   if candidates.count>1 then
-                     candidates.dump_info(V_Debug);
+                     { Display info when multiple candidates are found }
+                     if candidates.count>1 then
+                       candidates.dump_info(V_Debug);
 {$endif EXTDEBUG}
 
-                   { Choose the best candidate and count the number of
-                     candidates left }
-                   cand_cnt:=candidates.choose_best(procdefinition,
-                     assigned(left) and
-                     not assigned(tcallparanode(left).right) and
-                     (tcallparanode(left).left.resultdef.typ=variantdef));
+                     { Choose the best candidate and count the number of
+                       candidates left }
+                     cand_cnt:=candidates.choose_best(procdefinition,
+                       assigned(left) and
+                       not assigned(tcallparanode(left).right) and
+                       (tcallparanode(left).left.resultdef.typ=variantdef));
 
-                   { All parameters are checked, check if there are any
-                     procedures left }
-                   if cand_cnt>0 then
-                    begin
-                      { Multiple candidates left? }
-                      if cand_cnt>1 then
-                       begin
-                         CGMessage(type_e_cant_choose_overload_function);
+                     { All parameters are checked, check if there are any
+                       procedures left }
+                     if cand_cnt>0 then
+                      begin
+                        { Multiple candidates left? }
+                        if cand_cnt>1 then
+                         begin
+                           CGMessage(type_e_cant_choose_overload_function);
 {$ifdef EXTDEBUG}
-                         candidates.dump_info(V_Hint);
+                           candidates.dump_info(V_Hint);
 {$else EXTDEBUG}
-                         candidates.list(false);
+                           candidates.list(false);
 {$endif EXTDEBUG}
-                         { we'll just use the first candidate to make the
-                           call }
-                       end;
+                           { we'll just use the first candidate to make the
+                             call }
+                         end;
 
-                      { assign procdefinition }
-                      if symtableproc=nil then
-                        symtableproc:=procdefinition.owner;
-                    end
-                   else
-                    begin
-                      { No candidates left, this must be a type error,
-                        because wrong size is already checked. procdefinition
-                        is filled with the first (random) definition that is
-                        found. We use this definition to display a nice error
-                        message that the wrong type is passed }
-                      candidates.find_wrong_para;
-                      candidates.list(true);
+                        { assign procdefinition }
+                        if symtableproc=nil then
+                          symtableproc:=procdefinition.owner;
+                      end
+                     else
+                      begin
+                        { No candidates left, this must be a type error,
+                          because wrong size is already checked. procdefinition
+                          is filled with the first (random) definition that is
+                          found. We use this definition to display a nice error
+                          message that the wrong type is passed }
+                        candidates.find_wrong_para;
+                        candidates.list(true);
 {$ifdef EXTDEBUG}
-                      candidates.dump_info(V_Hint);
+                        candidates.dump_info(V_Hint);
 {$endif EXTDEBUG}
 
-                      { We can not proceed, release all procs and exit }
-                      candidates.free;
-                      goto errorexit;
-                    end;
+                        { We can not proceed, release all procs and exit }
+                        candidates.free;
+                        exit;
+                      end;
 
-                   candidates.free;
-               end; { end of procedure to call determination }
-           end;
+                     candidates.free;
+                 end; { end of procedure to call determination }
+             end;
 
-          { check for hints (deprecated etc) }
-          if procdefinition.typ = procdef then
-            check_hints(tprocdef(procdefinition).procsym,tprocdef(procdefinition).symoptions,tprocdef(procdefinition).deprecatedmsg);
+            { check for hints (deprecated etc) }
+            if procdefinition.typ = procdef then
+              check_hints(tprocdef(procdefinition).procsym,tprocdef(procdefinition).symoptions,tprocdef(procdefinition).deprecatedmsg);
 
-          { add reference to corresponding procsym; may not be the one
-            originally found/passed to the constructor because of overloads }
-          if procdefinition.typ = procdef then
-            addsymref(tprocdef(procdefinition).procsym);
+            { add reference to corresponding procsym; may not be the one
+              originally found/passed to the constructor because of overloads }
+            if procdefinition.typ = procdef then
+              addsymref(tprocdef(procdefinition).procsym);
 
-          { add needed default parameters }
-          if (paralength<procdefinition.maxparacount) then
-           begin
-             paraidx:=0;
-             i:=0;
-             while (i<paralength) do
-              begin
-                if paraidx>=procdefinition.Paras.count then
-                  internalerror(200306181);
-                if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
-                  inc(i);
-                inc(paraidx);
-              end;
-             while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
-               inc(paraidx);
-             while (paraidx<procdefinition.paras.count) do
-              begin
-                if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
-                 internalerror(200212142);
-                left:=ccallparanode.create(genconstsymtree(
-                    tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
-                { Ignore vs_hidden parameters }
-                repeat
+            { add needed default parameters }
+            if (paralength<procdefinition.maxparacount) then
+             begin
+               paraidx:=0;
+               i:=0;
+               while (i<paralength) do
+                begin
+                  if paraidx>=procdefinition.Paras.count then
+                    internalerror(200306181);
+                  if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
+                    inc(i);
                   inc(paraidx);
-                until (paraidx>=procdefinition.paras.count) or
-                  not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
-              end;
-           end;
+                end;
+               while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+                 inc(paraidx);
+               while (paraidx<procdefinition.paras.count) do
+                begin
+                  if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+                   internalerror(200212142);
+                  left:=ccallparanode.create(genconstsymtree(
+                      tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
+                  { Ignore vs_hidden parameters }
+                  repeat
+                    inc(paraidx);
+                  until (paraidx>=procdefinition.paras.count) or
+                    not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+                end;
+             end;
 
-          { recursive call? }
-          if assigned(current_procinfo) and
-             (procdefinition=current_procinfo.procdef) then
-            include(current_procinfo.flags,pi_is_recursive);
-
-          { handle predefined procedures }
-          is_const:=(po_internconst in procdefinition.procoptions) and
-                    ((block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) or
-                     (assigned(left) and ((tcallparanode(left).left.nodetype in [realconstn,ordconstn])
-                      and (not assigned(tcallparanode(left).right) or (tcallparanode(left).right.nodetype in [realconstn,ordconstn])))));
-          if (procdefinition.proccalloption=pocall_internproc) or is_const then
-           begin
-             if assigned(left) then
-              begin
-                { convert types to those of the prototype, this is required by functions like ror, rol, sar
-                  some use however a dummy type (Typedfile) so this would break them }
-                if not(tprocdef(procdefinition).extnumber in [fpc_in_Reset_TypedFile,fpc_in_Rewrite_TypedFile]) then
-                  begin
-                    { bind parasyms to the callparanodes and insert hidden parameters }
-                    bind_parasym;
+            { recursive call? }
+            if assigned(current_procinfo) and
+               (procdefinition=current_procinfo.procdef) then
+              include(current_procinfo.flags,pi_is_recursive);
+
+            { handle predefined procedures }
+            is_const:=(po_internconst in procdefinition.procoptions) and
+                      ((block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) or
+                       (assigned(left) and ((tcallparanode(left).left.nodetype in [realconstn,ordconstn])
+                        and (not assigned(tcallparanode(left).right) or (tcallparanode(left).right.nodetype in [realconstn,ordconstn])))));
+            if (procdefinition.proccalloption=pocall_internproc) or is_const then
+             begin
+               if assigned(left) then
+                begin
+                  { convert types to those of the prototype, this is required by functions like ror, rol, sar
+                    some use however a dummy type (Typedfile) so this would break them }
+                  if not(tprocdef(procdefinition).extnumber in [fpc_in_Reset_TypedFile,fpc_in_Rewrite_TypedFile]) then
+                    begin
+                      { bind parasyms to the callparanodes and insert hidden parameters }
+                      bind_parasym;
 
-                    { insert type conversions for parameters }
-                    if assigned(left) then
-                      tcallparanode(left).insert_typeconv;
-                  end;
+                      { insert type conversions for parameters }
+                      if assigned(left) then
+                        tcallparanode(left).insert_typeconv;
+                    end;
 
-                { ptr and settextbuf need two args }
-                if assigned(tcallparanode(left).right) then
-                 begin
-                   hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
-                   left:=nil;
-                 end
-                else
-                 begin
-                   hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
-                   tcallparanode(left).left:=nil;
-                 end;
-              end
-             else
-              hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
-             result:=hpt;
-             goto errorexit;
-           end;
+                  { ptr and settextbuf need two args }
+                  if assigned(tcallparanode(left).right) then
+                   begin
+                     hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
+                     left:=nil;
+                   end
+                  else
+                   begin
+                     hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
+                     tcallparanode(left).left:=nil;
+                   end;
+                end
+               else
+                hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
+               result:=hpt;
+               exit;
+             end;
 
-         { ensure that the result type is set }
-         if not(cnf_typedefset in callnodeflags) then
-          begin
-            { constructors return their current class type, not the type where the
-              constructor is declared, this can be different because of inheritance }
-            if (procdefinition.proctypeoption=potype_constructor) and
-               assigned(methodpointer) and
-               assigned(methodpointer.resultdef) and
-               (methodpointer.resultdef.typ=classrefdef) then
-              resultdef:=tclassrefdef(methodpointer.resultdef).pointeddef
-            else
-            { Member call to a (inherited) constructor from the class, the return
-              value is always self, so we change it to voidtype to generate an
-              error and to prevent users from generating non-working code
-              when they expect to clone the current instance, see bug 3662 (PFV) }
+           { ensure that the result type is set }
+           if not(cnf_typedefset in callnodeflags) then
+            begin
+              { constructors return their current class type, not the type where the
+                constructor is declared, this can be different because of inheritance }
               if (procdefinition.proctypeoption=potype_constructor) and
-                 is_class(tprocdef(procdefinition).struct) and
                  assigned(methodpointer) and
-                 (methodpointer.nodetype=loadn) and
-                 (loadnf_is_self in tloadnode(methodpointer).loadnodeflags) then
-                resultdef:=voidtype
+                 assigned(methodpointer.resultdef) and
+                 (methodpointer.resultdef.typ=classrefdef) then
+                resultdef:=tclassrefdef(methodpointer.resultdef).pointeddef
               else
-                resultdef:=procdefinition.returndef;
-           end
-         else
-           resultdef:=typedef;
-
-         { Check object/class for methods }
-         if assigned(methodpointer) then
-          begin
-            { direct call to inherited abstract method, then we
-              can already give a error in the compiler instead
-              of a runtime error }
-            if (cnf_inherited in callnodeflags) and
-               (po_abstractmethod in procdefinition.procoptions) then
-              begin
-                if (m_delphi in current_settings.modeswitches) and
-                  (cnf_anon_inherited in callnodeflags) then
-                  begin
-                    CGMessage(cg_h_inherited_ignored);
-                    result:=cnothingnode.create;
-                    exit;
-                  end
+              { Member call to a (inherited) constructor from the class, the return
+                value is always self, so we change it to voidtype to generate an
+                error and to prevent users from generating non-working code
+                when they expect to clone the current instance, see bug 3662 (PFV) }
+                if (procdefinition.proctypeoption=potype_constructor) and
+                   is_class(tprocdef(procdefinition).struct) and
+                   assigned(methodpointer) and
+                   (methodpointer.nodetype=loadn) and
+                   (loadnf_is_self in tloadnode(methodpointer).loadnodeflags) then
+                  resultdef:=voidtype
                 else
-                  CGMessage(cg_e_cant_call_abstract_method);
-              end;
+                  resultdef:=procdefinition.returndef;
+             end
+           else
+             resultdef:=typedef;
 
-            { directly calling an interface/protocol/category/class helper
-              method via its type is not possible (always must be called via
-              the actual instance) }
-            if (methodpointer.nodetype=typen) and
-               (is_interface(methodpointer.resultdef) or
-                is_objc_protocol_or_category(methodpointer.resultdef)) then
-              CGMessage1(type_e_class_type_expected,methodpointer.resultdef.typename);
-
-            { if an inherited con- or destructor should be  }
-            { called in a con- or destructor then a warning }
-            { will be made                                  }
-            { con- and destructors need a pointer to the vmt }
-            if (cnf_inherited in callnodeflags) and
-               (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
-               is_object(methodpointer.resultdef) and
-               not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
-             CGMessage(cg_w_member_cd_call_from_method);
-
-            if methodpointer.nodetype<>typen then
-             begin
-                { Remove all postfix operators }
-                hpt:=methodpointer;
-                while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
-                  hpt:=tunarynode(hpt).left;
-
-                if ((hpt.nodetype=loadvmtaddrn) or
-                   ((hpt.nodetype=loadn) and assigned(tloadnode(hpt).resultdef) and (tloadnode(hpt).resultdef.typ=classrefdef))) and
-                   not (procdefinition.proctypeoption=potype_constructor) and
-                   not (po_classmethod in procdefinition.procoptions) and
-                   not (po_staticmethod in procdefinition.procoptions) then
-                  { error: we are calling instance method from the class method/static method }
-                  CGMessage(parser_e_only_class_members);
-
-               if (procdefinition.proctypeoption=potype_constructor) and
-                  assigned(symtableproc) and
-                  (symtableproc.symtabletype=withsymtable) and
-                  (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
-                 CGmessage(cg_e_cannot_call_cons_dest_inside_with);
-
-               { skip (absolute and other simple) type conversions -- only now,
-                 because the checks above have to take type conversions into
-                 e.g. class reference types account }
-               hpt:=actualtargetnode(@hpt)^;
-
-               { R.Init then R will be initialized by the constructor,
-                 Also allow it for simple loads }
-               if (procdefinition.proctypeoption=potype_constructor) or
-                  ((hpt.nodetype=loadn) and
-                   (((methodpointer.resultdef.typ=objectdef) and
-                     not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)) or
-                    (methodpointer.resultdef.typ=recorddef)
-                   )
-                  ) then
-                 { a constructor will and a method may write something to }
-                 { the fields                                             }
-                 set_varstate(methodpointer,vs_readwritten,[])
-               else
-                 set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
-             end;
+           { Check object/class for methods }
+           if assigned(methodpointer) then
+            begin
+              { direct call to inherited abstract method, then we
+                can already give a error in the compiler instead
+                of a runtime error }
+              if (cnf_inherited in callnodeflags) and
+                 (po_abstractmethod in procdefinition.procoptions) then
+                begin
+                  if (m_delphi in current_settings.modeswitches) and
+                    (cnf_anon_inherited in callnodeflags) then
+                    begin
+                      CGMessage(cg_h_inherited_ignored);
+                      result:=cnothingnode.create;
+                      exit;
+                    end
+                  else
+                    CGMessage(cg_e_cant_call_abstract_method);
+                end;
 
-            { if we are calling the constructor check for abstract
-              methods. Ignore inherited and member calls, because the
-              class is then already created }
-            if (procdefinition.proctypeoption=potype_constructor) and
-               not(cnf_inherited in callnodeflags) and
-               not(cnf_member_call in callnodeflags) then
-              verifyabstractcalls;
-          end
-         else
-          begin
-            { When this is method the methodpointer must be available }
-            if (right=nil) and
-               (procdefinition.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
-               not procdefinition.no_self_node then
-              internalerror(200305061);
-          end;
+              { directly calling an interface/protocol/category/class helper
+                method via its type is not possible (always must be called via
+                the actual instance) }
+              if (methodpointer.nodetype=typen) and
+                 (is_interface(methodpointer.resultdef) or
+                  is_objc_protocol_or_category(methodpointer.resultdef)) then
+                CGMessage1(type_e_class_type_expected,methodpointer.resultdef.typename);
+
+              { if an inherited con- or destructor should be  }
+              { called in a con- or destructor then a warning }
+              { will be made                                  }
+              { con- and destructors need a pointer to the vmt }
+              if (cnf_inherited in callnodeflags) and
+                 (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
+                 is_object(methodpointer.resultdef) and
+                 not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
+               CGMessage(cg_w_member_cd_call_from_method);
+
+              if methodpointer.nodetype<>typen then
+               begin
+                  { Remove all postfix operators }
+                  hpt:=methodpointer;
+                  while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
+                    hpt:=tunarynode(hpt).left;
+
+                  if ((hpt.nodetype=loadvmtaddrn) or
+                     ((hpt.nodetype=loadn) and assigned(tloadnode(hpt).resultdef) and (tloadnode(hpt).resultdef.typ=classrefdef))) and
+                     not (procdefinition.proctypeoption=potype_constructor) and
+                     not (po_classmethod in procdefinition.procoptions) and
+                     not (po_staticmethod in procdefinition.procoptions) then
+                    { error: we are calling instance method from the class method/static method }
+                    CGMessage(parser_e_only_class_members);
+
+                 if (procdefinition.proctypeoption=potype_constructor) and
+                    assigned(symtableproc) and
+                    (symtableproc.symtabletype=withsymtable) and
+                    (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
+                   CGmessage(cg_e_cannot_call_cons_dest_inside_with);
+
+                 { skip (absolute and other simple) type conversions -- only now,
+                   because the checks above have to take type conversions into
+                   e.g. class reference types account }
+                 hpt:=actualtargetnode(@hpt)^;
+
+                 { R.Init then R will be initialized by the constructor,
+                   Also allow it for simple loads }
+                 if (procdefinition.proctypeoption=potype_constructor) or
+                    ((hpt.nodetype=loadn) and
+                     (((methodpointer.resultdef.typ=objectdef) and
+                       not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)) or
+                      (methodpointer.resultdef.typ=recorddef)
+                     )
+                    ) then
+                   { a constructor will and a method may write something to }
+                   { the fields                                             }
+                   set_varstate(methodpointer,vs_readwritten,[])
+                 else
+                   set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
+               end;
 
-         { Set flag that the procedure uses varargs, also if they are not passed it is still
-           needed for x86_64 to pass the number of SSE registers used }
-         if po_varargs in procdefinition.procoptions then
-           include(callnodeflags,cnf_uses_varargs);
+              { if we are calling the constructor check for abstract
+                methods. Ignore inherited and member calls, because the
+                class is then already created }
+              if (procdefinition.proctypeoption=potype_constructor) and
+                 not(cnf_inherited in callnodeflags) and
+                 not(cnf_member_call in callnodeflags) then
+                verifyabstractcalls;
+            end
+           else
+            begin
+              { When this is method the methodpointer must be available }
+              if (right=nil) and
+                 (procdefinition.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
+                 not procdefinition.no_self_node then
+                internalerror(200305061);
+            end;
 
-         { set the appropriate node flag if the call never returns }
-         if po_noreturn in procdefinition.procoptions then
-           include(callnodeflags,cnf_call_never_returns);
+           { Set flag that the procedure uses varargs, also if they are not passed it is still
+             needed for x86_64 to pass the number of SSE registers used }
+           if po_varargs in procdefinition.procoptions then
+             include(callnodeflags,cnf_uses_varargs);
 
-         { Change loading of array of const to varargs }
-         if assigned(left) and
-            is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vardef) and
-            (procdefinition.proccalloption in cdecl_pocalls) then
-           convert_carg_array_of_const;
+           { set the appropriate node flag if the call never returns }
+           if po_noreturn in procdefinition.procoptions then
+             include(callnodeflags,cnf_call_never_returns);
 
-         { bind parasyms to the callparanodes and insert hidden parameters }
-         bind_parasym;
+           { Change loading of array of const to varargs }
+           if assigned(left) and
+              is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vardef) and
+              (procdefinition.proccalloption in cdecl_pocalls) then
+             convert_carg_array_of_const;
 
-         { insert type conversions for parameters }
-         if assigned(left) then
-           tcallparanode(left).insert_typeconv;
+           { bind parasyms to the callparanodes and insert hidden parameters }
+           bind_parasym;
 
-         { dispinterface methode invoke? }
-         if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) then
-           begin
-             case procdefinition.proctypeoption of
-               potype_propgetter: calltype:=dct_propget;
-               potype_propsetter: calltype:=dct_propput;
-             else
-               calltype:=dct_method;
-             end;
-             { if the result is used, we've to insert a call to convert the type to be on the "safe side" }
-             if (cnf_return_value_used in callnodeflags) and not is_void(procdefinition.returndef) then
-               begin
-                 result:=internalstatements(statements);
-                 converted_result_data:=ctempcreatenode.create(procdefinition.returndef,sizeof(procdefinition.returndef),
-                   tt_persistent,true);
-                 addstatement(statements,converted_result_data);
-                 addstatement(statements,cassignmentnode.create(ctemprefnode.create(converted_result_data),
-                   ctypeconvnode.create_internal(
-                     translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,procdefinition.returndef),
-                   procdefinition.returndef)));
-                 addstatement(statements,ctempdeletenode.create_normal_temp(converted_result_data));
-                 addstatement(statements,ctemprefnode.create(converted_result_data));
-               end
-             else
-               result:=translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,voidtype);
+           { insert type conversions for parameters }
+           if assigned(left) then
+             tcallparanode(left).insert_typeconv;
 
-             { don't free reused nodes }
-             methodpointer:=nil;
-             parameters:=nil;
-           end;
+           { dispinterface methode invoke? }
+           if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) then
+             begin
+               case procdefinition.proctypeoption of
+                 potype_propgetter: calltype:=dct_propget;
+                 potype_propsetter: calltype:=dct_propput;
+               else
+                 calltype:=dct_method;
+               end;
+               { if the result is used, we've to insert a call to convert the type to be on the "safe side" }
+               if (cnf_return_value_used in callnodeflags) and not is_void(procdefinition.returndef) then
+                 begin
+                   result:=internalstatements(statements);
+                   converted_result_data:=ctempcreatenode.create(procdefinition.returndef,sizeof(procdefinition.returndef),
+                     tt_persistent,true);
+                   addstatement(statements,converted_result_data);
+                   addstatement(statements,cassignmentnode.create(ctemprefnode.create(converted_result_data),
+                     ctypeconvnode.create_internal(
+                       translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,procdefinition.returndef),
+                     procdefinition.returndef)));
+                   addstatement(statements,ctempdeletenode.create_normal_temp(converted_result_data));
+                   addstatement(statements,ctemprefnode.create(converted_result_data));
+                 end
+               else
+                 result:=translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,voidtype);
 
-      errorexit:
-         aktcallnode:=oldcallnode;
+               { don't free reused nodes }
+               methodpointer:=nil;
+               parameters:=nil;
+             end;
+
+         finally
+           aktcallnode:=oldcallnode;
+         end;
       end;
 
 
@@ -3590,123 +3822,131 @@ implementation
 
       var
         para: tcallparanode;
+        oldcallnode: tcallnode;
       begin
          result:=nil;
 
-         { as pass_1 is never called on the methodpointer node, we must check
-           here that it's not a helper type }
-         if assigned(methodpointer) and
-             (methodpointer.nodetype=typen) and
-             is_objectpascal_helper(ttypenode(methodpointer).typedef) and
-             not ttypenode(methodpointer).helperallowed then
-           Message(parser_e_no_category_as_types);
-
-         { can we get rid of the call? }
-         if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
-            not(cnf_return_value_used in callnodeflags) and
-           (procdefinition.typ=procdef) and
-           tprocdef(procdefinition).isempty and
-           { allow only certain proc options }
-           ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
-             po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
-             po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
-             po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
-             po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
-           begin
-             { check parameters for side effects }
-             para:=tcallparanode(left);
-             while assigned(para) do
-               begin
-                 if (para.parasym.typ = paravarsym) and
-                    ((para.parasym.refs>0) or
-                    { array of consts are converted later on so we need to skip them here
-                      else no error detection is done }
-                     is_array_of_const(para.parasym.vardef) or
-                     not(cs_opt_dead_values in current_settings.optimizerswitches) or
-                     might_have_sideeffects(para.left)) then
-                     break;
-                  para:=tcallparanode(para.right);
-               end;
-             { finally, remove it if no parameter with side effect has been found }
-             if para=nil then
-               begin
-                 result:=cnothingnode.create;
-                 exit;
-               end;
-           end;
-
-         { convert Objective-C calls into a message call }
-         if (procdefinition.typ=procdef) and
-            (po_objc in tprocdef(procdefinition).procoptions) then
-           begin
-             if not(cnf_objc_processed in callnodeflags) then
-               objc_convert_to_message_send;
-           end
-         else
-           begin
-             { The following don't apply to obj-c: obj-c methods can never be
-               inlined because they're always virtual and the destination can
-               change at run, and for the same reason we also can't perform
-               WPO on them (+ they have no constructors) }
+         oldcallnode:=aktcallnode;
+         aktcallnode:=self;
 
-             { Check if the call can be inlined, sets the cnf_do_inline flag }
-             check_inlining;
+         try
+           { as pass_1 is never called on the methodpointer node, we must check
+             here that it's not a helper type }
+           if assigned(methodpointer) and
+               (methodpointer.nodetype=typen) and
+               is_objectpascal_helper(ttypenode(methodpointer).typedef) and
+               not ttypenode(methodpointer).helperallowed then
+             Message(parser_e_no_category_as_types);
+
+           { can we get rid of the call? }
+           if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
+              not(cnf_return_value_used in callnodeflags) and
+             (procdefinition.typ=procdef) and
+             tprocdef(procdefinition).isempty and
+             { allow only certain proc options }
+             ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
+               po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
+               po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
+               po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
+               po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
+             begin
+               { check parameters for side effects }
+               para:=tcallparanode(left);
+               while assigned(para) do
+                 begin
+                   if (para.parasym.typ = paravarsym) and
+                      ((para.parasym.refs>0) or
+                      { array of consts are converted later on so we need to skip them here
+                        else no error detection is done }
+                       is_array_of_const(para.parasym.vardef) or
+                       not(cs_opt_dead_values in current_settings.optimizerswitches) or
+                       might_have_sideeffects(para.left)) then
+                       break;
+                    para:=tcallparanode(para.right);
+                 end;
+               { finally, remove it if no parameter with side effect has been found }
+               if para=nil then
+                 begin
+                   result:=cnothingnode.create;
+                   exit;
+                 end;
+             end;
 
-             { must be called before maybe_load_in_temp(methodpointer), because
-               it converts the methodpointer into a temp in case it's a call
-               (and we want to know the original call)
-             }
-             register_created_object_types;
-           end;
+           { convert Objective-C calls into a message call }
+           if (procdefinition.typ=procdef) and
+              (po_objc in tprocdef(procdefinition).procoptions) then
+             begin
+               if not(cnf_objc_processed in callnodeflags) then
+                 objc_convert_to_message_send;
+             end
+           else
+             begin
+               { The following don't apply to obj-c: obj-c methods can never be
+                 inlined because they're always virtual and the destination can
+                 change at run, and for the same reason we also can't perform
+                 WPO on them (+ they have no constructors) }
+
+               { Check if the call can be inlined, sets the cnf_do_inline flag }
+               check_inlining;
+
+               { must be called before maybe_load_in_temp(methodpointer), because
+                 it converts the methodpointer into a temp in case it's a call
+                 (and we want to know the original call)
+               }
+               register_created_object_types;
+             end;
 
-         { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
-           is a calln this is even required to not execute the calln twice.
-           This needs to be done after the resulttype pass, because in the resulttype we can still convert the
-           calln to a loadn (PFV) }
-         if assigned(methodpointer) then
-           maybe_load_in_temp(methodpointer);
+           { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
+             is a calln this is even required to not execute the calln twice.
+             This needs to be done after the resulttype pass, because in the resulttype we can still convert the
+             calln to a loadn (PFV) }
+           if assigned(methodpointer) then
+             maybe_load_in_temp(methodpointer);
 
-         { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
-         maybe_create_funcret_node;
+           { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
+           maybe_create_funcret_node;
 
-         { Insert the self,vmt,function result in the parameters }
-         gen_hidden_parameters;
+           { Insert the self,vmt,function result in the parameters }
+           gen_hidden_parameters;
 
-         { Remove useless nodes from init/final blocks }
-         { (simplify depends on typecheck info)        }
-         if assigned(callinitblock) then
-           begin
-             typecheckpass(tnode(callinitblock));
-             doinlinesimplify(tnode(callinitblock));
-           end;
-         if assigned(callcleanupblock) then
-           begin
-             typecheckpass(tnode(callcleanupblock));
-             doinlinesimplify(tnode(callcleanupblock));
-           end;
+           { Remove useless nodes from init/final blocks }
+           { (simplify depends on typecheck info)        }
+           if assigned(callinitblock) then
+             begin
+               typecheckpass(tnode(callinitblock));
+               doinlinesimplify(tnode(callinitblock));
+             end;
+           if assigned(callcleanupblock) then
+             begin
+               typecheckpass(tnode(callcleanupblock));
+               doinlinesimplify(tnode(callcleanupblock));
+             end;
 
-         { If a constructor calls another constructor of the same or of an
-           inherited class, some targets (jvm) have to generate different
-           entry code for the constructor. }
-         if (current_procinfo.procdef.proctypeoption=potype_constructor) and
-            (procdefinition.typ=procdef) and
-            (tprocdef(procdefinition).proctypeoption=potype_constructor) and
-            ([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
-           current_procinfo.ConstructorCallingConstructor:=true;
-
-         { object check helper will load VMT -> needs GOT }
-         if (cs_check_object in current_settings.localswitches) and
-            (cs_create_pic in current_settings.moduleswitches) then
-           include(current_procinfo.flags,pi_needs_got);
-
-         { Continue with checking a normal call or generate the inlined code }
-         if cnf_do_inline in callnodeflags then
-           result:=pass1_inline
-         else
-           begin
-             mark_unregable_parameters;
-             result:=pass1_normal;
-           end;
+           { If a constructor calls another constructor of the same or of an
+             inherited class, some targets (jvm) have to generate different
+             entry code for the constructor. }
+           if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+              (procdefinition.typ=procdef) and
+              (tprocdef(procdefinition).proctypeoption=potype_constructor) and
+              ([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
+             current_procinfo.ConstructorCallingConstructor:=true;
+
+           { object check helper will load VMT -> needs GOT }
+           if (cs_check_object in current_settings.localswitches) and
+              (cs_create_pic in current_settings.moduleswitches) then
+             include(current_procinfo.flags,pi_needs_got);
+
+           { Continue with checking a normal call or generate the inlined code }
+           if cnf_do_inline in callnodeflags then
+             result:=pass1_inline
+           else
+             begin
+               mark_unregable_parameters;
+               result:=pass1_normal;
+             end;
+         finally
+           aktcallnode:=oldcallnode;
+         end;
       end;
 
 
index da7dcc62932f84d20a6880665212caa0b6576cee..1a40eb576f83e3fabab7bb763ae19a2560a71740 100644 (file)
@@ -176,6 +176,11 @@ interface
         if (nf_explicit in flags) and
            not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
           begin
+             { overriding methods must be able to know in advance whether this
+               code path will be taken by checking expectloc, so they can call
+               the inherited method in that case }
+             if left.expectloc in [LOC_FLAGS,LOC_JUMP] then
+               internalerror(2014122901);
              location_copy(location,left.location);
              newsize:=def_cgsize(resultdef);
              { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
index d6348d324d26c6896fc76cb74e27c361267b50c9..f1e5ef216f09617b3ff64eae6a423e2efef0914a 100644 (file)
@@ -749,16 +749,12 @@ implementation
       secondpass(left);
 
       opsize:=tcgsize2unsigned[left.location.size];
-      if opsize < OS_32 then
-        opsize:=OS_32;
-
-      if (left.location.loc <> LOC_REGISTER) or
-         (left.location.size <> opsize) then
+      if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
         hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,cgsize_orddef(opsize),true);
 
-      location_reset(location,LOC_REGISTER,opsize);
-      location.register := cg.getintregister(current_asmdata.CurrAsmList,opsize);
-      cg.a_bit_scan_reg_reg(current_asmdata.CurrAsmList,reverse,opsize,left.location.register,location.register);
+      location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+      location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+      cg.a_bit_scan_reg_reg(current_asmdata.CurrAsmList,reverse,opsize,location.size,left.location.register,location.register);
     end;
 
 
index 1473aafb29cfd965b011e537ec54bf036deb1588..2fe9c184e6f3d6721a244e0293b229f45607d3c0 100644 (file)
@@ -768,9 +768,17 @@ implementation
                            (right.resultdef.typ=floatdef) and
                            (left.location.size<>right.location.size) then
                           begin
-                            hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
-                              right.resultdef,left.resultdef,
-                              right.location.reference,left.location.reference)
+                            { assume that all float types can be handed by the
+                              fpu if one can be handled by the fpu }
+                            if not use_vectorfpu(left.resultdef) or
+                               not use_vectorfpu(right.resultdef) then
+                              hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
+                                right.resultdef,left.resultdef,
+                                right.location.reference,left.location.reference)
+                            else
+                              hlcg.a_loadmm_ref_ref(current_asmdata.CurrAsmList,
+                                right.resultdef,left.resultdef,
+                                right.location.reference,left.location.reference,mms_movescalar)
                           end
                         else
                           begin
index 82f75f4e66dc2ab6e7b6a52ef86ddde02e50c342..8a38b40769128c34a58f1da6d7c707283decc099 100644 (file)
@@ -457,9 +457,9 @@ implementation
     procedure tcgshlshrnode.second_integer;
       var
          op : topcg;
-         opdef,right_opdef : tdef;
+         opdef: tdef;
          hcountreg : tregister;
-         opsize,right_opsize : tcgsize;
+         opsize : tcgsize;
          shiftval : longint;
       begin
          { determine operator }
@@ -472,44 +472,51 @@ implementation
 {$ifdef cpunodefaultint}
         opsize:=left.location.size;
         opdef:=left.resultdef;
-        right_opsize:=opsize;
-        right_opdef:=opdef;
 {$else cpunodefaultint}
-         { load left operators in a register }
-         if is_signed(left.resultdef) then
-           begin
-             right_opsize:=OS_SINT;
-             right_opdef:=ossinttype;
-             {$ifdef cpu16bitalu}
-               if left.resultdef.size > 2 then
-                 begin
-                   opsize:=OS_S32;
-                   opdef:=s32inttype;
-                 end
-               else
-             {$endif cpu16bitalu}
-                 begin
-                   opsize:=OS_SINT;
-                   opdef:=ossinttype
-                 end;
-           end
-         else
-           begin
-             right_opsize:=OS_INT;
-             right_opdef:=osuinttype;
-             {$ifdef cpu16bitalu}
-               if left.resultdef.size > 2 then
-                 begin
-                   opsize:=OS_32;
-                   opdef:=u32inttype;
-                 end
-               else
-             {$endif cpu16bitalu}
-                 begin
-                   opsize:=OS_INT;
-                   opdef:=osuinttype;
-                 end;
-             end;
+        if left.resultdef.size<=4 then
+          begin
+            if is_signed(left.resultdef) then
+              begin
+                if (sizeof(aint)<4) and
+                   (left.resultdef.size<=sizeof(aint)) then
+                  begin
+                    opsize:=OS_SINT;
+                    opdef:=sinttype;
+                  end
+                else
+                  begin
+                    opdef:=s32inttype;
+                    opsize:=OS_S32
+                  end
+              end
+            else
+              begin
+                if (sizeof(aint)<4) and
+                   (left.resultdef.size<=sizeof(aint)) then
+                  begin
+                    opsize:=OS_INT;
+                    opdef:=uinttype;
+                  end
+                else
+                  begin
+                    opdef:=u32inttype;
+                    opsize:=OS_32;
+                  end
+              end
+          end
+        else
+          begin
+            if is_signed(left.resultdef) then
+              begin
+                opdef:=s64inttype;
+                opsize:=OS_S64;
+              end
+            else
+              begin
+                opdef:=u64inttype;
+                opsize:=OS_64;
+              end;
+          end;
 {$endif cpunodefaultint}
 
          if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
@@ -538,14 +545,8 @@ implementation
                 is done since most target cpu which will use this
                 node do not support a shift count in a mem. location (cec)
               }
-              if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
-                begin
-                  hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,right_opdef);
-                  hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,right_opdef,right.location,hcountreg);
-                end
-              else
-                hcountreg:=right.location.register;
-              hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,hcountreg,left.location.register,location.register);
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,opdef,true);
+              hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register);
            end;
          { shl/shr nodes return the same type as left, which can be different
            from opdef }
index ad742fc3f21b6a24463799ce490ae11b964eebc5..1e8c24fdcf090de98c9308eab05130a04b6dce8a 100644 (file)
@@ -27,7 +27,8 @@ unit ncgmem;
 interface
 
     uses
-      globtype,cgbase,cpuinfo,cpubase,
+      globtype,cgbase,cgutils,cpuinfo,cpubase,
+      symtype,
       node,nmem;
 
     type
@@ -67,10 +68,12 @@ interface
            This routine should update location.reference correctly,
            so it points to the correct address.
          }
-         procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);virtual;
-         procedure update_reference_reg_packed(maybe_const_reg:tregister;l:aint);virtual;
+         procedure update_reference_reg_mul(maybe_const_reg: tregister;regsize: tdef; l: aint);virtual;
+         procedure update_reference_reg_packed(maybe_const_reg: tregister; regsize: tdef; l: aint);virtual;
+         procedure update_reference_offset(var ref: treference; index, mulsize: aint); virtual;
          procedure second_wideansistring;virtual;
          procedure second_dynamicarray;virtual;
+         function valid_index_size(size: tcgsize): boolean;virtual;
        public
          procedure pass_generate_code;override;
        end;
@@ -81,11 +84,11 @@ implementation
     uses
       systems,
       cutils,cclasses,verbose,globals,constexp,
-      symconst,symbase,symtype,symdef,symsym,symcpu,symtable,defutil,paramgr,
+      symconst,symbase,symdef,symsym,symcpu,symtable,defutil,paramgr,
       aasmbase,aasmtai,aasmdata,
       procinfo,pass_2,parabase,
       pass_1,nld,ncon,nadd,ncnv,nutils,
-      cgutils,cgobj,hlcgobj,
+      cgobj,hlcgobj,
       tgobj,ncgutil,objcgutl,
       defcmp
       ;
@@ -525,8 +528,8 @@ implementation
              }
              asmsym:=current_asmdata.RefAsmSymbol(vs.mangledname);
              reference_reset_symbol(tmpref,asmsym,0,sizeof(pint));
-             location.reference.index:=cg.getaddressregister(current_asmdata.CurrAsmList);
-             cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,location.reference.index);
+             location.reference.index:=hlcg.getintregister(current_asmdata.CurrAsmList,ptruinttype);
+             hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,ptruinttype,ptruinttype,tmpref,location.reference.index);
              { always packrecords C -> natural alignment }
              location.reference.alignment:=vs.vardef.alignment;
            end
@@ -619,7 +622,7 @@ implementation
      { the live range of the LOC_CREGISTER will most likely overlap the   }
      { the live range of the target LOC_(C)REGISTER)                      }
      { The passed register may be a LOC_CREGISTER as well.                }
-     procedure tcgvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+     procedure tcgvecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
        var
          hreg: tregister;
        begin
@@ -649,7 +652,7 @@ implementation
 
 
      { see remarks for tcgvecnode.update_reference_reg_mul above }
-     procedure tcgvecnode.update_reference_reg_packed(maybe_const_reg:tregister;l:aint);
+     procedure tcgvecnode.update_reference_reg_packed(maybe_const_reg: tregister; regsize: tdef; l:aint);
        var
          sref: tsubsetreference;
          offsetreg, hreg: tregister;
@@ -667,7 +670,7 @@ implementation
 {$endif not cpu64bitalu}
              ) then
            begin
-             update_reference_reg_mul(maybe_const_reg,l div 8);
+             update_reference_reg_mul(maybe_const_reg,regsize,l div 8);
              exit;
            end;
          if (l > 8*sizeof(aint)) then
@@ -678,7 +681,7 @@ implementation
          cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_INT,l,hreg);
          { keep alignment for index }
          sref.ref.alignment := left.resultdef.alignment;
-         if not ispowerof2(sref.ref.alignment,temp) then
+         if not ispowerof2(packedbitsloadsize(l),temp) then
            internalerror(2006081201);
          alignpower:=temp;
          offsetreg := cg.getaddressregister(current_asmdata.CurrAsmList);
@@ -705,6 +708,12 @@ implementation
        end;
 
 
+     procedure tcgvecnode.update_reference_offset(var ref: treference; index, mulsize: aint);
+       begin
+         inc(ref.offset,index*mulsize);
+       end;
+
+
      procedure tcgvecnode.second_wideansistring;
        begin
        end;
@@ -714,6 +723,13 @@ implementation
        end;
 
 
+     function tcgvecnode.valid_index_size(size: tcgsize): boolean;
+       begin
+         result:=
+           tcgsize2signed[size]=tcgsize2signed[OS_ADDR];
+       end;
+
+
      procedure tcgvecnode.rangecheck_array;
        var
          hightree : tnode;
@@ -859,6 +875,7 @@ implementation
          paraloc2 : tcgpara;
          subsetref : tsubsetreference;
          temp : longint;
+         indexdef : tdef;
       begin
          paraloc1.init;
          paraloc2.init;
@@ -916,7 +933,7 @@ implementation
 
               { in ansistrings/widestrings S[1] is p<w>char(S)[0] }
               if not(cs_zerobasedstrings in current_settings.localswitches) then
-                dec(location.reference.offset,offsetdec);
+                update_reference_offset(location.reference,-1,offsetdec);
            end
          else if is_dynamic_array(left.resultdef) then
            begin
@@ -971,7 +988,7 @@ implementation
               or is_64bitint(resultdef)
 {$endif not cpu64bitalu}
               ) then
-           dec(location.reference.offset,bytemulsize*tarraydef(left.resultdef).lowrange);
+           update_reference_offset(location.reference,-tarraydef(left.resultdef).lowrange,bytemulsize);
 
          if right.nodetype=ordconstn then
            begin
@@ -992,10 +1009,10 @@ implementation
                    { only orddefs are bitpacked }
                    not is_ordinal(resultdef))) then
                 begin
-                  extraoffset:=bytemulsize*tordconstnode(right).value.svalue;
-                  inc(location.reference.offset,extraoffset);
-                  { adjust alignment after to this change }
-                  location.reference.alignment:=newalignment(location.reference.alignment,extraoffset);
+                  extraoffset:=tordconstnode(right).value.svalue;
+                  update_reference_offset(location.reference,extraoffset,bytemulsize);
+                  { adjust alignment after this change }
+                  location.reference.alignment:=newalignment(location.reference.alignment,extraoffset*bytemulsize);
                   { don't do this for floats etc.; needed to properly set the }
                   { size for bitpacked arrays (e.g. a bitpacked array of      }
                   { enums who are size 2 but fit in one byte -> in the array  }
@@ -1008,10 +1025,10 @@ implementation
                 begin
                   subsetref.ref := location.reference;
                   subsetref.ref.alignment := left.resultdef.alignment;
-                  if not ispowerof2(subsetref.ref.alignment,temp) then
+                  if not ispowerof2(packedbitsloadsize(resultdef.packedbitsize),temp) then
                     internalerror(2006081212);
                   alignpow:=temp;
-                  inc(subsetref.ref.offset,((mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) shr (3+alignpow)) shl alignpow);
+                  update_reference_offset(subsetref.ref,(mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) shr (3+alignpow),1 shl alignpow);
                   subsetref.bitindexreg := NR_NO;
                   subsetref.startbit := (mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) and ((1 shl (3+alignpow))-1);
                   subsetref.bitlen := resultdef.packedbitsize;
@@ -1056,8 +1073,7 @@ implementation
                             replacenode(rightp^,taddnode(rightp^).left);
                           end;
                      end;
-                   inc(location.reference.offset,
-                       mulsize*extraoffset);
+                   update_reference_offset(location.reference,extraoffset,mulsize);
                 end;
               { calculate from left to right }
               if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
@@ -1075,8 +1091,14 @@ implementation
               secondpass(right);
 
               { if mulsize = 1, we won't have to modify the index }
-              if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or (right.location.size<>OS_ADDR) then
-                hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,ptruinttype,true);
+              if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
+                 not valid_index_size(right.location.size) then
+                begin
+                  hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,ptruinttype,true);
+                  indexdef:=ptruinttype
+                end
+              else
+                indexdef:=right.resultdef;
 
               if isjump then
                begin
@@ -1098,9 +1120,9 @@ implementation
               { insert the register and the multiplication factor in the
                 reference }
               if not is_packed_array(left.resultdef) then
-                update_reference_reg_mul(right.location.register,mulsize)
+                update_reference_reg_mul(right.location.register,indexdef,mulsize)
               else
-                update_reference_reg_packed(right.location.register,mulsize);
+                update_reference_reg_packed(right.location.register,indexdef,mulsize);
            end;
 
         location.size:=newsize;
index 2208ee1e95d0efac1286caf6bf1a22621d1ff9af..57c2ba55cd0b8281393fdcc88597c6f30dc2a859 100644 (file)
@@ -598,82 +598,6 @@ implementation
                             Init/Finalize Code
 ****************************************************************************}
 
-    procedure copyvalueparas(p:TObject;arg:pointer);
-      var
-        href : treference;
-        hreg : tregister;
-        list : TAsmList;
-        hsym : tparavarsym;
-        l    : longint;
-        localcopyloc : tlocation;
-        sizedef : tdef;
-      begin
-        list:=TAsmList(arg);
-        if (tsym(p).typ=paravarsym) and
-           (tparavarsym(p).varspez=vs_value) and
-          (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
-          begin
-            { we have no idea about the alignment at the caller side }
-            hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,true,1);
-            if is_open_array(tparavarsym(p).vardef) or
-               is_array_of_const(tparavarsym(p).vardef) then
-              begin
-                { cdecl functions don't have a high pointer so it is not possible to generate
-                  a local copy }
-                if not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
-                  begin
-                    hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
-                    if not assigned(hsym) then
-                      internalerror(200306061);
-                    sizedef:=getpointerdef(tparavarsym(p).vardef);
-                    hreg:=hlcg.getaddressregister(list,sizedef);
-                    if not is_packed_array(tparavarsym(p).vardef) then
-                      hlcg.g_copyvaluepara_openarray(list,href,hsym.initialloc,tarraydef(tparavarsym(p).vardef),hreg)
-                    else
-                      internalerror(2006080401);
-//                      cg.g_copyvaluepara_packedopenarray(list,href,hsym.intialloc,tarraydef(tparavarsym(p).vardef).elepackedbitsize,hreg);
-                    hlcg.a_load_reg_loc(list,sizedef,sizedef,hreg,tparavarsym(p).initialloc);
-                  end;
-              end
-            else
-              begin
-                { Allocate space for the local copy }
-                l:=tparavarsym(p).getsize;
-                localcopyloc.loc:=LOC_REFERENCE;
-                localcopyloc.size:=int_cgsize(l);
-                tg.GetLocal(list,l,tparavarsym(p).vardef,localcopyloc.reference);
-                { Copy data }
-                if is_shortstring(tparavarsym(p).vardef) then
-                  begin
-                    { this code is only executed before the code for the body and the entry/exit code is generated
-                      so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
-                    }
-                    include(current_procinfo.flags,pi_do_call);
-                    hlcg.g_copyshortstring(list,href,localcopyloc.reference,tstringdef(tparavarsym(p).vardef));
-                  end
-                else if tparavarsym(p).vardef.typ = variantdef then
-                  begin
-                    { this code is only executed before the code for the body and the entry/exit code is generated
-                      so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
-                    }
-                    include(current_procinfo.flags,pi_do_call);
-                    hlcg.g_copyvariant(list,href,localcopyloc.reference,tvariantdef(tparavarsym(p).vardef))
-                  end
-                else
-                  begin
-                    { pass proper alignment info }
-                    localcopyloc.reference.alignment:=tparavarsym(p).vardef.alignment;
-                    cg.g_concatcopy(list,href,localcopyloc.reference,tparavarsym(p).vardef.size);
-                  end;
-                { update localloc of varsym }
-                tg.Ungetlocal(list,tparavarsym(p).localloc.reference);
-                tparavarsym(p).localloc:=localcopyloc;
-                tparavarsym(p).initialloc:=localcopyloc;
-              end;
-          end;
-      end;
-
-
     { generates the code for incrementing the reference count of parameters and
       initialize out parameters }
     procedure init_paras(p:TObject;arg:pointer);
@@ -698,7 +622,11 @@ implementation
                  if not((tparavarsym(p).vardef.typ=variantdef) and
                     paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
                    begin
-                     hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+                     hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,
+                       is_open_array(tparavarsym(p).vardef) or
+                       ((target_info.system in systems_caller_copy_addr_value_para) and
+                        paramanager.push_addr_param(vs_value,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)),
+                        sizeof(pint));
                      if is_open_array(tparavarsym(p).vardef) then
                        begin
                          { open arrays do not contain correct element count in their rtti,
@@ -864,12 +792,11 @@ implementation
         end;
 
       var
-        paraloc  : pcgparalocation;
-        href     : treference;
-        sizeleft : aint;
-{$if defined(sparc) or defined(arm) or defined(mips)}
-        tempref  : treference;
-{$endif defined(sparc) or defined(arm) or defined(mips)}
+        paraloc   : pcgparalocation;
+        href      : treference;
+        sizeleft  : aint;
+        alignment : longint;
+        tempref   : treference;
 {$ifdef mips}
         tmpreg   : tregister;
 {$endif mips}
@@ -1085,7 +1012,38 @@ implementation
                         end
 {$endif defined(cpu8bitalu)}
                       else
-                        internalerror(200410105);
+                        begin
+                          { this can happen if a parameter is spread over
+                            multiple paralocs, e.g. if a record with two single
+                            fields must be passed in two single precision
+                            registers }
+                          { does it fit in the register of destloc? }
+                          sizeleft:=para.intsize;
+                          if sizeleft<>vardef.size then
+                            internalerror(2014122806);
+                          if sizeleft<>tcgsize2size[destloc.size] then
+                            internalerror(200410105);
+                          { store everything first to memory, then load it in
+                            destloc }
+                          tg.gettemp(list,sizeleft,sizeleft,tt_persistent,tempref);
+                          gen_alloc_regloc(list,destloc);
+                          while sizeleft>0 do
+                            begin
+                              if not assigned(paraloc) then
+                                internalerror(2014122807);
+                              unget_para(paraloc^);
+                              cg.a_load_cgparaloc_ref(list,paraloc^,tempref,sizeleft,newalignment(para.alignment,para.intsize-sizeleft));
+                              if (paraloc^.size=OS_NO) and
+                                 assigned(paraloc^.next) then
+                                internalerror(2014122805);
+                              inc(tempref.offset,tcgsize2size[paraloc^.size]);
+                              dec(sizeleft,tcgsize2size[paraloc^.size]);
+                              paraloc:=paraloc^.next;
+                            end;
+                          dec(tempref.offset,para.intsize);
+                          cg.a_load_ref_reg(list,para.size,para.size,tempref,destloc.register);
+                          tg.ungettemp(list,tempref);
+                        end;
                     end
                   else
                     begin
@@ -1214,10 +1172,17 @@ implementation
               else
 {$endif not cpu64bitalu}
                 begin
-                  unget_para(paraloc^);
-                  gen_alloc_regloc(list,destloc);
-                  { from register to register -> alignment is irrelevant }
-                  cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
+                  if not assigned(paraloc^.next) then
+                    begin
+                      unget_para(paraloc^);
+                      gen_alloc_regloc(list,destloc);
+                      { from register to register -> alignment is irrelevant }
+                      cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
+                    end
+                  else
+                    begin
+                      internalerror(200410108);
+                    end;
                   { data could come in two memory locations, for now
                     we simply ignore the sanity check (FK)
                   if assigned(paraloc^.next) then
@@ -1293,7 +1258,7 @@ implementation
         { generate copies of call by value parameters, must be done before
           the initialization and body is parsed because the refcounts are
           incremented using the local copies }
-        current_procinfo.procdef.parast.SymList.ForEachCall(@copyvalueparas,list);
+        current_procinfo.procdef.parast.SymList.ForEachCall(@hlcg.g_copyvalueparas,list);
         if not(po_assembler in current_procinfo.procdef.procoptions) then
           begin
             { initialize refcounted paras, and trash others. Needed here
index 56bcdf417db7279414e5813fbcf2bb0a1a9579b4..7bdadfb964d2e05152f88b24f1fbf4aef36b75f1 100644 (file)
@@ -2374,6 +2374,10 @@ implementation
                                  ((resultdef.typ=enumdef) and
                                   (left.resultdef.typ=objectdef))) or
 {$endif}
+                                (
+                                 is_void(left.resultdef)  and
+                                 (left.nodetype=derefn)
+                                ) or
                                 (
                                  not(is_open_array(left.resultdef)) and
                                  not(is_array_constructor(left.resultdef)) and
@@ -2388,10 +2392,6 @@ implementation
                                    { the softfloat code generates casts <const. float> to record }
                                    (nf_internal in flags)
                                  ))
-                                ) or
-                                (
-                                 is_void(left.resultdef)  and
-                                 (left.nodetype=derefn)
                                 )
                                ) then
                            CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename)
index a81bdfe459d7728b241fe157066835f3a5b6a1fb..7f8fed41ff6e0888b507b1874859e659551d4914 100644 (file)
@@ -2631,6 +2631,10 @@ implementation
                   if (left.resultdef.typ<>undefineddef) and
                       paramanager.push_high_param(vs_value,left.resultdef,current_procinfo.procdef.proccalloption) then
                    begin
+                     { this should be an open array or array of const, both of
+                       which can only be simple load nodes of parameters }
+                     if left.nodetype<>loadn then
+                       internalerror(2014120701);
                      hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
                      if assigned(hightree) then
                       begin
index 2026b6490b6e2e676176fdde91d00e28aa538e09..bec09106e2e18f3cc57b8ad7d010c4f496fb4025 100644 (file)
@@ -326,7 +326,7 @@ implementation
                  begin
                    if assigned(left) then
                      internalerror(200309289);
-                   left:=cloadparentfpnode.create(tprocdef(symtable.defowner));
+                   left:=cloadparentfpnode.create(tprocdef(symtable.defowner),lpf_forload);
                    { we can't inline the referenced parent procedure }
                    exclude(tprocdef(symtable.defowner).procoptions,po_inline);
                    { reference in nested procedures, variable needs to be in memory }
@@ -484,7 +484,7 @@ implementation
               begin
                 { parent frame pointer pointer as "self" }
                 left.free;
-                left:=cloadparentfpnode.create(tprocdef(p.owner.defowner));
+                left:=cloadparentfpnode.create(tprocdef(p.owner.defowner),lpf_forpara);
               end;
           end
         { we should never go from nested to non-nested }
index 7953b0861455436b0452786b553862970735b563..f31359626b81d3bdbb9172e29e04e9917612b426 100644 (file)
@@ -45,10 +45,18 @@ interface
        end;
        tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
 
+       tloadparentfpkind = (
+         { as parameter to a nested routine (current routine's frame) }
+         lpf_forpara,
+         { to load a local from a parent routine in the current nested routine
+           (some parent routine's frame) }
+         lpf_forload
+       );
        tloadparentfpnode = class(tunarynode)
           parentpd : tprocdef;
           parentpdderef : tderef;
-          constructor create(pd:tprocdef);virtual;
+          kind: tloadparentfpkind;
+          constructor create(pd: tprocdef; fpkind: tloadparentfpkind);virtual;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure buildderefimpl;override;
@@ -240,7 +248,8 @@ implementation
            include(current_procinfo.flags,pi_needs_got);
          if left.nodetype<>typen then
            begin
-             if (is_objc_class_or_protocol(left.resultdef) or
+             if (target_info.system=system_aarch64_darwin) and
+                (is_objc_class_or_protocol(left.resultdef) or
                  is_objcclassref(left.resultdef)) then
                begin
                  { on non-fragile ABI platforms, the ISA pointer may be opaque
@@ -294,7 +303,7 @@ implementation
                         TLOADPARENTFPNODE
 *****************************************************************************}
 
-    constructor tloadparentfpnode.create(pd:tprocdef);
+    constructor tloadparentfpnode.create(pd: tprocdef; fpkind: tloadparentfpkind);
       begin
         inherited create(loadparentfpn,nil);
         if not assigned(pd) then
@@ -302,6 +311,7 @@ implementation
         if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
           internalerror(200309284);
         parentpd:=pd;
+        kind:=fpkind;
       end;
 
 
@@ -309,6 +319,7 @@ implementation
       begin
         inherited ppuload(t,ppufile);
         ppufile.getderef(parentpdderef);
+        kind:=tloadparentfpkind(ppufile.getbyte);
       end;
 
 
@@ -316,6 +327,7 @@ implementation
       begin
         inherited ppuwrite(ppufile);
         ppufile.putderef(parentpdderef);
+        ppufile.putbyte(byte(kind));
       end;
 
 
@@ -337,7 +349,8 @@ implementation
       begin
         result:=
           inherited docompare(p) and
-          (tloadparentfpnode(p).parentpd=parentpd);
+          (tloadparentfpnode(p).parentpd=parentpd) and
+          (tloadparentfpnode(p).kind=kind);
       end;
 
 
@@ -347,6 +360,7 @@ implementation
       begin
          p:=tloadparentfpnode(inherited dogetcopy);
          p.parentpd:=parentpd;
+         p.kind:=kind;
          dogetcopy:=p;
       end;
 
index 648378b3f34d3193f2f17658d2a7a652a99d27e5..cf113b076eed280944335012a13f113147cbd31f 100644 (file)
@@ -91,7 +91,7 @@ implementation
     end;
 
 
-    { Used by PowerPC/64, ARM, and x86_64 }
+    { Used by PowerPC/64, ARM, x86_64 and AArch64 }
     tobjcrttiwriter_nonfragile = class(tobjcrttiwriter)
      protected
       ObjCEmptyCacheVar,
index 00dfb27b0abe362b3fd83b5e27173beb2b98d2de..f26bceb90d7ce7212d601634784e8fd29152b9eb 100644 (file)
@@ -153,13 +153,13 @@ end;
                 { in case we are in a category method, we need the metaclass of the
                   superclass class extended by this category (= metaclass of superclass of superclass)
                   for the fragile abi, and the metaclass of the superclass for the non-fragile ABI }
-{$if defined(onlymacosx10_6) or defined(arm) }
+{$if defined(onlymacosx10_6) or defined(arm) or defined(aarch64)}
                 { NOTE: those send2 methods are only available on Mac OS X 10.6 and later!
                     (but also on all iPhone SDK revisions we support) }
                 if (target_info.system in systems_objc_nfabi) then
                   result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(tclassrefdef(def).pointeddef).childof))
                 else
-{$endif onlymacosx10_6 or arm}
+{$endif onlymacosx10_6 or arm aarch64}
                   result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(tclassrefdef(def).pointeddef).childof.childof));
                 tloadvmtaddrnode(result).forcall:=true;
                 result:=cloadvmtaddrnode.create(result);
@@ -183,14 +183,14 @@ end;
             tloadvmtaddrnode(result).forcall:=true;
           end;
 
-{$if defined(onlymacosx10_6) or defined(arm) }
+{$if defined(onlymacosx10_6) or defined(arm) or defined(aarch64)}
         { For the non-fragile ABI, the superclass send2 method itself loads the
           superclass. For the fragile ABI, we have to do this ourselves.
 
           NOTE: those send2 methods are only available on Mac OS X 10.6 and later!
             (but also on all iPhone SDK revisions we support) }
         if not(target_info.system in systems_objc_nfabi) then
-{$endif onlymacosx10_6 or arm}
+{$endif onlymacosx10_6 or arm or aarch64}
           result:=objcloadbasefield(result,'SUPERCLASS');
         typecheckpass(result);
       end;
index 4b1c54da7736b6f103811a44c0288496409a1c1d..5489456fe3b08bdd14276f9deee0551d01caadc5 100644 (file)
@@ -68,6 +68,8 @@ interface
 {$endif i386}
 {$ifdef arm}
          RELOC_RELATIVE_24,
+         RELOC_RELATIVE_24_THUMB,
+         RELOC_RELATIVE_CALL_THUMB,
 {$endif arm}
          { Relative relocation }
          RELOC_RELATIVE,
@@ -170,6 +172,10 @@ interface
        { Darwin asm is using indirect symbols resolving }
        indsymbol  : TObjSymbol;
 
+{$ifdef ARM}
+       ThumbFunc : boolean;
+{$endif ARM}
+
        constructor create(AList:TFPHashObjectList;const AName:string);
        function  address:aword;
        procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
@@ -287,6 +293,9 @@ interface
      public
        CurrPass  : byte;
        ExecStack : boolean;
+{$ifdef ARM}
+       ThumbFunc : boolean;
+{$endif ARM}
        constructor create(const n:string);virtual;
        destructor  destroy;override;
        { Sections }
@@ -982,6 +991,9 @@ implementation
         FCachedAsmSymbolList:=TFPObjectList.Create(false);
         { section class type for creating of new sections }
         FCObjSection:=TObjSection;
+{$ifdef ARM}
+        ThumbFunc:=false;
+{$endif ARM}
       end;
 
 
@@ -1166,6 +1178,11 @@ implementation
         result:=TObjSymbol(FObjSymbolList.Find(aname));
         if not assigned(result) then
           result:=TObjSymbol.Create(FObjSymbolList,aname);
+
+{$ifdef ARM}
+        result.ThumbFunc:=ThumbFunc;
+        ThumbFunc:=false;
+{$endif ARM}
       end;
 
 
index e17d7763941a88e0a86396ac7c7c2f878fec61c1..3b58e82801d6aab5301602b69bfcff08628cd6ea 100644 (file)
@@ -261,9 +261,9 @@ interface
        TLSDIR_SIZE      = $18;
 {$endif i386}
 {$ifdef arm}
-       COFF_MAGIC       = $1c0;
        COFF_OPT_MAGIC   = $10b;
        TLSDIR_SIZE      = $18;
+       function COFF_MAGIC: word;
 {$endif arm}
 {$ifdef x86_64}
        COFF_MAGIC       = $8664;
@@ -422,6 +422,11 @@ implementation
        IMAGE_REL_ARM_BLX11         = $0009;
        IMAGE_REL_ARM_SECTION       = $000E;     { Section table index }
        IMAGE_REL_ARM_SECREL        = $000F;     { Offset within section }
+       IMAGE_REL_ARM_MOV32A        = $0010;     { 32-bit VA applied to MOVW+MOVT pair, added to existing imm (ARM) }
+       IMAGE_REL_ARM_MOV32T        = $0011;     { 32-bit VA applied to MOVW+MOVT pair, added to existing imm (THUMB) }
+       IMAGE_REL_ARM_BRANCH20T     = $0012;     { Thumb: 20 most significant bits of 32 bit B cond instruction }
+       IMAGE_REL_ARM_BRANCH24T     = $0014;     { Thumb: 24 most significant bits of 32 bit B uncond instruction }
+       IMAGE_REL_ARM_BLX23T        = $0015;     { 23 most significant bits of 32 bit BL/BLX instruction. Transformed to BLX if target is Thumb }
 {$endif arm}
 
 {$ifdef i386}
@@ -913,6 +918,14 @@ const pemagic : array[0..3] of byte = (
                     if (relocval<>$3f) and (relocval<>0) then
                       internalerror(200606085);  { offset overflow }
                   end;
+                RELOC_RELATIVE_24_THUMB:
+                  begin
+                    relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset) shr 1 - 4;
+                    address:=address or ((relocval shr 1) and $ffffff) or ((relocval and 1) shl 24);
+                    relocval:=relocval shr 25;
+                    if (relocval<>$3f) and (relocval<>0) then
+                      internalerror(200606085);  { offset overflow }
+                  end;
 {$endif arm}
 {$ifdef x86_64}
                 { 64 bit coff only }
@@ -1009,10 +1022,9 @@ const pemagic : array[0..3] of byte = (
           result:=aname
         else
           begin
-            { non-PECOFF targets lack rodata support.
-              TODO: WinCE likely supports it, but needs testing. }
+            { non-PECOFF targets lack rodata support }
             if (atype in [sec_rodata,sec_rodata_norel]) and
-               not (target_info.system in systems_windows) then
+               not (target_info.system in systems_all_windows) then
               atype:=sec_data;
             secname:=coffsecnames[atype];
             if create_smartlink_sections and
@@ -1038,8 +1050,7 @@ const pemagic : array[0..3] of byte = (
       begin
         if (aType in [sec_rodata,sec_rodata_norel]) then
           begin
-            { TODO: WinCE needs testing }
-            if (target_info.system in systems_windows) then
+            if (target_info.system in systems_all_windows) then
               aType:=sec_rodata_norel
             else
               aType:=sec_data;
@@ -1279,6 +1290,10 @@ const pemagic : array[0..3] of byte = (
                 rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
               RELOC_SECREL32 :
                 rel.reloctype:=IMAGE_REL_ARM_SECREL;
+              RELOC_RELATIVE_24 :
+                rel.reloctype:=IMAGE_REL_ARM_BRANCH24;
+              RELOC_RELATIVE_24_THUMB:
+                rel.reloctype:=IMAGE_REL_ARM_BLX24;
 {$endif arm}
 {$ifdef i386}
               RELOC_RELATIVE :
@@ -1597,6 +1612,8 @@ const pemagic : array[0..3] of byte = (
                rel_type:=RELOC_RELATIVE_24;
              IMAGE_REL_ARM_SECREL:
                rel_type:=RELOC_SECREL32;
+             IMAGE_REL_ARM_BLX24:
+               rel_type:=RELOC_RELATIVE_24_THUMB;
 {$endif arm}
 {$ifdef i386}
              IMAGE_REL_I386_PCRLONG :
@@ -2962,6 +2979,15 @@ const pemagic : array[0..3] of byte = (
         DLLReader.Free;
       end;
 
+{$ifdef arm}
+    function COFF_MAGIC: word;
+      begin
+        if GenerateThumb2Code and (current_settings.cputype>=cpu_armv7) then
+          COFF_MAGIC:=$1c4 // IMAGE_FILE_MACHINE_ARMNT
+        else
+          COFF_MAGIC:=$1c0; // IMAGE_FILE_MACHINE_ARM
+      end;
+{$endif arm}
 
 {*****************************************************************************
                                   Initialize
@@ -3045,7 +3071,7 @@ const pemagic : array[0..3] of byte = (
             asmbin : '';
             asmcmd : '';
             supported_targets : [system_arm_wince];
-            flags : [af_outputbinary];
+            flags : [af_outputbinary,af_smartlink_sections];
             labelprefix : '.L';
             comment : '';
             dollarsign: '$';
index 8a8ee3388a2c64fd643257333561aff88b56457f..938b79899e00e113c40c37739d7a2c7128341fdc 100644 (file)
@@ -181,6 +181,7 @@ interface
        TEncodeRelocProc=function(objrel:TObjRelocation):byte;
        TLoadRelocProc=procedure(objrel:TObjRelocation);
        TLoadSectionProc=function(objinput:TElfObjInput;objdata:TObjData;const shdr:TElfsechdr;shindex:longint):boolean;
+       TEncodeFlagsProc=function:longword;
        TDynamicReloc=(
          dr_relative,
          dr_glob_dat,
@@ -199,6 +200,7 @@ interface
          encodereloc: TEncodeRelocProc;
          loadreloc: TLoadRelocProc;
          loadsection: TLoadSectionProc;
+         encodeflags: TEncodeFlagsProc;
        end;
 
 
@@ -966,6 +968,12 @@ implementation
           elfsym.st_name:=nameidx;
         elfsym.st_size:=objsym.size;
         elfsym.st_value:=objsym.address;
+
+{$ifdef ARM}
+        if objsym.ThumbFunc then
+          inc(elfsym.st_value);
+{$endif ARM}
+
         case objsym.bind of
           AB_LOCAL :
             begin
@@ -1272,6 +1280,8 @@ implementation
            header.e_shnum:=nsections;
            header.e_ehsize:=sizeof(telfheader);
            header.e_shentsize:=sizeof(telfsechdr);
+           if assigned(ElfTarget.encodeflags) then
+             header.e_flags:=ElfTarget.encodeflags();
            MaybeSwapHeader(header);
            writer.write(header,sizeof(header));
            writer.writezeros($40-sizeof(header)); { align }
@@ -2043,6 +2053,8 @@ implementation
         header.e_shnum:=ExeSectionList.Count+1;
         header.e_phnum:=segmentlist.count;
         header.e_ehsize:=sizeof(telfheader);
+        if assigned(ElfTarget.encodeflags) then
+          header.e_flags:=ElfTarget.encodeflags();
         if assigned(EntrySym) then
           header.e_entry:=EntrySym.Address;
         header.e_shentsize:=sizeof(telfsechdr);
index 86119ebc721f5c1910e8da1995081f0eb8260118..c57425d5dd518cd4c042b831fffb6cb2f81a072e 100644 (file)
@@ -646,6 +646,9 @@ begin
 {$ifdef i8086}
       '8',
 {$endif}
+{$ifdef aarch64}
+      'a',
+{$endif}
 {$ifdef arm}
       'A',
 {$endif}
@@ -895,7 +898,7 @@ begin
   if MacVersionSet then
     exit;
   { check for deployment target set via environment variable }
-  if not(target_info.system in [system_i386_iphonesim,system_arm_darwin]) then
+  if not(target_info.system in [system_i386_iphonesim,system_arm_darwin,system_aarch64_darwin,system_x86_64_iphonesim]) then
     begin
       envstr:=GetEnvironmentVariable('MACOSX_DEPLOYMENT_TARGET');
       if envstr<>'' then
@@ -939,6 +942,12 @@ begin
         set_system_compvar('IPHONE_OS_VERSION_MIN_REQUIRED','30000');
         iPhoneOSVersionMin:='3.0';
       end;
+    system_aarch64_darwin,
+    system_x86_64_iphonesim:
+      begin
+        set_system_compvar('IPHONE_OS_VERSION_MIN_REQUIRED','70000');
+        iPhoneOSVersionMin:='7.0';
+      end
     else
       internalerror(2012031001);
   end;
@@ -1487,10 +1496,16 @@ begin
                    Message2(option_obsolete_switch_use_new,'-Fg','-Fl');
                  'l' :
                    begin
-                     if ispara then
-                       ParaLibraryPath.AddPath(sysrootpath,More,false)
+                     if path_absolute(More) then
+                       if ispara then
+                         ParaLibraryPath.AddPath(sysrootpath,More,false)
+                       else
+                         LibrarySearchPath.AddPath(sysrootpath,More,true)
                      else
-                       LibrarySearchPath.AddPath(sysrootpath,More,true);
+                       if ispara then
+                         ParaLibraryPath.AddPath('',More,false)
+                       else
+                         LibrarySearchPath.AddPath('',More,true);
                    end;
                  'L' :
                    begin
@@ -2210,7 +2225,7 @@ begin
                       end;
                     'M':
                       begin
-                        if (target_info.system in (systems_darwin-[system_i386_iphonesim])) and
+                        if (target_info.system in (systems_darwin-[system_i386_iphonesim,system_arm_darwin,system_aarch64_darwin,system_x86_64_iphonesim])) and
                            ParseMacVersionMin(MacOSXVersionMin,iPhoneOSVersionMin,'MAC_OS_X_VERSION_MIN_REQUIRED',copy(More,2,255),false) then
                           begin
                             break;
@@ -2243,7 +2258,7 @@ begin
                       end;
                     'P':
                       begin
-                        if (target_info.system in [system_i386_iphonesim,system_arm_darwin]) and
+                        if (target_info.system in [system_i386_iphonesim,system_arm_darwin,system_aarch64_darwin,system_x86_64_iphonesim]) and
                            ParseMacVersionMin(iPhoneOSVersionMin,MacOSXVersionMin,'IPHONE_OS_VERSION_MIN_REQUIRED',copy(More,2,255),true) then
                           begin
                             break;
@@ -3218,9 +3233,9 @@ begin
 
 { abs(long) is handled internally on all CPUs }
   def_system_macro('FPC_HAS_INTERNAL_ABS_LONG');
-{$if defined(x86_64) or defined(powerpc64)}
+{$if defined(x86_64) or defined(powerpc64) or defined(cpuaarch64)}
   def_system_macro('FPC_HAS_INTERNAL_ABS_INT64');
-{$endif x86_64 or powerpc64}
+{$endif x86_64 or powerpc64 or aarch64}
 
   def_system_macro('FPC_HAS_UNICODESTRING');
   def_system_macro('FPC_RTTI_PACKSET1');
@@ -3403,6 +3418,12 @@ begin
     mm_huge:    def_system_macro('FPC_MM_HUGE');
   end;
 {$endif i8086}
+{$ifdef aarch64}
+  def_system_macro('CPUAARCH64');
+  def_system_macro('CPU64');
+  def_system_macro('FPC_CURRENCY_IS_INT64');
+  def_system_macro('FPC_COMP_IS_INT64');
+{$endif aarch64}
 
   if tf_cld in target_info.flags then
     if not UpdateTargetSwitchStr('CLD', init_settings.targetswitches, true) then
@@ -3689,14 +3710,15 @@ begin
   case target_info.system of
     system_arm_darwin:
       begin
-        { set default cpu type to ARMv6 for Darwin unless specified otherwise, and fpu
-          to VFPv2 }
+        { set default cpu type to ARMv7 for Darwin unless specified otherwise, and fpu
+          to VFPv3 (that's what all 32 bit ARM iOS devices use nowadays)
+        }
         if not option.CPUSetExplicitly then
-          init_settings.cputype:=cpu_armv6;
+          init_settings.cputype:=cpu_armv7;
         if not option.OptCPUSetExplicitly then
-          init_settings.optimizecputype:=cpu_armv6;
+          init_settings.optimizecputype:=cpu_armv7;
         if not option.FPUSetExplicitly then
-          init_settings.fputype:=fpu_vfpv2;
+          init_settings.fputype:=fpu_vfpv3;
       end;
     system_arm_android:
       begin
@@ -3796,7 +3818,7 @@ if (target_info.abi = abi_eabihf) then
 {$endif}
       def_system_macro('FPC_HAS_TYPE_SINGLE');
       def_system_macro('FPC_HAS_TYPE_DOUBLE');
-{$if not defined(i386) and not defined(x86_64) and not defined(i8086)}
+{$if not defined(i386) and not defined(x86_64) and not defined(i8086) and not defined(aarch64)}
       def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
 {$endif}
 {$if defined(m68k)}
@@ -3836,7 +3858,7 @@ if (target_info.abi = abi_eabihf) then
 {$endif ARM}
 
 { inline bsf/bsr implementation }
-{$if defined(i386) or defined(x86_64)}
+{$if defined(i386) or defined(x86_64) or defined(aarch64)}
   def_system_macro('FPC_HAS_INTERNAL_BSF');
   def_system_macro('FPC_HAS_INTERNAL_BSR');
 {$endif}
index 9e06613722204c3a939e6a42dca46368dc61b55c..df9daa3fa433c5d724c52651a55f6f7059e86e11 100644 (file)
@@ -308,11 +308,21 @@ implementation
            { We need a local copy for a value parameter when only the
              address is pushed. Open arrays and Array of Const are
              an exception because they are allocated at runtime and the
-             address that is pushed is patched }
+             address that is pushed is patched.
+
+             Arrays passed to cdecl routines are special: they are pointers in
+             C and hence must be passed as such. Due to historical reasons, if
+             a cdecl routine is implemented in Pascal, we still make a copy on
+             the callee side. Do this the same on platforms that normally must
+             make a copy on the caller side, as otherwise the behaviour will
+             be different (and less perfomant) for routines implemented in C }
            if (varspez=vs_value) and
               paramanager.push_addr_param(varspez,vardef,pd.proccalloption) and
               not(is_open_array(vardef) or
-                  is_array_of_const(vardef)) then
+                  is_array_of_const(vardef)) and
+              (not(target_info.system in systems_caller_copy_addr_value_para) or
+               ((pd.proccalloption in cdecl_pocalls) and
+                (vardef.typ=arraydef))) then
              include(varoptions,vo_has_local_copy);
 
            { needs high parameter ? }
index d1c74f7a398b502cf96306c9786a1df769481aaa..a92fc1061eadb862b0ed2f7caedc053802c47eda 100644 (file)
@@ -188,7 +188,8 @@ const
     { 12 } 16 {'avr'},
     { 13 } 32 {'mipsel'},
     { 14 } 32 {'jvm'},
-    { 15 } 16 {'i8086'}
+    { 15 } 16 {'i8086'},
+    { 16 } 64 {'aarch64'}
     );
   CpuAluBitSize : array[tsystemcpu] of longint =
     (
@@ -207,7 +208,8 @@ const
     { 12 }  8 {'avr'},
     { 13 } 32 {'mipsel'},
     { 14 } 64 {'jvm'},
-    { 15 } 16 {'i8086'}
+    { 15 } 16 {'i8086'},
+    { 16 } 64 {'aarch64'}
     );
 {$endif generic_cpu}
 
index def1535b3afb17027ce05b349a8ecc447159ec5e..01944ae907705d8192bc6de5a9fbc40e7b6a88fc 100644 (file)
@@ -161,6 +161,12 @@ implementation
             Message(parser_h_inlining_disabled);
             exit;
           end;
+        if pi_calls_c_varargs in current_procinfo.flags then
+          begin
+            Message1(parser_h_not_supported_for_inline,'called C-style varargs functions');
+            Message(parser_h_inlining_disabled);
+            exit;
+          end;
         { the compiler cannot handle inherited in inlined subroutines because
           it tries to search for self in the symtable, however, the symtable
           is not available }
index 9e6a243de8c4614827253be18d30855279ec0c6f..6483272fdd4907d2ef0b86650ee41e29b963a48c 100644 (file)
@@ -268,6 +268,10 @@ implementation
         create_fpu_types;
         s64currencytype:=corddef.create(scurrency,low(int64),high(int64));
 {$endif arm}
+{$ifdef aarch64}
+        create_fpu_types;
+        s64currencytype:=corddef.create(scurrency,low(int64),high(int64));
+{$endif aarch64}
 {$ifdef avr}
         s32floattype:=cfloatdef.create(s32real);
         s64floattype:=cfloatdef.create(s64real);
@@ -734,7 +738,6 @@ implementation
 //        aiclass[ait_labeled_instruction]:=tai_labeled_instruction;
 {$endif SPARC}
 {$ifdef arm}
-        aiclass[ait_thumb_func]:=tai_thumb_func;
         aiclass[ait_thumb_set]:=tai_thumb_set;
 {$endif arm}
         aiclass[ait_set]:=tai_set;
index 734c7fe89d92abf8b46740432425d13f5361320a..b07d8db42b0e44afca98c0dfccb157b05696bf67 100644 (file)
@@ -287,12 +287,24 @@ unit raatt;
            end;
 {$endif POWERPC}
 {$if defined(ARM)}
-           { Thumb-2 instructions can have a .W postfix to indicate 32bit instructions
+           {
+             Thumb-2 instructions can have a .W postfix to indicate 32bit instructions,
+             Also in unified syntax sizes and types are indicated with something like a .<dt> prefix for example
            }
            case c of
              '.':
                begin
-                 actasmpattern:=actasmpattern+c;
+                 if len>1 then
+                   begin
+                     while c in ['A'..'Z','a'..'z','0'..'9','_','.'] do
+                       begin
+                         inc(len);
+                         actasmpattern[len]:=c;
+                         c:=current_scanner.asmgetchar;
+                       end;
+                     actasmpattern[0]:=chr(len);
+                   end;
+                 {actasmpattern:=actasmpattern+c;
                  c:=current_scanner.asmgetchar;
 
                  if upcase(c) = 'W' then
@@ -301,10 +313,22 @@ unit raatt;
                      c:=current_scanner.asmgetchar;
                    end
                  else
-                   internalerror(2010122301);
+                   internalerror(2010122301);}
                end
            end;
 {$endif ARM}
+{$ifdef aarch64}
+           { b.cond }
+           case c of
+             '.':
+               begin
+                 repeat
+                   actasmpattern:=actasmpattern+c;
+                   c:=current_scanner.asmgetchar;
+                 until not(c in ['a'..'z','A'..'Z']);
+               end;
+           end;
+{$endif aarch64}
            { Opcode ? }
            If is_asmopcode(upper(actasmpattern)) then
             Begin
@@ -1282,10 +1306,16 @@ unit raatt;
         while (actasmtoken=AS_DOT) do
          begin
            Consume(AS_DOT);
-           if actasmtoken=AS_ID then
-            s:=s+'.'+actasmpattern;
-           if not Consume(AS_ID) then
+
+           { a record field could have the same name as a register }
+           if actasmtoken in [AS_ID,AS_REGISTER] then
+             begin
+               s:=s+'.'+actasmpattern;
+               consume(actasmtoken)
+             end
+           else
             begin
+              Consume(AS_ID);
               RecoverConsume(true);
               break;
             end;
index d767d04237daa0aaeba6d3acc21a26747e4b2fc5..d829882159547091fbe9a373cd524ba82f41dd05 100644 (file)
@@ -69,6 +69,10 @@ type
       OPR_MODEFLAGS : (flags : tcpumodeflags);
       OPR_SPECIALREG: (specialreg : tregister; specialregflags : tspecialregflags);
 {$endif arm}
+{$ifdef aarch64}
+      OPR_SHIFTEROP : (shifterop : tshifterop);
+      OPR_COND      : (cc : tasmcond);
+{$endif aarch64}
   end;
 
   TOperand = class
@@ -1062,15 +1066,17 @@ end;
 {$ifdef ARM}
               OPR_REGSET:
                 ai.loadregset(i-1,regtype,subreg,regset,usermode);
-              OPR_SHIFTEROP:
-                ai.loadshifterop(i-1,shifterop);
-              OPR_COND:
-                ai.loadconditioncode(i-1,cc);
               OPR_MODEFLAGS:
                 ai.loadmodeflags(i-1,flags);
               OPR_SPECIALREG:
                 ai.loadspecialreg(i-1,specialreg,specialregflags);
 {$endif ARM}
+{$if defined(arm) or defined(aarch64)}
+             OPR_SHIFTEROP:
+               ai.loadshifterop(i-1,shifterop);
+             OPR_COND:
+               ai.loadconditioncode(i-1,cc);
+{$endif arm or aarch64}
               { ignore wrong operand }
               OPR_NONE:
                 ;
index 027e7dce8e63f364431ccacd6131b80a8a8a1c0a..1123ffb2665dc63143d6d1e6dd198cccd79ccc79 100644 (file)
@@ -114,6 +114,7 @@ implementation
         encodereloc:       @elf_sparc_encodeReloc;
         loadreloc:         @elf_sparc_loadReloc;
         loadsection:       nil;
+        encodeflags:       nil;
       );
 
     as_sparc_elf32_info : tasminfo =
index bc9fc8b68c7907627cd9d36666d224ebeb5d33e8..663a5956e683f16afe8a1c82c2d085e3ef13e0f0 100644 (file)
@@ -2830,6 +2830,7 @@ implementation
            sc80real:
              if target_info.system in [system_i386_darwin,
                   system_i386_iphonesim,system_x86_64_darwin,
+                  system_x86_64_iphonesim,
                   system_x86_64_linux,system_x86_64_freebsd,
                   system_x86_64_openbsd,system_x86_64_netbsd,
                   system_x86_64_solaris,system_x86_64_embedded,
@@ -7504,7 +7505,7 @@ implementation
       begin
         if assigned(objc_fastenumeration) then
           exit;
-        if not(target_info.system in [system_arm_darwin,system_i386_iphonesim]) then
+        if not(target_info.system in [system_arm_darwin,system_i386_iphonesim,system_aarch64_darwin,system_x86_64_iphonesim]) then
           cocoaunit:='COCOAALL'
         else
           cocoaunit:='IPHONEALL';
@@ -7532,6 +7533,11 @@ implementation
 {$define use_vectorfpuimplemented}
         use_vectorfpu:=(current_settings.fputype in vfp_scalar);
 {$endif arm}
+{$ifdef aarch64}
+{$define use_vectorfpuimplemented}
+        use_vectorfpu:=true;
+{$endif aarch64}
+
 {$ifndef use_vectorfpuimplemented}
         use_vectorfpu:=false;
 {$endif}
index bd9fff3f711773b9e3653cf4e9b8f376521bf615..c3ab6a126dbb795ce069dd0e5f7115ee95633687 100644 (file)
@@ -49,7 +49,8 @@
              cpu_avr,                      { 12 }
              cpu_mipsel,                   { 13 }
              cpu_jvm,                      { 14 }
-             cpu_i8086                     { 15 }
+             cpu_i8086,                    { 15 }
+             cpu_aarch64                   { 16 }
        );
 
        tasmmode= (asmmode_none
@@ -68,6 +69,7 @@
             ,asmmode_avr_gas
             ,asmmode_i8086_intel
             ,asmmode_i8086_att
+            ,asmmode_arm_gas_unified
        );
 
      (* IMPORTANT NOTE:
              system_mipsel_embedded,    { 82 }
              system_i386_aros,          { 83 }
              system_x86_64_aros,        { 84 }
-             system_x86_64_dragonfly    { 85 }
+             system_x86_64_dragonfly,   { 85 }
+             system_aarch64_darwin,     { 86 }
+             system_x86_64_iphonesim,   { 87 }
+             system_aarch64_linux       { 88 }
        );
 
      type
              ,as_i8086_nasm
              ,as_i8086_nasmobj
              ,as_gas_powerpc_xcoff
+             ,as_arm_elf32
              ,as_clang
        );
 
             ,abi_powerpc_sysv,abi_powerpc_aix
             ,abi_eabi,abi_armeb,abi_eabihf
             ,abi_old_win32_gnu
+            ,abi_aarch64_darwin
        );
 
 
index 79339cc73f9414a3cb01b8470c8d13753bfb4a51..f7efda8517c9bda004c6c623f02bf16d1aee88f2 100644 (file)
@@ -216,7 +216,7 @@ interface
        systems_android = [system_arm_android, system_i386_android, system_mipsel_android];
        systems_linux = [system_i386_linux,system_x86_64_linux,system_powerpc_linux,system_powerpc64_linux,
                        system_arm_linux,system_sparc_linux,system_alpha_linux,system_m68k_linux,
-                       system_x86_6432_linux,system_mipseb_linux,system_mipsel_linux];
+                       system_x86_6432_linux,system_mipseb_linux,system_mipsel_linux,system_aarch64_linux];
        systems_dragonfly = [system_x86_64_dragonfly];
        systems_freebsd = [system_i386_freebsd,
                           system_x86_64_freebsd];
@@ -242,7 +242,8 @@ interface
        { all darwin systems }
        systems_darwin = [system_powerpc_darwin,system_i386_darwin,
                          system_powerpc64_darwin,system_x86_64_darwin,
-                         system_arm_darwin,system_i386_iphonesim];
+                         system_arm_darwin,system_i386_iphonesim,
+                         system_aarch64_darwin,system_x86_64_iphonesim];
 
        {all solaris systems }
        systems_solaris = [system_sparc_solaris, system_i386_solaris,
@@ -285,7 +286,7 @@ interface
        systems_objc_supported = systems_darwin;
 
        { systems using the non-fragile Objective-C ABI }
-       systems_objc_nfabi = [system_powerpc64_darwin,system_x86_64_darwin,system_arm_darwin,system_i386_iphonesim];
+       systems_objc_nfabi = [system_powerpc64_darwin,system_x86_64_darwin,system_arm_darwin,system_i386_iphonesim,system_aarch64_darwin,system_x86_64_iphonesim];
 
        { all systems supporting exports from programs or units }
        systems_unit_program_exports = [system_i386_win32,
@@ -335,6 +336,10 @@ interface
          system_jvm_android32
        ];
 
+       { all systems where a value parameter passed by reference must be copied
+         on the caller side rather than on the callee side }
+       systems_caller_copy_addr_value_para = [system_aarch64_darwin];
+
        { pointer checking (requires special code in FPC_CHECKPOINTER,
          and can never work for libc-based targets or any other program
          linking to an external library)
@@ -348,7 +353,8 @@ interface
 
        cpu2str : array[TSystemCpu] of string[10] =
             ('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
-             'mips','arm', 'powerpc64', 'avr', 'mipsel','jvm', 'i8086');
+             'mips','arm', 'powerpc64', 'avr', 'mipsel','jvm', 'i8086',
+             'aarch64');
 
        abiinfo : array[tabi] of tabiinfo = (
          (name: 'DEFAULT'; supported: true),
@@ -357,7 +363,8 @@ interface
          (name: 'EABI'   ; supported:{$ifdef FPC_ARMEL}true{$else}false{$endif}),
          (name: 'ARMEB'  ; supported:{$ifdef FPC_ARMEB}true{$else}false{$endif}),
          (name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}),
-         (name: 'OLDWIN32GNU'; supported:{$ifdef I386}true{$else}false{$endif})
+         (name: 'OLDWIN32GNU'; supported:{$ifdef I386}true{$else}false{$endif}),
+         (name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif})
        );
 
     var
@@ -923,6 +930,21 @@ begin
 {$ifdef i8086}
   default_target(system_i8086_msdos);
 {$endif i8086}
+
+{$ifdef aarch64}
+  {$ifdef cpuaarch64}
+    default_target(source_info.system);
+  {$else cpuaarch64}
+    {$ifdef darwin}
+      {$define default_target_set}
+      default_target(system_aarch64_darwin);
+    {$endif darwin}
+    {$ifndef default_target_set}
+      default_target(system_aarch64_linux);
+      {$define default_target_set}
+    {$endif}
+  {$endif cpuaarch64}
+{$endif aarch64}
 end;
 
 
index 8aafa380586a92af15cac977797544fa9ca14251..916c66171c88987ad78facaa62efe1561e513f5a 100644 (file)
@@ -952,6 +952,69 @@ unit i_bsd;
           );
 
 
+       system_x86_64_iphonesim_info  : tsysteminfo =
+          (
+            system       : system_x86_64_iphonesim;
+            name         : 'Darwin/iPhoneSim for x86_64';
+            shortname    : 'iPhoneSim';
+            flags        : [tf_p_ext_support,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_default,tf_has_winlike_resources];
+            cpu          : cpu_x86_64;
+            unit_env     : 'BSDUNITS';
+            extradefines : 'UNIX;BSD;HASUNIX;DARWIN'; // also define darwin for code compatibility
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.s';
+            objext       : '.o';
+            resext       : '.res';
+            resobjext    : '.or';
+            sharedlibext : '.dylib';
+            staticlibext : '.a';
+            staticlibprefix : 'libp';
+            sharedlibprefix : 'lib';
+            sharedClibext : '.dylib';
+            staticClibext : '.a';
+            staticClibprefix : 'lib';
+            sharedClibprefix : 'lib';
+            importlibprefix : 'libimp';
+            importlibext : '.a';
+            Cprefix      : '_';
+            newline      : #10;
+            dirsep       : '/';
+            assem        : as_clang;
+            assemextern  : as_clang;
+            link         : ld_none;
+            linkextern   : ld_bsd;
+            ar           : ar_gnu_ar;
+            res          : res_macho;
+            dbg          : dbg_dwarf2;
+            script       : script_unix;
+            endian       : endian_little;
+            alignment    :
+              (
+                procalign       : 8;
+                loopalign       : 4;
+                jumpalign       : 0;
+                constalignmin   : 0;
+                constalignmax   : 8;
+                varalignmin     : 0;
+                varalignmax     : 16;
+                localalignmin   : 4;
+                localalignmax   : 16;
+                recordalignmin  : 0;
+                recordalignmax  : 16;
+                maxCrecordalign : 16
+              );
+            first_parm_offset : 16;
+            stacksize   : 262144;
+            stackalign   : 16;
+            abi : abi_default;
+          );
+
+
        system_arm_darwin_info : tsysteminfo =
           (
             system       : system_arm_darwin;
@@ -984,8 +1047,8 @@ unit i_bsd;
             Cprefix      : '_';
             newline      : #10;
             dirsep       : '/';
-            assem        : as_darwin;
-            assemextern  : as_darwin;
+            assem        : as_clang;
+            assemextern  : as_clang;
             link         : ld_none;
             linkextern   : ld_bsd;
             ar           : ar_gnu_ar;
@@ -1014,6 +1077,71 @@ unit i_bsd;
             abi : abi_default
           );
 
+
+       system_aarch64_darwin_info  : tsysteminfo =
+          (
+            system       : system_aarch64_darwin;
+            name         : 'Darwin for AArch64';
+            shortname    : 'Darwin';
+            flags        : [tf_p_ext_support,tf_requires_proper_alignment,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_default,tf_has_winlike_resources];
+            cpu          : cpu_aarch64;
+            unit_env     : 'BSDUNITS';
+            extradefines : 'UNIX;BSD;HASUNIX';
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.s';
+            objext       : '.o';
+            resext       : '.res';
+            resobjext    : '.or';
+            sharedlibext : '.dylib';
+            staticlibext : '.a';
+            staticlibprefix : 'libp';
+            sharedlibprefix : 'lib';
+            sharedClibext : '.dylib';
+            staticClibext : '.a';
+            staticClibprefix : 'lib';
+            sharedClibprefix : 'lib';
+            importlibprefix : 'libimp';
+            importlibext : '.a';
+            Cprefix      : '_';
+            newline      : #10;
+            dirsep       : '/';
+            assem        : as_clang;
+            assemextern  : as_clang;
+            link         : ld_none;
+            linkextern   : ld_bsd;
+            ar           : ar_gnu_ar;
+            res          : res_macho;
+            dbg          : dbg_dwarf2;
+            script       : script_unix;
+            endian       : endian_little;
+            alignment    :
+              (
+                procalign       : 8;
+                loopalign       : 4;
+                jumpalign       : 0;
+                constalignmin   : 0;
+                constalignmax   : 8;
+                varalignmin     : 0;
+                varalignmax     : 16;
+                localalignmin   : 4;
+                localalignmax   : 16;
+                recordalignmin  : 0;
+                recordalignmax  : 16;
+                maxCrecordalign : 16
+              );
+            first_parm_offset : 16;
+            stacksize   : 8*1024*1024;
+            stackalign   : 16;
+            abi : abi_aarch64_darwin;
+          );
+
+
+
   implementation
 
 initialization
@@ -1071,4 +1199,9 @@ initialization
      set_source_info(system_arm_darwin_info);
   {$endif Darwin}
 {$endif cpuarm}
+{$ifdef cpuaarch64}
+  {$ifdef Darwin}
+     set_source_info(system_aarch64_darwin_info);
+  {$endif Darwin}
+{$endif cpuaarch64}
 end.
index 258bf2815e9c41eb51b57f50854df53b4e5a424a..6fe976397d7a7d0cd244f40ebf29d2acc0fb2080 100644 (file)
@@ -811,6 +811,73 @@ unit i_linux;
 {$endif FPC_ARMEL}
 {$endif FPC_ARMHF}
 
+       system_aarch64_linux_info  : tsysteminfo =
+          (
+            system       : system_aarch64_linux;
+            name         : 'Linux for AArch64';
+            shortname    : 'Linux';
+            flags        : [tf_needs_symbol_size,
+                            tf_needs_symbol_type,
+                            tf_files_case_sensitive,
+                            tf_requires_proper_alignment,
+                            tf_smartlink_sections,tf_pic_uses_got,
+                            tf_has_winlike_resources];
+            cpu          : cpu_aarch64;
+            unit_env     : 'LINUXUNITS';
+            extradefines : 'UNIX;HASUNIX';
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.s';
+            objext       : '.o';
+            resext       : '.res';
+            resobjext    : '.or';
+            sharedlibext : '.so';
+            staticlibext : '.a';
+            staticlibprefix : 'libp';
+            sharedlibprefix : 'lib';
+            sharedClibext : '.so';
+            staticClibext : '.a';
+            staticClibprefix : 'lib';
+            sharedClibprefix : 'lib';
+            importlibprefix : 'libimp';
+            importlibext : '.a';
+            Cprefix      : '';
+            newline      : #10;
+            dirsep       : '/';
+            assem        : as_gas;
+            assemextern  : as_gas;
+            link         : ld_none;
+            linkextern   : ld_linux;
+            ar           : ar_gnu_ar;
+            res          : res_elf;
+            dbg          : dbg_dwarf2;
+            script       : script_unix;
+            endian       : endian_little;
+            alignment    :
+              (
+                procalign       : 8;
+                loopalign       : 4;
+                jumpalign       : 0;
+                constalignmin   : 0;
+                constalignmax   : 8;
+                varalignmin     : 0;
+                varalignmax     : 16;
+                localalignmin   : 4;
+                localalignmax   : 16;
+                recordalignmin  : 0;
+                recordalignmax  : 16;
+                maxCrecordalign : 16
+              );
+            first_parm_offset : 16;
+            stacksize    : 8*1024*1024;
+            stackalign   : 16;
+            abi : abi_default;
+          );
+
        system_mipseb_linux_info : tsysteminfo =
           (
             system       : system_mipseb_LINUX;
@@ -987,6 +1054,11 @@ initialization
     set_source_info(system_arm_linux_info);
   {$endif linux}
 {$endif CPUARM}
+{$ifdef cpuaarch64}
+  {$ifdef linux}
+    set_source_info(system_aarch64_linux_info);
+  {$endif linux}
+{$endif cpuaarch64}
 {$ifdef CPUMIPSEB}
   {$ifdef linux}
     set_source_info(system_mipseb_linux_info);
index ff73b431a696a72a56cf3e6444ea05ec133ff349..1d2f783861c5bfc585c19968328bb83459ffdb38 100644 (file)
@@ -198,7 +198,7 @@ unit i_win;
             Cprefix      : '';
             newline      : #13#10;
             dirsep       : '\';
-            assem        : as_gas;
+            assem        : as_arm_pecoffwince;
             assemextern  : as_gas;
             link         : ld_int_windows;
             linkextern   : ld_windows;
index b35a78aecbd2360416f511d02b360d113ea1d959..e4146157234a199ecd19cfc21e77fa1270c6e4f0 100644 (file)
@@ -230,28 +230,49 @@ begin
     begin
       if not(cs_profile in current_settings.moduleswitches) then
         begin
-          { 10.8 and later: no crt1.* }
-          if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
-            exit('');
-          { x86: crt1.10.6.o -> crt1.10.5.o -> crt1.o }
-          { others: crt1.10.5 -> crt1.o }
-{$if defined(i386) or defined(x86_64)}
-          if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
-            exit('crt1.10.6.o');
-{$endif}
-          if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
-            exit('crt1.10.5.o');
-{$if defined(arm)}
-          { iOS:
-              iOS 6 and later: nothing
-              iOS 3.1 - 5.x: crt1.3.1.o
-              pre-iOS 3.1: crt1.o
-          }
-          if (CompareVersionStrings(iPhoneOSVersionMin,'6.0')>=0) then
-            exit('');
-          if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
-            exit('crt1.3.1.o');
-{$endif}
+          case target_info.system of
+            system_powerpc_darwin,
+            system_powerpc64_darwin,
+            system_i386_darwin,
+            system_x86_64_darwin:
+              begin
+                { 10.8 and later: no crt1.* }
+                if CompareVersionStrings(MacOSXVersionMin,'10.8')>=0 then
+                  exit('');
+                { x86: crt1.10.6.o -> crt1.10.5.o -> crt1.o }
+                { others: crt1.10.5 -> crt1.o }
+                if (target_info.system in [system_i386_darwin,system_x86_64_darwin]) and
+                   (CompareVersionStrings(MacOSXVersionMin,'10.6')>=0) then
+                  exit('crt1.10.6.o');
+                if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
+                  exit('crt1.10.5.o');
+              end;
+            system_arm_darwin:
+              begin
+                { iOS:
+                    iOS 6 and later: nothing
+                    iOS 3.1 - 5.x: crt1.3.1.o
+                    pre-iOS 3.1: crt1.o
+                }
+                if (CompareVersionStrings(iPhoneOSVersionMin,'6.0')>=0) then
+                  exit('');
+                if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
+                  exit('crt1.3.1.o');
+              end;
+            system_i386_iphonesim,
+            system_x86_64_iphonesim:
+              begin
+                { "recent versions" must not use anything (https://github.com/llvm-mirror/clang/commit/e6d04f3d152a22077022cf9287d4c538a0918ab0 )
+                  What those recent versions could be, is anyone's guess. It
+                  still seems to work with 8.1 and no longer with 8.3, so use
+                  8.1 as a cut-off point }
+                if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
+                  exit('');
+              end;
+            system_aarch64_darwin:
+              { never anything }
+              exit('');
+          end;
           { nothing special -> default }
           result:='crt1.o';
         end
@@ -268,34 +289,68 @@ begin
     begin
       if (apptype=app_bundle) then
         begin
-          { < 10.6: bundle1.o
-            >= 10.6: nothing }
-          if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
-            exit('');
-          { iOS: < 3.1: bundle1.o
-                 >= 3.1: nothing }
-{$if defined(arm)}
-          if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
-            exit('');
-{$endif}
+          case target_info.system of
+            system_powerpc_darwin,
+            system_powerpc64_darwin,
+            system_i386_darwin,
+            system_x86_64_darwin:
+              begin
+                { < 10.6: bundle1.o
+                  >= 10.6: nothing }
+                if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
+                  exit('');
+              end;
+            system_arm_darwin,
+            system_aarch64_darwin:
+              begin
+                { iOS: < 3.1: bundle1.o
+                       >= 3.1: nothing }
+                if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
+                  exit('');
+              end;
+            system_i386_iphonesim,
+            system_x86_64_iphonesim:
+              begin
+                { see rule for crt1.o }
+                if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
+                  exit('');
+              end;
+          end;
           result:='bundle1.o';
         end
       else
         begin
-          { >= 10.6: nothing
-            = 10.5: dylib1.10.5.o
-            < 10.5: dylib1.o
-          }
-          if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
-            exit('');
-          if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
-            exit('dylib1.10.5.o');
-          { iOS: < 3.1: dylib1.o
-                 >= 3.1: nothing }
-{$if defined(arm)}
-          if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
-            exit('');
-{$endif}
+          case target_info.system of
+            system_powerpc_darwin,
+            system_powerpc64_darwin,
+            system_i386_darwin,
+            system_x86_64_darwin:
+              begin
+                { >= 10.6: nothing
+                  = 10.5: dylib1.10.5.o
+                  < 10.5: dylib1.o
+                }
+                if CompareVersionStrings(MacOSXVersionMin,'10.6')>=0 then
+                  exit('');
+                if CompareVersionStrings(MacOSXVersionMin,'10.5')>=0 then
+                  exit('dylib1.10.5.o');
+              end;
+            system_arm_darwin,
+            system_aarch64_darwin:
+              begin
+                { iOS: < 3.1: dylib1.o
+                       >= 3.1: nothing }
+                if (CompareVersionStrings(iPhoneOSVersionMin,'3.1')>=0) then
+                  exit('');
+              end;
+            system_i386_iphonesim,
+            system_x86_64_iphonesim:
+              begin
+                { see rule for crt1.o }
+                if (CompareVersionStrings(iPhoneOSVersionMin,'8.1')>0) then
+                  exit('');
+              end;
+          end;
           result:='dylib1.o';
         end;
     end;
@@ -417,12 +472,17 @@ begin
           LinkRes.Add('i386');
         system_powerpc64_darwin:
           LinkRes.Add('ppc64');
-        system_x86_64_darwin:
+        system_x86_64_darwin,
+        system_x86_64_iphonesim:
           LinkRes.Add('x86_64');
         system_arm_darwin:
           { current versions of the linker require the sub-architecture type
             to be specified }
           LinkRes.Add(lower(cputypestr[current_settings.cputype]));
+        system_aarch64_darwin:
+          LinkRes.Add('arm64');
+        else
+          internalerror(2014121801);
       end;
       if MacOSXVersionMin<>'' then
         begin
@@ -934,6 +994,9 @@ initialization
   RegisterImport(system_x86_64_darwin,timportlibdarwin);
   RegisterExport(system_x86_64_darwin,texportlibdarwin);
   RegisterTarget(system_x86_64_darwin_info);
+  RegisterImport(system_x86_64_iphonesim,timportlibdarwin);
+  RegisterExport(system_x86_64_iphonesim,texportlibdarwin);
+  RegisterTarget(system_x86_64_iphonesim_info);
 {$endif}
 {$ifdef i386}
   RegisterImport(system_i386_freebsd,timportlibbsd);
@@ -976,6 +1039,11 @@ initialization
   RegisterExport(system_arm_darwin,texportlibdarwin);
   RegisterTarget(system_arm_darwin_info);
 {$endif arm}
+{$ifdef aarch64}
+  RegisterImport(system_aarch64_darwin,timportlibdarwin);
+  RegisterExport(system_aarch64_darwin,texportlibdarwin);
+  RegisterTarget(system_aarch64_darwin_info);
+{$endif aarch64}
 
   RegisterRes(res_elf_info,TWinLikeResourceFile);
   RegisterRes(res_macho_info,TWinLikeResourceFile);
index ed0161c7fd9d0728e41c6362d82232d3d20d0b55..0342bc992c2d717c0c7f070d23c839e216087fdb 100644 (file)
@@ -198,6 +198,10 @@ end;
 {$endif FPC_ARMHF}
 {$endif arm}
 
+{$ifdef aarch64}
+const defdynlinker='/lib/ld-linux-aarch64.so.1';
+{$endif aarch64}
+
 {$ifdef mips}
   const defdynlinker='/lib/ld.so.1';
 {$endif mips}
@@ -288,6 +292,7 @@ const
 {$ifdef POWERPC64} platform_select='-b elf64-powerpc -m elf64ppc';{$endif}
 {$ifdef sparc}     platform_select='-b elf32-sparc -m elf32_sparc';{$endif}
 {$ifdef arm}       platform_select='';{$endif} {unknown :( }
+{$ifdef aarch64}   platform_select='';{$endif} {unknown :( }
 {$ifdef m68k}      platform_select='';{$endif} {unknown :( }
 {$ifdef mips}
   {$ifdef mipsel}  
@@ -712,6 +717,236 @@ begin
       add('}');
 {$endif x86_64}
 
+{$ifdef AArch64}
+{$define LINKERSCRIPT_INCLUDED}
+      if isdll or (sysrootpath='') then begin
+        { On other architectures, supplying a complete linker script
+          without the -T option just results in:
+            warning: link.res contains output sections; did you forget -T?
+          However, with a recent aarch64 linker the result is:
+            /usr/bin/ld: internal error ../../ld/ldlang.c 5221
+          So in these cases, where -T will not be used, we supply a
+          minimal linker script with just the FPC-specific part: }
+        add('SECTIONS');
+        add('{');
+        add('  .data           :');
+        add('  {');
+        { extra by FPC }
+        add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+        add('  }');
+        add('}');
+      end else begin
+        { Complete linker script for aarch64-linux: }
+        add('SECTIONS');
+        add('{');
+        add('  /* Read-only sections, merged into text segment: */');
+        add('  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;');
+        add('  .interp         : { *(.interp) }');
+        add('  .note.gnu.build-id : { *(.note.gnu.build-id) }');
+        add('  .hash           : { *(.hash) }');
+        add('  .gnu.hash       : { *(.gnu.hash) }');
+        add('  .dynsym         : { *(.dynsym) }');
+        add('  .dynstr         : { *(.dynstr) }');
+        add('  .gnu.version    : { *(.gnu.version) }');
+        add('  .gnu.version_d  : { *(.gnu.version_d) }');
+        add('  .gnu.version_r  : { *(.gnu.version_r) }');
+        add('  .rela.dyn       :');
+        add('    {');
+        add('      *(.rela.init)');
+        add('      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
+        add('      *(.rela.fini)');
+        add('      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
+        add('      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
+        add('      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
+        add('      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
+        add('      *(.rela.ctors)');
+        add('      *(.rela.dtors)');
+        add('      *(.rela.got)');
+        add('      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
+        add('      *(.rela.ifunc)');
+        add('    }');
+        add('  .rela.plt       :');
+        add('    {');
+        add('      *(.rela.plt)');
+        add('      PROVIDE_HIDDEN (__rela_iplt_start = .);');
+        add('      *(.rela.iplt)');
+        add('      PROVIDE_HIDDEN (__rela_iplt_end = .);');
+        add('    }');
+        add('  .init           :');
+        add('  {');
+        add('    KEEP (*(SORT_NONE(.init)))');
+        add('  } =0');
+        add('  .plt            : ALIGN(16) { *(.plt) *(.iplt) }');
+        add('  .text           :');
+        add('  {');
+        add('    *(.text.unlikely .text.*_unlikely .text.unlikely.*)');
+        add('    *(.text.exit .text.exit.*)');
+        add('    *(.text.startup .text.startup.*)');
+        add('    *(.text.hot .text.hot.*)');
+        add('    *(.text .stub .text.* .gnu.linkonce.t.*)');
+        add('    /* .gnu.warning sections are handled specially by elf32.em.  */');
+        add('    *(.gnu.warning)');
+        add('  } =0');
+        add('  .fini           :');
+        add('  {');
+        add('    KEEP (*(SORT_NONE(.fini)))');
+        add('  } =0');
+        add('  PROVIDE (__etext = .);');
+        add('  PROVIDE (_etext = .);');
+        add('  PROVIDE (etext = .);');
+        add('  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }');
+        add('  .rodata1        : { *(.rodata1) }');
+        add('  .eh_frame_hdr : { *(.eh_frame_hdr) }');
+        add('  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }');
+        add('  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table');
+        add('  .gcc_except_table.*) }');
+        add('  /* These sections are generated by the Sun/Oracle C++ compiler.  */');
+        add('  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges');
+        add('  .exception_ranges*) }');
+        add('  /* Adjust the address for the data segment.  We want to adjust up to');
+        add('     the same address within the page on the next page up.  */');
+        add('  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));');
+        add('  /* Exception handling  */');
+        add('  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }');
+        add('  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }');
+        add('  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }');
+        add('  /* Thread Local Storage sections  */');
+        add('  .tdata          : { *(.tdata .tdata.* .gnu.linkonce.td.*) }');
+        add('  .tbss           : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }');
+        add('  .preinit_array     :');
+        add('  {');
+        add('    PROVIDE_HIDDEN (__preinit_array_start = .);');
+        add('    KEEP (*(.preinit_array))');
+        add('    PROVIDE_HIDDEN (__preinit_array_end = .);');
+        add('  }');
+        add('  .init_array     :');
+        add('  {');
+        add('    PROVIDE_HIDDEN (__init_array_start = .);');
+        add('    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))');
+        add('    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))');
+        add('    PROVIDE_HIDDEN (__init_array_end = .);');
+        add('  }');
+        add('  .fini_array     :');
+        add('  {');
+        add('    PROVIDE_HIDDEN (__fini_array_start = .);');
+        add('    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))');
+        add('    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))');
+        add('    PROVIDE_HIDDEN (__fini_array_end = .);');
+        add('  }');
+        add('  .ctors          :');
+        add('  {');
+        add('    /* gcc uses crtbegin.o to find the start of');
+        add('       the constructors, so we make sure it is');
+        add('       first.  Because this is a wildcard, it');
+        add('       doesn''t matter if the user does not');
+        add('       actually link against crtbegin.o; the');
+        add('       linker won''t look for a file to match a');
+        add('       wildcard.  The wildcard also means that it');
+        add('       doesn''t matter which directory crtbegin.o');
+        add('       is in.  */');
+        add('    KEEP (*crtbegin.o(.ctors))');
+        add('    KEEP (*crtbegin?.o(.ctors))');
+        add('    /* We don''t want to include the .ctor section from');
+        add('       the crtend.o file until after the sorted ctors.');
+        add('       The .ctor section from the crtend file contains the');
+        add('       end of ctors marker and it must be last */');
+        add('    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))');
+        add('    KEEP (*(SORT(.ctors.*)))');
+        add('    KEEP (*(.ctors))');
+        add('  }');
+        add('  .dtors          :');
+        add('  {');
+        add('    KEEP (*crtbegin.o(.dtors))');
+        add('    KEEP (*crtbegin?.o(.dtors))');
+        add('    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))');
+        add('    KEEP (*(SORT(.dtors.*)))');
+        add('    KEEP (*(.dtors))');
+        add('  }');
+        add('  .jcr            : { KEEP (*(.jcr)) }');
+        add('  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }');
+        add('  .dynamic        : { *(.dynamic) }');
+        add('  .got            : { *(.got) *(.igot) }');
+        add('  . = DATA_SEGMENT_RELRO_END (24, .);');
+        add('  .got.plt        : { *(.got.plt)  *(.igot.plt) }');
+        add('  .data           :');
+        add('  {');
+        add('    PROVIDE (__data_start = .);');
+
+        { extra by FPC }
+        add('    KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+
+        add('    *(.data .data.* .gnu.linkonce.d.*)');
+        add('    SORT(CONSTRUCTORS)');
+        add('  }');
+        add('  .data1          : { *(.data1) }');
+        add('  _edata = .; PROVIDE (edata = .);');
+        add('  . = .;');
+        add('  __bss_start = .;');
+        add('  __bss_start__ = .;');
+        add('  .bss            :');
+        add('  {');
+        add('   *(.dynbss)');
+        add('   *(.bss .bss.* .gnu.linkonce.b.*)');
+        add('   *(COMMON)');
+        add('   /* Align here to ensure that the .bss section occupies space up to');
+        add('      _end.  Align after .bss to ensure correct alignment even if the');
+        add('      .bss section disappears because there are no input sections.');
+        add('      FIXME: Why do we need it? When there is no .bss section, we don''t');
+        add('      pad the .data section.  */');
+        add('   . = ALIGN(. != 0 ? 64 / 8 : 1);');
+        add('  }');
+        add('  _bss_end__ = . ; __bss_end__ = . ;');
+        add('  . = ALIGN(64 / 8);');
+        add('  . = SEGMENT_START("ldata-segment", .);');
+        add('  . = ALIGN(64 / 8);');
+        add('  __end__ = . ;');
+        add('  _end = .; PROVIDE (end = .);');
+        add('  . = DATA_SEGMENT_END (.);');
+        add('  /* Stabs debugging sections.  */');
+        add('  .stab          0 : { *(.stab) }');
+        add('  .stabstr       0 : { *(.stabstr) }');
+        add('  .stab.excl     0 : { *(.stab.excl) }');
+        add('  .stab.exclstr  0 : { *(.stab.exclstr) }');
+        add('  .stab.index    0 : { *(.stab.index) }');
+        add('  .stab.indexstr 0 : { *(.stab.indexstr) }');
+        add('  .comment       0 : { *(.comment) }');
+        add('  /* DWARF debug sections.');
+        add('     Symbols in the DWARF debugging sections are relative to the beginning');
+        add('     of the section so we begin them at 0.  */');
+        add('  /* DWARF 1 */');
+        add('  .debug          0 : { *(.debug) }');
+        add('  .line           0 : { *(.line) }');
+        add('  /* GNU DWARF 1 extensions */');
+        add('  .debug_srcinfo  0 : { *(.debug_srcinfo) }');
+        add('  .debug_sfnames  0 : { *(.debug_sfnames) }');
+        add('  /* DWARF 1.1 and DWARF 2 */');
+        add('  .debug_aranges  0 : { *(.debug_aranges) }');
+        add('  .debug_pubnames 0 : { *(.debug_pubnames) }');
+        add('  /* DWARF 2 */');
+        add('  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }');
+        add('  .debug_abbrev   0 : { *(.debug_abbrev) }');
+        add('  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }');
+        add('  .debug_frame    0 : { *(.debug_frame) }');
+        add('  .debug_str      0 : { *(.debug_str) }');
+        add('  .debug_loc      0 : { *(.debug_loc) }');
+        add('  .debug_macinfo  0 : { *(.debug_macinfo) }');
+        add('  /* SGI/MIPS DWARF 2 extensions */');
+        add('  .debug_weaknames 0 : { *(.debug_weaknames) }');
+        add('  .debug_funcnames 0 : { *(.debug_funcnames) }');
+        add('  .debug_typenames 0 : { *(.debug_typenames) }');
+        add('  .debug_varnames  0 : { *(.debug_varnames) }');
+        add('  /* DWARF 3 */');
+        add('  .debug_pubtypes 0 : { *(.debug_pubtypes) }');
+        add('  .debug_ranges   0 : { *(.debug_ranges) }');
+        add('  /* DWARF Extension.  */');
+        add('  .debug_macro    0 : { *(.debug_macro) }');
+        add('  .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }');
+        add('  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }');
+        add('  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }');
+        add('}');
+      end;
+{$endif AArch64}
+
 {$ifdef ARM}
       if target_info.abi in [abi_eabi,abi_eabihf] then
         begin
@@ -1553,6 +1788,11 @@ initialization
   RegisterExport(system_arm_linux,texportliblinux);
   RegisterTarget(system_arm_linux_info);
 {$endif ARM}
+{$ifdef aarch64}
+  RegisterImport(system_aarch64_linux,timportliblinux);
+  RegisterExport(system_aarch64_linux,texportliblinux);
+  RegisterTarget(system_aarch64_linux_info);
+{$endif aarch64}
 {$ifdef MIPS}
 {$ifdef MIPSEL}
   RegisterImport(system_mipsel_linux,timportliblinux);
index 6c47ba2ad0474e012676a18e8f9f474cb89c54cb..de49cb6f636ebb9ad8c187afc390f0a130da08f6 100644 (file)
@@ -179,7 +179,7 @@ implementation
        tempfreelist:=nil;
        templist:=nil;
        { we could create a new child class for this but I don't if it is worth the effort (FK) }
-{$if defined(powerpc) or defined(powerpc64) or defined(avr) or defined(jvm)}
+{$if defined(powerpc) or defined(powerpc64) or defined(avr) or defined(jvm) or defined(aarch64)}
        direction:=1;
 {$else}
        direction:=-1;
index 9c4ce7ac949a1e598608eaeaca2acf4d02c4db45..2000c78fc3edbdf712aebfbb84c0d2399b76154e 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 [target]
-programs=fpc ppufiles ppudump ppumove mkarmins mkx86ins
+programs=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
 rst=fpcsubst
 
 [clean]
index 7da8dd2e1afa79b3184c45141f71108603896118..ad79833bdfdf84810add33171a44564641b1aab7 100644 (file)
@@ -143,6 +143,10 @@ program fpc;
      ppcbin:='ppcarm';
      processorname:='arm';
 {$endif arm}
+{$ifdef aarch64}
+     ppcbin:='ppca64';
+     processorname:='aarch64';
+{$endif arm}
 {$ifdef sparc}
      ppcbin:='ppcsparc';
      processorname:='sparc';
@@ -202,7 +206,9 @@ program fpc;
                      else
                        if processorstr <> processorname then
                          begin
-                           if processorstr='arm' then
+                           if processorstr='aarch64' then
+                             cpusuffix:='a64'
+                           else if processorstr='arm' then
                              cpusuffix:='arm'
                            else if processorstr='i386' then
                              cpusuffix:='386'
index 4edc87f4e38ef23cf5c431458f6920223f512e88..8ac0d1090a32204cc9c1617feb53b2ad4ff270b6 100644 (file)
@@ -14,7 +14,7 @@
  **********************************************************************}
 {$mode objfpc}
 
-program mkarmins;
+program mka64ins;
 
 const
   Version = '0.9';
@@ -153,7 +153,7 @@ begin
   writeln('creating ',fn);
   assign(f,fn);
   rewrite(f);
-  writeln(f,'{ don''t edit, this file is generated from armins.dat }');
+  writeln(f,'{ don''t edit, this file is generated from a64ins.dat }');
   writeln(f,'(');
 end;
 
index b8b90671200f476fd3a83250b68bf83a412b7492..ad423285e5c0368b3ef0f5cc8f7fe95b0a6b039c 100644 (file)
@@ -186,7 +186,7 @@ var
    opcode,
    codes,
    flags   : string;
-   optypes : array[1..4] of string;
+   optypes : array[1..6] of string;
 begin
    writeln('Narm Instruction Table Converter Version ',Version);
    insns:=0;
@@ -298,6 +298,8 @@ begin
         optypes[2]:='';
         optypes[3]:='';
         optypes[4]:='';
+        optypes[5]:='';
+        optypes[6]:='';
         codes:='';
         flags:='';
         skip:=false;
@@ -324,8 +326,8 @@ begin
           else
             break;
         until false;
-        for j:=1 to 4-ops do
-          optypes[4-j+1]:='ot_none';
+        for j:=1 to 6-ops do
+          optypes[6-j+1]:='ot_none';
         { codes }
         skipspace;
         j:=0;
@@ -385,7 +387,7 @@ begin
             writeln(insfile,'  (');
             writeln(insfile,'    opcode  : ',opcode,';');
             writeln(insfile,'    ops     : ',ops,';');
-            writeln(insfile,'    optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
+            writeln(insfile,'    optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],',',optypes[5],',',optypes[6],');');
             writeln(insfile,'    code    : ',codes,';');
             writeln(insfile,'    flags   : ',flags);
             write(insfile,'  )');
index 0eed7fa1bf57a264b0180213770e2d84a65a72fc..ae2aef8d2e98ff56a849fc70ea625aa92539a297 100644 (file)
@@ -76,7 +76,8 @@ const
     { 12 } 'avr',
     { 13 } 'mipsel',
     { 14 } 'jvm',
-    { 15 } 'i8086'
+    { 15 } 'i8086',
+    { 16 } 'aarch64'
     );
 
 { List of all supported system-cpu couples }
@@ -109,7 +110,7 @@ const
   { 24 }  'OpenBSD-i386',
   { 25 }  'OpenBSD-m68k',
   { 26 }  'Linux-x86-64',
-  { 27 }  'MacOSX-ppc',
+  { 27 }  'Darwin-ppc',
   { 28 }  'OS/2 via EMX',
   { 29 }  'NetBSD-powerpc',
   { 30 }  'OpenBSD-powerpc',
@@ -128,7 +129,7 @@ const
   { 43 }  'Linux-powerpc64',
   { 44 }  'Darwin-i386',
   { 45 }  'PalmOS-arm',
-  { 46 }  'MacOSX-powerpc64',
+  { 46 }  'Darwin-powerpc64',
   { 47 }  'NDS-arm',
   { 48 }  'Embedded-i386',
   { 49 }  'Embedded-m68k',
@@ -143,7 +144,7 @@ const
   { 58 }  'Embedded-powerpc64',
   { 59 }  'Symbian-i386',
   { 60 }  'Symbian-arm',
-  { 61 }  'MacOSX-x64',
+  { 61 }  'Darwin-x64',
   { 62 }  'Embedded-avr',
   { 63 }  'Haiku-i386',
   { 64 }  'Darwin-ARM',
@@ -167,7 +168,10 @@ const
   { 82 }  'Embedded-mipsel',
   { 83 }  'AROS-i386',
   { 84 }  'AROS-x86-64',
-  { 85 }  'DragonFly-x86-64'
+  { 85 }  'DragonFly-x86-64',
+  { 86 }  'Darwin-AArch64',
+  { 87 }  'iPhoneSim-x86-64',
+  { 88 }  'Linux-AArch64'
   );
 
 const
index 0e859683792e8db4f0b4d1d59cd8c542325aadfa..8c7f14a50826e9ab409321dd90e9fdcc69af0de6 100644 (file)
@@ -77,6 +77,9 @@ interface
 {$ifdef cpumipsel}
         source_cpu_string = 'mipsel';
 {$endif cpumipsel}
+{$ifdef cpuaarch64}
+        source_cpu_string = 'aarch64';
+{$endif cpuaarch64}
 
 function version_string:string;
 function full_version_string:string;
index d3fbdae09c8f1a01bfd62988dce7620d79b68cca..0b5dc2cf54a75403b84cf2a703a5f1ebaaa22ea2 100644 (file)
@@ -511,7 +511,7 @@ interface
             idtxt  : 'AS-DARWIN';
             asmbin : 'as';
             asmcmd : '-o $OBJ $EXTRAOPT $ASM -arch x86_64';
-            supported_targets : [system_x86_64_darwin];
+            supported_targets : [system_x86_64_darwin,system_x86_64_iphonesim];
             flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
             labelprefix : 'L';
             comment : '# ';
@@ -524,7 +524,7 @@ interface
             idtxt  : 'CLANG';
             asmbin : 'clang';
             asmcmd : '-c -o $OBJ $EXTRAOPT -arch x86_64 $DARWINVERSION -x assembler $ASM';
-            supported_targets : [system_x86_64_darwin];
+            supported_targets : [system_x86_64_darwin,system_x86_64_iphonesim];
             flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
             labelprefix : 'L';
             comment : '# ';
index 02a79bbcd65a8fa6fad865c41a55a0d2bf22a061..744610759033c8874811b915644fac94601e4a96 100644 (file)
@@ -82,7 +82,7 @@ unit cgx86;
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
 
         { bit scan instructions }
-        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister); override;
 
         { fpu move instructions }
         procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
@@ -507,7 +507,7 @@ unit cgx86;
               end
             else
               { Always use RIP relative symbol addressing for Windows and Darwin targets. }
-              if (target_info.system in (systems_all_windows+[system_x86_64_darwin])) and (ref.base<>NR_RIP) then
+              if (target_info.system in (systems_all_windows+[system_x86_64_darwin,system_x86_64_iphonesim])) and (ref.base<>NR_RIP) then
                 begin
                   if (ref.refaddr=addr_no) and (ref.base=NR_NO) and (ref.index=NR_NO) then
                     begin
@@ -810,7 +810,7 @@ unit cgx86;
             reference_reset_symbol(r,sym,0,sizeof(pint));
             if (cs_create_pic in current_settings.moduleswitches) and
                { darwin's assembler doesn't want @PLT after call symbols }
-               not(target_info.system in [system_x86_64_darwin,system_i386_iphonesim]) then
+               not(target_info.system in [system_x86_64_darwin,system_i386_iphonesim,system_x86_64_iphonesim]) then
               begin
 {$ifdef i386}
                 include(current_procinfo.flags,pi_needs_got);
@@ -1048,7 +1048,7 @@ unit cgx86;
                           a_op_const_reg(list,OP_ADD,OS_ADDR,offset,r);
                       end
 {$ifdef x86_64}
-                    else if (target_info.system in (systems_all_windows+[system_x86_64_darwin]))
+                    else if (target_info.system in (systems_all_windows+[system_x86_64_darwin,system_x86_64_iphonesim]))
                         or (cs_create_pic in current_settings.moduleswitches)
                         then
                       begin
@@ -2012,20 +2012,36 @@ unit cgx86;
         end;
       end;
 
-     procedure tcgx86.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+     procedure tcgx86.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister);
      var
+       tmpreg: tregister;
        opsize: topsize;
        l : TAsmLabel;
      begin
-       opsize:=tcgsize2opsize[size];
+       { no bsf/bsr for byte }
+       if srcsize in [OS_8,OS_S8] then
+         begin
+           tmpreg:=getintregister(list,OS_INT);
+           a_load_reg_reg(list,srcsize,OS_INT,src,tmpreg);
+           src:=tmpreg;
+           srcsize:=OS_INT;
+         end;
+       { source and destination register must have the same size }
+       if tcgsize2size[srcsize]<>tcgsize2size[dstsize] then
+         tmpreg:=getintregister(list,srcsize)
+       else
+         tmpreg:=dst;
+       opsize:=tcgsize2opsize[srcsize];
        if not reverse then
-         list.concat(taicpu.op_reg_reg(A_BSF,opsize,src,dst))
+         list.concat(taicpu.op_reg_reg(A_BSF,opsize,src,tmpreg))
        else
-         list.concat(taicpu.op_reg_reg(A_BSR,opsize,src,dst));
+         list.concat(taicpu.op_reg_reg(A_BSR,opsize,src,tmpreg));
        current_asmdata.getjumplabel(l);
        a_jmp_cond(list,OC_NE,l);
-       list.concat(taicpu.op_const_reg(A_MOV,opsize,$ff,dst));
+       list.concat(taicpu.op_const_reg(A_MOV,opsize,$ff,tmpreg));
        a_label(list,l);
+       if tmpreg<>dst then
+         a_load_reg_reg(list,srcsize,dstsize,tmpreg,dst);
      end;
 
 {*************** compare instructructions ****************}
@@ -2690,7 +2706,8 @@ unit cgx86;
                a_call_name(list,'MCOUNT',false);
              end;
            system_x86_64_linux,
-           system_x86_64_darwin:
+           system_x86_64_darwin,
+           system_x86_64_iphonesim:
              begin
                a_call_name(list,'mcount',false);
              end;
@@ -3044,7 +3061,7 @@ unit cgx86;
         { create pic'ed? }
         if (cs_create_pic in current_settings.moduleswitches) and
            { darwin/x86_64's assembler doesn't want @PLT after call symbols }
-           not(target_info.system in [system_x86_64_darwin,system_i386_iphonesim]) then
+           not(target_info.system in [system_x86_64_darwin,system_i386_iphonesim,system_x86_64_iphonesim]) then
           ref.refaddr:=addr_pic
         else
           ref.refaddr:=addr_full;
index 40cb3e3bc662ac3bf1f356b1bef8a6f49d0eae2f..f4a371e11de02869960d7010c649b4b367865474 100644 (file)
@@ -27,6 +27,7 @@ interface
     uses
       globtype,
       cgbase,cpuinfo,cpubase,
+      symtype,
       node,nmem,ncgmem;
 
     type
@@ -35,7 +36,7 @@ interface
       end;
 
       tx86vecnode = class(tcgvecnode)
-        procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);override;
+        procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);override;
       end;
 
 implementation
@@ -86,7 +87,7 @@ implementation
      { the live range of the LOC_CREGISTER will most likely overlap the   }
      { the live range of the target LOC_(C)REGISTER)                      }
      { The passed register may be a LOC_CREGISTER as well.                }
-     procedure tx86vecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+     procedure tx86vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
        var
          l2 : integer;
          hreg : tregister;
index d702844f4fac90976568e974314af440c4631cea..8bb4a446e4a975cf4b2ea1ca808a7a3a9e0963f0 100644 (file)
@@ -476,7 +476,7 @@ unit cgcpu;
             reference_reset_symbol(r,sym,0,sizeof(pint));
             if (cs_create_pic in current_settings.moduleswitches) and
                { darwin/x86_64's assembler doesn't want @PLT after call symbols }
-               (target_info.system<>system_x86_64_darwin) then
+               not(target_info.system in systems_darwin) then
               r.refaddr:=addr_pic
             else
               r.refaddr:=addr_full;
index baaec487d037395225094956530c86dfe6729cea..9a3d8d87b6694e43ff2211e314a0fc296932b6aa 100644 (file)
@@ -664,6 +664,7 @@ implementation
         encodereloc:       @elf_x86_64_encodeReloc;
         loadreloc:         @elf_x86_64_loadReloc;
         loadsection:       nil;
+        encodeflags:       nil;
       );
 
 
index 0395cb4a8fb53e83d03c0e9b192e25311e052810..037e5d8297f321eac8de7cc6170457feabbd03e4 100644 (file)
@@ -13,7 +13,7 @@ units=acceleratorsresource bitmapresource coffconsts coffreader cofftypes \
       groupresource icocurtypes machoconsts machoreader machotypes machowriter \
       resdatastream resfactory resmerger resource resourcetree resreader reswriter \
       stringtableresource strtable tlbreader versionconsts versionresource versiontypes \
-      winpeimagereader
+      winpeimagereader xcoffwriter
 rsts=versiontypes stringtableresource resource resfactory
 
 
index 5673950a3bda0ca1169f20243b500f1e20744ccf..1e7b7572c0d524977341e24730edffc61bd1439b 100644 (file)
@@ -22,7 +22,7 @@ interface
 type
   TElfMachineType = (emtnone, emtsparc, emti386, emtm68k, emtppc, emtppc64,
                      emtarm, emtarmeb, emtia64, emtx86_64, emtalpha,
-                     emtmips, emtmipsel);
+                     emtmips, emtmipsel, emtaarch64);
 const
   ELFMAGIC     = chr($7f)+'ELF';
 
@@ -71,6 +71,7 @@ const
   EM_IA_64       = 50;
   EM_MIPS_X      = 51; // GNU readelf returns machine name "Stanford MIPS-X"
   EM_X86_64      = 62;
+  EM_AARCH64     = 183;
   EM_ALPHA       = $9026; //unofficial, but used by gnu toolchain
   
   //machine-specific flags
@@ -130,6 +131,7 @@ const
   R_PPC_ADDR32    =   1;
   R_PPC64_ADDR64  =  38;
   R_ARM_ABS32     =   2;
+  R_AARCH64_ABS64 = 257;
   R_68K_32        =   1;
   R_SPARC_32      =   3;
   R_ALPHA_REFQUAD =   2;
index dec11858fe0592201388dcefaecb265f60f78e2c..aa94e988e8cb20e5914eaf7eb810fb29af1c9dbc 100644 (file)
@@ -33,6 +33,9 @@
     fMachineType:=emtarmeb;
     {$ENDIF}
   {$ENDIF}
+  {$IFDEF CPUAARCH64}
+  fMachineType:=emtaarch64;
+  {$ENDIF}
   {$IFDEF CPU68K}
   fMachineType:=emtm68k;
   {$ENDIF}
index 42159dd5a3c7958d9128527b3819a93e5a59c073..c6774a6ee6b0e3f3680a4f61ef75be46c65b8e24 100644 (file)
@@ -282,6 +282,7 @@ begin
                     fMachineType:=emtarm
                   else
                     fMachineType:=emtarmeb;
+      EM_AARCH64: fMachineType:=emtaarch64;
       EM_ALPHA  : fMachineType:=emtalpha;
       EM_IA_64  : fMachineType:=emtia64;
       EM_X86_64 : fMachineType:=emtx86_64;
index 3da0abfed1dd8d74ec77348ef86cd45fe08fa624..4a649b5d85ae755af4a7dfdb4cc8aa45a0755187 100644 (file)
@@ -27,7 +27,7 @@ type
   _TElfRelocTable_= class
   private
     fList : TFPList;
-    fRelocType : byte;
+    fRelocType : longword;
     fEntrySize : integer;
     fSectionType : integer;
     fSectionName : string;
@@ -418,6 +418,7 @@ begin
       EM_386    : begin RelocType:=R_386_32;        SectionType:=SHT_REL;  end;
       EM_PPC    : begin RelocType:=R_PPC_ADDR32;    SectionType:=SHT_RELA; end;
       EM_ARM    : begin RelocType:=R_ARM_ABS32;     SectionType:=SHT_REL;  end;
+      EM_AARCH64: begin RelocType:=R_AARCH64_ABS64; SectionType:=SHT_RELA; end;
       EM_68K    : begin RelocType:=R_68K_32;        SectionType:=SHT_RELA; end;
       EM_SPARC  : begin RelocType:=R_SPARC_32;      SectionType:=SHT_RELA; end;
       EM_X86_64 : begin RelocType:=R_x86_64_64;     SectionType:=SHT_RELA; end;
index 1a1e9d2b8e9489aa2279a360c925ca9672ffdfcc..eba1e8fe350f5116186d0afcf672edbd0a7d3034 100644 (file)
@@ -155,7 +155,7 @@ type
 
 type
   TElfRelocInfo = record
-    RelocType : byte;
+    RelocType : longword;
     SectionType : integer;
   end;
 (*
@@ -551,6 +551,7 @@ begin
     emtppc64  : begin fMachineTypeInt:=EM_PPC64; fBits:=ELFCLASS64; fOrder:=ELFDATA2MSB; end;
     emtarm    : begin fMachineTypeInt:=EM_ARM; fBits:=ELFCLASS32; fOrder:=ELFDATA2LSB; end;
     emtarmeb  : begin fMachineTypeInt:=EM_ARM; fBits:=ELFCLASS32; fOrder:=ELFDATA2MSB; end;
+    emtaarch64: begin fMachineTypeInt:=EM_AARCH64; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
     emtalpha  : begin fMachineTypeInt:=EM_ALPHA; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
     emtia64   : begin fMachineTypeInt:=EM_IA_64; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
     emtx86_64 : begin fMachineTypeInt:=EM_X86_64; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
index 7c99421c82ca59a7a26482123f1af714eb75055c..b952265edef13f5e40b7b8ff9fb62903c50a32a5 100644 (file)
@@ -48,6 +48,7 @@ const
   CPU_TYPE_I386      = 7;
   CPU_TYPE_X86_64    = CPU_TYPE_I386 or CPU_ARCH_ABI64;
   CPU_TYPE_ARM       = 12;
+  CPU_TYPE_ARM64     = CPU_TYPE_ARM or CPU_ARCH_ABI64;
   CPU_TYPE_POWERPC   = 18;
   CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC or CPU_ARCH_ABI64;
 
@@ -61,6 +62,8 @@ const
   CPU_SUBTYPE_ARM_V5TEJ   = 7;
   CPU_SUBTYPE_ARM_XSCALE  = 8;
   CPU_SUBTYPE_ARM_V7      = 9;
+  CPU_SUBTYPE_ARM64_ALL   = 0;
+  CPU_SUBTYPE_ARM64_V8    = 1;
 
   //Mach-O object types
   MH_OBJECT      = $1;            // relocatable object file
@@ -180,6 +183,8 @@ const
   N_SECT = $e;             // defined in section number n_sect
   N_PBUD = $c;             // prebound undefined (defined in a dylib)
   N_INDR = $a;             // indirect
+
+  NO_SECT = $0;            // symbol is not in any section
   
   //Relocations: masks for flag
   R_SYMBOLNUM_BE = $FFFFFF00;
@@ -206,6 +211,9 @@ const
   // relocation types - ARM
   ARM_RELOC_VANILLA = 0; // generic relocation
 
+  // relocation types - AARCH64
+  ARM64_RELOC_UNSIGNED = 0; // for pointers
+
 implementation
 
 end.
index 66b46a758afbe9697f364c9e885298db54b8624a..c1bc1c4eea9c71f34ce710bd90e5c1dc50ad2223 100644 (file)
@@ -29,6 +29,9 @@
   {$IFDEF CPUARM}
   fMachineType:=mmtarm;
   {$ENDIF}
+  {$IFDEF CPUAARCH64}
+  fMachineType:=mmtarm64;
+  {$ENDIF}
 
   fBits:=MACH_ERRBIT;
   {$IFDEF CPU32}
index 17f28e33bedb140bc4ead31cc13a7365c4a76812..7ebd608fff15ee48931ebfb7bd6fa325f1ddf5ab 100644 (file)
@@ -219,7 +219,8 @@ begin
     CPU_TYPE_X86_64    : fMachineType:=mmtx86_64;
     CPU_TYPE_POWERPC   : fMachineType:=mmtpowerpc;
     CPU_TYPE_POWERPC64 : fMachineType:=mmtpowerpc64;
-    CPU_TYPE_ARM       : fMachineType:=mmtarm
+    CPU_TYPE_ARM       : fMachineType:=mmtarm;
+    CPU_TYPE_ARM64     : fMachineType:=mmtarm64
     else exit;
   end;
   
index bb1194f0abce055a2fad117ae6b70c8be4f50c48..68287a296e87c81c90ffd838964a2494c40e7432 100644 (file)
@@ -17,10 +17,11 @@ type
   _TMachOSymbolTable_ = class(TMachOSymbolTable)
   protected
     function AddSymbol(aName : string; sect : byte; addr : longword;
-      glob : boolean) : integer; override;
+      glob, undef : boolean) : integer; override;
   protected
   public
     procedure WriteToStream(aStream : TStream); override;
+    procedure SetSymbolOffset(symbolnum : integer; offset: longword); override;
   end;
 
   _TMachOSubWriter_ = class(TAbstractMachOSubWriter)
@@ -34,7 +35,6 @@ type
     procedure AllocateSpaceForLoadCommands(aStream : TStream); override;
 
     procedure FixLoadCommands(aStream : TStream; aResources : TResources); override;
-    procedure FixResHeader(aStream : TStream); override;
   public
     constructor Create(aParent : TMachOResourceWriter; const aMachineType
       : TMachOMachineType; const aSubMachineType: TMachoSubMachineType;
@@ -44,13 +44,17 @@ type
 { _TMachOSymbolTable_ }
 
 function _TMachOSymbolTable_.AddSymbol(aName: string; sect: byte; addr: longword;
-  glob: boolean): integer;
+  glob, undef: boolean): integer;
 var p : _PNlist_;
 begin
   p:=GetMem(sizeof(_TNlist_));
   p^.strx:=fStringTable.Add(aName);
-  p^._type:=N_SECT;
-  if glob then p^._type:=p^._type or N_EXT;
+  if not undef then
+    p^._type:=N_SECT
+  else
+    p^._type:=N_UNDF;
+  if glob then
+    p^._type:=p^._type or N_EXT;
   p^.desc:=0;
   p^.sect:=sect;
   p^.value:=addr;
@@ -61,10 +65,20 @@ end;
 procedure _TMachOSymbolTable_.WriteToStream(aStream: TStream);
 var nlist : _TNlist_;
     i : integer;
+    sawglobal: boolean;
 begin
+  { first write local symbols, then global ones, as ilocalsym is hardcoded to
+    be index 0. Can't reorder here because we may already have used symbol
+    numbers to generate relocations -> give an error if a global symbol
+    comes before any local symbols }
+  sawglobal:=false;
   for i:=0 to fList.Count-1 do
   begin
     nlist:=_PNlist_(fList[i])^;
+    if (nlist._type and N_EXT)<>0 then
+      sawglobal:=true
+    else if sawglobal then
+      raise EMachOResourceWriterSymbolTableWrongOrderException.Create('');
     if fOppositeEndianess then
     begin
       nlist.strx:=SwapEndian(nlist.strx);
@@ -75,6 +89,14 @@ begin
   end;
 end;
 
+procedure _TMachOSymbolTable_.SetSymbolOffset(symbolnum: integer; offset: longword);
+var
+  p : _PNlist_;
+begin
+  p:=_PNlist_(flist[symbolnum]);
+  p^.value:=offset;
+end;
+
 { _TMachOSubWriter_ }
 
 procedure _TMachOSubWriter_.SwapSection(var aSection: _TSection_);
@@ -109,8 +131,13 @@ begin
   hdr.count:=aResources.Count;
   hdr.usedhandles:=0;
   hdr.handles:=0;
-  fRelocations.Add(0,1);
-  fRelocations.Add(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),2);
+  { the first pointer (rootptr at offset 0) goes to the root node, which comes
+    right after the header (the addend has been set to sizeof(hdr) -> add the
+    address of the fpc.resources section to it via a relocations}
+  fRelocations.Add(0,ffpcresourcessym);
+  { the last pointer (handles at offset sizeof(fields before it)) goes to the
+    fpc.reshandles section }
+  fRelocations.Add(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),ffpcreshandlessym);
   if fOppositeEndianess then
   begin
     hdr.rootptr:=SwapEndian(hdr.rootptr);
@@ -124,6 +151,7 @@ end;
 
 procedure _TMachOSubWriter_.WriteNodeInfos(aStream: TStream);
 begin
+  { offset inside the object }
   fCurOfs:=sizeof(_TResHdr_);
   WriteNodeInfo(aStream,fRoot);
   WriteSubNodes(aStream,fRoot);
@@ -138,7 +166,7 @@ begin
   else
   begin
     infonode.nameid:=fResStrTable.StartOfs+aNode.NameRVA;
-    fRelocations.Add(fCurOfs,1);
+    fRelocations.Add(fCurOfs,ffpcresourcessym);
   end;
   infonode.ncount:=aNode.NamedCount;
   if aNode.IsLeaf then
@@ -154,7 +182,7 @@ begin
   end;
   fRelocations.Add(
     fCurOfs+sizeof(infonode.nameid)+sizeof(infonode.ncount)+
-    sizeof(infonode.idcountsize),1);
+    sizeof(infonode.idcountsize),ffpcresourcessym);
   if fOppositeEndianess then
   begin
     infonode.nameid:=SwapEndian(infonode.nameid);
@@ -171,7 +199,7 @@ var buf : pbyte;
 begin
   fHeader.sizeofcmds:=
     //segment+res section+bss section
-    sizeof(_TSegmentCommand_)+sizeof(_TSection_)*2+
+    sizeof(_TSegmentCommand_)+sizeof(_TSection_)*3+
     //symbol table and dynamic symbol table commands
     sizeof(TSymtabCommand)+sizeof(TDySymtabCommand)+
     //common header of the three commands
@@ -190,21 +218,35 @@ var ldcommand : TLoadCommand;
     segcommand : _TSegmentCommand_;
     symcommand : TSymtabCommand;
     dysymcommand : TDySymtabCommand;
-    ressection,bsssection : _TSection_;
+    ressection,bsssection,textsection : _TSection_;
 begin
   ldcommand.cmd:=fSegType;
-  ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(segcommand)+sizeof(ressection)*2;
+  ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(segcommand)+sizeof(ressection)*3;
 
   FillByte(segcommand.name[0],16,0);
   segcommand.vmaddr:=0;
   segcommand.vmsize:=fDataCurOfs+sizeof(_ptrtype_)*aResources.Count;
   segcommand.fileoff:=fSectionStart;
   segcommand.filesize:=fDataCurOfs;
-  segcommand.maxprot:=VM_PROT_READ or VM_PROT_WRITE;
-  segcommand.initprot:=VM_PROT_READ or VM_PROT_WRITE;
-  segcommand.nsects:=2;
+  segcommand.maxprot:=VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE;
+  segcommand.initprot:=VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE;
+  segcommand.nsects:=3;
   segcommand.flags:=0;
 
+  fillbyte(textsection,sizeof(textsection),0);
+  textsection.sectname:='__text';
+  textsection.segname:='__TEXT';
+  textsection.addr:=0;
+  textsection.size:=0;
+  textsection.offset:=segcommand.fileoff;
+  textsection.align:=0;
+  textsection.reloff:=0;
+  textsection.nreloc:=0;
+  textsection.flags:=S_ATTR_PURE_INSTRUCTIONS;
+  textsection.reserved1:=0;
+  textsection.reserved2:=0;
+
+  fillbyte(ressection,sizeof(ressection),0);
   ressection.sectname:=RsrcSectName;
   ressection.segname:=DataSegName;
   ressection.addr:=0;
@@ -217,6 +259,7 @@ begin
   ressection.reserved1:=0;
   ressection.reserved2:=0;
 
+  fillbyte(bsssection,sizeof(bsssection),0);
   bsssection.sectname:=HandlesSectName;
   bsssection.segname:=DataSegName;
   bsssection.addr:=fDataCurOfs;
@@ -243,12 +286,14 @@ begin
     segcommand.nsects:=SwapEndian(segcommand.nsects);
     segcommand.flags:=SwapEndian(segcommand.flags);
 
+    SwapSection(textsection);
     SwapSection(ressection);
     SwapSection(bsssection);
   end;
 
   aStream.WriteBuffer(ldcommand,sizeof(ldcommand));
   aStream.WriteBuffer(segcommand,sizeof(segcommand));
+  aStream.WriteBuffer(textsection,sizeof(textsection));
   aStream.WriteBuffer(ressection,sizeof(ressection));
   aStream.WriteBuffer(bsssection,sizeof(bsssection));
 
@@ -258,7 +303,7 @@ begin
   symcommand.symoff:=fSymbolTable.StartOfs;
   symcommand.nsyms:=fSymbolTable.Count;
   symcommand.stroff:=fMachOStringTable.StartOfs;
-  symcommand.strsize:=NextAligned(fDataAlignment,fMachOStringTable.Size);
+  symcommand.strsize:=NextAligned(4,fMachOStringTable.Size);
 
   if fOppositeEndianess then
   begin
@@ -325,17 +370,6 @@ begin
   aStream.WriteBuffer(dysymcommand,sizeof(dysymcommand));
 end;
 
-procedure _TMachOSubWriter_.FixResHeader(aStream : TStream);
-var hdr : _TResHdr_;
-begin
-  hdr.handles:=fDataCurOfs;
-  if fOppositeEndianess then
-    hdr.handles:=SwapEndian(hdr.handles);
-  aStream.Seek(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),
-    soFromCurrent);
-  aStream.WriteBuffer(hdr.handles,sizeof(hdr.handles));
-end;
-
 constructor _TMachOSubWriter_.Create(aParent : TMachOResourceWriter;
   const aMachineType : TMachOMachineType; const aSubMachineType: TMachoSubMachineType; const aOppositeEndianess : boolean);
 begin
index ec5288d60c3667f75beb3cf4889bbc3756e566ba..0feb0c1e66532d491f8aa754c6e0d9f2fefe280d 100644 (file)
@@ -19,17 +19,20 @@ unit machotypes;
 
 interface
 
+{$packrecords c}
+
 type
-  TMachOMachineType = (mmtpowerpc, mmtpowerpc64, mmti386, mmtx86_64, mmtarm);
+  TMachOMachineType = (mmtpowerpc, mmtpowerpc64, mmti386, mmtx86_64, mmtarm, mmtarm64);
   TMachOSubMachineTypePowerPC = (msmppc_all);
   TMachOSubMachineTypePowerPC64 = (msmppc64_all);
   TMachOSubMachineType386 = (msm386_all);
   TMachOSubMachineTypex64 = (msmx64_all);
   TMachOSubMachineTypeArm = (msmarm_all,msmarm_v4t,msmarm_v6,msmarm_v5tej,msmarm_xscale,msmarm_v7);
+  TMachOSubMachineTypeAarch64 = (msmaarch64_all);
   TSegSectName = array[0..15] of char;
 
 type
-  TMachHdr = packed record
+  TMachHdr = record
     magic : longword;
     cputype : longint;
     cpusubtype : longint;
@@ -39,14 +42,14 @@ type
     flags : longword;
   end;
 
-  TLoadCommand = packed record
+  TLoadCommand = record
     cmd : longword;
     cmdsize : longword;
   end;
 
   //note: all commands don't include first two longwords
 
-  TSegmentCommand32 = packed record
+  TSegmentCommand32 = record
     name     : TSegSectName;
     vmaddr   : longword;
     vmsize   : longword;
@@ -58,7 +61,7 @@ type
     flags    : longword;
   end;
 
-  TSegmentCommand64 = packed record
+  TSegmentCommand64 = record
     name     : TSegSectName;
     vmaddr   : qword;
     vmsize   : qword;
@@ -70,7 +73,7 @@ type
     flags    : longword;
   end;
   
-  TSection32 = packed record
+  TSection32 = record
     sectname : TSegSectName;
     segname  : TSegSectName;
     addr : longword;
@@ -84,7 +87,7 @@ type
     reserved2 : longword;
   end;
 
-  TSection64 = packed record
+  TSection64 = record
     sectname : TSegSectName;
     segname  : TSegSectName;
     addr : qword;
@@ -99,14 +102,14 @@ type
     reserved3 : longword;
   end;
 
-  TSymtabCommand = packed record
+  TSymtabCommand = record
     symoff : longword;
     nsyms : longword;
     stroff : longword;
     strsize : longword;
   end;
   
-  TDySymtabCommand = packed record
+  TDySymtabCommand = record
     ilocalsym : longword;
     nlocalsym : longword;
     iextdefsym : longword;
@@ -127,7 +130,7 @@ type
     nlocrel : longword;
   end;
   
-  TNList32 = packed record
+  TNList32 = record
     strx : longword;
     _type : byte;
     sect : byte;
@@ -136,7 +139,7 @@ type
   end;
   PNList32 = ^TNList32;
   
-  TNList64 = packed record
+  TNList64 = record
     strx : longword;
     _type : byte;
     sect : byte;
@@ -145,7 +148,7 @@ type
   end;
   PNList64 = ^TNList64;
 
-  TRelocationInfo = packed record
+  TRelocationInfo = record
     address : longword;
     flags : longword;
   end;
index 3b7946b1d0a4d82fa76a7752c5fb890e26d9c167..3fc3f700a4422af2e2d6e6853d5786db6adeb579 100644 (file)
@@ -25,6 +25,7 @@ uses
 type
   EMachOResourceWriterException = class(EResourceWriterException);
   EMachOResourceWriterUnknownBitSizeException = class(EMachOResourceWriterException);
+  EMachOResourceWriterSymbolTableWrongOrderException = class(EMachOResourceWriterException);
 
 type
 
@@ -37,6 +38,7 @@ type
       msm386_all: (f386SubType: TMachOSubMachineType386);
       msmx64_all: (fX64SubType: TMachOSubMachineTypex64);
       mmtarm: (fArmSubType: TMachOSubMachineTypeArm);
+      mmtarm64: (fArm64SubType: TMachOSubMachineTypeAarch64);
   end;
 
   TMachOResourceWriter = class(TAbstractResourceWriter)
@@ -85,7 +87,7 @@ type
   public
     constructor Create(aMachineType : TMachOMachineType; aOppositeEndianess : boolean);
     destructor Destroy; override;
-    procedure Add(addr : longword; sectnum : longword);
+    procedure Add(addr: longword; symnum: longword);
     procedure Clear;
     procedure WriteToStream(aStream : TStream);
     property Count : integer read GetCount;
@@ -104,15 +106,17 @@ type
     fOppositeEndianess : boolean;
     function GetCount : integer;
     function AddSymbol(aName : string; sect : byte; addr : longword;
-      glob : boolean) : integer; virtual; abstract;
+      glob, undef : boolean) : integer; virtual; abstract;
   protected
   public
     constructor Create(aStringTable : TObjectStringTable);
     destructor Destroy; override;
-    function AddLocal(aName : string; sect : byte; addr : longword) : integer;
-    function AddGlobal(aName : string; sect : byte; addr : longword) : integer;
+    function AddLocal(const aName : string; sect : byte; addr : longword) : integer;
+    function AddGlobal(const aName : string; sect : byte; addr : longword) : integer;
+    function AddExternal(const aName : string) : integer;
     procedure Clear;
     procedure WriteToStream(aStream : TStream); virtual; abstract;
+    procedure SetSymbolOffset(symbolnum : integer; offset: longword); virtual; abstract;
     property Count : integer read GetCount;
     property LocalCount : integer read fLocalCount;
     property GlobalCount : integer read fGlobalCount;
@@ -140,6 +144,8 @@ type
     fCurOfs : longword;
     fDataCurOfs : longword;
     fSectionStart : longword;
+    ffpcresourcessym,
+    ffpcreshandlessym : integer;
 
     function NextAligned(aBound, aValue : longword) : longword;
     procedure Align(aBound : integer; aStream : TStream);
@@ -240,17 +246,23 @@ begin
   fList.Free;
 end;
 
-function TMachOSymbolTable.AddLocal(aName: string; sect: byte; addr: longword
+function TMachOSymbolTable.AddLocal(const aName: string; sect: byte; addr: longword
   ): integer;
 begin
-  Result:=AddSymbol(aName,sect,addr,false);
+  Result:=AddSymbol(aName,sect,addr,false,false);
   inc(fLocalCount);
 end;
 
-function TMachOSymbolTable.AddGlobal(aName: string; sect: byte; addr: longword
+function TMachOSymbolTable.AddGlobal(const aName: string; sect: byte; addr: longword
   ): integer;
 begin
-  Result:=AddSymbol(aName,sect,addr,true);
+  Result:=AddSymbol(aName,sect,addr,true,false);
+  inc(fGlobalCount);
+end;
+
+function TMachOSymbolTable.AddExternal(const aName: string): integer;
+begin
+  Result:=AddSymbol(aName,NO_SECT,0,false,true);
   inc(fGlobalCount);
 end;
 
@@ -301,6 +313,11 @@ begin
                      fRelocType:=ARM_RELOC_VANILLA;
                      fRelocSize:=2;
                    end;
+    mmtarm64    : begin
+                    fEndianess:=MACH_LITTLE_ENDIAN;
+                    fRelocType:=ARM64_RELOC_UNSIGNED;
+                    fRelocSize:=3;
+                  end;
   end;
   fOppositeEndianess:=aOppositeEndianess;
 end;
@@ -311,7 +328,7 @@ begin
   fList.Free;
 end;
 
-procedure TMachORelocations.Add(addr: longword; sectnum: longword);
+procedure TMachORelocations.Add(addr: longword; symnum: longword);
 var p : PRelocationInfo;
 begin
   p:=GetMem(sizeof(TRelocationInfo));
@@ -319,15 +336,19 @@ begin
   //bit fields make things difficult...
   if fEndianess=MACH_BIG_ENDIAN then
   begin
-    p^.flags:=sectnum shl 8;
+    p^.flags:=symnum shl 8;
     p^.flags:=p^.flags or (fRelocSize shl 5); //length
     p^.flags:=p^.flags or fRelocType;
+    { reference via symbol }
+    p^.flags:=p^.flags or R_EXTERN_BE;
   end
   else
   begin
-    p^.flags:=sectnum and R_SYMBOLNUM_LE;
+    p^.flags:=symnum and R_SYMBOLNUM_LE;
     p^.flags:=p^.flags or (fRelocSize shl 25); //length
     p^.flags:=p^.flags or (fRelocType shl 28);
+    { reference via symbol }
+    p^.flags:=p^.flags or R_EXTERN_LE;
   end;
   fList.Add(p);
 end;
@@ -491,6 +512,7 @@ const
   armsm2int: array[TMachOSubMachineTypeArm] of longint = (CPU_SUBTYPE_ARM_ALL,
     CPU_SUBTYPE_ARM_V4T,CPU_SUBTYPE_ARM_V6,CPU_SUBTYPE_ARM_V5TEJ,
     CPU_SUBTYPE_ARM_XSCALE,CPU_SUBTYPE_ARM_V7);
+  arm64sm2int: array[TMachOSubMachineTypeAarch64] of longint = (CPU_SUBTYPE_ARM64_ALL);
 begin
   aStream.Position:=0;
   case fMachineType of
@@ -519,6 +541,11 @@ begin
                      fHeader.cputype:=CPU_TYPE_ARM;
                      fHeader.cpusubtype:=armsm2int[fSubMachineType.fArmSubType];
                    end;
+    mmtarm64    : begin
+                    fHeader.magic:=MH_MAGIC_64;
+                    fHeader.cputype:=CPU_TYPE_ARM64;
+                    fHeader.cpusubtype:=arm64sm2int[fSubMachineType.fArm64SubType];
+                  end;
   end;
   fHeader.filetype:=MH_OBJECT;
   fHeader.ncmds:=3;
@@ -544,22 +571,39 @@ begin
   AllocateSpaceForLoadCommands(aStream);
   fSectionStart:=aStream.Position;
   fRoot:=TRootResTreeNode(fParent.GetTree(aResources));
+  { on AArch64, if you want to refer to a section from another one, you
+    have to do it via an explicit symbol reference.
+
+  }
+  { dummy text section symbol }
+  fSymbolTable.AddLocal('ltmp0',1,0);
+  { dummy fpc.resources symbol }
+  fSymbolTable.AddLocal('ltmp1',2,0);
+  { the offset needs to be the offset in the file, *not* relative to the start
+    of the section. We don't know here yet how large the fpcresources section
+    will be -> fix up later }
+  ffpcreshandlessym:=fSymbolTable.AddGlobal('__fpc_reshandles_internal',3,0);
+  { don't add this before any local symbols, as local symbols must be written
+    first. We can't reorder while writing the symbol table, because we already
+    need the symbol numbers above }
+  ffpcresourcessym:=fSymbolTable.AddGlobal('FPC_RESSYMBOL',2,0);
+
   PrescanResourceTree;
   WriteResHeader(aStream,aResources);
   WriteNodeInfos(aStream);
   WriteResStringTable(aStream);
   WriteRawData(aStream);
-//  fSymbolTable.AddGlobal('FPCRES_SECTION',1,0);
-  fSymbolTable.AddGlobal('FPC_RESSYMBOL',1,0);
   fRelocations.StartOfs:=aStream.Position;
   WriteRelocations(aStream);
+
+  { fix up offset of fpcreshandles symbol }
+  fSymbolTable.SetSymbolOffset(ffpcreshandlessym,fDataCurOfs);
   fSymbolTable.StartOfs:=aStream.Position;
   WriteSymbolTable(aStream);
   fMachOStringTable.StartOfs:=aStream.Position;
   WriteMachOStringTable(aStream);
   FixHeader(aStream);
   FixLoadCommands(aStream,aResources);
-  FixResHeader(aStream);
 end;
 
 constructor TAbstractMachOSubWriter.Create(aParent : TMachOResourceWriter;
@@ -602,6 +646,7 @@ begin
     mmti386      : begin fBits:=MACH_32BIT; fEndianess:=MACH_LITTLE_ENDIAN; end;
     mmtx86_64    : begin fBits:=MACH_64BIT; fEndianess:=MACH_LITTLE_ENDIAN; end;
     mmtarm       : begin fBits:=MACH_32BIT; fEndianess:=MACH_LITTLE_ENDIAN; end;
+    mmtarm64     : begin fBits:=MACH_64BIT; fEndianess:=MACH_LITTLE_ENDIAN; end;
   end;
   fMachineType:=aMachineType;
   fOppositeEndianess:=fNativeEndianess<>fEndianess;
index 35b5fb61c9a06072ff4f9edb5375c1862793c994..1938f2aa45e59505e9a7f8a2e306ac3ba84f41cb 100644 (file)
@@ -110,7 +110,7 @@ Type
   // Please keep this order, see OSCPUSupported below
   TCpu=(cpuNone,
     i386,m68k,powerpc,sparc,x86_64,arm,powerpc64,avr,armeb,
-    mips,mipsel,jvm,i8086
+    mips,mipsel,jvm,i8086,aarch64
   );
   TCPUS = Set of TCPU;
 
@@ -184,45 +184,45 @@ Const
 
   { This table is kept OS,Cpu because it is easier to maintain (PFV) }
   OSCPUSupported : array[TOS,TCpu] of boolean = (
-    { os          none   i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb  mips   mipsel jvm    i8086}
-    { none }    ( false, false, false, false, false, false, false, false, false, false, false, false, false, false),
-    { linux }   ( false, true,  true,  true,  true,  true,  true,  true,  false, true , true , true , false, false),
-    { go32v2 }  ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { win32 }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { os2 }     ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { freebsd } ( false, true,  true,  false, false, true,  false, false, false, false, false, false, false, false),
-    { beos }    ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { netbsd }  ( false, true,  true,  true,  true,  true,  false, false, false, false, false, false, false, false),
-    { amiga }   ( false, false, true,  true,  false, false, false, false, false, false, false, false, false, false),
-    { atari }   ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false),
-    { solaris } ( false, true,  false, false, true,  true,  false, false, false, false, false, false, false, false),
-    { qnx }     ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { netware } ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { openbsd } ( false, true,  true,  false, false, true,  false, false, false, false, false, false, false, false),
-    { wdosx }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { palmos }  ( false, false, true,  false, false, false, true,  false, false, false, false, false, false, false),
-    { macos }   ( false, false, false, true,  false, false, false, false, false, false, false, false, false, false),
-    { darwin }  ( false, true,  false, true,  false, true,  true,  true,  false, false, false, false, false, false),
-    { emx }     ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { watcom }  ( false, true,  false, false, false ,false, false, false, false, false, false, false, false, false),
-    { morphos } ( false, false, false, true,  false ,false, false, false, false, false, false, false, false, false),
-    { netwlibc }( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { win64   } ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false),
-    { wince    }( false, true,  false, false, false, false, true,  false, false, false, false, false, false, false),
-    { gba    }  ( false, false, false, false, false, false, true,  false, false, false, false, false, false, false),
-    { nds    }  ( false, false, false, false, false, false, true,  false, false, false, false, false, false, false),
-    { embedded }( false, true,  true,  true,  true,  true,  true,  true,  true,  true , false, false, false, false),
-    { symbian } ( false, true,  false, false, false, false, true,  false, false, false, false, false, false, false),
-    { haiku }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { iphonesim}( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { aix    }  ( false, false, false, true,  false, false, false, true,  false, false, false, false, false, false),
-    { java }    ( false, false, false, false, false, false, false, false, false, false, false, false, true , false),
-    { android } ( false, true,  false, false, false, false, true,  false, false, false, false, true,  true , false),
-    { nativent }( false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
-    { msdos }   ( false, false, false, false, false, false, false, false, false, false, false, false, false, true ),
-    { wii }     ( false, false, false, true , false, false, false, false, false, false, false, false, false, false),
-    { aros }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
-    { dragonfly}( false, false, false, false, false, true, false, false, false, false, false, false, false, false )
+    { os          none   i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb  mips   mipsel jvm    i8086  aarch64 }
+    { none }    ( false, false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { linux }   ( false, true,  true,  true,  true,  true,  true,  true,  false, true , true , true , false, false, true ),
+    { go32v2 }  ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { win32 }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { os2 }     ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { freebsd } ( false, true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false),
+    { beos }    ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { netbsd }  ( false, true,  true,  true,  true,  true,  false, false, false, false, false, false, false, false, false),
+    { amiga }   ( false, false, true,  true,  false, false, false, false, false, false, false, false, false, false, false),
+    { atari }   ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false, false),
+    { solaris } ( false, true,  false, false, true,  true,  false, false, false, false, false, false, false, false, false),
+    { qnx }     ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { netware } ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { openbsd } ( false, true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false),
+    { wdosx }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { palmos }  ( false, false, true,  false, false, false, true,  false, false, false, false, false, false, false, false),
+    { macos }   ( false, false, false, true,  false, false, false, false, false, false, false, false, false, false, false),
+    { darwin }  ( false, true,  false, true,  false, true,  true,  true,  false, false, false, false, false, false, true ),
+    { emx }     ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { watcom }  ( false, true,  false, false, false ,false, false, false, false, false, false, false, false, false, false),
+    { morphos } ( false, false, false, true,  false ,false, false, false, false, false, false, false, false, false, false),
+    { netwlibc }( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { win64   } ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false, false),
+    { wince    }( false, true,  false, false, false, false, true,  false, false, false, false, false, false, false, false),
+    { gba    }  ( false, false, false, false, false, false, true,  false, false, false, false, false, false, false, false),
+    { nds    }  ( false, false, false, false, false, false, true,  false, false, false, false, false, false, false, false),
+    { embedded }( false, true,  true,  true,  true,  true,  true,  true,  true,  true , false, false, false, false, false),
+    { symbian } ( false, true,  false, false, false, false, true,  false, false, false, false, false, false, false, false),
+    { haiku }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { iphonesim}( false, true,  false, false, false, true, false, false, false, false, false, false, false, false, false),
+    { aix    }  ( false, false, false, true,  false, false, false, true,  false, false, false, false, false, false, false),
+    { java }    ( false, false, false, false, false, false, false, false, false, false, false, false, true , false, false),
+    { android } ( false, true,  false, false, false, false, true,  false, false, false, false, true,  true , false, false),
+    { nativent }( false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { msdos }   ( false, false, false, false, false, false, false, false, false, false, false, false, false, true , false),
+    { wii }     ( false, false, false, true , false, false, false, false, false, false, false, false, false, false, false),
+    { aros }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false, false),
+    { dragonfly}( false, false, false, false, false, true,  false, false, false, false, false, false, false, false, false)
   );
 
   // Useful
@@ -2645,6 +2645,7 @@ begin
       x86_64:   result := GetGccDirArch('cpux86_64','-m64');
       powerpc:  result := GetGccDirArch('cpupowerpc','-m32');
       powerpc64:result := GetGccDirArch('cpupowerpc64','-m64');
+      aarch64:  result := GetGccDirArch('cpuaarch64','');
     end {case}
   else if OS = darwin then
     case CPU of
@@ -2652,6 +2653,8 @@ begin
       x86_64:   result := GetGccDirArch('cpux86_64','-arch x86_64');
       powerpc:  result := GetGccDirArch('cpupowerpc','-arch ppc');
       powerpc64:result := GetGccDirArch('cpupowerpc64','-arch ppc64');
+      { this target uses clang }
+      aarch64:  result := ''
     end; {case}
 end;
 
index 72aeea636ff812a101f4a8a2e45831c82919394f..14f3a8cf2d58a56a159b493e8adda1fd64c05d9a 100644 (file)
@@ -7,7 +7,7 @@ name=univint
 version=3.0.4
 
 [target]
-units=iosxlocale
+units=iosxlocale iosxwstr
 
 [libs]
 libversion=2.0.0
index d123c2338ea6d0fd6ed62ba57c29788288b3e4f4..9553396539e7406430e34f7b417f341b81aef777 100644 (file)
@@ -22,6 +22,7 @@ begin
     P.OSes:=[darwin,iphonesim];
 
     T:=P.Targets.AddUnit('iosxlocale.pp');
+    T:=P.Targets.AddUnit('iosxwstr.pp');
 
 {$ifndef ALLPACKAGES}
     Run;
diff --git a/fpcsrc/packages/iosxlocale/src/iosxwstr.pp b/fpcsrc/packages/iosxlocale/src/iosxwstr.pp
new file mode 100644 (file)
index 0000000..cdbc31f
--- /dev/null
@@ -0,0 +1,665 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2015 by Jonas Maebe,
+    member of the Free Pascal development team.
+
+    CoreFoundation-based wide string support
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ **********************************************************************}
+
+{$mode objfpc}
+{$implicitexceptions off}
+
+unit iosxwstr;
+
+interface
+
+{$linkframework CoreFoundation}
+
+  procedure SetCFWidestringManager;
+
+implementation
+
+  uses
+    unixcp,
+    { for access to libiconv-based routines }
+    cwstring,
+    MacTypes,
+    CFBase,CFString,CFStringEncodingExt,CFLocale;
+
+  procedure fpc_rangeerror; [external name 'FPC_RANGEERROR'];
+
+  var
+    CWStringWideStringManager: TUnicodeStringManager;
+
+  procedure InitThread;
+    begin
+      { we don't need anything special, but since we may use cwstring itself,
+        call through to it }
+      CWStringWideStringManager.ThreadInitProc;
+    end;
+
+
+  procedure FiniThread;
+    begin
+      { we don't need anything special, but since we may use cwstring itself,
+        call through to it }
+      CWStringWideStringManager.ThreadFiniProc;
+    end;
+
+
+  function get_cfencoding_for_cp(cp: TSystemCodePage): CFStringEncoding;
+    var
+      defscp: TSystemCodePage;
+    begin
+      { translate placeholder code pages }
+      if (cp=CP_ACP) or
+         (cp=CP_OEMCP) then
+        cp:=DefaultSystemCodePage;
+      result:=CFStringConvertWindowsCodepageToEncoding(cp);
+    end;
+
+
+  procedure GetAnsiDataFromCFString(str: CFstringRef; cfcp: CFStringEncoding; estimated_length: SizeInt; var dest: RawByteString);
+    var
+      range: CFRange;
+      encodedlen,convertedchars: CFIndex;
+      strlen: SizeInt;
+    begin
+      { first rough estimate for the length }
+      setlength(dest,estimated_length);
+      { try to convert }
+      range.location:=0;
+      strlen:=CFStringGetLength(str);
+      range.length:=strlen;
+      convertedchars:=CFStringGetBytes(str,range,cfcp,ByteParameter('?'),false,UInt8Ptr(dest),estimated_length,encodedlen);
+      { failed -> bail out }
+      if convertedchars<0 then
+        begin
+          CFRelease(str);
+          runerror(231);
+        end
+      { if partially succesful, recreate with the required len }
+      else if convertedchars<strlen then
+        begin
+          setlength(dest,encodedlen);
+          { try again }
+          convertedchars:=CFStringGetBytes(str,range,cfcp,ByteParameter('?'),false,UInt8Ptr(dest),encodedlen,encodedlen);
+          { failed again ? }
+          if convertedchars<>strlen then
+            begin
+              CFRelease(str);
+              runerror(231);
+            end;
+        end;
+      { truncate }
+      setlength(dest,encodedlen);
+    end;
+
+
+  function CFStringCreateFromAnsiData(data: pchar; len: SizeInt; cp: TSystemCodePage): CFStringRef;
+    var
+      strlen,encodedlen: CFIndex;
+      range: CFRange;
+      cfcp: CFStringEncoding;
+    begin
+      result:=nil;
+      { get source cf codepage }
+      cfcp:=get_cfencoding_for_cp(cp);
+      { unsupported encoding -> try libiconv instead }
+      if cfcp=kCFStringEncodingInvalidId then
+        exit;
+      { make a cfstring from the original data }
+      result:=CFStringCreateWithBytesNoCopy(nil,UnivPtr(data),len,cfcp,false,kCFAllocatorNull);
+    end;
+
+
+  function CFStringCreateFromAnsiDataOptionallyViaUnicodeString(data: pchar; len: SizeInt; cp: TSystemCodePage; out wtemp: UnicodeString): CFStringRef;
+    begin
+      result:=CFStringCreateFromAnsiData(data,len,cp);
+      { failed -> translate via libiconv and then create using the unicodestring
+        characters; since we use the no-copy constructor for performance
+        reasons, the unicodestring has to survive this routine }
+      if not assigned(result) then
+        begin
+          CWStringWideStringManager.Ansi2UnicodeMoveProc(data,cp,wtemp,len);
+          result:=CFStringCreateWithCharactersNoCopy(nil,UniCharPtr(wtemp),len,kCFAllocatorNull);
+        end;
+    end;
+
+
+  function CFStringCreateFromWideData(data: pwidechar; len: SizeInt): CFStringRef; inline;
+    begin
+      { make a cfstring from the utf-16 data }
+      result:=CFStringCreateWithCharactersNoCopy(nil,UniCharPtr(data),len,kCFAllocatorNull);
+    end;
+
+
+  function CFStringCreateFromWideDataOptionallyViaUUTF8String(data: pwidechar; len: SizeInt; out temp: RawByteString): CFStringRef;
+    begin
+      result:=CFStringCreateFromWideData(data,len);
+      { failed -> translate to UTF-8 via libiconv to filter out any
+        potentially invalid characters and then create using the unicodestring
+        characters; since we use the no-copy constructor for performance
+        reasons, the unicodestring has to survive this routine }
+      if not assigned(result) then
+        begin
+          CWStringWideStringManager.Unicode2AnsiMoveProc(data,temp,CP_UTF8,len);
+          result:=CFStringCreateWithBytesNoCopy(nil,UnivPtr(temp),length(temp),kCFStringEncodingUTF8,false,kCFAllocatorNull);
+          if not assigned(result) then
+            runerror(231)
+        end;
+    end;
+
+
+  procedure Wide2AnsiMove(source:pwidechar; var dest:RawByteString; cp:TSystemCodePage; len:SizeInt);
+    var
+      str: CFStringRef;
+      strlen,estimatedlen: CFIndex;
+      cfcp: CFStringEncoding;
+    begin
+      str:=nil;
+      { get target cf codepage }
+      cfcp:=get_cfencoding_for_cp(cp);
+      { unsupported encoding -> default move }
+      if cfcp<>kCFStringEncodingInvalidId then
+        { make a cfstring from the utf-16 data }
+        str:=CFStringCreateFromWideData(source,len);
+      { You cannot create a CFString for a sequence that contains an error :/
+        We want to replace the error positions with '?' -> fall back to libiconv
+      }
+      if not assigned(str) then
+        begin
+          CWStringWideStringManager.Unicode2AnsiMoveProc(source,dest,cp,len);
+          exit;
+        end;
+
+      GetAnsiDataFromCFString(str,cfcp,len*3,dest);
+      { set code page }
+      SetCodePage(dest,cp,false);
+      { release cfstring }
+      CFRelease(str);
+    end;
+
+
+  procedure Ansi2WideMove(source:pchar; cp:TSystemCodePage; var dest:widestring; len:SizeInt);
+    var
+      str: CFStringRef;
+      strlen,encodedlen: CFIndex;
+      range: CFRange;
+      cfcp: CFStringEncoding;
+    begin
+      str:=CFStringCreateFromAnsiData(source,len,cp);
+      { You cannot create a CFString for a sequence that contains an error :/
+        We want to replace the error positions with '?' -> fall back to libiconv
+      }
+      if not assigned(str) then
+        begin
+          CWStringWideStringManager.Ansi2UnicodeMoveProc(source,cp,dest,len);
+          exit;
+        end;
+
+      { convert }
+      range.location:=0;
+      strlen:=CFStringGetLength(str);
+      range.length:=strlen;
+      setlength(dest,strlen);
+      CFStringGetCharacters(str,range,UniCharPtr(dest));
+      { release cfstring }
+      CFRelease(str);
+    end;
+
+
+  function LowerWideString(const s : WideString) : WideString;
+    var
+      str: CFStringRef;
+      mstr: CFMutableStringRef;
+      range: CFRange;
+      encodedlen: CFIndex;
+      locale: CFLocaleRef;
+      temp: RawByteString;
+    begin
+      { empty string -> exit }
+      if s='' then
+        begin
+          result:='';
+          exit;
+        end;
+      { create cfstring from the string data }
+      str:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s),length(s),temp);
+      { convert to mutable cfstring }
+      mstr:=CFStringCreateMutableCopy(nil,0,str);
+      { lowercase }
+      locale:=CFLocaleCopyCurrent;
+      CFStringLowercase(mstr,locale);
+      CFRelease(locale);
+      { extract the data again }
+      range.location:=0;
+      range.length:=CFStringGetLength(CFStringRef(mstr));
+      setlength(result,range.length);
+      CFStringGetCharacters(mstr,range,UniCharPtr(result));
+      CFRelease(mstr);
+      CFRelease(str);
+    end;
+
+
+  function UpperWideString(const s : WideString) : WideString;
+  var
+    str: CFStringRef;
+    mstr: CFMutableStringRef;
+    range: CFRange;
+    encodedlen: CFIndex;
+    locale: CFLocaleRef;
+    temp: RawByteString;
+  begin
+    { empty string -> exit }
+    if s='' then
+      begin
+        result:='';
+        exit;
+      end;
+    { create cfstring from the string data }
+    str:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s),length(s),temp);
+    { convert to mutable cfstring }
+    mstr:=CFStringCreateMutableCopy(nil,0,str);
+    { lowercase }
+    locale:=CFLocaleCopyCurrent;
+    CFStringUppercase(mstr,locale);
+    CFRelease(locale);
+    { extract the data again }
+    range.location:=0;
+    range.length:=CFStringGetLength(CFStringRef(mstr));
+    setlength(result,range.length);
+    CFStringGetCharacters(mstr,range,UniCharPtr(result));
+    CFRelease(mstr);
+    CFRelease(str);
+  end;
+
+
+  function UpperLowerAnsiString(const s: AnsiString; upper: boolean): AnsiString;
+    var
+      str: CFStringRef;
+      mstr: CFMutableStringRef;
+      cfcp: CFStringEncoding;
+      locale: CFLocaleRef;
+      wtemp: UnicodeString;
+      range: CFRange;
+    begin
+      if s='' then
+        begin
+          result:='';
+          exit
+        end;
+      str:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s),length(s),StringCodePage(s),wtemp);
+      { unsupported encoding for either CF or iconv -> return original string }
+      if not assigned(str) then
+        begin
+          result:=s;
+          exit;
+        end;
+      { convert to mutable cfstring }
+      mstr:=CFStringCreateMutableCopy(nil,0,str);
+      CFRelease(str);
+      { upper/lowercase }
+      locale:=CFLocaleCopyCurrent;
+      if upper then
+        CFStringUppercase(mstr,locale)
+      else
+        CFStringLowercase(mstr,locale);
+      CFRelease(locale);
+      { convert back to ansistring }
+      cfcp:=get_cfencoding_for_cp(StringCodePage(s));
+      if cfcp<>kCFStringEncodingInvalidId then
+        begin
+          GetAnsiDataFromCFString(CFStringRef(mstr),cfcp,length(s),RawByteString(result));
+          SetCodePage(RawByteString(result),StringCodePage(s),false);
+        end
+      else
+        begin
+          { unsupported encoding -> use libiconv instead via UTF-16
+            intermediate }
+          range.location:=0;
+          range.length:=CFStringGetLength(mstr);
+          SetLength(wtemp,range.length);
+          CFStringGetCharacters(mstr,range,UniCharPtr(wtemp));
+          CWStringWideStringManager.Wide2AnsiMoveProc(pwidechar(wtemp),RawByteString(result),StringCodePage(s),range.length);
+        end;
+      CFRelease(mstr);
+    end;
+
+
+  function LowerAnsiString(const s: AnsiString): AnsiString;
+    begin
+      result:=UpperLowerAnsiString(s,false);
+    end;
+
+
+  function UpperAnsiString(const s: AnsiString): AnsiString;
+    begin
+      result:=UpperLowerAnsiString(s,true);
+    end;
+
+
+  function CompareCFStrings(const s1, s2: CFStringRef; case_insensitive: boolean): longint;
+    var
+      flags: CFStringCompareFlags;
+    begin
+      flags:=0;
+      if case_insensitive then
+        flags:=flags or kCFCompareCaseInsensitive;
+      result:=CFStringCompare(s1,s2,flags)
+    end;
+
+
+  function CompareWideString(const s1, s2 : WideString) : PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      temp1, temp2: RawByteString;
+    begin
+      cfstr1:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s1),length(s1),temp1);
+      cfstr2:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s2),length(s2),temp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,false);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+  function CompareTextWideString(const s1, s2 : WideString): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      temp1, temp2: RawByteString;
+    begin
+      cfstr1:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s1),length(s1),temp1);
+      cfstr2:=CFStringCreateFromWideDataOptionallyViaUUTF8String(pwidechar(s2),length(s2),temp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,true);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  function InternalCodePointLength(const Str: PChar; cfcp: CFStringEncoding; maxlookahead: ptrint): PtrInt;
+    var
+      cfstr: CFStringRef;
+    begin
+      result:=0;
+      { try creating a string with the first 1, 2, ... bytes until we find a
+        valid one }
+      while (str[result]<>#0) and
+            (result<maxlookahead) do
+        begin
+          inc(result);
+          cfstr:=CFStringCreateWithBytesNoCopy(nil,UnivPtr(Str),result,cfcp,false,kCFAllocatorNull);
+          if assigned(cfstr) then
+            begin
+              CFRelease(cfstr);
+              exit;
+            end;
+        end;
+      result:=-1;
+    end;
+
+
+  function CharLengthPChar(const Str: PChar): PtrInt;
+    var
+      cfstr: CFStringRef;
+      cfcp: CFStringEncoding;
+      s: PChar;
+      tmplen: PtrInt;
+    begin
+      result:=0;
+      if str[0]=#0 then
+        exit;
+      cfcp:=get_cfencoding_for_cp(DefaultSystemCodePage);
+      if cfcp=kCFStringEncodingInvalidId then
+        begin
+          { or -1? }
+          result:=strlen(Str);
+          exit
+        end;
+      s:=str;
+      repeat
+        tmplen:=InternalCodePointLength(s,cfcp,8);
+        { invalid -> skip }
+        if tmplen=-1 then
+          tmplen:=1;
+        inc(s,tmplen);
+        inc(result);
+      until s[0]=#0;
+    end;
+
+
+  function CodePointLength(const Str: PChar; maxlookahead: ptrint): PtrInt;
+    var
+      cfstr: CFStringRef;
+      cfcp: CFStringEncoding;
+    begin
+      result:=0;
+      if str[0]=#0 then
+        exit;
+      cfcp:=get_cfencoding_for_cp(DefaultSystemCodePage);
+      if cfcp=kCFStringEncodingInvalidId then
+        begin
+          { if we would return -1, then the caller would keep trying with
+            longer and longer sequences, but that wouldn't change anything }
+          result:=1;
+          exit
+        end;
+      result:=InternalCodePointLength(str,cfcp,maxlookahead);
+    end;
+
+
+  function CompareStrAnsiString(const s1, s2: ansistring): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      wtemp1, wtemp2: UnicodeString;
+    begin
+      cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s1),length(s1),StringCodePage(s1),wtemp1);
+      cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s2),length(s2),StringCodePage(s2),wtemp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,false);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  function StrCompAnsi(s1,s2 : PChar): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      wtemp1, wtemp2: UnicodeString;
+    begin
+      cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,strlen(s1),DefaultSystemCodePage,wtemp1);
+      cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,strlen(s2),DefaultSystemCodePage,wtemp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,false);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  function AnsiCompareText(const S1, S2: ansistring): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      wtemp1, wtemp2: UnicodeString;
+    begin
+      cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s1),length(s1),DefaultSystemCodePage,wtemp1);
+      cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(pchar(s2),length(s2),DefaultSystemCodePage,wtemp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,true);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  function AnsiStrIComp(S1, S2: PChar): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      wtemp1, wtemp2: UnicodeString;
+    begin
+      cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,strlen(s1),DefaultSystemCodePage,wtemp1);
+      cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,strlen(s2),DefaultSystemCodePage,wtemp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,true);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  function AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      wtemp1, wtemp2: UnicodeString;
+    begin
+      cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,MaxLen,StringCodePage(s1),wtemp1);
+      cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,MaxLen,StringCodePage(s2),wtemp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,false);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  function AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
+    var
+      cfstr1, cfstr2: CFStringRef;
+      wtemp1, wtemp2: UnicodeString;
+    begin
+      cfstr1:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s1,MaxLen,StringCodePage(s1),wtemp1);
+      cfstr2:=CFStringCreateFromAnsiDataOptionallyViaUnicodeString(s2,MaxLen,StringCodePage(s2),wtemp2);
+      result:=CompareCFStrings(cfstr1,cfstr2,true);
+      CFRelease(cfstr1);
+      CFRelease(cfstr2);
+    end;
+
+
+  procedure ansi2pchar(const s: ansistring; const orgp: pchar; out p: pchar);
+    var
+      newlen: sizeint;
+    begin
+      newlen:=length(s);
+      if newlen>strlen(orgp) then
+        fpc_rangeerror;
+      p:=orgp;
+      if (newlen>0) then
+        move(s[1],p[0],newlen);
+      p[newlen]:=#0;
+    end;
+
+
+  function AnsiStrLower(Str: PChar): PChar;
+    var
+      temp: ansistring;
+    begin
+      temp:=loweransistring(str);
+      ansi2pchar(temp,str,result);
+    end;
+
+
+  function AnsiStrUpper(Str: PChar): PChar;
+    var
+      temp: ansistring;
+    begin
+      temp:=upperansistring(str);
+      ansi2pchar(temp,str,result);
+    end;
+
+
+  function GetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
+    var
+      langinfo: pchar;
+    begin
+      { don't use CFStringGetSystemEncoding, that one returns MacRoman on e.g.
+        an English system, which is definitely not what we want. Since there are
+        no "ansi" interfaces on OS X and all APIs support all characters, always
+        use UTF-8. Additionally, Â Darwin always uses UTF-8 for file system
+        operations }
+      result:=CP_UTF8;
+    end;
+
+
+  procedure SetStdIOCodePage(var T: Text); inline;
+    begin
+      case TextRec(T).Mode of
+        fmInput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleInput);
+        fmOutput:TextRec(T).CodePage:=GetStandardCodePage(scpConsoleOutput);
+      end;
+    end;
+
+
+  procedure SetStdIOCodePages; inline;
+    begin
+      SetStdIOCodePage(Input);
+      SetStdIOCodePage(Output);
+      SetStdIOCodePage(ErrOutput);
+      SetStdIOCodePage(StdOut);
+      SetStdIOCodePage(StdErr);
+    end;
+
+
+  procedure SetCFWideStringManager;
+    var
+      CFWideStringManager : TUnicodeStringManager;
+    begin
+      GetUnicodeStringManager(CWStringWideStringManager);
+      CFWideStringManager:=CWStringWideStringManager;
+      with CFWideStringManager do
+        begin
+          Wide2AnsiMoveProc:=@Wide2AnsiMove;
+          Ansi2WideMoveProc:=@Ansi2WideMove;
+
+          UpperWideStringProc:=@UpperWideString;
+          LowerWideStringProc:=@LowerWideString;
+
+          CompareWideStringProc:=@CompareWideString;
+          CompareTextWideStringProc:=@CompareTextWideString;
+
+          CharLengthPCharProc:=@CharLengthPChar;
+          CodePointLengthProc:=@CodePointLength;
+
+          UpperAnsiStringProc:=@UpperAnsiString;
+          LowerAnsiStringProc:=@LowerAnsiString;
+          CompareStrAnsiStringProc:=@CompareStrAnsiString;
+          CompareTextAnsiStringProc:=@AnsiCompareText;
+          StrCompAnsiStringProc:=@StrCompAnsi;
+          StrICompAnsiStringProc:=@AnsiStrIComp;
+          StrLCompAnsiStringProc:=@AnsiStrLComp;
+          StrLICompAnsiStringProc:=@AnsiStrLIComp;
+          StrLowerAnsiStringProc:=@AnsiStrLower;
+          StrUpperAnsiStringProc:=@AnsiStrUpper;
+          ThreadInitProc:=@InitThread;
+          ThreadFiniProc:=@FiniThread;
+          { Unicode }
+          Unicode2AnsiMoveProc:=@Wide2AnsiMove;
+          Ansi2UnicodeMoveProc:=@Ansi2WideMove;
+          UpperUnicodeStringProc:=@UpperWideString;
+          LowerUnicodeStringProc:=@LowerWideString;
+          CompareUnicodeStringProc:=@CompareWideString;
+          CompareTextUnicodeStringProc:=@CompareTextWideString;
+          { CodePage }
+          GetStandardCodePageProc:=@GetStandardCodePage;
+        end;
+      SetUnicodeStringManager(CFWideStringManager);
+    end;
+
+
+initialization
+  SetCFWideStringManager;
+
+  { set the DefaultSystemCodePage }
+  DefaultSystemCodePage:=GetStandardCodePage(scpAnsi);
+  DefaultFileSystemCodePage:=GetStandardCodePage(scpFileSystemSingleByte);
+  DefaultRTLFileSystemCodePage:=DefaultFileSystemCodePage;
+
+  SetStdIOCodePages;
+
+  { don't call init, we don't need to do anything and the cwstring routine we
+    call through has already been called from the init code of cwstring itself
+  InitThread;
+  }
+finalization
+  { don't call for the same reason as not calling FiniThread
+  FiniThread;
+  }
+  { restore previous widestring manager so that subsequent calls
+    into the widestring manager won't trigger the finalized functionality }
+  SetWideStringManager(CWStringWideStringManager);
+end.
index 32fb02b303972c496658187e20680a892b06372c..c20586f6d577a9e70dbe6c94258dd4e1bef94c72 100644 (file)
@@ -13,7 +13,7 @@
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 }
 
-{$if not defined(cpux86_64) and not defined(NO_SYSCALL_SOCKETCALL)}
+{$if not defined(cpux86_64) and not defined(cpuaarch64) and not defined(NO_SYSCALL_SOCKETCALL)}
   {$define NEED_SOCKETCALL}
 {$endif}
 
index 597e5de6b3409933c8a353b8ff5680897b9464bd..fbccd25075276dc5045c14d65a1f84dfe499223a 100644 (file)
@@ -876,7 +876,7 @@ uses Syscall;
 
 {$ifndef FPC_USE_LIBC}
  {$if defined(Linux)}
-  {$if defined(cpux86_64) or defined(NO_SYSCALL_IPC)}
+  {$if defined(cpux86_64) or defined(cpuaarch64) or defined(NO_SYSCALL_IPC)}
     {$i ipcsys.inc}
   {$else}
     {$i ipccall.inc}
diff --git a/fpcsrc/rtl/aarch64/aarch64.inc b/fpcsrc/rtl/aarch64/aarch64.inc
new file mode 100644 (file)
index 0000000..38b51ff
--- /dev/null
@@ -0,0 +1,322 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2014 by Jonas Maebe, member of
+    the Free Pascal development team.
+
+    Processor dependent implementation for the system unit for
+    AArch64
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$IFNDEF LINUX}
+    {$DEFINE USE_DCBZ}
+{$ENDIF LINUX}
+
+{****************************************************************************
+                           AArch64 specific stuff
+****************************************************************************}
+const
+  fpu_ioe = 1 shl 8;
+  fpu_dze = 1 shl 9;
+  fpu_ofe = 1 shl 10;
+  fpu_ufe = 1 shl 11;
+  fpu_ixe = 1 shl 12;
+  fpu_ide = 1 shl 15;
+  fpu_exception_mask = fpu_ioe or fpu_dze or fpu_ofe or fpu_ufe or fpu_ixe or fpu_ide;
+  fpu_exception_mask_to_status_mask_shift = 8;
+
+function getfpcr: dword; nostackframe; assembler;
+  asm
+    mrs x0,fpcr
+  end;
+
+
+procedure setfpcr(val: dword); nostackframe; assembler;
+  asm
+    msr fpcr,x0
+  end;
+
+
+function getfpsr: dword; nostackframe; assembler;
+  asm
+    mrs x0,fpsr
+  end;
+
+
+procedure setfpsr(val: dword); nostackframe; assembler;
+  asm
+    msr fpsr, x0
+  end;
+
+
+procedure fpc_enable_fpu_exceptions;
+  begin
+    { clear all "exception happened" flags we care about}
+    setfpsr(getfpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift));
+    { enable invalid operations and division by zero exceptions. }
+    setfpcr(getfpcr or fpu_exception_mask);
+  end;
+
+procedure fpc_cpuinit;
+  begin
+    { don't let libraries influence the FPU cw set by the host program }
+    if not IsLibrary then
+      fpc_enable_fpu_exceptions;
+  end;
+
+
+{****************************************************************************
+                                Move / Fill
+****************************************************************************}
+
+
+{****************************************************************************
+                                 String
+****************************************************************************}
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler; nostackframe;
+  asm
+    cbz x0, .Lcaller_addr_invalid
+    ldur x0, [x0]
+    cbz x0, .Lcaller_addr_invalid
+    ldur x0, [x0, #8]
+   .Lcaller_addr_invalid:
+  end;
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler; nostackframe;
+  asm
+    cbz x0, .Lcaller_addr_invalid
+    ldur x0, [x0]
+   .Lcaller_addr_invalid:
+  end;
+
+
+{$define FPC_SYSTEM_HAS_SPTR}
+Function Sptr : Pointer;assembler; nostackframe;
+  asm
+    mov x0, sp
+  end;
+
+
+{****************************************************************************
+                                 Str()
+****************************************************************************}
+
+{ int_str: generic implementation is used for now }
+
+
+{****************************************************************************
+                             Multithreading
+****************************************************************************}
+
+{ perform a thread-safe inc/dec }
+
+{$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
+function declocked(var l : longint) : boolean;assembler;nostackframe;
+  { input:  address of l in x0                                      }
+  { output: boolean indicating whether l is zero after decrementing }
+  asm
+  .LDecLockedLoop:
+    ldxr   w1,[x0]
+    sub    w1,w1,#1
+    stxr   w2,w1,[x0]
+    cbnz   w2,.LDecLockedLoop
+    cset   w0, eq
+  end;
+
+
+{$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
+procedure inclocked(var l : longint);assembler;nostackframe;
+  asm
+  .LIncLockedLoop:
+    ldxr   w1,[x0]
+    add    w1,w1,#1
+    stxr   w2,w1,[x0]
+    cbnz   w2,.LIncLockedLoop
+  end;
+
+
+{$define FPC_SYSTEM_HAS_DECLOCKED_INT64}
+function declocked(var l : int64) : boolean;assembler;nostackframe;
+  { input:  address of l in x0                                      }
+  { output: boolean indicating whether l is zero after decrementing }
+  asm
+  .LDecLockedLoop:
+    ldxr   x1,[x0]
+    subs   x1,x1,#1
+    stxr   w2,x1,[x0]
+    cbnz   w2,.LDecLockedLoop
+    cset   w0, eq
+  end;
+
+
+{$define FPC_SYSTEM_HAS_INCLOCKED_INT64}
+procedure inclocked(var l : int64);assembler;nostackframe;
+  asm
+  .LIncLockedLoop:
+    ldxr   x1,[x0]
+    add    x1,x1,#1
+    stxr   w2,x1,[x0]
+    cbnz   w2,.LIncLockedLoop
+  end;
+
+
+function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
+  { input:  address of target in x0 }
+  { output: target-1 in x0          }
+  { side-effect: target := target-1 }
+  asm
+  .LInterDecLockedLoop:
+    ldxr   w1,[x0]
+    sub    w1,w1,#1
+    stxr   w2,w1,[x0]
+    cbnz   w2,.LInterDecLockedLoop
+    mov    w0,w1
+  end;
+
+
+function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
+  { input:  address of target in x0 }
+  { output: target+1 in x0          }
+  { side-effect: target := target+1 }
+  asm
+  .LInterIncLockedLoop:
+    ldxr   w1,[x0]
+    add    w1,w1,#1
+    stxr   w2,w1,[x0]
+    cbnz   w2,.LInterIncLockedLoop
+    mov    w0,w1
+  end;
+
+
+function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+  { input:  address of target in x0, source in w1 }
+  { output: target in x0                          }
+  { side-effect: target := source                 }
+  asm
+  .LInterLockedXchgLoop:
+    ldxr   w2,[x0]
+    stxr   w3,w1,[x0]
+    cbnz   w3,.LInterLockedXchgLoop
+    mov    w0,w2
+  end;
+
+
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+  asm
+  .LInterLockedXchgAddLoop:
+    ldxr   w2,[x0]
+    add    w4,w2,w1
+    stxr   w3,w4,[x0]
+    cbnz   w3,.LInterLockedXchgAddLoop
+    mov    w0,w2
+  end;
+
+
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
+  { input:  address of target in x0, newvalue in w1, comparand in w2 }
+  { output: value stored in target before entry of the function      }
+  { side-effect: NewValue stored in target if (target = comparand)   }
+  asm
+  .LInterlockedCompareExchangeLoop:
+    ldxr   w3,[x0]
+    cmp    w3,w2
+    csel   w4,w1,w3,eq
+    stxr   w5,w4,[x0]
+    cbnz   w5,.LInterlockedCompareExchangeLoop
+    mov    w0,w3
+  end;
+
+
+function InterLockedDecrement64 (var Target: int64) : int64; assembler; nostackframe;
+  asm
+  .LInterDecLockedLoop:
+    ldxr   x1,[x0]
+    sub    x1,x1,#1
+    stxr   w2,x1,[x0]
+    cbnz   w2,.LInterDecLockedLoop
+    mov    x0,x1
+  end;
+
+
+function InterLockedIncrement64 (var Target: int64) : int64; assembler; nostackframe;
+  asm
+  .LInterIncLockedLoop:
+    ldxr   x1,[x0]
+    add    x1,x1,#1
+    stxr   w2,x1,[x0]
+    cbnz   w2,.LInterIncLockedLoop
+    mov    x0,x1
+  end;
+
+
+function InterLockedExchange64 (var Target: int64;Source : int64) : int64; assembler; nostackframe;
+  asm
+  .LInterLockedXchgLoop:
+    ldxr   x2,[x0]
+    stxr   w3,x1,[x0]
+    cbnz   w3,.LInterLockedXchgLoop
+    mov    x0,x2
+  end;
+
+
+function InterLockedExchangeAdd64 (var Target: int64;Source : int64) : int64; assembler; nostackframe;
+  asm
+  .LInterLockedXchgAddLoop:
+    ldxr   x2,[x0]
+    add    x4,x2,x1
+    stxr   w3,x4,[x0]
+    cbnz   w3,.LInterLockedXchgAddLoop
+    mov    x0,x2
+  end;
+
+
+function InterLockedCompareExchange64(var Target: int64; NewValue, Comperand : int64): int64; assembler; nostackframe;
+  asm
+  .LInterlockedCompareExchangeLoop:
+    ldxr   x3,[x0]
+    cmp    x3,x2
+    csel   x4,x1,x3,eq
+    stxr   w5,x4,[x0]
+    cbnz   w5,.LInterlockedCompareExchangeLoop
+    mov    x0,x3
+  end;
+
+
+{$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
+{$define FPC_SYSTEM_HAS_MEM_BARRIER}
+procedure ReadBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
+  asm
+    { dmb ishld }
+    dmb #9
+  end;
+
+procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  { reads imply barrier on earlier reads depended on }
+end;
+
+procedure ReadWriteBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
+asm
+  { dmb ish }
+  dmb #11
+end;
+
+procedure WriteBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
+asm
+  { dmb ishst }
+  dmb #10
+end;
+
+{$endif}
diff --git a/fpcsrc/rtl/aarch64/int64p.inc b/fpcsrc/rtl/aarch64/int64p.inc
new file mode 100644 (file)
index 0000000..4a18e16
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    This file contains some helper routines for int64 and qword
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{ only dummy on AArch64 since it has a 64 bit integer unit }
diff --git a/fpcsrc/rtl/aarch64/makefile.cpu b/fpcsrc/rtl/aarch64/makefile.cpu
new file mode 100644 (file)
index 0000000..d380a26
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Here we set processor dependent include file names.
+#
+
+CPUNAMES=aarch64 int64p math set setjump setjumph strings stringss
+CPUINCNAMES=$(addsuffix .inc,$(CPUNAMES))
+#
diff --git a/fpcsrc/rtl/aarch64/math.inc b/fpcsrc/rtl/aarch64/math.inc
new file mode 100644 (file)
index 0000000..99e8efb
--- /dev/null
@@ -0,0 +1,86 @@
+{
+    Implementation of mathematical routines for x86_64
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2005 by the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
+{****************************************************************************
+                       Floating point type routines
+ ****************************************************************************}
+
+    {$ifndef FPC_SYSTEM_HAS_ABS}
+    {$define FPC_SYSTEM_HAS_ABS}
+    function fpc_abs_real(d : ValReal) : ValReal;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    {$endif FPC_SYSTEM_HAS_ABS}
+
+
+    {$ifndef FPC_SYSTEM_HAS_SQR}
+    {$define FPC_SYSTEM_HAS_SQR}
+    function fpc_sqr_real(d : ValReal) : ValReal;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    {$endif FPC_SYSTEM_HAS_SQR}
+
+
+    {$ifndef FPC_SYSTEM_HAS_SQRT}
+    {$define FPC_SYSTEM_HAS_SQRT}
+    function fpc_sqrt_real(d : ValReal) : ValReal;compilerproc;
+    begin
+      { Function is handled internal in the compiler }
+      runerror(207);
+      result:=0;
+    end;
+    {$endif FPC_SYSTEM_HAS_SQRT}
+
+
+    {$ifndef FPC_SYSTEM_HAS_INT}
+    {$define FPC_SYSTEM_HAS_INT}
+    function fpc_int_real(d : ValReal) : ValReal;assembler;nostackframe;compilerproc;
+      asm
+        { round as floating point towards zero }
+        frintz d0,d0
+      end;
+    {$endif FPC_SYSTEM_HAS_INT}
+
+
+    {$ifndef FPC_SYSTEM_HAS_TRUNC}
+    {$define FPC_SYSTEM_HAS_TRUNC}
+    function fpc_trunc_real(d : ValReal) : int64;assembler;nostackframe;compilerproc;
+      asm
+        { round to signed integer towards zero }
+        fcvtzs x0,d0
+      end;
+    {$endif FPC_SYSTEM_HAS_TRUNC}
+
+
+    {$ifndef FPC_SYSTEM_HAS_ROUND}
+    {$define FPC_SYSTEM_HAS_ROUND}
+    function fpc_round_real(d : ValReal) : int64;assembler;nostackframe;compilerproc;
+      asm
+        { round as floating point using current rounding mode }
+        frintx d0,d0
+        { convert to signed integer rounding towards zero (there's no "round to
+          integer using current rounding mode") }
+        fcvtzs x0,d0
+      end;
+    {$endif FPC_SYSTEM_HAS_ROUND}
+
+
diff --git a/fpcsrc/rtl/aarch64/mathu.inc b/fpcsrc/rtl/aarch64/mathu.inc
new file mode 100644 (file)
index 0000000..dacd3db
--- /dev/null
@@ -0,0 +1,157 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2014 by Jonas Maebe
+    member of the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+**********************************************************************}
+
+{$asmmode gas}
+
+function getfpcr: dword; nostackframe; assembler;
+  asm
+    mrs x0,fpcr
+  end;
+
+
+procedure setfpcr(val: dword); nostackframe; assembler;
+  asm
+    msr fpcr,x0
+  end;
+
+
+function getfpsr: dword; nostackframe; assembler;
+  asm
+    mrs x0,fpsr
+  end;
+
+
+procedure setfpsr(val: dword); nostackframe; assembler;
+  asm
+    msr fpsr, x0
+  end;
+
+
+function GetRoundMode: TFPURoundingMode;
+  const
+    bits2rm: array[0..3] of TFPURoundingMode = (rmNearest,rmUp,rmDown,rmTruncate);
+  begin
+    result:=TFPURoundingMode(bits2rm[(getfpcr shr 22) and 3])
+  end;
+
+
+function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
+  const
+    rm2bits: array[TFPURoundingMode] of byte = (0,2,1,3);
+  begin
+    softfloat_rounding_mode:=RoundMode;
+    SetRoundMode:=RoundMode;
+    setfpcr((getfpcr and $ff3fffff) or (rm2bits[RoundMode] shl 22));
+  end;
+
+
+function GetPrecisionMode: TFPUPrecisionMode;
+  begin
+    result:=pmDouble;
+  end;
+
+
+function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
+  begin
+    result:=pmDouble;
+  end;
+
+
+const
+  fpu_ioe = 1 shl 8;
+  fpu_dze = 1 shl 9;
+  fpu_ofe = 1 shl 10;
+  fpu_ufe = 1 shl 11;
+  fpu_ixe = 1 shl 12;
+  fpu_ide = 1 shl 15;
+  fpu_exception_mask = fpu_ioe or fpu_dze or fpu_ofe or fpu_ufe or fpu_ixe or fpu_ide;
+  fpu_exception_mask_to_status_mask_shift = 8;
+
+
+function GetExceptionMask: TFPUExceptionMask;
+  var
+    fpcr: dword;
+  begin
+    fpcr:=getfpcr;
+    result:=[];
+    if ((fpcr and fpu_ioe)=0) then
+      result := result+[exInvalidOp];
+    if ((fpcr and fpu_ofe)=0) then
+      result := result+[exOverflow];
+    if ((fpcr and fpu_ufe)=0) then
+      result := result+[exUnderflow];
+    if ((fpcr and fpu_dze)=0) then
+      result := result+[exZeroDivide];
+    if ((fpcr and fpu_ixe)=0) then
+      result := result+[exPrecision];
+    if ((fpcr and fpu_ide)=0) then
+      result := result+[exDenormalized];
+  end;
+
+
+function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
+  var
+    newfpcr: dword;
+  begin
+    softfloat_exception_mask:=mask;
+    newfpcr:=fpu_exception_mask;
+    if exInvalidOp in Mask then
+      newfpcr:=newfpcr and not(fpu_ioe);
+    if exOverflow in Mask then
+      newfpcr:=newfpcr and not(fpu_ofe);
+    if exUnderflow in Mask then
+      newfpcr:=newfpcr and not(fpu_ufe);
+    if exZeroDivide in Mask then
+      newfpcr:=newfpcr and not(fpu_dze);
+    if exPrecision in Mask then
+      newfpcr:=newfpcr and not(fpu_ixe);
+    if exDenormalized in Mask then
+      newfpcr:=newfpcr and not(fpu_ide);
+    { clear "exception happened" flags }
+    ClearExceptions(false);
+    { set new exception mask }
+    setfpcr((getfpcr and not(fpu_exception_mask)) or newfpcr);
+    { unsupported mask bits will remain 0 -> read exception mask again }
+    result:=GetExceptionMask;
+    softfloat_exception_mask:=result;
+  end;
+
+
+procedure ClearExceptions(RaisePending: Boolean);
+  var
+    fpsr: dword;
+    f: TFPUException;
+  begin
+    fpsr:=getfpsr;
+    if raisepending then
+      begin
+        if (fpsr and (fpu_dze shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+          float_raise(exZeroDivide);
+        if (fpsr and (fpu_ofe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+          float_raise(exOverflow);
+        if (fpsr and (fpu_ufe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+          float_raise(exUnderflow);
+        if (fpsr and (fpu_ioe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+          float_raise(exInvalidOp);
+        if (fpsr and (fpu_ixe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+          float_raise(exPrecision);
+        if (fpsr and (fpu_ide shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
+          float_raise(exDenormalized);
+        { now the soft float exceptions }
+        for f in  softfloat_exception_flags do
+          float_raise(f);
+      end;
+    softfloat_exception_flags:=[];
+    setfpsr(fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift));
+  end;
diff --git a/fpcsrc/rtl/aarch64/set.inc b/fpcsrc/rtl/aarch64/set.inc
new file mode 100644 (file)
index 0000000..af93168
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2002 by the Free Pascal development team
+
+    Include file with set operations called by the compiler
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
diff --git a/fpcsrc/rtl/aarch64/setjump.inc b/fpcsrc/rtl/aarch64/setjump.inc
new file mode 100644 (file)
index 0000000..db4e7a7
--- /dev/null
@@ -0,0 +1,59 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2015 by Jonas Maebe and other members of the
+    Free Pascal development team
+
+    SetJmp/Longjmp implementation for AArch64
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+
+ **********************************************************************}
+
+function fpc_setjmp(var S: jmp_buf): longint; assembler; [public, alias:'FPC_SETJMP']; nostackframe; compilerproc;
+  asm
+    mov x3, sp
+    stp x19, x20, [x0, #jmp_buf.x19]
+    stp x21, x22, [x0, #jmp_buf.x21]
+    stp x23, x24, [x0, #jmp_buf.x23]
+    stp x25, x26, [x0, #jmp_buf.x25]
+    stp x27, x28, [x0, #jmp_buf.x27]
+    stp x29, x30, [x0, #jmp_buf.x29]
+    str x3,       [x0, #jmp_buf.xsp]
+
+    stp d8,  d9,  [x0, #jmp_buf.d8]
+    stp d10, d11, [x0, #jmp_buf.d10]
+    stp d12, d13, [x0, #jmp_buf.d12]
+    stp d14, d15, [x0, #jmp_buf.d14]
+
+    mov x0, xzr
+  end;
+
+
+procedure fpc_longjmp(var S: jmp_buf ;value: longint); assembler; [public, alias:'FPC_LONGJMP']; nostackframe; compilerproc;
+  asm
+    ldr x3,       [x0, #jmp_buf.xsp]
+
+    ldp x19, x20, [x0, #jmp_buf.x19]
+    ldp x21, x22, [x0, #jmp_buf.x21]
+    ldp x23, x24, [x0, #jmp_buf.x23]
+    ldp x25, x26, [x0, #jmp_buf.x25]
+    ldp x27, x28, [x0, #jmp_buf.x27]
+    ldp x29, x30, [x0, #jmp_buf.x29]
+
+    mov sp, x3
+
+    ldp d8,  d9,  [x0, #jmp_buf.d8]
+    ldp d10, d11, [x0, #jmp_buf.d10]
+    ldp d12, d13, [x0, #jmp_buf.d12]
+    ldp d14, d15, [x0, #jmp_buf.d14]
+
+    mov x0, x1
+  end;
+
+
diff --git a/fpcsrc/rtl/aarch64/setjumph.inc b/fpcsrc/rtl/aarch64/setjumph.inc
new file mode 100644 (file)
index 0000000..81436cd
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2000-2002 by Jonas Maebe and other members of the
+    Free Pascal development team
+
+    SetJmp/Longjmp declarations
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+type
+   jmp_buf = record
+     x19: qword;
+     x20: qword;
+     x21: qword;
+     x22: qword;
+     x23: qword;
+     x24: qword;
+     x25: qword;
+     x26: qword;
+     x27: qword;
+     x28: qword;
+     x29: qword;
+     x30: qword;
+     xsp: qword;
+     d8: qword;
+     d9: qword;
+     d10: qword;
+     d11: qword;
+     d12: qword;
+     d13: qword;
+     d14: qword;
+     d15: qword;
+   end;
+   pjmp_buf = ^jmp_buf;
+
+function setjmp(var S : jmp_buf) : longint;[external name 'FPC_SETJMP'];
+procedure longjmp(var S : jmp_buf;value : longint);[external name 'FPC_LONGJMP'];
+
diff --git a/fpcsrc/rtl/aarch64/strings.inc b/fpcsrc/rtl/aarch64/strings.inc
new file mode 100644 (file)
index 0000000..c922666
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2003 by Florian Klaempfl, member of the
+    Free Pascal development team
+
+    Processor dependent part of strings.pp, that can be shared with
+    sysutils unit.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
diff --git a/fpcsrc/rtl/aarch64/stringss.inc b/fpcsrc/rtl/aarch64/stringss.inc
new file mode 100644 (file)
index 0000000..b305728
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Jonas Maebe, member of the
+    Free Pascal development team
+
+    Processor dependent part of strings.pp, not shared with
+    sysutils unit.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
index 09e9ed978efea9b4a90d7c1973b7ffac0aa70277..a62255d58bc93e3a0d93e490c193407964c920f6 100644 (file)
@@ -15,8 +15,6 @@
 
  **********************************************************************}
 
-{$asmmode gas}
-
 {$ifndef FPC_SYSTEM_HAS_MOVE}
 {$define FPC_SYSTEM_FPC_MOVE}
 {$endif FPC_SYSTEM_HAS_MOVE}
index 921ae24345e9efbd99f2543e37122bb85828268a..248744d8c0d5fe447bf3e8337e809a70aa65585b 100644 (file)
@@ -15,7 +15,7 @@
 
  **********************************************************************}
 
-{$asmmode gas}
+{$asmmode divided}
 
 {$ifndef FPC_SYSTEM_HAS_MOVE}
 {$define FPC_SYSTEM_FPC_MOVE}
index ab7395e77a0684594ace859941cf42f6299e05c5..00bcd5d59272be2d1418fb85f120037c40ab46b3 100644 (file)
@@ -30,8 +30,8 @@
   {$endif}
 {$endif}
 
-{$if (defined(darwin) and defined(cpuarm)) or defined(iphonesim)}
-  {$define darwinarm}
+{$if (defined(darwin) and (defined(cpuarm) or defined(cpuaarch64))) or defined(iphonesim)}
+  {$define darwin_new_iostructs}
 {$endif}
 
 //      CONST SYS_NMLN=65;
@@ -88,7 +88,7 @@ TYPE
         st_qspare2    : cint64;
 {$else dragonfly}
         st_dev        : dev_t;             // inode's device
-{$ifdef darwinarm}
+{$ifdef darwin_new_iostructs}
         st_mode       : mode_t;            // inode protection mode
         st_nlink      : nlink_t;           // number of hard links
         st_ino        : ino_t;             // inode's number
@@ -115,7 +115,7 @@ TYPE
         st_mtimensec  : clong;             // nsec of last data modification
         st_ctime      : time_t;            // time of last file status change
         st_ctimensec  : clong;             // nsec of last file status change
-{$ifdef darwinarm}
+{$ifdef darwin_new_iostructs}
         st_birthtime  : time_t;            // File creation time
         st_birthtimensec : clong;          // nsec of file creation time
 {$endif}
@@ -144,7 +144,7 @@ TYPE
    pStat = ^stat;
 
   { directory services }
-{$ifndef darwinarm}
+{$ifndef darwin_new_iostructs}
    dirent  = record
         d_fileno      : cuint32;                        // file number of entry
         d_reclen      : cuint16;                        // length of this record
@@ -152,7 +152,7 @@ TYPE
         d_namlen      : cuint8;                         // length of string in d_name
         d_name        : array[0..(255 + 1)-1] of char;  // name must be no longer than this
    end;
-{$else not darwinarm}
+{$else not darwin_new_iostructs}
    {$packrecords 4}
    { available on Mac OS X 10.6 and later, and used by all iPhoneOS versions }
    dirent  = record
@@ -164,7 +164,7 @@ TYPE
         d_name        : array[0..PATH_MAX-1] of char;        // name must be no longer than this
    end;
    {$packrecords c}
-{$endif darwinarm}
+{$endif darwin_new_iostructs}
    TDirent = dirent;
    pDirent = ^dirent;
 
diff --git a/fpcsrc/rtl/darwin/aarch64/sig_cpu.inc b/fpcsrc/rtl/darwin/aarch64/sig_cpu.inc
new file mode 100644 (file)
index 0000000..13345b2
--- /dev/null
@@ -0,0 +1,47 @@
+
+{$IFDEF FPC}
+{$PACKRECORDS C}
+{$ENDIF}
+
+
+
+  type
+     __darwin_arm_exception_state64 = record
+          __far : cuint64;
+          __esr : cuint32;
+          __exception : cuint32;
+       end;
+
+     __darwin_arm_thread_state64 = record
+          __r : array[0..28] of cuint64;
+          __fp : cuint64;
+          __lr : cuint64;
+          __sp : cuint64;
+          __pc : cuint64;
+          __cpsr : cuint32;
+       end;
+
+     __darwin_arm_neon_state64 = record
+          { actually an array of cuint128 }
+          __r : array[0..31] of record l1,l2: cuint64; end;
+          __fpsr : cuint32;
+          __fpcr : cuint32;
+          { array of cuint128 is aligned/padded to multiple of 16 bytes }
+          pad: cuint64;
+       end;
+
+     __darwin_arm_debug_state64 = record
+          __bvr : array[0..15] of cuint64;
+          __bcr : array[0..15] of cuint64;
+          __wvr : array[0..15] of cuint64;
+          __wcr : array[0..15] of cuint64;
+          __mdscr_el1: cuint64;
+       end;
+
+     mcontext_t = record
+          __es : __darwin_arm_exception_state64;
+          __ss : __darwin_arm_thread_state64;
+          __fs : __darwin_arm_neon_state64;
+       end;
+
+
diff --git a/fpcsrc/rtl/darwin/aarch64/sighnd.inc b/fpcsrc/rtl/darwin/aarch64/sighnd.inc
new file mode 100644 (file)
index 0000000..e9a7d42
--- /dev/null
@@ -0,0 +1,61 @@
+{
+   This file is part of the Free Pascal run time library.
+   (c) 2008 by Jonas Maebe
+   member of the Free Pascal development team.
+
+   See the file COPYING.FPC, included in this distribution,
+   for details about the copyright.
+
+   Signalhandler for Darwin/arm
+
+   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.
+}
+
+
+procedure SignalToRunerror(Sig: cint; info : PSigInfo; SigContext:PSigContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
+var
+  res : word;
+begin
+  res:=0;
+  case sig of
+    SIGFPE :
+      begin
+        Case Info^.si_code Of
+          FPE_FLTDIV,
+          FPE_INTDIV : Res:=200;  { floating point divide by zero }
+          FPE_FLTOVF : Res:=205;  { floating point overflow }
+          FPE_FLTUND : Res:=206;  { floating point underflow }
+          FPE_FLTRES,             { floating point inexact result }
+          FPE_FLTINV : Res:=207;  { invalid floating point operation }
+          Else
+            Res:=207; {coprocessor error}
+        end;
+        { clear "exception happened" flags }
+        SigContext^.uc_mcontext^.__fs.__fpsr:=SigContext^.uc_mcontext^.__fs.__fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift);
+      end;
+    SIGBUS:
+        res:=214;
+    SIGILL,
+    SIGSEGV :
+        res:=216;
+    SIGINT:
+        res:=217;
+    SIGQUIT:
+        res:=233;
+  end;
+  {$ifdef FPC_USE_SIGPROCMASK}
+   reenable_signal(sig);
+  {$endif }
+
+  { return to trampoline }
+  if res <> 0 then
+    begin
+      SigContext^.uc_mcontext^.__ss.__r[0] := res;
+      SigContext^.uc_mcontext^.__ss.__r[1] := SigContext^.uc_mcontext^.__ss.__pc;
+      SigContext^.uc_mcontext^.__ss.__r[2] := SigContext^.uc_mcontext^.__ss.__fp;
+      pointer(SigContext^.uc_mcontext^.__ss.__pc) := @HandleErrorAddrFrame;
+    end;
+end;
+
index 0d80d3555c28940ec7ea4296fc358aaf997161ee..a9a1eb7313522d837711e99fe9dc98c9f7d3a09a 100644 (file)
@@ -30,27 +30,21 @@ const
   {$ENDIF}
   FPCRES_EXT = '.fpcres';
   FPCRES_ARCH =
-    {$IFDEF CPUI386}
+    {$if defined(cpui386)}
     '.i386';
-    {$ELSE}
-      {$IFDEF CPUX86_64}
-      '.x86_64';
-      {$ELSE}
-        {$IFDEF CPUPOWERPC32}
-        '.powerpc';
-        {$ELSE}
-          {$IFDEF CPUPOWERPC64}
-          '.powerpc64';
-          {$ELSE}
-            {$IFDEF CPUARM}
-            '.arm';
-            {$ELSE}
-              '';
-            {$ENDIF}
-          {$ENDIF}
-        {$ENDIF}
-      {$ENDIF}
-    {$ENDIF}
+    {$elseif defined(cpux86_64)}
+    '.x86_64';
+    {$elseif defined(cpupowerpc32)}
+    '.powerpc';
+    {$elseif defined(cpupowerpc64)}
+    '.powerpc64';
+    {$elseif defined(cpuarm)}
+    '.arm';
+    {$elseif defined(cpuaarch64)}
+    '.aarch64';
+    {$else}
+    {$error add support for cpu architecture}
+    {$endif}
 
 type
   TExtHeader = packed record
index 15fbb9c9729fd830bbd37771566b407f394bea94..aa12ebcb8915361689b829e6e40d6e86c3d6c5ef 100644 (file)
@@ -35,7 +35,7 @@ type
     pGid     = ^gid_t;
     TIOCtlRequest = cuLong;
 
-{$if not defined(cpuarm) and not defined(iphonesim)}
+{$if not defined(cpuarm) and not defined(aarch64) and not defined(iphonesim)}
     ino_t    = cuint32;         { used for file serial numbers }
 {$else}
     ino_t    = cuint64;
@@ -144,7 +144,7 @@ type
           val: array[0..1] of cint32;
      end;
 
-{$if defined(cpuarm) or defined(iphonesim)}
+{$if defined(cpuarm) or defined(cpuaarch64) or defined(iphonesim)}
      { structure used on iPhoneOS and available on Mac OS X 10.6 and later }
      tstatfs = record
           bsize : cuint32;
index a3f843b9e28ed9a61f1f860e57e39b6ab3aceaf6..78de160c552911af564c6d618f4bc7af8a4bb0bc 100644 (file)
 {$ifdef cpuarm}
     {$include arm/sig_cpu.inc}
 {$else cpuarm}
+{$ifdef cpuaarch64}
+    {$include aarch64/sig_cpu.inc}
+{$else cpuaarch64}
     {$error Unsupported cpu type!}
+{$endif cpuaarch64}
 {$endif cpuarm}
 {$endif cpux86_64}
 {$endif cpui386}
index 9376ff1b6a23be1f3c43ab8b03d274cea21cafec..90c026204fcdf4b2833deb08c7ff6709caad6cc3 100644 (file)
@@ -110,6 +110,10 @@ type
   {$define longdouble_is_double}
 {$ifend}
 
+{$if defined(darwin) and defined(cpuaarch64)}
+  {$define longdouble_is_double}
+{$ifend}
+
 {$ifndef FPUNONE}
 {$if defined(longdouble_is_double) or not defined(FPC_HAS_CEXTENDED)}
   clongdouble=double;
index 088d7e553e7eccac3355f6117ef3a74313213e5d..e7fc167c7c86dbd45442d1d718256956e002beea 100644 (file)
@@ -3,7 +3,7 @@ unit objc;
 
 {$ifdef darwin}
 {$define targethandled}
-{$if defined(iphonesim) or defined(cpuarm) or defined(cpux86_64) or defined(cpupowerpc64)}
+{$if defined(iphonesim) or defined(cpuarm) or defined(cpux86_64) or defined(cpupowerpc64) or defined(cpuaarch64)}
 {$i objcnf.inc}
 {$endif}
 
index f46979245613752d711cea7856c96fe6c4f91ed2..ba93ab76e7ba71d4dacb4cc0fe66ba04f0d7b913 100644 (file)
@@ -172,12 +172,16 @@ type
   function  objc_msgSend(self: id; op: SEL): id; cdecl; varargs; external libname;
   function  objc_msgSendSuper(const super: pobjc_super; op: SEL): id; cdecl; varargs; external libname;
   function  objc_msgSendSuper2(const super: pobjc_super; op: SEL): id; cdecl; varargs; weakexternal libname; { Mac OS X 10.6 and later }
-  { The following two are declared as procedures with the hidden result pointer
-    as their first parameter. This corresponds to the declaration below as far
-    as the code generator is concerned (and is easier to handle in the compiler).  }
+{ the AArch64 ABI does not require special handling of struct returns, so no
+  special handlers are provided/required }
+{$ifndef cpuaarch64}
+{ The following two are declared as procedures with the hidden result pointer
+  as their first parameter. This corresponds to the declaration below as far
+  as the code generator is concerned (and is easier to handle in the compiler).  }
   function  objc_msgSend_stret(self: id; op: SEL): tdummyrecbyaddrresult; cdecl; varargs; external libname;
   function  objc_msgSendSuper_stret(const super: pobjc_super; op: SEL): tdummyrecbyaddrresult; cdecl; varargs; external libname;
   function  objc_msgSendSuper2_stret(const super: pobjc_super; op: SEL): tdummyrecbyaddrresult; cdecl; varargs; weakexternal libname;
+{$endif cpuaarch64}
   { This one actually also exists to return extended on x86_64, but
     we don't support that yet
   }
@@ -230,7 +234,9 @@ type
   function class_getInstanceMethod(cls:pobjc_class; name:SEL):Method; cdecl; external libname;
   function class_getClassMethod(cls:pobjc_class; name:SEL):Method; cdecl; external libname;
   function class_getMethodImplementation(cls:pobjc_class; name:SEL):IMP; cdecl; external libname;
+{$ifndef cpuaarch64}
   function class_getMethodImplementation_stret(cls:pobjc_class; name:SEL):IMP; cdecl; external libname;
+{$endif cpuaarch64}
   function class_respondsToSelector(cls:pobjc_class; sel:SEL):BOOL; cdecl; external libname;
   function class_copyMethodList(cls:pobjc_class; outCount:pdword):PMethod; cdecl; external libname;
 
index 3787f13bb0858e2384092ffefb9d3c668f5327b8..5f4a45447a5aebd8f31259545114a5d829fc4661 100644 (file)
@@ -264,6 +264,13 @@ function do_isdevice(handle:thandle):boolean;forward;
 {$endif cpumips}
 {$endif not cpumipsel}
 
+{$ifdef cpuaarch64}
+  {$ifdef SYSPROCDEFINED}
+    {$Error Can't determine processor type !}
+  {$endif}
+  {$i aarch64.inc}  { Case dependent, don't change }
+  {$define SYSPROCDEFINED}
+{$endif cpuaarch64}
 
 {$ifndef SYSPROCDEFINED}
   {$Error Can't determine processor type !}
index 5f7ed3fb930d22727441f45c5bc482a213a05ad3..10ff8b206842d773edb57470f3226fbee3181478 100644 (file)
@@ -332,6 +332,22 @@ Type
   FarPointer = Pointer;
 {$endif CPUAVR}
 
+{$ifdef CPUAARCH64}
+  {$define DEFAULT_DOUBLE}
+
+  {$define SUPPORT_SINGLE}
+  {$define SUPPORT_DOUBLE}
+
+  ValReal = Double;
+
+  { map comp to int64, but this doesn't mean we compile the comp support in! }
+  Comp = Int64;
+  PComp = ^Comp;
+
+  FarPointer = Pointer;
+{$endif CPUAARCH64}
+
+
 {$ifdef CPU64}
   SizeInt = Int64;
   SizeUInt = QWord;
@@ -861,13 +877,13 @@ function NtoLE(const AValue: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
 {$define FPC_HAS_INTERNAL_ROX_WORD}
 {$endif defined(cpux86_64) or defined(cpui386)}
 
-{$if defined(cpux86_64) or defined(cpui386) or defined(arm) or defined(powerpc) or defined(powerpc64)}
+{$if defined(cpux86_64) or defined(cpui386) or defined(arm) or defined(powerpc) or defined(powerpc64) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_ROX_DWORD}
-{$endif defined(cpux86_64) or defined(cpui386) or defined(arm) or defined(powerpc) or defined(powerpc64)}
+{$endif defined(cpux86_64) or defined(cpui386) or defined(arm) or defined(powerpc) or defined(powerpc64) or defined(cpuaarch64)}
 
-{$if defined(cpux86_64) or defined(powerpc64)}
+{$if defined(cpux86_64) or defined(powerpc64) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_ROX_QWORD}
-{$endif defined(cpux86_64) or defined(powerpc64)}
+{$endif defined(cpux86_64) or defined(powerpc64) or defined(cpuaarch64)}
 
 {$endif FPC_HAS_INTERNAL_ROX}
 
@@ -942,9 +958,9 @@ function RolQWord(Const AValue : QWord;const Dist : Byte): QWord;{$ifdef SYSTEMI
 {$define FPC_HAS_INTERNAL_SAR_DWORD}
 { $endif defined(cpux86_64) or defined(cpui386) or defined(arm) or defined(powerpc) or defined(powerpc64) or defined(mips) or defined(mipsel)}
 
-{$if defined(cpux86_64) or defined(powerpc64)}
+{$if defined(cpux86_64) or defined(powerpc64) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_SAR_QWORD}
-{$endif defined(cpux86_64) or defined(powerpc64)}
+{$endif defined(cpux86_64) or defined(powerpc64) or defined(cpuaarch64)}
 
 {$endif FPC_HAS_INTERNAL_SAR}
 
@@ -976,23 +992,23 @@ function fpc_SarInt64(Const AValue : Int64;const Shift : Byte): Int64;compilerpr
 {$endif FPC_HAS_INTERNAL_SAR_QWORD}
 
 {$ifdef FPC_HAS_INTERNAL_BSF}
-{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm)}
+{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_BSF_BYTE}
 {$define FPC_HAS_INTERNAL_BSF_WORD}
 {$define FPC_HAS_INTERNAL_BSF_DWORD}
 {$endif}
-{$if defined(cpux86_64)}
+{$if defined(cpux86_64) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_BSF_QWORD}
 {$endif}
 {$endif}
 
 {$ifdef FPC_HAS_INTERNAL_BSR}
-{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm)}
+{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_BSR_BYTE}
 {$define FPC_HAS_INTERNAL_BSR_WORD}
 {$define FPC_HAS_INTERNAL_BSR_DWORD}
 {$endif}
-{$if defined(cpux86_64)}
+{$if defined(cpux86_64) or defined(cpuaarch64)}
 {$define FPC_HAS_INTERNAL_BSR_QWORD}
 {$endif}
 {$endif}
diff --git a/fpcsrc/rtl/linux/aarch64/bsyscall.inc b/fpcsrc/rtl/linux/aarch64/bsyscall.inc
new file mode 100644 (file)
index 0000000..c690ebe
--- /dev/null
@@ -0,0 +1 @@
+{ nothing }
diff --git a/fpcsrc/rtl/linux/aarch64/cprt0.as b/fpcsrc/rtl/linux/aarch64/cprt0.as
new file mode 100644 (file)
index 0000000..fd83610
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+   Start-up code for Free Pascal Compiler when linking with C library.
+
+   Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+       .text
+       .align 2
+
+       .globl _start
+       .type  _start,#function
+_start:
+       /* Initialise FP to zero */
+       mov     x29,#0
+
+       /* This is rtld_fini */
+       mov     x5,x0
+
+       /* Get argc, argv, envp */
+       ldr     x1,[sp]
+       add     x2,sp,#8
+       add     x11,x1,#1
+       add     x11,x2,x11,lsl #3
+
+       /* Save argc, argv, envp, and initial stack pointer */
+       adrp    x10,:got:operatingsystem_parameter_argc
+       ldr     x10,[x10,#:got_lo12:operatingsystem_parameter_argc]
+       str     x1,[x10]
+       adrp    x10,:got:operatingsystem_parameter_argv
+       ldr     x10,[x10,#:got_lo12:operatingsystem_parameter_argv]
+       str     x2,[x10]
+       adrp    x10,:got:operatingsystem_parameter_envp
+       ldr     x10,[x10,#:got_lo12:operatingsystem_parameter_envp]
+       str     x11,[x10]
+       adrp    x10,:got:__stkptr
+       ldr     x10,[x10,#:got_lo12:__stkptr]
+       mov     x6,sp
+       str     x6,[x10]
+
+       /* __libc_start_main(main, argc, argv,
+                            init, fini, rtld_fini, stack_end) */
+       adrp    x0,:got:PASCALMAIN
+       ldr     x0,[x0,#:got_lo12:PASCALMAIN]
+       adrp    x3,:got:__libc_csu_init
+       ldr     x3,[x3,#:got_lo12:__libc_csu_init]
+       adrp    x4,:got:__libc_csu_fini
+       ldr     x4,[x4,#:got_lo12:__libc_csu_fini]
+       bl      __libc_start_main
+
+       /* This should never happen */
+       b       abort
+
+       .globl  _haltproc
+       .type   _haltproc,#function
+_haltproc:
+       adrp    x0,:got:operatingsystem_result
+       ldr     x0,[x0,#:got_lo12:operatingsystem_result]
+       ldr     w0,[x0]
+       mov     w8,#94 // syscall_nr_exit_group
+       svc     #0
+       b       _haltproc
+
+       /* Define a symbol for the first piece of initialized data. */
+       .data
+       .align 3
+       .globl __data_start
+__data_start:
+       .long 0
+       .weak data_start
+       data_start = __data_start
+
+       .bss
+       .align 3
+
+       .comm __stkptr,8
+
+       .comm operatingsystem_parameter_envp,8
+       .comm operatingsystem_parameter_argc,8
+       .comm operatingsystem_parameter_argv,8
+
+       .section .note.GNU-stack,"",%progbits
diff --git a/fpcsrc/rtl/linux/aarch64/dllprt0.as b/fpcsrc/rtl/linux/aarch64/dllprt0.as
new file mode 100644 (file)
index 0000000..e91b758
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+   Start-up code for Free Pascal Compiler in a shared library,
+   not linking with C library.
+
+   Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+       .text
+       .align 2
+
+       .globl  _startlib
+       .type   _startlib,#function
+_startlib:
+       .globl  FPC_SHARED_LIB_START
+       .type   FPC_SHARED_LIB_START,#function
+FPC_SHARED_LIB_START:
+       stp     x29,x30,[sp,#-16]!
+
+       /* Save argc, argv and envp */
+       adrp    x9,:got:operatingsystem_parameter_argc
+       ldr     x9,[x9,#:got_lo12:operatingsystem_parameter_argc]
+       str     x0,[x9]
+       adrp    x9,:got:operatingsystem_parameter_argv
+       ldr     x9,[x9,#:got_lo12:operatingsystem_parameter_argv]
+       str     x1,[x9]
+       adrp    x9,:got:operatingsystem_parameter_envp
+       ldr     x9,[x9,#:got_lo12:operatingsystem_parameter_envp]
+       str     x2,[x9]
+
+       /* Save initial stackpointer */
+       adrp    x9,:got:__stkptr
+       ldr     x9,[x9,#:got_lo12:__stkptr]
+       mov     x10,sp
+       str     x10,[x9]
+
+       /* Call main */
+       bl      PASCALMAIN
+
+       /* Return */
+       ldp     x29,x30,[sp],#16
+       ret
+
+       .globl  _haltproc
+       .type   _haltproc,#function
+_haltproc:
+       adrp    x0,:got:operatingsystem_result
+       ldr     x0,[x0,#:got_lo12:operatingsystem_result]
+       ldr     w0,[x0]
+       mov     w8,#94 // syscall_nr_exit_group
+       svc     #0
+       b       _haltproc
+
+       /* Define a symbol for the first piece of initialized data. */
+       .data
+       .align 3
+       .globl __data_start
+__data_start:
+       .long 0
+       .weak data_start
+       data_start = __data_start
+
+       .bss
+       .align 3
+
+       .comm __dl_fini,8
+       .comm __stkptr,8
+
+       .comm operatingsystem_parameter_envp,8
+       .comm operatingsystem_parameter_argc,8
+       .comm operatingsystem_parameter_argv,8
+
+       .section .note.GNU-stack,"",%progbits
diff --git a/fpcsrc/rtl/linux/aarch64/gprt0.as b/fpcsrc/rtl/linux/aarch64/gprt0.as
new file mode 100644 (file)
index 0000000..e3a1b59
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+   Start-up code for Free Pascal Compiler when linking with C library
+   with profiling support.
+
+   Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+       .text
+       .align 2
+       b       xx_aarch64_gprt0_unimplemented
diff --git a/fpcsrc/rtl/linux/aarch64/prt0.as b/fpcsrc/rtl/linux/aarch64/prt0.as
new file mode 100644 (file)
index 0000000..277d309
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+   Start-up code for Free Pascal Compiler, not in a shared library,
+   not linking with C library.
+
+   Written by Edmund Grimley Evans in 2015 and released into the public domain.
+*/
+
+       .text
+       .align 2
+
+       .globl _dynamic_start
+       .type  _dynamic_start,#function
+_dynamic_start:
+       ldr     x10,=__dl_fini
+       str     x0,[x10]
+       b       _start
+
+       .globl  _start
+       .type   _start,#function
+_start:
+       /* Initialise FP to zero */
+       mov     x29,#0
+
+       /* Get argc, argv, envp */
+       ldr     x1,[sp]
+       add     x2,sp,#8
+       add     x11,x1,#1
+       add     x11,x2,x11,lsl #3
+
+       /* Save argc, argv, envp, and initial stack pointer */
+       ldr     x10,=operatingsystem_parameter_argc
+       str     x1,[x10]
+       ldr     x10,=operatingsystem_parameter_argv
+       str     x2,[x10]
+       ldr     x10,=operatingsystem_parameter_envp
+       str     x11,[x10]
+       ldr     x10,=__stkptr
+       mov     x6,sp
+       str     x6,[x10]
+
+       /* Call main */
+       bl      PASCALMAIN
+
+       .globl  _haltproc
+       .type   _haltproc,#function
+_haltproc:
+       ldr     x10,=__dl_fini
+       ldr     x0,[x10]
+       cbz     x0,.Lexit
+       blr     x0
+.Lexit:
+       ldr     x10,=operatingsystem_result
+       ldr     w0,[x10]
+       mov     w8,#94 // syscall_nr_exit_group
+       svc     #0
+       b       _haltproc
+
+       /* Define a symbol for the first piece of initialized data. */
+       .data
+       .align 3
+       .globl __data_start
+__data_start:
+       .long 0
+       .weak data_start
+       data_start = __data_start
+
+       .bss
+       .align 3
+
+       .comm __dl_fini,8
+       .comm __stkptr,8
+
+       .comm operatingsystem_parameter_envp,8
+       .comm operatingsystem_parameter_argc,8
+       .comm operatingsystem_parameter_argv,8
+
+       .section .note.GNU-stack,"",%progbits
diff --git a/fpcsrc/rtl/linux/aarch64/sighnd.inc b/fpcsrc/rtl/linux/aarch64/sighnd.inc
new file mode 100644 (file)
index 0000000..011b63a
--- /dev/null
@@ -0,0 +1,44 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Michael Van Canneyt,
+    member of the Free Pascal development team.
+
+    Signal handler is arch dependant due to processor to language
+    exception conversion.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+procedure SignalToRunerror(Sig: longint; SigInfo: PSigInfo; UContext: PUContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
+
+var
+  res : word;
+begin
+  res:=0;
+  case sig of
+    SIGFPE:
+        res:=207;
+    SIGILL:
+        res:=216;
+    SIGSEGV :
+        res:=216;
+    SIGBUS:
+        res:=214;
+    SIGINT:
+        res:=217;
+    SIGQUIT:
+        res:=233;
+  end;
+  reenable_signal(sig);
+  { give runtime error at the position where the signal was raised }
+  if res<>0 then
+    HandleErrorAddrFrame(res,
+      pointer(uContext^.uc_mcontext.pc),
+      pointer(uContext^.uc_mcontext.regs[29]));
+end;
diff --git a/fpcsrc/rtl/linux/aarch64/sighndh.inc b/fpcsrc/rtl/linux/aarch64/sighndh.inc
new file mode 100644 (file)
index 0000000..8fa6a35
--- /dev/null
@@ -0,0 +1,47 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Jonas Maebe,
+    member of the Free Pascal development team.
+
+    TSigContext and associated structures.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$packrecords C}
+
+type
+  PSigContext = ^TSigContext;
+  TSigContext = record
+    fault_address : cULong;
+    regs : array[0..30] of cULong;
+    sp : cULong;
+    pc : cULong;
+    pstate : cULong;
+    __pad : cULong;
+    { The following field should be 16-byte-aligned. Currently the
+      directive for specifying alignment is buggy, so the preceding
+      field was added so that the record has the right size. }
+    __reserved : array[0..4095] of cUChar;
+  end;
+
+  stack_t = record
+    ss_sp : pointer;
+    ss_flags : cInt;
+    ss_size : size_t;
+  end;
+
+  PUContext = ^TUContext;
+  TUContext = record
+    uc_flags : cULong;
+    uc_link : PUContext;
+    uc_stack : stack_t;
+    uc_mcontext : TSigContext;
+    uc_sigmask : sigset_t;
+  end;
diff --git a/fpcsrc/rtl/linux/aarch64/stat.inc b/fpcsrc/rtl/linux/aarch64/stat.inc
new file mode 100644 (file)
index 0000000..6d69441
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Jonas Maebe, (c) 2005 Thomas Schatzl,
+    members of the Free Pascal development team.
+
+    Contains the definition of the stat type for the PowerPC64 platform.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ This structure was adapted from
+
+    include/uapi/asm-generic/stat.h
+
+  in Linux 4.0. Note that the stat record is the same for direct
+  syscalls as for when linking to libc.
+}
+
+{$PACKRECORDS C}
+  stat = record
+    case integer of
+    0 : (
+      st_dev        : cULong;
+      st_ino        : cULong;
+      st_mode       : cUInt;
+      st_nlink      : cUInt;
+      st_uid        : cUInt;
+      st_gid        : cUInt;
+      st_rdev       : cULong;
+      __pad1a       : cULong;
+      st_size       : cLong;
+      st_blksize    : cInt;
+      __pad2a       : cInt;
+      st_blocks     : cLong;
+      st_atime      : cLong;
+      st_atime_nsec : cULong;
+      st_mtime      : cLong;
+      st_mtime_nsec : cULong;
+      st_ctime      : cLong;
+      st_ctime_nsec : cULong;
+      __unused4a    : cUInt;
+      __unused5a    : cUInt;
+      );
+    1 : (
+      dev           : cULong deprecated;
+      ino           : cULong deprecated;
+      mode          : cUInt deprecated;
+      nlink         : cUInt deprecated;
+      uid           : cUInt deprecated;
+      gid           : cUInt deprecated;
+      rdev          : cULong deprecated;
+      __pad1b       : cULong deprecated;
+      size          : cLong deprecated;
+      blksize       : cInt deprecated;
+      __pad2b       : cInt deprecated;
+      blocks        : cLong deprecated;
+      atime         : cLong deprecated;
+      atime_nsec    : cULong deprecated;
+      mtime         : cLong deprecated;
+      mtime_nsec    : cULong deprecated;
+      ctime         : cLong deprecated;
+      ctime_nsec    : cULong deprecated;
+      __unused4b    : cUInt deprecated;
+      __unused5b    : cUInt deprecated;
+      );
+  end;
diff --git a/fpcsrc/rtl/linux/aarch64/syscall.inc b/fpcsrc/rtl/linux/aarch64/syscall.inc
new file mode 100644 (file)
index 0000000..5001aa6
--- /dev/null
@@ -0,0 +1,127 @@
+{
+  This file is part of the Free Pascal run time library.
+
+  Perform syscall with 0..6 arguments.
+  If syscall return value is negative, negate it, set errno, and return -1.
+
+  Written by Edmund Grimley Evans in 2015 and released into the public domain.
+}
+
+function FpSysCall(sysnr:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
+asm
+  mov w8,w0
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL1'];
+asm
+  mov w8,w0
+  mov x0,x1
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL2'];
+asm
+  mov w8,w0
+  mov x0,x1
+  mov x1,x2
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL3'];
+asm
+  mov w8,w0
+  mov x0,x1
+  mov x1,x2
+  mov x2,x3
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL4'];
+asm
+  mov w8,w0
+  mov x0,x1
+  mov x1,x2
+  mov x2,x3
+  mov x3,x4
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL5'];
+asm
+  mov w8,w0
+  mov x0,x1
+  mov x1,x2
+  mov x2,x3
+  mov x3,x4
+  mov x4,x5
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL6'];
+asm
+  mov w8,w0
+  mov x0,x1
+  mov x1,x2
+  mov x2,x3
+  mov x3,x4
+  mov x4,x5
+  mov x5,x6
+  svc #0
+  tbz x0,#63,.Ldone
+  str x30,[sp,#-16]!
+  neg x0,x0
+  bl seterrno
+  ldr x30,[sp],#16
+  mov x0,#-1
+.Ldone:
+end;
diff --git a/fpcsrc/rtl/linux/aarch64/syscallh.inc b/fpcsrc/rtl/linux/aarch64/syscallh.inc
new file mode 100644 (file)
index 0000000..6961a19
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    Copyright (c) 2002 by Marco van de Voort
+
+    Header for syscalls in system unit.
+
+    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., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301, USA.
+
+ ****************************************************************************
+
+}
+
+Type
+  TSysResult = Int64;
+  TSysParam  = Int64;
+
+function Do_SysCall(sysnr:TSysParam):TSysResult; external name 'FPC_SYSCALL0';
+function Do_SysCall(sysnr,param1:TSysParam):TSysResult; external name 'FPC_SYSCALL1';
+function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult; external name 'FPC_SYSCALL2';
+function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; external name 'FPC_SYSCALL3';
+function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; external name 'FPC_SYSCALL4';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult; external name 'FPC_SYSCALL5';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult; external name 'FPC_SYSCALL6';
diff --git a/fpcsrc/rtl/linux/aarch64/sysnr.inc b/fpcsrc/rtl/linux/aarch64/sysnr.inc
new file mode 100644 (file)
index 0000000..3763caa
--- /dev/null
@@ -0,0 +1 @@
+{$i ../sysnr-gen.inc}
index afd68b7b79a56f0d62f3e35f8c6e9ab90ada0fc4..c8d78496725adacd163a518b26a346203d378d84 100644 (file)
@@ -297,7 +297,11 @@ end;
 function fpgetpgrp : pid_t;
 
 begin
+{$if defined(generic_linux_syscalls)}
+ fpgetpgrp:=do_syscall(syscall_nr_getpgid,0);
+{$else}
  fpgetpgrp:=do_syscall(syscall_nr_getpgrp);
+{$endif}
 end;
 
 function fpsetsid : pid_t;
@@ -327,29 +331,59 @@ Function fplink(existing:pchar;newone:pchar):cint;
   In effect, new will be the same file as old.
 }
 begin
+{$if defined(generic_linux_syscalls)}
+  fpLink:=Do_Syscall(syscall_nr_linkat,AT_FDCWD,TSysParam(existing),AT_FDCWD,TSysParam(newone),0);
+{$else}
   fpLink:=Do_Syscall(syscall_nr_link,TSysParam(existing),TSysParam(newone));
+{$endif}
 end;
 
 Function fpmkfifo(path:pchar;mode:mode_t):cint;
 
 begin
 
+{$if defined(generic_linux_syscalls)}
+fpmkfifo:=do_syscall(syscall_nr_mknodat,AT_FDCWD,TSysParam(path),TSysParam(mode or S_IFIFO),TSysParam(0));
+{$else}
 fpmkfifo:=do_syscall(syscall_nr_mknod,TSysParam(path),TSysParam(mode or S_IFIFO),TSysParam(0));
+{$endif}
 end;
 
 Function fpchmod(path:pchar;mode:mode_t):cint;
 
 begin
+{$if defined(generic_linux_syscalls)}
+  fpchmod:=do_syscall(syscall_nr_fchmodat,AT_FDCWD,TSysParam(path),TSysParam(mode),0);
+{$else}
   fpchmod:=do_syscall(syscall_nr_chmod,TSysParam(path),TSysParam(mode));
+{$endif}
 end;
 
 Function fpchown(path:pchar;owner:uid_t;group:gid_t):cint;
 
 begin
+{$if defined(generic_linux_syscalls)}
+  fpChOwn:=do_syscall(syscall_nr_fchownat,AT_FDCWD,TSysParam(path),TSysParam(owner),TSysParam(group),0);
+{$else}
   fpChOwn:=do_syscall(syscall_nr_chown,TSysParam(path),TSysParam(owner),TSysParam(group));
+{$endif}
 end;
 
-{$ifndef NO_SYSCALL_UTIME}
+{$if defined(generic_linux_syscalls)}
+
+Function fpUtime(path:pchar;times:putimbuf):cint;
+var
+  tsa: Array[0..1] of timespec;
+begin
+  tsa[0].tv_sec := times^.actime;
+  tsa[0].tv_nsec := 0;
+  tsa[1].tv_sec := times^.modtime;
+  tsa[1].tv_nsec := 0;
+  fputime:=do_syscall(syscall_nr_utimensat,AT_FDCWD,TSysParam(path),
+                      TSysParam(@tsa),0);
+end;
+
+{$elseif not defined(NO_SYSCALL_UTIME)}
 
 Function fpUtime(path:pchar;times:putimbuf):cint;
 
@@ -377,7 +411,11 @@ end;
 Function fppipe(var fildes : tfildes):cint;
 
 begin
+{$if defined(generic_linux_syscalls)}
+ fppipe:=do_syscall(syscall_nr_pipe2,TSysParam(@fildes),0);
+{$else}
  fppipe:=do_syscall(syscall_nr_pipe,TSysParam(@fildes));
+{$endif}
 end;
 {$endif FPC_BASEUNIX_HAS_FPPIPE}
 
@@ -422,6 +460,18 @@ Function fpSelect(N:cint;readfds,writefds,exceptfds:pfdSet;TimeOut:PTimeVal):cin
   Select checks whether the file descriptor sets in readfs/writefs/exceptfs
   have changed.
 }
+{$if defined(generic_linux_syscalls)}
+
+var ts : timespec;
+begin
+  ts.tv_sec := timeout^.tv_sec;
+  ts.tv_nsec := timeout^.tv_usec * 1000;
+  fpSelect:=do_syscall(syscall_nr_pselect6,n,
+                       tsysparam(readfds),tsysparam(writefds),
+                       tsysparam(exceptfds),tsysparam(@ts),0);
+end;
+
+{$else}
 
 begin
 {$ifdef cpux86_64}
@@ -436,10 +486,27 @@ begin
 {$endif bunxfunc_fpselect_implemented}
 end;
 
+{$endif}
+
 function fpPoll(fds: ppollfd; nfds: cuint; timeout: clong): cint;
+{$if defined(generic_linux_syscalls)}
+var ts : timespec;
+begin
+  if timeout<0 then
+    fpPoll:=do_syscall(syscall_nr_ppoll,tsysparam(fds),tsysparam(nfds),0,0)
+  else
+    begin
+      ts.tv_sec := timeout div 1000;
+      ts.tv_nsec := (timeout mod 1000) * 1000000;
+      fpPoll:=do_syscall(syscall_nr_ppoll,tsysparam(fds),tsysparam(nfds),
+                         tsysparam(@ts),0);
+    end
+end;
+{$else}
 begin
   fpPoll:=do_syscall(syscall_nr_poll,tsysparam(fds),tsysparam(nfds),tsysparam(timeout));
 end;
+{$endif}
 
 Function fpLstat(path:pchar;Info:pstat):cint;
 {
@@ -447,6 +514,9 @@ Function fpLstat(path:pchar;Info:pstat):cint;
 }
 
 begin
+{$if defined(generic_linux_syscalls)}
+ fpLStat:=do_syscall(syscall_nr_fstatat,AT_FDCWD,TSysParam(path),TSysParam(info),0)
+{$else}
  fpLStat:=do_syscall(
 {$ifdef cpu64}
     syscall_nr_lstat,
@@ -454,6 +524,7 @@ begin
     syscall_nr_lstat64,
 {$endif}
     TSysParam(path),TSysParam(info));
+{$endif}
 end;
 
 
@@ -465,12 +536,12 @@ function fpNice(N:cint):cint;
 Doesn't exist in BSD. Linux emu uses setpriority in a construct as below:
 }
 
-{$ifdef cpux86_64}
+{$if defined(generic_linux_syscalls) or defined(cpux86_64)}
 var
   oldprio : cint;
 {$endif}
 begin
-{$ifdef cpux86_64}
+{$if defined(generic_linux_syscalls) or defined(cpux86_64)}
   oldprio:=fpGetPriority(Prio_Process,0);
   fpNice:=fpSetPriority(Prio_Process,0,oldprio+N);
   if fpNice=0 then
@@ -536,7 +607,11 @@ Function fpSymlink(oldname,newname:pchar):cint;
 }
 
 begin
+{$if defined(generic_linux_syscalls)}
+  fpsymlink:=do_syscall(syscall_nr_symlinkat,TSysParam(oldname),AT_FDCWD,TSysParam(newname));
+{$else}
   fpsymlink:=do_syscall(syscall_nr_symlink,TSysParam(oldname),TSysParam(newname));
+{$endif}
 end;
 
 function Fppread(fd: cint; buf: pchar; nbytes : size_t; offset:Toff): ssize_t; [public, alias : 'FPC_SYSC_PREAD'];
index d9f4f51b26399e56c939fad1a342e38b34dddd1b..4f4333f9dc68b2ddbe5d04be29704adc7b90e1bb 100644 (file)
@@ -17,6 +17,8 @@
 **********************************************************************}
 unit Linux;
 
+{$i osdefs.inc}
+
 {$packrecords c}
 {$ifdef FPC_USE_LIBC} 
  {$linklib rt} // for clock* functions
@@ -527,7 +529,11 @@ end;
 
 function epoll_create(size: cint): cint;
 begin
+{$if defined(generic_linux_syscalls)}
+  epoll_create := do_syscall(syscall_nr_epoll_create1,0)
+{$else}
   epoll_create := do_syscall(syscall_nr_epoll_create,tsysparam(size));
+{$endif}
 end;
 
 function epoll_ctl(epfd, op, fd: cint; event: pepoll_event): cint;
@@ -538,8 +544,13 @@ end;
 
 function epoll_wait(epfd: cint; events: pepoll_event; maxevents, timeout: cint): cint;
 begin
+{$if defined(generic_linux_syscalls)}
+  epoll_wait := do_syscall(syscall_nr_epoll_pwait, tsysparam(epfd),
+    tsysparam(events), tsysparam(maxevents), tsysparam(timeout),0);
+{$else}
   epoll_wait := do_syscall(syscall_nr_epoll_wait, tsysparam(epfd),
     tsysparam(events), tsysparam(maxevents), tsysparam(timeout));
+{$endif}
 end;
 
 function capget(header:Puser_cap_header;data:Puser_cap_data):cint;
@@ -695,7 +706,11 @@ end;
 function inotify_init1(flags:cint):cint;
 
 begin
+{$if defined(generic_linux_syscalls)}
+  inotify_init1:=do_SysCall(syscall_nr_inotify_init1,tsysparam(flags));
+{$else}
   inotify_init1:=do_SysCall(syscall_nr_inotify_init,tsysparam(flags));
+{$endif}
 end;
 
 function inotify_add_watch(fd:cint; name:Pchar; mask:cuint32):cint;
index 1a87825725164108a8d0ebaf4cd451234c7daf03..5fd08913117164bd6e3e18d8c0b88828de256703 100644 (file)
@@ -1924,9 +1924,16 @@ Function Sys_Mkdir(Filename:pchar;mode:longint):longint;
 var
   regs : SysCallregs;
 begin
+{$if defined(generic_linux_syscalls)}
+  regs.reg2:=AT_FDCWD;
+  regs.reg3:=longint(filename);
+  regs.reg4:=mode;
+  Sys_MkDir:=SysCall(SysCall_nr_mkdirat,regs);
+{$else}
   regs.reg2:=longint(filename);
   regs.reg3:=mode;
   Sys_MkDir:=SysCall(SysCall_nr_mkdir,regs);
+{$endif}
 end;
 
 
@@ -1935,8 +1942,15 @@ Function Sys_Rmdir(Filename:pchar):longint;
 var
   regs : SysCallregs;
 begin
+{$if defined(generic_linux_syscalls)}
+  regs.reg2:=AT_FDCWD;
+  regs.reg3:=longint(filename);
+  regs.reg4:=AT_REMOVEDIR;
+  Sys_Rmdir:=SysCall(SysCall_nr_unlinkat,regs);
+{$else}
   regs.reg2:=longint(filename);
   Sys_Rmdir:=SysCall(SysCall_nr_rmdir,regs);
+{$endif}
 end;
 
 
@@ -2744,7 +2758,18 @@ var
 begin
   sr.reg2:=oldfile;
   sr.reg3:=newfile;
+{$if defined(generic_linux_syscalls)}
+  sr.reg4:=0;
+  if oldfile<>newfile then
+    SysCall(Syscall_nr_dup3,sr)
+  else
+    begin
+      sr.reg3:=F_GetFd;
+      SysCall(Syscall_nr_fcntl,sr);
+    end;
+{$else}
   SysCall(Syscall_nr_dup2,sr);
+{$endif}
   linuxerror:=errno;
   Dup2:=(LinuxError=0);
 end;
@@ -2782,7 +2807,12 @@ var
   regs : SysCallregs;
 begin
   regs.reg2:=longint(@pip);
+{$if defined(generic_linux_syscalls)}
+  regs.reg3:=0;
+  SysCall(SysCall_nr_pipe2,regs);
+{$else}
   SysCall(SysCall_nr_pipe,regs);
+{$endif}
   pipe_in:=pip[1];
   pipe_out:=pip[2];
   linuxerror:=errno;
index cfb86faec401af6bd81f91e99b46cf63b38aa62d..a8da1dd8e7ef772fd80166f7d9c6904396d850a9 100644 (file)
@@ -85,3 +85,7 @@
   {$endif FPC_ABI_EABI}
 {$endif cpuarm}
 
+{$ifdef cpuaarch64}
+  {$define generic_linux_syscalls}
+  {$undef usestime}
+{$endif cpuaarch64}
index ad360c4d7269c0df96ff14ca5e0ff478ccac63be..52f80bea81adedfd45d010ac6c8897c3728d0675 100644 (file)
@@ -20,7 +20,7 @@
 *****************************************************************************}
 
 function Fptime(tloc:pTime_t): Time_t; [public, alias : 'FPC_SYSC_TIME'];
-{$ifdef FPC_USEGETTIMEOFDAY}
+{$if defined(generic_linux_syscalls) or defined(FPC_USEGETTIMEOFDAY)}
 VAR tv     : timeval;
     tz     : timezone;
     retval : longint;
@@ -49,7 +49,11 @@ end;
 function Fpopen(path: pchar; flags : cint; mode: mode_t):cint; [public, alias : 'FPC_SYSC_OPEN'];
 
 Begin
+{$if defined(generic_linux_syscalls)}
+ Fpopen:=do_syscall(syscall_nr_openat,AT_FDCWD,TSysParam(path),TSysParam(flags or O_LARGEFILE),TSysParam(mode));
+{$else}
  Fpopen:=do_syscall(syscall_nr_open,TSysParam(path),TSysParam(flags or O_LARGEFILE),TSysParam(mode));
+{$endif}
 End;
 
 function Fpclose(fd : cint): cint; [public, alias : 'FPC_SYSC_CLOSE'];
@@ -98,20 +102,32 @@ end;
 function Fpunlink(path: pchar): cint; [public, alias : 'FPC_SYSC_UNLINK'];
 
 begin
+{$if defined(generic_linux_syscalls)}
+  Fpunlink:=do_syscall(syscall_nr_unlinkat,AT_FDCWD,TSysParam(path),0);
+{$else}
   Fpunlink:=do_syscall(syscall_nr_unlink,TSysParam(path));
+{$endif}
 end;
 
 function Fprename(old : pchar; newpath: pchar): cint; [public, alias : 'FPC_SYSC_RENAME'];
 
 begin
+{$if defined(generic_linux_syscalls)}
+  Fprename:=do_syscall(syscall_nr_renameat,AT_FDCWD,TSysParam(old),AT_FDCWD,TSysParam(newpath));
+{$else}
   Fprename:=do_syscall(syscall_nr_rename,TSysParam(old),TSysParam(newpath));
+{$endif}
 end;
 
 function Fpstat(path: pchar; var buf: stat):cint; [public, alias : 'FPC_SYSC_STAT'];
 
 begin
 {$if defined(cpu64)}
-  Fpstat:=do_syscall(syscall_nr_stat,TSysParam(path),TSysParam(@buf));
+  {$if defined(generic_linux_syscalls)}
+    Fpstat:=do_syscall(syscall_nr_fstatat,AT_FDCWD,TSysParam(path),TSysParam(@buf),0);
+  {$else}
+    Fpstat:=do_syscall(syscall_nr_stat,TSysParam(path),TSysParam(@buf));
+  {$endif}
 {$else}
   Fpstat:=do_syscall(syscall_nr_stat64,TSysParam(path),TSysParam(@buf));
 {$endif}
@@ -130,13 +146,21 @@ end;
 function Fpmkdir(path : pchar; mode: mode_t):cint; [public, alias : 'FPC_SYSC_MKDIR'];
 
 begin
+{$if defined(generic_linux_syscalls)}
+  Fpmkdir:=do_syscall(syscall_nr_mkdirat,AT_FDCWD,TSysParam(path),TSysParam(mode));
+{$else}
   Fpmkdir:=do_syscall(syscall_nr_mkdir,TSysParam(path),TSysParam(mode));
+{$endif}
 end;
 
 function Fprmdir(path : pchar): cint;  [public, alias : 'FPC_SYSC_RMDIR'];
 
 begin
+{$if defined(generic_linux_syscalls)}
+ Fprmdir:=do_syscall(syscall_nr_unlinkat,AT_FDCWD,TSysParam(path),AT_REMOVEDIR);
+{$else}
  Fprmdir:=do_syscall(syscall_nr_rmdir,TSysParam(path));
+{$endif}
 end;
 
 function Fpopendir(dirname : pchar): pdir;  [public, alias : 'FPC_SYSC_OPENDIR'];
@@ -363,7 +387,11 @@ function Fpfstat(fd : cint; var sb : stat): cint;  [public, alias : 'FPC_SYSC_FS
 
 begin
 {$if defined(cpu64)}
-  FpFStat:=do_SysCall(syscall_nr_fstat,TSysParam(fd),TSysParam(@sb));
+  {$if defined(generic_linux_syscalls)}
+    FpFStat:=do_SysCall(syscall_nr_fstat,TSysParam(fd),TSysParam(@sb));
+  {$else}
+    FpFStat:=do_SysCall(syscall_nr_fstat,TSysParam(fd),TSysParam(@sb));
+  {$endif}
 {$else}
   FpFStat:=do_SysCall(syscall_nr_fstat64,TSysParam(fd),TSysParam(@sb));
 {$endif}
@@ -380,9 +408,14 @@ function Fpfork : pid_t;  [public, alias : 'FPC_SYSC_FORK'];
   A negative value indicates that an error has occurred, the error is returned in
   LinuxError.
 }
-
+var
+  pid : Int64;
 Begin
+{$if defined(generic_linux_syscalls)}
+ Fpfork:=Do_syscall(syscall_nr_clone,clone_flags_fork,0,0,0,TSysParam(@pid));
+{$else}
  Fpfork:=Do_syscall(SysCall_nr_fork);
+{$endif}
 End;
 {$endif FPC_SYSTEM_HAS_FPFORK}
 
@@ -425,7 +458,7 @@ function Fpwaitpid(pid : pid_t; stat_loc : pcint; options: cint): pid_t; [public
 }
 
 begin
-{$ifdef WAIT4}
+{$if defined(generic_linux_syscalls) or defined(WAIT4)}
  FpWaitPID:=do_syscall(syscall_nr_Wait4,PID,TSysParam(Stat_loc),options,0);
 {$else WAIT4}
  FpWaitPID:=do_syscall(syscall_nr_WaitPID,PID,TSysParam(Stat_loc),options);
@@ -447,7 +480,11 @@ function Fpaccess(pathname : pchar; amode : cint): cint; [public, alias : 'FPC_S
 }
 
 begin
+{$if defined(generic_linux_syscalls)}
+ FpAccess:=do_syscall(syscall_nr_faccessat,AT_FDCWD,TSysParam(pathname),amode,0);
+{$else}
  FpAccess:=do_syscall(syscall_nr_access,TSysParam(pathname),amode);
+{$endif}
 end;
 
 (* overloaded
@@ -481,7 +518,16 @@ end;
 Function FpDup2(fildes,fildes2:cint):cint; [public, alias : 'FPC_SYSC_DUP2'];
 
 begin
+{$if defined(generic_linux_syscalls)}
+ if fildes<>fildes2 then
+   Fpdup2:=do_syscall(syscall_nr_dup3,TSysParam(fildes),TSysParam(fildes2),0)
+ else if do_syscall(syscall_nr_fcntl,TSysParam(fildes),1)<>-1 then
+   Fpdup2:=fildes2
+ else
+   Fpdup2:=-1;
+{$else}
  Fpdup2:=do_syscall(syscall_nr_dup2,TSysParam(fildes),TSysParam(fildes2));
+{$endif}
 end;
 
 
@@ -572,7 +618,11 @@ end;
 Function FpReadLink(name,linkname:pchar;maxlen:size_t):cint;  [public, alias : 'FPC_SYSC_READLINK'];
 
 begin
+{$if defined(generic_linux_syscalls)}
+  Fpreadlink:=do_syscall(syscall_nr_readlinkat,AT_FDCWD,TSysParam(name),TSysParam(linkname),maxlen);
+{$else}
   Fpreadlink:=do_syscall(syscall_nr_readlink, TSysParam(name),TSysParam(linkname),maxlen);
+{$endif}
 end;
 
 
index ac19d74addd922ca43c60977493fa8470a9e4d81..61242b756d13bc666220b30360216917518b314f 100644 (file)
@@ -290,7 +290,12 @@ CONST
 {$endif not cpumips}
 {$endif not cpusparc}
 
-{$if defined(cpuarm) or defined(cpualpha) or defined(cpublackfin) or defined(cpum68k)}
+    AT_FDCWD = -100;
+    AT_REMOVEDIR = $200;
+    clone_flags_fork = $01200011;
+      { SIGCHLD | CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID }
+
+{$if defined(cpuarm) or defined(cpualpha) or defined(cpublackfin) or defined(cpum68k) or defined(aarch64)}
     O_LARGEFILE =   $20000;
 {$endif}
 {$if defined(cpusparc) or defined(cpusparc64)}
diff --git a/fpcsrc/rtl/linux/pmutext.inc b/fpcsrc/rtl/linux/pmutext.inc
new file mode 100644 (file)
index 0000000..d762603
--- /dev/null
@@ -0,0 +1,58 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Peter Vreman
+    member of the Free Pascal development team.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ definition of pthread_mutex_t, because needed in both ptypes.inc and }
+{ in sysosh.inc                                                        }
+
+{ use a macro rather than a constant, so this name doesn't get exported
+  from the system unit interface; macro's have to be on at this point
+  because they're use to propagate the MUTEXTYPENAME here }
+
+{$if defined(CPUMIPS) or defined(cpuaarch64)}
+{$define USE_PTHREAD_SIZEOF}
+
+{$if defined(cpuaarch64)}
+  {$define __SIZEOF_PTHREAD_MUTEX_T := 48}
+{$elseif defined(CPU64)}
+  {$define __SIZEOF_PTHREAD_MUTEX_T := 40}
+{$else CPU64}
+  {$define __SIZEOF_PTHREAD_MUTEX_T := 24}
+{$endif CPU64}
+
+{$endif MIPS}
+
+  MUTEXTYPENAME = record
+    case byte of
+{$ifdef USE_PTHREAD_SIZEOF}
+      0 : (
+        __size : array[0..__SIZEOF_PTHREAD_MUTEX_T-1] of char;
+        __align : sizeint;
+      );
+{$endif}
+      1 : (
+        __m_reserved: longint;
+        __m_count: longint;
+        __m_owner: pointer;
+        __m_kind:  longint;
+        __m_lock:  record
+           __status: sizeint;
+          __spinlock: longint;
+        end;
+       );
+  end;
+
+{$ifdef __SIZEOF_PTHREAD_MUTEX_T}
+{$undef __SIZEOF_PTHREAD_MUTEX_T}
+{$endif __SIZEOF_PTHREAD_MUTEX_T}
+{$macro off}
\ No newline at end of file
index 14e6c181b65f1c11a79493aae26b12c09957e3f4..f3b30270913e3edf9ce0067ae21eff55bca8b373 100644 (file)
@@ -30,12 +30,21 @@ and all three 32-bit systems returned completely identical types too
 introduction)
 }
 
-{$ifdef CPUMIPS}
+{$if defined(CPUMIPS) or defined(cpuaarch64)}
 {$define USE_PTHREAD_SIZEOF}
-{$ifdef CPU64}
+{$if defined(cpuaarch64)}
+const
+  __SIZEOF_PTHREAD_ATTR_T = 64;
+  __SIZEOF_PTHREAD_MUTEXATTR_T = 8;
+  __SIZEOF_PTHREAD_COND_T = 48;
+  __SIZEOF_PTHREAD_CONDATTR_T = 8;
+  __SIZEOF_PTHREAD_RWLOCK_T = 56;
+  __SIZEOF_PTHREAD_RWLOCKATTR_T = 8;
+  __SIZEOF_PTHREAD_BARRIER_T = 32;
+  __SIZEOF_PTHREAD_BARRIERATTR_T = 8;
+{$elseif defined(CPU64)}
 const
   __SIZEOF_PTHREAD_ATTR_T = 56;
-  __SIZEOF_PTHREAD_MUTEX_T = 40;
   __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
   __SIZEOF_PTHREAD_COND_T = 48;
   __SIZEOF_PTHREAD_CONDATTR_T = 4;
@@ -46,7 +55,6 @@ const
 {$else : not CPU64, i.e. CPU32}
 const
   __SIZEOF_PTHREAD_ATTR_T = 36;
-  __SIZEOF_PTHREAD_MUTEX_T = 24;
   __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
   __SIZEOF_PTHREAD_COND_T = 48;
   __SIZEOF_PTHREAD_CONDATTR_T = 4;
@@ -55,7 +63,7 @@ const
   __SIZEOF_PTHREAD_BARRIER_T = 20;
   __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
 {$endif CPU32}
-{$endif MIPS}
+{$endif}
 
 {$I ctypes.inc}
 {$packrecords c}
@@ -256,24 +264,11 @@ Type
     __spinlock: cint;
   end;
 
-  pthread_mutex_t = record
-  {$ifdef USE_PTHREAD_SIZEOF}
-  case byte of
-   0 : (
-        __size : array[0..__SIZEOF_PTHREAD_MUTEX_T-1] of char;
-        __align : clong;
-       );
-  1 : (
-  {$endif}     
-    __m_reserved: cint;
-    __m_count: cint;
-    __m_owner: pointer;
-    __m_kind:  cint;
-    __m_lock: _pthread_fastlock;
-  {$ifdef USE_PTHREAD_SIZEOF}
-       );
-  {$endif}     
-  end;
+{$macro on}
+{$define MUTEXTYPENAME := pthread_mutex_t}
+{$i pmutext.inc}
+{$undef MUTEXTYPENAME}
+{$macro off}
 
   pthread_mutexattr_t = record
   {$ifdef USE_PTHREAD_SIZEOF}
diff --git a/fpcsrc/rtl/linux/sysnr-gen.inc b/fpcsrc/rtl/linux/sysnr-gen.inc
new file mode 100644 (file)
index 0000000..3525861
--- /dev/null
@@ -0,0 +1,277 @@
+
+{
+  System call numbers taken from include/uapi/asm-generic/unistd.h
+  in a 4.0 Linux kernel. They are therefore architecture-independent,
+  though only the newest architectures use this generic list.
+}
+
+Const
+        syscall_nr_io_setup                     = 0;
+        syscall_nr_io_destroy                   = 1;
+        syscall_nr_io_submit                    = 2;
+        syscall_nr_io_cancel                    = 3;
+        syscall_nr_io_getevents                 = 4;
+        syscall_nr_setxattr                     = 5;
+        syscall_nr_lsetxattr                    = 6;
+        syscall_nr_fsetxattr                    = 7;
+        syscall_nr_getxattr                     = 8;
+        syscall_nr_lgetxattr                    = 9;
+        syscall_nr_fgetxattr                    = 10;
+        syscall_nr_listxattr                    = 11;
+        syscall_nr_llistxattr                   = 12;
+        syscall_nr_flistxattr                   = 13;
+        syscall_nr_removexattr                  = 14;
+        syscall_nr_lremovexattr                 = 15;
+        syscall_nr_fremovexattr                 = 16;
+        syscall_nr_getcwd                       = 17;
+        syscall_nr_lookup_dcookie               = 18;
+        syscall_nr_eventfd2                     = 19;
+        syscall_nr_epoll_create1                = 20;
+        syscall_nr_epoll_ctl                    = 21;
+        syscall_nr_epoll_pwait                  = 22;
+        syscall_nr_dup                          = 23;
+        syscall_nr_dup3                         = 24;
+        syscall_nr_fcntl                        = 25;
+        syscall_nr_inotify_init1                = 26;
+        syscall_nr_inotify_add_watch            = 27;
+        syscall_nr_inotify_rm_watch             = 28;
+        syscall_nr_ioctl                        = 29;
+        syscall_nr_ioprio_set                   = 30;
+        syscall_nr_ioprio_get                   = 31;
+        syscall_nr_flock                        = 32;
+        syscall_nr_mknodat                      = 33;
+        syscall_nr_mkdirat                      = 34;
+        syscall_nr_unlinkat                     = 35;
+        syscall_nr_symlinkat                    = 36;
+        syscall_nr_linkat                       = 37;
+        syscall_nr_renameat                     = 38;
+        syscall_nr_umount2                      = 39;
+        syscall_nr_mount                        = 40;
+        syscall_nr_pivot_root                   = 41;
+        syscall_nr_nfsservctl                   = 42;
+        syscall_nr_statfs                       = 43;
+        syscall_nr_fstatfs                      = 44;
+        syscall_nr_truncate                     = 45;
+        syscall_nr_ftruncate                    = 46;
+        syscall_nr_fallocate                    = 47;
+        syscall_nr_faccessat                    = 48;
+        syscall_nr_chdir                        = 49;
+        syscall_nr_fchdir                       = 50;
+        syscall_nr_chroot                       = 51;
+        syscall_nr_fchmod                       = 52;
+        syscall_nr_fchmodat                     = 53;
+        syscall_nr_fchownat                     = 54;
+        syscall_nr_fchown                       = 55;
+        syscall_nr_openat                       = 56;
+        syscall_nr_close                        = 57;
+        syscall_nr_vhangup                      = 58;
+        syscall_nr_pipe2                        = 59;
+        syscall_nr_quotactl                     = 60;
+        syscall_nr_getdents64                   = 61;
+        syscall_nr_lseek                        = 62;
+        syscall_nr_read                         = 63;
+        syscall_nr_write                        = 64;
+        syscall_nr_readv                        = 65;
+        syscall_nr_writev                       = 66;
+        syscall_nr_pread64                      = 67;
+        syscall_nr_pwrite64                     = 68;
+        syscall_nr_preadv                       = 69;
+        syscall_nr_pwritev                      = 70;
+        syscall_nr_sendfile                     = 71;
+        syscall_nr_pselect6                     = 72;
+        syscall_nr_ppoll                        = 73;
+        syscall_nr_signalfd4                    = 74;
+        syscall_nr_vmsplice                     = 75;
+        syscall_nr_splice                       = 76;
+        syscall_nr_tee                          = 77;
+        syscall_nr_readlinkat                   = 78;
+        syscall_nr_fstatat                      = 79;
+        syscall_nr_fstat                        = 80;
+        syscall_nr_sync                         = 81;
+        syscall_nr_fsync                        = 82;
+        syscall_nr_fdatasync                    = 83;
+        syscall_nr_sync_file_range              = 84;
+        syscall_nr_timerfd_create               = 85;
+        syscall_nr_timerfd_settime              = 86;
+        syscall_nr_timerfd_gettime              = 87;
+        syscall_nr_utimensat                    = 88;
+        syscall_nr_acct                         = 89;
+        syscall_nr_capget                       = 90;
+        syscall_nr_capset                       = 91;
+        syscall_nr_personality                  = 92;
+        syscall_nr_exit                         = 93;
+        syscall_nr_exit_group                   = 94;
+        syscall_nr_waitid                       = 95;
+        syscall_nr_set_tid_address              = 96;
+        syscall_nr_unshare                      = 97;
+        syscall_nr_futex                        = 98;
+        syscall_nr_set_robust_list              = 99;
+        syscall_nr_get_robust_list              = 100;
+        syscall_nr_nanosleep                    = 101;
+        syscall_nr_getitimer                    = 102;
+        syscall_nr_setitimer                    = 103;
+        syscall_nr_kexec_load                   = 104;
+        syscall_nr_init_module                  = 105;
+        syscall_nr_delete_module                = 106;
+        syscall_nr_timer_create                 = 107;
+        syscall_nr_timer_gettime                = 108;
+        syscall_nr_timer_getoverrun             = 109;
+        syscall_nr_timer_settime                = 110;
+        syscall_nr_timer_delete                 = 111;
+        syscall_nr_clock_settime                = 112;
+        syscall_nr_clock_gettime                = 113;
+        syscall_nr_clock_getres                 = 114;
+        syscall_nr_clock_nanosleep              = 115;
+        syscall_nr_syslog                       = 116;
+        syscall_nr_ptrace                       = 117;
+        syscall_nr_sched_setparam               = 118;
+        syscall_nr_sched_setscheduler           = 119;
+        syscall_nr_sched_getscheduler           = 120;
+        syscall_nr_sched_getparam               = 121;
+        syscall_nr_sched_setaffinity            = 122;
+        syscall_nr_sched_getaffinity            = 123;
+        syscall_nr_sched_yield                  = 124;
+        syscall_nr_sched_get_priority_max       = 125;
+        syscall_nr_sched_get_priority_min       = 126;
+        syscall_nr_sched_rr_get_interval        = 127;
+        syscall_nr_restart_syscall              = 128;
+        syscall_nr_kill                         = 129;
+        syscall_nr_tkill                        = 130;
+        syscall_nr_tgkill                       = 131;
+        syscall_nr_sigaltstack                  = 132;
+        syscall_nr_rt_sigsuspend                = 133;
+        syscall_nr_rt_sigaction                 = 134;
+        syscall_nr_rt_sigprocmask               = 135;
+        syscall_nr_rt_sigpending                = 136;
+        syscall_nr_rt_sigtimedwait              = 137;
+        syscall_nr_rt_sigqueueinfo              = 138;
+        syscall_nr_rt_sigreturn                 = 139;
+        syscall_nr_setpriority                  = 140;
+        syscall_nr_getpriority                  = 141;
+        syscall_nr_reboot                       = 142;
+        syscall_nr_setregid                     = 143;
+        syscall_nr_setgid                       = 144;
+        syscall_nr_setreuid                     = 145;
+        syscall_nr_setuid                       = 146;
+        syscall_nr_setresuid                    = 147;
+        syscall_nr_getresuid                    = 148;
+        syscall_nr_setresgid                    = 149;
+        syscall_nr_getresgid                    = 150;
+        syscall_nr_setfsuid                     = 151;
+        syscall_nr_setfsgid                     = 152;
+        syscall_nr_times                        = 153;
+        syscall_nr_setpgid                      = 154;
+        syscall_nr_getpgid                      = 155;
+        syscall_nr_getsid                       = 156;
+        syscall_nr_setsid                       = 157;
+        syscall_nr_getgroups                    = 158;
+        syscall_nr_setgroups                    = 159;
+        syscall_nr_uname                        = 160;
+        syscall_nr_sethostname                  = 161;
+        syscall_nr_setdomainname                = 162;
+        syscall_nr_getrlimit                    = 163;
+        syscall_nr_setrlimit                    = 164;
+        syscall_nr_getrusage                    = 165;
+        syscall_nr_umask                        = 166;
+        syscall_nr_prctl                        = 167;
+        syscall_nr_getcpu                       = 168;
+        syscall_nr_gettimeofday                 = 169;
+        syscall_nr_settimeofday                 = 170;
+        syscall_nr_adjtimex                     = 171;
+        syscall_nr_getpid                       = 172;
+        syscall_nr_getppid                      = 173;
+        syscall_nr_getuid                       = 174;
+        syscall_nr_geteuid                      = 175;
+        syscall_nr_getgid                       = 176;
+        syscall_nr_getegid                      = 177;
+        syscall_nr_gettid                       = 178;
+        syscall_nr_sysinfo                      = 179;
+        syscall_nr_mq_open                      = 180;
+        syscall_nr_mq_unlink                    = 181;
+        syscall_nr_mq_timedsend                 = 182;
+        syscall_nr_mq_timedreceive              = 183;
+        syscall_nr_mq_notify                    = 184;
+        syscall_nr_mq_getsetattr                = 185;
+        syscall_nr_msgget                       = 186;
+        syscall_nr_msgctl                       = 187;
+        syscall_nr_msgrcv                       = 188;
+        syscall_nr_msgsnd                       = 189;
+        syscall_nr_semget                       = 190;
+        syscall_nr_semctl                       = 191;
+        syscall_nr_semtimedop                   = 192;
+        syscall_nr_semop                        = 193;
+        syscall_nr_shmget                       = 194;
+        syscall_nr_shmctl                       = 195;
+        syscall_nr_shmat                        = 196;
+        syscall_nr_shmdt                        = 197;
+        syscall_nr_socket                       = 198;
+        syscall_nr_socketpair                   = 199;
+        syscall_nr_bind                         = 200;
+        syscall_nr_listen                       = 201;
+        syscall_nr_accept                       = 202;
+        syscall_nr_connect                      = 203;
+        syscall_nr_getsockname                  = 204;
+        syscall_nr_getpeername                  = 205;
+        syscall_nr_sendto                       = 206;
+        syscall_nr_recvfrom                     = 207;
+        syscall_nr_setsockopt                   = 208;
+        syscall_nr_getsockopt                   = 209;
+        syscall_nr_shutdown                     = 210;
+        syscall_nr_sendmsg                      = 211;
+        syscall_nr_recvmsg                      = 212;
+        syscall_nr_readahead                    = 213;
+        syscall_nr_brk                          = 214;
+        syscall_nr_munmap                       = 215;
+        syscall_nr_mremap                       = 216;
+        syscall_nr_add_key                      = 217;
+        syscall_nr_request_key                  = 218;
+        syscall_nr_keyctl                       = 219;
+        syscall_nr_clone                        = 220;
+        syscall_nr_execve                       = 221;
+        syscall_nr_mmap                         = 222;
+        syscall_nr_fadvise64                    = 223;
+        syscall_nr_swapon                       = 224;
+        syscall_nr_swapoff                      = 225;
+        syscall_nr_mprotect                     = 226;
+        syscall_nr_msync                        = 227;
+        syscall_nr_mlock                        = 228;
+        syscall_nr_munlock                      = 229;
+        syscall_nr_mlockall                     = 230;
+        syscall_nr_munlockall                   = 231;
+        syscall_nr_mincore                      = 232;
+        syscall_nr_madvise                      = 233;
+        syscall_nr_remap_file_pages             = 234;
+        syscall_nr_mbind                        = 235;
+        syscall_nr_get_mempolicy                = 236;
+        syscall_nr_set_mempolicy                = 237;
+        syscall_nr_migrate_pages                = 238;
+        syscall_nr_move_pages                   = 239;
+        syscall_nr_rt_tgsigqueueinfo            = 240;
+        syscall_nr_perf_event_open              = 241;
+        syscall_nr_accept4                      = 242;
+        syscall_nr_recvmmsg                     = 243;
+        syscall_nr_arch_specific_syscall        = 244;
+
+        syscall_nr_wait4                        = 260;
+        syscall_nr_prlimit64                    = 261;
+        syscall_nr_fanotify_init                = 262;
+        syscall_nr_fanotify_mark                = 263;
+        syscall_nr_name_to_handle_at            = 264;
+        syscall_nr_open_by_handle_at            = 265;
+        syscall_nr_clock_adjtime                = 266;
+        syscall_nr_syncfs                       = 267;
+        syscall_nr_setns                        = 268;
+        syscall_nr_sendmmsg                     = 269;
+        syscall_nr_process_vm_readv             = 270;
+        syscall_nr_process_vm_writev            = 271;
+        syscall_nr_kcmp                         = 272;
+        syscall_nr_finit_module                 = 273;
+        syscall_nr_sched_setattr                = 274;
+        syscall_nr_sched_getattr                = 275;
+        syscall_nr_renameat2                    = 276;
+        syscall_nr_seccomp                      = 277;
+        syscall_nr_getrandom                    = 278;
+        syscall_nr_memfd_create                 = 279;
+        syscall_nr_bpf                          = 280;
+        syscall_nr_execveat                     = 281;
+        syscall_nr_syscalls                     = 282;
index ee0cf0a820135997c1ce33f0f2d62bcc79895abc..62d5f2d54412e1a877060e127f42cc1d8da7df0d 100644 (file)
@@ -23,18 +23,12 @@ type
   { pthread_t is defined as an "unsigned long" }
   TThreadID = PtrUInt;
 
-  { pthread_mutex_t }
   PRTLCriticalSection = ^TRTLCriticalSection;
-  TRTLCriticalSection = record
-    __m_reserved: longint;
-    __m_count: longint;
-    __m_owner: pointer;
-    __m_kind:  longint;
-    __m_lock:  record
-       __status: sizeint;
-      __spinlock: longint;
-    end;
-  end;
+{$macro on}
+{$define MUTEXTYPENAME := TRTLCriticalSection}
+{$i pmutext.inc}
+{$undef MUTEXTYPENAME}
+{$macro off}
 
 
 
index 78cfb03b29b227304406105e2cd30677062755a5..7554839b99df5cf87e6def24824f619a90285039 100644 (file)
@@ -22,6 +22,271 @@ Const
   NCCS = 32;
   NCC = 8;
 
+{$ifdef cpuaarch64}
+
+{ from Linux 4.0, include/uapi/asm-generic/ioctls.h }
+
+  { For Terminal handling }
+  TCGETS          = $5401;
+  TCSETS          = $5402;
+  TCSETSW         = $5403;
+  TCSETSF         = $5404;
+  TCGETA          = $5405;
+  TCSETA          = $5406;
+  TCSETAW         = $5407;
+  TCSETAF         = $5408;
+  TCSBRK          = $5409;
+  TCXONC          = $540A;
+  TCFLSH          = $540B;
+  TIOCEXCL        = $540C;
+  TIOCNXCL        = $540D;
+  TIOCSCTTY       = $540E;
+  TIOCGPGRP       = $540F;
+  TIOCSPGRP       = $5410;
+  TIOCOUTQ        = $5411;
+  TIOCSTI         = $5412;
+  TIOCGWINSZ      = $5413;
+  TIOCSWINSZ      = $5414;
+  TIOCMGET        = $5415;
+  TIOCMBIS        = $5416;
+  TIOCMBIC        = $5417;
+  TIOCMSET        = $5418;
+  TIOCGSOFTCAR    = $5419;
+  TIOCSSOFTCAR    = $541A;
+  FIONREAD        = $541B;
+  TIOCINQ         = FIONREAD;
+  TIOCLINUX       = $541C;
+  TIOCCONS        = $541D;
+  TIOCGSERIAL     = $541E;
+  TIOCSSERIAL     = $541F;
+  TIOCPKT         = $5420;
+  FIONBIO         = $5421;
+  TIOCNOTTY       = $5422;
+  TIOCSETD        = $5423;
+  TIOCGETD        = $5424;
+  TCSBRKP         = $5425;
+
+  TIOCSBRK        = $5427;
+  TIOCCBRK        = $5428;
+  TIOCGSID        = $5429;
+
+  TIOCGRS485      = $542E;
+  TIOCSRS485      = $542F;
+
+  TCGETX          = $5432;
+  TCSETX          = $5433;
+  TCSETXF         = $5434;
+  TCSETXW         = $5435;
+  TIOCVHANGUP     = $5437;
+
+  FIONCLEX        = $5450;
+  FIOCLEX         = $5451;
+  FIOASYNC        = $5452;
+  TIOCSERCONFIG   = $5453;
+  TIOCSERGWILD    = $5454;
+  TIOCSERSWILD    = $5455;
+  TIOCGLCKTRMIOS  = $5456;
+  TIOCSLCKTRMIOS  = $5457;
+  TIOCSERGSTRUCT  = $5458;
+  TIOCSERGETLSR   = $5459;
+  TIOCSERGETMULTI = $545A;
+  TIOCSERSETMULTI = $545B;
+  TIOCMIWAIT      = $545C;
+  TIOCGICOUNT     = $545D;
+
+  FIOQSIZE        = $5460;
+
+  TIOCPKT_DATA       = 0;
+  TIOCPKT_FLUSHREAD  = 1;
+  TIOCPKT_FLUSHWRITE = 2;
+  TIOCPKT_STOP       = 4;
+  TIOCPKT_START      = 8;
+  TIOCPKT_NOSTOP     = 16;
+  TIOCPKT_DOSTOP     = 32;
+  TIOCPKT_IOCTL      = 64;
+
+  TIOCSER_TEMT       = $01;
+
+{ from Linux 4.0, include/uapi/asm-generic/termbits.h }
+
+  { c_cc characters }
+  VINTR    = 0;
+  VQUIT    = 1;
+  VERASE   = 2;
+  VKILL    = 3;
+  VEOF     = 4;
+  VTIME    = 5;
+  VMIN     = 6;
+  VSWTC    = 7;
+  VSTART   = 8;
+  VSTOP    = 9;
+  VSUSP    = 10;
+  VEOL     = 11;
+  VREPRINT = 12;
+  VDISCARD = 13;
+  VWERASE  = 14;
+  VLNEXT   = 15;
+  VEOL2    = 16;
+
+  { c_iflag bits }
+  IGNBRK  = &0000001;
+  BRKINT  = &0000002;
+  IGNPAR  = &0000004;
+  PARMRK  = &0000010;
+  INPCK   = &0000020;
+  ISTRIP  = &0000040;
+  INLCR   = &0000100;
+  IGNCR   = &0000200;
+  ICRNL   = &0000400;
+  IUCLC   = &0001000;
+  IXON    = &0002000;
+  IXANY   = &0004000;
+  IXOFF   = &0010000;
+  IMAXBEL = &0020000;
+  IUTF8   = &0040000;
+
+  { c_oflag bits }
+  OPOST  = &0000001;
+  OLCUC  = &0000002;
+  ONLCR  = &0000004;
+  OCRNL  = &0000010;
+  ONOCR  = &0000020;
+  ONLRET = &0000040;
+  OFILL  = &0000100;
+  OFDEL  = &0000200;
+  NLDLY  = &0000400;
+  NL0    = &0000000;
+  NL1    = &0000400;
+  CRDLY  = &0003000;
+  CR0    = &0000000;
+  CR1    = &0001000;
+  CR2    = &0002000;
+  CR3    = &0003000;
+  TABDLY = &0014000;
+  TAB0   = &0000000;
+  TAB1   = &0004000;
+  TAB2   = &0010000;
+  TAB3   = &0014000;
+  XTABS  = &0014000;
+  BSDLY  = &0020000;
+  BS0    = &0000000;
+  BS1    = &0020000;
+  VTDLY  = &0040000;
+  VT0    = &0000000;
+  VT1    = &0040000;
+  FFDLY  = &0100000;
+  FF0    = &0000000;
+  FF1    = &0100000;
+
+  { c_cflag bits }
+  CBAUD    = &0010017;
+  B0       = &0000000;
+  B50      = &0000001;
+  B75      = &0000002;
+  B110     = &0000003;
+  B134     = &0000004;
+  B150     = &0000005;
+  B200     = &0000006;
+  B300     = &0000007;
+  B600     = &0000010;
+  B1200    = &0000011;
+  B1800    = &0000012;
+  B2400    = &0000013;
+  B4800    = &0000014;
+  B9600    = &0000015;
+  B19200   = &0000016;
+  B38400   = &0000017;
+  EXTA     = B19200;
+  EXTB     = B38400;
+  CSIZE    = &0000060;
+  CS5      = &0000000;
+  CS6      = &0000020;
+  CS7      = &0000040;
+  CS8      = &0000060;
+  CSTOPB   = &0000100;
+  CREAD    = &0000200;
+  PARENB   = &0000400;
+  PARODD   = &0001000;
+  HUPCL    = &0002000;
+  CLOCAL   = &0004000;
+  CBAUDEX  = &0010000;
+  BOTHER   = &0010000;
+  B57600   = &0010001;
+  B115200  = &0010002;
+  B230400  = &0010003;
+  B460800  = &0010004;
+  B500000  = &0010005;
+  B576000  = &0010006;
+  B921600  = &0010007;
+  B1000000 = &0010010;
+  B1152000 = &0010011;
+  B1500000 = &0010012;
+  B2000000 = &0010013;
+  B2500000 = &0010014;
+  B3000000 = &0010015;
+  B3500000 = &0010016;
+  B4000000 = &0010017;
+
+  CIBAUD   = &002003600000;
+  CMSPAR   = &010000000000;
+  CRTSCTS  = &020000000000;
+
+  IBSHIFT  = 16;
+
+  { c_lflag bits }
+  ISIG    = &0000001;
+  ICANON  = &0000002;
+  XCASE   = &0000004;
+  ECHO    = &0000010;
+  ECHOE   = &0000020;
+  ECHOK   = &0000040;
+  ECHONL  = &0000100;
+  NOFLSH  = &0000200;
+  TOSTOP  = &0000400;
+  ECHOCTL = &0001000;
+  ECHOPRT = &0002000;
+  ECHOKE  = &0004000;
+  FLUSHO  = &0010000;
+  PENDIN  = &0040000;
+  IEXTEN  = &0100000;
+  EXTPROC = &0200000;
+
+  { TCFlow }
+  TCOOFF = 0;
+  TCOON  = 1;
+  TCIOFF = 2;
+  TCION  = 3;
+
+  { TCFlush }
+  TCIFLUSH  = 0;
+  TCOFLUSH  = 1;
+  TCIOFLUSH = 2;
+
+  { TCSetAttr }
+  TCSANOW   = 0;
+  TCSADRAIN = 1;
+  TCSAFLUSH = 2;
+
+{ from Linux 4.0, include/uapi/asm-generic/termios.h }
+
+  { c_line bits }
+  TIOCM_LE   = $001;
+  TIOCM_DTR  = $002;
+  TIOCM_RTS  = $004;
+  TIOCM_ST   = $008;
+  TIOCM_SR   = $010;
+  TIOCM_CTS  = $020;
+  TIOCM_CAR  = $040;
+  TIOCM_RNG  = $080;
+  TIOCM_DSR  = $100;
+  TIOCM_CD   = TIOCM_CAR;
+  TIOCM_RI   = TIOCM_RNG;
+  TIOCM_OUT1 = $2000;
+  TIOCM_OUT2 = $4000;
+  TIOCM_LOOP = $8000;
+
+{$endif cpuaarch64}
+
 {$ifdef cpupowerpc}
   TCGETS            = $402c7413;
   TCSETS            = $802c7414;
index e088f19d3106f100de2b006fb923dc7d1ff14ad9..2089f310999403f421a2283fc3117e1ea9d12dde 100644 (file)
@@ -140,6 +140,10 @@ Type  PINTRTLEvent = ^TINTRTLEvent;
         threadvarblocksize:=align(threadvarblocksize,16);
         {$endif cpupowerpc64}
 
+        {$ifdef cpuaarch64}
+        threadvarblocksize:=align(threadvarblocksize,16);
+        {$endif cpuaarch64}
+
         offset:=threadvarblocksize;
 
         inc(threadvarblocksize,size);
index fa6405606e9b4ba0e1cf5af7020254f773da50db..c9068c50622b42f637347c3ddd1673b64b01beec 100644 (file)
@@ -230,12 +230,12 @@ procedure InitThread;
 var
   transliterate: cint;
   iconvindex: longint;
-{$if not(defined(darwin) and defined(cpuarm)) and not defined(iphonesim)}
+{$if not(defined(darwin) and (defined(cpuarm) or defined(cpuaarch64))) and not defined(iphonesim)}
   iconvname: rawbytestring;
 {$endif}
 begin
   current_DefaultSystemCodePage:=DefaultSystemCodePage;
-{$if not(defined(darwin) and defined(cpuarm)) and not defined(iphonesim)}
+{$if not(defined(darwin) and (defined(cpuarm) or defined(cpuaarch64))) and not defined(iphonesim)}
   iconvindex:=GetCodepageData(DefaultSystemCodePage);
   if iconvindex<>-1 then
     iconvname:=UnixCpMap[iconvindex].name
index 98db015f2a048514d789dcf25b3c3e9f90caa3ee..15c4634b7194c09b5637cf0aebd6d2563ecaebef 100644 (file)
@@ -67,7 +67,7 @@ interface
 
     type
       TCpu=(
-        c_i386,c_m68k,c_powerpc,c_sparc,c_x86_64,c_arm,c_powerpc64,c_avr,c_armeb,c_armel,c_mips,c_mipsel,c_mips64,c_mips64el,c_jvm,c_i8086
+        c_i386,c_m68k,c_powerpc,c_sparc,c_x86_64,c_arm,c_powerpc64,c_avr,c_armeb,c_armel,c_mips,c_mipsel,c_mips64,c_mips64el,c_jvm,c_i8086,c_aarch64
       );
 
       TOS=(
@@ -82,15 +82,15 @@ interface
 
     const
       CpuStr : array[TCpu] of string=(
-        'i386','m68k','powerpc','sparc','x86_64','arm','powerpc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','i8086'
+        'i386','m68k','powerpc','sparc','x86_64','arm','powerpc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','i8086','aarch64'
       );
 
       CpuSuffix : array[TCpu] of string=(
-        '_i386','_m68k','_powerpc','_sparc','_x86_64','_arm','_powerpc64','_avr','_armeb', '_armel', '_mips', '_mipsel', '_mips64', '_mips64el', '_jvm','_i8086'
+        '_i386','_m68k','_powerpc','_sparc','_x86_64','_arm','_powerpc64','_avr','_armeb', '_armel', '_mips', '_mipsel', '_mips64', '_mips64el', '_jvm','_i8086','_aarch64'
       );
 
       ppcSuffix : array[TCpu] of string=(
-        '386','m68k','ppc','sparc','x86_64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','8086'
+        '386','m68k','ppc','sparc','x86_64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','8086','aarch64'
       );
 
       OSStr : array[TOS] of string=(
@@ -113,44 +113,44 @@ interface
 
       { This table is kept OS,Cpu because it is easier to maintain (PFV) }
       OSCpuPossible : array[TOS,TCpu] of boolean = (
-        { os          i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb  armel  mips   mipsel mips64 misp64el jvm    i8086 }
-        { linux }   ( true,  true,  true,  true,  true,  true,  true,  false, true,  false, true,  true,  false, false,   false, false),
-        { go32v2 }  ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { win32 }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { os2 }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { freebsd } ( true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false,   false, false),
-        { beos }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { haiku }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { netbsd }  ( true,  true,  true,  true,  true,  false, false, false, false, false, false, false, false, false,   false, false),
-        { amiga }   ( false, true,  true,  false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { atari }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { solaris } ( true,  false, false, true,  true,  false, false, false, false, false, false, false, false, false,   false, false),
-        { qnx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { netware } ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { openbsd } ( true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false,   false, false),
-        { wdosx }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { palmos }  ( false, true,  false, false, false, true,  false, false, false, false, false, false, false, false,   false, false),
-        { macos }   ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { darwin }  ( true,  false, true,  false, true,  true,  true,  false, false, false, false, false, false, false,   false, false),
-        { emx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { watcom }  ( true,  false, false, false ,false, false, false, false, false, false, false, false, false, false,   false, false),
-        { morphos } ( false, false, true,  false ,false, false, false, false, false, false, false, false, false, false,   false, false),
-        { netwlibc }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { win64   } ( false, false, false, false, true,  false, false, false, false, false, false, false, false, false,   false, false),
-        { wince    }( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false),
-        { gba    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false),
-        { nds    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false),
-        { embedded }( true,  true,  true,  true,  true,  true,  true,  true,  true , false, false, true , false, false,   false, false),
-        { symbian } ( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false),
-        { nativent }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { iphonesim }( true, false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { wii }     ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        { aix }     ( false, false, true,  false, false, false, true,  false, false, false, false, false, false, false,   false, false),
-        { java }    ( false, false, false, false, false, false, false, false, false, false, false, false, false, false,   true,  false),
-        { android } ( true,  false, false, false, false, true,  false, false, false, false, false, true,  false, false,   true,  false),
-        { msdos }   ( false, false, false, false, false, false, false, false, false, false, false, false, false, false,   false, true),
-        { aros }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false),
-        {dragonfly} ( false, false, false, false, true,  false, false, false, false, false, false, false, false, false,   false, false)
+        { os          i386    m68k  ppc    sparc  x86_64 arm    ppc64  avr    armeb  armel  mips   mipsel mips64 misp64el jvm    i8086  aarch64}
+        { linux }   ( true,  true,  true,  true,  true,  true,  true,  false, true,  false, true,  true,  false, false,   false, false, true ),
+        { go32v2 }  ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { win32 }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { os2 }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { freebsd } ( true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false,   false, false, false),
+        { beos }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { haiku }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { netbsd }  ( true,  true,  true,  true,  true,  false, false, false, false, false, false, false, false, false,   false, false, false),
+        { amiga }   ( false, true,  true,  false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { atari }   ( false, true,  false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { solaris } ( true,  false, false, true,  true,  false, false, false, false, false, false, false, false, false,   false, false, false),
+        { qnx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { netware } ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { openbsd } ( true,  true,  false, false, true,  false, false, false, false, false, false, false, false, false,   false, false, false),
+        { wdosx }   ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { palmos }  ( false, true,  false, false, false, true,  false, false, false, false, false, false, false, false,   false, false, false),
+        { macos }   ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { darwin }  ( true,  false, true,  false, true,  true,  true,  false, false, false, false, false, false, false,   false, false, true ),
+        { emx }     ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { watcom }  ( true,  false, false, false ,false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { morphos } ( false, false, true,  false ,false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { netwlibc }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { win64   } ( false, false, false, false, true,  false, false, false, false, false, false, false, false, false,   false, false, false),
+        { wince    }( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false, false),
+        { gba    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false, false),
+        { nds    }  ( false, false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false, false),
+        { embedded }( true,  true,  true,  true,  true,  true,  true,  true,  true , false, false, true , false, false,   false, false, false),
+        { symbian } ( true,  false, false, false, false, true,  false, false, false, false, false, false, false, false,   false, false, false),
+        { nativent }( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { iphonesim }( true, false, false, false, true,  false, false, false, false, false, false, false, false, false,   false, false, false),
+        { wii }     ( false, false, true,  false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        { aix }     ( false, false, true,  false, false, false, true,  false, false, false, false, false, false, false,   false, false, false),
+        { java }    ( false, false, false, false, false, false, false, false, false, false, false, false, false, false,   true,  false, false),
+        { android } ( true,  false, false, false, false, true,  false, false, false, false, false, true,  false, false,   true,  false, false),
+        { msdos }   ( false, false, false, false, false, false, false, false, false, false, false, false, false, false,   false, true , false),
+        { aros }    ( true,  false, false, false, false, false, false, false, false, false, false, false, false, false,   false, false, false),
+        {dragonfly} ( false, false, false, false, true,  false, false, false, false, false, false, false, false, false,   false, false, false)
       );
 
     type
index bdaddc81f2163dc9c1728e2431d98a794d161f6d..83775e2f3729ba4ee9e71e8c34477b74680c5869 100644 (file)
@@ -73,7 +73,7 @@ begin
   writeln('                         i386, x86_64, arm (coff)');
   writeln('                         i386, x86_64, powerpc, powerpc64, arm, armeb, m68k,');
   writeln('                         sparc, alpha, ia64, mips, mipsel (elf)');
-  writeln('                         i386, x86_64, powerpc, powerpc64, arm (mach-o)');
+  writeln('                         i386, x86_64, powerpc, powerpc64, arm, aarch64 (mach-o)');
   writeln('                         bigendian, littleendian (external)');
   writeln('  --subarch, -s <name> Set object file sub-architecture. Supported values:');
   writeln('                         arm: all, v4t, v6, v5tej, xscale, v7');
@@ -252,6 +252,7 @@ begin
     mtia64 : Result.MachineType:=emtia64;
     mtmips : Result.MachineType:=emtmips;
     mtmipsel : Result.MachineType:=emtmipsel;
+    mtaarch64 : Result.MachineType:=emtaarch64;
   end;
 end;
 
@@ -312,6 +313,11 @@ begin
         Result.MachineType:=mmtarm;
         MachOSubMachineType.fArmSubType:=ArmSubMachine2MachOSubMachine[CurrentTarget.submachine.subarm];
       end;
+    mtaarch64 :
+      begin
+        Result.MachineType:=mmtarm64;
+        MachOSubMachineType.fArm64SubType:=msmaarch64_all;
+      end;
   end;
   Result.SubMachineType:=MachOSubMachineType;
 end;
index 7d5340c154e25d5cffdd95d60d81ae418a004b05..0e1964a89e8acd5eec5bd2efaa7573ecdac5516e 100644 (file)
@@ -22,7 +22,7 @@ interface
 
 type
   TMachineType = (mtnone, mti386,mtx86_64,mtppc,mtppc64,mtarm,mtarmeb,mtm68k,
-                  mtsparc,mtalpha,mtia64,mtmips,mtmipsel,
+                  mtsparc,mtalpha,mtia64,mtmips,mtmipsel,mtaarch64,
                   mtBigEndian,mtLittleEndian);
   TMachineTypes = set of TMachineType;
 
@@ -34,7 +34,7 @@ type
       mtarm,mtarmeb:
         (subarm: TSubMachineTypeArm);
       mtnone, mti386,mtx86_64,mtppc,mtppc64,mtm68k,
-      mtsparc,mtalpha,mtia64,mtmips,mtmipsel,
+      mtsparc,mtalpha,mtia64,mtmips,mtmipsel,mtaarch64,
       mtBigEndian,mtLittleEndian:
         (subgen: TSubMachineTypeGeneric);
   end;
@@ -83,6 +83,7 @@ var
     (name : 'ia64';         formats : [ofElf]),                   //mtia64
     (name : 'mips';         formats : [ofElf]; alias : 'mipseb'), //mtmips
     (name : 'mipsel';       formats : [ofElf]),                   //mtmipsel
+    (name : 'aarch64';      formats : [ofElf, ofMachO]),          //mtaarch64
     (name : 'bigendian';    formats : [ofExt]),                   //mtBigEndian
     (name : 'littleendian'; formats : [ofExt])                    //mtLittleEndian
   );
@@ -99,35 +100,31 @@ var
     (name : 'elf';      ext : '.or';     machines : [mti386,mtx86_64,mtppc,
                                                      mtppc64,mtarm,mtarmeb,
                                                      mtm68k,mtsparc,mtalpha,
-                                                     mtia64,mtmips,mtmipsel]),
+                                                     mtaarch64]),
     (name : 'coff';     ext : '.o';      machines : [mti386,mtx86_64,mtarm,
                                                      mtppc,mtppc64]),
     (name : 'xcoff';    ext : '.o';      machines : [mtppc{,mtppc64}]),
     (name : 'mach-o';   ext : '.or';     machines : [mti386,mtx86_64,mtppc,
-                                                     mtppc64,mtarm]),
+                                                     mtppc64,mtarm,mtaarch64]),
     (name : 'external'; ext : '.fpcres'; machines : [mtBigEndian,mtLittleEndian])
   );
 
 
   CurrentTarget : TResTarget =
   (
-  {$IFDEF CPUI386}
+  {$if defined(CPUI386)}
     machine : mti386;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUX86_64}
+  {$elseif defined(CPUX86_64)}
     machine : mtx86_64;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUPOWERPC32}
+  {$elseif defined(CPUPOWERPC32)}
     machine : mtppc;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUPOWERPC64}
+  {$elseif defined(CPUPOWERPC64)}
     machine : mtppc64;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUARM}
+  {$elseif defined(CPUARM)}
     {$IFDEF ENDIAN_LITTLE}
     machine : mtarm;
     submachine : (subarm: smtarm_all);
@@ -135,44 +132,31 @@ var
     machine : mtarmeb;
     submachine : (subarm: smtarm_all);
     {$ENDIF}
-  {$ELSE}
-  {$IFDEF CPU68K}
+  {$elseif defined(CPU68K)}
     machine : mtm68k;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUSPARC}
+  {$elseif defined(CPUSPARC)}
     machine : mtsparc;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUALPHA}
+  {$elseif defined(CPUALPHA)}
     machine : mtalpha;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUIA64}
+  {$elseif defined(CPUIA64)}
     machine : mtia64;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUMIPSEL}
+  {$elseif defined(CPUMIPSEL)}
     machine : mtmipsel;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
-  {$IFDEF CPUMIPS}
+  {$elseif defined(CPUMIPS)}
     machine : mtmips;
     submachine : (subgen: smtgen_all);
-  {$ELSE}
+  {$elseif defined(CPUAARCH64)}
+    machine : mtaarch64;
+    submachine : (subgen: smtgen_all);
+  {$else}
     machine : mti386;  //default i386
     submachine : (subgen: smtgen_all);
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
-  {$ENDIF}
+  {$endif}
 
   {$IFDEF WINDOWS}
     objformat : ofCoff;