--- /dev/null
--- /dev/null
++Description: Upstream includes in svn already arm64 support
++ This patch was created with a recipe from bug 784569 + minor changes by Elbrus:
++ mkdir a b
++ wget ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/source/fpcbuild-3.0.0rc2.tar.gz
++ tar xzf fpcbuild-3.0.0rc2.tar.gz -C a --strip-components=1
++ svn export -r 32015 http://svn.freepascal.org/svn/fpc/branches/fixes_3_0_ios b/fpcsrc
++ .
++ find [ab]/fpcsrc -name Makefile -delete
++ find [ab]/fpcsrc -name '*.[ao]' -o -name '*.exe' -delete
++
++ ( cd b && ../a/install/updfpmkver 3.0.0rc2 )
++ ( cd b && ../a/install/updmkver 3.0.0rc2 true )
++ cp -rT [ab]/fpcsrc/installer
++ cp -rT [ab]/fpcsrc/packages/chm
++ perl -i -pe "s/(patch_nr\s*=\s*)'.*'/\$1'0'/;" b/fpcsrc/compiler/version.pas
++ perl -i -pe "s/(minorpatch\s*=\s*)'.*'/\$1'rc2'/;" b/fpcsrc/compiler/version.pas
++ .
++ # delete directories univint and tests
++ .
++ git diff --no-prefix [ab]/fpcsrc > add-arm64-support.patch
++ .
++ # apply on top of full debian patches + quilt refresh
++ .
++ .
++ This patch was updated manually by elbrus upon merging 3.0.2 which should
++ contain support for AArch64, but too much of the patch still applied cleanly.
++Author: Edmund Grimley Evans <edmund.grimley.evans@gmail.com>
++Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=784569
++
++Index: fpc/fpcsrc/Makefile.fpc
++===================================================================
++--- fpc.orig/fpcsrc/Makefile.fpc
+++++ fpc/fpcsrc/Makefile.fpc
++@@ -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: fpc/fpcsrc/compiler/Makefile.fpc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/Makefile.fpc
+++++ fpc/fpcsrc/compiler/Makefile.fpc
++@@ -32,7 +32,7 @@ fpcdir=..
++ unexport FPC_VERSION FPC_COMPILERINFO
++
++ # Which platforms are ready for inclusion in the cycle
++-CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr 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: fpc/fpcsrc/compiler/aarch64/a64att.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/a64att.inc
+++++ fpc/fpcsrc/compiler/aarch64/a64att.inc
++@@ -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',
++@@ -17,40 +39,66 @@
++ 'ldtr',
++ 'sttr',
++ 'ldxr',
+++'ldxp',
++ 'stxr',
+++'stxp',
++ 'ldar',
++ 'stlr',
++ 'ldaxr',
++ 'stlxr',
+++'stlxp',
+++'ld1',
+++'ld2',
+++'ld3',
+++'ld4',
+++'st1',
+++'st2',
+++'st3',
+++'st4',
+++'ld1r',
+++'ld2r',
+++'ld3r',
+++'ld4r',
++ 'prfm',
+++'prfum',
++ 'add',
++-'adc',
++ 'sub',
++-'sbc',
++ 'cmp',
++ 'cmn',
++-'mov',
++ 'and',
++-'bic',
++ 'eor',
++-'eon',
++ 'orr',
++ 'orn',
++ 'tst',
++-'mvn',
+++'movz',
+++'movn',
++ 'movk',
+++'mrs',
+++'msr',
++ 'adrp',
++ 'adr',
++ 'bfm',
++ 'sbfm',
++ 'ubfm',
++ 'extr',
++-'sxt',
++-'uxt',
+++'adc',
+++'sbc',
+++'bic',
+++'eon',
++ 'asrv',
++-'llslv',
+++'lslv',
++ 'lsrv',
++ 'rorv',
+++'madd',
+++'msub',
+++'smaddl',
+++'smsubl',
+++'smulh',
+++'umaddl',
+++'umsubl',
+++'umulh',
+++'sdiv',
+++'udiv',
++ 'cls',
++ 'clz',
++ 'rbit',
++@@ -63,33 +111,39 @@
++ 'csneg',
++ 'ccmn',
++ 'ccmp',
++-'madd',
++-'msub',
++-'smaddl',
++-'smsubl',
++-'smulh',
++-'umaddl',
++-'umsubl',
++-'umulh',
++-'sdiv',
++-'udiv',
++-'neg',
+++'nop',
+++'yield',
+++'wfe',
+++'wfi',
+++'sev',
+++'sevl',
+++'mov',
+++'bfi',
+++'bfxil',
+++'sbfiz',
+++'sbfx',
+++'ubfiz',
+++'ubfx',
++ 'asr',
++ 'lsl',
++ 'lsr',
++ 'ror',
++-'cset',
++-'csetm',
++-'cinc',
++-'cinv',
++-'cneg',
+++'sxt',
+++'uxt',
+++'neg',
++ 'ngc',
+++'mvn',
++ 'mneg',
++ 'mul',
++ 'smnegl',
++ 'smull',
++ 'umnegl',
++ 'umull',
+++'cset',
+++'csetm',
+++'cinc',
+++'cinv',
+++'cneg',
++ 'fmov',
++ 'fcvt',
++ 'fcvtas',
++@@ -104,13 +158,13 @@
++ 'fcvtzu',
++ 'scvtf',
++ 'ucvtf',
++-'fprinta',
++-'fprinti',
++-'fprintm',
++-'fprintn',
++-'fprintp',
++-'fprintx',
++-'fprintz',
+++'frinta',
+++'frinti',
+++'frintm',
+++'frintn',
+++'frintp',
+++'frintx',
+++'frintz',
++ 'fabs',
++ 'fneg',
++ 'fsqrt',
++@@ -130,5 +184,8 @@
++ 'fcmpe',
++ 'fccmp',
++ 'fcmmpe',
++-'fcsel'
+++'fcsel',
+++'umov',
+++'ins',
+++'movi'
++ );
++Index: fpc/fpcsrc/compiler/aarch64/a64atts.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/a64atts.inc
+++++ fpc/fpcsrc/compiler/aarch64/a64atts.inc
++@@ -1,8 +1,65 @@
++-{ don't edit, this file is generated from armins.dat }
+++{ don't edit, this file is generated from a64ins.dat }
++ (
++ attsufNONE,
++ attsufNONE,
++ attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
+++attsufNONE,
++ attsufNONE,
++ attsufNONE,
++ attsufNONE,
++Index: fpc/fpcsrc/compiler/aarch64/a64ins.dat
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/a64ins.dat
+++++ fpc/fpcsrc/compiler/aarch64/a64ins.dat
++@@ -1,10 +1,15 @@
++-[NOP]
+++; invalid
+++[NONE]
++
++ [B]
++
++-[CB]
+++[CBZ]
+++
+++[CBNZ]
++
++-[TB]
+++[TBZ]
+++
+++[TBNZ]
++
++ [BL]
++
++@@ -14,10 +19,50 @@
++
++ [RET]
++
+++[BRK]
+++
+++[HLT]
+++
+++[HVC]
+++
+++[SMC]
+++
+++[SVC]
+++
+++[ERET]
+++
+++[DCPS1]
+++
+++[DCPS2]
+++
+++[DCPS3]
+++
+++[DRPS]
+++
+++[DC]
+++
+++[AT]
+++
+++[TLBI]
+++
+++[HINT]
+++
+++[CLREX]
+++
+++[DSB]
+++
+++[DMB]
+++
+++[ISB]
+++
++ [LDR]
++
++ [STR]
++
+++[LDUR]
+++
+++[STUR]
+++
++ [LDP]
++
++ [STP]
++@@ -32,8 +77,12 @@
++
++ [LDXR]
++
+++[LDXP]
+++
++ [STXR]
++
+++[STXP]
+++
++ [LDAR]
++
++ [STLR]
++@@ -42,40 +91,64 @@
++
++ [STLXR]
++
+++[STLXP]
+++
+++[LD1]
+++
+++[LD2]
+++
+++[LD3]
+++
+++[LD4]
+++
+++[ST1]
+++
+++[ST2]
+++
+++[ST3]
+++
+++[ST4]
+++
+++[LD1R]
+++
+++[LD2R]
+++
+++[LD3R]
+++
+++[LD4R]
+++
++ [PRFM]
++
++-[ADD]
+++[PRFUM]
++
++-[ADC]
+++[ADD]
++
++ [SUB]
++
++-[SBC]
++-
++ [CMP]
++
++ [CMN]
++
++-[MOV]
++-
++ [AND]
++
++-[BIC]
++-
++ [EOR]
++
++-[EON]
++-
++ [ORR]
++
++ [ORN]
++
++ [TST]
++
++-[MVN]
+++[MOVZ]
+++
+++[MOVN]
++
++ [MOVK]
++
+++[MRS]
+++
+++[MSR]
+++
++ [ADRP]
++
++ [ADR]
++@@ -88,18 +161,42 @@
++
++ [EXTR]
++
++-[SXT]
+++[ADC]
++
++-[UXT]
+++[SBC]
+++
+++[BIC]
+++
+++[EON]
++
++ [ASRV]
++
++-[LLSLV]
+++[LSLV]
++
++ [LSRV]
++
++ [RORV]
++
+++[MADD]
+++
+++[MSUB]
+++
+++[SMADDL]
+++
+++[SMSUBL]
+++
+++[SMULH]
+++
+++[UMADDL]
+++
+++[UMSUBL]
+++
+++[UMULH]
+++
+++[SDIV]
+++
+++[UDIV]
+++
++ [CLS]
++
++ [CLZ]
++@@ -124,29 +221,33 @@
++
++ [CCMP]
++
++-[MADD]
+++; Aliases
+++; they are not generated by the compiler, they are only used for inline assembler
+++[NOP]
++
++-[MSUB]
+++[YIELD]
++
++-[SMADDL]
+++[WFE]
++
++-[SMSUBL]
+++[WFI]
++
++-[SMULH]
+++[SEV]
++
++-[UMADDL]
+++[SEVL]
++
++-[UMSUBL]
+++[MOV]
++
++-[UMULH]
+++[BFI]
++
++-[SDIV]
+++[BFXIL]
++
++-[UDIV]
+++[SBFIZ]
++
++-; Aliases
++-; they are not generated by the compiler, they are only used for inline assembler
++-[NEG]
+++[SBFX]
+++
+++[UBFIZ]
+++
+++[UBFX]
++
++ [ASR]
++
++@@ -156,18 +257,16 @@
++
++ [ROR]
++
++-[CSET]
++-
++-[CSETM]
++-
++-[CINC]
+++[SXT]
++
++-[CINV]
+++[UXT]
++
++-[CNEG]
+++[NEG]
++
++ [NGC]
++
+++[MVN]
+++
++ [MNEG]
++
++ [MUL]
++@@ -180,6 +279,16 @@
++
++ [UMULL]
++
+++[CSET]
+++
+++[CSETM]
+++
+++[CINC]
+++
+++[CINV]
+++
+++[CNEG]
+++
++ [FMOV]
++
++ [FCVT]
++@@ -208,19 +317,19 @@
++
++ [UCVTF]
++
++-[FPRINTA]
+++[FRINTA]
++
++-[FPRINTI]
+++[FRINTI]
++
++-[FPRINTM]
+++[FRINTM]
++
++-[FPRINTN]
+++[FRINTN]
++
++-[FPRINTP]
+++[FRINTP]
++
++-[FPRINTX]
+++[FRINTX]
++
++-[FPRINTZ]
+++[FRINTZ]
++
++ [FABS]
++
++@@ -262,3 +371,8 @@
++
++ [FCSEL]
++
+++[UMOV]
+++
+++[INS]
+++
+++[MOVI]
++Index: fpc/fpcsrc/compiler/aarch64/a64op.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/a64op.inc
+++++ fpc/fpcsrc/compiler/aarch64/a64op.inc
++@@ -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: fpc/fpcsrc/compiler/aarch64/a64reg.dat
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/a64reg.dat
+++++ fpc/fpcsrc/compiler/aarch64/a64reg.dat
++@@ -70,169 +70,176 @@ W30,$01,$04,$1E,w30,30,30
++ X30,$01,$05,$1E,x30,30,30
++ WZR,$01,$04,$1F,wzr,31,31
++ XZR,$01,$05,$1F,xzr,31,31
+++; sp and zr share the same register number, but we still have to be able to
+++; differentiate them because some instructions can be encoded with both ->
+++; use a different superregister after all
+++WSP,$01,$04,$20,wsp,31,31
+++SP,$01,$05,$20,sp,31,31
++
++
++ ; vfp registers
++-B0,$04,$01,$00,b0,0,0
++-H0,$04,$03,$00,h0,0,0
++-S0,$04,$09,$00,s0,0,0
++-D0,$04,$0a,$00,d0,0,0
++-Q0,$04,$05,$00,q0,0,0
++-B1,$04,$01,$01,b1,1,1
++-H1,$04,$03,$01,h1,1,1
++-S1,$04,$09,$01,s1,1,1
++-D1,$04,$0a,$01,d1,1,1
++-Q1,$04,$05,$01,q1,1,1
++-B2,$04,$01,$02,b2,2,2
++-H2,$04,$03,$02,h2,2,2
++-S2,$04,$09,$02,s2,2,2
++-D2,$04,$0a,$02,d2,2,2
++-Q2,$04,$05,$02,q2,2,2
++-B3,$04,$01,$03,b3,3,3
++-H3,$04,$03,$03,h3,3,3
++-S3,$04,$09,$03,s3,3,3
++-D3,$04,$0a,$03,d3,3,3
++-Q3,$04,$05,$03,q3,3,3
++-B4,$04,$01,$04,b4,4,4
++-H4,$04,$03,$04,h4,4,4
++-S4,$04,$09,$04,s4,4,4
++-D4,$04,$0a,$04,d4,4,4
++-Q4,$04,$05,$04,q4,4,4
++-B5,$04,$01,$05,b5,5,5
++-H5,$04,$03,$05,h5,5,5
++-S5,$04,$09,$05,s5,5,5
++-D5,$04,$0a,$05,d5,5,5
++-Q5,$04,$05,$05,q5,5,5
++-B6,$04,$01,$06,b6,6,6
++-H6,$04,$03,$06,h6,6,6
++-S6,$04,$09,$06,s6,6,6
++-D6,$04,$0a,$06,d6,6,6
++-Q6,$04,$05,$06,q6,6,6
++-B7,$04,$01,$07,b7,7,7
++-H7,$04,$03,$07,h7,7,7
++-S7,$04,$09,$07,s7,7,7
++-D7,$04,$0a,$07,d7,7,7
++-Q7,$04,$05,$07,q7,7,7
++-B8,$04,$01,$08,b8,8,8
++-H8,$04,$03,$08,h8,8,8
++-S8,$04,$09,$08,s8,8,8
++-D8,$04,$0a,$08,d8,8,8
++-Q8,$04,$05,$08,q8,8,8
++-B9,$04,$01,$09,b9,9,9
++-H9,$04,$03,$09,h9,9,9
++-S9,$04,$09,$09,s9,9,9
++-D9,$04,$0a,$09,d9,9,9
++-Q9,$04,$05,$09,q9,9,9
++-B10,$04,$01,$0A,b10,10,10
++-H10,$04,$03,$0A,h10,10,10
++-S10,$04,$09,$0A,s10,10,10
++-D10,$04,$0a,$0A,d10,10,10
++-Q10,$04,$05,$0A,q10,10,10
++-B11,$04,$01,$0B,b11,11,11
++-H11,$04,$03,$0B,h11,11,11
++-S11,$04,$09,$0B,s11,11,11
++-D11,$04,$0a,$0B,d11,11,11
++-Q11,$04,$05,$0B,q11,11,11
++-B12,$04,$01,$0C,b12,12,12
++-H12,$04,$03,$0C,h12,12,12
++-S12,$04,$09,$0C,s12,12,12
++-D12,$04,$0a,$0C,d12,12,12
++-Q12,$04,$05,$0C,q12,12,12
++-B13,$04,$01,$0D,b13,13,13
++-H13,$04,$03,$0D,h13,13,13
++-S13,$04,$09,$0D,s13,13,13
++-D13,$04,$0a,$0D,d13,13,13
++-Q13,$04,$05,$0D,q13,13,13
++-B14,$04,$01,$0E,b14,14,14
++-H14,$04,$03,$0E,h14,14,14
++-S14,$04,$09,$0E,s14,14,14
++-D14,$04,$0a,$0E,d14,14,14
++-Q14,$04,$05,$0E,q14,14,14
++-B15,$04,$01,$0F,b15,15,15
++-H15,$04,$03,$0F,h15,15,15
++-S15,$04,$09,$0F,s15,15,15
++-D15,$04,$0a,$0F,d15,15,15
++-Q15,$04,$05,$0F,q15,15,15
++-B16,$04,$01,$10,b16,16,16
++-H16,$04,$03,$10,h16,16,16
++-S16,$04,$09,$10,s16,16,16
++-D16,$04,$0a,$10,d16,16,16
++-Q16,$04,$05,$10,q16,16,16
++-B17,$04,$01,$11,b17,17,17
++-H17,$04,$03,$11,h17,17,17
++-S17,$04,$09,$11,s17,17,17
++-D17,$04,$0a,$11,d17,17,17
++-Q17,$04,$05,$11,q17,17,17
++-B18,$04,$01,$12,b18,18,18
++-H18,$04,$03,$12,h18,18,18
++-S18,$04,$09,$12,s18,18,18
++-D18,$04,$0a,$12,d18,18,18
++-Q18,$04,$05,$12,q18,18,18
++-B19,$04,$01,$13,b19,19,19
++-H19,$04,$03,$13,h19,19,19
++-S19,$04,$09,$13,s19,19,19
++-D19,$04,$0a,$13,d19,19,19
++-Q19,$04,$05,$13,q19,19,19
++-B20,$04,$01,$14,b20,20,20
++-H20,$04,$03,$14,h20,20,20
++-S20,$04,$09,$14,s20,20,20
++-D20,$04,$0a,$14,d20,20,20
++-Q20,$04,$05,$14,q20,20,20
++-B21,$04,$01,$15,b21,21,21
++-H21,$04,$03,$15,h21,21,21
++-S21,$04,$09,$15,s21,21,21
++-D21,$04,$0a,$15,d21,21,21
++-Q21,$04,$05,$15,q21,21,21
++-B22,$04,$01,$16,b22,22,22
++-H22,$04,$03,$16,h22,22,22
++-S22,$04,$09,$16,s22,22,22
++-D22,$04,$0a,$16,d22,22,22
++-Q22,$04,$05,$16,q22,22,22
++-B23,$04,$01,$17,b23,23,23
++-H23,$04,$03,$17,h23,23,23
++-S23,$04,$09,$17,s23,23,23
++-D23,$04,$0a,$17,d23,23,23
++-Q23,$04,$05,$17,q23,23,23
++-B24,$04,$01,$18,b24,24,24
++-H24,$04,$03,$18,h24,24,24
++-S24,$04,$09,$18,s24,24,24
++-D24,$04,$0a,$18,d24,24,24
++-Q24,$04,$05,$18,q24,24,24
++-B25,$04,$01,$19,b25,25,25
++-H25,$04,$03,$19,h25,25,25
++-S25,$04,$09,$19,s25,25,25
++-D25,$04,$0a,$19,d25,25,25
++-Q25,$04,$05,$19,q25,25,25
++-B26,$04,$01,$1A,b26,26,26
++-H26,$04,$03,$1A,h26,26,26
++-S26,$04,$09,$1A,s26,26,26
++-D26,$04,$0a,$1A,d26,26,26
++-Q26,$04,$05,$1A,q26,26,26
++-B27,$04,$01,$1B,b27,27,27
++-H27,$04,$03,$1B,h27,27,27
++-S27,$04,$09,$1B,s27,27,27
++-D27,$04,$0a,$1B,d27,27,27
++-Q27,$04,$05,$1B,q27,27,27
++-B28,$04,$01,$1C,b28,28,28
++-H28,$04,$03,$1C,h28,28,28
++-S28,$04,$09,$1C,s28,28,28
++-D28,$04,$0a,$1C,d28,28,28
++-Q28,$04,$05,$1C,q28,28,28
++-B29,$04,$01,$1D,b29,29,29
++-H29,$04,$03,$1D,h29,29,29
++-S29,$04,$09,$1D,s29,29,29
++-D29,$04,$0a,$1D,d29,29,29
++-Q29,$04,$05,$1D,q29,29,29
++-B30,$04,$01,$1E,b30,30,30
++-H30,$04,$03,$1E,h30,30,30
++-S30,$04,$09,$1E,s30,30,30
++-D30,$04,$0a,$1E,d30,30,30
++-Q30,$04,$05,$1E,q30,30,30
++-B31,$04,$01,$1F,b31,31,31
++-H31,$04,$03,$1F,h31,31,31
++-S31,$04,$09,$1F,s31,31,31
++-D31,$04,$0a,$1F,d31,31,31
++-Q31,$04,$05,$1F,q31,31,31
+++B0,$04,$01,$00,b0,64,64
+++H0,$04,$03,$00,h0,64,64
+++S0,$04,$09,$00,s0,64,64
+++D0,$04,$0a,$00,d0,64,64
+++Q0,$04,$05,$00,q0,64,64
+++B1,$04,$01,$01,b1,65,65
+++H1,$04,$03,$01,h1,65,65
+++S1,$04,$09,$01,s1,65,65
+++D1,$04,$0a,$01,d1,65,65
+++Q1,$04,$05,$01,q1,65,65
+++B2,$04,$01,$02,b2,66,66
+++H2,$04,$03,$02,h2,66,66
+++S2,$04,$09,$02,s2,66,66
+++D2,$04,$0a,$02,d2,66,66
+++Q2,$04,$05,$02,q2,66,66
+++B3,$04,$01,$03,b3,67,67
+++H3,$04,$03,$03,h3,67,67
+++S3,$04,$09,$03,s3,67,67
+++D3,$04,$0a,$03,d3,67,67
+++Q3,$04,$05,$03,q3,67,67
+++B4,$04,$01,$04,b4,68,68
+++H4,$04,$03,$04,h4,68,68
+++S4,$04,$09,$04,s4,68,68
+++D4,$04,$0a,$04,d4,68,68
+++Q4,$04,$05,$04,q4,68,68
+++B5,$04,$01,$05,b5,69,69
+++H5,$04,$03,$05,h5,69,69
+++S5,$04,$09,$05,s5,69,69
+++D5,$04,$0a,$05,d5,69,69
+++Q5,$04,$05,$05,q5,69,69
+++B6,$04,$01,$06,b6,70,70
+++H6,$04,$03,$06,h6,70,70
+++S6,$04,$09,$06,s6,70,70
+++D6,$04,$0a,$06,d6,70,70
+++Q6,$04,$05,$06,q6,70,70
+++B7,$04,$01,$07,b7,71,71
+++H7,$04,$03,$07,h7,71,71
+++S7,$04,$09,$07,s7,71,71
+++D7,$04,$0a,$07,d7,71,71
+++Q7,$04,$05,$07,q7,71,71
+++B8,$04,$01,$08,b8,72,72
+++H8,$04,$03,$08,h8,72,72
+++S8,$04,$09,$08,s8,72,72
+++D8,$04,$0a,$08,d8,72,72
+++Q8,$04,$05,$08,q8,72,72
+++B9,$04,$01,$09,b9,73,73
+++H9,$04,$03,$09,h9,73,73
+++S9,$04,$09,$09,s9,73,73
+++D9,$04,$0a,$09,d9,73,73
+++Q9,$04,$05,$09,q9,73,73
+++B10,$04,$01,$0A,b10,74,74
+++H10,$04,$03,$0A,h10,74,74
+++S10,$04,$09,$0A,s10,74,74
+++D10,$04,$0a,$0A,d10,74,74
+++Q10,$04,$05,$0A,q10,74,74
+++B11,$04,$01,$0B,b11,75,75
+++H11,$04,$03,$0B,h11,75,75
+++S11,$04,$09,$0B,s11,75,75
+++D11,$04,$0a,$0B,d11,75,75
+++Q11,$04,$05,$0B,q11,75,75
+++B12,$04,$01,$0C,b12,76,76
+++H12,$04,$03,$0C,h12,76,76
+++S12,$04,$09,$0C,s12,76,76
+++D12,$04,$0a,$0C,d12,76,76
+++Q12,$04,$05,$0C,q12,76,76
+++B13,$04,$01,$0D,b13,77,77
+++H13,$04,$03,$0D,h13,77,77
+++S13,$04,$09,$0D,s13,77,77
+++D13,$04,$0a,$0D,d13,77,77
+++Q13,$04,$05,$0D,q13,77,77
+++B14,$04,$01,$0E,b14,78,78
+++H14,$04,$03,$0E,h14,78,78
+++S14,$04,$09,$0E,s14,78,78
+++D14,$04,$0a,$0E,d14,78,78
+++Q14,$04,$05,$0E,q14,78,78
+++B15,$04,$01,$0F,b15,79,79
+++H15,$04,$03,$0F,h15,79,79
+++S15,$04,$09,$0F,s15,79,79
+++D15,$04,$0a,$0F,d15,79,79
+++Q15,$04,$05,$0F,q15,79,79
+++B16,$04,$01,$10,b16,80,80
+++H16,$04,$03,$10,h16,80,80
+++S16,$04,$09,$10,s16,80,80
+++D16,$04,$0a,$10,d16,80,80
+++Q16,$04,$05,$10,q16,80,80
+++B17,$04,$01,$11,b17,81,81
+++H17,$04,$03,$11,h17,81,81
+++S17,$04,$09,$11,s17,81,81
+++D17,$04,$0a,$11,d17,81,81
+++Q17,$04,$05,$11,q17,81,81
+++B18,$04,$01,$12,b18,82,82
+++H18,$04,$03,$12,h18,82,82
+++S18,$04,$09,$12,s18,82,82
+++D18,$04,$0a,$12,d18,82,82
+++Q18,$04,$05,$12,q18,82,82
+++B19,$04,$01,$13,b19,83,83
+++H19,$04,$03,$13,h19,83,83
+++S19,$04,$09,$13,s19,83,83
+++D19,$04,$0a,$13,d19,83,83
+++Q19,$04,$05,$13,q19,83,83
+++B20,$04,$01,$14,b20,84,84
+++H20,$04,$03,$14,h20,84,84
+++S20,$04,$09,$14,s20,84,84
+++D20,$04,$0a,$14,d20,84,84
+++Q20,$04,$05,$14,q20,84,84
+++B21,$04,$01,$15,b21,85,85
+++H21,$04,$03,$15,h21,85,85
+++S21,$04,$09,$15,s21,85,85
+++D21,$04,$0a,$15,d21,85,85
+++Q21,$04,$05,$15,q21,85,85
+++B22,$04,$01,$16,b22,86,86
+++H22,$04,$03,$16,h22,86,86
+++S22,$04,$09,$16,s22,86,86
+++D22,$04,$0a,$16,d22,86,86
+++Q22,$04,$05,$16,q22,86,86
+++B23,$04,$01,$17,b23,87,87
+++H23,$04,$03,$17,h23,87,87
+++S23,$04,$09,$17,s23,87,87
+++D23,$04,$0a,$17,d23,87,87
+++Q23,$04,$05,$17,q23,87,87
+++B24,$04,$01,$18,b24,88,88
+++H24,$04,$03,$18,h24,88,88
+++S24,$04,$09,$18,s24,88,88
+++D24,$04,$0a,$18,d24,88,88
+++Q24,$04,$05,$18,q24,88,88
+++B25,$04,$01,$19,b25,89,89
+++H25,$04,$03,$19,h25,89,89
+++S25,$04,$09,$19,s25,89,89
+++D25,$04,$0a,$19,d25,89,89
+++Q25,$04,$05,$19,q25,89,89
+++B26,$04,$01,$1A,b26,90,90
+++H26,$04,$03,$1A,h26,90,90
+++S26,$04,$09,$1A,s26,90,90
+++D26,$04,$0a,$1A,d26,90,90
+++Q26,$04,$05,$1A,q26,90,90
+++B27,$04,$01,$1B,b27,91,91
+++H27,$04,$03,$1B,h27,91,91
+++S27,$04,$09,$1B,s27,91,91
+++D27,$04,$0a,$1B,d27,91,91
+++Q27,$04,$05,$1B,q27,91,91
+++B28,$04,$01,$1C,b28,92,92
+++H28,$04,$03,$1C,h28,92,92
+++S28,$04,$09,$1C,s28,92,92
+++D28,$04,$0a,$1C,d28,92,92
+++Q28,$04,$05,$1C,q28,92,92
+++B29,$04,$01,$1D,b29,93,93
+++H29,$04,$03,$1D,h29,93,93
+++S29,$04,$09,$1D,s29,93,93
+++D29,$04,$0a,$1D,d29,93,93
+++Q29,$04,$05,$1D,q29,93,93
+++B30,$04,$01,$1E,b30,94,94
+++H30,$04,$03,$1E,h30,94,94
+++S30,$04,$09,$1E,s30,94,94
+++D30,$04,$0a,$1E,d30,94,94
+++Q30,$04,$05,$1E,q30,94,94
+++B31,$04,$01,$1F,b31,95,95
+++H31,$04,$03,$1F,h31,95,95
+++S31,$04,$09,$1F,s31,95,95
+++D31,$04,$0a,$1F,d31,95,95
+++Q31,$04,$05,$1F,q31,95,95
++
++ NZCV,$05,$00,$00,nzcv,0,0
++-
+++FPCR,$05,$00,$01,fpcr,0,0
+++FPSR,$05,$00,$02,fpsr,0,0
+++TPIDR_EL0,$05,$00,$03,tpidr_el0,0,0
++Index: fpc/fpcsrc/compiler/aarch64/a64tab.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/a64tab.inc
+++++ fpc/fpcsrc/compiler/aarch64/a64tab.inc
++@@ -1,4 +1,4 @@
++-{ don't edit, this file is generated from armins.dat }
+++{ don't edit, this file is generated from a64ins.dat }
++ (
++
++ );
++Index: fpc/fpcsrc/compiler/aarch64/aasmcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/aasmcpu.pas
+++++ fpc/fpcsrc/compiler/aarch64/aasmcpu.pas
++@@ -1,7 +1,7 @@
++ {
++ Copyright (c) 2003-2012 by Florian Klaempfl and others
++
++- Contains the assembler object for ARM64
+++ Contains the assembler object for Aarch64
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++@@ -149,9 +149,6 @@ uses
++
++ pinsentry=^tinsentry;
++
++-{ const
++- InsTab : array[0..instabentries-1] of TInsEntry={$i a64tab.inc} }
++-
++ var
++ InsTabCache : PInsTabCache;
++
++@@ -159,6 +156,7 @@ uses
++ taicpu = class(tai_cpu_abstract_sym)
++ oppostfix : TOpPostfix;
++ procedure loadshifterop(opidx:longint;const so:tshifterop);
+++ procedure loadconditioncode(opidx: longint; const c: tasmcond);
++ constructor op_none(op : tasmop);
++
++ constructor op_reg(op : tasmop;_op1 : tregister);
++@@ -167,15 +165,21 @@ uses
++
++ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
++ constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+++ constructor op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
++ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+++ constructor op_reg_const_shifterop(op : tasmop;_op1: tregister; _op2: aint;_op3 : tshifterop);
++
++ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
++ constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
++ constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+++ constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3, _op4: aint);
+++ constructor op_reg_reg_const_shifterop(op : tasmop;_op1,_op2 : tregister; _op3: aint; const _op4 : tshifterop);
++ constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
++ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
++ constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
++- constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+++ constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
+++ constructor op_reg_reg_reg_cond(op : tasmop;_op1,_op2,_op3 : tregister; const _op4: tasmcond);
+++
++
++ { this is for Jmp instructions }
++ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
++@@ -188,6 +192,7 @@ uses
++ function is_same_reg_move(regtype: Tregistertype):boolean; override;
++
++ function spilling_get_operation_type(opnr: longint): topertype;override;
+++ function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
++
++ { assembler }
++ public
++@@ -203,28 +208,29 @@ uses
++ procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
++ procedure ppubuildderefimploper(var o:toper);override;
++ procedure ppuderefoper(var o:toper);override;
++- private
++- { next fields are filled in pass1, so pass2 is faster }
++- inssize : shortint;
++- insoffset : longint;
++- LastInsOffset : longint; { need to be public to be reset }
++- insentry : PInsEntry;
++- function InsEnd:longint;
++- procedure create_ot(objdata:TObjData);
++- function Matches(p:PInsEntry):longint;
++- function calcsize(p:PInsEntry):shortint;
++- procedure gencode(objdata:TObjData);
++- function NeedAddrPrefix(opidx:byte):boolean;
++- procedure Swapoperands;
++- function FindInsentry(objdata:TObjData):boolean;
++ end;
++
++ tai_align = class(tai_align_abstract)
++ { nothing to add }
++ end;
++
++- function spilling_create_load(const ref:treference;r:tregister):Taicpu;
++- function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+++ type
+++ tsimplereftype =
+++ { valid reference }
+++ (sr_simple,
+++ { invalid reference, should not be generated by the code generator (but
+++ can be encountered via inline assembly, where it must be rejected) }
+++ sr_internal_illegal,
+++ { invalid reference, may be generated by the code generator and then
+++ must be simplified (also rejected in inline assembly) }
+++ sr_complex);
+++
+++ function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
+++ function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
+++ function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
+++
+++ function spilling_create_load(const ref: treference; r: tregister): taicpu;
+++ function spilling_create_store(r: tregister; const ref: treference): taicpu;
++
++ function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
++ function setcondition(i : taicpu;c : tasmcond) : taicpu;
++@@ -261,6 +267,21 @@ implementation
++ end;
++
++
+++ procedure taicpu.loadconditioncode(opidx: longint; const c: tasmcond);
+++ begin
+++ allocate_oper(opidx+1);
+++ with oper[opidx]^ do
+++ begin
+++ if typ<>top_conditioncode then
+++ begin
+++ clearop(opidx);
+++ end;
+++ cc:=c;
+++ typ:=top_conditioncode;
+++ end;
+++ end;
+++
+++
++ {*****************************************************************************
++ taicpu Constructors
++ *****************************************************************************}
++@@ -314,6 +335,16 @@ implementation
++ end;
++
++
+++ constructor taicpu.op_reg_const_shifterop(op: tasmop; _op1: tregister; _op2: aint; _op3: tshifterop);
+++ begin
+++ inherited create(op);
+++ ops:=3;
+++ loadreg(0,_op1);
+++ loadconst(1,_op2);
+++ loadshifterop(2,_op3);
+++ end;
+++
+++
++ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
++ begin
++ inherited create(op);
++@@ -323,6 +354,15 @@ implementation
++ end;
++
++
+++ constructor taicpu.op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
+++ begin
+++ inherited create(op);
+++ ops:=2;
+++ loadreg(0,_op1);
+++ loadconditioncode(1,_op2);
+++ end;
+++
+++
++ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
++ begin
++ inherited create(op);
++@@ -354,6 +394,28 @@ implementation
++ end;
++
++
+++ constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+++ begin
+++ inherited create(op);
+++ ops:=4;
+++ loadreg(0,_op1);
+++ loadreg(1,_op2);
+++ loadconst(2,aint(_op3));
+++ loadconst(3,aint(_op4));
+++ end;
+++
+++
+++ constructor taicpu.op_reg_reg_const_shifterop(op: tasmop; _op1, _op2: tregister; _op3: aint; const _op4: tshifterop);
+++ begin
+++ inherited create(op);
+++ ops:=4;
+++ loadreg(0,_op1);
+++ loadreg(1,_op2);
+++ loadconst(2,aint(_op3));
+++ loadshifterop(3,_op4);
+++ end;
+++
+++
++ constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
++ begin
++ inherited create(op);
++@@ -384,7 +446,7 @@ implementation
++ end;
++
++
++- constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+++ constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
++ begin
++ inherited create(op);
++ ops:=4;
++@@ -394,6 +456,16 @@ implementation
++ loadshifterop(3,_op4);
++ end;
++
+++ constructor taicpu.op_reg_reg_reg_cond(op: tasmop; _op1, _op2, _op3: tregister; const _op4: tasmcond);
+++ begin
+++ inherited create(op);
+++ ops:=4;
+++ loadreg(0,_op1);
+++ loadreg(1,_op2);
+++ loadreg(2,_op3);
+++ loadconditioncode(3,_op4);
+++ end;
+++
++
++ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
++ begin
++@@ -454,85 +526,403 @@ implementation
++ end;
++
++
++- function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+++ function spilling_create_op(op: tasmop; const ref: treference; r: tregister): taicpu;
+++ const
+++ { invalid sizes for aarch64 are 0 }
+++ subreg2bytesize: array[TSubRegister] of byte =
+++ (0,0,0,0,4,8,0,0,0,4,8,0,0,0);
++ var
++- op: tasmop;
+++ scalefactor: byte;
++ begin
+++ scalefactor:=subreg2bytesize[getsubreg(r)];
+++ if scalefactor=0 then
+++ internalerror(2014120301);
+++ if (ref.offset>4095*scalefactor) or
+++ ((ref.offset>255) and
+++ ((ref.offset mod scalefactor)<>0)) or
+++ (ref.offset<-256) then
+++ internalerror(2014120302);
++ case getregtype(r) of
++- R_INTREGISTER :
++- result:=taicpu.op_reg_ref(A_LDR,r,ref);
++- R_MMREGISTER :
++- begin
++- case getsubreg(r) of
++- R_SUBFD:
++- op:=A_LDR;
++- R_SUBFS:
++- op:=A_LDR;
++- else
++- internalerror(2009112905);
++- end;
++- result:=taicpu.op_reg_ref(op,r,ref);
++- end;
+++ R_INTREGISTER,
+++ R_MMREGISTER:
+++ result:=taicpu.op_reg_ref(op,r,ref);
++ else
++ internalerror(200401041);
++ end;
++ end;
++
++
++- function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+++ function is_valid_load_symbol(op: tasmop; oppostfix: toppostfix; const ref: treference): tsimplereftype;
+++ begin
+++ result:=sr_complex;
+++ if not assigned(ref.symboldata) and
+++ not(ref.refaddr in [addr_gotpageoffset,addr_gotpage,addr_pageoffset,addr_page]) then
+++ exit;
+++ { can't use pre-/post-indexed mode here (makes no sense either) }
+++ if ref.addressmode<>AM_OFFSET then
+++ exit;
+++ { "ldr literal" must be a 32/64 bit LDR and have a symbol }
+++ if assigned(ref.symboldata) and
+++ ((op<>A_LDR) or
+++ not(oppostfix in [PF_NONE,PF_W,PF_SW]) or
+++ not assigned(ref.symbol)) then
+++ exit;
+++ { if this is a (got) page offset load, we must have a base register and a
+++ symbol }
+++ if (ref.refaddr in [addr_gotpageoffset,addr_pageoffset]) and
+++ (not assigned(ref.symbol) or
+++ (ref.base=NR_NO) or
+++ (ref.index<>NR_NO) or
+++ (ref.offset<>0)) then
+++ begin
+++ result:=sr_internal_illegal;
+++ exit;
+++ end;
+++ { cannot have base or index register (we generate these kind of
+++ references internally, they should never end up here with an
+++ extra base or offset) }
+++ if (ref.refaddr in [addr_gotpage,addr_page]) and
+++ (ref.base<>NR_NO) or
+++ (ref.index<>NR_NO) then
+++ begin
+++ result:=sr_internal_illegal;
+++ exit;
+++ end;
+++ result:=sr_simple;
+++ end;
+++
+++
+++ function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
++ var
++- op: tasmop;
+++ maxoffs: asizeint;
+++ accesssize: longint;
++ begin
++- case getregtype(r) of
++- R_INTREGISTER :
++- result:=taicpu.op_reg_ref(A_STR,r,ref);
++- R_MMREGISTER :
++- begin
++- case getsubreg(r) of
++- R_SUBFD:
++- op:=A_STR;
++- R_SUBFS:
++- op:=A_STR;
+++ result:=sr_internal_illegal;
+++ { post-indexed is only allowed for vector and immediate loads/stores }
+++ if (ref.addressmode=AM_POSTINDEXED) and
+++ not(op in [A_LD1,A_LD2,A_LD3,A_LD4,A_ST1,A_ST2,A_ST3,A_ST4]) and
+++ (not(op in [A_LDR,A_STR,A_LDP,A_STP]) or
+++ (ref.base=NR_NO) or
+++ (ref.index<>NR_NO)) then
+++ exit;
+++
+++ { can only have a shift mode if we have an index }
+++ if (ref.index=NR_NO) and
+++ (ref.shiftmode<>SM_None) then
+++ exit;
+++
+++ { the index can never be the stack pointer }
+++ if ref.index=NR_SP then
+++ exit;
+++
+++ { no instruction supports an index without a base }
+++ if (ref.base=NR_NO) and
+++ (ref.index<>NR_NO) then
+++ begin
+++ result:=sr_complex;
+++ exit;
+++ end;
+++
+++ { LDR literal or GOT entry: 32 or 64 bit, label }
+++ if assigned(ref.symboldata) or
+++ assigned(ref.symbol) then
+++ begin
+++ { we generate these kind of references internally; at least for now,
+++ they should never end up here with an extra base or offset or so }
+++ result:=is_valid_load_symbol(op,oppostfix,ref);
+++ exit;
+++ end;
+++
+++ { any other reference cannot be gotpage/gotpageoffset/pic }
+++ if ref.refaddr in [addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset,addr_pic] then
+++ exit;
+++
+++ { base & index:
+++ * index cannot be the stack pointer
+++ * offset must be 0
+++ * can scale with the size of the access
+++ * can zero/sign extend 32 bit index register, and/or multiple by
+++ access size
+++ * no pre/post-indexing
+++ }
+++ if (ref.base<>NR_NO) and
+++ (ref.index<>NR_NO) then
+++ begin
+++ if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
+++ exit;
+++ case op of
+++ { this holds for both integer and fpu/vector loads }
+++ A_LDR,A_STR:
+++ if (ref.offset=0) and
+++ (((ref.shiftmode=SM_None) and
+++ (ref.shiftimm=0)) or
+++ ((ref.shiftmode in [SM_LSL,SM_UXTW,SM_SXTW]) and
+++ (ref.shiftimm=tcgsizep2size[size]))) then
+++ result:=sr_simple
++ else
++- internalerror(2009112904);
++- end;
++- result:=taicpu.op_reg_ref(op,r,ref);
+++ result:=sr_complex;
+++ { todo }
+++ A_LD1,A_LD2,A_LD3,A_LD4,
+++ A_ST1,A_ST2,A_ST3,A_ST4:
+++ internalerror(2014110704);
+++ { these don't support base+index }
+++ A_LDUR,A_STUR,
+++ A_LDP,A_STP:
+++ result:=sr_complex;
+++ else
+++ { nothing: result is already sr_internal_illegal };
+++ end;
+++ exit;
+++ end;
+++
+++ { base + immediate offset. Variants:
+++ * LDR*/STR*:
+++ - pre- or post-indexed with signed 9 bit immediate
+++ - regular with unsiged scaled immediate (multiple of access
+++ size), in the range 0 to (12 bit * access_size)-1
+++ * LDP/STP
+++ - pre- or post-indexed with signed 9 bit immediate
+++ - regular with signed 9 bit immediate
+++ * LDUR*/STUR*:
+++ - regular with signed 9 bit immediate
+++ }
+++ if ref.base<>NR_NO then
+++ begin
+++ accesssize:=1 shl tcgsizep2size[size];
+++ case op of
+++ A_LDR,A_STR:
+++ begin
+++ if (ref.addressmode=AM_OFFSET) and
+++ (ref.offset>=0) and
+++ (ref.offset<(((1 shl 12)-1)*accesssize)) and
+++ ((ref.offset mod accesssize)=0) then
+++ result:=sr_simple
+++ else if (ref.offset>=-256) and
+++ (ref.offset<=255) then
+++ begin
+++ { non pre-/post-indexed regular loads/stores can only be
+++ performed using LDUR/STUR }
+++ if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
+++ result:=sr_simple
+++ else
+++ result:=sr_complex
+++ end
+++ else
+++ result:=sr_complex;
+++ end;
+++ A_LDP,A_LDNP,
+++ A_STP,A_STNP:
+++ begin
+++ { only supported for 32/64 bit }
+++ if not(oppostfix in [PF_W,PF_SW,PF_None]) then
+++ exit;
+++ { offset must be a multple of the access size }
+++ if (ref.offset mod accesssize)<>0 then
+++ exit;
+++ { offset must fit in a signed 7 bit offset }
+++ if (ref.offset>=-(1 shl (6+tcgsizep2size[size]))) and
+++ (ref.offset<=(1 shl (6+tcgsizep2size[size]))-1) then
+++ result:=sr_simple
+++ else
+++ result:=sr_complex;
+++ end;
+++ A_LDUR,A_STUR:
+++ begin
+++ if (ref.addressmode=AM_OFFSET) and
+++ (ref.offset>=-256) and
+++ (ref.offset<=255) then
+++ result:=sr_simple
+++ else
+++ result:=sr_complex;
+++ end;
+++ { todo }
+++ A_LD1,A_LD2,A_LD3,A_LD4,
+++ A_ST1,A_ST2,A_ST3,A_ST4:
+++ internalerror(2014110907);
+++ A_LDAR,
+++ A_LDAXR,
+++ A_LDXR,
+++ A_LDXP,
+++ A_STLR,
+++ A_STLXR,
+++ A_STLXP,
+++ A_STXP,
+++ A_STXR:
+++ begin
+++ if (ref.addressmode=AM_OFFSET) and
+++ (ref.offset=0) then
+++ result:=sr_simple;
+++ end
+++ else
+++ { nothing: result is already sr_internal_illegal };
++ end;
+++ exit;
+++ end;
+++ { absolute addresses are not supported, have to load them first into
+++ a register }
+++ result:=sr_complex;
+++ end;
+++
+++
+++ function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
+++ begin
+++ case opc of
+++ A_ADD,
+++ A_AND,
+++ A_EON,
+++ A_EOR,
+++ A_ORN,
+++ A_ORR,
+++ A_SUB:
+++ result:=opnr=3;
+++ A_BIC,
+++ A_CMN,
+++ A_CMP,
+++ A_MOVK,
+++ A_MOVZ,
+++ A_MOVN,
+++ A_MVN,
+++ A_NEG,
+++ A_TST:
+++ result:=opnr=2;
++ else
++- internalerror(200401041);
+++ result:=false;
++ end;
++ end;
++
++
+++ function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
+++ begin
+++ case opc of
+++ A_ADD,
+++ A_SUB,
+++ A_NEG,
+++ A_AND,
+++ A_TST,
+++ A_CMN,
+++ A_CMP:
+++ begin
+++ result:=false;
+++ if not useszr then
+++ result:=
+++ (sm in shiftedregmodes) and
+++ ((shiftimm in [0..31]) or
+++ (is64bit and
+++ (shiftimm in [32..63])));
+++ if not usessp then
+++ result:=
+++ result or
+++ ((sm in extendedregmodes) and
+++ (shiftimm in [0..4]));
+++ end;
+++ A_BIC,
+++ A_EON,
+++ A_EOR,
+++ A_MVN,
+++ A_ORN,
+++ A_ORR:
+++ result:=
+++ (sm in shiftedregmodes) and
+++ (shiftimm in [0..31*(ord(is64bit)+1)+ord(is64bit)]);
+++ A_MOVK,
+++ A_MOVZ,
+++ A_MOVN:
+++ result:=
+++ (sm=SM_LSL) and
+++ ((shiftimm in [0,16]) or
+++ (is64bit and
+++ (shiftimm in [32,48])));
+++ else
+++ result:=false;
+++ end;
+++ end;
+++
+++
+++ function spilling_create_load(const ref: treference; r: tregister): taicpu;
+++ var
+++ op: tasmop;
+++ begin
+++ if (ref.index<>NR_NO) or
+++ (ref.offset<-256) or
+++ (ref.offset>255) then
+++ op:=A_LDR
+++ else
+++ op:=A_LDUR;
+++ result:=spilling_create_op(op,ref,r);
+++ end;
+++
+++
+++ function spilling_create_store(r: tregister; const ref: treference): taicpu;
+++ var
+++ op: tasmop;
+++ begin
+++ if (ref.index<>NR_NO) or
+++ (ref.offset<-256) or
+++ (ref.offset>255) then
+++ op:=A_STR
+++ else
+++ op:=A_STUR;
+++ result:=spilling_create_op(op,ref,r);
+++ end;
+++
+++
++ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
++ begin
++ case opcode of
++- A_ADC,A_ADD,A_AND,A_BIC,
++- A_EOR,A_CLZ,A_RBIT,
++- A_LDR,
++- A_MOV,A_MVN,A_MUL,
++- A_ORR,A_SBC,A_SUB,
++- A_UXT,A_SXT:
+++ A_B,A_BL,
+++ A_CMN,A_CMP,
+++ A_CCMN,A_CCMP,
+++ A_TST:
+++ result:=operand_read;
+++ A_STR,A_STUR:
++ if opnr=0 then
++- result:=operand_write
+++ result:=operand_read
++ else
+++ { check for pre/post indexed in spilling_get_operation_type_ref }
++ result:=operand_read;
++- A_B,A_BL,
++- A_CMN,A_CMP,A_TST:
++- result:=operand_read;
++- A_STR:
++- { important is what happens with the involved registers }
+++ A_STLXP,
+++ A_STLXR,
+++ A_STXP,
+++ A_STXR:
++ if opnr=0 then
++- result := operand_read
+++ result:=operand_write
++ else
++- { check for pre/post indexed }
++- result := operand_read;
++- else
++- internalerror(200403151);
+++ result:=operand_read;
+++ A_STP:
+++ begin
+++ if opnr in [0,1] then
+++ result:=operand_read
+++ else
+++ { check for pre/post indexed in spilling_get_operation_type_ref }
+++ result:=operand_read;
+++ end;
+++ A_LDP,
+++ A_LDXP:
+++ begin
+++ if opnr in [0,1] then
+++ result:=operand_write
+++ else
+++ { check for pre/post indexed in spilling_get_operation_type_ref }
+++ result:=operand_read;
+++ end;
+++ else
+++ if opnr=0 then
+++ result:=operand_write
+++ else
+++ result:=operand_read;
++ end;
++ end;
++
++
+++ function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+++ begin
+++ result:=operand_read;
+++ if (oper[opnr]^.ref^.base = reg) and
+++ (oper[opnr]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
+++ result:=operand_readwrite;
+++ end;
+++
+++
++ procedure BuildInsTabCache;
++ var
++ i : longint;
++@@ -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.
++Index: fpc/fpcsrc/compiler/aarch64/agcpugas.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/agcpugas.pas
++@@ -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: fpc/fpcsrc/compiler/aarch64/aoptcpub.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/aoptcpub.pas
+++++ fpc/fpcsrc/compiler/aarch64/aoptcpub.pas
++@@ -118,17 +118,35 @@ Implementation
++ End;
++
++
++- function TAoptBaseCpu.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
+++ function TAoptBaseCpu.RegModifiedByInstruction(reg: tregister; p1: tai): boolean;
++ var
++- i : Longint;
+++ i: longint;
+++ preg: tregister;
++ begin
++ result:=false;
++ for i:=0 to taicpu(p1).ops-1 do
++- if (taicpu(p1).oper[i]^.typ=top_reg) and (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
++- begin
++- result:=true;
++- exit;
++- end;
+++ case taicpu(p1).oper[i]^.typ of
+++ top_reg:
+++ begin
+++ preg:=taicpu(p1).oper[i]^.reg;
+++ if (getregtype(preg)=getregtype(reg)) and
+++ (getsupreg(preg)=getsupreg(reg)) and
+++ (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
+++ begin
+++ result:=true;
+++ exit;
+++ end;
+++ end;
+++ top_ref:
+++ begin
+++ if (taicpu(p1).oper[i]^.ref^.addressmode<>am_offset) and
+++ (reg=taicpu(p1).oper[i]^.ref^.base) then
+++ begin
+++ result:=true;
+++ exit
+++ end;
+++ end;
+++ end;
++ end;
++
++ End.
++Index: fpc/fpcsrc/compiler/aarch64/cgcpu.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/cgcpu.pas
++@@ -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: fpc/fpcsrc/compiler/aarch64/cpubase.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/cpubase.pas
+++++ fpc/fpcsrc/compiler/aarch64/cpubase.pas
++@@ -1,7 +1,8 @@
++ {
++ Copyright (c) 1998-2012 by Florian Klaempfl and Peter Vreman
+++ Copyright (c) 2014 by Jonas Maebe and Florian Klaempfl
++
++- Contains the base types for ARM64
+++ Contains the base types for Aarch64
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++@@ -68,14 +69,22 @@ unit cpubase;
++ { Available Superregisters }
++ {$i ra64sup.inc}
++
+++ RS_IP0 = RS_X16;
+++ RS_IP1 = RS_X17;
+++
++ R_SUBWHOLE = R_SUBQ;
++
++ { Available Registers }
++ {$i ra64con.inc}
++
+++ NR_IP0 = NR_X16;
+++ NR_IP1 = NR_X17;
+++
++ { Integer Super registers first and last }
++ first_int_supreg = RS_X0;
++- first_int_imreg = $20;
+++ { xzr and sp take up a separate super register because some instructions
+++ are ambiguous otherwise }
+++ first_int_imreg = $21;
++
++ { Integer Super registers first and last }
++ first_fpu_supreg = RS_S0;
++@@ -92,7 +101,7 @@ unit cpubase;
++ The value of this constant is equal to the constant
++ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
++ }
++- std_param_align = 4;
+++ std_param_align = 8;
++
++ { TODO: Calculate bsstart}
++ regnumber_count_bsstart = 128;
++@@ -109,7 +118,7 @@ unit cpubase;
++ {$i ra64dwa.inc}
++ );
++ { registers which may be destroyed by calls }
++- VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X29..RS_X30];
+++ VOLATILE_INTREGISTERS = [RS_X0..RS_X18,RS_X30];
++ VOLATILE_MMREGISTERS = [RS_D0..RS_D7,RS_D16..RS_D31];
++
++ type
++@@ -126,16 +135,23 @@ unit cpubase;
++ TOpPostfix = (PF_None,
++ { update condition flags }
++ PF_S,
++- { load/store }
++- PF_B,PF_SB,PF_H,PF_SH
+++ { load/store sizes }
+++ PF_B,PF_SB,PF_H,PF_SH,PF_W,PF_SW
++ );
++
++ TOpPostfixes = set of TOpPostfix;
++
++ const
++- oppostfix2str : array[TOpPostfix] of string[2] = ('',
+++ tcgsizep2size: array[OS_NO..OS_F128] of byte =
+++ {OS_NO }
+++ (0,
+++ {OS_8,OS_16,OS_32,OS_64,OS_128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128}
+++ 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
+++ {OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,}
+++ 2, 3, 0, 3, 4);
+++ oppostfix2str: array[TOpPostfix] of string[2] = ('',
++ 's',
++- 'b','sb','h','sh');
+++ 'b','sb','h','sh','w','sw');
++
++ {*****************************************************************************
++ Conditions
++@@ -150,13 +166,15 @@ unit cpubase;
++ TAsmConds = set of TAsmCond;
++
++ const
+++ C_CS = C_HS;
+++ C_CC = C_LO;
++ cond2str : array[TAsmCond] of string[2]=('',
++ 'eq','ne','hs','lo','mi','pl','vs','vc','hi','ls',
++ 'ge','lt','gt','le','al','nv'
++ );
++
++ uppercond2str : array[TAsmCond] of string[2]=('',
++- 'EQ','NE','hs','LO','MI','PL','VS','VC','HI','LS',
+++ 'EQ','NE','HS','LO','MI','PL','VS','VC','HI','LS',
++ 'GE','LT','GT','LE','AL','NV'
++ );
++
++@@ -168,12 +186,28 @@ unit cpubase;
++ TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
++ F_GE,F_LT,F_GT,F_LE);
++
+++ const
+++ F_HS = F_CS;
+++ F_LO = F_CC;
+++
++ {*****************************************************************************
++ Operands
++ *****************************************************************************}
++
+++ type
++ taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
++- tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR);
+++
+++ tshiftmode = (SM_None,
+++ { shifted register instructions. LSL can also be used for
+++ the index register of certain loads/stores }
+++ SM_LSL,SM_LSR,SM_ASR,
+++ { extended register instructions: zero/sign extension +
+++ optional shift (interpreted as LSL after extension)
+++ -- the index register of certain loads/stores can be
+++ extended via (s|u)xtw with a shiftval of either 0 or
+++ log2(transfer size of the load/store)
+++ }
+++ SM_UXTB,SM_UXTH,SM_UXTW,SM_UXTX,SM_SXTB,SM_SXTH,SM_SXTW,SM_SXTX);
++
++ tupdatereg = (UR_None,UR_Update);
++
++@@ -184,12 +218,6 @@ unit cpubase;
++ shiftimm : byte;
++ end;
++
++- tcpumodeflag = (mfA, mfI, mfF);
++- tcpumodeflags = set of tcpumodeflag;
++-
++- tspecialregflag = (srC, srX, srS, srF);
++- tspecialregflags = set of tspecialregflag;
++-
++ {*****************************************************************************
++ Constants
++ *****************************************************************************}
++@@ -201,6 +229,10 @@ unit cpubase;
++ maxfpuregs = 32;
++ maxaddrregs = 0;
++
+++ shiftedregmodes = [SM_LSL,SM_UXTB,SM_UXTH,SM_UXTW,SM_UXTX,SM_SXTB,SM_SXTH,SM_SXTW,SM_SXTX];
+++ extendedregmodes = [SM_LSL,SM_LSR,SM_ASR];
+++
+++
++ {*****************************************************************************
++ Operand Sizes
++ *****************************************************************************}
++@@ -232,17 +264,23 @@ unit cpubase;
++ Generic Register names
++ *****************************************************************************}
++
++- NR_SP = NR_XZR;
++- RS_SP = RS_XZR;
++- NR_WSP = NR_WZR;
++- RS_WSP = RS_WZR;
+++
+++ NR_FP = NR_X29;
+++ RS_FP = RS_X29;
+++ NR_WFP = NR_W29;
+++ RS_WFP = RS_W29;
+++
+++ NR_LR = NR_X30;
+++ RS_LR = RS_X30;
+++ NR_WLR = NR_W30;
+++ RS_WLR = RS_W30;
++
++ { Stack pointer register }
++ NR_STACK_POINTER_REG = NR_SP;
++ RS_STACK_POINTER_REG = RS_SP;
++- { Frame pointer register (initialized in tarmprocinfo.init_framepointer) }
++- RS_FRAME_POINTER_REG: tsuperregister = RS_X29;
++- NR_FRAME_POINTER_REG: tregister = NR_X29;
+++ { Frame pointer register }
+++ NR_FRAME_POINTER_REG = NR_X29;
+++ RS_FRAME_POINTER_REG = RS_X29;
++ { Register for addressing absolute data in a position independant way,
++ such as in PIC code. The exact meaning is ABI specific. For
++ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
++@@ -307,6 +345,9 @@ unit cpubase;
++
++ function dwarf_reg(r:tregister):shortint;
++
+++ function is_shifter_const(d: aint; size: tcgsize): boolean;
+++
+++
++ implementation
++
++ uses
++@@ -329,13 +370,24 @@ unit cpubase;
++ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
++ begin
++ case regtype of
+++ R_INTREGISTER:
+++ begin
+++ case s of
+++ { there's only Wn and Xn }
+++ OS_64,
+++ OS_S64:
+++ cgsize2subreg:=R_SUBWHOLE;
+++ else
+++ cgsize2subreg:=R_SUBD;
+++ end;
+++ end;
++ R_MMREGISTER:
++ begin
++ case s of
++ OS_F32:
++- cgsize2subreg:=R_SUBFS;
+++ cgsize2subreg:=R_SUBMMS;
++ OS_F64:
++- cgsize2subreg:=R_SUBFD;
+++ cgsize2subreg:=R_SUBMMD;
++ else
++ internalerror(2009112701);
++ end;
++@@ -349,18 +401,22 @@ unit cpubase;
++ function reg_cgsize(const reg: tregister): tcgsize;
++ begin
++ case getregtype(reg) of
++- R_INTREGISTER :
++- reg_cgsize:=OS_32;
++- R_FPUREGISTER :
++- reg_cgsize:=OS_F80;
+++ R_INTREGISTER:
+++ case getsubreg(reg) of
+++ R_SUBD:
+++ result:=OS_32
+++ else
+++ result:=OS_64;
+++ end;
++ R_MMREGISTER :
++ begin
++ case getsubreg(reg) of
++- R_SUBFD,
++- R_SUBWHOLE:
+++ R_SUBMMD:
++ result:=OS_F64;
++- R_SUBFS:
+++ R_SUBMMS:
++ result:=OS_F32;
+++ R_SUBMMWHOLE:
+++ result:=OS_M128;
++ else
++ internalerror(2009112903);
++ end;
++@@ -373,9 +429,7 @@ unit cpubase;
++
++ function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
++ begin
++- { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
++- To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
++- is_calljmp:= o in [A_B,A_BLR,A_RET];
+++ is_calljmp:=o in [A_B,A_BL,A_BLR,A_RET,A_CBNZ,A_CBZ,A_TBNZ,A_TBZ];
++ end;
++
++
++@@ -391,8 +445,8 @@ unit cpubase;
++
++ function flags_to_cond(const f: TResFlags) : TAsmCond;
++ const
++- flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
++- (C_EQ,C_NE,C_HI,C_LO,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+++ flag_2_cond: array[TResFlags] of TAsmCond =
+++ (C_EQ,C_NE,C_HS,C_LO,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
++ C_GE,C_LT,C_GT,C_LE);
++ begin
++ if f>high(flag_2_cond) then
++@@ -434,7 +488,7 @@ unit cpubase;
++ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
++ const
++ inverse: array[TAsmCond] of TAsmCond=(C_None,
++- C_NE,C_EQ,C_LO,C_HI,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+++ C_NE,C_EQ,C_LO,C_HS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
++ C_LT,C_GE,C_LE,C_GT,C_None,C_None
++ );
++ begin
++@@ -456,4 +510,112 @@ unit cpubase;
++ end;
++
++
+++ function is_shifter_const(d: aint; size: tcgsize): boolean;
+++ var
+++ pattern, checkpattern: qword;
+++ patternlen, maxbits, replicatedlen: longint;
+++ rightmostone, rightmostzero, checkbit, secondrightmostbit: longint;
+++ begin
+++ result:=false;
+++ { patterns with all bits 0 or 1 cannot be represented this way }
+++ if (d=0) then
+++ exit;
+++ case size of
+++ OS_64,
+++ OS_S64:
+++ begin
+++ if d=-1 then
+++ exit;
+++ maxbits:=64;
+++ end
+++ else
+++ begin
+++ if longint(d)=-1 then
+++ exit;
+++ { we'll generate a 32 bit pattern -> ignore upper sign bits in
+++ case of negative longint value }
+++ d:=cardinal(d);
+++ maxbits:=32;
+++ end;
+++ end;
+++ { "The Logical (immediate) instructions accept a bitmask immediate value
+++ that is a 32-bit pattern or a 64-bit pattern viewed as a vector of
+++ identical elements of size e = 2, 4, 8, 16, 32 or, 64 bits. Each
+++ element contains the same sub-pattern, that is a single run of
+++ 1 to (e - 1) nonzero bits from bit 0 followed by zero bits, then
+++ rotated by 0 to (e - 1) bits." (ARMv8 ARM)
+++
+++ Rather than generating all possible patterns and checking whether they
+++ match our constant, we check whether the lowest 2/4/8/... bits are
+++ a valid pattern, and if so whether the constant consists of a
+++ replication of this pattern. Such a valid pattern has the form of
+++ either (regexp notation)
+++ * 1+0+1*
+++ * 0+1+0* }
+++ patternlen:=2;
+++ while patternlen<=maxbits do
+++ begin
+++ { try lowest <patternlen> bits of d as pattern }
+++ if patternlen<>64 then
+++ pattern:=qword(d) and ((qword(1) shl patternlen)-1)
+++ else
+++ pattern:=qword(d);
+++ { valid pattern? If it contains too many 1<->0 transitions, larger
+++ parts of d cannot be a valid pattern either }
+++ rightmostone:=BsfQWord(pattern);
+++ rightmostzero:=BsfQWord(not(pattern));
+++ { pattern all ones or zeroes -> not a valid pattern (but larger ones
+++ can still be valid, since we have too few transitions) }
+++ if (rightmostone<patternlen) and
+++ (rightmostzero<patternlen) then
+++ begin
+++ if rightmostone>rightmostzero then
+++ begin
+++ { we have .*1*0* -> check next zero position by shifting
+++ out the existing zeroes (shr rightmostone), inverting and
+++ then again looking for the rightmost one position }
+++ checkpattern:=not(pattern);
+++ checkbit:=rightmostone;
+++ end
+++ else
+++ begin
+++ { same as above, but for .*0*1* }
+++ checkpattern:=pattern;
+++ checkbit:=rightmostzero;
+++ end;
+++ secondrightmostbit:=BsfQWord(checkpattern shr checkbit)+checkbit;
+++ { if this position is >= patternlen -> ok (1 transition),
+++ otherwise we now have 2 transitions and have to check for a
+++ third (if there is one, abort)
+++
+++ bsf returns 255 if no 1 bit is found, so in that case it's
+++ also ok
+++ }
+++ if secondrightmostbit<patternlen then
+++ begin
+++ secondrightmostbit:=BsfQWord(not(checkpattern) shr secondrightmostbit)+secondrightmostbit;
+++ if secondrightmostbit<patternlen then
+++ exit;
+++ end;
+++ { ok, this is a valid pattern, now does d consist of a
+++ repetition of this pattern? }
+++ replicatedlen:=patternlen;
+++ checkpattern:=pattern;
+++ while replicatedlen<maxbits do
+++ begin
+++ { douplicate current pattern }
+++ checkpattern:=checkpattern or (checkpattern shl replicatedlen);
+++ replicatedlen:=replicatedlen*2;
+++ end;
+++ if qword(d)=checkpattern then
+++ begin
+++ { yes! }
+++ result:=true;
+++ exit;
+++ end;
+++ end;
+++ patternlen:=patternlen*2;
+++ end;
+++ end;
+++
++ end.
++Index: fpc/fpcsrc/compiler/aarch64/cpuinfo.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/cpuinfo.pas
+++++ fpc/fpcsrc/compiler/aarch64/cpuinfo.pas
++@@ -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
++Index: fpc/fpcsrc/compiler/aarch64/cpunode.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/cpunode.pas
++@@ -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: fpc/fpcsrc/compiler/aarch64/cpupara.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/cpupara.pas
+++++ fpc/fpcsrc/compiler/aarch64/cpupara.pas
++@@ -1,5 +1,5 @@
++ {
++- Copyright (c) 2003-2012 by Florian Klaempfl and others
+++ Copyright (c) 2013-2014 by Jonas Maebe, Florian Klaempfl and others
++
++ AArch64 specific calling conventions
++
++@@ -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;
+++ { ABI: if the parameter would be passed in registers, it is returned
+++ in those registers; otherwise, it's returned by reference }
+++ result:=push_addr_param(vs_value,def,pd.proccalloption);
++ end;
++
++
++- procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
++- begin
++- curintreg:=RS_R0;
++- curfloatreg:=RS_F0;
++- curmmreg:=RS_D0;
++- cur_stack_offset:=0;
++- sparesinglereg := NR_NO;
++- end;
++-
++-
++- function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
++- var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
++-
+++ procedure 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;
+++ { hidden function result parameter is passed in X8 (doesn't have to
+++ be valid on return) according to the ABI
++
++- hp.paraloc[side].reset;
++-
++- { currently only support C-style array of const,
++- there should be no location assigned to the vararg array itself }
++- if (p.proccalloption in cstylearrayofconst) and
++- is_array_of_const(paradef) then
++- begin
++- paraloc:=hp.paraloc[side].add_location;
++- { hack: the paraloc must be valid, but is not actually used }
++- paraloc^.loc:=LOC_REGISTER;
++- paraloc^.register:=NR_R0;
++- paraloc^.size:=OS_ADDR;
++- break;
++- end;
++-
++- if push_addr_param(hp.varspez,paradef,p.proccalloption) then
++- begin
++- paradef:=getpointerdef(paradef);
++- loc:=LOC_REGISTER;
++- paracgsize := OS_ADDR;
++- paralen := tcgsize2size[OS_ADDR];
++- end
++- else
+++ -- don't follow the ABI for managed types, because
+++ a) they are passed in registers as parameters, so we should also
+++ return them in a register to be ABI-compliant (which we can't
+++ because the entire compiler is built around the idea that
+++ they are returned by reference, for ref-counting performance
+++ and Delphi-compatibility reasons)
+++ b) there are hacks in the system unit that expect that you can
+++ call
+++ function f: com_interface;
+++ as
+++ procedure p(out o: obj);
+++ That can only work in case we do not use x8 to return them
+++ from the function, but the regular first parameter register.
+++
+++ As the ABI says this behaviour is ok for C++ classes with a
+++ non-trivial copy constructor or destructor, it seems reasonable
+++ for us to do this for managed types as well.}
+++ if (vo_is_funcret in hp.varoptions) and
+++ not is_managed_type(hp.vardef) then
++ begin
++- if not is_special_array(paradef) then
++- paralen := paradef.size
++- else
++- paralen := tcgsize2size[def_cgsize(paradef)];
++- loc := getparaloc(p.proccalloption,paradef,isvariadic);
++- if (paradef.typ in [objectdef,arraydef,recorddef]) and
++- not is_special_array(paradef) and
++- (hp.varspez in [vs_value,vs_const]) then
++- paracgsize := int_cgsize(paralen)
++- else
+++ hp.paraloc[side].reset;
+++ hp.paraloc[side].size:=OS_ADDR;
+++ hp.paraloc[side].alignment:=voidpointertype.alignment;
+++ hp.paraloc[side].intsize:=voidpointertype.size;
+++ hp.paraloc[side].def:=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;
++- begin
++- init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
++-
++- 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)
+++ function taarch64paramanager.create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;
+++ begin
+++ init_para_alloc_values;
+++
+++ { 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;
++Index: fpc/fpcsrc/compiler/aarch64/cpupi.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/cpupi.pas
++@@ -0,0 +1,68 @@
+++{
+++ Copyright (c) 2002 by Florian Klaempfl
+++
+++ This unit contains the CPU specific part of tprocinfo
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit cpupi;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++ uses
+++ procinfo,
+++ psub;
+++
+++ type
+++ taarch64procinfo=class(tcgprocinfo)
+++ constructor create(aparent: tprocinfo); override;
+++ procedure set_first_temp_offset; override;
+++ end;
+++
+++implementation
+++
+++ uses
+++ tgobj,
+++ cpubase;
+++
+++ constructor taarch64procinfo.create(aparent: tprocinfo);
+++ begin
+++ inherited;
+++ { use the stack pointer as framepointer, because
+++ 1) we exactly know the offsets of the temps from the stack pointer
+++ after pass 1 (based on the require parameter stack size for called
+++ routines), while we don't know it for the frame pointer (it depends
+++ on the number of saved registers)
+++ 2) temp offsets from the stack pointer are positive while those from
+++ the frame pointer are negative, and we can directly encode much
+++ bigger positive offsets in the instructions
+++ }
+++ framepointer:=NR_STACK_POINTER_REG;
+++ end;
+++
+++ procedure taarch64procinfo.set_first_temp_offset;
+++ begin
+++ { leave room for allocated parameters }
+++ tg.setfirsttemp(align(maxpushedparasize,16));
+++ end;
+++
+++
+++begin
+++ cprocinfo:=taarch64procinfo;
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/cputarg.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/cputarg.pas
++@@ -0,0 +1,70 @@
+++{
+++ Copyright (c) 2001-2002 by Peter Vreman
+++
+++ Includes the AArch64 dependent target units
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit cputarg;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++
+++implementation
+++
+++ uses
+++ systems { prevent a syntax error when nothing is included }
+++
+++{**************************************
+++ Targets
+++**************************************}
+++
+++ {$ifndef NOTARGETLINUX}
+++ ,t_linux
+++ {$endif}
+++ {$ifndef NOTARGETBSD}
+++ ,t_bsd
+++ {$endif}
+++
+++{**************************************
+++ Assemblers
+++**************************************}
+++
+++ {$ifndef NOAGCPUGAS}
+++ ,agcpugas
+++ {$endif}
+++
+++{**************************************
+++ Assembler Readers
+++**************************************}
+++
+++ {$ifndef NoRaarmgas}
+++ ,racpugas
+++ {$endif NoRaarmgas}
+++
+++{**************************************
+++ Debuginfo
+++**************************************}
+++
+++ {$ifndef NoDbgDwarf}
+++ ,dbgdwarf
+++ {$endif NoDbgDwarf}
+++ ;
+++
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/hlcgcpu.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/hlcgcpu.pas
++@@ -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.
++Index: fpc/fpcsrc/compiler/aarch64/ncpuadd.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/ncpuadd.pas
++@@ -0,0 +1,402 @@
+++{
+++ Copyright (c) 2014 Jonas Maebe
+++
+++ Code generation for add nodes on AArch64
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit ncpuadd;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++ uses
+++ node,ncgadd,cpubase;
+++
+++ type
+++ taarch64addnode = class(tcgaddnode)
+++ private
+++ function GetResFlags(unsigned:Boolean):TResFlags;
+++ function GetFPUResFlags:TResFlags;
+++ protected
+++ procedure second_addfloat;override;
+++ procedure second_cmpfloat;override;
+++ procedure second_cmpboolean;override;
+++ procedure second_cmpsmallset;override;
+++ procedure second_cmpordinal;override;
+++ procedure second_addordinal;override;
+++ procedure second_add64bit; override;
+++ procedure second_cmp64bit; override;
+++ public
+++ function use_generic_mul32to64: boolean; override;
+++ end;
+++
+++ implementation
+++
+++ uses
+++ systems,
+++ cutils,verbose,
+++ paramgr,procinfo,
+++ aasmtai,aasmdata,aasmcpu,defutil,
+++ cgbase,cgcpu,cgutils,
+++ cpupara,
+++ ncon,nset,nadd,
+++ hlcgobj, ncgutil,cgobj;
+++
+++{*****************************************************************************
+++ taarch64addnode
+++*****************************************************************************}
+++
+++ function taarch64addnode.GetResFlags(unsigned:Boolean):TResFlags;
+++ begin
+++ case NodeType of
+++ equaln:
+++ GetResFlags:=F_EQ;
+++ unequaln:
+++ GetResFlags:=F_NE;
+++ else
+++ if not(unsigned) then
+++ begin
+++ if nf_swapped in flags then
+++ case NodeType of
+++ ltn:
+++ GetResFlags:=F_GT;
+++ lten:
+++ GetResFlags:=F_GE;
+++ gtn:
+++ GetResFlags:=F_LT;
+++ gten:
+++ GetResFlags:=F_LE;
+++ else
+++ internalerror(2014082010);
+++ end
+++ else
+++ case NodeType of
+++ ltn:
+++ GetResFlags:=F_LT;
+++ lten:
+++ GetResFlags:=F_LE;
+++ gtn:
+++ GetResFlags:=F_GT;
+++ gten:
+++ GetResFlags:=F_GE;
+++ else
+++ internalerror(2014082011);
+++ end;
+++ end
+++ else
+++ begin
+++ if nf_swapped in Flags then
+++ case NodeType of
+++ ltn:
+++ GetResFlags:=F_HI;
+++ lten:
+++ GetResFlags:=F_HS;
+++ gtn:
+++ GetResFlags:=F_LO;
+++ gten:
+++ GetResFlags:=F_LS;
+++ else
+++ internalerror(2014082012);
+++ end
+++ else
+++ case NodeType of
+++ ltn:
+++ GetResFlags:=F_LO;
+++ lten:
+++ GetResFlags:=F_LS;
+++ gtn:
+++ GetResFlags:=F_HI;
+++ gten:
+++ GetResFlags:=F_HS;
+++ else
+++ internalerror(2014082013);
+++ end;
+++ end;
+++ end;
+++ end;
+++
+++
+++ function taarch64addnode.GetFPUResFlags:TResFlags;
+++ begin
+++ case NodeType of
+++ equaln:
+++ result:=F_EQ;
+++ unequaln:
+++ result:=F_NE;
+++ else
+++ begin
+++ if nf_swapped in Flags then
+++ case NodeType of
+++ ltn:
+++ result:=F_GT;
+++ lten:
+++ result:=F_GE;
+++ gtn:
+++ result:=F_LO;
+++ gten:
+++ result:=F_LS;
+++ else
+++ internalerror(2014082014);
+++ end
+++ else
+++ case NodeType of
+++ ltn:
+++ result:=F_LO;
+++ lten:
+++ result:=F_LS;
+++ gtn:
+++ result:=F_GT;
+++ gten:
+++ result:=F_GE;
+++ else
+++ internalerror(2014082015);
+++ end;
+++ end;
+++ end;
+++ end;
+++
+++
+++ procedure taarch64addnode.second_addfloat;
+++ var
+++ op : TAsmOp;
+++ begin
+++ pass_left_right;
+++ if nf_swapped in flags then
+++ swapleftright;
+++
+++ { force fpureg as location, left right doesn't matter
+++ as both will be in a fpureg }
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+++
+++ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+++ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+++
+++ case nodetype of
+++ addn :
+++ begin
+++ op:=A_FADD;
+++ end;
+++ muln :
+++ begin
+++ op:=A_FMUL;
+++ end;
+++ subn :
+++ begin
+++ op:=A_FSUB;
+++ end;
+++ slashn :
+++ begin
+++ op:=A_FDIV;
+++ end;
+++ else
+++ internalerror(200306014);
+++ end;
+++
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+++ location.register,left.location.register,right.location.register));
+++ end;
+++
+++
+++ procedure taarch64addnode.second_cmpfloat;
+++ begin
+++ pass_left_right;
+++ if nf_swapped in flags then
+++ swapleftright;
+++
+++ { force fpureg as location, left right doesn't matter
+++ as both will be in a fpureg }
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+++
+++ location_reset(location,LOC_FLAGS,OS_NO);
+++ location.resflags:=getfpuresflags;
+++
+++ { signalling compare so we can get exceptions }
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCMPE,
+++ left.location.register,right.location.register));
+++ end;
+++
+++
+++ procedure taarch64addnode.second_cmpboolean;
+++ begin
+++ pass_left_right;
+++ force_reg_left_right(true,true);
+++
+++ if right.location.loc=LOC_CONSTANT then
+++ begin
+++ if right.location.value>=0 then
+++ Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMP,left.location.size,left.location.register,right.location.value,NR_XZR,NR_NO,false,false)
+++ else
+++ { avoid overflow if value=low(int64) }
+++{$push}{$r-}{$q-}
+++ Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMN,left.location.size,left.location.register,-right.location.value,NR_XZR,NR_NO,false,false)
+++{$pop}
+++ end
+++ else
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+++
+++ location_reset(location,LOC_FLAGS,OS_NO);
+++ location.resflags:=getresflags(true);
+++ end;
+++
+++
+++ procedure taarch64addnode.second_cmpsmallset;
+++ var
+++ tmpreg : tregister;
+++ op: tasmop;
+++ begin
+++ pass_left_right;
+++
+++ location_reset(location,LOC_FLAGS,OS_NO);
+++
+++ force_reg_left_right(true,true);
+++
+++ if right.location.loc=LOC_CONSTANT then
+++ begin
+++ { when doing a cmp/cmn on 32 bit, we care whether the *lower 32 bit*
+++ is a positive/negative value -> sign extend }
+++ if not(right.location.size in [OS_64,OS_S64]) then
+++ right.location.value:=longint(right.location.value);
+++ if right.location.value>=0 then
+++ op:=A_CMP
+++ else
+++ op:=A_CMN;
+++ end
+++ else
+++ { for DFA }
+++ op:=A_NONE;
+++
+++ case nodetype of
+++ equaln,
+++ unequaln:
+++ begin
+++ if right.location.loc=LOC_CONSTANT then
+++ tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),left.location.register,abs(right.location.value),NR_XZR,NR_NO,false,false)
+++ else
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+++ location.resflags:=getresflags(true);
+++ end;
+++ lten,
+++ gten:
+++ begin
+++ if (not(nf_swapped in flags) and
+++ (nodetype=lten)) or
+++ ((nf_swapped in flags) and
+++ (nodetype=gten)) then
+++ swapleftright;
+++ { we can't handle left as a constant yet }
+++ if left.location.loc=LOC_CONSTANT then
+++ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+++ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
+++ if right.location.loc=LOC_CONSTANT then
+++ begin
+++ hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,right.location.value,left.location.register,tmpreg);
+++ tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),tmpreg,abs(right.location.value),NR_XZR,NR_NO,false,false)
+++ end
+++ else
+++ begin
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
+++ end;
+++ location.resflags:=F_EQ;
+++ end;
+++ else
+++ internalerror(2012042701);
+++ end;
+++ end;
+++
+++
+++ procedure taarch64addnode.second_cmpordinal;
+++ var
+++ unsigned : boolean;
+++ begin
+++ pass_left_right;
+++ force_reg_left_right(true,true);
+++
+++ unsigned:=not(is_signed(left.resultdef)) or
+++ not(is_signed(right.resultdef));
+++
+++ if right.location.loc = LOC_CONSTANT then
+++ begin
+++ if right.location.value>=0 then
+++ Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMP,left.location.size,left.location.register,right.location.value,NR_XZR,NR_NO,false,false)
+++ else
+++{$push}{$r-}{$q-}
+++ Tcgaarch64(cg).handle_reg_imm12_reg(current_asmdata.CurrAsmList,A_CMN,left.location.size,left.location.register,-right.location.value,NR_XZR,NR_NO,false,false)
+++{$pop}
+++ end
+++ else
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+++
+++ location_reset(location,LOC_FLAGS,OS_NO);
+++ location.resflags:=getresflags(unsigned);
+++ end;
+++
+++
+++ procedure taarch64addnode.second_addordinal;
+++ const
+++ multops: array[boolean] of TAsmOp = (A_SMULL,A_UMULL);
+++ var
+++ unsigned: boolean;
+++ begin
+++ { 32x32->64 multiplication }
+++ if (nodetype=muln) and
+++ is_32bit(left.resultdef) and
+++ is_32bit(right.resultdef) and
+++ is_64bit(resultdef) then
+++ begin
+++ unsigned:=not(is_signed(left.resultdef)) or
+++ not(is_signed(right.resultdef));
+++ pass_left_right;
+++ force_reg_left_right(true,true);
+++ { force_reg_left_right can leave right as a LOC_CONSTANT (we can't
+++ say "a constant register is okay, but an ordinal constant isn't) }
+++ if right.location.loc=LOC_CONSTANT then
+++ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+++ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+++ location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+++ current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg_reg(multops[unsigned],location.register,left.location.register,right.location.register));
+++ end
+++ else
+++ inherited second_addordinal;
+++ end;
+++
+++
+++ procedure taarch64addnode.second_add64bit;
+++ begin
+++ second_addordinal;
+++ end;
+++
+++
+++ procedure taarch64addnode.second_cmp64bit;
+++ begin
+++ second_cmpordinal;
+++ end;
+++
+++
+++ function taarch64addnode.use_generic_mul32to64: boolean;
+++ begin
+++ result:=false;
+++ end;
+++
+++
+++begin
+++ caddnode:=taarch64addnode;
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/ncpucnv.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/ncpucnv.pas
++@@ -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.
++Index: fpc/fpcsrc/compiler/aarch64/ncpuinl.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/ncpuinl.pas
++@@ -0,0 +1,184 @@
+++{
+++ Copyright (c) 1998-2002 by Florian Klaempfl
+++
+++ Generates ARM inline nodes
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit ncpuinl;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++ uses
+++ node,ninl,ncginl;
+++
+++ type
+++ taarch64inlinenode = class(tcgInlineNode)
+++ function first_abs_real: tnode; override;
+++ function first_sqr_real: tnode; override;
+++ function first_sqrt_real: tnode; override;
+++ function first_round_real: tnode; override;
+++ function first_trunc_real: tnode; override;
+++ procedure second_abs_real; override;
+++ procedure second_sqr_real; override;
+++ procedure second_sqrt_real; override;
+++ procedure second_abs_long; override;
+++ procedure second_round_real; override;
+++ procedure second_trunc_real; override;
+++ procedure second_get_frame; override;
+++ private
+++ procedure load_fpu_location;
+++ end;
+++
+++
+++implementation
+++
+++ uses
+++ globtype,verbose,globals,
+++ cpuinfo, defutil,symdef,aasmdata,aasmcpu,
+++ cgbase,cgutils,pass_1,pass_2,
+++ cpubase,ncgutil,cgobj,cgcpu, hlcgobj;
+++
+++{*****************************************************************************
+++ taarch64inlinenode
+++*****************************************************************************}
+++
+++ procedure taarch64inlinenode.load_fpu_location;
+++ begin
+++ secondpass(left);
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+++ location_copy(location,left.location);
+++ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+++ location.loc:=LOC_MMREGISTER;
+++ end;
+++
+++
+++ function taarch64inlinenode.first_abs_real : tnode;
+++ begin
+++ expectloc:=LOC_MMREGISTER;
+++ result:=nil;
+++ end;
+++
+++
+++ function taarch64inlinenode.first_sqr_real : tnode;
+++ begin
+++ expectloc:=LOC_MMREGISTER;
+++ result:=nil;
+++ end;
+++
+++
+++ function taarch64inlinenode.first_sqrt_real : tnode;
+++ begin
+++ expectloc:=LOC_MMREGISTER;
+++ result:=nil;
+++ end;
+++
+++
+++ function taarch64inlinenode.first_round_real: tnode;
+++ begin
+++ expectloc:=LOC_MMREGISTER;
+++ result:=nil;
+++ end;
+++
+++
+++ function taarch64inlinenode.first_trunc_real: tnode;
+++ begin
+++ expectloc:=LOC_MMREGISTER;
+++ result:=nil;
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_abs_real;
+++ begin
+++ load_fpu_location;
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABS,location.register,left.location.register));
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_sqr_real;
+++ begin
+++ load_fpu_location;
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FMUL,location.register,left.location.register,left.location.register));
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_sqrt_real;
+++ begin
+++ load_fpu_location;
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT,location.register,left.location.register));
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_abs_long;
+++ var
+++ opsize : tcgsize;
+++ hp : taicpu;
+++ begin
+++ secondpass(left);
+++ opsize:=def_cgsize(left.resultdef);
+++ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+++ location:=left.location;
+++ location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+++
+++ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_NEG,location.register,left.location.register),PF_S));
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_cond(A_CSEL,location.register,location.register,left.location.register,C_GE));
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_round_real;
+++ var
+++ hreg: tregister;
+++ begin
+++ secondpass(left);
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+++ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+++ location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+++ hreg:=cg.getmmregister(current_asmdata.CurrAsmList,left.location.size);
+++ { round as floating point using current rounding mode }
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRINTX,hreg,left.location.register));
+++ { convert to signed integer rounding towards zero (there's no "round to
+++ integer using current rounding mode") }
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCVTZS,location.register,hreg));
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_trunc_real;
+++ begin
+++ secondpass(left);
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+++ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+++ location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+++ { convert to signed integer rounding towards zero }
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCVTZS,location.register,left.location.register));
+++ end;
+++
+++
+++ procedure taarch64inlinenode.second_get_frame;
+++ begin
+++ location_reset(location,LOC_CREGISTER,OS_ADDR);
+++ { this routine is used to get the frame pointer for backtracing
+++ purposes. current_procinfo.framepointer is set to SP because that one
+++ is used to access temps. On most platforms these two frame pointers
+++ are the same, but not on AArch64. }
+++ location.register:=NR_FRAME_POINTER_REG;
+++ end;
+++
+++begin
+++ cinlinenode:=taarch64inlinenode;
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/ncpumat.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/ncpumat.pas
++@@ -0,0 +1,196 @@
+++{
+++ Copyright (c) 1998-2002, 2014 by Florian Klaempfl and Jonas Maebe
+++
+++ Generate AArch64 assembler for math nodes
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit ncpumat;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++ uses
+++ node,nmat,ncgmat;
+++
+++ type
+++ taarch64moddivnode = class(tmoddivnode)
+++ function pass_1: tnode; override;
+++ procedure pass_generate_code;override;
+++ end;
+++
+++ taarch64notnode = class(tcgnotnode)
+++ procedure second_boolean;override;
+++ end;
+++
+++ taarch64unaryminusnode = class(tcgunaryminusnode)
+++ procedure second_float; override;
+++ end;
+++
+++implementation
+++
+++ uses
+++ globtype,systems,constexp,
+++ cutils,verbose,globals,
+++ symconst,symdef,
+++ aasmbase,aasmcpu,aasmtai,aasmdata,
+++ defutil,
+++ cgbase,cgobj,hlcgobj,pass_2,procinfo,
+++ ncon,
+++ cpubase,
+++ ncgutil,cgcpu,cgutils;
+++
+++{*****************************************************************************
+++ taarch64moddivnode
+++*****************************************************************************}
+++
+++ function taarch64moddivnode.pass_1: tnode;
+++ begin
+++ result:=inherited pass_1;
+++ if not assigned(result) then
+++ include(current_procinfo.flags,pi_do_call);
+++ end;
+++
+++
+++ procedure taarch64moddivnode.pass_generate_code;
+++ var
+++ op : tasmop;
+++ tmpreg,
+++ numerator,
+++ divider,
+++ resultreg : tregister;
+++ hl : tasmlabel;
+++ overflowloc: tlocation;
+++ begin
+++ secondpass(left);
+++ secondpass(right);
+++
+++ { set result location }
+++ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+++ location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+++ resultreg:=location.register;
+++
+++ { put numerator in register }
+++ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+++ numerator:=left.location.register;
+++
+++ { load divider in a register }
+++ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+++ divider:=right.location.register;
+++
+++ { start division }
+++ if is_signed(left.resultdef) then
+++ op:=A_SDIV
+++ else
+++ op:=A_UDIV;
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,numerator,divider));
+++
+++ { no divide-by-zero detection available in hardware, emulate (if it's a
+++ constant, this will have been detected earlier already) }
+++ if (right.nodetype<>ordconstn) then
+++ begin
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,
+++ right.location.register,0));
+++
+++ current_asmdata.getjumplabel(hl);
+++ current_asmdata.CurrAsmList.concat(taicpu.op_cond_sym(A_B,C_NE,hl));
+++ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIVBYZERO',false);
+++ cg.a_label(current_asmdata.CurrAsmList,hl);
+++ end;
+++
+++ { in case of overflow checking, also check for low(int64) div (-1)
+++ (no hardware support for this either) }
+++ if (cs_check_overflow in current_settings.localswitches) and
+++ is_signed(left.resultdef) and
+++ ((right.nodetype<>ordconstn) or
+++ (tordconstnode(right).value=-1)) then
+++ begin
+++ { num=ffff... and div=8000... <=>
+++ num xor not(div xor 8000...) = 0
+++ (and we have the "eon" operation, which performs "xor not(...)" }
+++ tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
+++ hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,left.resultdef,low(int64),left.location.register,tmpreg);
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_EON,
+++ tmpreg,left.location.register,tmpreg));
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,tmpreg,0));
+++ { now the zero/equal flag is set in case we divided low(int64) by
+++ (-1) }
+++ location_reset(overflowloc,LOC_FLAGS,OS_NO);
+++ overflowloc.resflags:=F_EQ;
+++ cg.g_overflowcheck_loc(current_asmdata.CurrAsmList,location,resultdef,overflowloc);
+++ end;
+++
+++ { in case of modulo, multiply result again by the divider and subtract
+++ from the numerator }
+++ if nodetype=modn then
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MSUB,resultreg,
+++ resultreg,divider,numerator));
+++ end;
+++
+++
+++{*****************************************************************************
+++ taarch64notnode
+++*****************************************************************************}
+++
+++ procedure taarch64notnode.second_boolean;
+++ begin
+++ if not handle_locjump then
+++ begin
+++ secondpass(left);
+++ case left.location.loc of
+++ LOC_FLAGS :
+++ begin
+++ location_copy(location,left.location);
+++ inverse_flags(location.resflags);
+++ end;
+++ LOC_REGISTER, LOC_CREGISTER,
+++ LOC_REFERENCE, LOC_CREFERENCE,
+++ LOC_SUBSETREG, LOC_CSUBSETREG,
+++ LOC_SUBSETREF, LOC_CSUBSETREF:
+++ begin
+++ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,
+++ left.location.register,0));
+++ location_reset(location,LOC_FLAGS,OS_NO);
+++ location.resflags:=F_EQ;
+++ end;
+++ else
+++ internalerror(2003042401);
+++ end;
+++ end;
+++ end;
+++
+++
+++{*****************************************************************************
+++ taarch64unaryminusnode
+++*****************************************************************************}
+++
+++ procedure taarch64unaryminusnode.second_float;
+++ begin
+++ secondpass(left);
+++ hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+++ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+++ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FNEG,location.register,left.location.register));
+++ end;
+++
+++begin
+++ cmoddivnode:=taarch64moddivnode;
+++ cnotnode:=taarch64notnode;
+++ cunaryminusnode:=taarch64unaryminusnode;
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/ncpumem.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/ncpumem.pas
++@@ -0,0 +1,142 @@
+++{
+++ Copyright (c) 2014 by Jonas Maebe
+++
+++ Generate AArch64 code for in memory related nodes
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit ncpumem;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++ uses
+++ globtype,
+++ cgbase,
+++ symtype,
+++ node,nmem,ncgmem;
+++
+++ type
+++ taarch64loadparentfpnode = class(tcgloadparentfpnode)
+++ procedure pass_generate_code; override;
+++ end;
+++
+++ taarch64vecnode = class(tcgvecnode)
+++ protected
+++ function valid_index_size(size: tcgsize): boolean; override;
+++ public
+++ procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint); override;
+++ end;
+++
+++implementation
+++
+++ uses
+++ cutils,verbose,
+++ defutil,
+++ aasmdata,cpubase,
+++ cgutils,
+++ cgobj;
+++
+++ { taarch64loadparentfpnode }
+++
+++ procedure taarch64loadparentfpnode.pass_generate_code;
+++ begin
+++ inherited pass_generate_code;
+++ { see the comments in tcgaarch64.g_proc_entry }
+++ if (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
+++ (location.register=NR_STACK_POINTER_REG) then
+++ if (kind=lpf_forpara) then
+++ location.register:=NR_FRAME_POINTER_REG
+++ else
+++ begin
+++ { load stack pointer in a different register, as many instructions
+++ cannot directly work with the stack pointer. The register
+++ allocator can merge them if possible }
+++ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+++ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_STACK_POINTER_REG,location.register);
+++ location.loc:=LOC_REGISTER;
+++ end;
+++ end;
+++
+++
+++ { taarch64vecnode }
+++
+++ function taarch64vecnode.valid_index_size(size: tcgsize): boolean;
+++ begin
+++ { all sizes are ok if we handle the "reference reg mul", because
+++ a) we use a 64 bit register for 64 bit values, and a 32 bit one (that
+++ we can sign/zero-extend inside the reference) for smaller values
+++ b) for values < 32 bit, the entire 32 bit register always contains the
+++ sign/zero-extended version of the value }
+++ result:=
+++ not is_packed_array(left.resultdef) and
+++ (get_mul_size in [1,2,4,8,16]);
+++ end;
+++
+++
+++ procedure taarch64vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
+++ var
+++ base: tregister;
+++ oldoffset: asizeint;
+++ shift: byte;
+++ begin
+++ { we can only scale the index by shl 0..4 }
+++ if not(l in [1,2,4,8,16]) then
+++ begin
+++ inherited;
+++ exit;
+++ end;
+++ { we need a base set and an index available }
+++ if (location.reference.base=NR_NO) or
+++ (location.reference.index<>NR_NO) then
+++ begin
+++ { don't integrate the offset yet, make_simple_ref() may be able to
+++ handle it more efficiently later (unless an offset is all we have
+++ -> optimization for someone that wants to add support for AArch64
+++ embedded targets) }
+++ oldoffset:=location.reference.offset;
+++ location.reference.offset:=0;
+++ base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+++ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,base);
+++ reference_reset_base(location.reference,base,oldoffset,location.reference.alignment);
+++ end;
+++ shift:=BsfDWord(l);
+++ location.reference.index:=maybe_const_reg;
+++ { sign/zero-extend? }
+++ if regsize.size=8 then
+++ if shift<>0 then
+++ location.reference.shiftmode:=SM_LSL
+++ else
+++ location.reference.shiftmode:=SM_NONE
+++ else if is_signed(regsize) then
+++ location.reference.shiftmode:=SM_SXTW
+++ else if shift<>0 then
+++ location.reference.shiftmode:=SM_UXTW
+++ else
+++ { the upper 32 bits are always already zero-extended -> just use 64 bit
+++ register }
+++ location.reference.index:=cg.makeregsize(current_asmdata.CurrAsmList,location.reference.index,OS_64);
+++ location.reference.shiftimm:=shift;
+++ location.reference.alignment:=newalignment(location.reference.alignment,l);
+++ end;
+++
+++
+++begin
+++ cloadparentfpnode:=taarch64loadparentfpnode;
+++ cvecnode:=taarch64vecnode;
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/ncpuset.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/ncpuset.pas
++@@ -0,0 +1,175 @@
+++{
+++ Copyright (c) 2015 by Jonas Maebe
+++
+++ Generate AArch64 assembler for in set/case nodes
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit ncpuset;
+++
+++{$i fpcdefs.inc}
+++
+++interface
+++
+++ uses
+++ node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,aasmdata,globtype;
+++
+++ type
+++ taarch64casenode = class(tcgcasenode)
+++ protected
+++ procedure optimizevalues(var max_linear_list: aint; var max_dist: aword);override;
+++ function has_jumptable: boolean;override;
+++ procedure genjumptable(hp: pcaselabel ;min_, max_: aint);override;
+++ end;
+++
+++
+++implementation
+++
+++ uses
+++ systems,
+++ verbose,globals,constexp,
+++ symconst,symdef,defutil,
+++ paramgr,
+++ cpuinfo,
+++ pass_2,cgcpu,
+++ ncon,
+++ tgobj,ncgutil,regvars,rgobj,aasmcpu,
+++ procinfo,
+++ cgutils;
+++
+++{*****************************************************************************
+++ TCGCASENODE
+++*****************************************************************************}
+++
+++
+++ procedure taarch64casenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
+++ begin
+++ max_linear_list:=10;
+++ end;
+++
+++
+++ function taarch64casenode.has_jumptable: boolean;
+++ begin
+++ has_jumptable:=true;
+++ end;
+++
+++
+++ procedure taarch64casenode.genjumptable(hp: pcaselabel; min_, max_: aint);
+++ var
+++ last: TConstExprInt;
+++ tablelabel: TAsmLabel;
+++ basereg,indexreg,jumpreg: TRegister;
+++ href: TReference;
+++ opcgsize: tcgsize;
+++ sectype: TAsmSectiontype;
+++ jtitemconsttype: taiconst_type;
+++
+++ procedure genitem(list:TAsmList;t : pcaselabel);
+++ var
+++ i : aint;
+++ begin
+++ if assigned(t^.less) then
+++ genitem(list,t^.less);
+++ { fill possible hole }
+++ i:=last.svalue+1;
+++ while i<=t^._low.svalue-1 do
+++ begin
+++ list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,elselabel));
+++ inc(i);
+++ end;
+++ i:=t^._low.svalue;
+++ while i<=t^._high.svalue do
+++ begin
+++ list.concat(Tai_const.Create_rel_sym(jtitemconsttype,tablelabel,blocklabel(t^.blockid)));
+++ inc(i);
+++ end;
+++ last:=t^._high;
+++ if assigned(t^.greater) then
+++ genitem(list,t^.greater);
+++ end;
+++
+++ begin
+++ if not(target_info.system in systems_darwin) then
+++ jtitemconsttype:=aitconst_32bit
+++ else
+++ { see https://gmplib.org/list-archives/gmp-bugs/2012-December/002836.html }
+++ jtitemconsttype:=aitconst_darwin_dwarf_delta32;
+++
+++ last:=min_;
+++ opcgsize:=def_cgsize(opsize);
+++ { a <= x <= b <-> unsigned(x-a) <= (b-a) }
+++ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opcgsize,aint(min_),hregister);
+++ if not(jumptable_no_range) then
+++ begin
+++ { case expr greater than max_ => goto elselabel }
+++ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opcgsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
+++ min_:=0;
+++ end;
+++ { local label in order to avoid using GOT }
+++ current_asmdata.getlabel(tablelabel,alt_data);
+++ indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_ADDR);
+++ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opcgsize,OS_ADDR,hregister,indexreg);
+++ { load table address }
+++ reference_reset_symbol(href,tablelabel,0,4);
+++ basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+++ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
+++ { load table slot, 32-bit sign extended }
+++ reference_reset_base(href,basereg,0,4);
+++ href.index:=indexreg;
+++ href.shiftmode:=SM_LSL;
+++ href.shiftimm:=2;
+++ jumpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+++ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,jumpreg);
+++ { add table address }
+++ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,basereg,jumpreg);
+++ { and finally jump }
+++ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_BR,jumpreg));
+++ { generate jump table }
+++ if not(target_info.system in systems_darwin) then
+++ sectype:=sec_rodata
+++ else
+++ begin
+++ { on Mac OS X, dead code stripping ("smart linking") happens based on
+++ global symbols: every global/static symbol (symbols that do not
+++ start with "L") marks the start of a new "subsection" that is
+++ discarded by the linker if there are no references to this symbol.
+++ This means that if you put the jump table in the rodata section, it
+++ will become part of the block of data associated with the previous
+++ non-L-label in the rodata section and stay or be thrown away
+++ depending on whether that block of data is referenced. Therefore,
+++ jump tables must be added in the code section and since aktlocaldata
+++ is inserted right after the routine, it will become part of the
+++ same subsection that contains the routine's code }
+++ sectype:=sec_code;
+++ end;
+++ new_section(current_procinfo.aktlocaldata,sectype,current_procinfo.procdef.mangledname,4);
+++ if target_info.system in systems_darwin then
+++ begin
+++ { additionally, these tables are now marked via ".data_region jt32"
+++ and ".end_data_region" }
+++ current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_data_region,'jt32'));
+++ end;
+++ current_procinfo.aktlocaldata.concat(Tai_label.Create(tablelabel));
+++ genitem(current_procinfo.aktlocaldata,hp);
+++ if target_info.system in systems_darwin then
+++ current_procinfo.aktlocaldata.concat(tai_directive.Create(asd_end_data_region,''));
+++ end;
+++
+++
+++begin
+++ ccasenode:=taarch64casenode;
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/ra64con.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64con.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64con.inc
++@@ -64,6 +64,8 @@ NR_W30 = tregister($0104001E);
++ NR_X30 = tregister($0105001E);
++ NR_WZR = tregister($0104001F);
++ NR_XZR = tregister($0105001F);
+++NR_WSP = tregister($01040020);
+++NR_SP = tregister($01050020);
++ NR_B0 = tregister($04010000);
++ NR_H0 = tregister($04030000);
++ NR_S0 = tregister($04090000);
++@@ -225,3 +227,6 @@ NR_S31 = tregister($0409001F);
++ NR_D31 = tregister($040a001F);
++ NR_Q31 = tregister($0405001F);
++ NR_NZCV = tregister($05000000);
+++NR_FPCR = tregister($05000001);
+++NR_FPSR = tregister($05000002);
+++NR_TPIDR_EL0 = tregister($05000003);
++Index: fpc/fpcsrc/compiler/aarch64/ra64dwa.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64dwa.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64dwa.inc
++@@ -64,164 +64,169 @@
++ 30,
++ 31,
++ 31,
+++31,
+++31,
+++64,
+++64,
+++64,
+++64,
+++64,
+++65,
+++65,
+++65,
+++65,
+++65,
+++66,
+++66,
+++66,
+++66,
+++66,
+++67,
+++67,
+++67,
+++67,
+++67,
+++68,
+++68,
+++68,
+++68,
+++68,
+++69,
+++69,
+++69,
+++69,
+++69,
+++70,
+++70,
+++70,
+++70,
+++70,
+++71,
+++71,
+++71,
+++71,
+++71,
+++72,
+++72,
+++72,
+++72,
+++72,
+++73,
+++73,
+++73,
+++73,
+++73,
+++74,
+++74,
+++74,
+++74,
+++74,
+++75,
+++75,
+++75,
+++75,
+++75,
+++76,
+++76,
+++76,
+++76,
+++76,
+++77,
+++77,
+++77,
+++77,
+++77,
+++78,
+++78,
+++78,
+++78,
+++78,
+++79,
+++79,
+++79,
+++79,
+++79,
+++80,
+++80,
+++80,
+++80,
+++80,
+++81,
+++81,
+++81,
+++81,
+++81,
+++82,
+++82,
+++82,
+++82,
+++82,
+++83,
+++83,
+++83,
+++83,
+++83,
+++84,
+++84,
+++84,
+++84,
+++84,
+++85,
+++85,
+++85,
+++85,
+++85,
+++86,
+++86,
+++86,
+++86,
+++86,
+++87,
+++87,
+++87,
+++87,
+++87,
+++88,
+++88,
+++88,
+++88,
+++88,
+++89,
+++89,
+++89,
+++89,
+++89,
+++90,
+++90,
+++90,
+++90,
+++90,
+++91,
+++91,
+++91,
+++91,
+++91,
+++92,
+++92,
+++92,
+++92,
+++92,
+++93,
+++93,
+++93,
+++93,
+++93,
+++94,
+++94,
+++94,
+++94,
+++94,
+++95,
+++95,
+++95,
+++95,
+++95,
++ 0,
++ 0,
++ 0,
++-0,
++-0,
++-1,
++-1,
++-1,
++-1,
++-1,
++-2,
++-2,
++-2,
++-2,
++-2,
++-3,
++-3,
++-3,
++-3,
++-3,
++-4,
++-4,
++-4,
++-4,
++-4,
++-5,
++-5,
++-5,
++-5,
++-5,
++-6,
++-6,
++-6,
++-6,
++-6,
++-7,
++-7,
++-7,
++-7,
++-7,
++-8,
++-8,
++-8,
++-8,
++-8,
++-9,
++-9,
++-9,
++-9,
++-9,
++-10,
++-10,
++-10,
++-10,
++-10,
++-11,
++-11,
++-11,
++-11,
++-11,
++-12,
++-12,
++-12,
++-12,
++-12,
++-13,
++-13,
++-13,
++-13,
++-13,
++-14,
++-14,
++-14,
++-14,
++-14,
++-15,
++-15,
++-15,
++-15,
++-15,
++-16,
++-16,
++-16,
++-16,
++-16,
++-17,
++-17,
++-17,
++-17,
++-17,
++-18,
++-18,
++-18,
++-18,
++-18,
++-19,
++-19,
++-19,
++-19,
++-19,
++-20,
++-20,
++-20,
++-20,
++-20,
++-21,
++-21,
++-21,
++-21,
++-21,
++-22,
++-22,
++-22,
++-22,
++-22,
++-23,
++-23,
++-23,
++-23,
++-23,
++-24,
++-24,
++-24,
++-24,
++-24,
++-25,
++-25,
++-25,
++-25,
++-25,
++-26,
++-26,
++-26,
++-26,
++-26,
++-27,
++-27,
++-27,
++-27,
++-27,
++-28,
++-28,
++-28,
++-28,
++-28,
++-29,
++-29,
++-29,
++-29,
++-29,
++-30,
++-30,
++-30,
++-30,
++-30,
++-31,
++-31,
++-31,
++-31,
++-31,
++ 0
++Index: fpc/fpcsrc/compiler/aarch64/ra64nor.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64nor.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64nor.inc
++@@ -1,2 +1,2 @@
++ { don't edit, this file is generated from a64reg.dat }
++-226
+++231
++Index: fpc/fpcsrc/compiler/aarch64/ra64num.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64num.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64num.inc
++@@ -64,6 +64,8 @@ tregister($0104001E),
++ tregister($0105001E),
++ tregister($0104001F),
++ tregister($0105001F),
+++tregister($01040020),
+++tregister($01050020),
++ tregister($04010000),
++ tregister($04030000),
++ tregister($04090000),
++@@ -224,4 +226,7 @@ tregister($0403001F),
++ tregister($0409001F),
++ tregister($040a001F),
++ tregister($0405001F),
++-tregister($05000000)
+++tregister($05000000),
+++tregister($05000001),
+++tregister($05000002),
+++tregister($05000003)
++Index: fpc/fpcsrc/compiler/aarch64/ra64rni.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64rni.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64rni.inc
++@@ -32,6 +32,7 @@
++ 59,
++ 61,
++ 63,
+++65,
++ 2,
++ 4,
++ 6,
++@@ -64,102 +65,7 @@
++ 60,
++ 62,
++ 64,
++-65,
++-70,
++-75,
++-80,
++-85,
++-90,
++-95,
++-100,
++-105,
++-110,
++-115,
++-120,
++-125,
++-130,
++-135,
++-140,
++-145,
++-150,
++-155,
++-160,
++-165,
++-170,
++-175,
++-180,
++-185,
++-190,
++-195,
++-200,
++-205,
++-210,
++-215,
++-220,
++ 66,
++-71,
++-76,
++-81,
++-86,
++-91,
++-96,
++-101,
++-106,
++-111,
++-116,
++-121,
++-126,
++-131,
++-136,
++-141,
++-146,
++-151,
++-156,
++-161,
++-166,
++-171,
++-176,
++-181,
++-186,
++-191,
++-196,
++-201,
++-206,
++-211,
++-216,
++-221,
++-69,
++-74,
++-79,
++-84,
++-89,
++-94,
++-99,
++-104,
++-109,
++-114,
++-119,
++-124,
++-129,
++-134,
++-139,
++-144,
++-149,
++-154,
++-159,
++-164,
++-169,
++-174,
++-179,
++-184,
++-189,
++-194,
++-199,
++-204,
++-209,
++-214,
++-219,
++-224,
++ 67,
++ 72,
++ 77,
++@@ -224,4 +130,103 @@
++ 213,
++ 218,
++ 223,
++-225
+++71,
+++76,
+++81,
+++86,
+++91,
+++96,
+++101,
+++106,
+++111,
+++116,
+++121,
+++126,
+++131,
+++136,
+++141,
+++146,
+++151,
+++156,
+++161,
+++166,
+++171,
+++176,
+++181,
+++186,
+++191,
+++196,
+++201,
+++206,
+++211,
+++216,
+++221,
+++226,
+++69,
+++74,
+++79,
+++84,
+++89,
+++94,
+++99,
+++104,
+++109,
+++114,
+++119,
+++124,
+++129,
+++134,
+++139,
+++144,
+++149,
+++154,
+++159,
+++164,
+++169,
+++174,
+++179,
+++184,
+++189,
+++194,
+++199,
+++204,
+++209,
+++214,
+++219,
+++224,
+++70,
+++75,
+++80,
+++85,
+++90,
+++95,
+++100,
+++105,
+++110,
+++115,
+++120,
+++125,
+++130,
+++135,
+++140,
+++145,
+++150,
+++155,
+++160,
+++165,
+++170,
+++175,
+++180,
+++185,
+++190,
+++195,
+++200,
+++205,
+++210,
+++215,
+++220,
+++225,
+++227,
+++228,
+++229,
+++230
++Index: fpc/fpcsrc/compiler/aarch64/ra64sri.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64sri.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64sri.inc
++@@ -1,8 +1,39 @@
++ { don't edit, this file is generated from a64reg.dat }
++ 0,
++-65,
+++67,
+++72,
+++117,
+++122,
+++127,
+++132,
+++137,
+++142,
+++147,
+++152,
+++157,
+++162,
+++77,
+++167,
+++172,
+++177,
+++182,
+++187,
+++192,
+++197,
+++202,
+++207,
+++212,
+++82,
+++217,
+++222,
+++87,
+++92,
+++97,
+++102,
+++107,
+++112,
++ 70,
++-115,
+++75,
++ 120,
++ 125,
++ 130,
++@@ -12,8 +43,8 @@
++ 150,
++ 155,
++ 160,
++-75,
++ 165,
+++80,
++ 170,
++ 175,
++ 180,
++@@ -23,15 +54,18 @@
++ 200,
++ 205,
++ 210,
++-80,
++ 215,
++-220,
++ 85,
+++220,
+++225,
++ 90,
++ 95,
++ 100,
++ 105,
++ 110,
+++115,
+++228,
+++229,
++ 68,
++ 73,
++ 118,
++@@ -64,9 +98,9 @@
++ 103,
++ 108,
++ 113,
++-66,
+++227,
++ 71,
++-116,
+++76,
++ 121,
++ 126,
++ 131,
++@@ -76,8 +110,8 @@
++ 151,
++ 156,
++ 161,
++-76,
++ 166,
+++81,
++ 171,
++ 176,
++ 181,
++@@ -87,16 +121,16 @@
++ 201,
++ 206,
++ 211,
++-81,
++ 216,
++-221,
++ 86,
+++221,
+++226,
++ 91,
++ 96,
++ 101,
++ 106,
++ 111,
++-225,
+++116,
++ 69,
++ 74,
++ 119,
++@@ -129,38 +163,8 @@
++ 104,
++ 109,
++ 114,
++-67,
++-72,
++-117,
++-122,
++-127,
++-132,
++-137,
++-142,
++-147,
++-152,
++-157,
++-162,
++-77,
++-167,
++-172,
++-177,
++-182,
++-187,
++-192,
++-197,
++-202,
++-207,
++-212,
++-82,
++-217,
++-222,
++-87,
++-92,
++-97,
++-102,
++-107,
++-112,
+++66,
+++230,
++ 1,
++ 3,
++ 21,
++@@ -192,6 +196,7 @@
++ 15,
++ 17,
++ 19,
+++65,
++ 63,
++ 2,
++ 4,
++Index: fpc/fpcsrc/compiler/aarch64/ra64sta.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64sta.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64sta.inc
++@@ -64,164 +64,169 @@
++ 30,
++ 31,
++ 31,
+++31,
+++31,
+++64,
+++64,
+++64,
+++64,
+++64,
+++65,
+++65,
+++65,
+++65,
+++65,
+++66,
+++66,
+++66,
+++66,
+++66,
+++67,
+++67,
+++67,
+++67,
+++67,
+++68,
+++68,
+++68,
+++68,
+++68,
+++69,
+++69,
+++69,
+++69,
+++69,
+++70,
+++70,
+++70,
+++70,
+++70,
+++71,
+++71,
+++71,
+++71,
+++71,
+++72,
+++72,
+++72,
+++72,
+++72,
+++73,
+++73,
+++73,
+++73,
+++73,
+++74,
+++74,
+++74,
+++74,
+++74,
+++75,
+++75,
+++75,
+++75,
+++75,
+++76,
+++76,
+++76,
+++76,
+++76,
+++77,
+++77,
+++77,
+++77,
+++77,
+++78,
+++78,
+++78,
+++78,
+++78,
+++79,
+++79,
+++79,
+++79,
+++79,
+++80,
+++80,
+++80,
+++80,
+++80,
+++81,
+++81,
+++81,
+++81,
+++81,
+++82,
+++82,
+++82,
+++82,
+++82,
+++83,
+++83,
+++83,
+++83,
+++83,
+++84,
+++84,
+++84,
+++84,
+++84,
+++85,
+++85,
+++85,
+++85,
+++85,
+++86,
+++86,
+++86,
+++86,
+++86,
+++87,
+++87,
+++87,
+++87,
+++87,
+++88,
+++88,
+++88,
+++88,
+++88,
+++89,
+++89,
+++89,
+++89,
+++89,
+++90,
+++90,
+++90,
+++90,
+++90,
+++91,
+++91,
+++91,
+++91,
+++91,
+++92,
+++92,
+++92,
+++92,
+++92,
+++93,
+++93,
+++93,
+++93,
+++93,
+++94,
+++94,
+++94,
+++94,
+++94,
+++95,
+++95,
+++95,
+++95,
+++95,
++ 0,
++ 0,
++ 0,
++-0,
++-0,
++-1,
++-1,
++-1,
++-1,
++-1,
++-2,
++-2,
++-2,
++-2,
++-2,
++-3,
++-3,
++-3,
++-3,
++-3,
++-4,
++-4,
++-4,
++-4,
++-4,
++-5,
++-5,
++-5,
++-5,
++-5,
++-6,
++-6,
++-6,
++-6,
++-6,
++-7,
++-7,
++-7,
++-7,
++-7,
++-8,
++-8,
++-8,
++-8,
++-8,
++-9,
++-9,
++-9,
++-9,
++-9,
++-10,
++-10,
++-10,
++-10,
++-10,
++-11,
++-11,
++-11,
++-11,
++-11,
++-12,
++-12,
++-12,
++-12,
++-12,
++-13,
++-13,
++-13,
++-13,
++-13,
++-14,
++-14,
++-14,
++-14,
++-14,
++-15,
++-15,
++-15,
++-15,
++-15,
++-16,
++-16,
++-16,
++-16,
++-16,
++-17,
++-17,
++-17,
++-17,
++-17,
++-18,
++-18,
++-18,
++-18,
++-18,
++-19,
++-19,
++-19,
++-19,
++-19,
++-20,
++-20,
++-20,
++-20,
++-20,
++-21,
++-21,
++-21,
++-21,
++-21,
++-22,
++-22,
++-22,
++-22,
++-22,
++-23,
++-23,
++-23,
++-23,
++-23,
++-24,
++-24,
++-24,
++-24,
++-24,
++-25,
++-25,
++-25,
++-25,
++-25,
++-26,
++-26,
++-26,
++-26,
++-26,
++-27,
++-27,
++-27,
++-27,
++-27,
++-28,
++-28,
++-28,
++-28,
++-28,
++-29,
++-29,
++-29,
++-29,
++-29,
++-30,
++-30,
++-30,
++-30,
++-30,
++-31,
++-31,
++-31,
++-31,
++-31,
++ 0
++Index: fpc/fpcsrc/compiler/aarch64/ra64std.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64std.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64std.inc
++@@ -64,6 +64,8 @@
++ 'x30',
++ 'wzr',
++ 'xzr',
+++'wsp',
+++'sp',
++ 'b0',
++ 'h0',
++ 's0',
++@@ -224,4 +226,7 @@
++ 's31',
++ 'd31',
++ 'q31',
++-'nzcv'
+++'nzcv',
+++'fpcr',
+++'fpsr',
+++'tpidr_el0'
++Index: fpc/fpcsrc/compiler/aarch64/ra64sup.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aarch64/ra64sup.inc
+++++ fpc/fpcsrc/compiler/aarch64/ra64sup.inc
++@@ -64,6 +64,8 @@ RS_W30 = $1E;
++ RS_X30 = $1E;
++ RS_WZR = $1F;
++ RS_XZR = $1F;
+++RS_WSP = $20;
+++RS_SP = $20;
++ RS_B0 = $00;
++ RS_H0 = $00;
++ RS_S0 = $00;
++@@ -225,3 +227,6 @@ RS_S31 = $1F;
++ RS_D31 = $1F;
++ RS_Q31 = $1F;
++ RS_NZCV = $00;
+++RS_FPCR = $01;
+++RS_FPSR = $02;
+++RS_TPIDR_EL0 = $03;
++Index: fpc/fpcsrc/compiler/aarch64/racpu.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/racpu.pas
++@@ -0,0 +1,88 @@
+++{
+++ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+++ Copyright (c) 2014 by Jonas Maebe
+++
+++ Handles the common AArch64 assembler reader routines
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++unit racpu;
+++
+++{$i fpcdefs.inc}
+++
+++ interface
+++
+++ uses
+++ cgbase,
+++ cpubase,
+++ aasmtai,aasmdata,
+++ rautils;
+++
+++ type
+++ TAArch64Operand=class(TOperand)
+++ end;
+++
+++ TAArch64Instruction=class(TInstruction)
+++ oppostfix : toppostfix;
+++ function ConcatInstruction(p:TAsmList) : tai;override;
+++ function Is64bit: boolean;
+++ function cgsize: tcgsize;
+++ end;
+++
+++ implementation
+++
+++ uses
+++ verbose,
+++ aasmcpu;
+++
+++ function TAArch64Instruction.ConcatInstruction(p:TAsmList) : tai;
+++ begin
+++ result:=inherited ConcatInstruction(p);
+++ taicpu(result).oppostfix:=oppostfix;
+++ end;
+++
+++
+++ function TAArch64Instruction.Is64bit: boolean;
+++ begin
+++ result:=
+++ (operands[1].opr.typ=OPR_REGISTER) and
+++ (getsubreg(operands[1].opr.reg)=R_SUBQ);
+++ end;
+++
+++ function TAArch64Instruction.cgsize: tcgsize;
+++ begin
+++ if ops<1 then
+++ internalerror(2014122001);
+++ if operands[1].opr.typ<>OPR_REGISTER then
+++ internalerror(2014122002);
+++ result:=reg_cgsize(operands[1].opr.reg);
+++ { a 32 bit integer register could actually be 16 or 8 bit }
+++ if result=OS_32 then
+++ case oppostfix of
+++ PF_B:
+++ result:=OS_8;
+++ PF_SB:
+++ result:=OS_S8;
+++ PF_H:
+++ result:=OS_16;
+++ PF_SH:
+++ result:=OS_S16;
+++ end;
+++ end;
+++
+++
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/racpugas.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/racpugas.pas
++@@ -0,0 +1,1053 @@
+++{
+++ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+++ Copyright (c) 2014 by Jonas Maebe
+++
+++ Does the parsing for the AArch64 GNU AS styled inline assembler.
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************
+++}
+++Unit racpugas;
+++
+++{$i fpcdefs.inc}
+++
+++ Interface
+++
+++ uses
+++ raatt,racpu,
+++ cpubase;
+++
+++ type
+++ taarch64attreader = class(tattreader)
+++ actoppostfix : TOpPostfix;
+++ function is_asmopcode(const s: string):boolean;override;
+++ function is_register(const s:string):boolean;override;
+++ procedure handleopcode;override;
+++ procedure BuildReference(oper: taarch64operand; is64bit: boolean);
+++ procedure BuildOperand(oper: taarch64operand; is64bit: boolean);
+++ function TryBuildShifterOp(instr: taarch64instruction; opnr: longint) : boolean;
+++ procedure BuildOpCode(instr: taarch64instruction);
+++ procedure ReadSym(oper: taarch64operand; is64bit: boolean);
+++ procedure ConvertCalljmp(instr: taarch64instruction);
+++ function ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
+++ end;
+++
+++
+++ Implementation
+++
+++ uses
+++ { helpers }
+++ cutils,
+++ { global }
+++ globtype,verbose,
+++ systems,aasmbase,aasmtai,aasmdata,aasmcpu,
+++ { symtable }
+++ symconst,symsym,
+++ procinfo,
+++ rabase,rautils,
+++ cgbase,cgutils;
+++
+++
+++ function taarch64attreader.is_register(const s:string):boolean;
+++ type
+++ treg2str = record
+++ name : string[3];
+++ reg : tregister;
+++ end;
+++
+++ const
+++ extraregs : array[0..3] of treg2str = (
+++ (name: 'FP' ; reg: NR_FP),
+++ (name: 'LR' ; reg: NR_LR),
+++ (name: 'IP0'; reg: NR_IP0),
+++ (name: 'IP1'; reg: NR_IP1));
+++
+++ var
+++ i : longint;
+++
+++ begin
+++ result:=inherited is_register(s);
+++ { reg found?
+++ possible aliases are always 2 or 3 chars
+++ }
+++ if result or not(length(s) in [2,3]) then
+++ exit;
+++ for i:=low(extraregs) to high(extraregs) do
+++ begin
+++ if s=extraregs[i].name then
+++ begin
+++ actasmregister:=extraregs[i].reg;
+++ result:=true;
+++ actasmtoken:=AS_REGISTER;
+++ exit;
+++ end;
+++ end;
+++ end;
+++
+++
+++ procedure taarch64attreader.ReadSym(oper: taarch64operand; is64bit: boolean);
+++ var
+++ tempstr, mangledname : string;
+++ typesize,l,k: aint;
+++ begin
+++ tempstr:=actasmpattern;
+++ Consume(AS_ID);
+++ { typecasting? }
+++ if (actasmtoken=AS_LPAREN) and
+++ SearchType(tempstr,typesize) then
+++ begin
+++ oper.hastype:=true;
+++ Consume(AS_LPAREN);
+++ BuildOperand(oper,is64bit);
+++ Consume(AS_RPAREN);
+++ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+++ oper.SetSize(typesize,true);
+++ end
+++ else
+++ if not oper.SetupVar(tempstr,false) then
+++ Message1(sym_e_unknown_id,tempstr);
+++ { record.field ? }
+++ if actasmtoken=AS_DOT then
+++ begin
+++ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+++ if (mangledname<>'') then
+++ Message(asmr_e_invalid_reference_syntax);
+++ inc(oper.opr.ref.offset,l);
+++ end;
+++ end;
+++
+++
+++ Procedure taarch64attreader.BuildReference(oper: taarch64operand; is64bit: boolean);
+++
+++ procedure do_error;
+++ begin
+++ Message(asmr_e_invalid_reference_syntax);
+++ RecoverConsume(false);
+++ end;
+++
+++
+++ procedure test_end(require_rbracket : boolean);
+++ begin
+++ if require_rbracket then begin
+++ if not(actasmtoken=AS_RBRACKET) then
+++ begin
+++ do_error;
+++ exit;
+++ end
+++ else
+++ Consume(AS_RBRACKET);
+++ if (actasmtoken=AS_NOT) then
+++ begin
+++ oper.opr.ref.addressmode:=AM_PREINDEXED;
+++ Consume(AS_NOT);
+++ end;
+++ end;
+++ if not(actasmtoken in [AS_SEPARATOR,AS_end]) then
+++ do_error
+++ else
+++ begin
+++{$IFDEF debugasmreader}
+++ writeln('TEST_end_FINAL_OK. Created the following ref:');
+++ writeln('oper.opr.ref.shiftimm=',oper.opr.ref.shiftimm);
+++ writeln('oper.opr.ref.shiftmode=',ord(oper.opr.ref.shiftmode));
+++ writeln('oper.opr.ref.index=',ord(oper.opr.ref.index));
+++ writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
+++ writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
+++ writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
+++ writeln;
+++{$endIF debugasmreader}
+++ end;
+++ end;
+++
+++
+++ function is_shifter_ref_operation(var a : tshiftmode) : boolean;
+++ begin
+++ a:=SM_NONE;
+++ if (actasmpattern='LSL') then
+++ a:=SM_LSL
+++ else if (actasmpattern='UXTW') then
+++ a:=SM_UXTW
+++ else if (actasmpattern='SXTW') then
+++ a:=SM_SXTW
+++ else if (actasmpattern='SXTX') then
+++ a:=SM_SXTX;
+++ is_shifter_ref_operation:=not(a=SM_NONE);
+++ end;
+++
+++
+++ procedure read_index_shift(require_rbracket : boolean);
+++ var
+++ shift: aint;
+++ begin
+++ case actasmtoken of
+++ AS_COMMA :
+++ begin
+++ Consume(AS_COMMA);
+++ if not(actasmtoken=AS_ID) then
+++ do_error;
+++ if is_shifter_ref_operation(oper.opr.ref.shiftmode) then
+++ begin
+++ Consume(actasmtoken);
+++ if actasmtoken=AS_HASH then
+++ begin
+++ Consume(AS_HASH);
+++ shift:=BuildConstExpression(false,true);
+++ if not(shift in [0,2+ord(is64bit)]) then
+++ do_error;
+++ oper.opr.ref.shiftimm:=shift;
+++ test_end(require_rbracket);
+++ end;
+++ end
+++ else
+++ begin
+++ do_error;
+++ exit;
+++ end;
+++ end;
+++ AS_RBRACKET :
+++ if require_rbracket then
+++ test_end(require_rbracket)
+++ else
+++ begin
+++ do_error;
+++ exit;
+++ end;
+++ AS_SEPARATOR,AS_END :
+++ if not require_rbracket then
+++ test_end(false)
+++ else
+++ do_error;
+++ else
+++ begin
+++ do_error;
+++ exit;
+++ end;
+++ end;
+++ end;
+++
+++
+++ procedure read_index(require_rbracket : boolean);
+++ var
+++ recname : string;
+++ o_int,s_int : aint;
+++ begin
+++ case actasmtoken of
+++ AS_REGISTER :
+++ begin
+++ if getsupreg(actasmregister)=RS_XZR then
+++ Message1(asmr_e_invalid_ref_register,actasmpattern);
+++ oper.opr.ref.index:=actasmregister;
+++ Consume(AS_REGISTER);
+++ read_index_shift(require_rbracket);
+++ exit;
+++ end;
+++ AS_HASH : // constant
+++ begin
+++ Consume(AS_HASH);
+++(*
+++ if actasmtoken=AS_COLON then
+++ begin
+++ consume(AS_COLON);
+++ { GNU-style lower 12 bits of address of non-GOT-based
+++ access }
+++ if (actasmpattern='LO12') then
+++ begin
+++ consume(actasmtoken);
+++ consume(AS_COLON);
+++ if not oper.SetupVar(actasmpattern,false) then
+++ begin
+++ do_error;
+++ exit
+++ end;
+++ consume(AS_ID);
+++ oper.opr.ref.refaddr:=addr_??? (not gotpageoffset);
+++ end
+++ else
+++ begin
+++ do_error;
+++ exit
+++ end;
+++ end
+++ else
+++*)
+++ begin
+++ o_int:=BuildConstExpression(false,true);
+++ inc(oper.opr.ref.offset,o_int);
+++ end;
+++ test_end(require_rbracket);
+++ exit;
+++ end;
+++ AS_ID :
+++ begin
+++ recname:=actasmpattern;
+++ Consume(AS_ID);
+++ { Apple-style got page offset }
+++ if actasmtoken=AS_AT then
+++ begin
+++ if not oper.SetupVar(recname,false) then
+++ begin
+++ do_error;
+++ exit
+++ end;
+++ consume(AS_AT);
+++ if actasmpattern='GOTPAGEOFF' then
+++ begin
+++ consume(actasmtoken);
+++ oper.opr.ref.refaddr:=addr_gotpageoffset;
+++ end
+++ else if actasmpattern='PAGEOFF' then
+++ begin
+++ consume(actasmtoken);
+++ oper.opr.ref.refaddr:=addr_pageoffset;
+++ end
+++ else
+++ begin
+++ do_error;
+++ exit
+++ end;
+++ end
+++ else
+++ begin
+++ BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
+++ inc(oper.opr.ref.offset,o_int);
+++ end;
+++ test_end(require_rbracket);
+++ exit;
+++ end;
+++ AS_AT:
+++ begin
+++ do_error;
+++ exit;
+++ end;
+++ AS_RBRACKET :
+++ begin
+++ if require_rbracket then
+++ begin
+++ test_end(require_rbracket);
+++ exit;
+++ end
+++ else
+++ begin
+++ do_error; // unexpected rbracket
+++ exit;
+++ end;
+++ end;
+++ AS_SEPARATOR,AS_end :
+++ begin
+++ if not require_rbracket then
+++ begin
+++ test_end(false);
+++ exit;
+++ end
+++ else
+++ begin
+++ do_error;
+++ exit;
+++ end;
+++ end;
+++ else
+++ begin
+++ // unexpected token
+++ do_error;
+++ exit;
+++ end;
+++ end; // case
+++ end;
+++
+++
+++ procedure try_prepostindexed;
+++ begin
+++ Consume(AS_RBRACKET);
+++ case actasmtoken of
+++ AS_COMMA :
+++ begin // post-indexed
+++ Consume(AS_COMMA);
+++ oper.opr.ref.addressmode:=AM_POSTINDEXED;
+++ read_index(false);
+++ exit;
+++ end;
+++ AS_NOT :
+++ begin // pre-indexed
+++ Consume(AS_NOT);
+++ oper.opr.ref.addressmode:=AM_PREINDEXED;
+++ test_end(false);
+++ exit;
+++ end;
+++ else
+++ begin
+++ test_end(false);
+++ exit;
+++ end;
+++ end; // case
+++ end;
+++
+++ begin
+++ Consume(AS_LBRACKET);
+++ oper.opr.ref.addressmode:=AM_OFFSET; // assume "neither PRE nor POST inc"
+++ if actasmtoken=AS_REGISTER then
+++ begin
+++ if getsupreg(actasmregister)=RS_XZR then
+++ Message1(asmr_e_invalid_ref_register,actasmpattern);
+++ oper.opr.ref.base:=actasmregister;
+++ Consume(AS_REGISTER);
+++ case actasmtoken of
+++ AS_RBRACKET :
+++ begin
+++ try_prepostindexed;
+++ exit;
+++ end;
+++ AS_COMMA :
+++ begin
+++ Consume(AS_COMMA);
+++ read_index(true);
+++ exit;
+++ end;
+++ else
+++ begin
+++ Message(asmr_e_invalid_reference_syntax);
+++ RecoverConsume(false);
+++ end;
+++ end;
+++ end
+++ else
+++ Begin
+++ case actasmtoken of
+++ AS_ID :
+++ begin
+++ { TODO: local variables and parameters }
+++ Message(asmr_e_invalid_reference_syntax);
+++ RecoverConsume(false);
+++ exit;
+++ end;
+++ else
+++ begin // elsecase
+++ Message(asmr_e_invalid_reference_syntax);
+++ RecoverConsume(false);
+++ exit;
+++ end;
+++ end;
+++ end;
+++ end;
+++
+++
+++ function taarch64attreader.TryBuildShifterOp(instr: taarch64instruction; opnr: longint): boolean;
+++
+++ procedure handlepara(sm : tshiftmode);
+++ begin
+++ consume(AS_ID);
+++ fillchar(instr.operands[opnr].opr,sizeof(instr.operands[opnr].opr),0);
+++ instr.operands[opnr].opr.typ:=OPR_SHIFTEROP;
+++ instr.operands[opnr].opr.shifterop.shiftmode:=sm;
+++ if (sm=SM_LSL) or
+++ (actasmtoken=AS_HASH) then
+++ begin
+++ consume(AS_HASH);
+++ instr.operands[opnr].opr.shifterop.shiftimm:=BuildConstExpression(false,false);
+++ end;
+++ end;
+++
+++ const
+++ shiftmode2str: array[SM_LSL..SM_SXTX] of string[4] =
+++ ('LSL','LSR','ASR',
+++ 'UXTB','UXTH','UXTW','UXTX',
+++ 'SXTB','SXTH','SXTW','SXTX');
+++ var
+++ sm: tshiftmode;
+++ i: longint;
+++ usessp,
+++ useszr: boolean;
+++ begin
+++ result:=false;
+++ if (actasmtoken=AS_ID) then
+++ begin
+++ for sm:=low(shiftmode2str) to high(shiftmode2str) do
+++ if actasmpattern=shiftmode2str[sm] then
+++ begin
+++ handlepara(sm);
+++ if instr.operands[1].opr.typ=OPR_REGISTER then
+++ begin
+++ { the possible shifter ops depend on whether this
+++ instruction uses sp and/or zr }
+++ usessp:=false;
+++ useszr:=false;
+++ for i:=low(instr.operands) to pred(opnr) do
+++ begin
+++ if (instr.operands[1].opr.typ=OPR_REGISTER) then
+++ case getsupreg(instr.operands[1].opr.reg) of
+++ RS_XZR:
+++ useszr:=true;
+++ RS_SP:
+++ usessp:=true;
+++ end;
+++ end;
+++ result:=valid_shifter_operand(instr.opcode,useszr,usessp,instr.Is64bit,sm,instr.operands[opnr].opr.shifterop.shiftimm);
+++ end
+++ end;
+++ end;
+++ end;
+++
+++
+++ function taarch64attreader.ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
+++ begin
+++ case actopcode of
+++ A_CSEL,A_CSINC,A_CSINV,A_CSNEG,A_CSET,A_CSETM,
+++ A_CINC,A_CINV,A_CNEG,A_CCMN,A_CCMP,
+++ A_B:
+++ begin
+++ { search for condition, conditions are always 2 chars }
+++ if (is_operand<>(actopcode=A_B)) and
+++ (length(hs)>1) then
+++ begin
+++ { workaround for DFA bug }
+++ result:=low(tasmcond);
+++ for result:=low(tasmcond) to high(tasmcond) do
+++ begin
+++ if hs=uppercond2str[result] then
+++ exit;
+++ end;
+++ end;
+++ end;
+++ end;
+++ result:=C_None;;
+++ end;
+++
+++
+++ Procedure taarch64attreader.BuildOperand(oper: taarch64operand; is64bit: boolean);
+++ var
+++ expr: string;
+++ typesize, l: aint;
+++
+++ procedure MaybeAddGotAddrMode;
+++ begin
+++ if actasmtoken=AS_AT then
+++ begin
+++ consume(AS_AT);
+++ if actasmpattern='GOTPAGE' then
+++ oper.opr.ref.refaddr:=addr_gotpage
+++ else if actasmpattern='GOTPAGEOFF' then
+++ oper.opr.ref.refaddr:=addr_gotpageoffset
+++ else if actasmpattern='PAGE' then
+++ oper.opr.ref.refaddr:=addr_page
+++ else if actasmpattern='PAGEOFF' then
+++ oper.opr.ref.refaddr:=addr_pageoffset
+++ else
+++ Message(asmr_e_expr_illegal);
+++ consume(actasmtoken);
+++ end
+++ else
+++ oper.opr.ref.refaddr:=addr_pic;
+++ end;
+++
+++ procedure AddLabelOperand(hl:tasmlabel);
+++ begin
+++ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+++ is_calljmp(actopcode) then
+++ begin
+++ oper.opr.typ:=OPR_SYMBOL;
+++ oper.opr.symbol:=hl;
+++ end
+++ else if (actopcode=A_ADR) or
+++ (actopcode=A_ADRP) then
+++ begin
+++ oper.InitRef;
+++ MaybeAddGotAddrMode;
+++ oper.opr.ref.symbol:=hl;
+++ if (actasmtoken in [AS_PLUS, AS_MINUS]) then
+++ begin
+++ l:=BuildConstExpression(true,false);
+++ oper.opr.ref.offset:=l;
+++ end;
+++ end;
+++ end;
+++
+++
+++ procedure MaybeRecordOffset;
+++ var
+++ mangledname: string;
+++ hasdot : boolean;
+++ l,
+++ toffset,
+++ tsize : aint;
+++ begin
+++ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+++ exit;
+++ l:=0;
+++ hasdot:=(actasmtoken=AS_DOT);
+++ if hasdot then
+++ begin
+++ if expr<>'' then
+++ begin
+++ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+++ if (oper.opr.typ<>OPR_CONSTANT) and
+++ (mangledname<>'') then
+++ Message(asmr_e_wrong_sym_type);
+++ inc(l,toffset);
+++ oper.SetSize(tsize,true);
+++ end;
+++ end;
+++ if actasmtoken in [AS_PLUS,AS_MINUS] then
+++ inc(l,BuildConstExpression(true,false));
+++ case oper.opr.typ of
+++ OPR_LOCAL :
+++ begin
+++ { don't allow direct access to fields of parameters, because that
+++ will generate buggy code. Allow it only for explicit typecasting }
+++ if hasdot and
+++ (not oper.hastype) and
+++ (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+++ (current_procinfo.procdef.proccalloption<>pocall_register) then
+++ Message(asmr_e_cannot_access_field_directly_for_parameters);
+++ inc(oper.opr.localsymofs,l)
+++ end;
+++ OPR_CONSTANT :
+++ inc(oper.opr.val,l);
+++ OPR_REFERENCE :
+++ if (mangledname<>'') then
+++ begin
+++ if (oper.opr.val<>0) then
+++ Message(asmr_e_wrong_sym_type);
+++ oper.opr.typ:=OPR_SYMBOL;
+++ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+++ end
+++ else
+++ inc(oper.opr.val,l);
+++ OPR_SYMBOL:
+++ Message(asmr_e_invalid_symbol_ref);
+++ else
+++ internalerror(200309221);
+++ end;
+++ end;
+++
+++
+++ function MaybeBuildReference(is64bit: boolean):boolean;
+++ { Try to create a reference, if not a reference is found then false
+++ is returned }
+++ begin
+++ MaybeBuildReference:=true;
+++ case actasmtoken of
+++ AS_INTNUM,
+++ AS_MINUS,
+++ AS_PLUS:
+++ Begin
+++ oper.opr.ref.offset:=BuildConstExpression(True,False);
+++ if actasmtoken<>AS_LPAREN then
+++ Message(asmr_e_invalid_reference_syntax)
+++ else
+++ BuildReference(oper,is64bit);
+++ end;
+++ AS_LPAREN:
+++ BuildReference(oper,is64bit);
+++ AS_ID: { only a variable is allowed ... }
+++ Begin
+++ ReadSym(oper,is64bit);
+++ case actasmtoken of
+++ AS_end,
+++ AS_SEPARATOR,
+++ AS_COMMA: ;
+++ AS_LPAREN:
+++ BuildReference(oper,is64bit);
+++ else
+++ Begin
+++ Message(asmr_e_invalid_reference_syntax);
+++ Consume(actasmtoken);
+++ end;
+++ end; {end case }
+++ end;
+++ else
+++ MaybeBuildReference:=false;
+++ end; { end case }
+++ end;
+++
+++
+++ var
+++ tempreg: tregister;
+++ hl: tasmlabel;
+++ icond: tasmcond;
+++ Begin
+++ expr:='';
+++ case actasmtoken of
+++ AS_LBRACKET: { Memory reference or constant expression }
+++ Begin
+++ oper.InitRef;
+++ BuildReference(oper,is64bit);
+++ end;
+++
+++ AS_HASH: { Constant expression }
+++ Begin
+++ Consume(AS_HASH);
+++ BuildConstantOperand(oper);
+++ end;
+++
+++ (*
+++ AS_INTNUM,
+++ AS_MINUS,
+++ AS_PLUS:
+++ Begin
+++ { Constant memory offset }
+++ { This must absolutely be followed by ( }
+++ oper.InitRef;
+++ oper.opr.ref.offset:=BuildConstExpression(True,False);
+++ if actasmtoken<>AS_LPAREN then
+++ begin
+++ ofs:=oper.opr.ref.offset;
+++ BuildConstantOperand(oper);
+++ inc(oper.opr.val,ofs);
+++ end
+++ else
+++ BuildReference(oper,is64bit);
+++ end;
+++ *)
+++ AS_ID: { A constant expression, or a Variable ref. }
+++ Begin
+++ { Condition code? }
+++ icond:=ToConditionCode(actasmpattern,true);
+++ if icond<>C_None then
+++ begin
+++ oper.opr.typ:=OPR_COND;
+++ oper.opr.cc:=icond;
+++ consume(AS_ID);
+++ end
+++ else
+++ { Local Label ? }
+++ if is_locallabel(actasmpattern) then
+++ begin
+++ CreateLocalLabel(actasmpattern,hl,false);
+++ Consume(AS_ID);
+++ AddLabelOperand(hl);
+++ end
+++ else
+++ { Check for label }
+++ if SearchLabel(actasmpattern,hl,false) then
+++ begin
+++ Consume(AS_ID);
+++ AddLabelOperand(hl);
+++ end
+++ else
+++ { probably a variable or normal expression }
+++ { or a procedure (such as in CALL ID) }
+++ begin
+++ { is it a constant ? }
+++ if SearchIConstant(actasmpattern,l) then
+++ begin
+++ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+++ Message(asmr_e_invalid_operand_type);
+++ BuildConstantOperand(oper);
+++ end
+++ else
+++ begin
+++ expr:=actasmpattern;
+++ Consume(AS_ID);
+++ { typecasting? }
+++ if (actasmtoken=AS_LPAREN) and
+++ SearchType(expr,typesize) then
+++ begin
+++ oper.hastype:=true;
+++ Consume(AS_LPAREN);
+++ BuildOperand(oper,is64bit);
+++ Consume(AS_RPAREN);
+++ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+++ oper.SetSize(typesize,true);
+++ end
+++ else
+++ begin
+++ if not(oper.SetupVar(expr,false)) then
+++ Begin
+++ { look for special symbols ... }
+++ if expr= '__HIGH' then
+++ begin
+++ consume(AS_LPAREN);
+++ if not oper.setupvar('high'+actasmpattern,false) then
+++ Message1(sym_e_unknown_id,'high'+actasmpattern);
+++ consume(AS_ID);
+++ consume(AS_RPAREN);
+++ end
+++ else
+++ if expr = '__RESULT' then
+++ oper.SetUpResult
+++ else
+++ if expr = '__SELF' then
+++ oper.SetupSelf
+++ else
+++ if expr = '__OLDEBP' then
+++ oper.SetupOldEBP
+++ else
+++ Message1(sym_e_unknown_id,expr);
+++ end
+++ else
+++ MaybeAddGotAddrMode;
+++ end;
+++ end;
+++ if actasmtoken=AS_DOT then
+++ MaybeRecordOffset;
+++ { add a constant expression? }
+++ if (actasmtoken=AS_PLUS) then
+++ begin
+++ l:=BuildConstExpression(true,false);
+++ case oper.opr.typ of
+++ OPR_CONSTANT :
+++ inc(oper.opr.val,l);
+++ OPR_LOCAL :
+++ inc(oper.opr.localsymofs,l);
+++ OPR_REFERENCE :
+++ inc(oper.opr.ref.offset,l);
+++ else
+++ internalerror(200309202);
+++ end;
+++ end
+++ end;
+++ { Do we have a indexing reference, then parse it also }
+++ if actasmtoken=AS_LPAREN then
+++ BuildReference(oper,is64bit);
+++ end;
+++
+++ { Register, a variable reference or a constant reference }
+++ AS_REGISTER:
+++ Begin
+++ { save the type of register used. }
+++ tempreg:=actasmregister;
+++ Consume(AS_REGISTER);
+++ if (actasmtoken in [AS_end,AS_SEPARATOR,AS_COMMA]) then
+++ Begin
+++ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+++ Message(asmr_e_invalid_operand_type);
+++ oper.opr.typ:=OPR_REGISTER;
+++ oper.opr.reg:=tempreg;
+++ end
+++ else
+++ Message(asmr_e_syn_operand);
+++ end;
+++
+++ AS_end,
+++ AS_SEPARATOR,
+++ AS_COMMA: ;
+++ else
+++ Begin
+++ Message(asmr_e_syn_operand);
+++ Consume(actasmtoken);
+++ end;
+++ end; { end case }
+++ end;
+++
+++{*****************************************************************************
+++ taarch64attreader
+++*****************************************************************************}
+++
+++ procedure taarch64attreader.BuildOpCode(instr: taarch64instruction);
+++ var
+++ operandnum : longint;
+++ Begin
+++ { opcode }
+++ if (actasmtoken<>AS_OPCODE) then
+++ Begin
+++ Message(asmr_e_invalid_or_missing_opcode);
+++ RecoverConsume(true);
+++ exit;
+++ end;
+++ { Fill the instr object with the current state }
+++ with instr do
+++ begin
+++ Opcode:=ActOpcode;
+++ condition:=ActCondition;
+++ oppostfix:=actoppostfix;
+++ end;
+++ Consume(AS_OPCODE);
+++
+++ { We are reading operands, so opcode will be an AS_ID }
+++ operandnum:=1;
+++ { Zero operand opcode ? }
+++ if actasmtoken in [AS_SEPARATOR,AS_end] then
+++ begin
+++ instr.Ops:=0;
+++ exit;
+++ end;
+++ { Read the operands }
+++ repeat
+++ case actasmtoken of
+++ AS_COMMA: { Operand delimiter }
+++ Begin
+++ { operandnum and not operandnum+1, because tinstruction is
+++ one-based and taicpu is zero-based)
+++ }
+++ if can_be_shifter_operand(instr.opcode,operandnum) then
+++ begin
+++ Consume(AS_COMMA);
+++ if not TryBuildShifterOp(instr,operandnum+1) then
+++ Message(asmr_e_illegal_shifterop_syntax);
+++ Inc(operandnum);
+++ end
+++ else
+++ begin
+++ if operandnum>Max_Operands then
+++ Message(asmr_e_too_many_operands)
+++ else
+++ Inc(operandnum);
+++ Consume(AS_COMMA);
+++ end;
+++ end;
+++ AS_SEPARATOR,
+++ AS_end : { End of asm operands for this opcode }
+++ begin
+++ break;
+++ end;
+++ else
+++ begin
+++ BuildOperand(taarch64operand(instr.operands[operandnum]),instr.Is64bit);
+++ instr.Ops:=operandnum;
+++ if instr.operands[operandnum].opr.typ=OPR_REFERENCE then
+++ if simple_ref_type(instr.opcode,instr.cgsize,instr.oppostfix,instr.operands[operandnum].opr.ref)<>sr_simple then
+++ Message(asmr_e_invalid_reference_syntax);
+++ ;
+++ end;
+++ end; { end case }
+++ until false;
+++ end;
+++
+++
+++ function taarch64attreader.is_asmopcode(const s: string):boolean;
+++
+++ const
+++ { sorted by length so longer postfixes will match first }
+++ postfix2strsorted : array[1..7] of string[3] = (
+++ 'SB','SH','SW',
+++ 'B','H','W',
+++ 'S');
+++
+++ postfixsorted : array[1..7] of TOpPostfix = (
+++ PF_SB,PF_SH,PF_SW,
+++ PF_B,PF_H,PF_W,
+++ PF_S);
+++
+++ var
+++ j : longint;
+++ hs : string;
+++ maxlen : longint;
+++ icond : tasmcond;
+++ Begin
+++ { making s a value parameter would break other assembler readers }
+++ hs:=s;
+++ is_asmopcode:=false;
+++
+++ { clear opcode }
+++ actopcode:=A_None;
+++ actcondition:=C_None;
+++
+++ { b.cond ? }
+++ if (length(hs)=4) and
+++ (hs[1]='B') and
+++ (hs[2]='.') then
+++ begin
+++ actopcode:=A_B;
+++ actasmtoken:=AS_OPCODE;
+++ actcondition:=ToConditionCode(copy(hs,3,length(actasmpattern)-2),false);
+++ if actcondition<>C_None then
+++ is_asmopcode:=true;
+++ exit;
+++ end;
+++
+++ maxlen:=max(length(hs),7);
+++ actopcode:=A_NONE;
+++ for j:=maxlen downto 1 do
+++ begin
+++ actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
+++ if actopcode<>A_NONE then
+++ begin
+++ actasmtoken:=AS_OPCODE;
+++ { strip op code }
+++ delete(hs,1,j);
+++ break;
+++ end;
+++ end;
+++ if actopcode=A_NONE then
+++ exit;
+++
+++ { check for postfix }
+++ if length(hs)>0 then
+++ begin
+++ for j:=low(postfixsorted) to high(postfixsorted) do
+++ begin
+++ if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+++ begin
+++ actoppostfix:=postfixsorted[j];
+++ { strip postfix }
+++ delete(hs,1,length(postfix2strsorted[j]));
+++ break;
+++ end;
+++ end;
+++ end;
+++ { if we stripped all postfixes, it's a valid opcode }
+++ is_asmopcode:=length(hs)=0;
+++ end;
+++
+++
+++ procedure taarch64attreader.ConvertCalljmp(instr: taarch64instruction);
+++ var
+++ newopr : toprrec;
+++ begin
+++ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+++ begin
+++ newopr.typ:=OPR_SYMBOL;
+++ newopr.symbol:=instr.Operands[1].opr.ref.symbol;
+++ newopr.symofs:=instr.Operands[1].opr.ref.offset;
+++ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+++ (instr.Operands[1].opr.ref.index<>NR_NO) or
+++ (instr.Operands[1].opr.ref.refaddr<>addr_pic) then
+++ Message(asmr_e_syn_operand);
+++ instr.Operands[1].opr:=newopr;
+++ end;
+++ end;
+++
+++ procedure taarch64attreader.handleopcode;
+++ var
+++ instr: taarch64instruction;
+++ begin
+++ instr:=taarch64instruction.Create(taarch64operand);
+++ BuildOpcode(instr);
+++ if is_calljmp(instr.opcode) then
+++ ConvertCalljmp(instr);
+++ {
+++ instr.AddReferenceSizes;
+++ instr.SetInstructionOpsize;
+++ instr.CheckOperandSizes;
+++ }
+++ instr.ConcatInstruction(curlist);
+++ instr.Free;
+++ actoppostfix:=PF_None;
+++ end;
+++
+++
+++{*****************************************************************************
+++ Initialize
+++*****************************************************************************}
+++
+++const
+++ asmmode_arm_att_info : tasmmodeinfo =
+++ (
+++ id : asmmode_arm_gas;
+++ idtxt : 'GAS';
+++ casmreader : taarch64attreader;
+++ );
+++
+++ asmmode_arm_standard_info : tasmmodeinfo =
+++ (
+++ id : asmmode_standard;
+++ idtxt : 'STANDARD';
+++ casmreader : taarch64attreader;
+++ );
+++
+++initialization
+++ RegisterAsmMode(asmmode_arm_att_info);
+++ RegisterAsmMode(asmmode_arm_standard_info);
+++end.
++Index: fpc/fpcsrc/compiler/aarch64/rgcpu.pas
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/compiler/aarch64/rgcpu.pas
++@@ -0,0 +1,171 @@
+++{
+++ Copyright (c) 1998-2002 by Florian Klaempfl
+++
+++ This unit implements the SPARC specific class for the register
+++ allocator
+++
+++ This program is free software; you can redistribute it and/or modify
+++ it under the terms of the GNU General Public License as published by
+++ the Free Software Foundation; either version 2 of the License, or
+++ (at your option) any later version.
+++
+++ This program is distributed in the hope that it will be useful,
+++ but WITHOUT ANY WARRANTY; without even the implied warranty of
+++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+++ GNU General Public License for more details.
+++
+++ You should have received a copy of the GNU General Public License
+++ along with this program; if not, write to the Free Software
+++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+++
+++ ****************************************************************************}
+++unit rgcpu;
+++
+++{$i fpcdefs.inc}
+++
+++ interface
+++
+++ uses
+++ aasmbase,aasmcpu,aasmtai,aasmdata,
+++ cgbase,cgutils,
+++ cpubase,
+++ globtype,
+++ rgobj;
+++
+++ type
+++ trgcpu=class(trgobj)
+++ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);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: fpc/fpcsrc/compiler/aasmtai.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aasmtai.pas
+++++ fpc/fpcsrc/compiler/aasmtai.pas
++@@ -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: fpc/fpcsrc/compiler/aggas.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aggas.pas
+++++ fpc/fpcsrc/compiler/aggas.pas
++@@ -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: fpc/fpcsrc/compiler/aoptobj.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/aoptobj.pas
+++++ fpc/fpcsrc/compiler/aoptobj.pas
++@@ -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: fpc/fpcsrc/compiler/arm/aasmcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/aasmcpu.pas
+++++ fpc/fpcsrc/compiler/arm/aasmcpu.pas
++@@ -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;
++@@ -1605,6 +1812,12 @@ implementation
++ 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
++ s:=s+'reg';
++@@ -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;
++
+++ function MakeRegList(reglist: tcpuregisterset): word;
+++ var
+++ i, w: word;
+++ begin
+++ result:=0;
+++ w:=1;
+++ for i:=RS_R0 to RS_R15 do
+++ begin
+++ if i in reglist then
+++ result:=result or w;
+++ w:=w shl 1
+++ end;
+++ end;
+++
+++ function getcoproc(reg: tregister): byte;
+++ begin
+++ if reg=NR_p15 then
+++ result:=15
+++ else
+++ begin
+++ Message1(asmw_e_invalid_opcode_and_operands,'Invalid coprocessor port');
+++ result:=0;
+++ end;
+++ end;
+++
+++ function getcoprocreg(reg: tregister): byte;
+++ begin
+++ result:=getsupreg(reg)-getsupreg(NR_CR0);
+++ end;
+++
+++ 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;
+++
+++ 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;
+++
+++ 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 is_sat then
+++ begin
+++ bytes:=bytes or ((typ and 1) shl 5);
+++ bytes:=bytes or ((typ shr 1) shl 21);
+++ end
+++ else
+++ 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;
+++
++ begin
++ bytes:=$0;
+++ bytelen:=4;
++ i_field:=0;
++ { evaluate and set condition code }
+++ bytes:=bytes or (CondVal[condition] shl 28);
++
++ { condition code allowed? }
++
++ { setup rest of the instruction }
++ case insentry^.code[0] of
++- #$08:
+++ #$01: // B/BL
++ begin
++ { set instruction code }
++- bytes:=bytes or (ord(insentry^.code[1]) shl 26);
++- bytes:=bytes or (ord(insentry^.code[2]) shl 21);
+++ 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 }
+++ { 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;
++
++- { set s if necessary }
+++ 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;
++- #$ff:
++- internalerror(2005091101);
++- else
++- internalerror(2005091102);
++- end;
++- { we're finished, write code }
++- objdata.writebytes(bytes,sizeof(bytes));
++- 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]);
++
++-{$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;
++- }
+++ if ops=3 then
+++ begin
+++ msb:=(oper[1]^.val+oper[2]^.val-1);
++
++- // 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
++- }
+++ { 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);
++
++- 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 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;
++
++- if (data >= 0x1000)
++- {
++- errfunc (ERR_NONFATAL, "too long offset");
++- }
+++ 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);
++
++- 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;
+++ bytes:=bytes or (((Rd and $1E) shr 1) shl 16);
+++ bytes:=bytes or ((Rd and $1) shl 7);
++
++- 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:=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);
++
++- 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:=bytes or (((Rd and $1E) shr 1) shl 12);
+++ bytes:=bytes or ((Rd and $1) shl 22);
++
++- bytes[3] |= c;
++- }
+++ 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);
++
++- // 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;
++- }
+++ Rd:=getmmreg(oper[0]^.reg);
+++ Rm:=getmmreg(oper[1]^.reg);
++
++- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
++- return;
+++ bytes:=bytes or (1 shl 8);
++
++- 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);
++- }
+++ bytes:=bytes or ((Rd and $F) shl 12);
+++ bytes:=bytes or (((Rd and $10) shr 4) shl 22);
++
++- // 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:=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;
++
++- bytes[3] |= c;
++- }
+++ bytes:=bytes or (Rn shl 16);
++
++- // 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;
++- }
+++ 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;
++
++- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
++- return;
+++ bytes:=bytes or (Rn shl 16);
++
+++ 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;
++
++- 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;
+++ 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;
++
++- bytes[0] = c | *codes++;
+++ bytes:=bytes or (1 shl 8);
+++ end;
++
++- bytes[1] = *codes;
+++ bytes:=bytes or (Rd shl 12);
+++ bytes:=bytes or (Rn shl 16);
+++ bytes:=bytes or (Rm shl 0);
+++
+++ 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);
++
++- // Implicit S code
++- bytes[1] |= 0x10;
+++ if (ops=2) and
+++ (oppostfix in [PF_F32F64,PF_F64F32]) then
+++ begin
+++ if oppostfix=PF_F32F64 then
+++ begin
+++ bytes:=bytes or (1 shl 8);
++
++- c = regval (&ins->oprs[0],1);
++- // Rn in low nibble
++- bytes[1] |= c;
+++ 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;
++
++- // No destination
++- bytes[2] = 0;
+++ bytes:=bytes and $FFF0FFFF;
+++ bytes:=bytes or ($7 shl 16);
++
++- 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:=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[3] |= c;
++- }
+++ d:=rd and 1;
+++ rd:=rd shr 1;
+++ end;
+++ R_SUBFD:
+++ begin
+++ rd:=getmmreg(oper[0]^.reg);
++
++- // 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;
++- }
+++ d:=(rd shr 4) and 1;
+++ rd:=rd and $F;
+++ end;
+++ end;
++
++- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
++- return;
+++ m:=0;
+++ case getsubreg(oper[1]^.reg) of
+++ R_SUBNONE:
+++ rm:=getsupreg(oper[1]^.reg);
+++ R_SUBFS:
+++ begin
+++ rm:=getmmreg(oper[1]^.reg);
++
++- case 0x10: // MRS Rd,<psr>
++- ++codes;
+++ m:=rm and 1;
+++ rm:=rm shr 1;
+++ end;
+++ R_SUBFD:
+++ begin
+++ rm:=getmmreg(oper[1]^.reg);
++
++- bytes[0] = c | *codes++;
+++ m:=(rm shr 4) and 1;
+++ rm:=rm and $F;
+++ 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 if ops=2 then
+++ begin
+++ case oppostfix of
+++ PF_S32F64,
+++ PF_U32F64,
+++ PF_F64S32,
+++ PF_F64U32:
+++ bytes:=bytes or (1 shl 8);
+++ end;
++
++- bytes[2] = c << 4;
+++ 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;
++
++- bytes[3] = 0;
+++ bytes:=bytes or (1 shl 18);
++
++- c = ins->oprs[1].basereg;
+++ D:=rd and $1; Rd:=Rd shr 1;
++
++- if (c == R_CPSR || c == R_SPSR)
++- {
++- if (c == R_SPSR)
++- {
++- bytes[1] |= 0x40;
++- }
++- }
++- else
++- {
++- errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
++- }
+++ 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;
++
++- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+++ M:=rm and $1; Rm:=Rm shr 1;
++
++- return;
+++ 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;
++
++- case 0x11: // MSR <psr>,Rm
++- case 0x12: // MSR <psrf>,Rm
++- case 0x13: // MSR <psrf>,#expression
++- ++codes;
+++ bytes:=bytes or (Rd shl 12);
+++ bytes:=bytes or (Rm shl 0);
++
++- bytes[0] = c | *codes++;
+++ 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);
++
++- bytes[1] = *codes++;
+++ 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] = *codes;
+++ 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');
++
+++ rn:=16;
+++ end;
+++ else
+++ Rn:=0;
+++ message(asmw_e_invalid_opcode_and_operands);
+++ end;
++
++- if (keep == 0x11 || keep == 0x12)
++- {
++- // Rm
++- c = regval (&ins->oprs[1],1);
+++ 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;
++
++- bytes[3] = c;
++- }
++- else
++- {
++- int shimm;
+++ 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;
++
++- shimm = imm_shift (ins->oprs[1].offset);
+++ 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);
++
++- if (shimm == -1)
++- {
++- errfunc (ERR_NONFATAL, "cannot create that constant");
++- }
++- bytes[3] = shimm & 0xFF;
++- bytes[2] |= (shimm & 0xF00) >> 8;
++- }
+++ bytes:=bytes or (Rd shl 12);
+++ bytes:=bytes or (D shl 22);
++
++- c = ins->oprs[0].basereg;
+++ rn:=rn-oper[2]^.val;
++
++- 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;
+++ 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);
++
++- case 0x14: // MUL Rd,Rm,Rs
++- case 0x15: // MULA Rd,Rm,Rs,Rn
++- ++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[0] = c | *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[1] = *codes++;
+++ bytes:=bytes or (Rn shl 16);
++
++- bytes[3] = *codes;
+++ { 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;
++
++- // Rd
++- bytes[1] |= regval (&ins->oprs[0],1);
++- if (has_S_code)
++- bytes[1] |= 0x10;
+++ 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;
++
++- // Rm
++- bytes[3] |= regval (&ins->oprs[1],1);
+++ dp_operation:=(oper[1]^.subreg=R_SUBFD);
+++ if oper[1]^.regset^=[] then
+++ message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
+++
+++ rd:=0;
+++ for r:=0 to 31 do
+++ if r in oper[1]^.regset^ then
+++ begin
+++ rd:=r;
+++ break;
+++ end;
++
++- // Rs
++- bytes[2] = regval (&ins->oprs[2],1);
+++ rn:=32-rd;
+++ for r:=rd+1 to 31 do
+++ if not(r in oper[1]^.regset^) then
+++ begin
+++ rn:=r-rd;
+++ break;
+++ end;
++
++- if (keep == 0x15)
++- {
++- bytes[2] |= regval (&ins->oprs[3],1) << 4;
++- }
++- break;
+++ if dp_operation then
+++ begin
+++ bytes:=bytes or (1 shl 8);
++
++- case 0x16: // SMLAL RdHi,RdLo,Rm,Rs
++- ++codes;
+++ bytes:=bytes or (rn*2);
++
++- bytes[0] = c | *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[1] = *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:=0;
+++ for r:=0 to 31 do
+++ if r in oper[0]^.regset^ then
+++ begin
+++ rd:=r;
+++ break;
+++ end;
++
++- bytes[3] = *codes;
+++ rn:=32-rd;
+++ for r:=rd+1 to 31 do
+++ if not(r in oper[0]^.regset^) then
+++ begin
+++ rn:=r-rd;
+++ break;
+++ end;
++
++- // RdHi
++- bytes[1] |= regval (&ins->oprs[1],1);
++- if (has_S_code)
++- bytes[1] |= 0x10;
+++ if dp_operation then
+++ begin
+++ bytes:=bytes or (1 shl 8);
++
++- // RdLo
++- bytes[2] = regval (&ins->oprs[0],1) << 4;
++- // Rm
++- bytes[3] |= regval (&ins->oprs[2],1);
+++ bytes:=bytes or (rn*2);
++
++- // Rs
++- bytes[2] |= regval (&ins->oprs[3],1);
+++ 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;
++
++- break;
+++ 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);
++
++- case 0x17: // LDR Rd, expression
++- ++codes;
+++ if getsubreg(oper[0]^.reg)=R_SUBFD then
+++ begin
+++ bytes:=bytes or (1 shl 8);
++
++- bytes[0] = c | *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;
++
++- bytes[1] = *codes++;
+++ { 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;
++
++- // 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");
++- }
+++ offset:=offset div 4;
++
++- // Rn - implicit R15
++- bytes[1] |= 0xF;
+++ 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;
++
++- if (ins->oprs[1].segment != segment)
++- {
++- errfunc (ERR_NONFATAL, "label not in same segment");
++- }
+++ 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;
++
++- data = ins->oprs[1].offset - (offset + 8);
+++ { 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;
++
++- if (data < 0)
++- {
++- data = -data;
++- }
++- else
++- {
++- bytes[1] |= 0x80;
++- }
+++ { 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;
++
++- if (data >= 0x1000)
++- {
++- errfunc (ERR_NONFATAL, "too long offset");
++- }
+++ 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[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
++- }
+++ { set opcode }
+++ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+++ bytes:=bytes or ord(insentry^.code[2]);
++
++- if (has_W_code)
++- {
++- bytes[1] |= 0x20; // write-back
++- }
+++ if insentry^.code[0]=#$63 then
+++ bytes:=bytes or (CondVal[condition] shl 8);
++
++- // Rn
++- c = regval (&ins->oprs[1],1);
++- bytes[1] |= c;
+++ 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 (c == 0x15) // R15
++- data = -8;
++- else
++- data = 0;
+++ 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;
++
++- if (data < 0)
++- {
++- data = -data;
++- }
++- else
++- {
++- bytes[1] |= 0x80;
++- }
+++ { set opcode }
+++ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+++ bytes:=bytes or ord(insentry^.code[2]);
++
++- 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");
++- }
+++ 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;
++
++- 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;
++- }
++- }
+++ { 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;
++
++- break;
+++ { 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;
++
++- case 0x22: // LDRH Rd, expression
++- ++codes;
+++ { 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;
++
++- bytes[0] = c | 0x01; // Implicit pre-index
+++ { set opcode }
+++ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+++ { set opers }
+++ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
++
++- bytes[1] = *codes++;
+++ 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;
++
++- // Rd
++- bytes[2] = regval (&ins->oprs[0],1) << 4;
+++ offset:=offset div 2;
+++ end
+++ else
+++ offset:=oper[1]^.val div 2;
++
++- // Rn - implicit R15
++- bytes[1] |= 0xF;
+++ 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;
++
++- if (ins->oprs[1].segment != segment)
++- {
++- errfunc (ERR_NONFATAL, "label not in same segment");
++- }
+++ { set opcode }
+++ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
++
++- data = ins->oprs[1].offset - (offset + 8);
+++ 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);
++
++- if (data < 0)
++- {
++- data = -data;
++- }
++- else
++- {
++- bytes[1] |= 0x80;
++- }
+++ 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);
++
++- if (data >= 0x100)
++- {
++- errfunc (ERR_NONFATAL, "too long offset");
++- }
++- bytes[3] = *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;
+++ end;
+++ end;
+++ #$6A: { Thumb: IT }
+++ begin
+++ bytelen:=2;
+++ bytes:=0;
++
++- bytes[2] |= ((data & 0xF0) >> 4);
++- bytes[3] |= data & 0xF;
++- break;
+++ { set opcode }
+++ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+++ bytes:=bytes or (ord(insentry^.code[2]) shl 0);
++
++- case 0x23: // LDRH Rd, Rn
++- ++codes;
+++ bytes:=bytes or (CondVal[oper[0]^.cc] shl 4);
++
++- bytes[0] = c | 0x01; // Implicit pre-index
+++ 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;
++
++- bytes[1] = *codes++;
+++ 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;
++
++- // Rd
++- bytes[2] = regval (&ins->oprs[0],1) << 4;
+++ { 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;
++
++- // Rn
++- c = regval (&ins->oprs[1],1);
++- bytes[1] |= c;
+++ { set opcode }
+++ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+++ bytes:=bytes or ord(insentry^.code[2]);
+++
+++ 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 (c == 0x15) // R15
++- data = -8;
++- else
++- data = 0;
+++ 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 (data < 0)
++- {
++- data = -data;
++- }
++- else
++- {
++- bytes[1] |= 0x80;
++- }
+++ 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 (data >= 0x100)
++- {
++- errfunc (ERR_NONFATAL, "too long offset");
++- }
++- bytes[3] = *codes++;
+++ 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);
++
++- 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");
++- }
++- }
+++ 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);
++
++- bytes[3] = *codes++;
+++ 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 (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");
++- }
+++ 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 & 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;
+++ 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 0x26: // LDM/STM Rn, {reg-list}
++- ++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;
+++ offset:=offset;
+++ end;
++
++- bytes[0] |= ( *codes >> 4) & 0xF;
++- bytes[1] = ( *codes << 4) & 0xF0;
++- ++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;
++
++- if (has_W_code)
++- {
++- bytes[1] |= 0x20;
++- }
++- if (has_F_code)
++- {
++- bytes[1] |= 0x40;
++- }
+++ 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
++- bytes[1] |= regval (&ins->oprs[0],1);
+++ 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;
++
++- data = ins->oprs[1].basereg;
+++ 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);
+++
+++ if (ops>=(offset+2)) and
+++ (oper[offset+1]^.typ=top_const) then
+++ bytes:=bytes or (oper[offset+1]^.val and $1F);
++
++- bytes[2] = ((data >> 8) & 0xFF);
++- bytes[3] = (data & 0xFF);
+++ 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]);
++
++- break;
+++ 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;
++
++- case 0x27: // SWP Rd, Rm, [Rn]
++- ++codes;
+++ 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;
++
++- bytes[0] = c;
+++ 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] |= *codes++;
+++ bytes:=bytes or (i_field and $1F);
+++ 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;
++-
++- 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
++- {
+++ 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]);
+++
+++ 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);
++
++- }
++- ++codes;
++- }
++- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
++-}
+++ 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]);
++
++-*)
++-{$endif dummy}
+++ 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;
++
++- constructor tai_thumb_func.create;
++- begin
++- inherited create;
++- typ:=ait_thumb_func;
++- end;
+++ 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 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);
+++
+++ 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);
+++
+++ 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;
+++
+++ 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);
+++
+++ 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;
+++
+++ for r:=0 to 15 do
+++ if r in oper[1]^.regset^ then
+++ bytes:=bytes or (1 shl r);
+++
+++ 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;
+++
+++ 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);
+++
+++ 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 (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 (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 opcode=A_MRS then
+++ begin
+++ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+++
+++ case oper[1]^.reg of
+++ NR_MSP: bytes:=bytes or $08;
+++ NR_PSP: bytes:=bytes or $09;
+++
+++ NR_IPSR: bytes:=bytes or $05;
+++ NR_EPSR: bytes:=bytes or $06;
+++ NR_APSR: bytes:=bytes or $00;
+++
+++ 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);
+++
+++ 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;
+++
+++ NR_MSP: bytes:=bytes or $08;
+++ NR_PSP: bytes:=bytes or $09;
+++
+++ 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;
+++ 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]);
+++
+++ 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;
+++
+++ 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;
+++
+++ 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);
+++
+++ 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:=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;
+++
+++ 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;
+++
+++ 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);
+++
+++ case opcode of
+++ A_FLT:
+++ begin
+++ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+++ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
+++
+++ 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;
+++
+++ 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);
+++
+++ 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);
+++
+++ 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;
+++
+++ { 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);
+++
+++ { we're finished, write code }
+++ objdata.writebytes(bytes,bytelen);
+++ end;
++
++ begin
++ cai_align:=tai_align;
++Index: fpc/fpcsrc/compiler/arm/agarmgas.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/agarmgas.pas
+++++ fpc/fpcsrc/compiler/arm/agarmgas.pas
++@@ -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: fpc/fpcsrc/compiler/arm/aoptcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/aoptcpu.pas
+++++ fpc/fpcsrc/compiler/arm/aoptcpu.pas
++@@ -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: fpc/fpcsrc/compiler/arm/armatt.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armatt.inc
+++++ fpc/fpcsrc/compiler/arm/armatt.inc
++@@ -1,12 +1,9 @@
++ { don't edit, this file is generated from armins.dat }
++ (
++ 'none',
++-'abs',
++-'acs',
++-'asn',
++-'atn',
++ 'adc',
++ 'add',
+++'addw',
++ 'adf',
++ 'adr',
++ 'and',
++@@ -17,24 +14,18 @@
++ 'bkpt',
++ 'bx',
++ 'cdp',
++-'cmf',
++-'cmfe',
++ 'cmn',
++ 'cmp',
+++'cmf',
+++'cmfe',
+++'stf',
+++'ldf',
+++'lfm',
++ 'clz',
++-'cnf',
++-'cos',
++ 'cps',
++ 'cpsid',
++ 'cpsie',
++-'dvf',
++ 'eor',
++-'exp',
++-'fdv',
++-'flt',
++-'fix',
++-'fml',
++-'frd',
++ 'ldc',
++ 'ldm',
++ 'ldrbt',
++@@ -44,41 +35,32 @@
++ 'ldrsb',
++ 'ldrsh',
++ 'ldrt',
++-'ldf',
++-'lfm',
++-'lgn',
++-'log',
++ 'mcr',
+++'mcr2',
+++'mrc',
+++'mrc2',
+++'mcrr',
+++'mcrr2',
+++'mrrc',
+++'mrrc2',
++ 'mla',
++ 'mov',
++-'mrc',
++ 'mrs',
++ 'msr',
++-'mnf',
++-'muf',
++ 'mul',
++ 'mvf',
++ 'mvn',
+++'vmov',
++ 'nop',
+++'orn',
++ 'orr',
++-'rdf',
++-'rfs',
++-'rfc',
++-'rmf',
++-'rpw',
++ 'rsb',
++ 'rsc',
++-'rsf',
++-'rnd',
++-'pol',
++ 'sbc',
++ 'sfm',
++ 'sin',
++ 'smlal',
++ 'smull',
++-'sqt',
++-'suf',
++-'stf',
++ 'stm',
++ 'str',
++ 'strb',
++@@ -89,16 +71,14 @@
++ 'swi',
++ 'swp',
++ 'swpb',
++-'tan',
++ 'teq',
++ 'tst',
++ 'umlal',
++ 'umull',
++ 'wfs',
++ 'ldrd',
++-'mcrr',
++-'mrrc',
++ 'pld',
+++'pldw',
++ 'qadd',
++ 'qdadd',
++ 'qdsub',
++@@ -113,6 +93,12 @@
++ 'smlaltt',
++ 'smlawb',
++ 'smlawt',
+++'vldm',
+++'vstm',
+++'vpop',
+++'vpush',
+++'vldr',
+++'vstr',
++ 'smulbb',
++ 'smulbt',
++ 'smultb',
++@@ -120,67 +106,13 @@
++ 'smulwb',
++ 'smulwt',
++ 'strd',
++-'fabsd',
++-'fabss',
++-'faddd',
++-'fadds',
++-'fcmpd',
++-'fcmped',
++-'fcmpes',
++-'fcmpezd',
++-'fcmpezs',
++-'fcmps',
++-'fcmpzd',
++-'fcmpzs',
++-'fcpyd',
++-'fcpys',
++-'fcvtds',
++-'fcvtsd',
++-'fdivd',
++-'fdivs',
++-'fldd',
++-'fldm',
++-'flds',
++-'fmacd',
++-'fmacs',
++-'fmdhr',
++-'fmdlr',
++-'fmrdh',
++-'fmrdl',
++-'fmrs',
++-'fmrx',
++-'fmscd',
++-'fmscs',
++-'fmsr',
++-'fmstat',
++-'fmuld',
++-'fmuls',
++-'fmxr',
++-'fnegd',
++-'fnegs',
++-'fnmacd',
++-'fnmacs',
++-'fnmscd',
++-'fnmscs',
++-'fnmuld',
++-'fnmuls',
++-'fsitod',
++-'fsitos',
++-'fsqrtd',
++-'fsqrts',
+++'ldrht',
+++'strht',
+++'ldrsbt',
+++'ldrsht',
++ 'fstd',
++ 'fstm',
++ 'fsts',
++-'fsubd',
++-'fsubs',
++-'ftosid',
++-'ftosis',
++-'ftouid',
++-'ftouis',
++-'fuitod',
++-'fuitos',
++-'fmdrr',
++-'fmrrd',
++ 'bfc',
++ 'bfi',
++ 'clrex',
++@@ -188,8 +120,13 @@
++ 'ldrexb',
++ 'ldrexd',
++ 'ldrexh',
+++'strex',
+++'strexb',
+++'strexd',
+++'strexh',
++ 'mls',
++-'pkh',
+++'pkhbt',
+++'pkhtb',
++ 'pli',
++ 'qadd16',
++ 'qadd8',
++@@ -212,6 +149,8 @@
++ 'lsr',
++ 'lsl',
++ 'ror',
+++'rrx',
+++'umaal',
++ 'shadd16',
++ 'shadd8',
++ 'shasx',
++@@ -233,49 +172,102 @@
++ 'ssax',
++ 'ssub16',
++ 'ssub8',
++-'strex',
++-'strexb',
++-'strexd',
++-'strexh',
++ 'sxtab',
++ 'sxtab16',
++ 'sxtah',
+++'ubfx',
+++'uxtab',
+++'uxtab16',
+++'uxtah',
++ 'sxtb',
++ 'sxtb16',
+++'sxth',
++ 'uxtb',
+++'uxtb16',
++ 'uxth',
++-'sxth',
++ 'uadd16',
++ 'uadd8',
++ 'uasx',
++-'ubfx',
++ 'uhadd16',
++ 'uhadd8',
++ 'uhasx',
++ 'uhsax',
++ 'uhsub16',
++ 'uhsub8',
++-'umaal',
++ 'uqadd16',
++ 'uqadd8',
++ 'uqasx',
++ 'uqsax',
++ 'uqsub16',
++ 'uqsub8',
++-'uqsad8',
++-'uqsada8',
+++'usad8',
+++'usada8',
++ 'usat',
++ 'usat16',
++ 'usax',
++ 'usub16',
++ 'usub8',
++-'uxtab',
++-'uxtab16',
++-'uxtah',
++-'uxtb16',
++ 'wfe',
++ 'wfi',
++ 'yield',
+++'fabsd',
+++'fabss',
+++'faddd',
+++'fadds',
+++'fcmpd',
+++'fcmps',
+++'fcmped',
+++'fcmpes',
+++'fcmpzd',
+++'fcmpzs',
+++'fcmpezd',
+++'fcmpezs',
+++'fcpyd',
+++'fcpys',
+++'fcvtds',
+++'fcvtsd',
+++'fdivd',
+++'fdivs',
+++'fldd',
+++'fldm',
+++'flds',
+++'fmacd',
+++'fmacs',
+++'fmdhr',
+++'fmdlr',
+++'fmrdh',
+++'fmrdl',
+++'fmrs',
+++'fmrx',
+++'fmscd',
+++'fmscs',
+++'fmsr',
+++'fmstat',
+++'fmuld',
+++'fmuls',
+++'fmxr',
+++'fnegd',
+++'fnegs',
+++'fnmacd',
+++'fnmacs',
+++'fnmscd',
+++'fnmscs',
+++'fnmuld',
+++'fnmuls',
+++'fsitod',
+++'fsitos',
+++'fsqrtd',
+++'fsqrts',
+++'fsubd',
+++'fsubs',
+++'ftosid',
+++'ftosis',
+++'ftouid',
+++'ftouis',
+++'fuitod',
+++'fuitos',
+++'fmdrr',
+++'fmrrd',
++ 'pop',
++ 'push',
++ 'sdiv',
++@@ -306,29 +298,59 @@
++ 'vcmp',
++ 'vcmpe',
++ 'vcvt',
+++'vcvtr',
++ 'vdiv',
++-'vldm',
++-'vldr',
++-'vmov',
++ 'vmrs',
++ 'vmsr',
++-'vmul',
++ 'vmla',
++ 'vmls',
+++'vmul',
++ 'vnmla',
++ 'vnmls',
+++'vnmul',
++ 'vfma',
++ 'vfms',
++ 'vfnma',
++ 'vfnms',
++ 'vneg',
++-'vnmul',
++-'vpop',
++-'vpush',
++ 'vsqrt',
++-'vstm',
++-'vstr',
++ 'vsub',
+++'dmb',
+++'isb',
+++'dsb',
+++'smc',
++ 'neg',
++-'svc'
+++'svc',
+++'bxj',
+++'udf',
+++'tan',
+++'sqt',
+++'suf',
+++'rsf',
+++'rnd',
+++'pol',
+++'rdf',
+++'rfs',
+++'rfc',
+++'wfc',
+++'rmf',
+++'rpw',
+++'mnf',
+++'muf',
+++'abs',
+++'acs',
+++'asn',
+++'atn',
+++'cnf',
+++'cnfe',
+++'cos',
+++'dvf',
+++'exp',
+++'fdv',
+++'flt',
+++'fix',
+++'fml',
+++'frd',
+++'lgn',
+++'log'
++ );
++Index: fpc/fpcsrc/compiler/arm/armatts.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armatts.inc
+++++ fpc/fpcsrc/compiler/arm/armatts.inc
++@@ -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: fpc/fpcsrc/compiler/arm/armins.dat
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armins.dat
+++++ fpc/fpcsrc/compiler/arm/armins.dat
++@@ -85,713 +85,1756 @@
++ [NONE]
++ void void none
++
++-[ABScc]
++-
++-[ACScc]
+++[ADCcc]
+++reglo,reglo \x6B\x41\x40 THUMB,ARMv4T
++
++-[ASNcc]
+++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
+++
+++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
+++
+++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
++
++-[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
+++[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
++
++-[CDP]
++-reg8,reg8 \300\1\x10\101 ARM7
+++reg32 \3\x01\x2F\xFF\x10 ARM32,ARMv4T
++
++-[CMFcc]
++-
++-[CMFEcc]
+++[CDP]
+++reg8,reg8 \300\1\x10\101 ARM32,ARMv4
++
++ [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
+++reglo,reglo \x6B\x42\xC0 THUMB,ARMv4T
+++
+++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
+++
+++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
+++
+++reg32,reg32 \xC\x1\x40 ARM32,ARMv4
+++reg32,reg32,shifterop \xE\x1\x40 ARM32,ARMv4
+++reg32,immshifter \xF\x3\x40 ARM32,ARMv4
++
++-[COScc]
+++[CMFcc]
+++fpureg,fpureg \xA2\xE\x90 ARM32,FPA
+++fpureg,immshifter \xA2\xE\x90 ARM32,FPA
++
++-[CPS]
++-[CPSID]
++-[CPSIE]
+++[CMFEcc]
+++fpureg,fpureg \xA2\xE\xC0 ARM32,FPA
+++fpureg,immshifter \xA2\xE\xC0 ARM32,FPA
++
++-[DVFcc]
+++[STFcc]
+++fpureg,memam2 \xA0\xC\x00\x1\x0 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
+++[LDFcc]
+++fpureg,memam2 \xA0\xC\x10\x1\x0 ARM32,FPA
++
++-[EXPcc]
+++[LFMcc]
+++fpureg,imm32,memam2 \xA0\xC\x10\x2\x0 ARM32,FPA
+++fpureg,immshifter,memam2 \xA0\xC\x10\x2\x0 ARM32,FPA
++
++-[FDVcc]
+++[CLZcc]
+++reg32,reg32 \x80\xFA\xB0\xF0\x80 THUMB32,ARMv6T2
+++reg32,reg32 \x32\x01\x6F\xF\x10 ARM32,ARMv4
++
++-[FLTcc]
+++[CPS]
+++immshifter \x8F\xF3\xAF\x81\x00 THUMB32,ARMv6T2
+++immshifter \x46\xF1\x2\x0\x0 ARM32,ARMv6
++
++-[FIXcc]
+++[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
++
++-[FMLcc]
+++[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
++
++-[FRDcc]
+++[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
+++
+++[MCR2cc]
+++regf,immshifter,reg32,regf,regf \x1C\xFE\x0\x1 ARM32,ARMv5T
+++regf,immshifter,reg32,regf,regf,immshifter \x1C\xFE\x0\x1 ARM32,ARMv5T
+++
+++[MRCcc]
+++regf,immshifter,reg32,regf,regf \x1C\xE\x10\x1 ARM32,ARMv4
+++regf,immshifter,reg32,regf,regf,immshifter \x1C\xE\x10\x1 ARM32,ARMv4
+++
+++[MRC2cc]
+++regf,immshifter,reg32,regf,regf \x1C\xFE\x10\x1 ARM32,ARMv5T
+++regf,immshifter,reg32,regf,regf,immshifter \x1C\xFE\x10\x1 ARM32,ARMv5T
++
++-[LFMcc]
++-reg32,imm8,fpureg \xF0\x02\x01 FPA
+++[MCRRcc]
+++regf,immshifter,reg32,reg32,regf \x1D\xC\x40\x0 ARM32,ARMv5TE
++
++-[LGNcc]
+++[MCRR2cc]
+++regf,immshifter,reg32,reg32,regf \x1D\xFC\x40\x0 ARM32,ARMv6
++
++-[LOGcc]
+++[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
++-
++-[NOP]
++-
++-[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
+++reglo,reglo \x6B\x43\xc0 THUMB,ARMv4T
++
++-[RDFcc]
+++reg32,immshifter \x80\xF0\x6F\x0\x0 THUMB32,ARMv6T2
+++reg32,reg32 \x80\xEA\x6F\x0\x0 THUMB32,WIDE,ARMv6T2
++
++-[RFScc]
+++reg32,reg32 \x8\x1\xE0 ARM32,ARMv4
+++reg32,reg32,shifterop \xA\x1\xE0 ARM32,ARMv4
+++reg32,immshifter \xB\x1\xE0 ARM32,ARMv4
+++
+++[VMOVcc]
+++vreg,vreg \x90\xEE\xB0\xA\x40 THUMB32,VFPv2
+++vreg,vreg \x40\xE\xB0\xA\x40 ARM32,VFPv2
+++
+++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
+++
+++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
+++
+++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
++
++-[RFCcc]
+++[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
++
++-[RMFcc]
+++[ORRcc]
+++reglo,reglo \x6B\x43\x00 THUMB,ARMv4T
++
++-[RPWcc]
+++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
+++
+++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
++
++ [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
++-
++-[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
+++reglo,reglo,immzero \x6B\x42\x40 THUMB,ARMv4T
++
++-[RSFcc]
+++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
++
++-[RNDcc]
++-
++-[POLcc]
+++[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]
++-
++-[FABSScc]
++-
++-[FADDDcc]
++-
++-[FADDScc]
++-
++-[FCMPDcc]
++-
++-[FCMPEDcc]
++-
++-[FCMPEScc]
++-
++-[FCMPEZDcc]
++-
++-[FCMPEZScc]
++-
++-[FCMPScc]
++-
++-[FCMPZDcc]
++-
++-[FCMPZScc]
++-
++-[FCPYDcc]
++-
++-[FCPYScc]
++-
++-[FCVTDScc]
++-
++-[FCVTSDcc]
++-
++-[FDIVDcc]
++-
++-[FDIVScc]
++-
++-[FLDDcc]
++-
++-[FLDMcc]
++-
++-[FLDScc]
++-
++-[FMACDcc]
++-
++-[FMACScc]
++-
++-[FMDHRcc]
++-
++-[FMDLRcc]
++-
++-[FMRDHcc]
++-
++-[FMRDLcc]
++-
++-[FMRScc]
++-
++-[FMRXcc]
++-
++-[FMSCDcc]
++-
++-[FMSCScc]
++-
++-[FMSRcc]
++-
++-[FMSTATcc]
++-
++-[FMULDcc]
++-
++-[FMULScc]
++-
++-[FMXRcc]
++-
++-[FNEGDcc]
++-
++-[FNEGScc]
++-
++-[FNMACDcc]
++-
++-[FNMACScc]
++-
++-[FNMSCDcc]
++-
++-[FNMSCScc]
++-
++-[FNMULDcc]
++-
++-[FNMULScc]
++-
++-[FSITODcc]
++-
++-[FSITOScc]
++-
++-[FSQRTDcc]
++-
++-[FSQRTScc]
+++[LDRHTcc]
+++reg32,memam2 \x88\xF8\x30\xE\x0\0 THUMB32,ARMv6T2
+++reg32,memam2 \x19\x0\x30\x0\xB0 ARM32,ARMv4
+++
+++[STRHTcc]
+++reg32,memam2 \x88\xF8\x20\xE\x0\0 THUMB32,ARMv6T2
+++
+++reg32,memam2 \x88\xF8\x20\xE\x0\0 THUMB32,ARMv6T2
+++reg32,memam2 \x1E\x0\x20\x0\xB0 ARM32,ARMv4
+++
+++[LDRSBTcc]
+++reg32,memam2 \x88\xF9\x10\xE\x0\0 THUMB32,ARMv6T2
+++reg32,memam2 \x1E\x0\x30\x0\xD0 ARM32,ARMv4
+++
+++[LDRSHTcc]
+++reg32,memam2 \x88\xF9\x30\xE\x0\0 THUMB32,ARMv6T2
+++reg32,memam2 \x1E\x0\x30\x0\xF0 ARM32,ARMv4
++
++ [FSTDcc]
+++vreg,memam2 \x95\xED\x0\xA THUMB32,VFPv2
+++vreg,memam2 \x45\xD\x0\xA ARM32,VFPv2
++
++ [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
++
++ [FSTScc]
+++vreg,memam2 \x95\xED\x0\xA THUMB32,VFPv2
+++vreg,memam2 \x45\xD\x0\xA ARM32,VFPv2
++
++-[FSUBDcc]
++-
++-[FSUBScc]
+++; ARMv6
++
++-[FTOSIDcc]
+++[BFCcc]
+++reg32,immshifter,immshifter \x84\xF3\x6F\x0\x0 THUMB32,ARMv6T2
+++reg32,immshifter,imm32 \x84\xF3\x6F\x0\x0 THUMB32,ARMv6T2
++
++-[FTOSIScc]
+++reg32,immshifter,immshifter \x2D\x7\xC0\x0\x1F ARM32,ARMv4
+++reg32,immshifter,imm32 \x2D\x7\xC0\x0\x1F ARM32,ARMv4
++
++-[FTOUIDcc]
+++[BFIcc]
+++reg32,reg32,immshifter,immshifter \x84\xF3\x60\x0\x0 THUMB32,ARMv6T2
+++reg32,reg32,immshifter,imm32 \x84\xF3\x60\x0\x0 THUMB32,ARMv6T2
++
++-[FTOUIScc]
+++reg32,reg32,immshifter,immshifter \x2D\x7\xC0\x0\x10 ARM32,ARMv4
+++reg32,reg32,immshifter,imm32 \x2D\x7\xC0\x0\x10 ARM32,ARMv4
++
++-[FUITODcc]
+++[CLREX]
+++void \x80\xF3\xBF\x8F\x2F THUMB32,ARMv7
+++void \x2F\xF5\x7F\xF0\x1F ARM32,ARMv6K
++
++-[FUITOScc]
+++[LDREXcc]
+++reg32,memam6 \x8A\xE8\x50\x0F\x00 THUMB32,ARMv6T2
+++reg32,memam6 \x18\x01\x90\x0F\x9F ARM32,ARMv4
++
++-[FMDRRcc]
+++[LDREXBcc]
+++reg32,memam6 \x8A\xE8\xD0\x0F\x4F THUMB32,ARMv7
+++reg32,memam6 \x18\x01\xD0\x0F\x9F ARM32,ARMv4
++
++-[FMRRDcc]
+++[LDREXDcc]
+++reg32,reg32,memam6 \x8A\xE8\xD0\x00\x7F THUMB32,ARMv7
+++reg32,reg32,memam6 \x18\x01\xB0\x0F\x9F ARM32,ARMv4
++
++-; ARMv6
+++[LDREXHcc]
+++reg32,memam6 \x8A\xE8\xD0\x0F\x5F THUMB32,ARMv7
+++reg32,memam6 \x18\x01\xF0\x0F\x9F ARM32,ARMv4
++
++-[BFCcc]
+++[STREXcc]
+++reg32,reg32,memam6 \x8B\xE8\x40\x00\x00 THUMB32,ARMv6T2
+++reg32,reg32,memam6 \x18\x01\x80\x0F\x90 ARM32,ARMv4
++
++-[BFIcc]
+++[STREXBcc]
+++reg32,reg32,memam6 \x8B\xE8\xC0\x0F\x40 THUMB32,ARMv7
+++reg32,reg32,memam6 \x18\x01\xC0\x0F\x90 ARM32,ARMv4
++
++-[CLREX]
+++[STREXDcc]
+++reg32,reg32,reg32,memam6 \x8B\xE8\xC0\x00\x70 THUMB32,ARMv7
+++reg32,reg32,reg32,memam6 \x18\x01\xA0\x0F\x90 ARM32,ARMv4
++
++-[LDREXcc]
++-[LDREXBcc]
++-[LDREXDcc]
++-[LDREXHcc]
+++[STREXHcc]
+++reg32,reg32,memam6 \x8B\xE8\xC0\x0F\x50 THUMB32,ARMv7
+++reg32,reg32,memam6 \x18\x01\xE0\x0F\x90 ARM32,ARMv4
++
++ [MLScc]
+++reg32,reg32,reg32,reg32 \x80\xFB\x0\x0\x10 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x15\x00\x60\x9 ARM32,ARMv6T2
+++
+++[PKHBTcc]
+++reg32,reg32,reg32 \x80\xEA\xC0\x0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x0 THUMB32,ARMv6T2
+++
+++reg32,reg32,reg32 \x16\x6\x80\x1 ARM32,ARMv6
+++reg32,reg32,reg32,shifterop \x16\x6\x80\x1 ARM32,ARMv6
+++
+++[PKHTBcc]
+++reg32,reg32,reg32 \x80\xEA\xC0\x0\x10 THUMB32,ARMv6T2
+++reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x10 THUMB32,ARMv6T2
++
++-[PKHcc]
+++reg32,reg32,reg32 \x16\x6\x80\x1 ARM32,ARMv6
+++reg32,reg32,reg32,shifterop \x16\x6\x80\x5 ARM32,ARMv6
++
++ [PLI]
+++memam2 \x87\xF9\x10\xF0\x0 THUMB32,ARMv7
+++memam2 \x25\xF4\x50\xF0\x0 ARM32,ARMv7
++
++ [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
++
++ [RBITcc]
+++reg32,reg32 \x80\xFA\x90\xF0\xA0 THUMB32,ARMv6T2
+++reg32,reg32 \x32\x6\xFF\xF\x30 ARM32,ARMv6T2
++
++ [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
+++
++ [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
+++
++ [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
++
++ [SADD16cc]
+++reg32,reg32,reg32 \x80\xFA\90\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x10\xF1 ARM32,ARMv6
+++
++ [SADD8cc]
+++reg32,reg32,reg32 \x80\xFA\80\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x10\xF9 ARM32,ARMv6
+++
++ [SASXcc]
+++reg32,reg32,reg32 \x80\xFA\A0\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x10\xF3 ARM32,ARMv6
++
++ [SBFXcc]
+++reg32,reg32,immshifter,immshifter \x84\xF3\x40\x0\x0 THUMB32,ARMv6T2
+++reg32,reg32,immshifter,immshifter \x2D\x7\xA0\x0\x50 ARM32,ARMv6T2
++
++ [SELcc]
+++reg32,reg32,reg32 \x80\xFA\xA0\xF0\x80 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x80\xFB ARM32,ARMv6
++
++ [SETEND]
+++immshifter \x2B\xF1\x01\x0\x0 ARM32,ARMv6
++
++ [SEVcc]
+++void \x64\xBF\x40 THUMB,ARMv7
+++void \x2F\x3\x20\xF0\x4 ARM32,ARMv6K
++
++ [ASRcc]
+++reglo,immshifter \x60\x1\x0 THUMB,ARMv4T
+++reglo,reglo,immshifter \x60\x1\x0 THUMB,ARMv4T
+++reglo,reglo \x6B\x41\x0 THUMB,ARMv4T
+++
+++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
+++
+++reg32,reg32,reg32 \x30\x1\xA0\x0\x50 ARM32,ARMv4
+++reg32,reg32,immshifter \x30\x1\xA0\x0\x40 ARM32,ARMv4
++
++ [LSRcc]
+++reglo,immshifter \x60\x8\x0 THUMB,ARMv4T
+++reglo,reglo,immshifter \x60\x8\x0 THUMB,ARMv4T
+++reglo,reglo \x6B\x40\xC0 THUMB,ARMv4T
+++
+++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
+++
+++reg32,reg32,reg32 \x30\x1\xA0\x0\x30 ARM32,ARMv4
+++reg32,reg32,immshifter \x30\x1\xA0\x0\x20 ARM32,ARMv4
++
++ [LSLcc]
+++reglo,immshifter \x60\x0\x0 THUMB,ARMv4T
+++reglo,reglo,immshifter \x60\x0\x0 THUMB,ARMv4T
+++reglo,reglo \x6B\x40\x80 THUMB,ARMv4T
+++
+++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
+++
+++reg32,reg32,reg32 \x30\x1\xA0\x0\x10 ARM32,ARMv4
+++reg32,reg32,immshifter \x30\x1\xA0\x0\x00 ARM32,ARMv4
++
++ [RORcc]
+++reglo,reglo \x6B\x41\xC0 THUMB,ARMv4T
+++
+++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
+++
+++reg32,reg32,reg32 \x30\x1\xA0\x0\x70 ARM32,ARMv4
+++reg32,reg32,immshifter \x30\x1\xA0\x0\x60 ARM32,ARMv4
+++
+++[RRXcc]
+++reg32,reg32 \x80\xEA\x4F\x00\x30 THUMB32,ARMv6T2
+++reg32,reg32 \x30\x1\xA0\x0\x60 ARM32,ARMv4
+++
+++[UMAALcc]
+++reg32,reg32,reg32,reg32 \x85\xFB\xE0\x0\x60 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x16\x0\x40\x9 ARM32,ARMv6
++
++ [SHADD16cc]
+++reg32,reg32,reg32 \x80\xFA\x90\xF0\x20 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x30\xF1 ARM32,ARMv6
+++
++ [SHADD8cc]
+++reg32,reg32,reg32 \x80\xFA\x80\xF0\x20 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x30\xF9 ARM32,ARMv6
+++
++ [SHASXcc]
+++reg32,reg32,reg32 \x80\xFA\xA0\xF0\x20 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x30\xF3 ARM32,ARMv6
+++
++ [SHSAXcc]
+++reg32,reg32,reg32 \x80\xFA\xE0\xF0\x20 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x30\xF5 ARM32,ARMv6
+++
++ [SHSUB16cc]
+++reg32,reg32,reg32 \x80\xFA\xD0\xF0\x20 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x30\xF7 ARM32,ARMv6
+++
++ [SHSUB8cc]
+++reg32,reg32,reg32 \x80\xFA\xC0\xF0\x20 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x30\xFF ARM32,ARMv6
++
++ [SMLADcc]
+++reg32,reg32,reg32,reg32 \x80\xFB\x20\x0\x00 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x15\x7\x00\x1 ARM32,ARMv6
+++
++ [SMLALDcc]
+++reg32,reg32,reg32,reg32 \x85\xFB\xC0\x0\xC0 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x16\x7\x40\x1 ARM32,ARMv4
+++
++ [SMLSDcc]
+++reg32,reg32,reg32,reg32 \x80\xFB\x40\x0\x00 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x15\x7\x00\x5 ARM32,ARMv6
+++
++ [SMLSLDcc]
+++reg32,reg32,reg32,reg32 \x85\xFB\xD0\x0\xC0 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x16\x7\x40\x5 ARM32,ARMv6
+++
++ [SMMLAcc]
+++reg32,reg32,reg32,reg32 \x80\xFB\x50\x0\x00 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x15\x7\x50\x1 ARM32,ARMv6
+++
++ [SMMLScc]
+++reg32,reg32,reg32,reg32 \x80\xFB\x60\x0\x00 THUMB32,ARMv6T2
+++reg32,reg32,reg32,reg32 \x15\x7\x50\xD ARM32,ARMv6
+++
++ [SMMULcc]
+++reg32,reg32,reg32 \x80\xFB\x50\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x15\x7\x50\x1\xF ARM32,ARMv6
+++
++ [SMUADcc]
+++reg32,reg32,reg32 \x80\xFB\x20\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x15\x7\x00\x1\xF ARM32,ARMv6
+++
++ [SMUSDcc]
+++reg32,reg32,reg32 \x80\xFB\x40\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x15\x7\x00\x5\xF ARM32,ARMv6
++
++ [SRScc]
++
++ [SSATcc]
+++reg32,immshifter,reg32 \x83\xF3\x00\x0\x0 THUMB32,ARMv6T2
+++reg32,immshifter,reg32,shifterop \x83\xF3\x00\x0\x0 THUMB32,ARMv6T2
+++
+++reg32,immshifter,reg32 \x2A\x6\xA0\x0\x10 ARM32,ARMv6
+++reg32,immshifter,reg32,shifterop \x2A\x6\xA0\x0\x10 ARM32,ARMv6
+++
++ [SSAT16cc]
+++reg32,immshifter,reg32 \x83\xF3\x20\x0\x0 THUMB32,ARMv6T2
+++reg32,immshifter,reg32 \x2A\x6\xA0\xF\x30 ARM32,ARMv6
+++
++ [SSAXcc]
+++reg32,reg32,reg32 \x80\xFA\xE0\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x10\xF5 ARM32,ARMv6
++
++ [SSUB16cc]
++-[SSUB8cc]
+++reg32,reg32,reg32 \x80\xFA\xD0\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x10\xF7 ARM32,ARMv6
++
++-[STREXcc]
++-[STREXBcc]
++-[STREXDcc]
++-[STREXHcc]
+++[SSUB8cc]
+++reg32,reg32,reg32 \x80\xFA\xC0\xF0\x0 THUMB32,ARMv6T2
+++reg32,reg32,reg32 \x16\x06\x10\xFF ARM32,ARMv6
++
++ [SXTABcc]
+++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\x06\xA0\x07 ARM32,ARMv6
+++reg32,reg32,reg32,shifterop \x16\x06\xA0\x07 ARM32,ARMv6
+++
++ [SXTAB16cc]
+++reg32,reg32,reg32 \x86\xFA\x20\xF0\x80 THUMB32,ARMv6T2
+++reg32,reg32,reg32,shifterop \x86\xFA\x20\xF0\x80 THUMB32,ARMv6T2
+++
+++reg32,reg32,reg32 \x16\x06\x80\x07 ARM32,ARMv6
+++reg32,reg32,reg32,shifterop \x16\x06\x80\x07 ARM32,ARMv6
+++
++ [SXTAHcc]
+++reg32,reg32,reg32 \x86\xFA\x00\xF0\x80 THUMB32,ARMv6T2
+++reg32,reg32,reg32,shifterop \x86\xFA\x00\xF0\x80 THUMB32,ARMv6T2
+++
+++reg32,reg32,reg32 \x16\x06\xB0\x07 ARM32,ARMv6
+++reg32,reg32,reg32,shifterop \x16\x06\xB0\x07 ARM32,ARMv6
+++
+++[UBFXcc]
+++reg32,reg32,immshifter,immshifter \x84\xF3\xC0\x0\x0 THUMB32,ARMv6T2
+++reg32,reg32,immshifter,immshifter \x2D\x7\xE0\x0\x50 ARM32,ARMv4
+++
+++[UXTABcc]
+++reg32,reg32,reg32 \x86\xFA\x50\xF0\x80 THUMB32,ARMv6T2
+++reg32,reg32,reg32,shifterop \x86\xFA\x50\xF0\x80 THUMB32,ARMv6T2
+++
+++reg32,reg32,reg32 \x16\x6\xE0\x7 ARM32,ARMv6
+++reg32,reg32,reg32,shifterop \x16\x6\xE0\x7 ARM32,ARMv6
+++
+++[UXTAB16cc]
+++reg32,reg32,reg32 \x86\xFA\x30\xF0\x80 THUMB32,ARMv6T2
+++reg32,reg32,reg32,shifterop \x86\xFA\x30\xF0\x80 THUMB32,ARMv6T2
+++
+++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
+++
++ [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
++
++-[TBB]
++-[TBH]
+++[TBBcc]
+++memam2 \x8E\xE8\xD0\xF0\x00 THUMB32,ARMv6T2
+++
+++[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: fpc/fpcsrc/compiler/arm/armnop.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armnop.inc
+++++ fpc/fpcsrc/compiler/arm/armnop.inc
++@@ -1,2 +1,2 @@
++ { don't edit, this file is generated from armins.dat }
++-105;
+++952;
++Index: fpc/fpcsrc/compiler/arm/armop.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armop.inc
+++++ fpc/fpcsrc/compiler/arm/armop.inc
++@@ -1,12 +1,9 @@
++ { don't edit, this file is generated from armins.dat }
++ (
++ A_NONE,
++-A_ABS,
++-A_ACS,
++-A_ASN,
++-A_ATN,
++ A_ADC,
++ A_ADD,
+++A_ADDW,
++ A_ADF,
++ A_ADR,
++ A_AND,
++@@ -17,24 +14,18 @@ A_BLX,
++ A_BKPT,
++ A_BX,
++ A_CDP,
++-A_CMF,
++-A_CMFE,
++ A_CMN,
++ A_CMP,
+++A_CMF,
+++A_CMFE,
+++A_STF,
+++A_LDF,
+++A_LFM,
++ A_CLZ,
++-A_CNF,
++-A_COS,
++ A_CPS,
++ A_CPSID,
++ A_CPSIE,
++-A_DVF,
++ A_EOR,
++-A_EXP,
++-A_FDV,
++-A_FLT,
++-A_FIX,
++-A_FML,
++-A_FRD,
++ A_LDC,
++ A_LDM,
++ A_LDRBT,
++@@ -44,41 +35,32 @@ A_LDRH,
++ A_LDRSB,
++ A_LDRSH,
++ A_LDRT,
++-A_LDF,
++-A_LFM,
++-A_LGN,
++-A_LOG,
++ A_MCR,
+++A_MCR2,
+++A_MRC,
+++A_MRC2,
+++A_MCRR,
+++A_MCRR2,
+++A_MRRC,
+++A_MRRC2,
++ A_MLA,
++ A_MOV,
++-A_MRC,
++ A_MRS,
++ A_MSR,
++-A_MNF,
++-A_MUF,
++ A_MUL,
++ A_MVF,
++ A_MVN,
+++A_VMOV,
++ A_NOP,
+++A_ORN,
++ A_ORR,
++-A_RDF,
++-A_RFS,
++-A_RFC,
++-A_RMF,
++-A_RPW,
++ A_RSB,
++ A_RSC,
++-A_RSF,
++-A_RND,
++-A_POL,
++ A_SBC,
++ A_SFM,
++ A_SIN,
++ A_SMLAL,
++ A_SMULL,
++-A_SQT,
++-A_SUF,
++-A_STF,
++ A_STM,
++ A_STR,
++ A_STRB,
++@@ -89,16 +71,14 @@ A_SUB,
++ A_SWI,
++ A_SWP,
++ A_SWPB,
++-A_TAN,
++ A_TEQ,
++ A_TST,
++ A_UMLAL,
++ A_UMULL,
++ A_WFS,
++ A_LDRD,
++-A_MCRR,
++-A_MRRC,
++ A_PLD,
+++A_PLDW,
++ A_QADD,
++ A_QDADD,
++ A_QDSUB,
++@@ -113,6 +93,12 @@ A_SMLALTB,
++ A_SMLALTT,
++ A_SMLAWB,
++ A_SMLAWT,
+++A_VLDM,
+++A_VSTM,
+++A_VPOP,
+++A_VPUSH,
+++A_VLDR,
+++A_VSTR,
++ A_SMULBB,
++ A_SMULBT,
++ A_SMULTB,
++@@ -120,67 +106,13 @@ A_SMULTT,
++ A_SMULWB,
++ A_SMULWT,
++ A_STRD,
++-A_FABSD,
++-A_FABSS,
++-A_FADDD,
++-A_FADDS,
++-A_FCMPD,
++-A_FCMPED,
++-A_FCMPES,
++-A_FCMPEZD,
++-A_FCMPEZS,
++-A_FCMPS,
++-A_FCMPZD,
++-A_FCMPZS,
++-A_FCPYD,
++-A_FCPYS,
++-A_FCVTDS,
++-A_FCVTSD,
++-A_FDIVD,
++-A_FDIVS,
++-A_FLDD,
++-A_FLDM,
++-A_FLDS,
++-A_FMACD,
++-A_FMACS,
++-A_FMDHR,
++-A_FMDLR,
++-A_FMRDH,
++-A_FMRDL,
++-A_FMRS,
++-A_FMRX,
++-A_FMSCD,
++-A_FMSCS,
++-A_FMSR,
++-A_FMSTAT,
++-A_FMULD,
++-A_FMULS,
++-A_FMXR,
++-A_FNEGD,
++-A_FNEGS,
++-A_FNMACD,
++-A_FNMACS,
++-A_FNMSCD,
++-A_FNMSCS,
++-A_FNMULD,
++-A_FNMULS,
++-A_FSITOD,
++-A_FSITOS,
++-A_FSQRTD,
++-A_FSQRTS,
+++A_LDRHT,
+++A_STRHT,
+++A_LDRSBT,
+++A_LDRSHT,
++ A_FSTD,
++ A_FSTM,
++ A_FSTS,
++-A_FSUBD,
++-A_FSUBS,
++-A_FTOSID,
++-A_FTOSIS,
++-A_FTOUID,
++-A_FTOUIS,
++-A_FUITOD,
++-A_FUITOS,
++-A_FMDRR,
++-A_FMRRD,
++ A_BFC,
++ A_BFI,
++ A_CLREX,
++@@ -188,8 +120,13 @@ A_LDREX,
++ A_LDREXB,
++ A_LDREXD,
++ A_LDREXH,
+++A_STREX,
+++A_STREXB,
+++A_STREXD,
+++A_STREXH,
++ A_MLS,
++-A_PKH,
+++A_PKHBT,
+++A_PKHTB,
++ A_PLI,
++ A_QADD16,
++ A_QADD8,
++@@ -212,6 +149,8 @@ A_ASR,
++ A_LSR,
++ A_LSL,
++ A_ROR,
+++A_RRX,
+++A_UMAAL,
++ A_SHADD16,
++ A_SHADD8,
++ A_SHASX,
++@@ -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: fpc/fpcsrc/compiler/arm/armreg.dat
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armreg.dat
+++++ fpc/fpcsrc/compiler/arm/armreg.dat
++@@ -87,7 +87,7 @@ S28,$04,$06,$0E,s28,0,0
++ S29,$04,$06,$2E,s29,0,0
++ D14,$04,$07,$0E,d14,0,0
++ S30,$04,$06,$0F,s30,0,0
++-S31,$04,$06,$2F,s21,0,0
+++S31,$04,$06,$2F,s31,0,0
++ D15,$04,$07,$0F,d15,0,0
++ D16,$04,$07,$10,d16,0,0
++ D17,$04,$07,$11,d17,0,0
++@@ -145,4 +145,11 @@ BASEPRI,$05,$00,$1F,basepri,0,0
++ BASEPRI_MAX,$05,$00,$20,basepri_max,0,0
++ FAULTMASK,$05,$00,$21,faultmask,0,0
++ CONTROL,$05,$00,$22,control,0,0
++-
+++; VFP registers
+++FPSID,$05,$00,$23,fpsid,0,0
+++MVFR1,$05,$00,$24,mvfr1,0,0
+++MVFR0,$05,$00,$25,mvfr0,0,0
+++FPEXC,$05,$00,$26,fpexc,0,0
+++APSR_nzcvq,$05,$00,$27,apsr_nzcvq,0,0
+++APSR_g,$05,$00,$28,apsr_g,0,0
+++APSR_nzcvqg,$05,$00,$29,apsr_nzcvqg,0,0
++Index: fpc/fpcsrc/compiler/arm/armtab.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/armtab.inc
+++++ fpc/fpcsrc/compiler/arm/armtab.inc
++@@ -3,736 +3,6665 @@
++ (
++ opcode : A_NONE;
++ ops : 0;
++- optypes : (ot_none,ot_none,ot_none,ot_none);
+++ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
++ code : #0;
++ flags : if_none
++ ),
++ (
++ opcode : A_ADC;
+++ ops : 2;
+++ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+++ code : #107#65#64;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADC;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #128#241#64#0#0;
+++ flags : if_thumb32 or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADC;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+++ code : #128#235#64#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADC;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
++- code : #4#0#160;
++- flags : if_arm7
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+++ code : #128#235#64#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADC;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #128#241#64#0#0;
+++ flags : if_thumb32 or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADC;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #128#235#64#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
++ ),
++ (
++ opcode : A_ADC;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
++- code : #5#0#160;
++- flags : if_arm7
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+++ code : #128#235#64#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADC;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #4#0#160;
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ADC;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
++ code : #6#0#160;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ADC;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
++ code : #7#2#160;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+++ code : #97#68#0;
+++ flags : if_thumb or if_armv4t
++ ),
++ (
++ opcode : A_ADD;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
++- code : #4#0#128;
++- flags : if_arm7
+++ optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+++ code : #96#24#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 2;
+++ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #96#28#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #96#28#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 2;
+++ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #107#48#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reglo,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #100#168#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #100#176#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_regsp,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #100#68#104;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 2;
+++ optypes : (ot_regsp,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+++ code : #100#68#133;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #128#241#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+++ code : #128#235#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+++ code : #128#235#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #128#241#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #128#235#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
++ ),
++ (
++ opcode : A_ADD;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
++- code : #5#0#128;
++- flags : if_arm7
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+++ code : #128#235#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADD;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #4#0#128;
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ADD;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
++ code : #6#0#128;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ADD;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
++ code : #7#2#128;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
+++ ),
+++ (
+++ opcode : A_ADDW;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #129#242#0#0#0;
+++ flags : if_thumb32 or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADF;
+++ ops : 3;
+++ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+++ code : #161#0#0;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ opcode : A_ADF;
+++ ops : 3;
+++ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #161#0#0;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ opcode : A_ADR;
+++ ops : 2;
+++ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #103#160#0#2;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADR;
+++ ops : 2;
+++ optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+++ code : #103#160#0#2;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_ADR;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+++ code : #129#242#175#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADR;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #129#242#175#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADR;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+++ code : #129#242#175#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_ADR;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+++ code : #51#2#15;
+++ flags : if_arm32 or if_armv4
+++ ),
+++ (
+++ opcode : A_AND;
+++ ops : 2;
+++ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+++ code : #107#64#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_AND;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+++ code : #128#240#0#0#0;
+++ flags : if_thumb32 or if_armv6t2
+++ ),
+++ (
+++ opcode : A_AND;
+++ ops : 2;
+++ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+++ code : #128#234#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
++ ),
++ (
++ opcode : A_AND;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
++- code : #4#0#0;
++- flags : if_arm7
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+++ code : #128#234#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_AND;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+++ code : #128#240#0#0#0;
+++ flags : if_thumb32 or if_armv6t2
+++ ),
+++ (
+++ opcode : A_AND;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #128#234#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
++ ),
++ (
++ opcode : A_AND;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
++- code : #5#0#0;
++- flags : if_arm7
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+++ code : #128#234#0#0#0;
+++ flags : if_thumb32 or if_wide or if_armv6t2
+++ ),
+++ (
+++ opcode : A_AND;
+++ ops : 3;
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+++ code : #4#0#0;
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_AND;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
++ code : #6#0#0;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_AND;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
++ code : #7#2#0;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
+++ ),
+++ (
+++ opcode : A_B;
+++ ops : 1;
+++ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+++ code : #98#224#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_B;
+++ ops : 1;
+++ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+++ code : #98#224#0;
+++ flags : if_thumb or if_armv4t
+++ ),
+++ (
+++ opcode : A_B;
+++ ops : 1;
+++ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+++ code : #98#224#0;
+++ flags : if_thumb or if_armv4t
++ ),
++ (
++ opcode : A_B;
++ ops : 1;
++- optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+++ 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_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_memory or ot_bits32,ot_none,ot_none,ot_none);
+++ 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_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_memory or ot_bits32,ot_none,ot_none,ot_none);
++- code : #15#15;
++- flags : if_arm7
+++ 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_immediate24,ot_none,ot_none,ot_none);
++- code : #15#15;
++- flags : if_arm7
+++ 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);
+++ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
++ code : #3#1#47#255#16;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4t
++ ),
++ (
++ opcode : A_CDP;
++ ops : 2;
++- optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+++ optypes : (ot_reg8,ot_reg8,ot_none,ot_none,ot_none,ot_none);
++ code : #192#1#16#65;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_CMN;
++ ops : 2;
++- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
++- code : #12#1#96;
++- flags : if_arm7
+++ 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_reg32,ot_none);
++- code : #13#1#96;
++- flags : if_arm7
+++ 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_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
++ code : #14#1#96;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_CMN;
++ ops : 2;
++- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
++- code : #15#3#96;
++- flags : if_arm7
+++ 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_reg32,ot_reg32,ot_none,ot_none);
++- code : #12#1#64;
++- flags : if_arm7
+++ 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_reg32,ot_none);
++- code : #13#1#64;
++- flags : if_arm7
+++ 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_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
++ code : #14#1#64;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_CMP;
++ ops : 2;
++- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
++ code : #15#3#64;
++- flags : if_arm7
+++ 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);
++- code : #39#1#1;
++- flags : if_arm7
+++ 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_reg32,ot_none);
++- code : #4#0#32;
++- flags : if_arm7
+++ 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_reg32);
++- code : #5#0#32;
++- flags : if_arm7
+++ 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_immediate);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
++ code : #6#0#32;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_EOR;
++ 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#32;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_LDC;
++ ops : 2;
++- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
++ code : #209#192#1#17#65;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_LDM;
++ ops : 2;
++- optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
+++ 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_arm7
+++ 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_reg32,ot_memoryam2,ot_none,ot_none);
++- code : #23#7#16;
++- flags : if_arm7
+++ 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_reg32,ot_memoryam2,ot_none,ot_none);
++- code : #23#5#16;
++- flags : if_arm7
+++ 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_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
++- code : #34#80#176;
++- flags : if_arm7
+++ 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_reg32,ot_reg32,ot_none,ot_none);
++- code : #35#80#176;
++- flags : if_arm7
+++ 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 : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
++- code : #36#80#176;
++- flags : if_arm7
+++ 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 : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
++- code : #37#16#176;
++- flags : if_arm7
+++ 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_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
++- code : #34#80#208;
++- flags : if_arm7
+++ 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_reg32,ot_none,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_LDRSB;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
++ code : #36#80#208;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_LDRSB;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
++ code : #37#16#208;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_LDRSH;
++ ops : 2;
++- optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
++- code : #34#80#240;
++- flags : if_arm7
+++ 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_reg32,ot_none,ot_none);
++- code : #35#80#240;
++- flags : if_arm7
+++ 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 : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
++- code : #36#80#240;
++- flags : if_arm7
+++ 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_LDRSH;
++- ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
++- code : #37#16#240;
++- flags : if_arm7
+++ 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_LFM;
++- ops : 3;
++- optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
++- code : #240#2#1;
++- flags : if_fpa
+++ 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);
++- code : #21#0#32#144;
++- flags : if_arm7
+++ 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_reg32,ot_none,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_MSR;
++ ops : 2;
++- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
++- code : #17#1#41#240;
++- flags : if_arm7
+++ 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);
++- code : #18#1#40#240;
++- flags : if_arm7
+++ 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_immediate,ot_none,ot_none);
++- code : #19#3#40#240;
++- flags : if_arm7
+++ 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_reg32,ot_reg32,ot_reg32,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_MVF;
++ ops : 2;
++- optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none);
++- code : #242;
++- flags : if_fpa
+++ 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_immediatefpu,ot_none,ot_none);
++- code : #242;
++- flags : if_fpa
+++ 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_reg32,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ORR;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
++ code : #5#1#128;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ORR;
++ 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#128;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_ORR;
++ 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#128;
++- flags : if_arm7
+++ 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_reg32,ot_none);
++- code : #4#0#96;
++- flags : if_arm7
+++ 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_reg32);
++- code : #5#0#96;
++- flags : if_arm7
+++ 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_immediate);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
++ code : #6#0#96;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_RSB;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
++- code : #7#2#96;
++- flags : if_arm7
+++ 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);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
++ code : #4#0#224;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_RSC;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
++ code : #5#0#224;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_RSC;
++ 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#224;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_RSC;
++ 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#224;
++- flags : if_arm7
+++ 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_reg32,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_SBC;
++ ops : 4;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
++ code : #5#0#192;
++- flags : if_arm7
+++ 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_immediate);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
++ code : #6#0#192;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_SBC;
++ 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#192;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_SFM;
++ 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_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);
++- code : #22#0#224#144;
++- flags : if_arm7
+++ 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);
++- code : #22#0#192#144;
++- flags : if_arm7
+++ 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_memoryam4,ot_reglist,ot_none,ot_none);
+++ 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_arm7
+++ 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);
+++ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
++ code : #23#4#0;
++- flags : if_arm7
+++ 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_reg32,ot_memoryam2,ot_none,ot_none);
++- code : #23#6#0;
++- flags : if_arm7
+++ 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_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
++- code : #34#64#176;
++- flags : if_arm7
+++ 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_reg32,ot_reg32,ot_none,ot_none);
++- code : #35#64#176;
++- flags : if_arm7
+++ 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 : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
++- code : #36#64#176;
++- flags : if_arm7
+++ 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_reg32,ot_reg32,ot_reg32,ot_none);
++- code : #37#0#176;
++- flags : if_arm7
+++ 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_reg32,ot_reg32,ot_shifterop,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_SUB;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
++ code : #4#0#64;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_SUB;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
++ code : #4#0#64;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++- opcode : A_SWI;
++- ops : 1;
++- optypes : (ot_immediate,ot_none,ot_none,ot_none);
++- code : #2#15;
++- flags : if_arm7
+++ 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_reg32,ot_none);
++- code : #39#1#144;
++- flags : if_arm7
+++ 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_reg32,ot_none);
++- code : #39#1#144;
++- flags : if_arm7
+++ 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_reg32,ot_none,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TEQ;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
++ code : #13#1#32;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TEQ;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
++ code : #14#1#32;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TEQ;
++ ops : 2;
++- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
++ code : #15#3#32;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TST;
++ ops : 2;
++- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+++ 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_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TST;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
++ code : #13#1#0;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TST;
++ ops : 3;
++- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+++ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
++ code : #14#1#0;
++- flags : if_arm7
+++ flags : if_arm32 or if_armv4
++ ),
++ (
++ opcode : A_TST;
++ ops : 2;
++- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+++ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
++ code : #15#3#0;
++- flags : if_arm7
+++ 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);
++- code : #22#0#160#144;
++- flags : if_arm7
+++ 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);
++- code : #22#0#128#144;
++- flags : if_arm7
+++ 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_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_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_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_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_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_VNMLA;
+++ ops : 3;
+++ 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_VNMLA;
+++ ops : 3;
+++ 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_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_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_VNMUL;
+++ ops : 3;
+++ 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_VNMUL;
+++ ops : 3;
+++ 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_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_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_VFMS;
+++ ops : 3;
+++ 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_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_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_VFNMA;
+++ ops : 3;
+++ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+++ code : #66#14#144#10#0;
+++ flags : if_arm32 or if_vfpv4
+++ ),
+++ (
+++ opcode : A_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_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_VNEG;
+++ ops : 2;
+++ 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_VNEG;
+++ ops : 2;
+++ 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_VSQRT;
+++ ops : 2;
+++ 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_VSQRT;
+++ ops : 2;
+++ 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_VSUB;
+++ ops : 3;
+++ 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_VSUB;
+++ ops : 3;
+++ 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_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_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_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_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_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_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_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_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_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_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_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_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+++ code : #161#1#21;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ opcode : A_TAN;
+++ ops : 2;
+++ 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_SQT;
+++ ops : 2;
+++ 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_SQT;
+++ ops : 2;
+++ 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_SUF;
+++ ops : 3;
+++ 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_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_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_RSF;
+++ ops : 3;
+++ 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_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_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_POL;
+++ ops : 3;
+++ 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_POL;
+++ ops : 3;
+++ 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_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_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_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_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_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_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_RMF;
+++ ops : 3;
+++ 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_RPW;
+++ ops : 3;
+++ 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_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_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_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_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+++ code : #161#0#2;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ opcode : A_MUF;
+++ ops : 3;
+++ 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_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_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_ACS;
+++ ops : 2;
+++ 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_ACS;
+++ ops : 2;
+++ 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_ASN;
+++ ops : 2;
+++ 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_ASN;
+++ ops : 2;
+++ 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_ATN;
+++ ops : 2;
+++ 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_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_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_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_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_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_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_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_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+++ code : #161#0#8;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ opcode : A_DVF;
+++ ops : 3;
+++ 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_EXP;
+++ ops : 2;
+++ 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_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_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+++ code : #161#0#20;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ opcode : A_FDV;
+++ ops : 3;
+++ 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_FLT;
+++ ops : 2;
+++ 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_FIX;
+++ ops : 2;
+++ 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_FML;
+++ ops : 3;
+++ 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_FML;
+++ ops : 3;
+++ 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_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_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+++ code : #161#1#13;
+++ flags : if_arm32 or if_fpa
+++ ),
+++ (
+++ 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_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: fpc/fpcsrc/compiler/arm/cgcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/cgcpu.pas
+++++ fpc/fpcsrc/compiler/arm/cgcpu.pas
++@@ -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: fpc/fpcsrc/compiler/arm/cpubase.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/cpubase.pas
+++++ fpc/fpcsrc/compiler/arm/cpubase.pas
++@@ -93,7 +93,7 @@ unit cpubase;
++ first_mm_imreg = $30;
++
++ { TODO: Calculate bsstart}
++- regnumber_count_bsstart = 64;
+++ regnumber_count_bsstart = 128;
++
++ regnumber_table : array[tregisterindex] of tregister = (
++ {$i rarmnum.inc}
++@@ -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: fpc/fpcsrc/compiler/arm/cpuelf.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/cpuelf.pas
+++++ fpc/fpcsrc/compiler/arm/cpuelf.pas
++@@ -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: fpc/fpcsrc/compiler/arm/cpuinfo.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/cpuinfo.pas
+++++ fpc/fpcsrc/compiler/arm/cpuinfo.pas
++@@ -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: fpc/fpcsrc/compiler/arm/narmadd.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/narmadd.pas
+++++ fpc/fpcsrc/compiler/arm/narmadd.pas
++@@ -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: fpc/fpcsrc/compiler/arm/narmcnv.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/narmcnv.pas
+++++ fpc/fpcsrc/compiler/arm/narmcnv.pas
++@@ -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: fpc/fpcsrc/compiler/arm/narminl.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/narminl.pas
+++++ fpc/fpcsrc/compiler/arm/narminl.pas
++@@ -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: fpc/fpcsrc/compiler/arm/narmmat.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/narmmat.pas
+++++ fpc/fpcsrc/compiler/arm/narmmat.pas
++@@ -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: fpc/fpcsrc/compiler/arm/narmmem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/narmmem.pas
+++++ fpc/fpcsrc/compiler/arm/narmmem.pas
++@@ -27,6 +27,7 @@ interface
++
++ uses
++ globtype,
+++ symtype,
++ cgbase,cpubase,nmem,ncgmem;
++
++ type
++@@ -36,7 +37,7 @@ interface
++
++
++ tarmvecnode = class(tcgvecnode)
++- procedure update_reference_reg_mul(maybe_const_reg: tregister; l: aint);override;
+++ procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);override;
++ end;
++
++ implementation
++@@ -70,7 +71,7 @@ implementation
++ TARMVECNODE
++ *****************************************************************************}
++
++- procedure tarmvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+++ procedure tarmvecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
++ var
++ hreg: tregister;
++ hl : longint;
++@@ -79,7 +80,7 @@ implementation
++ (GenerateThumbCode) or
++ { simple constant? }
++ (l=1) or ispowerof2(l,hl) or ispowerof2(l+1,hl) or ispowerof2(l-1,hl) then
++- inherited update_reference_reg_mul(maybe_const_reg,l)
+++ inherited update_reference_reg_mul(maybe_const_reg,regsize,l)
++ else if (location.reference.base<>NR_NO) then
++ begin
++ hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
++Index: fpc/fpcsrc/compiler/arm/raarmgas.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/raarmgas.pas
+++++ fpc/fpcsrc/compiler/arm/raarmgas.pas
++@@ -30,6 +30,7 @@ Unit raarmgas;
++ cpubase;
++
++ type
+++
++ tarmattreader = class(tattreader)
++ actoppostfix : TOpPostfix;
++ actwideformat : boolean;
++@@ -45,6 +46,13 @@ Unit raarmgas;
++ procedure ReadSym(oper : tarmoperand);
++ procedure ConvertCalljmp(instr : tarminstruction);
++ procedure HandleTargetDirective; override;
+++ protected
+++ function is_unified: boolean; virtual;
+++ end;
+++
+++ tarmunifiedattreader = class(tarmattreader)
+++ protected
+++ function is_unified: boolean; override;
++ end;
++
++
++@@ -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: fpc/fpcsrc/compiler/arm/rarmcon.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmcon.inc
+++++ fpc/fpcsrc/compiler/arm/rarmcon.inc
++@@ -123,3 +123,10 @@ NR_BASEPRI = tregister($0500001F);
++ NR_BASEPRI_MAX = tregister($05000020);
++ NR_FAULTMASK = tregister($05000021);
++ NR_CONTROL = tregister($05000022);
+++NR_FPSID = tregister($05000023);
+++NR_MVFR1 = tregister($05000024);
+++NR_MVFR0 = tregister($05000025);
+++NR_FPEXC = tregister($05000026);
+++NR_APSR_nzcvq = tregister($05000027);
+++NR_APSR_g = tregister($05000028);
+++NR_APSR_nzcvqg = tregister($05000029);
++Index: fpc/fpcsrc/compiler/arm/rarmdwa.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmdwa.inc
+++++ fpc/fpcsrc/compiler/arm/rarmdwa.inc
++@@ -122,4 +122,11 @@
++ 0,
++ 0,
++ 0,
+++0,
+++0,
+++0,
+++0,
+++0,
+++0,
+++0,
++ 0
++Index: fpc/fpcsrc/compiler/arm/rarmnor.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmnor.inc
+++++ fpc/fpcsrc/compiler/arm/rarmnor.inc
++@@ -1,2 +1,2 @@
++ { don't edit, this file is generated from armreg.dat }
++-124
+++131
++Index: fpc/fpcsrc/compiler/arm/rarmnum.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmnum.inc
+++++ fpc/fpcsrc/compiler/arm/rarmnum.inc
++@@ -122,4 +122,11 @@ tregister($0500001E),
++ tregister($0500001F),
++ tregister($05000020),
++ tregister($05000021),
++-tregister($05000022)
+++tregister($05000022),
+++tregister($05000023),
+++tregister($05000024),
+++tregister($05000025),
+++tregister($05000026),
+++tregister($05000027),
+++tregister($05000028),
+++tregister($05000029)
++Index: fpc/fpcsrc/compiler/arm/rarmrni.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmrni.inc
+++++ fpc/fpcsrc/compiler/arm/rarmrni.inc
++@@ -122,4 +122,11 @@
++ 120,
++ 121,
++ 122,
++-123
+++123,
+++124,
+++125,
+++126,
+++127,
+++128,
+++129,
+++130
++Index: fpc/fpcsrc/compiler/arm/rarmsri.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmsri.inc
+++++ fpc/fpcsrc/compiler/arm/rarmsri.inc
++@@ -1,7 +1,10 @@
++ { don't edit, this file is generated from armreg.dat }
++ 0,
++ 110,
+++129,
++ 92,
+++128,
+++130,
++ 120,
++ 121,
++ 123,
++@@ -65,11 +68,15 @@
++ 23,
++ 24,
++ 122,
+++127,
++ 90,
+++124,
++ 114,
++ 113,
++ 111,
++ 117,
+++126,
+++125,
++ 109,
++ 119,
++ 118,
++@@ -104,7 +111,6 @@
++ 53,
++ 28,
++ 55,
++-71,
++ 56,
++ 58,
++ 59,
++@@ -116,6 +122,7 @@
++ 68,
++ 29,
++ 70,
+++71,
++ 31,
++ 32,
++ 34,
++Index: fpc/fpcsrc/compiler/arm/rarmsta.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmsta.inc
+++++ fpc/fpcsrc/compiler/arm/rarmsta.inc
++@@ -122,4 +122,11 @@
++ 0,
++ 0,
++ 0,
+++0,
+++0,
+++0,
+++0,
+++0,
+++0,
+++0,
++ 0
++Index: fpc/fpcsrc/compiler/arm/rarmstd.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmstd.inc
+++++ fpc/fpcsrc/compiler/arm/rarmstd.inc
++@@ -70,7 +70,7 @@
++ 's29',
++ 'd14',
++ 's30',
++-'s21',
+++'s31',
++ 'd15',
++ 'd16',
++ 'd17',
++@@ -122,4 +122,11 @@
++ 'basepri',
++ 'basepri_max',
++ 'faultmask',
++-'control'
+++'control',
+++'fpsid',
+++'mvfr1',
+++'mvfr0',
+++'fpexc',
+++'apsr_nzcvq',
+++'apsr_g',
+++'apsr_nzcvqg'
++Index: fpc/fpcsrc/compiler/arm/rarmsup.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/arm/rarmsup.inc
+++++ fpc/fpcsrc/compiler/arm/rarmsup.inc
++@@ -123,3 +123,10 @@ RS_BASEPRI = $1F;
++ RS_BASEPRI_MAX = $20;
++ RS_FAULTMASK = $21;
++ RS_CONTROL = $22;
+++RS_FPSID = $23;
+++RS_MVFR1 = $24;
+++RS_MVFR0 = $25;
+++RS_FPEXC = $26;
+++RS_APSR_nzcvq = $27;
+++RS_APSR_g = $28;
+++RS_APSR_nzcvqg = $29;
++Index: fpc/fpcsrc/compiler/assemble.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/assemble.pas
+++++ fpc/fpcsrc/compiler/assemble.pas
++@@ -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: fpc/fpcsrc/compiler/cgbase.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/cgbase.pas
+++++ fpc/fpcsrc/compiler/cgbase.pas
++@@ -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: fpc/fpcsrc/compiler/cghlcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/cghlcpu.pas
+++++ fpc/fpcsrc/compiler/cghlcpu.pas
++@@ -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: fpc/fpcsrc/compiler/cgobj.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/cgobj.pas
+++++ fpc/fpcsrc/compiler/cgobj.pas
++@@ -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: fpc/fpcsrc/compiler/cgutils.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/cgutils.pas
+++++ fpc/fpcsrc/compiler/cgutils.pas
++@@ -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: fpc/fpcsrc/compiler/fpcdefs.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/fpcdefs.inc
+++++ fpc/fpcsrc/compiler/fpcdefs.inc
++@@ -242,6 +242,7 @@
++ {$define cpurox}
++ {$define cputargethasfixedstack}
++ {$define cpurefshaveindexreg}
+++ {$define SUPPORT_GET_FRAME}
++ {$endif aarch64}
++
++ {$IFDEF MACOS}
++Index: fpc/fpcsrc/compiler/hlcg2ll.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/hlcg2ll.pas
+++++ fpc/fpcsrc/compiler/hlcg2ll.pas
++@@ -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: fpc/fpcsrc/compiler/hlcgobj.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/hlcgobj.pas
+++++ fpc/fpcsrc/compiler/hlcgobj.pas
++@@ -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: fpc/fpcsrc/compiler/i386/cpuelf.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/i386/cpuelf.pas
+++++ fpc/fpcsrc/compiler/i386/cpuelf.pas
++@@ -496,6 +496,7 @@ implementation
++ encodereloc: @elf_i386_encodeReloc;
++ loadreloc: @elf_i386_loadReloc;
++ loadsection: nil;
+++ encodeflags: nil;
++ );
++
++ as_i386_elf32_info : tasminfo =
++Index: fpc/fpcsrc/compiler/i8086/n8086mem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/i8086/n8086mem.pas
+++++ fpc/fpcsrc/compiler/i8086/n8086mem.pas
++@@ -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: fpc/fpcsrc/compiler/jvm/hlcgcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/jvm/hlcgcpu.pas
+++++ fpc/fpcsrc/compiler/jvm/hlcgcpu.pas
++@@ -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: fpc/fpcsrc/compiler/m68k/n68kmem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/m68k/n68kmem.pas
+++++ fpc/fpcsrc/compiler/m68k/n68kmem.pas
++@@ -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: fpc/fpcsrc/compiler/mips/cpuelf.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/mips/cpuelf.pas
+++++ fpc/fpcsrc/compiler/mips/cpuelf.pas
++@@ -1026,6 +1026,7 @@ implementation
++ encodereloc: @elf_mips_encodeReloc;
++ loadreloc: @elf_mips_loadReloc;
++ loadsection: @elf_mips_loadSection;
+++ encodeflags: nil;
++ );
++
++ initialization
++Index: fpc/fpcsrc/compiler/msg/errore.msg
++===================================================================
++--- fpc.orig/fpcsrc/compiler/msg/errore.msg
+++++ fpc/fpcsrc/compiler/msg/errore.msg
++@@ -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
++ 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
++ 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 (W
++ 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 (
++ 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 (
++ 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; s
++ 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: fpc/fpcsrc/compiler/msgidx.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/msgidx.inc
+++++ fpc/fpcsrc/compiler/msgidx.inc
++@@ -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: fpc/fpcsrc/compiler/ncal.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncal.pas
+++++ fpc/fpcsrc/compiler/ncal.pas
++@@ -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;
++-
++- { determine the type of the parameters }
++- if assigned(left) then
++- begin
++- tcallparanode(left).get_paratype;
++- if codegenerror then
++- goto errorexit;
++- end;
++-
++- if assigned(methodpointer) then
++- typecheckpass(methodpointer);
+++ try
+++ { determine length of parameter list }
+++ pt:=tcallparanode(left);
+++ paralength:=0;
+++ while assigned(pt) do
+++ begin
+++ inc(paralength);
+++ pt:=tcallparanode(pt.right);
+++ end;
++
++- { procedure variable ? }
++- if assigned(right) then
++- begin
++- set_varstate(right,vs_read,[vsf_must_be_valid]);
++- typecheckpass(right);
+++ { determine the type of the parameters }
+++ if assigned(left) then
+++ begin
+++ tcallparanode(left).get_paratype;
++ if codegenerror then
++- exit;
+++ exit;
+++ end;
++
++- procdefinition:=tabstractprocdef(right.resultdef);
+++ if assigned(methodpointer) then
+++ typecheckpass(methodpointer);
++
++- { 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;
+++ { 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);
+++
+++ { 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));
++-
++- { 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);
+++ { 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);
++ {$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);
++-
++- { 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);
+++ { 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 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;
++-
++- { recursive call? }
++- if assigned(current_procinfo) and
++- (procdefinition=current_procinfo.procdef) then
++- include(current_procinfo.flags,pi_is_recursive);
+++ 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;
++
++- { 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;
+++
+++ { 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;
+++
+++ { 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;
+++
+++ { 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);
+++ { 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);
+++
+++ { set the appropriate node flag if the call never returns }
+++ if po_noreturn in procdefinition.procoptions then
+++ include(callnodeflags,cnf_call_never_returns);
+++
+++ { 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;
+++
+++ { bind parasyms to the callparanodes and insert hidden parameters }
+++ bind_parasym;
+++
+++ { insert type conversions for parameters }
+++ if assigned(left) then
+++ tcallparanode(left).insert_typeconv;
++
++- if methodpointer.nodetype<>typen then
+++ { dispinterface methode invoke? }
+++ if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) 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,[])
+++ case procdefinition.proctypeoption of
+++ potype_propgetter: calltype:=dct_propget;
+++ potype_propsetter: calltype:=dct_propput;
++ else
++- set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
++- 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;
++-
++- { 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);
++-
++- { set the appropriate node flag if the call never returns }
++- if po_noreturn in procdefinition.procoptions then
++- include(callnodeflags,cnf_call_never_returns);
++-
++- { 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;
++-
++- { bind parasyms to the callparanodes and insert hidden parameters }
++- bind_parasym;
++-
++- { insert type conversions for parameters }
++- if assigned(left) then
++- tcallparanode(left).insert_typeconv;
+++ 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);
++
++- { 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;
+++ { don't free reused nodes }
+++ methodpointer:=nil;
+++ parameters:=nil;
++ 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);
++
++- { don't free reused nodes }
++- methodpointer:=nil;
++- parameters:=nil;
++- end;
++-
++- errorexit:
++- aktcallnode:=oldcallnode;
+++ 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;
+++ oldcallnode:=aktcallnode;
+++ aktcallnode:=self;
++
++- { 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;
+++ 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;
++
++- { 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;
++-
++- { 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;
+++ { 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;
++
++- { 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;
+++ { 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;
+++
+++ { 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;
+++
+++ { 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: fpc/fpcsrc/compiler/ncgcnv.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncgcnv.pas
+++++ fpc/fpcsrc/compiler/ncgcnv.pas
++@@ -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: fpc/fpcsrc/compiler/ncginl.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncginl.pas
+++++ fpc/fpcsrc/compiler/ncginl.pas
++@@ -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: fpc/fpcsrc/compiler/ncgld.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncgld.pas
+++++ fpc/fpcsrc/compiler/ncgld.pas
++@@ -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: fpc/fpcsrc/compiler/ncgmat.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncgmat.pas
+++++ fpc/fpcsrc/compiler/ncgmat.pas
++@@ -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: fpc/fpcsrc/compiler/ncgmem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncgmem.pas
+++++ fpc/fpcsrc/compiler/ncgmem.pas
++@@ -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: fpc/fpcsrc/compiler/ncgutil.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncgutil.pas
+++++ fpc/fpcsrc/compiler/ncgutil.pas
++@@ -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: fpc/fpcsrc/compiler/ncnv.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ncnv.pas
+++++ fpc/fpcsrc/compiler/ncnv.pas
++@@ -2375,6 +2375,10 @@ implementation
++ (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
++ not(is_array_of_const(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: fpc/fpcsrc/compiler/ninl.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ninl.pas
+++++ fpc/fpcsrc/compiler/ninl.pas
++@@ -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: fpc/fpcsrc/compiler/nld.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/nld.pas
+++++ fpc/fpcsrc/compiler/nld.pas
++@@ -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: fpc/fpcsrc/compiler/nmem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/nmem.pas
+++++ fpc/fpcsrc/compiler/nmem.pas
++@@ -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: fpc/fpcsrc/compiler/objcgutl.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/objcgutl.pas
+++++ fpc/fpcsrc/compiler/objcgutl.pas
++@@ -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: fpc/fpcsrc/compiler/objcutil.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/objcutil.pas
+++++ fpc/fpcsrc/compiler/objcutil.pas
++@@ -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: fpc/fpcsrc/compiler/ogbase.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ogbase.pas
+++++ fpc/fpcsrc/compiler/ogbase.pas
++@@ -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: fpc/fpcsrc/compiler/ogcoff.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ogcoff.pas
+++++ fpc/fpcsrc/compiler/ogcoff.pas
++@@ -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: fpc/fpcsrc/compiler/ogelf.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ogelf.pas
+++++ fpc/fpcsrc/compiler/ogelf.pas
++@@ -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: fpc/fpcsrc/compiler/options.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/options.pas
+++++ fpc/fpcsrc/compiler/options.pas
++@@ -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: fpc/fpcsrc/compiler/pparautl.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/pparautl.pas
+++++ fpc/fpcsrc/compiler/pparautl.pas
++@@ -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: fpc/fpcsrc/compiler/ppu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/ppu.pas
+++++ fpc/fpcsrc/compiler/ppu.pas
++@@ -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: fpc/fpcsrc/compiler/psub.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/psub.pas
+++++ fpc/fpcsrc/compiler/psub.pas
++@@ -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: fpc/fpcsrc/compiler/psystem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/psystem.pas
+++++ fpc/fpcsrc/compiler/psystem.pas
++@@ -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: fpc/fpcsrc/compiler/raatt.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/raatt.pas
+++++ fpc/fpcsrc/compiler/raatt.pas
++@@ -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: fpc/fpcsrc/compiler/rautils.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/rautils.pas
+++++ fpc/fpcsrc/compiler/rautils.pas
++@@ -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: fpc/fpcsrc/compiler/sparc/cpuelf.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/sparc/cpuelf.pas
+++++ fpc/fpcsrc/compiler/sparc/cpuelf.pas
++@@ -114,6 +114,7 @@ implementation
++ encodereloc: @elf_sparc_encodeReloc;
++ loadreloc: @elf_sparc_loadReloc;
++ loadsection: nil;
+++ encodeflags: nil;
++ );
++
++ as_sparc_elf32_info : tasminfo =
++Index: fpc/fpcsrc/compiler/symdef.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/symdef.pas
+++++ fpc/fpcsrc/compiler/symdef.pas
++@@ -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: fpc/fpcsrc/compiler/systems/i_bsd.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems/i_bsd.pas
+++++ fpc/fpcsrc/compiler/systems/i_bsd.pas
++@@ -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: fpc/fpcsrc/compiler/systems/i_linux.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems/i_linux.pas
+++++ fpc/fpcsrc/compiler/systems/i_linux.pas
++@@ -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: fpc/fpcsrc/compiler/systems/i_win.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems/i_win.pas
+++++ fpc/fpcsrc/compiler/systems/i_win.pas
++@@ -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: fpc/fpcsrc/compiler/systems/t_bsd.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems/t_bsd.pas
+++++ fpc/fpcsrc/compiler/systems/t_bsd.pas
++@@ -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: fpc/fpcsrc/compiler/systems/t_linux.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems/t_linux.pas
+++++ fpc/fpcsrc/compiler/systems/t_linux.pas
++@@ -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: fpc/fpcsrc/compiler/systems.inc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems.inc
+++++ fpc/fpcsrc/compiler/systems.inc
++@@ -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:
++@@ -165,7 +167,10 @@
++ 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
++@@ -211,6 +216,7 @@
++ ,as_i8086_nasm
++ ,as_i8086_nasmobj
++ ,as_gas_powerpc_xcoff
+++ ,as_arm_elf32
++ ,as_clang
++ );
++
++@@ -283,6 +289,7 @@
++ ,abi_powerpc_sysv,abi_powerpc_aix
++ ,abi_eabi,abi_armeb,abi_eabihf
++ ,abi_old_win32_gnu
+++ ,abi_aarch64_darwin
++ );
++
++
++Index: fpc/fpcsrc/compiler/systems.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/systems.pas
+++++ fpc/fpcsrc/compiler/systems.pas
++@@ -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: fpc/fpcsrc/compiler/tgobj.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/tgobj.pas
+++++ fpc/fpcsrc/compiler/tgobj.pas
++@@ -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: fpc/fpcsrc/compiler/utils/Makefile.fpc
++===================================================================
++--- fpc.orig/fpcsrc/compiler/utils/Makefile.fpc
+++++ fpc/fpcsrc/compiler/utils/Makefile.fpc
++@@ -3,7 +3,7 @@
++ #
++
++ [target]
++-programs=fpc ppufiles ppudump ppumove mkarmins mkx86ins
+++programs=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
++ rst=fpcsubst
++
++ [clean]
++Index: fpc/fpcsrc/compiler/utils/fpc.pp
++===================================================================
++--- fpc.orig/fpcsrc/compiler/utils/fpc.pp
+++++ fpc/fpcsrc/compiler/utils/fpc.pp
++@@ -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: fpc/fpcsrc/compiler/utils/mka64ins.pp
++===================================================================
++--- fpc.orig/fpcsrc/compiler/utils/mka64ins.pp
+++++ fpc/fpcsrc/compiler/utils/mka64ins.pp
++@@ -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: fpc/fpcsrc/compiler/utils/mkarmins.pp
++===================================================================
++--- fpc.orig/fpcsrc/compiler/utils/mkarmins.pp
+++++ fpc/fpcsrc/compiler/utils/mkarmins.pp
++@@ -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: fpc/fpcsrc/compiler/utils/ppuutils/ppudump.pp
++===================================================================
++--- fpc.orig/fpcsrc/compiler/utils/ppuutils/ppudump.pp
+++++ fpc/fpcsrc/compiler/utils/ppuutils/ppudump.pp
++@@ -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: fpc/fpcsrc/compiler/version.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/version.pas
+++++ fpc/fpcsrc/compiler/version.pas
++@@ -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: fpc/fpcsrc/compiler/x86/agx86att.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/x86/agx86att.pas
+++++ fpc/fpcsrc/compiler/x86/agx86att.pas
++@@ -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: fpc/fpcsrc/compiler/x86/cgx86.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/x86/cgx86.pas
+++++ fpc/fpcsrc/compiler/x86/cgx86.pas
++@@ -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: fpc/fpcsrc/compiler/x86/nx86mem.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/x86/nx86mem.pas
+++++ fpc/fpcsrc/compiler/x86/nx86mem.pas
++@@ -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: fpc/fpcsrc/compiler/x86_64/cgcpu.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/x86_64/cgcpu.pas
+++++ fpc/fpcsrc/compiler/x86_64/cgcpu.pas
++@@ -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: fpc/fpcsrc/compiler/x86_64/cpuelf.pas
++===================================================================
++--- fpc.orig/fpcsrc/compiler/x86_64/cpuelf.pas
+++++ fpc/fpcsrc/compiler/x86_64/cpuelf.pas
++@@ -664,6 +664,7 @@ implementation
++ encodereloc: @elf_x86_64_encodeReloc;
++ loadreloc: @elf_x86_64_loadReloc;
++ loadsection: nil;
+++ encodeflags: nil;
++ );
++
++
++Index: fpc/fpcsrc/packages/fcl-res/Makefile.fpc.fpcmake
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/Makefile.fpc.fpcmake
+++++ fpc/fpcsrc/packages/fcl-res/Makefile.fpc.fpcmake
++@@ -13,7 +13,7 @@ units=acceleratorsresource bitmapresourc
++ 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: fpc/fpcsrc/packages/fcl-res/src/elfconsts.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/elfconsts.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/elfconsts.pp
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/elfdefaulttarget.inc
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/elfdefaulttarget.inc
+++++ fpc/fpcsrc/packages/fcl-res/src/elfdefaulttarget.inc
++@@ -33,6 +33,9 @@
++ fMachineType:=emtarmeb;
++ {$ENDIF}
++ {$ENDIF}
+++ {$IFDEF CPUAARCH64}
+++ fMachineType:=emtaarch64;
+++ {$ENDIF}
++ {$IFDEF CPU68K}
++ fMachineType:=emtm68k;
++ {$ENDIF}
++Index: fpc/fpcsrc/packages/fcl-res/src/elfreader.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/elfreader.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/elfreader.pp
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/elfsubwriter.inc
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/elfsubwriter.inc
+++++ fpc/fpcsrc/packages/fcl-res/src/elfsubwriter.inc
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/elfwriter.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/elfwriter.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/elfwriter.pp
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/machoconsts.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/machoconsts.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/machoconsts.pp
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/machodefaulttarget.inc
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/machodefaulttarget.inc
+++++ fpc/fpcsrc/packages/fcl-res/src/machodefaulttarget.inc
++@@ -29,6 +29,9 @@
++ {$IFDEF CPUARM}
++ fMachineType:=mmtarm;
++ {$ENDIF}
+++ {$IFDEF CPUAARCH64}
+++ fMachineType:=mmtarm64;
+++ {$ENDIF}
++
++ fBits:=MACH_ERRBIT;
++ {$IFDEF CPU32}
++Index: fpc/fpcsrc/packages/fcl-res/src/machoreader.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/machoreader.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/machoreader.pp
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/machosubwriter.inc
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/machosubwriter.inc
+++++ fpc/fpcsrc/packages/fcl-res/src/machosubwriter.inc
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/machotypes.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/machotypes.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/machotypes.pp
++@@ -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: fpc/fpcsrc/packages/fcl-res/src/machowriter.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fcl-res/src/machowriter.pp
+++++ fpc/fpcsrc/packages/fcl-res/src/machowriter.pp
++@@ -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: fpc/fpcsrc/packages/fpmkunit/src/fpmkunit.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/fpmkunit/src/fpmkunit.pp
+++++ fpc/fpcsrc/packages/fpmkunit/src/fpmkunit.pp
++@@ -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: fpc/fpcsrc/packages/iosxlocale/Makefile.fpc.fpcmake
++===================================================================
++--- fpc.orig/fpcsrc/packages/iosxlocale/Makefile.fpc.fpcmake
+++++ fpc/fpcsrc/packages/iosxlocale/Makefile.fpc.fpcmake
++@@ -7,7 +7,7 @@ name=univint
++ version=3.0.4
++
++ [target]
++-units=iosxlocale
+++units=iosxlocale iosxwstr
++
++ [libs]
++ libversion=2.0.0
++Index: fpc/fpcsrc/packages/iosxlocale/fpmake.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/iosxlocale/fpmake.pp
+++++ fpc/fpcsrc/packages/iosxlocale/fpmake.pp
++@@ -22,6 +22,7 @@ begin
++ P.OSes:=[darwin,iphonesim];
++
++ T:=P.Targets.AddUnit('iosxlocale.pp');
+++ T:=P.Targets.AddUnit('iosxwstr.pp');
++
++ {$ifndef ALLPACKAGES}
++ Run;
++Index: fpc/fpcsrc/packages/iosxlocale/src/iosxwstr.pp
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/packages/iosxlocale/src/iosxwstr.pp
++@@ -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: fpc/fpcsrc/packages/rtl-extra/src/linux/unixsock.inc
++===================================================================
++--- fpc.orig/fpcsrc/packages/rtl-extra/src/linux/unixsock.inc
+++++ fpc/fpcsrc/packages/rtl-extra/src/linux/unixsock.inc
++@@ -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: fpc/fpcsrc/packages/rtl-extra/src/unix/ipc.pp
++===================================================================
++--- fpc.orig/fpcsrc/packages/rtl-extra/src/unix/ipc.pp
+++++ fpc/fpcsrc/packages/rtl-extra/src/unix/ipc.pp
++@@ -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}
++Index: fpc/fpcsrc/rtl/aarch64/aarch64.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/aarch64.inc
++@@ -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}
++Index: fpc/fpcsrc/rtl/aarch64/int64p.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/int64p.inc
++@@ -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 }
++Index: fpc/fpcsrc/rtl/aarch64/makefile.cpu
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/makefile.cpu
++@@ -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))
+++#
++Index: fpc/fpcsrc/rtl/aarch64/math.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/math.inc
++@@ -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}
+++
+++
++Index: fpc/fpcsrc/rtl/aarch64/mathu.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/mathu.inc
++@@ -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;
++Index: fpc/fpcsrc/rtl/aarch64/set.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/set.inc
++@@ -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.
+++
+++ **********************************************************************}
+++
++Index: fpc/fpcsrc/rtl/aarch64/setjump.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/setjump.inc
++@@ -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;
+++
+++
++Index: fpc/fpcsrc/rtl/aarch64/setjumph.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/setjumph.inc
++@@ -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'];
+++
++Index: fpc/fpcsrc/rtl/aarch64/strings.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/strings.inc
++@@ -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.
+++
+++ **********************************************************************}
+++
++Index: fpc/fpcsrc/rtl/aarch64/stringss.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/aarch64/stringss.inc
++@@ -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: fpc/fpcsrc/rtl/arm/arm.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/arm/arm.inc
+++++ fpc/fpcsrc/rtl/arm/arm.inc
++@@ -15,8 +15,6 @@
++
++ **********************************************************************}
++
++-{$asmmode gas}
++-
++ {$ifndef FPC_SYSTEM_HAS_MOVE}
++ {$define FPC_SYSTEM_FPC_MOVE}
++ {$endif FPC_SYSTEM_HAS_MOVE}
++Index: fpc/fpcsrc/rtl/arm/thumb2.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/arm/thumb2.inc
+++++ fpc/fpcsrc/rtl/arm/thumb2.inc
++@@ -15,7 +15,7 @@
++
++ **********************************************************************}
++
++-{$asmmode gas}
+++{$asmmode divided}
++
++ {$ifndef FPC_SYSTEM_HAS_MOVE}
++ {$define FPC_SYSTEM_FPC_MOVE}
++Index: fpc/fpcsrc/rtl/bsd/ostypes.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/bsd/ostypes.inc
+++++ fpc/fpcsrc/rtl/bsd/ostypes.inc
++@@ -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;
++
++Index: fpc/fpcsrc/rtl/darwin/aarch64/sig_cpu.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/darwin/aarch64/sig_cpu.inc
++@@ -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;
+++
+++
++Index: fpc/fpcsrc/rtl/darwin/aarch64/sighnd.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/darwin/aarch64/sighnd.inc
++@@ -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: fpc/fpcsrc/rtl/darwin/extres_multiarch.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/darwin/extres_multiarch.inc
+++++ fpc/fpcsrc/rtl/darwin/extres_multiarch.inc
++@@ -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: fpc/fpcsrc/rtl/darwin/ptypes.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/darwin/ptypes.inc
+++++ fpc/fpcsrc/rtl/darwin/ptypes.inc
++@@ -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: fpc/fpcsrc/rtl/darwin/signal.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/darwin/signal.inc
+++++ fpc/fpcsrc/rtl/darwin/signal.inc
++@@ -193,7 +193,11 @@
++ {$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: fpc/fpcsrc/rtl/inc/ctypes.pp
++===================================================================
++--- fpc.orig/fpcsrc/rtl/inc/ctypes.pp
+++++ fpc/fpcsrc/rtl/inc/ctypes.pp
++@@ -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: fpc/fpcsrc/rtl/inc/objc.pp
++===================================================================
++--- fpc.orig/fpcsrc/rtl/inc/objc.pp
+++++ fpc/fpcsrc/rtl/inc/objc.pp
++@@ -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: fpc/fpcsrc/rtl/inc/objcnf.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/inc/objcnf.inc
+++++ fpc/fpcsrc/rtl/inc/objcnf.inc
++@@ -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: fpc/fpcsrc/rtl/inc/system.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/inc/system.inc
+++++ fpc/fpcsrc/rtl/inc/system.inc
++@@ -264,6 +264,13 @@ function do_isdevice(handle:thandle):boo
++ {$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: fpc/fpcsrc/rtl/inc/systemh.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/inc/systemh.inc
+++++ fpc/fpcsrc/rtl/inc/systemh.inc
++@@ -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): QWo
++ {$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;c
++ {$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 : Int
++ {$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}
++Index: fpc/fpcsrc/rtl/linux/aarch64/bsyscall.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/bsyscall.inc
++@@ -0,0 +1 @@
+++{ nothing }
++Index: fpc/fpcsrc/rtl/linux/aarch64/cprt0.as
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/cprt0.as
++@@ -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
++Index: fpc/fpcsrc/rtl/linux/aarch64/dllprt0.as
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/dllprt0.as
++@@ -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
++Index: fpc/fpcsrc/rtl/linux/aarch64/gprt0.as
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/gprt0.as
++@@ -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
++Index: fpc/fpcsrc/rtl/linux/aarch64/prt0.as
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/prt0.as
++@@ -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
++Index: fpc/fpcsrc/rtl/linux/aarch64/sighnd.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/sighnd.inc
++@@ -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;
++Index: fpc/fpcsrc/rtl/linux/aarch64/sighndh.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/sighndh.inc
++@@ -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;
++Index: fpc/fpcsrc/rtl/linux/aarch64/stat.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/stat.inc
++@@ -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;
++Index: fpc/fpcsrc/rtl/linux/aarch64/syscall.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/syscall.inc
++@@ -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;
++Index: fpc/fpcsrc/rtl/linux/aarch64/syscallh.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/syscallh.inc
++@@ -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';
++Index: fpc/fpcsrc/rtl/linux/aarch64/sysnr.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/aarch64/sysnr.inc
++@@ -0,0 +1 @@
+++{$i ../sysnr-gen.inc}
++Index: fpc/fpcsrc/rtl/linux/bunxsysc.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/bunxsysc.inc
+++++ fpc/fpcsrc/rtl/linux/bunxsysc.inc
++@@ -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:pc
++ 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,writefd
++ 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):
++ }
++
++ 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
++ }
++
++ 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: fpc/fpcsrc/rtl/linux/linux.pp
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/linux.pp
+++++ fpc/fpcsrc/rtl/linux/linux.pp
++@@ -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: fpc/fpcsrc/rtl/linux/oldlinux.pp
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/oldlinux.pp
+++++ fpc/fpcsrc/rtl/linux/oldlinux.pp
++@@ -1924,9 +1924,16 @@ Function Sys_Mkdir(Filename:pchar;mode:l
++ 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):longi
++ 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: fpc/fpcsrc/rtl/linux/osdefs.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/osdefs.inc
+++++ fpc/fpcsrc/rtl/linux/osdefs.inc
++@@ -85,3 +85,7 @@
++ {$endif FPC_ABI_EABI}
++ {$endif cpuarm}
++
+++{$ifdef cpuaarch64}
+++ {$define generic_linux_syscalls}
+++ {$undef usestime}
+++{$endif cpuaarch64}
++Index: fpc/fpcsrc/rtl/linux/ossysc.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/ossysc.inc
+++++ fpc/fpcsrc/rtl/linux/ossysc.inc
++@@ -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 : sta
++
++ 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
++ 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
++ }
++
++ 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; amod
++ }
++
++ 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: fpc/fpcsrc/rtl/linux/ostypes.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/ostypes.inc
+++++ fpc/fpcsrc/rtl/linux/ostypes.inc
++@@ -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)}
++Index: fpc/fpcsrc/rtl/linux/pmutext.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/pmutext.inc
++@@ -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: fpc/fpcsrc/rtl/linux/ptypes.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/ptypes.inc
+++++ fpc/fpcsrc/rtl/linux/ptypes.inc
++@@ -30,12 +30,21 @@ and all three 32-bit systems returned co
++ 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}
++Index: fpc/fpcsrc/rtl/linux/sysnr-gen.inc
++===================================================================
++--- /dev/null
+++++ fpc/fpcsrc/rtl/linux/sysnr-gen.inc
++@@ -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: fpc/fpcsrc/rtl/linux/sysosh.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/sysosh.inc
+++++ fpc/fpcsrc/rtl/linux/sysosh.inc
++@@ -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: fpc/fpcsrc/rtl/linux/termios.inc
++===================================================================
++--- fpc.orig/fpcsrc/rtl/linux/termios.inc
+++++ fpc/fpcsrc/rtl/linux/termios.inc
++@@ -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: fpc/fpcsrc/rtl/unix/cthreads.pp
++===================================================================
++--- fpc.orig/fpcsrc/rtl/unix/cthreads.pp
+++++ fpc/fpcsrc/rtl/unix/cthreads.pp
++@@ -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: fpc/fpcsrc/rtl/unix/cwstring.pp
++===================================================================
++--- fpc.orig/fpcsrc/rtl/unix/cwstring.pp
+++++ fpc/fpcsrc/rtl/unix/cwstring.pp
++@@ -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: fpc/fpcsrc/utils/fpcm/fpcmmain.pp
++===================================================================
++--- fpc.orig/fpcsrc/utils/fpcm/fpcmmain.pp
+++++ fpc/fpcsrc/utils/fpcm/fpcmmain.pp
++@@ -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','x64','arm','ppc64','avr','armeb', 'armel', 'mips', 'mipsel', 'mips64', 'mips64el', 'jvm','8086','a64'
++ );
++
++ 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: fpc/fpcsrc/utils/fpcres/fpcres.pas
++===================================================================
++--- fpc.orig/fpcsrc/utils/fpcres/fpcres.pas
+++++ fpc/fpcsrc/utils/fpcres/fpcres.pas
++@@ -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: fpc/fpcsrc/utils/fpcres/target.pas
++===================================================================
++--- fpc.orig/fpcsrc/utils/fpcres/target.pas
+++++ fpc/fpcsrc/utils/fpcres/target.pas
++@@ -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;